Updated to fedora-glibc-20050627T0850
[glibc.git] / nscd / connections.c
bloba9cdbd4cd8d1e901833debcd7b0d036302f62974
1 /* Inner loops of cache daemon.
2 Copyright (C) 1998-2003, 2004, 2005 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 (4);
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 (errno == EACCES ? 4 : 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 (errno == EACCES ? 4 : 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 #ifndef MSG_NOSIGNAL
625 # define MSG_NOSIGNAL 0
626 #endif
627 (void) TEMP_FAILURE_RETRY (sendmsg (fd, &msg, MSG_NOSIGNAL));
629 if (__builtin_expect (debug_level > 0, 0))
630 dbg_log (_("provide access to FD %d, for %s"), db->ro_fd, key);
632 #endif /* SCM_RIGHTS */
635 /* Handle new request. */
636 static void
637 handle_request (int fd, request_header *req, void *key, uid_t uid)
639 if (__builtin_expect (req->version, NSCD_VERSION) != NSCD_VERSION)
641 if (debug_level > 0)
642 dbg_log (_("\
643 cannot handle old request version %d; current version is %d"),
644 req->version, NSCD_VERSION);
645 return;
648 /* Make the SELinux check before we go on to the standard checks. We
649 need to verify that the request type is valid, since it has not
650 yet been checked at this point. */
651 if (selinux_enabled
652 && __builtin_expect (req->type, GETPWBYNAME) >= GETPWBYNAME
653 && __builtin_expect (req->type, LASTREQ) < LASTREQ
654 && nscd_request_avc_has_perm (fd, req->type) != 0)
655 return;
657 struct database_dyn *db = serv2db[req->type];
659 // XXX Clean up so that each new command need not introduce a
660 // XXX new conditional.
661 if ((__builtin_expect (req->type, GETPWBYNAME) >= GETPWBYNAME
662 && __builtin_expect (req->type, LASTDBREQ) <= LASTDBREQ)
663 || req->type == GETAI || req->type == INITGROUPS)
665 if (__builtin_expect (debug_level, 0) > 0)
667 if (req->type == GETHOSTBYADDR || req->type == GETHOSTBYADDRv6)
669 char buf[INET6_ADDRSTRLEN];
671 dbg_log ("\t%s (%s)", serv2str[req->type],
672 inet_ntop (req->type == GETHOSTBYADDR
673 ? AF_INET : AF_INET6,
674 key, buf, sizeof (buf)));
676 else
677 dbg_log ("\t%s (%s)", serv2str[req->type], (char *) key);
680 /* Is this service enabled? */
681 if (!db->enabled)
683 /* No, sent the prepared record. */
684 if (TEMP_FAILURE_RETRY (write (fd, db->disabled_iov->iov_base,
685 db->disabled_iov->iov_len))
686 != (ssize_t) db->disabled_iov->iov_len
687 && __builtin_expect (debug_level, 0) > 0)
689 /* We have problems sending the result. */
690 char buf[256];
691 dbg_log (_("cannot write result: %s"),
692 strerror_r (errno, buf, sizeof (buf)));
695 return;
698 /* Be sure we can read the data. */
699 if (__builtin_expect (pthread_rwlock_tryrdlock (&db->lock) != 0, 0))
701 ++db->head->rdlockdelayed;
702 pthread_rwlock_rdlock (&db->lock);
705 /* See whether we can handle it from the cache. */
706 struct datahead *cached;
707 cached = (struct datahead *) cache_search (req->type, key, req->key_len,
708 db, uid);
709 if (cached != NULL)
711 /* Hurray it's in the cache. */
712 if (writeall (fd, cached->data, cached->recsize)
713 != cached->recsize
714 && __builtin_expect (debug_level, 0) > 0)
716 /* We have problems sending the result. */
717 char buf[256];
718 dbg_log (_("cannot write result: %s"),
719 strerror_r (errno, buf, sizeof (buf)));
722 pthread_rwlock_unlock (&db->lock);
724 return;
727 pthread_rwlock_unlock (&db->lock);
729 else if (__builtin_expect (debug_level, 0) > 0)
731 if (req->type == INVALIDATE)
732 dbg_log ("\t%s (%s)", serv2str[req->type], (char *) key);
733 else
734 dbg_log ("\t%s", serv2str[req->type]);
737 /* Handle the request. */
738 switch (req->type)
740 case GETPWBYNAME:
741 addpwbyname (db, fd, req, key, uid);
742 break;
744 case GETPWBYUID:
745 addpwbyuid (db, fd, req, key, uid);
746 break;
748 case GETGRBYNAME:
749 addgrbyname (db, fd, req, key, uid);
750 break;
752 case GETGRBYGID:
753 addgrbygid (db, fd, req, key, uid);
754 break;
756 case GETHOSTBYNAME:
757 addhstbyname (db, fd, req, key, uid);
758 break;
760 case GETHOSTBYNAMEv6:
761 addhstbynamev6 (db, fd, req, key, uid);
762 break;
764 case GETHOSTBYADDR:
765 addhstbyaddr (db, fd, req, key, uid);
766 break;
768 case GETHOSTBYADDRv6:
769 addhstbyaddrv6 (db, fd, req, key, uid);
770 break;
772 case GETAI:
773 addhstai (db, fd, req, key, uid);
774 break;
776 case INITGROUPS:
777 addinitgroups (db, fd, req, key, uid);
778 break;
780 case GETSTAT:
781 case SHUTDOWN:
782 case INVALIDATE:
783 if (! secure_in_use)
785 /* Get the callers credentials. */
786 #ifdef SO_PEERCRED
787 struct ucred caller;
788 socklen_t optlen = sizeof (caller);
790 if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) < 0)
792 char buf[256];
794 dbg_log (_("error getting callers id: %s"),
795 strerror_r (errno, buf, sizeof (buf)));
796 break;
799 uid = caller.uid;
800 #else
801 /* Some systems have no SO_PEERCRED implementation. They don't
802 care about security so we don't as well. */
803 uid = 0;
804 #endif
807 /* Accept shutdown, getstat and invalidate only from root. For
808 the stat call also allow the user specified in the config file. */
809 if (req->type == GETSTAT)
811 if (uid == 0 || uid == stat_uid)
812 send_stats (fd, dbs);
814 else if (uid == 0)
816 if (req->type == INVALIDATE)
817 invalidate_cache (key);
818 else
819 termination_handler (0);
821 break;
823 case GETFDPW:
824 case GETFDGR:
825 case GETFDHST:
826 #ifdef SCM_RIGHTS
827 send_ro_fd (serv2db[req->type], key, fd);
828 #endif
829 break;
831 default:
832 /* Ignore the command, it's nothing we know. */
833 break;
838 /* Restart the process. */
839 static void
840 restart (void)
842 /* First determine the parameters. We do not use the parameters
843 passed to main() since in case nscd is started by running the
844 dynamic linker this will not work. Yes, this is not the usual
845 case but nscd is part of glibc and we occasionally do this. */
846 size_t buflen = 1024;
847 char *buf = alloca (buflen);
848 size_t readlen = 0;
849 int fd = open ("/proc/self/cmdline", O_RDONLY);
850 if (fd == -1)
852 dbg_log (_("\
853 cannot open /proc/self/cmdline: %s; disabling paranoia mode"),
854 strerror (errno));
856 paranoia = 0;
857 return;
860 while (1)
862 ssize_t n = TEMP_FAILURE_RETRY (read (fd, buf + readlen,
863 buflen - readlen));
864 if (n == -1)
866 dbg_log (_("\
867 cannot open /proc/self/cmdline: %s; disabling paranoia mode"),
868 strerror (errno));
870 close (fd);
871 paranoia = 0;
872 return;
875 readlen += n;
877 if (readlen < buflen)
878 break;
880 /* We might have to extend the buffer. */
881 size_t old_buflen = buflen;
882 char *newp = extend_alloca (buf, buflen, 2 * buflen);
883 buf = memmove (newp, buf, old_buflen);
886 close (fd);
888 /* Parse the command line. Worst case scenario: every two
889 characters form one parameter (one character plus NUL). */
890 char **argv = alloca ((readlen / 2 + 1) * sizeof (argv[0]));
891 int argc = 0;
893 char *cp = buf;
894 while (cp < buf + readlen)
896 argv[argc++] = cp;
897 cp = (char *) rawmemchr (cp, '\0') + 1;
899 argv[argc] = NULL;
901 /* Second, change back to the old user if we changed it. */
902 if (server_user != NULL)
904 if (setuid (old_uid) != 0)
906 dbg_log (_("\
907 cannot change to old UID: %s; disabling paranoia mode"),
908 strerror (errno));
910 paranoia = 0;
911 return;
914 if (setgid (old_gid) != 0)
916 dbg_log (_("\
917 cannot change to old GID: %s; disabling paranoia mode"),
918 strerror (errno));
920 setuid (server_uid);
921 paranoia = 0;
922 return;
926 /* Next change back to the old working directory. */
927 if (chdir (oldcwd) == -1)
929 dbg_log (_("\
930 cannot change to old working directory: %s; disabling paranoia mode"),
931 strerror (errno));
933 if (server_user != NULL)
935 setuid (server_uid);
936 setgid (server_gid);
938 paranoia = 0;
939 return;
942 /* Synchronize memory. */
943 for (int cnt = 0; cnt < lastdb; ++cnt)
945 /* Make sure nobody keeps using the database. */
946 dbs[cnt].head->timestamp = 0;
948 if (dbs[cnt].persistent)
949 // XXX async OK?
950 msync (dbs[cnt].head, dbs[cnt].memsize, MS_ASYNC);
953 /* The preparations are done. */
954 execv ("/proc/self/exe", argv);
956 /* If we come here, we will never be able to re-exec. */
957 dbg_log (_("re-exec failed: %s; disabling paranoia mode"),
958 strerror (errno));
960 if (server_user != NULL)
962 setuid (server_uid);
963 setgid (server_gid);
965 chdir ("/");
966 paranoia = 0;
970 /* List of file descriptors. */
971 struct fdlist
973 int fd;
974 struct fdlist *next;
976 /* Memory allocated for the list. */
977 static struct fdlist *fdlist;
978 /* List of currently ready-to-read file descriptors. */
979 static struct fdlist *readylist;
981 /* Conditional variable and mutex to signal availability of entries in
982 READYLIST. The condvar is initialized dynamically since we might
983 use a different clock depending on availability. */
984 static pthread_cond_t readylist_cond;
985 static pthread_mutex_t readylist_lock = PTHREAD_MUTEX_INITIALIZER;
987 /* The clock to use with the condvar. */
988 static clockid_t timeout_clock = CLOCK_REALTIME;
990 /* Number of threads ready to handle the READYLIST. */
991 static unsigned long int nready;
994 /* This is the main loop. It is replicated in different threads but the
995 `poll' call makes sure only one thread handles an incoming connection. */
996 static void *
997 __attribute__ ((__noreturn__))
998 nscd_run (void *p)
1000 const long int my_number = (long int) p;
1001 const int run_prune = my_number < lastdb && dbs[my_number].enabled;
1002 struct timespec prune_ts;
1003 int to = 0;
1004 char buf[256];
1006 if (run_prune)
1008 setup_thread (&dbs[my_number]);
1010 /* We are running. */
1011 dbs[my_number].head->timestamp = time (NULL);
1013 if (clock_gettime (timeout_clock, &prune_ts) == -1)
1014 /* Should never happen. */
1015 abort ();
1017 /* Compute timeout time. */
1018 prune_ts.tv_sec += CACHE_PRUNE_INTERVAL;
1021 /* Initial locking. */
1022 pthread_mutex_lock (&readylist_lock);
1024 /* One more thread available. */
1025 ++nready;
1027 while (1)
1029 while (readylist == NULL)
1031 if (run_prune)
1033 /* Wait, but not forever. */
1034 to = pthread_cond_timedwait (&readylist_cond, &readylist_lock,
1035 &prune_ts);
1037 /* If we were woken and there is no work to be done,
1038 just start pruning. */
1039 if (readylist == NULL && to == ETIMEDOUT)
1041 --nready;
1042 pthread_mutex_unlock (&readylist_lock);
1043 goto only_prune;
1046 else
1047 /* No need to timeout. */
1048 pthread_cond_wait (&readylist_cond, &readylist_lock);
1051 struct fdlist *it = readylist->next;
1052 if (readylist->next == readylist)
1053 /* Just one entry on the list. */
1054 readylist = NULL;
1055 else
1056 readylist->next = it->next;
1058 /* Extract the information and mark the record ready to be used
1059 again. */
1060 int fd = it->fd;
1061 it->next = NULL;
1063 /* One more thread available. */
1064 --nready;
1066 /* We are done with the list. */
1067 pthread_mutex_unlock (&readylist_lock);
1069 /* We do not want to block on a short read or so. */
1070 int fl = fcntl (fd, F_GETFL);
1071 if (fl == -1 || fcntl (fd, F_SETFL, fl | O_NONBLOCK) == -1)
1072 goto close_and_out;
1074 /* Now read the request. */
1075 request_header req;
1076 if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd, &req, sizeof (req)))
1077 != sizeof (req), 0))
1079 /* We failed to read data. Note that this also might mean we
1080 failed because we would have blocked. */
1081 if (debug_level > 0)
1082 dbg_log (_("short read while reading request: %s"),
1083 strerror_r (errno, buf, sizeof (buf)));
1084 goto close_and_out;
1087 /* Check whether this is a valid request type. */
1088 if (req.type < GETPWBYNAME || req.type >= LASTREQ)
1089 goto close_and_out;
1091 /* Some systems have no SO_PEERCRED implementation. They don't
1092 care about security so we don't as well. */
1093 uid_t uid = -1;
1094 #ifdef SO_PEERCRED
1095 pid_t pid = 0;
1097 if (secure_in_use)
1099 struct ucred caller;
1100 socklen_t optlen = sizeof (caller);
1102 if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) < 0)
1104 dbg_log (_("error getting callers id: %s"),
1105 strerror_r (errno, buf, sizeof (buf)));
1106 goto close_and_out;
1109 if (req.type < GETPWBYNAME || req.type > LASTDBREQ
1110 || serv2db[req.type]->secure)
1111 uid = caller.uid;
1113 pid = caller.pid;
1115 else if (__builtin_expect (debug_level > 0, 0))
1117 struct ucred caller;
1118 socklen_t optlen = sizeof (caller);
1120 if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) == 0)
1121 pid = caller.pid;
1123 #endif
1125 /* It should not be possible to crash the nscd with a silly
1126 request (i.e., a terribly large key). We limit the size to 1kb. */
1127 #define MAXKEYLEN 1024
1128 if (__builtin_expect (req.key_len, 1) < 0
1129 || __builtin_expect (req.key_len, 1) > MAXKEYLEN)
1131 if (debug_level > 0)
1132 dbg_log (_("key length in request too long: %d"), req.key_len);
1134 else
1136 /* Get the key. */
1137 char keybuf[MAXKEYLEN];
1139 if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd, keybuf,
1140 req.key_len))
1141 != req.key_len, 0))
1143 /* Again, this can also mean we would have blocked. */
1144 if (debug_level > 0)
1145 dbg_log (_("short read while reading request key: %s"),
1146 strerror_r (errno, buf, sizeof (buf)));
1147 goto close_and_out;
1150 if (__builtin_expect (debug_level, 0) > 0)
1152 #ifdef SO_PEERCRED
1153 if (pid != 0)
1154 dbg_log (_("\
1155 handle_request: request received (Version = %d) from PID %ld"),
1156 req.version, (long int) pid);
1157 else
1158 #endif
1159 dbg_log (_("\
1160 handle_request: request received (Version = %d)"), req.version);
1163 /* Phew, we got all the data, now process it. */
1164 handle_request (fd, &req, keybuf, uid);
1167 close_and_out:
1168 /* We are done. */
1169 close (fd);
1171 /* Check whether we should be pruning the cache. */
1172 assert (run_prune || to == 0);
1173 if (to == ETIMEDOUT)
1175 only_prune:
1176 /* The pthread_cond_timedwait() call timed out. It is time
1177 to clean up the cache. */
1178 assert (my_number < lastdb);
1179 prune_cache (&dbs[my_number], time (NULL));
1181 if (clock_gettime (timeout_clock, &prune_ts) == -1)
1182 /* Should never happen. */
1183 abort ();
1185 /* Compute next timeout time. */
1186 prune_ts.tv_sec += CACHE_PRUNE_INTERVAL;
1188 /* In case the list is emtpy we do not want to run the prune
1189 code right away again. */
1190 to = 0;
1193 /* Re-locking. */
1194 pthread_mutex_lock (&readylist_lock);
1196 /* One more thread available. */
1197 ++nready;
1202 static unsigned int nconns;
1204 static void
1205 fd_ready (int fd)
1207 pthread_mutex_lock (&readylist_lock);
1209 /* Find an empty entry in FDLIST. */
1210 size_t inner;
1211 for (inner = 0; inner < nconns; ++inner)
1212 if (fdlist[inner].next == NULL)
1213 break;
1214 assert (inner < nconns);
1216 fdlist[inner].fd = fd;
1218 if (readylist == NULL)
1219 readylist = fdlist[inner].next = &fdlist[inner];
1220 else
1222 fdlist[inner].next = readylist->next;
1223 readylist = readylist->next = &fdlist[inner];
1226 bool do_signal = true;
1227 if (__builtin_expect (nready == 0, 0))
1229 ++client_queued;
1230 do_signal = false;
1232 /* Try to start another thread to help out. */
1233 pthread_t th;
1234 if (nthreads < max_nthreads
1235 && pthread_create (&th, &attr, nscd_run,
1236 (void *) (long int) nthreads) == 0)
1238 /* We got another thread. */
1239 ++nthreads;
1240 /* The new thread might new a kick. */
1241 do_signal = true;
1246 pthread_mutex_unlock (&readylist_lock);
1248 /* Tell one of the worker threads there is work to do. */
1249 if (do_signal)
1250 pthread_cond_signal (&readylist_cond);
1254 /* Check whether restarting should happen. */
1255 static inline int
1256 restart_p (time_t now)
1258 return (paranoia && readylist == NULL && nready == nthreads
1259 && now >= restart_time);
1263 /* Array for times a connection was accepted. */
1264 static time_t *starttime;
1267 static void
1268 __attribute__ ((__noreturn__))
1269 main_loop_poll (void)
1271 struct pollfd *conns = (struct pollfd *) xmalloc (nconns
1272 * sizeof (conns[0]));
1274 conns[0].fd = sock;
1275 conns[0].events = POLLRDNORM;
1276 size_t nused = 1;
1277 size_t firstfree = 1;
1279 while (1)
1281 /* Wait for any event. We wait at most a couple of seconds so
1282 that we can check whether we should close any of the accepted
1283 connections since we have not received a request. */
1284 #define MAX_ACCEPT_TIMEOUT 30
1285 #define MIN_ACCEPT_TIMEOUT 5
1286 #define MAIN_THREAD_TIMEOUT \
1287 (MAX_ACCEPT_TIMEOUT * 1000 \
1288 - ((MAX_ACCEPT_TIMEOUT - MIN_ACCEPT_TIMEOUT) * 1000 * nused) / (2 * nconns))
1290 int n = poll (conns, nused, MAIN_THREAD_TIMEOUT);
1292 time_t now = time (NULL);
1294 /* If there is a descriptor ready for reading or there is a new
1295 connection, process this now. */
1296 if (n > 0)
1298 if (conns[0].revents != 0)
1300 /* We have a new incoming connection. Accept the connection. */
1301 int fd = TEMP_FAILURE_RETRY (accept (sock, NULL, NULL));
1303 /* use the descriptor if we have not reached the limit. */
1304 if (fd >= 0 && firstfree < nconns)
1306 conns[firstfree].fd = fd;
1307 conns[firstfree].events = POLLRDNORM;
1308 starttime[firstfree] = now;
1309 if (firstfree >= nused)
1310 nused = firstfree + 1;
1313 ++firstfree;
1314 while (firstfree < nused && conns[firstfree].fd != -1);
1317 --n;
1320 for (size_t cnt = 1; cnt < nused && n > 0; ++cnt)
1321 if (conns[cnt].revents != 0)
1323 fd_ready (conns[cnt].fd);
1325 /* Clean up the CONNS array. */
1326 conns[cnt].fd = -1;
1327 if (cnt < firstfree)
1328 firstfree = cnt;
1329 if (cnt == nused - 1)
1331 --nused;
1332 while (conns[nused - 1].fd == -1);
1334 --n;
1338 /* Now find entries which have timed out. */
1339 assert (nused > 0);
1341 /* We make the timeout length depend on the number of file
1342 descriptors currently used. */
1343 #define ACCEPT_TIMEOUT \
1344 (MAX_ACCEPT_TIMEOUT \
1345 - ((MAX_ACCEPT_TIMEOUT - MIN_ACCEPT_TIMEOUT) * nused) / nconns)
1346 time_t laststart = now - ACCEPT_TIMEOUT;
1348 for (size_t cnt = nused - 1; cnt > 0; --cnt)
1350 if (conns[cnt].fd != -1 && starttime[cnt] < laststart)
1352 /* Remove the entry, it timed out. */
1353 (void) close (conns[cnt].fd);
1354 conns[cnt].fd = -1;
1356 if (cnt < firstfree)
1357 firstfree = cnt;
1358 if (cnt == nused - 1)
1360 --nused;
1361 while (conns[nused - 1].fd == -1);
1365 if (restart_p (now))
1366 restart ();
1371 #ifdef HAVE_EPOLL
1372 static void
1373 main_loop_epoll (int efd)
1375 struct epoll_event ev = { 0, };
1376 int nused = 1;
1377 size_t highest = 0;
1379 /* Add the socket. */
1380 ev.events = EPOLLRDNORM;
1381 ev.data.fd = sock;
1382 if (epoll_ctl (efd, EPOLL_CTL_ADD, sock, &ev) == -1)
1383 /* We cannot use epoll. */
1384 return;
1386 while (1)
1388 struct epoll_event revs[100];
1389 # define nrevs (sizeof (revs) / sizeof (revs[0]))
1391 int n = epoll_wait (efd, revs, nrevs, MAIN_THREAD_TIMEOUT);
1393 time_t now = time (NULL);
1395 for (int cnt = 0; cnt < n; ++cnt)
1396 if (revs[cnt].data.fd == sock)
1398 /* A new connection. */
1399 int fd = TEMP_FAILURE_RETRY (accept (sock, NULL, NULL));
1401 if (fd >= 0)
1403 /* Try to add the new descriptor. */
1404 ev.data.fd = fd;
1405 if (fd >= nconns
1406 || epoll_ctl (efd, EPOLL_CTL_ADD, fd, &ev) == -1)
1407 /* The descriptor is too large or something went
1408 wrong. Close the descriptor. */
1409 close (fd);
1410 else
1412 /* Remember when we accepted the connection. */
1413 starttime[fd] = now;
1415 if (fd > highest)
1416 highest = fd;
1418 ++nused;
1422 else
1424 /* Remove the descriptor from the epoll descriptor. */
1425 struct epoll_event ev = { 0, };
1426 (void) epoll_ctl (efd, EPOLL_CTL_DEL, revs[cnt].data.fd, &ev);
1428 /* Get a worked to handle the request. */
1429 fd_ready (revs[cnt].data.fd);
1431 /* Reset the time. */
1432 starttime[revs[cnt].data.fd] = 0;
1433 if (revs[cnt].data.fd == highest)
1435 --highest;
1436 while (highest > 0 && starttime[highest] == 0);
1438 --nused;
1441 /* Now look for descriptors for accepted connections which have
1442 no reply in too long of a time. */
1443 time_t laststart = now - ACCEPT_TIMEOUT;
1444 for (int cnt = highest; cnt > STDERR_FILENO; --cnt)
1445 if (cnt != sock && starttime[cnt] != 0 && starttime[cnt] < laststart)
1447 /* We are waiting for this one for too long. Close it. */
1448 struct epoll_event ev = {0, };
1449 (void) epoll_ctl (efd, EPOLL_CTL_DEL, cnt, &ev);
1451 (void) close (cnt);
1453 starttime[cnt] = 0;
1454 if (cnt == highest)
1455 --highest;
1457 else if (cnt != sock && starttime[cnt] == 0 && cnt == highest)
1458 --highest;
1460 if (restart_p (now))
1461 restart ();
1464 #endif
1467 /* Start all the threads we want. The initial process is thread no. 1. */
1468 void
1469 start_threads (void)
1471 /* Initialize the conditional variable we will use. The only
1472 non-standard attribute we might use is the clock selection. */
1473 pthread_condattr_t condattr;
1474 pthread_condattr_init (&condattr);
1476 #if defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
1477 /* Determine whether the monotonous clock is available. */
1478 struct timespec dummy;
1479 # if _POSIX_MONOTONIC_CLOCK == 0
1480 if (sysconf (_SC_MONOTONIC_CLOCK) > 0)
1481 # endif
1483 # if defined _POSIX_CLOCK_SELECTION && _POSIX_CLOCK_SELECTION >= 0
1484 # if _POSIX_CLOCK_SELECTION == 0
1485 if (sysconf (_SC_CLOCK_SELECTION) > 0)
1486 # endif
1487 if (clock_getres (CLOCK_MONOTONIC, &dummy) == 0
1488 && pthread_condattr_setclock (&condattr, CLOCK_MONOTONIC) == 0)
1489 timeout_clock = CLOCK_MONOTONIC;
1490 # elif _POSIX_THREADS > 0
1491 if (sysconf (_SC_CLOCK_SELECTION) > 0)
1493 void *h = __libc_dlopen (LIBPTHREAD_SO);
1494 int (*condattr_setclock) (pthread_condattr_t *, __clockid_t) = NULL;
1496 if (h != NULL)
1497 condattr_setclock = __libc_dlsym (h, "pthread_condattr_setclock");
1499 if (condattr_setclock
1500 && clock_getres (CLOCK_MONOTONIC, &dummy) == 0
1501 && condattr_setclock (&condattr, CLOCK_MONOTONIC) == 0)
1502 timeout_clock = CLOCK_MONOTONIC;
1504 if (h != NULL)
1505 __libc_dlclose (h);
1507 # endif
1509 #endif
1511 pthread_cond_init (&readylist_cond, &condattr);
1512 pthread_condattr_destroy (&condattr);
1515 /* Create the attribute for the threads. They are all created
1516 detached. */
1517 pthread_attr_init (&attr);
1518 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
1519 /* Use 1MB stacks, twice as much for 64-bit architectures. */
1520 pthread_attr_setstacksize (&attr, 1024 * 1024 * (sizeof (void *) / 4));
1522 /* We allow less than LASTDB threads only for debugging. */
1523 if (debug_level == 0)
1524 nthreads = MAX (nthreads, lastdb);
1526 int nfailed = 0;
1527 for (long int i = 0; i < nthreads; ++i)
1529 pthread_t th;
1530 if (pthread_create (&th, &attr, nscd_run, (void *) (i - nfailed)) != 0)
1531 ++nfailed;
1533 if (nthreads - nfailed < lastdb)
1535 /* We could not start enough threads. */
1536 dbg_log (_("could only start %d threads; terminating"),
1537 nthreads - nfailed);
1538 exit (1);
1541 /* Determine how much room for descriptors we should initially
1542 allocate. This might need to change later if we cap the number
1543 with MAXCONN. */
1544 const long int nfds = sysconf (_SC_OPEN_MAX);
1545 #define MINCONN 32
1546 #define MAXCONN 16384
1547 if (nfds == -1 || nfds > MAXCONN)
1548 nconns = MAXCONN;
1549 else if (nfds < MINCONN)
1550 nconns = MINCONN;
1551 else
1552 nconns = nfds;
1554 /* We need memory to pass descriptors on to the worker threads. */
1555 fdlist = (struct fdlist *) xcalloc (nconns, sizeof (fdlist[0]));
1556 /* Array to keep track when connection was accepted. */
1557 starttime = (time_t *) xcalloc (nconns, sizeof (starttime[0]));
1559 /* In the main thread we execute the loop which handles incoming
1560 connections. */
1561 #ifdef HAVE_EPOLL
1562 int efd = epoll_create (100);
1563 if (efd != -1)
1565 main_loop_epoll (efd);
1566 close (efd);
1568 #endif
1570 main_loop_poll ();
1573 /* Look up the uid, gid, and supplementary groups to run nscd as. When
1574 this function is called, we are not listening on the nscd socket yet so
1575 we can just use the ordinary lookup functions without causing a lockup */
1576 static void
1577 begin_drop_privileges (void)
1579 struct passwd *pwd = getpwnam (server_user);
1581 if (pwd == NULL)
1583 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1584 error (EXIT_FAILURE, 0, _("Failed to run nscd as user '%s'"),
1585 server_user);
1588 server_uid = pwd->pw_uid;
1589 server_gid = pwd->pw_gid;
1591 /* Save the old UID/GID if we have to change back. */
1592 if (paranoia)
1594 old_uid = getuid ();
1595 old_gid = getgid ();
1598 if (getgrouplist (server_user, server_gid, NULL, &server_ngroups) == 0)
1600 /* This really must never happen. */
1601 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1602 error (EXIT_FAILURE, errno, _("initial getgrouplist failed"));
1605 server_groups = (gid_t *) xmalloc (server_ngroups * sizeof (gid_t));
1607 if (getgrouplist (server_user, server_gid, server_groups, &server_ngroups)
1608 == -1)
1610 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1611 error (EXIT_FAILURE, errno, _("getgrouplist failed"));
1616 /* Call setgroups(), setgid(), and setuid() to drop root privileges and
1617 run nscd as the user specified in the configuration file. */
1618 static void
1619 finish_drop_privileges (void)
1621 if (setgroups (server_ngroups, server_groups) == -1)
1623 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1624 error (EXIT_FAILURE, errno, _("setgroups failed"));
1627 if (setgid (server_gid) == -1)
1629 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1630 perror ("setgid");
1631 exit (4);
1634 if (setuid (server_uid) == -1)
1636 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1637 perror ("setuid");
1638 exit (4);
1642 /* Handle the HUP signal which will force a dump of the cache */
1643 void
1644 sighup_handler (int signum)
1646 /* Prune the password database */
1647 prune_cache (&dbs[pwddb], LONG_MAX);
1649 /* Prune the group database */
1650 prune_cache (&dbs[grpdb], LONG_MAX);
1652 /* Prune the host database */
1653 prune_cache (&dbs[hstdb], LONG_MAX);