.
[glibc/history.git] / nscd / connections.c
blob1a7dc77694d162caaef5e548afb1a9af48b75126
1 /* Inner loops of cache daemon.
2 Copyright (C) 1998-2003, 2004 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA. */
21 #include <alloca.h>
22 #include <assert.h>
23 #include <atomic.h>
24 #include <error.h>
25 #include <errno.h>
26 #include <fcntl.h>
27 #include <grp.h>
28 #include <libintl.h>
29 #include <pthread.h>
30 #include <pwd.h>
31 #include <resolv.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <arpa/inet.h>
36 #ifdef HAVE_EPOLL
37 # include <sys/epoll.h>
38 #endif
39 #include <sys/mman.h>
40 #include <sys/param.h>
41 #include <sys/poll.h>
42 #include <sys/socket.h>
43 #include <sys/stat.h>
44 #include <sys/un.h>
46 #include "nscd.h"
47 #include "dbg_log.h"
48 #include "selinux.h"
51 /* Number of bytes of data we initially reserve for each hash table bucket. */
52 #define DEFAULT_DATASIZE_PER_BUCKET 1024
55 /* Wrapper functions with error checking for standard functions. */
56 extern void *xmalloc (size_t n);
57 extern void *xcalloc (size_t n, size_t s);
58 extern void *xrealloc (void *o, size_t n);
60 /* Support to run nscd as an unprivileged user */
61 const char *server_user;
62 static uid_t server_uid;
63 static gid_t server_gid;
64 const char *stat_user;
65 uid_t stat_uid;
66 static gid_t *server_groups;
67 #ifndef NGROUPS
68 # define NGROUPS 32
69 #endif
70 static int server_ngroups;
72 static pthread_attr_t attr;
74 static void begin_drop_privileges (void);
75 static void finish_drop_privileges (void);
77 /* Map request type to a string. */
78 const char *serv2str[LASTREQ] =
80 [GETPWBYNAME] = "GETPWBYNAME",
81 [GETPWBYUID] = "GETPWBYUID",
82 [GETGRBYNAME] = "GETGRBYNAME",
83 [GETGRBYGID] = "GETGRBYGID",
84 [GETHOSTBYNAME] = "GETHOSTBYNAME",
85 [GETHOSTBYNAMEv6] = "GETHOSTBYNAMEv6",
86 [GETHOSTBYADDR] = "GETHOSTBYADDR",
87 [GETHOSTBYADDRv6] = "GETHOSTBYADDRv6",
88 [SHUTDOWN] = "SHUTDOWN",
89 [GETSTAT] = "GETSTAT",
90 [INVALIDATE] = "INVALIDATE",
91 [GETFDPW] = "GETFDPW",
92 [GETFDGR] = "GETFDGR",
93 [GETFDHST] = "GETFDHST",
94 [GETAI] = "GETAI",
95 [INITGROUPS] = "INITGROUPS"
98 /* The control data structures for the services. */
99 struct database_dyn dbs[lastdb] =
101 [pwddb] = {
102 .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
103 .enabled = 0,
104 .check_file = 1,
105 .persistent = 0,
106 .shared = 0,
107 .filename = "/etc/passwd",
108 .db_filename = _PATH_NSCD_PASSWD_DB,
109 .disabled_iov = &pwd_iov_disabled,
110 .postimeout = 3600,
111 .negtimeout = 20,
112 .wr_fd = -1,
113 .ro_fd = -1,
114 .mmap_used = false
116 [grpdb] = {
117 .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
118 .enabled = 0,
119 .check_file = 1,
120 .persistent = 0,
121 .shared = 0,
122 .filename = "/etc/group",
123 .db_filename = _PATH_NSCD_GROUP_DB,
124 .disabled_iov = &grp_iov_disabled,
125 .postimeout = 3600,
126 .negtimeout = 60,
127 .wr_fd = -1,
128 .ro_fd = -1,
129 .mmap_used = false
131 [hstdb] = {
132 .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
133 .enabled = 0,
134 .check_file = 1,
135 .persistent = 0,
136 .shared = 0,
137 .filename = "/etc/hosts",
138 .db_filename = _PATH_NSCD_HOSTS_DB,
139 .disabled_iov = &hst_iov_disabled,
140 .postimeout = 3600,
141 .negtimeout = 20,
142 .wr_fd = -1,
143 .ro_fd = -1,
144 .mmap_used = false
149 /* Mapping of request type to database. */
150 static struct database_dyn *const serv2db[LASTREQ] =
152 [GETPWBYNAME] = &dbs[pwddb],
153 [GETPWBYUID] = &dbs[pwddb],
154 [GETGRBYNAME] = &dbs[grpdb],
155 [GETGRBYGID] = &dbs[grpdb],
156 [GETHOSTBYNAME] = &dbs[hstdb],
157 [GETHOSTBYNAMEv6] = &dbs[hstdb],
158 [GETHOSTBYADDR] = &dbs[hstdb],
159 [GETHOSTBYADDRv6] = &dbs[hstdb],
160 [GETFDPW] = &dbs[pwddb],
161 [GETFDGR] = &dbs[grpdb],
162 [GETFDHST] = &dbs[hstdb],
163 [GETAI] = &dbs[hstdb],
164 [INITGROUPS] = &dbs[grpdb]
168 /* Number of seconds between two cache pruning runs. */
169 #define CACHE_PRUNE_INTERVAL 15
172 /* Initial number of threads to use. */
173 int nthreads = -1;
174 /* Maximum number of threads to use. */
175 int max_nthreads = 32;
177 /* Socket for incoming connections. */
178 static int sock;
180 /* Number of times clients had to wait. */
181 unsigned long int client_queued;
184 ssize_t
185 writeall (int fd, const void *buf, size_t len)
187 size_t n = len;
188 ssize_t ret;
191 ret = TEMP_FAILURE_RETRY (write (fd, buf, n));
192 if (ret <= 0)
193 break;
194 buf = (const char *) buf + ret;
195 n -= ret;
197 while (n > 0);
198 return ret < 0 ? ret : len - n;
202 /* Initialize database information structures. */
203 void
204 nscd_init (void)
206 /* Secure mode and unprivileged mode are incompatible */
207 if (server_user != NULL && secure_in_use)
209 dbg_log (_("Cannot run nscd in secure mode as unprivileged user"));
210 exit (1);
213 /* Look up unprivileged uid/gid/groups before we start listening on the
214 socket */
215 if (server_user != NULL)
216 begin_drop_privileges ();
218 if (nthreads == -1)
219 /* No configuration for this value, assume a default. */
220 nthreads = 2 * lastdb;
222 for (size_t cnt = 0; cnt < lastdb; ++cnt)
223 if (dbs[cnt].enabled)
225 pthread_rwlock_init (&dbs[cnt].lock, NULL);
226 pthread_mutex_init (&dbs[cnt].memlock, NULL);
228 if (dbs[cnt].persistent)
230 /* Try to open the appropriate file on disk. */
231 int fd = open (dbs[cnt].db_filename, O_RDWR);
232 if (fd != -1)
234 struct stat64 st;
235 void *mem;
236 size_t total;
237 struct database_pers_head head;
238 ssize_t n = TEMP_FAILURE_RETRY (read (fd, &head,
239 sizeof (head)));
240 if (n != sizeof (head) || fstat64 (fd, &st) != 0)
242 fail_db:
243 dbg_log (_("invalid persistent database file \"%s\": %s"),
244 dbs[cnt].db_filename, strerror (errno));
245 dbs[cnt].persistent = 0;
247 else if (head.module == 0 && head.data_size == 0)
249 /* The file has been created, but the head has not been
250 initialized yet. Remove the old file. */
251 unlink (dbs[cnt].db_filename);
253 else if (head.header_size != (int) sizeof (head))
255 dbg_log (_("invalid persistent database file \"%s\": %s"),
256 dbs[cnt].db_filename,
257 _("header size does not match"));
258 dbs[cnt].persistent = 0;
260 else if ((total = (sizeof (head)
261 + roundup (head.module * sizeof (ref_t),
262 ALIGN)
263 + head.data_size))
264 > st.st_size)
266 dbg_log (_("invalid persistent database file \"%s\": %s"),
267 dbs[cnt].db_filename,
268 _("file size does not match"));
269 dbs[cnt].persistent = 0;
271 else if ((mem = mmap (NULL, total, PROT_READ | PROT_WRITE,
272 MAP_SHARED, fd, 0)) == MAP_FAILED)
273 goto fail_db;
274 else
276 /* Success. We have the database. */
277 dbs[cnt].head = mem;
278 dbs[cnt].memsize = total;
279 dbs[cnt].data = (char *)
280 &dbs[cnt].head->array[roundup (dbs[cnt].head->module,
281 ALIGN / sizeof (ref_t))];
282 dbs[cnt].mmap_used = true;
284 if (dbs[cnt].suggested_module > head.module)
285 dbg_log (_("suggested size of table for database %s larger than the persistent database's table"),
286 dbnames[cnt]);
288 dbs[cnt].wr_fd = fd;
289 fd = -1;
290 /* We also need a read-only descriptor. */
291 if (dbs[cnt].shared)
293 dbs[cnt].ro_fd = open (dbs[cnt].db_filename, O_RDONLY);
294 if (dbs[cnt].ro_fd == -1)
295 dbg_log (_("\
296 cannot create read-only descriptor for \"%s\"; no mmap"),
297 dbs[cnt].db_filename);
300 // XXX Shall we test whether the descriptors actually
301 // XXX point to the same file?
304 /* Close the file descriptors in case something went
305 wrong in which case the variable have not been
306 assigned -1. */
307 if (fd != -1)
308 close (fd);
312 if (dbs[cnt].head == NULL)
314 /* No database loaded. Allocate the data structure,
315 possibly on disk. */
316 struct database_pers_head head;
317 size_t total = (sizeof (head)
318 + roundup (dbs[cnt].suggested_module
319 * sizeof (ref_t), ALIGN)
320 + (dbs[cnt].suggested_module
321 * DEFAULT_DATASIZE_PER_BUCKET));
323 /* Try to create the database. If we do not need a
324 persistent database create a temporary file. */
325 int fd;
326 int ro_fd = -1;
327 if (dbs[cnt].persistent)
329 fd = open (dbs[cnt].db_filename,
330 O_RDWR | O_CREAT | O_EXCL | O_TRUNC,
331 S_IRUSR | S_IWUSR);
332 if (fd != -1 && dbs[cnt].shared)
333 ro_fd = open (dbs[cnt].db_filename, O_RDONLY);
335 else
337 char fname[] = _PATH_NSCD_XYZ_DB_TMP;
338 fd = mkstemp (fname);
340 /* We do not need the file name anymore after we
341 opened another file descriptor in read-only mode. */
342 if (fd != -1)
344 if (dbs[cnt].shared)
345 ro_fd = open (fname, O_RDONLY);
347 unlink (fname);
351 if (fd == -1)
353 if (errno == EEXIST)
355 dbg_log (_("database for %s corrupted or simultaneously used; remove %s manually if necessary and restart"),
356 dbnames[cnt], dbs[cnt].db_filename);
357 // XXX Correct way to terminate?
358 exit (1);
361 if (dbs[cnt].persistent)
362 dbg_log (_("cannot create %s; no persistent database used"),
363 dbs[cnt].db_filename);
364 else
365 dbg_log (_("cannot create %s; no sharing possible"),
366 dbs[cnt].db_filename);
368 dbs[cnt].persistent = 0;
369 // XXX remember: no mmap
371 else
373 /* Tell the user if we could not create the read-only
374 descriptor. */
375 if (ro_fd == -1 && dbs[cnt].shared)
376 dbg_log (_("\
377 cannot create read-only descriptor for \"%s\"; no mmap"),
378 dbs[cnt].db_filename);
380 /* Before we create the header, initialiye the hash
381 table. So that if we get interrupted if writing
382 the header we can recognize a partially initialized
383 database. */
384 size_t ps = sysconf (_SC_PAGESIZE);
385 char tmpbuf[ps];
386 assert (~ENDREF == 0);
387 memset (tmpbuf, '\xff', ps);
389 size_t remaining = dbs[cnt].suggested_module * sizeof (ref_t);
390 off_t offset = sizeof (head);
392 size_t towrite;
393 if (offset % ps != 0)
395 towrite = MIN (remaining, ps - (offset % ps));
396 pwrite (fd, tmpbuf, towrite, offset);
397 offset += towrite;
398 remaining -= towrite;
401 while (remaining > ps)
403 pwrite (fd, tmpbuf, ps, offset);
404 offset += ps;
405 remaining -= ps;
408 if (remaining > 0)
409 pwrite (fd, tmpbuf, remaining, offset);
411 /* Create the header of the file. */
412 struct database_pers_head head =
414 .version = DB_VERSION,
415 .header_size = sizeof (head),
416 .module = dbs[cnt].suggested_module,
417 .data_size = (dbs[cnt].suggested_module
418 * DEFAULT_DATASIZE_PER_BUCKET),
419 .first_free = 0
421 void *mem;
423 if ((TEMP_FAILURE_RETRY (write (fd, &head, sizeof (head)))
424 != sizeof (head))
425 || ftruncate (fd, total) != 0
426 || (mem = mmap (NULL, total, PROT_READ | PROT_WRITE,
427 MAP_SHARED, fd, 0)) == MAP_FAILED)
429 unlink (dbs[cnt].db_filename);
430 dbg_log (_("cannot write to database file %s: %s"),
431 dbs[cnt].db_filename, strerror (errno));
432 dbs[cnt].persistent = 0;
434 else
436 /* Success. */
437 dbs[cnt].head = mem;
438 dbs[cnt].data = (char *)
439 &dbs[cnt].head->array[roundup (dbs[cnt].head->module,
440 ALIGN / sizeof (ref_t))];
441 dbs[cnt].memsize = total;
442 dbs[cnt].mmap_used = true;
444 /* Remember the descriptors. */
445 dbs[cnt].wr_fd = fd;
446 dbs[cnt].ro_fd = ro_fd;
447 fd = -1;
448 ro_fd = -1;
451 if (fd != -1)
452 close (fd);
453 if (ro_fd != -1)
454 close (ro_fd);
458 if (paranoia
459 && ((dbs[cnt].wr_fd != -1
460 && fcntl (dbs[cnt].wr_fd, F_SETFD, FD_CLOEXEC) == -1)
461 || (dbs[cnt].ro_fd != -1
462 && fcntl (dbs[cnt].ro_fd, F_SETFD, FD_CLOEXEC) == -1)))
464 dbg_log (_("\
465 cannot set socket to close on exec: %s; disabling paranoia mode"),
466 strerror (errno));
467 paranoia = 0;
470 if (dbs[cnt].head == NULL)
472 /* We do not use the persistent database. Just
473 create an in-memory data structure. */
474 assert (! dbs[cnt].persistent);
476 dbs[cnt].head = xmalloc (sizeof (struct database_pers_head)
477 + (dbs[cnt].suggested_module
478 * sizeof (ref_t)));
479 memset (dbs[cnt].head, '\0', sizeof (dbs[cnt].head));
480 assert (~ENDREF == 0);
481 memset (dbs[cnt].head->array, '\xff',
482 dbs[cnt].suggested_module * sizeof (ref_t));
483 dbs[cnt].head->module = dbs[cnt].suggested_module;
484 dbs[cnt].head->data_size = (DEFAULT_DATASIZE_PER_BUCKET
485 * dbs[cnt].head->module);
486 dbs[cnt].data = xmalloc (dbs[cnt].head->data_size);
487 dbs[cnt].head->first_free = 0;
489 dbs[cnt].shared = 0;
490 assert (dbs[cnt].ro_fd == -1);
493 if (dbs[cnt].check_file)
495 /* We need the modification date of the file. */
496 struct stat st;
498 if (stat (dbs[cnt].filename, &st) < 0)
500 /* We cannot stat() the file, disable file checking. */
501 dbg_log (_("cannot stat() file `%s': %s"),
502 dbs[cnt].filename, strerror (errno));
503 dbs[cnt].check_file = 0;
505 else
506 dbs[cnt].file_mtime = st.st_mtime;
510 /* Create the socket. */
511 sock = socket (AF_UNIX, SOCK_STREAM, 0);
512 if (sock < 0)
514 dbg_log (_("cannot open socket: %s"), strerror (errno));
515 exit (1);
517 /* Bind a name to the socket. */
518 struct sockaddr_un sock_addr;
519 sock_addr.sun_family = AF_UNIX;
520 strcpy (sock_addr.sun_path, _PATH_NSCDSOCKET);
521 if (bind (sock, (struct sockaddr *) &sock_addr, sizeof (sock_addr)) < 0)
523 dbg_log ("%s: %s", _PATH_NSCDSOCKET, strerror (errno));
524 exit (1);
527 /* We don't want to get stuck on accept. */
528 int fl = fcntl (sock, F_GETFL);
529 if (fl == -1 || fcntl (sock, F_SETFL, fl | O_NONBLOCK) == -1)
531 dbg_log (_("cannot change socket to nonblocking mode: %s"),
532 strerror (errno));
533 exit (1);
536 /* The descriptor needs to be closed on exec. */
537 if (paranoia && fcntl (sock, F_SETFD, FD_CLOEXEC) == -1)
539 dbg_log (_("cannot set socket to close on exec: %s"),
540 strerror (errno));
541 exit (1);
544 /* Set permissions for the socket. */
545 chmod (_PATH_NSCDSOCKET, DEFFILEMODE);
547 /* Set the socket up to accept connections. */
548 if (listen (sock, SOMAXCONN) < 0)
550 dbg_log (_("cannot enable socket to accept connections: %s"),
551 strerror (errno));
552 exit (1);
555 /* Change to unprivileged uid/gid/groups if specifed in config file */
556 if (server_user != NULL)
557 finish_drop_privileges ();
561 /* Close the connections. */
562 void
563 close_sockets (void)
565 close (sock);
569 static void
570 invalidate_cache (char *key)
572 dbtype number;
574 if (strcmp (key, "passwd") == 0)
575 number = pwddb;
576 else if (strcmp (key, "group") == 0)
577 number = grpdb;
578 else if (__builtin_expect (strcmp (key, "hosts"), 0) == 0)
580 number = hstdb;
582 /* Re-initialize the resolver. resolv.conf might have changed. */
583 res_init ();
585 else
586 return;
588 if (dbs[number].enabled)
589 prune_cache (&dbs[number], LONG_MAX);
593 #ifdef SCM_RIGHTS
594 static void
595 send_ro_fd (struct database_dyn *db, char *key, int fd)
597 /* If we do not have an read-only file descriptor do nothing. */
598 if (db->ro_fd == -1)
599 return;
601 /* We need to send some data along with the descriptor. */
602 struct iovec iov[1];
603 iov[0].iov_base = key;
604 iov[0].iov_len = strlen (key) + 1;
606 /* Prepare the control message to transfer the descriptor. */
607 union
609 struct cmsghdr hdr;
610 char bytes[CMSG_SPACE (sizeof (int))];
611 } buf;
612 struct msghdr msg = { .msg_iov = iov, .msg_iovlen = 1,
613 .msg_control = buf.bytes,
614 .msg_controllen = sizeof (buf) };
615 struct cmsghdr *cmsg = CMSG_FIRSTHDR (&msg);
617 cmsg->cmsg_level = SOL_SOCKET;
618 cmsg->cmsg_type = SCM_RIGHTS;
619 cmsg->cmsg_len = CMSG_LEN (sizeof (int));
621 *(int *) CMSG_DATA (cmsg) = db->ro_fd;
623 msg.msg_controllen = cmsg->cmsg_len;
625 /* Send the control message. We repeat when we are interrupted but
626 everything else is ignored. */
627 #ifndef MSG_NOSIGNAL
628 # define MSG_NOSIGNAL 0
629 #endif
630 (void) TEMP_FAILURE_RETRY (sendmsg (fd, &msg, MSG_NOSIGNAL));
632 if (__builtin_expect (debug_level > 0, 0))
633 dbg_log (_("provide access to FD %d, for %s"), db->ro_fd, key);
635 #endif /* SCM_RIGHTS */
638 /* Handle new request. */
639 static void
640 handle_request (int fd, request_header *req, void *key, uid_t uid)
642 if (__builtin_expect (req->version, NSCD_VERSION) != NSCD_VERSION)
644 if (debug_level > 0)
645 dbg_log (_("\
646 cannot handle old request version %d; current version is %d"),
647 req->version, NSCD_VERSION);
648 return;
651 /* Make the SELinux check before we go on to the standard checks. We
652 need to verify that the request type is valid, since it has not
653 yet been checked at this point. */
654 if (selinux_enabled
655 && __builtin_expect (req->type, GETPWBYNAME) >= GETPWBYNAME
656 && __builtin_expect (req->type, LASTREQ) < LASTREQ
657 && nscd_request_avc_has_perm (fd, req->type) != 0)
658 return;
660 struct database_dyn *db = serv2db[req->type];
662 // XXX Clean up so that each new command need not introduce a
663 // XXX new conditional.
664 if ((__builtin_expect (req->type, GETPWBYNAME) >= GETPWBYNAME
665 && __builtin_expect (req->type, LASTDBREQ) <= LASTDBREQ)
666 || req->type == GETAI || req->type == INITGROUPS)
668 if (__builtin_expect (debug_level, 0) > 0)
670 if (req->type == GETHOSTBYADDR || req->type == GETHOSTBYADDRv6)
672 char buf[INET6_ADDRSTRLEN];
674 dbg_log ("\t%s (%s)", serv2str[req->type],
675 inet_ntop (req->type == GETHOSTBYADDR
676 ? AF_INET : AF_INET6,
677 key, buf, sizeof (buf)));
679 else
680 dbg_log ("\t%s (%s)", serv2str[req->type], (char *) key);
683 /* Is this service enabled? */
684 if (!db->enabled)
686 /* No, sent the prepared record. */
687 if (TEMP_FAILURE_RETRY (write (fd, db->disabled_iov->iov_base,
688 db->disabled_iov->iov_len))
689 != (ssize_t) db->disabled_iov->iov_len
690 && __builtin_expect (debug_level, 0) > 0)
692 /* We have problems sending the result. */
693 char buf[256];
694 dbg_log (_("cannot write result: %s"),
695 strerror_r (errno, buf, sizeof (buf)));
698 return;
701 /* Be sure we can read the data. */
702 if (__builtin_expect (pthread_rwlock_tryrdlock (&db->lock) != 0, 0))
704 ++db->head->rdlockdelayed;
705 pthread_rwlock_rdlock (&db->lock);
708 /* See whether we can handle it from the cache. */
709 struct datahead *cached;
710 cached = (struct datahead *) cache_search (req->type, key, req->key_len,
711 db, uid);
712 if (cached != NULL)
714 /* Hurray it's in the cache. */
715 if (writeall (fd, cached->data, cached->recsize)
716 != cached->recsize
717 && __builtin_expect (debug_level, 0) > 0)
719 /* We have problems sending the result. */
720 char buf[256];
721 dbg_log (_("cannot write result: %s"),
722 strerror_r (errno, buf, sizeof (buf)));
725 pthread_rwlock_unlock (&db->lock);
727 return;
730 pthread_rwlock_unlock (&db->lock);
732 else if (__builtin_expect (debug_level, 0) > 0)
734 if (req->type == INVALIDATE)
735 dbg_log ("\t%s (%s)", serv2str[req->type], (char *) key);
736 else
737 dbg_log ("\t%s", serv2str[req->type]);
740 /* Handle the request. */
741 switch (req->type)
743 case GETPWBYNAME:
744 addpwbyname (db, fd, req, key, uid);
745 break;
747 case GETPWBYUID:
748 addpwbyuid (db, fd, req, key, uid);
749 break;
751 case GETGRBYNAME:
752 addgrbyname (db, fd, req, key, uid);
753 break;
755 case GETGRBYGID:
756 addgrbygid (db, fd, req, key, uid);
757 break;
759 case GETHOSTBYNAME:
760 addhstbyname (db, fd, req, key, uid);
761 break;
763 case GETHOSTBYNAMEv6:
764 addhstbynamev6 (db, fd, req, key, uid);
765 break;
767 case GETHOSTBYADDR:
768 addhstbyaddr (db, fd, req, key, uid);
769 break;
771 case GETHOSTBYADDRv6:
772 addhstbyaddrv6 (db, fd, req, key, uid);
773 break;
775 case GETAI:
776 addhstai (db, fd, req, key, uid);
777 break;
779 case INITGROUPS:
780 addinitgroups (db, fd, req, key, uid);
781 break;
783 case GETSTAT:
784 case SHUTDOWN:
785 case INVALIDATE:
786 if (! secure_in_use)
788 /* Get the callers credentials. */
789 #ifdef SO_PEERCRED
790 struct ucred caller;
791 socklen_t optlen = sizeof (caller);
793 if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) < 0)
795 char buf[256];
797 dbg_log (_("error getting callers id: %s"),
798 strerror_r (errno, buf, sizeof (buf)));
799 break;
802 uid = caller.uid;
803 #else
804 /* Some systems have no SO_PEERCRED implementation. They don't
805 care about security so we don't as well. */
806 uid = 0;
807 #endif
810 /* Accept shutdown, getstat and invalidate only from root. For
811 the stat call also allow the user specified in the config file. */
812 if (req->type == GETSTAT)
814 if (uid == 0 || uid == stat_uid)
815 send_stats (fd, dbs);
817 else if (uid == 0)
819 if (req->type == INVALIDATE)
820 invalidate_cache (key);
821 else
822 termination_handler (0);
824 break;
826 case GETFDPW:
827 case GETFDGR:
828 case GETFDHST:
829 #ifdef SCM_RIGHTS
830 send_ro_fd (serv2db[req->type], key, fd);
831 #endif
832 break;
834 default:
835 /* Ignore the command, it's nothing we know. */
836 break;
841 /* Restart the process. */
842 static void
843 restart (void)
845 /* First determine the parameters. We do not use the parameters
846 passed to main() since in case nscd is started by running the
847 dynamic linker this will not work. Yes, this is not the usual
848 case but nscd is part of glibc and we occasionally do this. */
849 size_t buflen = 1024;
850 char *buf = alloca (buflen);
851 size_t readlen = 0;
852 int fd = open ("/proc/self/cmdline", O_RDONLY);
853 if (fd == -1)
855 dbg_log (_("\
856 cannot open /proc/self/cmdline: %s; disabling paranoia mode"),
857 strerror (errno));
859 paranoia = 0;
860 return;
863 while (1)
865 ssize_t n = TEMP_FAILURE_RETRY (read (fd, buf + readlen,
866 buflen - readlen));
867 if (n == -1)
869 dbg_log (_("\
870 cannot open /proc/self/cmdline: %s; disabling paranoia mode"),
871 strerror (errno));
873 close (fd);
874 paranoia = 0;
875 return;
878 readlen += n;
880 if (readlen < buflen)
881 break;
883 /* We might have to extend the buffer. */
884 size_t old_buflen = buflen;
885 char *newp = extend_alloca (buf, buflen, 2 * buflen);
886 buf = memmove (newp, buf, old_buflen);
889 close (fd);
891 /* Parse the command line. Worst case scenario: every two
892 characters form one parameter (one character plus NUL). */
893 char **argv = alloca ((readlen / 2 + 1) * sizeof (argv[0]));
894 int argc = 0;
896 char *cp = buf;
897 while (cp < buf + readlen)
899 argv[argc++] = cp;
900 cp = (char *) rawmemchr (cp, '\0') + 1;
902 argv[argc] = NULL;
904 /* Second, change back to the old user if we changed it. */
905 if (server_user != NULL)
907 if (setuid (old_uid) != 0)
909 dbg_log (_("\
910 cannot change to old UID: %s; disabling paranoia mode"),
911 strerror (errno));
913 paranoia = 0;
914 return;
917 if (setgid (old_gid) != 0)
919 dbg_log (_("\
920 cannot change to old GID: %s; disabling paranoia mode"),
921 strerror (errno));
923 setuid (server_uid);
924 paranoia = 0;
925 return;
929 /* Next change back to the old working directory. */
930 if (chdir (oldcwd) == -1)
932 dbg_log (_("\
933 cannot change to old working directory: %s; disabling paranoia mode"),
934 strerror (errno));
936 if (server_user != NULL)
938 setuid (server_uid);
939 setgid (server_gid);
941 paranoia = 0;
942 return;
945 /* Synchronize memory. */
946 for (int cnt = 0; cnt < lastdb; ++cnt)
948 /* Make sure nobody keeps using the database. */
949 dbs[cnt].head->timestamp = 0;
951 if (dbs[cnt].persistent)
952 // XXX async OK?
953 msync (dbs[cnt].head, dbs[cnt].memsize, MS_ASYNC);
956 /* The preparations are done. */
957 execv ("/proc/self/exe", argv);
959 /* If we come here, we will never be able to re-exec. */
960 dbg_log (_("re-exec failed: %s; disabling paranoia mode"),
961 strerror (errno));
963 if (server_user != NULL)
965 setuid (server_uid);
966 setgid (server_gid);
968 chdir ("/");
969 paranoia = 0;
973 /* List of file descriptors. */
974 struct fdlist
976 int fd;
977 struct fdlist *next;
979 /* Memory allocated for the list. */
980 static struct fdlist *fdlist;
981 /* List of currently ready-to-read file descriptors. */
982 static struct fdlist *readylist;
984 /* Conditional variable and mutex to signal availability of entries in
985 READYLIST. The condvar is initialized dynamically since we might
986 use a different clock depending on availability. */
987 static pthread_cond_t readylist_cond;
988 static pthread_mutex_t readylist_lock = PTHREAD_MUTEX_INITIALIZER;
990 /* The clock to use with the condvar. */
991 static clockid_t timeout_clock = CLOCK_REALTIME;
993 /* Number of threads ready to handle the READYLIST. */
994 static unsigned long int nready;
997 /* This is the main loop. It is replicated in different threads but the
998 `poll' call makes sure only one thread handles an incoming connection. */
999 static void *
1000 __attribute__ ((__noreturn__))
1001 nscd_run (void *p)
1003 const long int my_number = (long int) p;
1004 const int run_prune = my_number < lastdb && dbs[my_number].enabled;
1005 struct timespec prune_ts;
1006 int to = 0;
1007 char buf[256];
1009 if (run_prune)
1011 setup_thread (&dbs[my_number]);
1013 /* We are running. */
1014 dbs[my_number].head->timestamp = time (NULL);
1016 if (clock_gettime (timeout_clock, &prune_ts) == -1)
1017 /* Should never happen. */
1018 abort ();
1020 /* Compute timeout time. */
1021 prune_ts.tv_sec += CACHE_PRUNE_INTERVAL;
1024 /* Initial locking. */
1025 pthread_mutex_lock (&readylist_lock);
1027 /* One more thread available. */
1028 ++nready;
1030 while (1)
1032 while (readylist == NULL)
1034 if (run_prune)
1036 /* Wait, but not forever. */
1037 to = pthread_cond_timedwait (&readylist_cond, &readylist_lock,
1038 &prune_ts);
1040 /* If we were woken and there is no work to be done,
1041 just start pruning. */
1042 if (readylist == NULL && to == ETIMEDOUT)
1044 --nready;
1045 pthread_mutex_unlock (&readylist_lock);
1046 goto only_prune;
1049 else
1050 /* No need to timeout. */
1051 pthread_cond_wait (&readylist_cond, &readylist_lock);
1054 struct fdlist *it = readylist->next;
1055 if (readylist->next == readylist)
1056 /* Just one entry on the list. */
1057 readylist = NULL;
1058 else
1059 readylist->next = it->next;
1061 /* Extract the information and mark the record ready to be used
1062 again. */
1063 int fd = it->fd;
1064 it->next = NULL;
1066 /* One more thread available. */
1067 --nready;
1069 /* We are done with the list. */
1070 pthread_mutex_unlock (&readylist_lock);
1072 /* We do not want to block on a short read or so. */
1073 int fl = fcntl (fd, F_GETFL);
1074 if (fl == -1 || fcntl (fd, F_SETFL, fl | O_NONBLOCK) == -1)
1075 goto close_and_out;
1077 /* Now read the request. */
1078 request_header req;
1079 if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd, &req, sizeof (req)))
1080 != sizeof (req), 0))
1082 /* We failed to read data. Note that this also might mean we
1083 failed because we would have blocked. */
1084 if (debug_level > 0)
1085 dbg_log (_("short read while reading request: %s"),
1086 strerror_r (errno, buf, sizeof (buf)));
1087 goto close_and_out;
1090 /* Check whether this is a valid request type. */
1091 if (req.type < GETPWBYNAME || req.type >= LASTREQ)
1092 goto close_and_out;
1094 /* Some systems have no SO_PEERCRED implementation. They don't
1095 care about security so we don't as well. */
1096 uid_t uid = -1;
1097 #ifdef SO_PEERCRED
1098 pid_t pid = 0;
1100 if (secure_in_use)
1102 struct ucred caller;
1103 socklen_t optlen = sizeof (caller);
1105 if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) < 0)
1107 dbg_log (_("error getting callers id: %s"),
1108 strerror_r (errno, buf, sizeof (buf)));
1109 goto close_and_out;
1112 if (req.type < GETPWBYNAME || req.type > LASTDBREQ
1113 || serv2db[req.type]->secure)
1114 uid = caller.uid;
1116 pid = caller.pid;
1118 else if (__builtin_expect (debug_level > 0, 0))
1120 struct ucred caller;
1121 socklen_t optlen = sizeof (caller);
1123 if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) == 0)
1124 pid = caller.pid;
1126 #endif
1128 /* It should not be possible to crash the nscd with a silly
1129 request (i.e., a terribly large key). We limit the size to 1kb. */
1130 #define MAXKEYLEN 1024
1131 if (__builtin_expect (req.key_len, 1) < 0
1132 || __builtin_expect (req.key_len, 1) > MAXKEYLEN)
1134 if (debug_level > 0)
1135 dbg_log (_("key length in request too long: %d"), req.key_len);
1137 else
1139 /* Get the key. */
1140 char keybuf[MAXKEYLEN];
1142 if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd, keybuf,
1143 req.key_len))
1144 != req.key_len, 0))
1146 /* Again, this can also mean we would have blocked. */
1147 if (debug_level > 0)
1148 dbg_log (_("short read while reading request key: %s"),
1149 strerror_r (errno, buf, sizeof (buf)));
1150 goto close_and_out;
1153 if (__builtin_expect (debug_level, 0) > 0)
1155 #ifdef SO_PEERCRED
1156 if (pid != 0)
1157 dbg_log (_("\
1158 handle_request: request received (Version = %d) from PID %ld"),
1159 req.version, (long int) pid);
1160 else
1161 #endif
1162 dbg_log (_("\
1163 handle_request: request received (Version = %d)"), req.version);
1166 /* Phew, we got all the data, now process it. */
1167 handle_request (fd, &req, keybuf, uid);
1170 close_and_out:
1171 /* We are done. */
1172 close (fd);
1174 /* Check whether we should be pruning the cache. */
1175 assert (run_prune || to == 0);
1176 if (to == ETIMEDOUT)
1178 only_prune:
1179 /* The pthread_cond_timedwait() call timed out. It is time
1180 to clean up the cache. */
1181 assert (my_number < lastdb);
1182 prune_cache (&dbs[my_number], time (NULL));
1184 if (clock_gettime (timeout_clock, &prune_ts) == -1)
1185 /* Should never happen. */
1186 abort ();
1188 /* Compute next timeout time. */
1189 prune_ts.tv_sec += CACHE_PRUNE_INTERVAL;
1191 /* In case the list is emtpy we do not want to run the prune
1192 code right away again. */
1193 to = 0;
1196 /* Re-locking. */
1197 pthread_mutex_lock (&readylist_lock);
1199 /* One more thread available. */
1200 ++nready;
1205 static unsigned int nconns;
1207 static void
1208 fd_ready (int fd)
1210 pthread_mutex_lock (&readylist_lock);
1212 /* Find an empty entry in FDLIST. */
1213 size_t inner;
1214 for (inner = 0; inner < nconns; ++inner)
1215 if (fdlist[inner].next == NULL)
1216 break;
1217 assert (inner < nconns);
1219 fdlist[inner].fd = fd;
1221 if (readylist == NULL)
1222 readylist = fdlist[inner].next = &fdlist[inner];
1223 else
1225 fdlist[inner].next = readylist->next;
1226 readylist = readylist->next = &fdlist[inner];
1229 bool do_signal = true;
1230 if (__builtin_expect (nready == 0, 0))
1232 ++client_queued;
1233 do_signal = false;
1235 /* Try to start another thread to help out. */
1236 pthread_t th;
1237 if (nthreads < max_nthreads
1238 && pthread_create (&th, &attr, nscd_run,
1239 (void *) (long int) nthreads) == 0)
1241 /* We got another thread. */
1242 ++nthreads;
1243 /* The new thread might new a kick. */
1244 do_signal = true;
1249 pthread_mutex_unlock (&readylist_lock);
1251 /* Tell one of the worker threads there is work to do. */
1252 if (do_signal)
1253 pthread_cond_signal (&readylist_cond);
1257 /* Check whether restarting should happen. */
1258 static inline int
1259 restart_p (time_t now)
1261 return (paranoia && readylist == NULL && nready == nthreads
1262 && now >= restart_time);
1266 /* Array for times a connection was accepted. */
1267 static time_t *starttime;
1270 static void
1271 __attribute__ ((__noreturn__))
1272 main_loop_poll (void)
1274 struct pollfd *conns = (struct pollfd *) xmalloc (nconns
1275 * sizeof (conns[0]));
1277 conns[0].fd = sock;
1278 conns[0].events = POLLRDNORM;
1279 size_t nused = 1;
1280 size_t firstfree = 1;
1282 while (1)
1284 /* Wait for any event. We wait at most a couple of seconds so
1285 that we can check whether we should close any of the accepted
1286 connections since we have not received a request. */
1287 #define MAX_ACCEPT_TIMEOUT 30
1288 #define MIN_ACCEPT_TIMEOUT 5
1289 #define MAIN_THREAD_TIMEOUT \
1290 (MAX_ACCEPT_TIMEOUT * 1000 \
1291 - ((MAX_ACCEPT_TIMEOUT - MIN_ACCEPT_TIMEOUT) * 1000 * nused) / (2 * nconns))
1293 int n = poll (conns, nused, MAIN_THREAD_TIMEOUT);
1295 time_t now = time (NULL);
1297 /* If there is a descriptor ready for reading or there is a new
1298 connection, process this now. */
1299 if (n > 0)
1301 if (conns[0].revents != 0)
1303 /* We have a new incoming connection. Accept the connection. */
1304 int fd = TEMP_FAILURE_RETRY (accept (sock, NULL, NULL));
1306 /* use the descriptor if we have not reached the limit. */
1307 if (fd >= 0 && firstfree < nconns)
1309 conns[firstfree].fd = fd;
1310 conns[firstfree].events = POLLRDNORM;
1311 starttime[firstfree] = now;
1312 if (firstfree >= nused)
1313 nused = firstfree + 1;
1316 ++firstfree;
1317 while (firstfree < nused && conns[firstfree].fd != -1);
1320 --n;
1323 for (size_t cnt = 1; cnt < nused && n > 0; ++cnt)
1324 if (conns[cnt].revents != 0)
1326 fd_ready (conns[cnt].fd);
1328 /* Clean up the CONNS array. */
1329 conns[cnt].fd = -1;
1330 if (cnt < firstfree)
1331 firstfree = cnt;
1332 if (cnt == nused - 1)
1334 --nused;
1335 while (conns[nused - 1].fd == -1);
1337 --n;
1341 /* Now find entries which have timed out. */
1342 assert (nused > 0);
1344 /* We make the timeout length depend on the number of file
1345 descriptors currently used. */
1346 #define ACCEPT_TIMEOUT \
1347 (MAX_ACCEPT_TIMEOUT \
1348 - ((MAX_ACCEPT_TIMEOUT - MIN_ACCEPT_TIMEOUT) * nused) / nconns)
1349 time_t laststart = now - ACCEPT_TIMEOUT;
1351 for (size_t cnt = nused - 1; cnt > 0; --cnt)
1353 if (conns[cnt].fd != -1 && starttime[cnt] < laststart)
1355 /* Remove the entry, it timed out. */
1356 (void) close (conns[cnt].fd);
1357 conns[cnt].fd = -1;
1359 if (cnt < firstfree)
1360 firstfree = cnt;
1361 if (cnt == nused - 1)
1363 --nused;
1364 while (conns[nused - 1].fd == -1);
1368 if (restart_p (now))
1369 restart ();
1374 #ifdef HAVE_EPOLL
1375 static void
1376 main_loop_epoll (int efd)
1378 struct epoll_event ev = { 0, };
1379 int nused = 1;
1380 size_t highest = 0;
1382 /* Add the socket. */
1383 ev.events = EPOLLRDNORM;
1384 ev.data.fd = sock;
1385 if (epoll_ctl (efd, EPOLL_CTL_ADD, sock, &ev) == -1)
1386 /* We cannot use epoll. */
1387 return;
1389 while (1)
1391 struct epoll_event revs[100];
1392 # define nrevs (sizeof (revs) / sizeof (revs[0]))
1394 int n = epoll_wait (efd, revs, nrevs, MAIN_THREAD_TIMEOUT);
1396 time_t now = time (NULL);
1398 for (int cnt = 0; cnt < n; ++cnt)
1399 if (revs[cnt].data.fd == sock)
1401 /* A new connection. */
1402 int fd = TEMP_FAILURE_RETRY (accept (sock, NULL, NULL));
1404 if (fd >= 0)
1406 /* Try to add the new descriptor. */
1407 ev.data.fd = fd;
1408 if (fd >= nconns
1409 || epoll_ctl (efd, EPOLL_CTL_ADD, fd, &ev) == -1)
1410 /* The descriptor is too large or something went
1411 wrong. Close the descriptor. */
1412 close (fd);
1413 else
1415 /* Remember when we accepted the connection. */
1416 starttime[fd] = now;
1418 if (fd > highest)
1419 highest = fd;
1421 ++nused;
1425 else
1427 /* Remove the descriptor from the epoll descriptor. */
1428 struct epoll_event ev = { 0, };
1429 (void) epoll_ctl (efd, EPOLL_CTL_DEL, revs[cnt].data.fd, &ev);
1431 /* Get a worked to handle the request. */
1432 fd_ready (revs[cnt].data.fd);
1434 /* Reset the time. */
1435 starttime[revs[cnt].data.fd] = 0;
1436 if (revs[cnt].data.fd == highest)
1438 --highest;
1439 while (highest > 0 && starttime[highest] == 0);
1441 --nused;
1444 /* Now look for descriptors for accepted connections which have
1445 no reply in too long of a time. */
1446 time_t laststart = now - ACCEPT_TIMEOUT;
1447 for (int cnt = highest; cnt > STDERR_FILENO; --cnt)
1448 if (cnt != sock && starttime[cnt] != 0 && starttime[cnt] < laststart)
1450 /* We are waiting for this one for too long. Close it. */
1451 struct epoll_event ev = {0, };
1452 (void) epoll_ctl (efd, EPOLL_CTL_DEL, cnt, &ev);
1454 (void) close (cnt);
1456 starttime[cnt] = 0;
1457 if (cnt == highest)
1458 --highest;
1460 else if (cnt != sock && starttime[cnt] == 0 && cnt == highest)
1461 --highest;
1463 if (restart_p (now))
1464 restart ();
1467 #endif
1470 /* Start all the threads we want. The initial process is thread no. 1. */
1471 void
1472 start_threads (void)
1474 /* Initialize the conditional variable we will use. The only
1475 non-standard attribute we might use is the clock selection. */
1476 pthread_condattr_t condattr;
1477 pthread_condattr_init (&condattr);
1479 #if defined _POSIX_CLOCK_SELECTION && _POSIX_CLOCK_SELECTION >= 0 \
1480 && defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
1481 /* Determine whether the monotonous clock is available. */
1482 struct timespec dummy;
1483 # if _POSIX_MONOTONIC_CLOCK == 0
1484 if (sysconf (_SC_MONOTONIC_CLOCK) > 0)
1485 # endif
1486 # if _POSIX_CLOCK_SELECTION == 0
1487 if (sysconf (_SC_CLOCK_SELECTION) > 0)
1488 # endif
1489 if (clock_getres (CLOCK_MONOTONIC, &dummy) == 0
1490 && pthread_condattr_setclock (&condattr, CLOCK_MONOTONIC) == 0)
1491 timeout_clock = CLOCK_MONOTONIC;
1492 #endif
1494 pthread_cond_init (&readylist_cond, &condattr);
1495 pthread_condattr_destroy (&condattr);
1498 /* Create the attribute for the threads. They are all created
1499 detached. */
1500 pthread_attr_init (&attr);
1501 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
1502 /* Use 1MB stacks, twice as much for 64-bit architectures. */
1503 pthread_attr_setstacksize (&attr, 1024 * 1024 * (sizeof (void *) / 4));
1505 /* We allow less than LASTDB threads only for debugging. */
1506 if (debug_level == 0)
1507 nthreads = MAX (nthreads, lastdb);
1509 int nfailed = 0;
1510 for (long int i = 0; i < nthreads; ++i)
1512 pthread_t th;
1513 if (pthread_create (&th, &attr, nscd_run, (void *) (i - nfailed)) != 0)
1514 ++nfailed;
1516 if (nthreads - nfailed < lastdb)
1518 /* We could not start enough threads. */
1519 dbg_log (_("could only start %d threads; terminating"),
1520 nthreads - nfailed);
1521 exit (1);
1524 /* Determine how much room for descriptors we should initially
1525 allocate. This might need to change later if we cap the number
1526 with MAXCONN. */
1527 const long int nfds = sysconf (_SC_OPEN_MAX);
1528 #define MINCONN 32
1529 #define MAXCONN 16384
1530 if (nfds == -1 || nfds > MAXCONN)
1531 nconns = MAXCONN;
1532 else if (nfds < MINCONN)
1533 nconns = MINCONN;
1534 else
1535 nconns = nfds;
1537 /* We need memory to pass descriptors on to the worker threads. */
1538 fdlist = (struct fdlist *) xcalloc (nconns, sizeof (fdlist[0]));
1539 /* Array to keep track when connection was accepted. */
1540 starttime = (time_t *) xcalloc (nconns, sizeof (starttime[0]));
1542 /* In the main thread we execute the loop which handles incoming
1543 connections. */
1544 #ifdef HAVE_EPOLL
1545 int efd = epoll_create (100);
1546 if (efd != -1)
1548 main_loop_epoll (efd);
1549 close (efd);
1551 #endif
1553 main_loop_poll ();
1557 /* Look up the uid, gid, and supplementary groups to run nscd as. When
1558 this function is called, we are not listening on the nscd socket yet so
1559 we can just use the ordinary lookup functions without causing a lockup */
1560 static void
1561 begin_drop_privileges (void)
1563 struct passwd *pwd = getpwnam (server_user);
1565 if (pwd == NULL)
1567 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1568 error (EXIT_FAILURE, 0, _("Failed to run nscd as user '%s'"),
1569 server_user);
1572 server_uid = pwd->pw_uid;
1573 server_gid = pwd->pw_gid;
1575 /* Save the old UID/GID if we have to change back. */
1576 if (paranoia)
1578 old_uid = getuid ();
1579 old_gid = getgid ();
1582 if (getgrouplist (server_user, server_gid, NULL, &server_ngroups) == 0)
1584 /* This really must never happen. */
1585 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1586 error (EXIT_FAILURE, errno, _("initial getgrouplist failed"));
1589 server_groups = (gid_t *) xmalloc (server_ngroups * sizeof (gid_t));
1591 if (getgrouplist (server_user, server_gid, server_groups, &server_ngroups)
1592 == -1)
1594 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1595 error (EXIT_FAILURE, errno, _("getgrouplist failed"));
1600 /* Call setgroups(), setgid(), and setuid() to drop root privileges and
1601 run nscd as the user specified in the configuration file. */
1602 static void
1603 finish_drop_privileges (void)
1605 if (setgroups (server_ngroups, server_groups) == -1)
1607 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1608 error (EXIT_FAILURE, errno, _("setgroups failed"));
1611 if (setgid (server_gid) == -1)
1613 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1614 perror ("setgid");
1615 exit (1);
1618 if (setuid (server_uid) == -1)
1620 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1621 perror ("setuid");
1622 exit (1);