2005-01-30 Ulrich Drepper <drepper@redhat.com>
[glibc/history.git] / nscd / connections.c
blobd4ce2d345e51a853f3f453f1b3b5db4ac058c451
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 char buf[CMSG_SPACE (sizeof (int))];
608 struct msghdr msg = { .msg_iov = iov, .msg_iovlen = 1,
609 .msg_control = buf, .msg_controllen = sizeof (buf) };
610 struct cmsghdr *cmsg = CMSG_FIRSTHDR (&msg);
612 cmsg->cmsg_level = SOL_SOCKET;
613 cmsg->cmsg_type = SCM_RIGHTS;
614 cmsg->cmsg_len = CMSG_LEN (sizeof (int));
616 *(int *) CMSG_DATA (cmsg) = db->ro_fd;
618 msg.msg_controllen = cmsg->cmsg_len;
620 /* Send the control message. We repeat when we are interrupted but
621 everything else is ignored. */
622 #ifndef MSG_NOSIGNAL
623 # define MSG_NOSIGNAL 0
624 #endif
625 (void) TEMP_FAILURE_RETRY (sendmsg (fd, &msg, MSG_NOSIGNAL));
627 if (__builtin_expect (debug_level > 0, 0))
628 dbg_log (_("provide access to FD %d, for %s"), db->ro_fd, key);
630 #endif /* SCM_RIGHTS */
633 /* Handle new request. */
634 static void
635 handle_request (int fd, request_header *req, void *key, uid_t uid)
637 if (__builtin_expect (req->version, NSCD_VERSION) != NSCD_VERSION)
639 if (debug_level > 0)
640 dbg_log (_("\
641 cannot handle old request version %d; current version is %d"),
642 req->version, NSCD_VERSION);
643 return;
646 /* Make the SELinux check before we go on to the standard checks. We
647 need to verify that the request type is valid, since it has not
648 yet been checked at this point. */
649 if (selinux_enabled
650 && __builtin_expect (req->type, GETPWBYNAME) >= GETPWBYNAME
651 && __builtin_expect (req->type, LASTREQ) < LASTREQ
652 && nscd_request_avc_has_perm (fd, req->type) != 0)
653 return;
655 struct database_dyn *db = serv2db[req->type];
657 // XXX Clean up so that each new command need not introduce a
658 // XXX new conditional.
659 if ((__builtin_expect (req->type, GETPWBYNAME) >= GETPWBYNAME
660 && __builtin_expect (req->type, LASTDBREQ) <= LASTDBREQ)
661 || req->type == GETAI || req->type == INITGROUPS)
663 if (__builtin_expect (debug_level, 0) > 0)
665 if (req->type == GETHOSTBYADDR || req->type == GETHOSTBYADDRv6)
667 char buf[INET6_ADDRSTRLEN];
669 dbg_log ("\t%s (%s)", serv2str[req->type],
670 inet_ntop (req->type == GETHOSTBYADDR
671 ? AF_INET : AF_INET6,
672 key, buf, sizeof (buf)));
674 else
675 dbg_log ("\t%s (%s)", serv2str[req->type], (char *) key);
678 /* Is this service enabled? */
679 if (!db->enabled)
681 /* No, sent the prepared record. */
682 if (TEMP_FAILURE_RETRY (write (fd, db->disabled_iov->iov_base,
683 db->disabled_iov->iov_len))
684 != (ssize_t) db->disabled_iov->iov_len
685 && __builtin_expect (debug_level, 0) > 0)
687 /* We have problems sending the result. */
688 char buf[256];
689 dbg_log (_("cannot write result: %s"),
690 strerror_r (errno, buf, sizeof (buf)));
693 return;
696 /* Be sure we can read the data. */
697 if (__builtin_expect (pthread_rwlock_tryrdlock (&db->lock) != 0, 0))
699 ++db->head->rdlockdelayed;
700 pthread_rwlock_rdlock (&db->lock);
703 /* See whether we can handle it from the cache. */
704 struct datahead *cached;
705 cached = (struct datahead *) cache_search (req->type, key, req->key_len,
706 db, uid);
707 if (cached != NULL)
709 /* Hurray it's in the cache. */
710 if (writeall (fd, cached->data, cached->recsize)
711 != cached->recsize
712 && __builtin_expect (debug_level, 0) > 0)
714 /* We have problems sending the result. */
715 char buf[256];
716 dbg_log (_("cannot write result: %s"),
717 strerror_r (errno, buf, sizeof (buf)));
720 pthread_rwlock_unlock (&db->lock);
722 return;
725 pthread_rwlock_unlock (&db->lock);
727 else if (__builtin_expect (debug_level, 0) > 0)
729 if (req->type == INVALIDATE)
730 dbg_log ("\t%s (%s)", serv2str[req->type], (char *) key);
731 else
732 dbg_log ("\t%s", serv2str[req->type]);
735 /* Handle the request. */
736 switch (req->type)
738 case GETPWBYNAME:
739 addpwbyname (db, fd, req, key, uid);
740 break;
742 case GETPWBYUID:
743 addpwbyuid (db, fd, req, key, uid);
744 break;
746 case GETGRBYNAME:
747 addgrbyname (db, fd, req, key, uid);
748 break;
750 case GETGRBYGID:
751 addgrbygid (db, fd, req, key, uid);
752 break;
754 case GETHOSTBYNAME:
755 addhstbyname (db, fd, req, key, uid);
756 break;
758 case GETHOSTBYNAMEv6:
759 addhstbynamev6 (db, fd, req, key, uid);
760 break;
762 case GETHOSTBYADDR:
763 addhstbyaddr (db, fd, req, key, uid);
764 break;
766 case GETHOSTBYADDRv6:
767 addhstbyaddrv6 (db, fd, req, key, uid);
768 break;
770 case GETAI:
771 addhstai (db, fd, req, key, uid);
772 break;
774 case INITGROUPS:
775 addinitgroups (db, fd, req, key, uid);
776 break;
778 case GETSTAT:
779 case SHUTDOWN:
780 case INVALIDATE:
781 if (! secure_in_use)
783 /* Get the callers credentials. */
784 #ifdef SO_PEERCRED
785 struct ucred caller;
786 socklen_t optlen = sizeof (caller);
788 if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) < 0)
790 char buf[256];
792 dbg_log (_("error getting callers id: %s"),
793 strerror_r (errno, buf, sizeof (buf)));
794 break;
797 uid = caller.uid;
798 #else
799 /* Some systems have no SO_PEERCRED implementation. They don't
800 care about security so we don't as well. */
801 uid = 0;
802 #endif
805 /* Accept shutdown, getstat and invalidate only from root. For
806 the stat call also allow the user specified in the config file. */
807 if (req->type == GETSTAT)
809 if (uid == 0 || uid == stat_uid)
810 send_stats (fd, dbs);
812 else if (uid == 0)
814 if (req->type == INVALIDATE)
815 invalidate_cache (key);
816 else
817 termination_handler (0);
819 break;
821 case GETFDPW:
822 case GETFDGR:
823 case GETFDHST:
824 #ifdef SCM_RIGHTS
825 send_ro_fd (serv2db[req->type], key, fd);
826 #endif
827 break;
829 default:
830 /* Ignore the command, it's nothing we know. */
831 break;
836 /* Restart the process. */
837 static void
838 restart (void)
840 /* First determine the parameters. We do not use the parameters
841 passed to main() since in case nscd is started by running the
842 dynamic linker this will not work. Yes, this is not the usual
843 case but nscd is part of glibc and we occasionally do this. */
844 size_t buflen = 1024;
845 char *buf = alloca (buflen);
846 size_t readlen = 0;
847 int fd = open ("/proc/self/cmdline", O_RDONLY);
848 if (fd == -1)
850 dbg_log (_("\
851 cannot open /proc/self/cmdline: %s; disabling paranoia mode"),
852 strerror (errno));
854 paranoia = 0;
855 return;
858 while (1)
860 ssize_t n = TEMP_FAILURE_RETRY (read (fd, buf + readlen,
861 buflen - readlen));
862 if (n == -1)
864 dbg_log (_("\
865 cannot open /proc/self/cmdline: %s; disabling paranoia mode"),
866 strerror (errno));
868 close (fd);
869 paranoia = 0;
870 return;
873 readlen += n;
875 if (readlen < buflen)
876 break;
878 /* We might have to extend the buffer. */
879 size_t old_buflen = buflen;
880 char *newp = extend_alloca (buf, buflen, 2 * buflen);
881 buf = memmove (newp, buf, old_buflen);
884 close (fd);
886 /* Parse the command line. Worst case scenario: every two
887 characters form one parameter (one character plus NUL). */
888 char **argv = alloca ((readlen / 2 + 1) * sizeof (argv[0]));
889 int argc = 0;
891 char *cp = buf;
892 while (cp < buf + readlen)
894 argv[argc++] = cp;
895 cp = (char *) rawmemchr (cp, '\0') + 1;
897 argv[argc] = NULL;
899 /* Second, change back to the old user if we changed it. */
900 if (server_user != NULL)
902 if (setuid (old_uid) != 0)
904 dbg_log (_("\
905 cannot change to old UID: %s; disabling paranoia mode"),
906 strerror (errno));
908 paranoia = 0;
909 return;
912 if (setgid (old_gid) != 0)
914 dbg_log (_("\
915 cannot change to old GID: %s; disabling paranoia mode"),
916 strerror (errno));
918 setuid (server_uid);
919 paranoia = 0;
920 return;
924 /* Next change back to the old working directory. */
925 if (chdir (oldcwd) == -1)
927 dbg_log (_("\
928 cannot change to old working directory: %s; disabling paranoia mode"),
929 strerror (errno));
931 if (server_user != NULL)
933 setuid (server_uid);
934 setgid (server_gid);
936 paranoia = 0;
937 return;
940 /* Synchronize memory. */
941 for (int cnt = 0; cnt < lastdb; ++cnt)
943 /* Make sure nobody keeps using the database. */
944 dbs[cnt].head->timestamp = 0;
946 if (dbs[cnt].persistent)
947 // XXX async OK?
948 msync (dbs[cnt].head, dbs[cnt].memsize, MS_ASYNC);
951 /* The preparations are done. */
952 execv ("/proc/self/exe", argv);
954 /* If we come here, we will never be able to re-exec. */
955 dbg_log (_("re-exec failed: %s; disabling paranoia mode"),
956 strerror (errno));
958 if (server_user != NULL)
960 setuid (server_uid);
961 setgid (server_gid);
963 chdir ("/");
964 paranoia = 0;
968 /* List of file descriptors. */
969 struct fdlist
971 int fd;
972 struct fdlist *next;
974 /* Memory allocated for the list. */
975 static struct fdlist *fdlist;
976 /* List of currently ready-to-read file descriptors. */
977 static struct fdlist *readylist;
979 /* Conditional variable and mutex to signal availability of entries in
980 READYLIST. The condvar is initialized dynamically since we might
981 use a different clock depending on availability. */
982 static pthread_cond_t readylist_cond;
983 static pthread_mutex_t readylist_lock = PTHREAD_MUTEX_INITIALIZER;
985 /* The clock to use with the condvar. */
986 static clockid_t timeout_clock = CLOCK_REALTIME;
988 /* Number of threads ready to handle the READYLIST. */
989 static unsigned long int nready;
992 /* This is the main loop. It is replicated in different threads but the
993 `poll' call makes sure only one thread handles an incoming connection. */
994 static void *
995 __attribute__ ((__noreturn__))
996 nscd_run (void *p)
998 const long int my_number = (long int) p;
999 const int run_prune = my_number < lastdb && dbs[my_number].enabled;
1000 struct timespec prune_ts;
1001 int to = 0;
1002 char buf[256];
1004 if (run_prune)
1006 setup_thread (&dbs[my_number]);
1008 /* We are running. */
1009 dbs[my_number].head->timestamp = time (NULL);
1011 if (clock_gettime (timeout_clock, &prune_ts) == -1)
1012 /* Should never happen. */
1013 abort ();
1015 /* Compute timeout time. */
1016 prune_ts.tv_sec += CACHE_PRUNE_INTERVAL;
1019 /* Initial locking. */
1020 pthread_mutex_lock (&readylist_lock);
1022 /* One more thread available. */
1023 ++nready;
1025 while (1)
1027 while (readylist == NULL)
1029 if (run_prune)
1031 /* Wait, but not forever. */
1032 to = pthread_cond_timedwait (&readylist_cond, &readylist_lock,
1033 &prune_ts);
1035 /* If we were woken and there is no work to be done,
1036 just start pruning. */
1037 if (readylist == NULL && to == ETIMEDOUT)
1039 --nready;
1040 pthread_mutex_unlock (&readylist_lock);
1041 goto only_prune;
1044 else
1045 /* No need to timeout. */
1046 pthread_cond_wait (&readylist_cond, &readylist_lock);
1049 struct fdlist *it = readylist->next;
1050 if (readylist->next == readylist)
1051 /* Just one entry on the list. */
1052 readylist = NULL;
1053 else
1054 readylist->next = it->next;
1056 /* Extract the information and mark the record ready to be used
1057 again. */
1058 int fd = it->fd;
1059 it->next = NULL;
1061 /* One more thread available. */
1062 --nready;
1064 /* We are done with the list. */
1065 pthread_mutex_unlock (&readylist_lock);
1067 /* We do not want to block on a short read or so. */
1068 int fl = fcntl (fd, F_GETFL);
1069 if (fl == -1 || fcntl (fd, F_SETFL, fl | O_NONBLOCK) == -1)
1070 goto close_and_out;
1072 /* Now read the request. */
1073 request_header req;
1074 if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd, &req, sizeof (req)))
1075 != sizeof (req), 0))
1077 /* We failed to read data. Note that this also might mean we
1078 failed because we would have blocked. */
1079 if (debug_level > 0)
1080 dbg_log (_("short read while reading request: %s"),
1081 strerror_r (errno, buf, sizeof (buf)));
1082 goto close_and_out;
1085 /* Check whether this is a valid request type. */
1086 if (req.type < GETPWBYNAME || req.type >= LASTREQ)
1087 goto close_and_out;
1089 /* Some systems have no SO_PEERCRED implementation. They don't
1090 care about security so we don't as well. */
1091 uid_t uid = -1;
1092 #ifdef SO_PEERCRED
1093 pid_t pid = 0;
1095 if (secure_in_use)
1097 struct ucred caller;
1098 socklen_t optlen = sizeof (caller);
1100 if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) < 0)
1102 dbg_log (_("error getting callers id: %s"),
1103 strerror_r (errno, buf, sizeof (buf)));
1104 goto close_and_out;
1107 if (req.type < GETPWBYNAME || req.type > LASTDBREQ
1108 || serv2db[req.type]->secure)
1109 uid = caller.uid;
1111 pid = caller.pid;
1113 else if (__builtin_expect (debug_level > 0, 0))
1115 struct ucred caller;
1116 socklen_t optlen = sizeof (caller);
1118 if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) == 0)
1119 pid = caller.pid;
1121 #endif
1123 /* It should not be possible to crash the nscd with a silly
1124 request (i.e., a terribly large key). We limit the size to 1kb. */
1125 #define MAXKEYLEN 1024
1126 if (__builtin_expect (req.key_len, 1) < 0
1127 || __builtin_expect (req.key_len, 1) > MAXKEYLEN)
1129 if (debug_level > 0)
1130 dbg_log (_("key length in request too long: %d"), req.key_len);
1132 else
1134 /* Get the key. */
1135 char keybuf[MAXKEYLEN];
1137 if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd, keybuf,
1138 req.key_len))
1139 != req.key_len, 0))
1141 /* Again, this can also mean we would have blocked. */
1142 if (debug_level > 0)
1143 dbg_log (_("short read while reading request key: %s"),
1144 strerror_r (errno, buf, sizeof (buf)));
1145 goto close_and_out;
1148 if (__builtin_expect (debug_level, 0) > 0)
1150 #ifdef SO_PEERCRED
1151 if (pid != 0)
1152 dbg_log (_("\
1153 handle_request: request received (Version = %d) from PID %ld"),
1154 req.version, (long int) pid);
1155 else
1156 #endif
1157 dbg_log (_("\
1158 handle_request: request received (Version = %d)"), req.version);
1161 /* Phew, we got all the data, now process it. */
1162 handle_request (fd, &req, keybuf, uid);
1165 close_and_out:
1166 /* We are done. */
1167 close (fd);
1169 /* Check whether we should be pruning the cache. */
1170 assert (run_prune || to == 0);
1171 if (to == ETIMEDOUT)
1173 only_prune:
1174 /* The pthread_cond_timedwait() call timed out. It is time
1175 to clean up the cache. */
1176 assert (my_number < lastdb);
1177 prune_cache (&dbs[my_number], time (NULL));
1179 if (clock_gettime (timeout_clock, &prune_ts) == -1)
1180 /* Should never happen. */
1181 abort ();
1183 /* Compute next timeout time. */
1184 prune_ts.tv_sec += CACHE_PRUNE_INTERVAL;
1186 /* In case the list is emtpy we do not want to run the prune
1187 code right away again. */
1188 to = 0;
1191 /* Re-locking. */
1192 pthread_mutex_lock (&readylist_lock);
1194 /* One more thread available. */
1195 ++nready;
1200 static unsigned int nconns;
1202 static void
1203 fd_ready (int fd)
1205 pthread_mutex_lock (&readylist_lock);
1207 /* Find an empty entry in FDLIST. */
1208 size_t inner;
1209 for (inner = 0; inner < nconns; ++inner)
1210 if (fdlist[inner].next == NULL)
1211 break;
1212 assert (inner < nconns);
1214 fdlist[inner].fd = fd;
1216 if (readylist == NULL)
1217 readylist = fdlist[inner].next = &fdlist[inner];
1218 else
1220 fdlist[inner].next = readylist->next;
1221 readylist = readylist->next = &fdlist[inner];
1224 bool do_signal = true;
1225 if (__builtin_expect (nready == 0, 0))
1227 ++client_queued;
1228 do_signal = false;
1230 /* Try to start another thread to help out. */
1231 pthread_t th;
1232 if (nthreads < max_nthreads
1233 && pthread_create (&th, &attr, nscd_run,
1234 (void *) (long int) nthreads) == 0)
1236 /* We got another thread. */
1237 ++nthreads;
1238 /* The new thread might new a kick. */
1239 do_signal = true;
1244 pthread_mutex_unlock (&readylist_lock);
1246 /* Tell one of the worker threads there is work to do. */
1247 if (do_signal)
1248 pthread_cond_signal (&readylist_cond);
1252 /* Check whether restarting should happen. */
1253 static inline int
1254 restart_p (time_t now)
1256 return (paranoia && readylist == NULL && nready == nthreads
1257 && now >= restart_time);
1261 /* Array for times a connection was accepted. */
1262 static time_t *starttime;
1265 static void
1266 __attribute__ ((__noreturn__))
1267 main_loop_poll (void)
1269 struct pollfd *conns = (struct pollfd *) xmalloc (nconns
1270 * sizeof (conns[0]));
1272 conns[0].fd = sock;
1273 conns[0].events = POLLRDNORM;
1274 size_t nused = 1;
1275 size_t firstfree = 1;
1277 while (1)
1279 /* Wait for any event. We wait at most a couple of seconds so
1280 that we can check whether we should close any of the accepted
1281 connections since we have not received a request. */
1282 #define MAX_ACCEPT_TIMEOUT 30
1283 #define MIN_ACCEPT_TIMEOUT 5
1284 #define MAIN_THREAD_TIMEOUT \
1285 (MAX_ACCEPT_TIMEOUT * 1000 \
1286 - ((MAX_ACCEPT_TIMEOUT - MIN_ACCEPT_TIMEOUT) * 1000 * nused) / (2 * nconns))
1288 int n = poll (conns, nused, MAIN_THREAD_TIMEOUT);
1290 time_t now = time (NULL);
1292 /* If there is a descriptor ready for reading or there is a new
1293 connection, process this now. */
1294 if (n > 0)
1296 if (conns[0].revents != 0)
1298 /* We have a new incoming connection. Accept the connection. */
1299 int fd = TEMP_FAILURE_RETRY (accept (sock, NULL, NULL));
1301 /* use the descriptor if we have not reached the limit. */
1302 if (fd >= 0 && firstfree < nconns)
1304 conns[firstfree].fd = fd;
1305 conns[firstfree].events = POLLRDNORM;
1306 starttime[firstfree] = now;
1307 if (firstfree >= nused)
1308 nused = firstfree + 1;
1311 ++firstfree;
1312 while (firstfree < nused && conns[firstfree].fd != -1);
1315 --n;
1318 for (size_t cnt = 1; cnt < nused && n > 0; ++cnt)
1319 if (conns[cnt].revents != 0)
1321 fd_ready (conns[cnt].fd);
1323 /* Clean up the CONNS array. */
1324 conns[cnt].fd = -1;
1325 if (cnt < firstfree)
1326 firstfree = cnt;
1327 if (cnt == nused - 1)
1329 --nused;
1330 while (conns[nused - 1].fd == -1);
1332 --n;
1336 /* Now find entries which have timed out. */
1337 assert (nused > 0);
1339 /* We make the timeout length depend on the number of file
1340 descriptors currently used. */
1341 #define ACCEPT_TIMEOUT \
1342 (MAX_ACCEPT_TIMEOUT \
1343 - ((MAX_ACCEPT_TIMEOUT - MIN_ACCEPT_TIMEOUT) * nused) / nconns)
1344 time_t laststart = now - ACCEPT_TIMEOUT;
1346 for (size_t cnt = nused - 1; cnt > 0; --cnt)
1348 if (conns[cnt].fd != -1 && starttime[cnt] < laststart)
1350 /* Remove the entry, it timed out. */
1351 (void) close (conns[cnt].fd);
1352 conns[cnt].fd = -1;
1354 if (cnt < firstfree)
1355 firstfree = cnt;
1356 if (cnt == nused - 1)
1358 --nused;
1359 while (conns[nused - 1].fd == -1);
1363 if (restart_p (now))
1364 restart ();
1369 #ifdef HAVE_EPOLL
1370 static void
1371 main_loop_epoll (int efd)
1373 struct epoll_event ev = { 0, };
1374 int nused = 1;
1375 size_t highest = 0;
1377 /* Add the socket. */
1378 ev.events = EPOLLRDNORM;
1379 ev.data.fd = sock;
1380 if (epoll_ctl (efd, EPOLL_CTL_ADD, sock, &ev) == -1)
1381 /* We cannot use epoll. */
1382 return;
1384 while (1)
1386 struct epoll_event revs[100];
1387 # define nrevs (sizeof (revs) / sizeof (revs[0]))
1389 int n = epoll_wait (efd, revs, nrevs, MAIN_THREAD_TIMEOUT);
1391 time_t now = time (NULL);
1393 for (int cnt = 0; cnt < n; ++cnt)
1394 if (revs[cnt].data.fd == sock)
1396 /* A new connection. */
1397 int fd = TEMP_FAILURE_RETRY (accept (sock, NULL, NULL));
1399 if (fd >= 0)
1401 /* Try to add the new descriptor. */
1402 ev.data.fd = fd;
1403 if (fd >= nconns
1404 || epoll_ctl (efd, EPOLL_CTL_ADD, fd, &ev) == -1)
1405 /* The descriptor is too large or something went
1406 wrong. Close the descriptor. */
1407 close (fd);
1408 else
1410 /* Remember when we accepted the connection. */
1411 starttime[fd] = now;
1413 if (fd > highest)
1414 highest = fd;
1416 ++nused;
1420 else
1422 /* Remove the descriptor from the epoll descriptor. */
1423 struct epoll_event ev = { 0, };
1424 (void) epoll_ctl (efd, EPOLL_CTL_DEL, revs[cnt].data.fd, &ev);
1426 /* Get a worked to handle the request. */
1427 fd_ready (revs[cnt].data.fd);
1429 /* Reset the time. */
1430 starttime[revs[cnt].data.fd] = 0;
1431 if (revs[cnt].data.fd == highest)
1433 --highest;
1434 while (highest > 0 && starttime[highest] == 0);
1436 --nused;
1439 /* Now look for descriptors for accepted connections which have
1440 no reply in too long of a time. */
1441 time_t laststart = now - ACCEPT_TIMEOUT;
1442 for (int cnt = highest; cnt > STDERR_FILENO; --cnt)
1443 if (cnt != sock && starttime[cnt] != 0 && starttime[cnt] < laststart)
1445 /* We are waiting for this one for too long. Close it. */
1446 struct epoll_event ev = {0, };
1447 (void) epoll_ctl (efd, EPOLL_CTL_DEL, cnt, &ev);
1449 (void) close (cnt);
1451 starttime[cnt] = 0;
1452 if (cnt == highest)
1453 --highest;
1455 else if (cnt != sock && starttime[cnt] == 0 && cnt == highest)
1456 --highest;
1458 if (restart_p (now))
1459 restart ();
1462 #endif
1465 /* Start all the threads we want. The initial process is thread no. 1. */
1466 void
1467 start_threads (void)
1469 /* Initialize the conditional variable we will use. The only
1470 non-standard attribute we might use is the clock selection. */
1471 pthread_condattr_t condattr;
1472 pthread_condattr_init (&condattr);
1474 #if defined _POSIX_CLOCK_SELECTION && _POSIX_CLOCK_SELECTION >= 0 \
1475 && defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
1476 /* Determine whether the monotonous clock is available. */
1477 struct timespec dummy;
1478 # if _POSIX_MONOTONIC_CLOCK == 0
1479 if (sysconf (_SC_MONOTONIC_CLOCK) > 0)
1480 # endif
1481 # if _POSIX_CLOCK_SELECTION == 0
1482 if (sysconf (_SC_CLOCK_SELECTION) > 0)
1483 # endif
1484 if (clock_getres (CLOCK_MONOTONIC, &dummy) == 0
1485 && pthread_condattr_setclock (&condattr, CLOCK_MONOTONIC) == 0)
1486 timeout_clock = CLOCK_MONOTONIC;
1487 #endif
1489 pthread_cond_init (&readylist_cond, &condattr);
1490 pthread_condattr_destroy (&condattr);
1493 /* Create the attribute for the threads. They are all created
1494 detached. */
1495 pthread_attr_init (&attr);
1496 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
1497 /* Use 1MB stacks, twice as much for 64-bit architectures. */
1498 pthread_attr_setstacksize (&attr, 1024 * 1024 * (sizeof (void *) / 4));
1500 /* We allow less than LASTDB threads only for debugging. */
1501 if (debug_level == 0)
1502 nthreads = MAX (nthreads, lastdb);
1504 int nfailed = 0;
1505 for (long int i = 0; i < nthreads; ++i)
1507 pthread_t th;
1508 if (pthread_create (&th, &attr, nscd_run, (void *) (i - nfailed)) != 0)
1509 ++nfailed;
1511 if (nthreads - nfailed < lastdb)
1513 /* We could not start enough threads. */
1514 dbg_log (_("could only start %d threads; terminating"),
1515 nthreads - nfailed);
1516 exit (1);
1519 /* Determine how much room for descriptors we should initially
1520 allocate. This might need to change later if we cap the number
1521 with MAXCONN. */
1522 const long int nfds = sysconf (_SC_OPEN_MAX);
1523 #define MINCONN 32
1524 #define MAXCONN 16384
1525 if (nfds == -1 || nfds > MAXCONN)
1526 nconns = MAXCONN;
1527 else if (nfds < MINCONN)
1528 nconns = MINCONN;
1529 else
1530 nconns = nfds;
1532 /* We need memory to pass descriptors on to the worker threads. */
1533 fdlist = (struct fdlist *) xcalloc (nconns, sizeof (fdlist[0]));
1534 /* Array to keep track when connection was accepted. */
1535 starttime = (time_t *) xcalloc (nconns, sizeof (starttime[0]));
1537 /* In the main thread we execute the loop which handles incoming
1538 connections. */
1539 #ifdef HAVE_EPOLL
1540 int efd = epoll_create (100);
1541 if (efd != -1)
1543 main_loop_epoll (efd);
1544 close (efd);
1546 #endif
1548 main_loop_poll ();
1552 /* Look up the uid, gid, and supplementary groups to run nscd as. When
1553 this function is called, we are not listening on the nscd socket yet so
1554 we can just use the ordinary lookup functions without causing a lockup */
1555 static void
1556 begin_drop_privileges (void)
1558 struct passwd *pwd = getpwnam (server_user);
1560 if (pwd == NULL)
1562 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1563 error (EXIT_FAILURE, 0, _("Failed to run nscd as user '%s'"),
1564 server_user);
1567 server_uid = pwd->pw_uid;
1568 server_gid = pwd->pw_gid;
1570 /* Save the old UID/GID if we have to change back. */
1571 if (paranoia)
1573 old_uid = getuid ();
1574 old_gid = getgid ();
1577 if (getgrouplist (server_user, server_gid, NULL, &server_ngroups) == 0)
1579 /* This really must never happen. */
1580 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1581 error (EXIT_FAILURE, errno, _("initial getgrouplist failed"));
1584 server_groups = (gid_t *) xmalloc (server_ngroups * sizeof (gid_t));
1586 if (getgrouplist (server_user, server_gid, server_groups, &server_ngroups)
1587 == -1)
1589 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1590 error (EXIT_FAILURE, errno, _("getgrouplist failed"));
1595 /* Call setgroups(), setgid(), and setuid() to drop root privileges and
1596 run nscd as the user specified in the configuration file. */
1597 static void
1598 finish_drop_privileges (void)
1600 if (setgroups (server_ngroups, server_groups) == -1)
1602 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1603 error (EXIT_FAILURE, errno, _("setgroups failed"));
1606 if (setgid (server_gid) == -1)
1608 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1609 perror ("setgid");
1610 exit (1);
1613 if (setuid (server_uid) == -1)
1615 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1616 perror ("setuid");
1617 exit (1);