Updated to fedora-glibc-2_3-20050226T0141
[glibc.git] / nscd / connections.c
blob897f4747de14b0d7fb7ddc5fcb5e2fc6e3ac0ca8
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 ssize_t
187 writeall (int fd, const void *buf, size_t len)
189 size_t n = len;
190 ssize_t ret;
193 ret = TEMP_FAILURE_RETRY (write (fd, buf, n));
194 if (ret <= 0)
195 break;
196 buf = (const char *) buf + ret;
197 n -= ret;
199 while (n > 0);
200 return ret < 0 ? ret : len - n;
204 /* Initialize database information structures. */
205 void
206 nscd_init (void)
208 /* Secure mode and unprivileged mode are incompatible */
209 if (server_user != NULL && secure_in_use)
211 dbg_log (_("Cannot run nscd in secure mode as unprivileged user"));
212 exit (1);
215 /* Look up unprivileged uid/gid/groups before we start listening on the
216 socket */
217 if (server_user != NULL)
218 begin_drop_privileges ();
220 if (nthreads == -1)
221 /* No configuration for this value, assume a default. */
222 nthreads = 2 * lastdb;
224 for (size_t cnt = 0; cnt < lastdb; ++cnt)
225 if (dbs[cnt].enabled)
227 pthread_rwlock_init (&dbs[cnt].lock, NULL);
228 pthread_mutex_init (&dbs[cnt].memlock, NULL);
230 if (dbs[cnt].persistent)
232 /* Try to open the appropriate file on disk. */
233 int fd = open (dbs[cnt].db_filename, O_RDWR);
234 if (fd != -1)
236 struct stat64 st;
237 void *mem;
238 size_t total;
239 struct database_pers_head head;
240 ssize_t n = TEMP_FAILURE_RETRY (read (fd, &head,
241 sizeof (head)));
242 if (n != sizeof (head) || fstat64 (fd, &st) != 0)
244 fail_db:
245 dbg_log (_("invalid persistent database file \"%s\": %s"),
246 dbs[cnt].db_filename, strerror (errno));
247 dbs[cnt].persistent = 0;
249 else if (head.module == 0 && head.data_size == 0)
251 /* The file has been created, but the head has not been
252 initialized yet. Remove the old file. */
253 unlink (dbs[cnt].db_filename);
255 else if (head.header_size != (int) sizeof (head))
257 dbg_log (_("invalid persistent database file \"%s\": %s"),
258 dbs[cnt].db_filename,
259 _("header size does not match"));
260 dbs[cnt].persistent = 0;
262 else if ((total = (sizeof (head)
263 + roundup (head.module * sizeof (ref_t),
264 ALIGN)
265 + head.data_size))
266 > st.st_size)
268 dbg_log (_("invalid persistent database file \"%s\": %s"),
269 dbs[cnt].db_filename,
270 _("file size does not match"));
271 dbs[cnt].persistent = 0;
273 else if ((mem = mmap (NULL, total, PROT_READ | PROT_WRITE,
274 MAP_SHARED, fd, 0)) == MAP_FAILED)
275 goto fail_db;
276 else
278 /* Success. We have the database. */
279 dbs[cnt].head = mem;
280 dbs[cnt].memsize = total;
281 dbs[cnt].data = (char *)
282 &dbs[cnt].head->array[roundup (dbs[cnt].head->module,
283 ALIGN / sizeof (ref_t))];
284 dbs[cnt].mmap_used = true;
286 if (dbs[cnt].suggested_module > head.module)
287 dbg_log (_("suggested size of table for database %s larger than the persistent database's table"),
288 dbnames[cnt]);
290 dbs[cnt].wr_fd = fd;
291 fd = -1;
292 /* We also need a read-only descriptor. */
293 if (dbs[cnt].shared)
295 dbs[cnt].ro_fd = open (dbs[cnt].db_filename, O_RDONLY);
296 if (dbs[cnt].ro_fd == -1)
297 dbg_log (_("\
298 cannot create read-only descriptor for \"%s\"; no mmap"),
299 dbs[cnt].db_filename);
302 // XXX Shall we test whether the descriptors actually
303 // XXX point to the same file?
306 /* Close the file descriptors in case something went
307 wrong in which case the variable have not been
308 assigned -1. */
309 if (fd != -1)
310 close (fd);
314 if (dbs[cnt].head == NULL)
316 /* No database loaded. Allocate the data structure,
317 possibly on disk. */
318 struct database_pers_head head;
319 size_t total = (sizeof (head)
320 + roundup (dbs[cnt].suggested_module
321 * sizeof (ref_t), ALIGN)
322 + (dbs[cnt].suggested_module
323 * DEFAULT_DATASIZE_PER_BUCKET));
325 /* Try to create the database. If we do not need a
326 persistent database create a temporary file. */
327 int fd;
328 int ro_fd = -1;
329 if (dbs[cnt].persistent)
331 fd = open (dbs[cnt].db_filename,
332 O_RDWR | O_CREAT | O_EXCL | O_TRUNC,
333 S_IRUSR | S_IWUSR);
334 if (fd != -1 && dbs[cnt].shared)
335 ro_fd = open (dbs[cnt].db_filename, O_RDONLY);
337 else
339 char fname[] = _PATH_NSCD_XYZ_DB_TMP;
340 fd = mkstemp (fname);
342 /* We do not need the file name anymore after we
343 opened another file descriptor in read-only mode. */
344 if (fd != -1)
346 if (dbs[cnt].shared)
347 ro_fd = open (fname, O_RDONLY);
349 unlink (fname);
353 if (fd == -1)
355 if (errno == EEXIST)
357 dbg_log (_("database for %s corrupted or simultaneously used; remove %s manually if necessary and restart"),
358 dbnames[cnt], dbs[cnt].db_filename);
359 // XXX Correct way to terminate?
360 exit (1);
363 if (dbs[cnt].persistent)
364 dbg_log (_("cannot create %s; no persistent database used"),
365 dbs[cnt].db_filename);
366 else
367 dbg_log (_("cannot create %s; no sharing possible"),
368 dbs[cnt].db_filename);
370 dbs[cnt].persistent = 0;
371 // XXX remember: no mmap
373 else
375 /* Tell the user if we could not create the read-only
376 descriptor. */
377 if (ro_fd == -1 && dbs[cnt].shared)
378 dbg_log (_("\
379 cannot create read-only descriptor for \"%s\"; no mmap"),
380 dbs[cnt].db_filename);
382 /* Before we create the header, initialiye the hash
383 table. So that if we get interrupted if writing
384 the header we can recognize a partially initialized
385 database. */
386 size_t ps = sysconf (_SC_PAGESIZE);
387 char tmpbuf[ps];
388 assert (~ENDREF == 0);
389 memset (tmpbuf, '\xff', ps);
391 size_t remaining = dbs[cnt].suggested_module * sizeof (ref_t);
392 off_t offset = sizeof (head);
394 size_t towrite;
395 if (offset % ps != 0)
397 towrite = MIN (remaining, ps - (offset % ps));
398 pwrite (fd, tmpbuf, towrite, offset);
399 offset += towrite;
400 remaining -= towrite;
403 while (remaining > ps)
405 pwrite (fd, tmpbuf, ps, offset);
406 offset += ps;
407 remaining -= ps;
410 if (remaining > 0)
411 pwrite (fd, tmpbuf, remaining, offset);
413 /* Create the header of the file. */
414 struct database_pers_head head =
416 .version = DB_VERSION,
417 .header_size = sizeof (head),
418 .module = dbs[cnt].suggested_module,
419 .data_size = (dbs[cnt].suggested_module
420 * DEFAULT_DATASIZE_PER_BUCKET),
421 .first_free = 0
423 void *mem;
425 if ((TEMP_FAILURE_RETRY (write (fd, &head, sizeof (head)))
426 != sizeof (head))
427 || ftruncate (fd, total) != 0
428 || (mem = mmap (NULL, total, PROT_READ | PROT_WRITE,
429 MAP_SHARED, fd, 0)) == MAP_FAILED)
431 unlink (dbs[cnt].db_filename);
432 dbg_log (_("cannot write to database file %s: %s"),
433 dbs[cnt].db_filename, strerror (errno));
434 dbs[cnt].persistent = 0;
436 else
438 /* Success. */
439 dbs[cnt].head = mem;
440 dbs[cnt].data = (char *)
441 &dbs[cnt].head->array[roundup (dbs[cnt].head->module,
442 ALIGN / sizeof (ref_t))];
443 dbs[cnt].memsize = total;
444 dbs[cnt].mmap_used = true;
446 /* Remember the descriptors. */
447 dbs[cnt].wr_fd = fd;
448 dbs[cnt].ro_fd = ro_fd;
449 fd = -1;
450 ro_fd = -1;
453 if (fd != -1)
454 close (fd);
455 if (ro_fd != -1)
456 close (ro_fd);
460 if (paranoia
461 && ((dbs[cnt].wr_fd != -1
462 && fcntl (dbs[cnt].wr_fd, F_SETFD, FD_CLOEXEC) == -1)
463 || (dbs[cnt].ro_fd != -1
464 && fcntl (dbs[cnt].ro_fd, F_SETFD, FD_CLOEXEC) == -1)))
466 dbg_log (_("\
467 cannot set socket to close on exec: %s; disabling paranoia mode"),
468 strerror (errno));
469 paranoia = 0;
472 if (dbs[cnt].head == NULL)
474 /* We do not use the persistent database. Just
475 create an in-memory data structure. */
476 assert (! dbs[cnt].persistent);
478 dbs[cnt].head = xmalloc (sizeof (struct database_pers_head)
479 + (dbs[cnt].suggested_module
480 * sizeof (ref_t)));
481 memset (dbs[cnt].head, '\0', sizeof (dbs[cnt].head));
482 assert (~ENDREF == 0);
483 memset (dbs[cnt].head->array, '\xff',
484 dbs[cnt].suggested_module * sizeof (ref_t));
485 dbs[cnt].head->module = dbs[cnt].suggested_module;
486 dbs[cnt].head->data_size = (DEFAULT_DATASIZE_PER_BUCKET
487 * dbs[cnt].head->module);
488 dbs[cnt].data = xmalloc (dbs[cnt].head->data_size);
489 dbs[cnt].head->first_free = 0;
491 dbs[cnt].shared = 0;
492 assert (dbs[cnt].ro_fd == -1);
495 if (dbs[cnt].check_file)
497 /* We need the modification date of the file. */
498 struct stat st;
500 if (stat (dbs[cnt].filename, &st) < 0)
502 /* We cannot stat() the file, disable file checking. */
503 dbg_log (_("cannot stat() file `%s': %s"),
504 dbs[cnt].filename, strerror (errno));
505 dbs[cnt].check_file = 0;
507 else
508 dbs[cnt].file_mtime = st.st_mtime;
512 /* Create the socket. */
513 sock = socket (AF_UNIX, SOCK_STREAM, 0);
514 if (sock < 0)
516 dbg_log (_("cannot open socket: %s"), strerror (errno));
517 exit (1);
519 /* Bind a name to the socket. */
520 struct sockaddr_un sock_addr;
521 sock_addr.sun_family = AF_UNIX;
522 strcpy (sock_addr.sun_path, _PATH_NSCDSOCKET);
523 if (bind (sock, (struct sockaddr *) &sock_addr, sizeof (sock_addr)) < 0)
525 dbg_log ("%s: %s", _PATH_NSCDSOCKET, strerror (errno));
526 exit (1);
529 /* We don't want to get stuck on accept. */
530 int fl = fcntl (sock, F_GETFL);
531 if (fl == -1 || fcntl (sock, F_SETFL, fl | O_NONBLOCK) == -1)
533 dbg_log (_("cannot change socket to nonblocking mode: %s"),
534 strerror (errno));
535 exit (1);
538 /* The descriptor needs to be closed on exec. */
539 if (paranoia && fcntl (sock, F_SETFD, FD_CLOEXEC) == -1)
541 dbg_log (_("cannot set socket to close on exec: %s"),
542 strerror (errno));
543 exit (1);
546 /* Set permissions for the socket. */
547 chmod (_PATH_NSCDSOCKET, DEFFILEMODE);
549 /* Set the socket up to accept connections. */
550 if (listen (sock, SOMAXCONN) < 0)
552 dbg_log (_("cannot enable socket to accept connections: %s"),
553 strerror (errno));
554 exit (1);
557 /* Change to unprivileged uid/gid/groups if specifed in config file */
558 if (server_user != NULL)
559 finish_drop_privileges ();
563 /* Close the connections. */
564 void
565 close_sockets (void)
567 close (sock);
571 static void
572 invalidate_cache (char *key)
574 dbtype number;
576 if (strcmp (key, "passwd") == 0)
577 number = pwddb;
578 else if (strcmp (key, "group") == 0)
579 number = grpdb;
580 else if (__builtin_expect (strcmp (key, "hosts"), 0) == 0)
582 number = hstdb;
584 /* Re-initialize the resolver. resolv.conf might have changed. */
585 res_init ();
587 else
588 return;
590 if (dbs[number].enabled)
591 prune_cache (&dbs[number], LONG_MAX);
595 #ifdef SCM_RIGHTS
596 static void
597 send_ro_fd (struct database_dyn *db, char *key, int fd)
599 /* If we do not have an read-only file descriptor do nothing. */
600 if (db->ro_fd == -1)
601 return;
603 /* We need to send some data along with the descriptor. */
604 struct iovec iov[1];
605 iov[0].iov_base = key;
606 iov[0].iov_len = strlen (key) + 1;
608 /* Prepare the control message to transfer the descriptor. */
609 char buf[CMSG_SPACE (sizeof (int))];
610 struct msghdr msg = { .msg_iov = iov, .msg_iovlen = 1,
611 .msg_control = buf, .msg_controllen = sizeof (buf) };
612 struct cmsghdr *cmsg = CMSG_FIRSTHDR (&msg);
614 cmsg->cmsg_level = SOL_SOCKET;
615 cmsg->cmsg_type = SCM_RIGHTS;
616 cmsg->cmsg_len = CMSG_LEN (sizeof (int));
618 *(int *) CMSG_DATA (cmsg) = db->ro_fd;
620 msg.msg_controllen = cmsg->cmsg_len;
622 /* Send the control message. We repeat when we are interrupted but
623 everything else is ignored. */
624 (void) TEMP_FAILURE_RETRY (sendmsg (fd, &msg, 0));
626 if (__builtin_expect (debug_level > 0, 0))
627 dbg_log (_("provide access to FD %d, for %s"), db->ro_fd, key);
629 #endif /* SCM_RIGHTS */
632 /* Handle new request. */
633 static void
634 handle_request (int fd, request_header *req, void *key, uid_t uid)
636 if (__builtin_expect (req->version, NSCD_VERSION) != NSCD_VERSION)
638 if (debug_level > 0)
639 dbg_log (_("\
640 cannot handle old request version %d; current version is %d"),
641 req->version, NSCD_VERSION);
642 return;
645 /* Make the SELinux check before we go on to the standard checks. We
646 need to verify that the request type is valid, since it has not
647 yet been checked at this point. */
648 if (selinux_enabled
649 && __builtin_expect (req->type, GETPWBYNAME) >= GETPWBYNAME
650 && __builtin_expect (req->type, LASTREQ) < LASTREQ
651 && nscd_request_avc_has_perm (fd, req->type) != 0)
652 return;
654 struct database_dyn *db = serv2db[req->type];
656 // XXX Clean up so that each new command need not introduce a
657 // XXX new conditional.
658 if ((__builtin_expect (req->type, GETPWBYNAME) >= GETPWBYNAME
659 && __builtin_expect (req->type, LASTDBREQ) <= LASTDBREQ)
660 || req->type == GETAI || req->type == INITGROUPS)
662 if (__builtin_expect (debug_level, 0) > 0)
664 if (req->type == GETHOSTBYADDR || req->type == GETHOSTBYADDRv6)
666 char buf[INET6_ADDRSTRLEN];
668 dbg_log ("\t%s (%s)", serv2str[req->type],
669 inet_ntop (req->type == GETHOSTBYADDR
670 ? AF_INET : AF_INET6,
671 key, buf, sizeof (buf)));
673 else
674 dbg_log ("\t%s (%s)", serv2str[req->type], (char *) key);
677 /* Is this service enabled? */
678 if (!db->enabled)
680 /* No, sent the prepared record. */
681 if (TEMP_FAILURE_RETRY (write (fd, db->disabled_iov->iov_base,
682 db->disabled_iov->iov_len))
683 != (ssize_t) db->disabled_iov->iov_len
684 && __builtin_expect (debug_level, 0) > 0)
686 /* We have problems sending the result. */
687 char buf[256];
688 dbg_log (_("cannot write result: %s"),
689 strerror_r (errno, buf, sizeof (buf)));
692 return;
695 /* Be sure we can read the data. */
696 if (__builtin_expect (pthread_rwlock_tryrdlock (&db->lock) != 0, 0))
698 ++db->head->rdlockdelayed;
699 pthread_rwlock_rdlock (&db->lock);
702 /* See whether we can handle it from the cache. */
703 struct datahead *cached;
704 cached = (struct datahead *) cache_search (req->type, key, req->key_len,
705 db, uid);
706 if (cached != NULL)
708 /* Hurray it's in the cache. */
709 if (writeall (fd, cached->data, cached->recsize)
710 != cached->recsize
711 && __builtin_expect (debug_level, 0) > 0)
713 /* We have problems sending the result. */
714 char buf[256];
715 dbg_log (_("cannot write result: %s"),
716 strerror_r (errno, buf, sizeof (buf)));
719 pthread_rwlock_unlock (&db->lock);
721 return;
724 pthread_rwlock_unlock (&db->lock);
726 else if (__builtin_expect (debug_level, 0) > 0)
728 if (req->type == INVALIDATE)
729 dbg_log ("\t%s (%s)", serv2str[req->type], (char *) key);
730 else
731 dbg_log ("\t%s", serv2str[req->type]);
734 /* Handle the request. */
735 switch (req->type)
737 case GETPWBYNAME:
738 addpwbyname (db, fd, req, key, uid);
739 break;
741 case GETPWBYUID:
742 addpwbyuid (db, fd, req, key, uid);
743 break;
745 case GETGRBYNAME:
746 addgrbyname (db, fd, req, key, uid);
747 break;
749 case GETGRBYGID:
750 addgrbygid (db, fd, req, key, uid);
751 break;
753 case GETHOSTBYNAME:
754 addhstbyname (db, fd, req, key, uid);
755 break;
757 case GETHOSTBYNAMEv6:
758 addhstbynamev6 (db, fd, req, key, uid);
759 break;
761 case GETHOSTBYADDR:
762 addhstbyaddr (db, fd, req, key, uid);
763 break;
765 case GETHOSTBYADDRv6:
766 addhstbyaddrv6 (db, fd, req, key, uid);
767 break;
769 case GETAI:
770 addhstai (db, fd, req, key, uid);
771 break;
773 case INITGROUPS:
774 addinitgroups (db, fd, req, key, uid);
775 break;
777 case GETSTAT:
778 case SHUTDOWN:
779 case INVALIDATE:
780 if (! secure_in_use)
782 /* Get the callers credentials. */
783 #ifdef SO_PEERCRED
784 struct ucred caller;
785 socklen_t optlen = sizeof (caller);
787 if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) < 0)
789 char buf[256];
791 dbg_log (_("error getting callers id: %s"),
792 strerror_r (errno, buf, sizeof (buf)));
793 break;
796 uid = caller.uid;
797 #else
798 /* Some systems have no SO_PEERCRED implementation. They don't
799 care about security so we don't as well. */
800 uid = 0;
801 #endif
804 /* Accept shutdown, getstat and invalidate only from root. For
805 the stat call also allow the user specified in the config file. */
806 if (req->type == GETSTAT)
808 if (uid == 0 || uid == stat_uid)
809 send_stats (fd, dbs);
811 else if (uid == 0)
813 if (req->type == INVALIDATE)
814 invalidate_cache (key);
815 else
816 termination_handler (0);
818 break;
820 case GETFDPW:
821 case GETFDGR:
822 case GETFDHST:
823 #ifdef SCM_RIGHTS
824 send_ro_fd (serv2db[req->type], key, fd);
825 #endif
826 break;
828 default:
829 /* Ignore the command, it's nothing we know. */
830 break;
835 /* Restart the process. */
836 static void
837 restart (void)
839 /* First determine the parameters. We do not use the parameters
840 passed to main() since in case nscd is started by running the
841 dynamic linker this will not work. Yes, this is not the usual
842 case but nscd is part of glibc and we occasionally do this. */
843 size_t buflen = 1024;
844 char *buf = alloca (buflen);
845 size_t readlen = 0;
846 int fd = open ("/proc/self/cmdline", O_RDONLY);
847 if (fd == -1)
849 dbg_log (_("\
850 cannot open /proc/self/cmdline: %s; disabling paranoia mode"),
851 strerror (errno));
853 paranoia = 0;
854 return;
857 while (1)
859 ssize_t n = TEMP_FAILURE_RETRY (read (fd, buf + readlen,
860 buflen - readlen));
861 if (n == -1)
863 dbg_log (_("\
864 cannot open /proc/self/cmdline: %s; disabling paranoia mode"),
865 strerror (errno));
867 close (fd);
868 paranoia = 0;
869 return;
872 readlen += n;
874 if (readlen < buflen)
875 break;
877 /* We might have to extend the buffer. */
878 size_t old_buflen = buflen;
879 char *newp = extend_alloca (buf, buflen, 2 * buflen);
880 buf = memmove (newp, buf, old_buflen);
883 close (fd);
885 /* Parse the command line. Worst case scenario: every two
886 characters form one parameter (one character plus NUL). */
887 char **argv = alloca ((readlen / 2 + 1) * sizeof (argv[0]));
888 int argc = 0;
890 char *cp = buf;
891 while (cp < buf + readlen)
893 argv[argc++] = cp;
894 cp = (char *) rawmemchr (cp, '\0') + 1;
896 argv[argc] = NULL;
898 /* Second, change back to the old user if we changed it. */
899 if (server_user != NULL)
901 if (setuid (old_uid) != 0)
903 dbg_log (_("\
904 cannot change to old UID: %s; disabling paranoia mode"),
905 strerror (errno));
907 paranoia = 0;
908 return;
911 if (setgid (old_gid) != 0)
913 dbg_log (_("\
914 cannot change to old GID: %s; disabling paranoia mode"),
915 strerror (errno));
917 setuid (server_uid);
918 paranoia = 0;
919 return;
923 /* Next change back to the old working directory. */
924 if (chdir (oldcwd) == -1)
926 dbg_log (_("\
927 cannot change to old working directory: %s; disabling paranoia mode"),
928 strerror (errno));
930 if (server_user != NULL)
932 setuid (server_uid);
933 setgid (server_gid);
935 paranoia = 0;
936 return;
939 /* Synchronize memory. */
940 for (int cnt = 0; cnt < lastdb; ++cnt)
942 /* Make sure nobody keeps using the database. */
943 dbs[cnt].head->timestamp = 0;
945 if (dbs[cnt].persistent)
946 // XXX async OK?
947 msync (dbs[cnt].head, dbs[cnt].memsize, MS_ASYNC);
950 /* The preparations are done. */
951 execv ("/proc/self/exe", argv);
953 /* If we come here, we will never be able to re-exec. */
954 dbg_log (_("re-exec failed: %s; disabling paranoia mode"),
955 strerror (errno));
957 if (server_user != NULL)
959 setuid (server_uid);
960 setgid (server_gid);
962 chdir ("/");
963 paranoia = 0;
967 /* List of file descriptors. */
968 struct fdlist
970 int fd;
971 struct fdlist *next;
973 /* Memory allocated for the list. */
974 static struct fdlist *fdlist;
975 /* List of currently ready-to-read file descriptors. */
976 static struct fdlist *readylist;
978 /* Conditional variable and mutex to signal availability of entries in
979 READYLIST. The condvar is initialized dynamically since we might
980 use a different clock depending on availability. */
981 static pthread_cond_t readylist_cond;
982 static pthread_mutex_t readylist_lock = PTHREAD_MUTEX_INITIALIZER;
984 /* The clock to use with the condvar. */
985 static clockid_t timeout_clock = CLOCK_REALTIME;
987 /* Number of threads ready to handle the READYLIST. */
988 static unsigned long int nready;
991 /* This is the main loop. It is replicated in different threads but the
992 `poll' call makes sure only one thread handles an incoming connection. */
993 static void *
994 __attribute__ ((__noreturn__))
995 nscd_run (void *p)
997 const long int my_number = (long int) p;
998 const int run_prune = my_number < lastdb && dbs[my_number].enabled;
999 struct timespec prune_ts;
1000 int to = 0;
1001 char buf[256];
1003 if (run_prune)
1005 setup_thread (&dbs[my_number]);
1007 /* We are running. */
1008 dbs[my_number].head->timestamp = time (NULL);
1010 if (clock_gettime (timeout_clock, &prune_ts) == -1)
1011 /* Should never happen. */
1012 abort ();
1014 /* Compute timeout time. */
1015 prune_ts.tv_sec += CACHE_PRUNE_INTERVAL;
1018 /* Initial locking. */
1019 pthread_mutex_lock (&readylist_lock);
1021 /* One more thread available. */
1022 ++nready;
1024 while (1)
1026 while (readylist == NULL)
1028 if (run_prune)
1030 /* Wait, but not forever. */
1031 to = pthread_cond_timedwait (&readylist_cond, &readylist_lock,
1032 &prune_ts);
1034 /* If we were woken and there is no work to be done,
1035 just start pruning. */
1036 if (readylist == NULL && to == ETIMEDOUT)
1038 --nready;
1039 pthread_mutex_unlock (&readylist_lock);
1040 goto only_prune;
1043 else
1044 /* No need to timeout. */
1045 pthread_cond_wait (&readylist_cond, &readylist_lock);
1048 struct fdlist *it = readylist->next;
1049 if (readylist->next == readylist)
1050 /* Just one entry on the list. */
1051 readylist = NULL;
1052 else
1053 readylist->next = it->next;
1055 /* Extract the information and mark the record ready to be used
1056 again. */
1057 int fd = it->fd;
1058 it->next = NULL;
1060 /* One more thread available. */
1061 --nready;
1063 /* We are done with the list. */
1064 pthread_mutex_unlock (&readylist_lock);
1066 /* We do not want to block on a short read or so. */
1067 int fl = fcntl (fd, F_GETFL);
1068 if (fl == -1 || fcntl (fd, F_SETFL, fl | O_NONBLOCK) == -1)
1069 goto close_and_out;
1071 /* Now read the request. */
1072 request_header req;
1073 if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd, &req, sizeof (req)))
1074 != sizeof (req), 0))
1076 /* We failed to read data. Note that this also might mean we
1077 failed because we would have blocked. */
1078 if (debug_level > 0)
1079 dbg_log (_("short read while reading request: %s"),
1080 strerror_r (errno, buf, sizeof (buf)));
1081 goto close_and_out;
1084 /* Check whether this is a valid request type. */
1085 if (req.type < GETPWBYNAME || req.type >= LASTREQ)
1086 goto close_and_out;
1088 /* Some systems have no SO_PEERCRED implementation. They don't
1089 care about security so we don't as well. */
1090 uid_t uid = -1;
1091 #ifdef SO_PEERCRED
1092 pid_t pid = 0;
1094 if (secure_in_use)
1096 struct ucred caller;
1097 socklen_t optlen = sizeof (caller);
1099 if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) < 0)
1101 dbg_log (_("error getting callers id: %s"),
1102 strerror_r (errno, buf, sizeof (buf)));
1103 goto close_and_out;
1106 if (req.type < GETPWBYNAME || req.type > LASTDBREQ
1107 || serv2db[req.type]->secure)
1108 uid = caller.uid;
1110 pid = caller.pid;
1112 else if (__builtin_expect (debug_level > 0, 0))
1114 struct ucred caller;
1115 socklen_t optlen = sizeof (caller);
1117 if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) == 0)
1118 pid = caller.pid;
1120 #endif
1122 /* It should not be possible to crash the nscd with a silly
1123 request (i.e., a terribly large key). We limit the size to 1kb. */
1124 #define MAXKEYLEN 1024
1125 if (__builtin_expect (req.key_len, 1) < 0
1126 || __builtin_expect (req.key_len, 1) > MAXKEYLEN)
1128 if (debug_level > 0)
1129 dbg_log (_("key length in request too long: %d"), req.key_len);
1131 else
1133 /* Get the key. */
1134 char keybuf[MAXKEYLEN];
1136 if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd, keybuf,
1137 req.key_len))
1138 != req.key_len, 0))
1140 /* Again, this can also mean we would have blocked. */
1141 if (debug_level > 0)
1142 dbg_log (_("short read while reading request key: %s"),
1143 strerror_r (errno, buf, sizeof (buf)));
1144 goto close_and_out;
1147 if (__builtin_expect (debug_level, 0) > 0)
1149 #ifdef SO_PEERCRED
1150 if (pid != 0)
1151 dbg_log (_("\
1152 handle_request: request received (Version = %d) from PID %ld"),
1153 req.version, (long int) pid);
1154 else
1155 #endif
1156 dbg_log (_("\
1157 handle_request: request received (Version = %d)"), req.version);
1160 /* Phew, we got all the data, now process it. */
1161 handle_request (fd, &req, keybuf, uid);
1164 close_and_out:
1165 /* We are done. */
1166 close (fd);
1168 /* Check whether we should be pruning the cache. */
1169 assert (run_prune || to == 0);
1170 if (to == ETIMEDOUT)
1172 only_prune:
1173 /* The pthread_cond_timedwait() call timed out. It is time
1174 to clean up the cache. */
1175 assert (my_number < lastdb);
1176 prune_cache (&dbs[my_number],
1177 prune_ts.tv_sec + (prune_ts.tv_nsec >= 500000000));
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_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
1475 /* Determine whether the monotonous clock is available. */
1476 struct timespec dummy;
1477 # if _POSIX_MONOTONIC_CLOCK == 0
1478 if (sysconf (_SC_MONOTONIC_CLOCK) > 0)
1479 # endif
1481 # if defined _POSIX_CLOCK_SELECTION && _POSIX_CLOCK_SELECTION >= 0
1482 # if _POSIX_CLOCK_SELECTION == 0
1483 if (sysconf (_SC_CLOCK_SELECTION) > 0)
1484 # endif
1485 if (clock_getres (CLOCK_MONOTONIC, &dummy) == 0
1486 && pthread_condattr_setclock (&condattr, CLOCK_MONOTONIC) == 0)
1487 timeout_clock = CLOCK_MONOTONIC;
1488 # elif _POSIX_THREADS > 0
1489 if (sysconf (_SC_CLOCK_SELECTION) > 0)
1491 void *h = __libc_dlopen (LIBPTHREAD_SO);
1492 int (*condattr_setclock) (pthread_condattr_t *, __clockid_t) = NULL;
1494 if (h != NULL)
1495 condattr_setclock = __libc_dlsym (h, "pthread_condattr_setclock");
1497 if (condattr_setclock
1498 && clock_getres (CLOCK_MONOTONIC, &dummy) == 0
1499 && condattr_setclock (&condattr, CLOCK_MONOTONIC) == 0)
1500 timeout_clock = CLOCK_MONOTONIC;
1502 if (h != NULL)
1503 __libc_dlclose (h);
1505 # endif
1507 #endif
1509 pthread_cond_init (&readylist_cond, &condattr);
1510 pthread_condattr_destroy (&condattr);
1513 /* Create the attribute for the threads. They are all created
1514 detached. */
1515 pthread_attr_init (&attr);
1516 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
1517 /* Use 1MB stacks, twice as much for 64-bit architectures. */
1518 pthread_attr_setstacksize (&attr, 1024 * 1024 * (sizeof (void *) / 4));
1520 /* We allow less than LASTDB threads only for debugging. */
1521 if (debug_level == 0)
1522 nthreads = MAX (nthreads, lastdb);
1524 int nfailed = 0;
1525 for (long int i = 0; i < nthreads; ++i)
1527 pthread_t th;
1528 if (pthread_create (&th, &attr, nscd_run, (void *) (i - nfailed)) != 0)
1529 ++nfailed;
1531 if (nthreads - nfailed < lastdb)
1533 /* We could not start enough threads. */
1534 dbg_log (_("could only start %d threads; terminating"),
1535 nthreads - nfailed);
1536 exit (1);
1539 /* Determine how much room for descriptors we should initially
1540 allocate. This might need to change later if we cap the number
1541 with MAXCONN. */
1542 const long int nfds = sysconf (_SC_OPEN_MAX);
1543 #define MINCONN 32
1544 #define MAXCONN 16384
1545 if (nfds == -1 || nfds > MAXCONN)
1546 nconns = MAXCONN;
1547 else if (nfds < MINCONN)
1548 nconns = MINCONN;
1549 else
1550 nconns = nfds;
1552 /* We need memory to pass descriptors on to the worker threads. */
1553 fdlist = (struct fdlist *) xcalloc (nconns, sizeof (fdlist[0]));
1554 /* Array to keep track when connection was accepted. */
1555 starttime = (time_t *) xcalloc (nconns, sizeof (starttime[0]));
1557 /* In the main thread we execute the loop which handles incoming
1558 connections. */
1559 #ifdef HAVE_EPOLL
1560 int efd = epoll_create (100);
1561 if (efd != -1)
1563 main_loop_epoll (efd);
1564 close (efd);
1566 #endif
1568 main_loop_poll ();
1571 /* Look up the uid, gid, and supplementary groups to run nscd as. When
1572 this function is called, we are not listening on the nscd socket yet so
1573 we can just use the ordinary lookup functions without causing a lockup */
1574 static void
1575 begin_drop_privileges (void)
1577 struct passwd *pwd = getpwnam (server_user);
1579 if (pwd == NULL)
1581 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1582 error (EXIT_FAILURE, 0, _("Failed to run nscd as user '%s'"),
1583 server_user);
1586 server_uid = pwd->pw_uid;
1587 server_gid = pwd->pw_gid;
1589 /* Save the old UID/GID if we have to change back. */
1590 if (paranoia)
1592 old_uid = getuid ();
1593 old_gid = getgid ();
1596 if (getgrouplist (server_user, server_gid, NULL, &server_ngroups) == 0)
1598 /* This really must never happen. */
1599 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1600 error (EXIT_FAILURE, errno, _("initial getgrouplist failed"));
1603 server_groups = (gid_t *) xmalloc (server_ngroups * sizeof (gid_t));
1605 if (getgrouplist (server_user, server_gid, server_groups, &server_ngroups)
1606 == -1)
1608 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1609 error (EXIT_FAILURE, errno, _("getgrouplist failed"));
1614 /* Call setgroups(), setgid(), and setuid() to drop root privileges and
1615 run nscd as the user specified in the configuration file. */
1616 static void
1617 finish_drop_privileges (void)
1619 if (setgroups (server_ngroups, server_groups) == -1)
1621 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1622 error (EXIT_FAILURE, errno, _("setgroups failed"));
1625 if (setgid (server_gid) == -1)
1627 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1628 perror ("setgid");
1629 exit (1);
1632 if (setuid (server_uid) == -1)
1634 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1635 perror ("setuid");
1636 exit (1);
1640 /* Handle the HUP signal which will force a dump of the cache */
1641 void
1642 sighup_handler (int signum)
1644 /* Prune the password database */
1645 prune_cache (&dbs[pwddb], LONG_MAX);
1647 /* Prune the group database */
1648 prune_cache (&dbs[grpdb], LONG_MAX);
1650 /* Prune the host database */
1651 prune_cache (&dbs[hstdb], LONG_MAX);