2.3.3-74
[glibc.git] / nscd / connections.c
blobaa760e02523409c33f5301f7b701734af97ae161
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 <dlfcn.h>
25 #include <error.h>
26 #include <errno.h>
27 #include <fcntl.h>
28 #include <grp.h>
29 #include <libintl.h>
30 #include <pthread.h>
31 #include <pwd.h>
32 #include <resolv.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <unistd.h>
36 #include <arpa/inet.h>
37 #ifdef HAVE_EPOLL
38 # include <sys/epoll.h>
39 #endif
40 #include <sys/mman.h>
41 #include <sys/param.h>
42 #include <sys/poll.h>
43 #include <sys/socket.h>
44 #include <sys/stat.h>
45 #include <sys/un.h>
46 #include <gnu/lib-names.h>
48 #include "nscd.h"
49 #include "dbg_log.h"
50 #include "selinux.h"
53 /* Number of bytes of data we initially reserve for each hash table bucket. */
54 #define DEFAULT_DATASIZE_PER_BUCKET 1024
57 /* Wrapper functions with error checking for standard functions. */
58 extern void *xmalloc (size_t n);
59 extern void *xcalloc (size_t n, size_t s);
60 extern void *xrealloc (void *o, size_t n);
62 /* Support to run nscd as an unprivileged user */
63 const char *server_user;
64 static uid_t server_uid;
65 static gid_t server_gid;
66 const char *stat_user;
67 uid_t stat_uid;
68 static gid_t *server_groups;
69 #ifndef NGROUPS
70 # define NGROUPS 32
71 #endif
72 static int server_ngroups;
74 static pthread_attr_t attr;
76 static void begin_drop_privileges (void);
77 static void finish_drop_privileges (void);
79 /* Map request type to a string. */
80 const char *serv2str[LASTREQ] =
82 [GETPWBYNAME] = "GETPWBYNAME",
83 [GETPWBYUID] = "GETPWBYUID",
84 [GETGRBYNAME] = "GETGRBYNAME",
85 [GETGRBYGID] = "GETGRBYGID",
86 [GETHOSTBYNAME] = "GETHOSTBYNAME",
87 [GETHOSTBYNAMEv6] = "GETHOSTBYNAMEv6",
88 [GETHOSTBYADDR] = "GETHOSTBYADDR",
89 [GETHOSTBYADDRv6] = "GETHOSTBYADDRv6",
90 [SHUTDOWN] = "SHUTDOWN",
91 [GETSTAT] = "GETSTAT",
92 [INVALIDATE] = "INVALIDATE",
93 [GETFDPW] = "GETFDPW",
94 [GETFDGR] = "GETFDGR",
95 [GETFDHST] = "GETFDHST",
96 [GETAI] = "GETAI",
97 [INITGROUPS] = "INITGROUPS"
100 /* The control data structures for the services. */
101 struct database_dyn dbs[lastdb] =
103 [pwddb] = {
104 .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
105 .enabled = 0,
106 .check_file = 1,
107 .persistent = 0,
108 .shared = 0,
109 .filename = "/etc/passwd",
110 .db_filename = _PATH_NSCD_PASSWD_DB,
111 .disabled_iov = &pwd_iov_disabled,
112 .postimeout = 3600,
113 .negtimeout = 20,
114 .wr_fd = -1,
115 .ro_fd = -1,
116 .mmap_used = false
118 [grpdb] = {
119 .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
120 .enabled = 0,
121 .check_file = 1,
122 .persistent = 0,
123 .shared = 0,
124 .filename = "/etc/group",
125 .db_filename = _PATH_NSCD_GROUP_DB,
126 .disabled_iov = &grp_iov_disabled,
127 .postimeout = 3600,
128 .negtimeout = 60,
129 .wr_fd = -1,
130 .ro_fd = -1,
131 .mmap_used = false
133 [hstdb] = {
134 .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
135 .enabled = 0,
136 .check_file = 1,
137 .persistent = 0,
138 .shared = 0,
139 .filename = "/etc/hosts",
140 .db_filename = _PATH_NSCD_HOSTS_DB,
141 .disabled_iov = &hst_iov_disabled,
142 .postimeout = 3600,
143 .negtimeout = 20,
144 .wr_fd = -1,
145 .ro_fd = -1,
146 .mmap_used = false
151 /* Mapping of request type to database. */
152 static struct database_dyn *const serv2db[LASTREQ] =
154 [GETPWBYNAME] = &dbs[pwddb],
155 [GETPWBYUID] = &dbs[pwddb],
156 [GETGRBYNAME] = &dbs[grpdb],
157 [GETGRBYGID] = &dbs[grpdb],
158 [GETHOSTBYNAME] = &dbs[hstdb],
159 [GETHOSTBYNAMEv6] = &dbs[hstdb],
160 [GETHOSTBYADDR] = &dbs[hstdb],
161 [GETHOSTBYADDRv6] = &dbs[hstdb],
162 [GETFDPW] = &dbs[pwddb],
163 [GETFDGR] = &dbs[grpdb],
164 [GETFDHST] = &dbs[hstdb],
165 [GETAI] = &dbs[hstdb],
166 [INITGROUPS] = &dbs[grpdb]
170 /* Number of seconds between two cache pruning runs. */
171 #define CACHE_PRUNE_INTERVAL 15
174 /* Initial number of threads to use. */
175 int nthreads = -1;
176 /* Maximum number of threads to use. */
177 int max_nthreads = 32;
179 /* Socket for incoming connections. */
180 static int sock;
182 /* Number of times clients had to wait. */
183 unsigned long int client_queued;
186 /* Initialize database information structures. */
187 void
188 nscd_init (void)
190 struct sockaddr_un sock_addr;
191 size_t cnt;
193 /* Secure mode and unprivileged mode are incompatible */
194 if (server_user != NULL && secure_in_use)
196 dbg_log (_("Cannot run nscd in secure mode as unprivileged user"));
197 exit (1);
200 /* Look up unprivileged uid/gid/groups before we start listening on the
201 socket */
202 if (server_user != NULL)
203 begin_drop_privileges ();
205 if (nthreads == -1)
206 /* No configuration for this value, assume a default. */
207 nthreads = 2 * lastdb;
209 for (cnt = 0; cnt < lastdb; ++cnt)
210 if (dbs[cnt].enabled)
212 pthread_rwlock_init (&dbs[cnt].lock, NULL);
213 pthread_mutex_init (&dbs[cnt].memlock, NULL);
215 if (dbs[cnt].persistent)
217 /* Try to open the appropriate file on disk. */
218 int fd = open (dbs[cnt].db_filename, O_RDWR);
219 if (fd != -1)
221 struct stat64 st;
222 void *mem;
223 size_t total;
224 struct database_pers_head head;
225 ssize_t n = TEMP_FAILURE_RETRY (read (fd, &head,
226 sizeof (head)));
227 if (n != sizeof (head) || fstat64 (fd, &st) != 0)
229 fail_db:
230 dbg_log (_("invalid persistent database file \"%s\": %s"),
231 dbs[cnt].db_filename, strerror (errno));
232 dbs[cnt].persistent = 0;
234 else if (head.module == 0 && head.data_size == 0)
236 /* The file has been created, but the head has not been
237 initialized yet. Remove the old file. */
238 unlink (dbs[cnt].db_filename);
240 else if (head.header_size != (int) sizeof (head))
242 dbg_log (_("invalid persistent database file \"%s\": %s"),
243 dbs[cnt].db_filename,
244 _("header size does not match"));
245 dbs[cnt].persistent = 0;
247 else if ((total = (sizeof (head)
248 + roundup (head.module * sizeof (ref_t),
249 ALIGN)
250 + head.data_size))
251 > st.st_size)
253 dbg_log (_("invalid persistent database file \"%s\": %s"),
254 dbs[cnt].db_filename,
255 _("file size does not match"));
256 dbs[cnt].persistent = 0;
258 else if ((mem = mmap (NULL, total, PROT_READ | PROT_WRITE,
259 MAP_SHARED, fd, 0)) == MAP_FAILED)
260 goto fail_db;
261 else
263 /* Success. We have the database. */
264 dbs[cnt].head = mem;
265 dbs[cnt].memsize = total;
266 dbs[cnt].data = (char *)
267 &dbs[cnt].head->array[roundup (dbs[cnt].head->module,
268 ALIGN / sizeof (ref_t))];
269 dbs[cnt].mmap_used = true;
271 if (dbs[cnt].suggested_module > head.module)
272 dbg_log (_("suggested size of table for database %s larger than the persistent database's table"),
273 dbnames[cnt]);
275 dbs[cnt].wr_fd = fd;
276 fd = -1;
277 /* We also need a read-only descriptor. */
278 if (dbs[cnt].shared)
280 dbs[cnt].ro_fd = open (dbs[cnt].db_filename, O_RDONLY);
281 if (dbs[cnt].ro_fd == -1)
282 dbg_log (_("\
283 cannot create read-only descriptor for \"%s\"; no mmap"),
284 dbs[cnt].db_filename);
287 // XXX Shall we test whether the descriptors actually
288 // XXX point to the same file?
291 /* Close the file descriptors in case something went
292 wrong in which case the variable have not been
293 assigned -1. */
294 if (fd != -1)
295 close (fd);
299 if (dbs[cnt].head == NULL)
301 /* No database loaded. Allocate the data structure,
302 possibly on disk. */
303 struct database_pers_head head;
304 size_t total = (sizeof (head)
305 + roundup (dbs[cnt].suggested_module
306 * sizeof (ref_t), ALIGN)
307 + (dbs[cnt].suggested_module
308 * DEFAULT_DATASIZE_PER_BUCKET));
310 /* Try to create the database. If we do not need a
311 persistent database create a temporary file. */
312 int fd;
313 int ro_fd = -1;
314 if (dbs[cnt].persistent)
316 fd = open (dbs[cnt].db_filename,
317 O_RDWR | O_CREAT | O_EXCL | O_TRUNC,
318 S_IRUSR | S_IWUSR);
319 if (fd != -1 && dbs[cnt].shared)
320 ro_fd = open (dbs[cnt].db_filename, O_RDONLY);
322 else
324 char fname[] = _PATH_NSCD_XYZ_DB_TMP;
325 fd = mkstemp (fname);
327 /* We do not need the file name anymore after we
328 opened another file descriptor in read-only mode. */
329 if (fd != -1)
331 if (dbs[cnt].shared)
332 ro_fd = open (fname, O_RDONLY);
334 unlink (fname);
338 if (fd == -1)
340 if (errno == EEXIST)
342 dbg_log (_("database for %s corrupted or simultaneously used; remove %s manually if necessary and restart"),
343 dbnames[cnt], dbs[cnt].db_filename);
344 // XXX Correct way to terminate?
345 exit (1);
348 if (dbs[cnt].persistent)
349 dbg_log (_("cannot create %s; no persistent database used"),
350 dbs[cnt].db_filename);
351 else
352 dbg_log (_("cannot create %s; no sharing possible"),
353 dbs[cnt].db_filename);
355 dbs[cnt].persistent = 0;
356 // XXX remember: no mmap
358 else
360 /* Tell the user if we could not create the read-only
361 descriptor. */
362 if (ro_fd == -1 && dbs[cnt].shared)
363 dbg_log (_("\
364 cannot create read-only descriptor for \"%s\"; no mmap"),
365 dbs[cnt].db_filename);
367 /* Before we create the header, initialiye the hash
368 table. So that if we get interrupted if writing
369 the header we can recognize a partially initialized
370 database. */
371 size_t ps = sysconf (_SC_PAGESIZE);
372 char tmpbuf[ps];
373 assert (~ENDREF == 0);
374 memset (tmpbuf, '\xff', ps);
376 size_t remaining = dbs[cnt].suggested_module * sizeof (ref_t);
377 off_t offset = sizeof (head);
379 size_t towrite;
380 if (offset % ps != 0)
382 towrite = MIN (remaining, ps - (offset % ps));
383 pwrite (fd, tmpbuf, towrite, offset);
384 offset += towrite;
385 remaining -= towrite;
388 while (remaining > ps)
390 pwrite (fd, tmpbuf, ps, offset);
391 offset += ps;
392 remaining -= ps;
395 if (remaining > 0)
396 pwrite (fd, tmpbuf, remaining, offset);
398 /* Create the header of the file. */
399 struct database_pers_head head =
401 .version = DB_VERSION,
402 .header_size = sizeof (head),
403 .module = dbs[cnt].suggested_module,
404 .data_size = (dbs[cnt].suggested_module
405 * DEFAULT_DATASIZE_PER_BUCKET),
406 .first_free = 0
408 void *mem;
410 if ((TEMP_FAILURE_RETRY (write (fd, &head, sizeof (head)))
411 != sizeof (head))
412 || ftruncate (fd, total) != 0
413 || (mem = mmap (NULL, total, PROT_READ | PROT_WRITE,
414 MAP_SHARED, fd, 0)) == MAP_FAILED)
416 unlink (dbs[cnt].db_filename);
417 dbg_log (_("cannot write to database file %s: %s"),
418 dbs[cnt].db_filename, strerror (errno));
419 dbs[cnt].persistent = 0;
421 else
423 /* Success. */
424 dbs[cnt].head = mem;
425 dbs[cnt].data = (char *)
426 &dbs[cnt].head->array[roundup (dbs[cnt].head->module,
427 ALIGN / sizeof (ref_t))];
428 dbs[cnt].memsize = total;
429 dbs[cnt].mmap_used = true;
431 /* Remember the descriptors. */
432 dbs[cnt].wr_fd = fd;
433 dbs[cnt].ro_fd = ro_fd;
434 fd = -1;
435 ro_fd = -1;
438 if (fd != -1)
439 close (fd);
440 if (ro_fd != -1)
441 close (ro_fd);
445 if (paranoia
446 && ((dbs[cnt].wr_fd != -1
447 && fcntl (dbs[cnt].wr_fd, F_SETFD, FD_CLOEXEC) == -1)
448 || (dbs[cnt].ro_fd != -1
449 && fcntl (dbs[cnt].ro_fd, F_SETFD, FD_CLOEXEC) == -1)))
451 dbg_log (_("\
452 cannot set socket to close on exec: %s; disabling paranoia mode"),
453 strerror (errno));
454 paranoia = 0;
457 if (dbs[cnt].head == NULL)
459 /* We do not use the persistent database. Just
460 create an in-memory data structure. */
461 assert (! dbs[cnt].persistent);
463 dbs[cnt].head = xmalloc (sizeof (struct database_pers_head)
464 + (dbs[cnt].suggested_module
465 * sizeof (ref_t)));
466 memset (dbs[cnt].head, '\0', sizeof (dbs[cnt].head));
467 assert (~ENDREF == 0);
468 memset (dbs[cnt].head->array, '\xff',
469 dbs[cnt].suggested_module * sizeof (ref_t));
470 dbs[cnt].head->module = dbs[cnt].suggested_module;
471 dbs[cnt].head->data_size = (DEFAULT_DATASIZE_PER_BUCKET
472 * dbs[cnt].head->module);
473 dbs[cnt].data = xmalloc (dbs[cnt].head->data_size);
474 dbs[cnt].head->first_free = 0;
476 dbs[cnt].shared = 0;
477 assert (dbs[cnt].ro_fd == -1);
480 if (dbs[cnt].check_file)
482 /* We need the modification date of the file. */
483 struct stat st;
485 if (stat (dbs[cnt].filename, &st) < 0)
487 /* We cannot stat() the file, disable file checking. */
488 dbg_log (_("cannot stat() file `%s': %s"),
489 dbs[cnt].filename, strerror (errno));
490 dbs[cnt].check_file = 0;
492 else
493 dbs[cnt].file_mtime = st.st_mtime;
497 /* Create the socket. */
498 sock = socket (AF_UNIX, SOCK_STREAM, 0);
499 if (sock < 0)
501 dbg_log (_("cannot open socket: %s"), strerror (errno));
502 exit (1);
504 /* Bind a name to the socket. */
505 sock_addr.sun_family = AF_UNIX;
506 strcpy (sock_addr.sun_path, _PATH_NSCDSOCKET);
507 if (bind (sock, (struct sockaddr *) &sock_addr, sizeof (sock_addr)) < 0)
509 dbg_log ("%s: %s", _PATH_NSCDSOCKET, strerror (errno));
510 exit (1);
513 /* We don't want to get stuck on accept. */
514 int fl = fcntl (sock, F_GETFL);
515 if (fl == -1 || fcntl (sock, F_SETFL, fl | O_NONBLOCK) == -1)
517 dbg_log (_("cannot change socket to nonblocking mode: %s"),
518 strerror (errno));
519 exit (1);
522 /* The descriptor needs to be closed on exec. */
523 if (paranoia && fcntl (sock, F_SETFD, FD_CLOEXEC) == -1)
525 dbg_log (_("cannot set socket to close on exec: %s"),
526 strerror (errno));
527 exit (1);
530 /* Set permissions for the socket. */
531 chmod (_PATH_NSCDSOCKET, DEFFILEMODE);
533 /* Set the socket up to accept connections. */
534 if (listen (sock, SOMAXCONN) < 0)
536 dbg_log (_("cannot enable socket to accept connections: %s"),
537 strerror (errno));
538 exit (1);
541 /* Change to unprivileged uid/gid/groups if specifed in config file */
542 if (server_user != NULL)
543 finish_drop_privileges ();
547 /* Close the connections. */
548 void
549 close_sockets (void)
551 close (sock);
555 static void
556 invalidate_cache (char *key)
558 dbtype number;
560 if (strcmp (key, "passwd") == 0)
561 number = pwddb;
562 else if (strcmp (key, "group") == 0)
563 number = grpdb;
564 else if (__builtin_expect (strcmp (key, "hosts"), 0) == 0)
566 number = hstdb;
568 /* Re-initialize the resolver. resolv.conf might have changed. */
569 res_init ();
571 else
572 return;
574 if (dbs[number].enabled)
575 prune_cache (&dbs[number], LONG_MAX);
579 #ifdef SCM_RIGHTS
580 static void
581 send_ro_fd (struct database_dyn *db, char *key, int fd)
583 /* If we do not have an read-only file descriptor do nothing. */
584 if (db->ro_fd == -1)
585 return;
587 /* We need to send some data along with the descriptor. */
588 struct iovec iov[1];
589 iov[0].iov_base = key;
590 iov[0].iov_len = strlen (key) + 1;
592 /* Prepare the control message to transfer the descriptor. */
593 char buf[CMSG_SPACE (sizeof (int))];
594 struct msghdr msg = { .msg_iov = iov, .msg_iovlen = 1,
595 .msg_control = buf, .msg_controllen = sizeof (buf) };
596 struct cmsghdr *cmsg = CMSG_FIRSTHDR (&msg);
598 cmsg->cmsg_level = SOL_SOCKET;
599 cmsg->cmsg_type = SCM_RIGHTS;
600 cmsg->cmsg_len = CMSG_LEN (sizeof (int));
602 *(int *) CMSG_DATA (cmsg) = db->ro_fd;
604 msg.msg_controllen = cmsg->cmsg_len;
606 /* Send the control message. We repeat when we are interrupted but
607 everything else is ignored. */
608 (void) TEMP_FAILURE_RETRY (sendmsg (fd, &msg, 0));
610 if (__builtin_expect (debug_level > 0, 0))
611 dbg_log (_("provide access to FD %d, for %s"), db->ro_fd, key);
613 #endif /* SCM_RIGHTS */
616 /* Handle new request. */
617 static void
618 handle_request (int fd, request_header *req, void *key, uid_t uid)
620 if (__builtin_expect (req->version, NSCD_VERSION) != NSCD_VERSION)
622 if (debug_level > 0)
623 dbg_log (_("\
624 cannot handle old request version %d; current version is %d"),
625 req->version, NSCD_VERSION);
626 return;
629 /* Make the SELinux check before we go on to the standard checks. We
630 need to verify that the request type is valid, since it has not
631 yet been checked at this point. */
632 if (selinux_enabled
633 && __builtin_expect (req->type, GETPWBYNAME) >= GETPWBYNAME
634 && __builtin_expect (req->type, LASTREQ) < LASTREQ
635 && nscd_request_avc_has_perm (fd, req->type) != 0)
636 return;
638 struct database_dyn *db = serv2db[req->type];
640 // XXX Clean up so that each new command need not introduce a
641 // XXX new conditional.
642 if ((__builtin_expect (req->type, GETPWBYNAME) >= GETPWBYNAME
643 && __builtin_expect (req->type, LASTDBREQ) <= LASTDBREQ)
644 || req->type == GETAI || req->type == INITGROUPS)
646 if (__builtin_expect (debug_level, 0) > 0)
648 if (req->type == GETHOSTBYADDR || req->type == GETHOSTBYADDRv6)
650 char buf[INET6_ADDRSTRLEN];
652 dbg_log ("\t%s (%s)", serv2str[req->type],
653 inet_ntop (req->type == GETHOSTBYADDR
654 ? AF_INET : AF_INET6,
655 key, buf, sizeof (buf)));
657 else
658 dbg_log ("\t%s (%s)", serv2str[req->type], (char *) key);
661 /* Is this service enabled? */
662 if (!db->enabled)
664 /* No, sent the prepared record. */
665 if (TEMP_FAILURE_RETRY (write (fd, db->disabled_iov->iov_base,
666 db->disabled_iov->iov_len))
667 != (ssize_t) db->disabled_iov->iov_len
668 && __builtin_expect (debug_level, 0) > 0)
670 /* We have problems sending the result. */
671 char buf[256];
672 dbg_log (_("cannot write result: %s"),
673 strerror_r (errno, buf, sizeof (buf)));
676 return;
679 /* Be sure we can read the data. */
680 if (__builtin_expect (pthread_rwlock_tryrdlock (&db->lock) != 0, 0))
682 ++db->head->rdlockdelayed;
683 pthread_rwlock_rdlock (&db->lock);
686 /* See whether we can handle it from the cache. */
687 struct datahead *cached;
688 cached = (struct datahead *) cache_search (req->type, key, req->key_len,
689 db, uid);
690 if (cached != NULL)
692 /* Hurray it's in the cache. */
693 if (TEMP_FAILURE_RETRY (write (fd, cached->data, cached->recsize))
694 != cached->recsize
695 && __builtin_expect (debug_level, 0) > 0)
697 /* We have problems sending the result. */
698 char buf[256];
699 dbg_log (_("cannot write result: %s"),
700 strerror_r (errno, buf, sizeof (buf)));
703 pthread_rwlock_unlock (&db->lock);
705 return;
708 pthread_rwlock_unlock (&db->lock);
710 else if (__builtin_expect (debug_level, 0) > 0)
712 if (req->type == INVALIDATE)
713 dbg_log ("\t%s (%s)", serv2str[req->type], (char *) key);
714 else
715 dbg_log ("\t%s", serv2str[req->type]);
718 /* Handle the request. */
719 switch (req->type)
721 case GETPWBYNAME:
722 addpwbyname (db, fd, req, key, uid);
723 break;
725 case GETPWBYUID:
726 addpwbyuid (db, fd, req, key, uid);
727 break;
729 case GETGRBYNAME:
730 addgrbyname (db, fd, req, key, uid);
731 break;
733 case GETGRBYGID:
734 addgrbygid (db, fd, req, key, uid);
735 break;
737 case GETHOSTBYNAME:
738 addhstbyname (db, fd, req, key, uid);
739 break;
741 case GETHOSTBYNAMEv6:
742 addhstbynamev6 (db, fd, req, key, uid);
743 break;
745 case GETHOSTBYADDR:
746 addhstbyaddr (db, fd, req, key, uid);
747 break;
749 case GETHOSTBYADDRv6:
750 addhstbyaddrv6 (db, fd, req, key, uid);
751 break;
753 case GETAI:
754 addhstai (db, fd, req, key, uid);
755 break;
757 case INITGROUPS:
758 addinitgroups (db, fd, req, key, uid);
759 break;
761 case GETSTAT:
762 case SHUTDOWN:
763 case INVALIDATE:
764 if (! secure_in_use)
766 /* Get the callers credentials. */
767 #ifdef SO_PEERCRED
768 struct ucred caller;
769 socklen_t optlen = sizeof (caller);
771 if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) < 0)
773 char buf[256];
775 dbg_log (_("error getting callers id: %s"),
776 strerror_r (errno, buf, sizeof (buf)));
777 break;
780 uid = caller.uid;
781 #else
782 /* Some systems have no SO_PEERCRED implementation. They don't
783 care about security so we don't as well. */
784 uid = 0;
785 #endif
788 /* Accept shutdown, getstat and invalidate only from root. For
789 the stat call also allow the user specified in the config file. */
790 if (req->type == GETSTAT)
792 if (uid == 0 || uid == stat_uid)
793 send_stats (fd, dbs);
795 else if (uid == 0)
797 if (req->type == INVALIDATE)
798 invalidate_cache (key);
799 else
800 termination_handler (0);
802 break;
804 case GETFDPW:
805 case GETFDGR:
806 case GETFDHST:
807 #ifdef SCM_RIGHTS
808 send_ro_fd (serv2db[req->type], key, fd);
809 #endif
810 break;
812 default:
813 /* Ignore the command, it's nothing we know. */
814 break;
819 /* Restart the process. */
820 static void
821 restart (void)
823 /* First determine the parameters. We do not use the parameters
824 passed to main() since in case nscd is started by running the
825 dynamic linker this will not work. Yes, this is not the usual
826 case but nscd is part of glibc and we occasionally do this. */
827 size_t buflen = 1024;
828 char *buf = alloca (buflen);
829 size_t readlen = 0;
830 int fd = open ("/proc/self/cmdline", O_RDONLY);
831 if (fd == -1)
833 dbg_log (_("\
834 cannot open /proc/self/cmdline: %s; disabling paranoia mode"),
835 strerror (errno));
837 paranoia = 0;
838 return;
841 while (1)
843 ssize_t n = TEMP_FAILURE_RETRY (read (fd, buf + readlen,
844 buflen - readlen));
845 if (n == -1)
847 dbg_log (_("\
848 cannot open /proc/self/cmdline: %s; disabling paranoia mode"),
849 strerror (errno));
851 close (fd);
852 paranoia = 0;
853 return;
856 readlen += n;
858 if (readlen < buflen)
859 break;
861 /* We might have to extend the buffer. */
862 size_t old_buflen = buflen;
863 char *newp = extend_alloca (buf, buflen, 2 * buflen);
864 buf = memmove (newp, buf, old_buflen);
867 close (fd);
869 /* Parse the command line. Worst case scenario: every two
870 characters form one parameter (one character plus NUL). */
871 char **argv = alloca ((readlen / 2 + 1) * sizeof (argv[0]));
872 int argc = 0;
874 char *cp = buf;
875 while (cp < buf + readlen)
877 argv[argc++] = cp;
878 cp = (char *) rawmemchr (cp, '\0') + 1;
880 argv[argc] = NULL;
882 /* Second, change back to the old user if we changed it. */
883 if (server_user != NULL)
885 if (setuid (old_uid) != 0)
887 dbg_log (_("\
888 cannot change to old UID: %s; disabling paranoia mode"),
889 strerror (errno));
891 paranoia = 0;
892 return;
895 if (setgid (old_gid) != 0)
897 dbg_log (_("\
898 cannot change to old GID: %s; disabling paranoia mode"),
899 strerror (errno));
901 setuid (server_uid);
902 paranoia = 0;
903 return;
907 /* Next change back to the old working directory. */
908 if (chdir (oldcwd) == -1)
910 dbg_log (_("\
911 cannot change to old working directory: %s; disabling paranoia mode"),
912 strerror (errno));
914 if (server_user != NULL)
916 setuid (server_uid);
917 setgid (server_gid);
919 paranoia = 0;
920 return;
923 /* Synchronize memory. */
924 for (int cnt = 0; cnt < lastdb; ++cnt)
926 /* Make sure nobody keeps using the database. */
927 dbs[cnt].head->timestamp = 0;
929 if (dbs[cnt].persistent)
930 // XXX async OK?
931 msync (dbs[cnt].head, dbs[cnt].memsize, MS_ASYNC);
934 /* The preparations are done. */
935 execv ("/proc/self/exe", argv);
937 /* If we come here, we will never be able to re-exec. */
938 dbg_log (_("re-exec failed: %s; disabling paranoia mode"),
939 strerror (errno));
941 if (server_user != NULL)
943 setuid (server_uid);
944 setgid (server_gid);
946 chdir ("/");
947 paranoia = 0;
951 /* List of file descriptors. */
952 struct fdlist
954 int fd;
955 struct fdlist *next;
957 /* Memory allocated for the list. */
958 static struct fdlist *fdlist;
959 /* List of currently ready-to-read file descriptors. */
960 static struct fdlist *readylist;
962 /* Conditional variable and mutex to signal availability of entries in
963 READYLIST. The condvar is initialized dynamically since we might
964 use a different clock depending on availability. */
965 static pthread_cond_t readylist_cond;
966 static pthread_mutex_t readylist_lock = PTHREAD_MUTEX_INITIALIZER;
968 /* The clock to use with the condvar. */
969 static clockid_t timeout_clock = CLOCK_REALTIME;
971 /* Number of threads ready to handle the READYLIST. */
972 static unsigned long int nready;
975 /* This is the main loop. It is replicated in different threads but the
976 `poll' call makes sure only one thread handles an incoming connection. */
977 static void *
978 __attribute__ ((__noreturn__))
979 nscd_run (void *p)
981 const long int my_number = (long int) p;
982 const int run_prune = my_number < lastdb && dbs[my_number].enabled;
983 struct timespec prune_ts;
984 int to = 0;
985 char buf[256];
987 if (run_prune)
989 setup_thread (&dbs[my_number]);
991 /* We are running. */
992 dbs[my_number].head->timestamp = time (NULL);
994 if (clock_gettime (timeout_clock, &prune_ts) == -1)
995 /* Should never happen. */
996 abort ();
998 /* Compute timeout time. */
999 prune_ts.tv_sec += CACHE_PRUNE_INTERVAL;
1002 /* Initial locking. */
1003 pthread_mutex_lock (&readylist_lock);
1005 /* One more thread available. */
1006 ++nready;
1008 while (1)
1010 while (readylist == NULL)
1012 if (run_prune)
1014 /* Wait, but not forever. */
1015 to = pthread_cond_timedwait (&readylist_cond, &readylist_lock,
1016 &prune_ts);
1018 /* If we were woken and there is no work to be done,
1019 just start pruning. */
1020 if (readylist == NULL && to == ETIMEDOUT)
1022 --nready;
1023 pthread_mutex_unlock (&readylist_lock);
1024 goto only_prune;
1027 else
1028 /* No need to timeout. */
1029 pthread_cond_wait (&readylist_cond, &readylist_lock);
1032 struct fdlist *it = readylist->next;
1033 if (readylist->next == readylist)
1034 /* Just one entry on the list. */
1035 readylist = NULL;
1036 else
1037 readylist->next = it->next;
1039 /* Extract the information and mark the record ready to be used
1040 again. */
1041 int fd = it->fd;
1042 it->next = NULL;
1044 /* One more thread available. */
1045 --nready;
1047 /* We are done with the list. */
1048 pthread_mutex_unlock (&readylist_lock);
1050 /* We do not want to block on a short read or so. */
1051 int fl = fcntl (fd, F_GETFL);
1052 if (fl == -1 || fcntl (fd, F_SETFL, fl | O_NONBLOCK) == -1)
1053 goto close_and_out;
1055 /* Now read the request. */
1056 request_header req;
1057 if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd, &req, sizeof (req)))
1058 != sizeof (req), 0))
1060 /* We failed to read data. Note that this also might mean we
1061 failed because we would have blocked. */
1062 if (debug_level > 0)
1063 dbg_log (_("short read while reading request: %s"),
1064 strerror_r (errno, buf, sizeof (buf)));
1065 goto close_and_out;
1068 /* Check whether this is a valid request type. */
1069 if (req.type < GETPWBYNAME || req.type >= LASTREQ)
1070 goto close_and_out;
1072 /* Some systems have no SO_PEERCRED implementation. They don't
1073 care about security so we don't as well. */
1074 uid_t uid = -1;
1075 #ifdef SO_PEERCRED
1076 pid_t pid = 0;
1078 if (secure_in_use)
1080 struct ucred caller;
1081 socklen_t optlen = sizeof (caller);
1083 if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) < 0)
1085 dbg_log (_("error getting callers id: %s"),
1086 strerror_r (errno, buf, sizeof (buf)));
1087 goto close_and_out;
1090 if (req.type < GETPWBYNAME || req.type > LASTDBREQ
1091 || serv2db[req.type]->secure)
1092 uid = caller.uid;
1094 pid = caller.pid;
1096 else if (__builtin_expect (debug_level > 0, 0))
1098 struct ucred caller;
1099 socklen_t optlen = sizeof (caller);
1101 if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) == 0)
1102 pid = caller.pid;
1104 #endif
1106 /* It should not be possible to crash the nscd with a silly
1107 request (i.e., a terribly large key). We limit the size to 1kb. */
1108 #define MAXKEYLEN 1024
1109 if (__builtin_expect (req.key_len, 1) < 0
1110 || __builtin_expect (req.key_len, 1) > MAXKEYLEN)
1112 if (debug_level > 0)
1113 dbg_log (_("key length in request too long: %d"), req.key_len);
1115 else
1117 /* Get the key. */
1118 char keybuf[MAXKEYLEN];
1120 if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd, keybuf,
1121 req.key_len))
1122 != req.key_len, 0))
1124 /* Again, this can also mean we would have blocked. */
1125 if (debug_level > 0)
1126 dbg_log (_("short read while reading request key: %s"),
1127 strerror_r (errno, buf, sizeof (buf)));
1128 goto close_and_out;
1131 if (__builtin_expect (debug_level, 0) > 0)
1133 #ifdef SO_PEERCRED
1134 if (pid != 0)
1135 dbg_log (_("\
1136 handle_request: request received (Version = %d) from PID %ld"),
1137 req.version, (long int) pid);
1138 else
1139 #endif
1140 dbg_log (_("\
1141 handle_request: request received (Version = %d)"), req.version);
1144 /* Phew, we got all the data, now process it. */
1145 handle_request (fd, &req, keybuf, uid);
1148 close_and_out:
1149 /* We are done. */
1150 close (fd);
1152 /* Check whether we should be pruning the cache. */
1153 assert (run_prune || to == 0);
1154 if (to == ETIMEDOUT)
1156 only_prune:
1157 /* The pthread_cond_timedwait() call timed out. It is time
1158 to clean up the cache. */
1159 assert (my_number < lastdb);
1160 prune_cache (&dbs[my_number],
1161 prune_ts.tv_sec + (prune_ts.tv_nsec >= 500000000));
1163 if (clock_gettime (timeout_clock, &prune_ts) == -1)
1164 /* Should never happen. */
1165 abort ();
1167 /* Compute next timeout time. */
1168 prune_ts.tv_sec += CACHE_PRUNE_INTERVAL;
1170 /* In case the list is emtpy we do not want to run the prune
1171 code right away again. */
1172 to = 0;
1175 /* Re-locking. */
1176 pthread_mutex_lock (&readylist_lock);
1178 /* One more thread available. */
1179 ++nready;
1184 static unsigned int nconns;
1186 static void
1187 fd_ready (int fd)
1189 pthread_mutex_lock (&readylist_lock);
1191 /* Find an empty entry in FDLIST. */
1192 size_t inner;
1193 for (inner = 0; inner < nconns; ++inner)
1194 if (fdlist[inner].next == NULL)
1195 break;
1196 assert (inner < nconns);
1198 fdlist[inner].fd = fd;
1200 if (readylist == NULL)
1201 readylist = fdlist[inner].next = &fdlist[inner];
1202 else
1204 fdlist[inner].next = readylist->next;
1205 readylist = readylist->next = &fdlist[inner];
1208 bool do_signal = true;
1209 if (__builtin_expect (nready == 0, 0))
1211 ++client_queued;
1212 do_signal = false;
1214 /* Try to start another thread to help out. */
1215 pthread_t th;
1216 if (nthreads < max_nthreads
1217 && pthread_create (&th, &attr, nscd_run,
1218 (void *) (long int) nthreads) == 0)
1220 /* We got another thread. */
1221 ++nthreads;
1222 /* The new thread might new a kick. */
1223 do_signal = true;
1228 pthread_mutex_unlock (&readylist_lock);
1230 /* Tell one of the worker threads there is work to do. */
1231 if (do_signal)
1232 pthread_cond_signal (&readylist_cond);
1236 /* Check whether restarting should happen. */
1237 static inline int
1238 restart_p (time_t now)
1240 return (paranoia && readylist == NULL && nready == nthreads
1241 && now >= restart_time);
1245 /* Array for times a connection was accepted. */
1246 static time_t *starttime;
1249 static void
1250 __attribute__ ((__noreturn__))
1251 main_loop_poll (void)
1253 struct pollfd *conns = (struct pollfd *) xmalloc (nconns
1254 * sizeof (conns[0]));
1256 conns[0].fd = sock;
1257 conns[0].events = POLLRDNORM;
1258 size_t nused = 1;
1259 size_t firstfree = 1;
1261 while (1)
1263 /* Wait for any event. We wait at most a couple of seconds so
1264 that we can check whether we should close any of the accepted
1265 connections since we have not received a request. */
1266 #define MAX_ACCEPT_TIMEOUT 30
1267 #define MIN_ACCEPT_TIMEOUT 5
1268 #define MAIN_THREAD_TIMEOUT \
1269 (MAX_ACCEPT_TIMEOUT * 1000 \
1270 - ((MAX_ACCEPT_TIMEOUT - MIN_ACCEPT_TIMEOUT) * 1000 * nused) / (2 * nconns))
1272 int n = poll (conns, nused, MAIN_THREAD_TIMEOUT);
1274 time_t now = time (NULL);
1276 /* If there is a descriptor ready for reading or there is a new
1277 connection, process this now. */
1278 if (n > 0)
1280 if (conns[0].revents != 0)
1282 /* We have a new incoming connection. Accept the connection. */
1283 int fd = TEMP_FAILURE_RETRY (accept (sock, NULL, NULL));
1285 /* use the descriptor if we have not reached the limit. */
1286 if (fd >= 0 && firstfree < nconns)
1288 conns[firstfree].fd = fd;
1289 conns[firstfree].events = POLLRDNORM;
1290 starttime[firstfree] = now;
1291 if (firstfree >= nused)
1292 nused = firstfree + 1;
1295 ++firstfree;
1296 while (firstfree < nused && conns[firstfree].fd != -1);
1299 --n;
1302 for (size_t cnt = 1; cnt < nused && n > 0; ++cnt)
1303 if (conns[cnt].revents != 0)
1305 fd_ready (conns[cnt].fd);
1307 /* Clean up the CONNS array. */
1308 conns[cnt].fd = -1;
1309 if (cnt < firstfree)
1310 firstfree = cnt;
1311 if (cnt == nused - 1)
1313 --nused;
1314 while (conns[nused - 1].fd == -1);
1316 --n;
1320 /* Now find entries which have timed out. */
1321 assert (nused > 0);
1323 /* We make the timeout length depend on the number of file
1324 descriptors currently used. */
1325 #define ACCEPT_TIMEOUT \
1326 (MAX_ACCEPT_TIMEOUT \
1327 - ((MAX_ACCEPT_TIMEOUT - MIN_ACCEPT_TIMEOUT) * nused) / nconns)
1328 time_t laststart = now - ACCEPT_TIMEOUT;
1330 for (size_t cnt = nused - 1; cnt > 0; --cnt)
1332 if (conns[cnt].fd != -1 && starttime[cnt] < laststart)
1334 /* Remove the entry, it timed out. */
1335 (void) close (conns[cnt].fd);
1336 conns[cnt].fd = -1;
1338 if (cnt < firstfree)
1339 firstfree = cnt;
1340 if (cnt == nused - 1)
1342 --nused;
1343 while (conns[nused - 1].fd == -1);
1347 if (restart_p (now))
1348 restart ();
1353 #ifdef HAVE_EPOLL
1354 static void
1355 main_loop_epoll (int efd)
1357 struct epoll_event ev = { 0, };
1358 int nused = 1;
1359 size_t highest = 0;
1361 /* Add the socket. */
1362 ev.events = EPOLLRDNORM;
1363 ev.data.fd = sock;
1364 if (epoll_ctl (efd, EPOLL_CTL_ADD, sock, &ev) == -1)
1365 /* We cannot use epoll. */
1366 return;
1368 while (1)
1370 struct epoll_event revs[100];
1371 # define nrevs (sizeof (revs) / sizeof (revs[0]))
1373 int n = epoll_wait (efd, revs, nrevs, MAIN_THREAD_TIMEOUT);
1375 time_t now = time (NULL);
1377 for (int cnt = 0; cnt < n; ++cnt)
1378 if (revs[cnt].data.fd == sock)
1380 /* A new connection. */
1381 int fd = TEMP_FAILURE_RETRY (accept (sock, NULL, NULL));
1383 if (fd >= 0)
1385 /* Try to add the new descriptor. */
1386 ev.data.fd = fd;
1387 if (fd >= nconns
1388 || epoll_ctl (efd, EPOLL_CTL_ADD, fd, &ev) == -1)
1389 /* The descriptor is too large or something went
1390 wrong. Close the descriptor. */
1391 close (fd);
1392 else
1394 /* Remember when we accepted the connection. */
1395 starttime[fd] = now;
1397 if (fd > highest)
1398 highest = fd;
1400 ++nused;
1404 else
1406 /* Remove the descriptor from the epoll descriptor. */
1407 struct epoll_event ev = { 0, };
1408 (void) epoll_ctl (efd, EPOLL_CTL_DEL, revs[cnt].data.fd, &ev);
1410 /* Get a worked to handle the request. */
1411 fd_ready (revs[cnt].data.fd);
1413 /* Reset the time. */
1414 starttime[revs[cnt].data.fd] = 0;
1415 if (revs[cnt].data.fd == highest)
1417 --highest;
1418 while (highest > 0 && starttime[highest] == 0);
1420 --nused;
1423 /* Now look for descriptors for accepted connections which have
1424 no reply in too long of a time. */
1425 time_t laststart = now - ACCEPT_TIMEOUT;
1426 for (int cnt = highest; cnt > STDERR_FILENO; --cnt)
1427 if (cnt != sock && starttime[cnt] != 0 && starttime[cnt] < laststart)
1429 /* We are waiting for this one for too long. Close it. */
1430 struct epoll_event ev = {0, };
1431 (void) epoll_ctl (efd, EPOLL_CTL_DEL, cnt, &ev);
1433 (void) close (cnt);
1435 starttime[cnt] = 0;
1436 if (cnt == highest)
1437 --highest;
1439 else if (cnt != sock && starttime[cnt] == 0 && cnt == highest)
1440 --highest;
1442 if (restart_p (now))
1443 restart ();
1446 #endif
1449 /* Start all the threads we want. The initial process is thread no. 1. */
1450 void
1451 start_threads (void)
1453 /* Initialize the conditional variable we will use. The only
1454 non-standard attribute we might use is the clock selection. */
1455 pthread_condattr_t condattr;
1456 pthread_condattr_init (&condattr);
1458 #if defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
1459 /* Determine whether the monotonous clock is available. */
1460 struct timespec dummy;
1461 # if _POSIX_MONOTONIC_CLOCK == 0
1462 if (sysconf (_SC_MONOTONIC_CLOCK) > 0)
1463 # endif
1465 # if defined _POSIX_CLOCK_SELECTION && _POSIX_CLOCK_SELECTION >= 0
1466 # if _POSIX_CLOCK_SELECTION == 0
1467 if (sysconf (_SC_CLOCK_SELECTION) > 0)
1468 # endif
1469 if (clock_getres (CLOCK_MONOTONIC, &dummy) == 0
1470 && pthread_condattr_setclock (&condattr, CLOCK_MONOTONIC) == 0)
1471 timeout_clock = CLOCK_MONOTONIC;
1472 # elif _POSIX_THREADS > 0
1473 if (sysconf (_SC_CLOCK_SELECTION) > 0)
1475 void *h = __libc_dlopen (LIBPTHREAD_SO);
1476 int (*condattr_setclock) (pthread_condattr_t *, __clockid_t) = NULL;
1478 if (h != NULL)
1479 condattr_setclock = __libc_dlsym (h, "pthread_condattr_setclock");
1481 if (condattr_setclock
1482 && clock_getres (CLOCK_MONOTONIC, &dummy) == 0
1483 && condattr_setclock (&condattr, CLOCK_MONOTONIC) == 0)
1484 timeout_clock = CLOCK_MONOTONIC;
1486 if (h != NULL)
1487 __libc_dlclose (h);
1489 # endif
1491 #endif
1493 pthread_cond_init (&readylist_cond, &condattr);
1494 pthread_condattr_destroy (&condattr);
1497 /* Create the attribute for the threads. They are all created
1498 detached. */
1499 pthread_attr_init (&attr);
1500 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
1501 /* Use 1MB stacks, twice as much for 64-bit architectures. */
1502 pthread_attr_setstacksize (&attr, 1024 * 1024 * (sizeof (void *) / 4));
1504 /* We allow less than LASTDB threads only for debugging. */
1505 if (debug_level == 0)
1506 nthreads = MAX (nthreads, lastdb);
1508 int nfailed = 0;
1509 for (long int i = 0; i < nthreads; ++i)
1511 pthread_t th;
1512 if (pthread_create (&th, &attr, nscd_run, (void *) (i - nfailed)) != 0)
1513 ++nfailed;
1515 if (nthreads - nfailed < lastdb)
1517 /* We could not start enough threads. */
1518 dbg_log (_("could only start %d threads; terminating"),
1519 nthreads - nfailed);
1520 exit (1);
1523 /* Determine how much room for descriptors we should initially
1524 allocate. This might need to change later if we cap the number
1525 with MAXCONN. */
1526 const long int nfds = sysconf (_SC_OPEN_MAX);
1527 #define MINCONN 32
1528 #define MAXCONN 16384
1529 if (nfds == -1 || nfds > MAXCONN)
1530 nconns = MAXCONN;
1531 else if (nfds < MINCONN)
1532 nconns = MINCONN;
1533 else
1534 nconns = nfds;
1536 /* We need memory to pass descriptors on to the worker threads. */
1537 fdlist = (struct fdlist *) xcalloc (nconns, sizeof (fdlist[0]));
1538 /* Array to keep track when connection was accepted. */
1539 starttime = (time_t *) xcalloc (nconns, sizeof (starttime[0]));
1541 /* In the main thread we execute the loop which handles incoming
1542 connections. */
1543 #ifdef HAVE_EPOLL
1544 int efd = epoll_create (100);
1545 if (efd != -1)
1547 main_loop_epoll (efd);
1548 close (efd);
1550 #endif
1552 main_loop_poll ();
1555 /* Look up the uid, gid, and supplementary groups to run nscd as. When
1556 this function is called, we are not listening on the nscd socket yet so
1557 we can just use the ordinary lookup functions without causing a lockup */
1558 static void
1559 begin_drop_privileges (void)
1561 struct passwd *pwd = getpwnam (server_user);
1563 if (pwd == NULL)
1565 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1566 error (EXIT_FAILURE, 0, _("Failed to run nscd as user '%s'"),
1567 server_user);
1570 server_uid = pwd->pw_uid;
1571 server_gid = pwd->pw_gid;
1573 /* Save the old UID/GID if we have to change back. */
1574 if (paranoia)
1576 old_uid = getuid ();
1577 old_gid = getgid ();
1580 if (getgrouplist (server_user, server_gid, NULL, &server_ngroups) == 0)
1582 /* This really must never happen. */
1583 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1584 error (EXIT_FAILURE, errno, _("initial getgrouplist failed"));
1587 server_groups = (gid_t *) xmalloc (server_ngroups * sizeof (gid_t));
1589 if (getgrouplist (server_user, server_gid, server_groups, &server_ngroups)
1590 == -1)
1592 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1593 error (EXIT_FAILURE, errno, _("getgrouplist failed"));
1598 /* Call setgroups(), setgid(), and setuid() to drop root privileges and
1599 run nscd as the user specified in the configuration file. */
1600 static void
1601 finish_drop_privileges (void)
1603 if (setgroups (server_ngroups, server_groups) == -1)
1605 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1606 error (EXIT_FAILURE, errno, _("setgroups failed"));
1609 if (setgid (server_gid) == -1)
1611 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1612 perror ("setgid");
1613 exit (1);
1616 if (setuid (server_uid) == -1)
1618 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1619 perror ("setuid");
1620 exit (1);
1624 /* Handle the HUP signal which will force a dump of the cache */
1625 void
1626 sighup_handler (int signum)
1628 /* Prune the password database */
1629 prune_cache (&dbs[pwddb], LONG_MAX);
1631 /* Prune the group database */
1632 prune_cache (&dbs[grpdb], LONG_MAX);
1634 /* Prune the host database */
1635 prune_cache (&dbs[hstdb], LONG_MAX);