Updated to fedora-glibc-2_3-20050718T0804
[glibc.git] / nscd / connections.c
blobb4de1df9eecb36f227ba5b4207c1447169105ed6
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 union
611 struct cmsghdr hdr;
612 char bytes[CMSG_SPACE (sizeof (int))];
613 } buf;
614 struct msghdr msg = { .msg_iov = iov, .msg_iovlen = 1,
615 .msg_control = buf.bytes,
616 .msg_controllen = sizeof (buf) };
617 struct cmsghdr *cmsg = CMSG_FIRSTHDR (&msg);
619 cmsg->cmsg_level = SOL_SOCKET;
620 cmsg->cmsg_type = SCM_RIGHTS;
621 cmsg->cmsg_len = CMSG_LEN (sizeof (int));
623 *(int *) CMSG_DATA (cmsg) = db->ro_fd;
625 msg.msg_controllen = cmsg->cmsg_len;
627 /* Send the control message. We repeat when we are interrupted but
628 everything else is ignored. */
629 #ifndef MSG_NOSIGNAL
630 # define MSG_NOSIGNAL 0
631 #endif
632 (void) TEMP_FAILURE_RETRY (sendmsg (fd, &msg, MSG_NOSIGNAL));
634 if (__builtin_expect (debug_level > 0, 0))
635 dbg_log (_("provide access to FD %d, for %s"), db->ro_fd, key);
637 #endif /* SCM_RIGHTS */
640 /* Handle new request. */
641 static void
642 handle_request (int fd, request_header *req, void *key, uid_t uid)
644 if (__builtin_expect (req->version, NSCD_VERSION) != NSCD_VERSION)
646 if (debug_level > 0)
647 dbg_log (_("\
648 cannot handle old request version %d; current version is %d"),
649 req->version, NSCD_VERSION);
650 return;
653 /* Make the SELinux check before we go on to the standard checks. We
654 need to verify that the request type is valid, since it has not
655 yet been checked at this point. */
656 if (selinux_enabled
657 && __builtin_expect (req->type, GETPWBYNAME) >= GETPWBYNAME
658 && __builtin_expect (req->type, LASTREQ) < LASTREQ
659 && nscd_request_avc_has_perm (fd, req->type) != 0)
660 return;
662 struct database_dyn *db = serv2db[req->type];
664 // XXX Clean up so that each new command need not introduce a
665 // XXX new conditional.
666 if ((__builtin_expect (req->type, GETPWBYNAME) >= GETPWBYNAME
667 && __builtin_expect (req->type, LASTDBREQ) <= LASTDBREQ)
668 || req->type == GETAI || req->type == INITGROUPS)
670 if (__builtin_expect (debug_level, 0) > 0)
672 if (req->type == GETHOSTBYADDR || req->type == GETHOSTBYADDRv6)
674 char buf[INET6_ADDRSTRLEN];
676 dbg_log ("\t%s (%s)", serv2str[req->type],
677 inet_ntop (req->type == GETHOSTBYADDR
678 ? AF_INET : AF_INET6,
679 key, buf, sizeof (buf)));
681 else
682 dbg_log ("\t%s (%s)", serv2str[req->type], (char *) key);
685 /* Is this service enabled? */
686 if (!db->enabled)
688 /* No, sent the prepared record. */
689 if (TEMP_FAILURE_RETRY (write (fd, db->disabled_iov->iov_base,
690 db->disabled_iov->iov_len))
691 != (ssize_t) db->disabled_iov->iov_len
692 && __builtin_expect (debug_level, 0) > 0)
694 /* We have problems sending the result. */
695 char buf[256];
696 dbg_log (_("cannot write result: %s"),
697 strerror_r (errno, buf, sizeof (buf)));
700 return;
703 /* Be sure we can read the data. */
704 if (__builtin_expect (pthread_rwlock_tryrdlock (&db->lock) != 0, 0))
706 ++db->head->rdlockdelayed;
707 pthread_rwlock_rdlock (&db->lock);
710 /* See whether we can handle it from the cache. */
711 struct datahead *cached;
712 cached = (struct datahead *) cache_search (req->type, key, req->key_len,
713 db, uid);
714 if (cached != NULL)
716 /* Hurray it's in the cache. */
717 if (writeall (fd, cached->data, cached->recsize)
718 != cached->recsize
719 && __builtin_expect (debug_level, 0) > 0)
721 /* We have problems sending the result. */
722 char buf[256];
723 dbg_log (_("cannot write result: %s"),
724 strerror_r (errno, buf, sizeof (buf)));
727 pthread_rwlock_unlock (&db->lock);
729 return;
732 pthread_rwlock_unlock (&db->lock);
734 else if (__builtin_expect (debug_level, 0) > 0)
736 if (req->type == INVALIDATE)
737 dbg_log ("\t%s (%s)", serv2str[req->type], (char *) key);
738 else
739 dbg_log ("\t%s", serv2str[req->type]);
742 /* Handle the request. */
743 switch (req->type)
745 case GETPWBYNAME:
746 addpwbyname (db, fd, req, key, uid);
747 break;
749 case GETPWBYUID:
750 addpwbyuid (db, fd, req, key, uid);
751 break;
753 case GETGRBYNAME:
754 addgrbyname (db, fd, req, key, uid);
755 break;
757 case GETGRBYGID:
758 addgrbygid (db, fd, req, key, uid);
759 break;
761 case GETHOSTBYNAME:
762 addhstbyname (db, fd, req, key, uid);
763 break;
765 case GETHOSTBYNAMEv6:
766 addhstbynamev6 (db, fd, req, key, uid);
767 break;
769 case GETHOSTBYADDR:
770 addhstbyaddr (db, fd, req, key, uid);
771 break;
773 case GETHOSTBYADDRv6:
774 addhstbyaddrv6 (db, fd, req, key, uid);
775 break;
777 case GETAI:
778 addhstai (db, fd, req, key, uid);
779 break;
781 case INITGROUPS:
782 addinitgroups (db, fd, req, key, uid);
783 break;
785 case GETSTAT:
786 case SHUTDOWN:
787 case INVALIDATE:
788 if (! secure_in_use)
790 /* Get the callers credentials. */
791 #ifdef SO_PEERCRED
792 struct ucred caller;
793 socklen_t optlen = sizeof (caller);
795 if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) < 0)
797 char buf[256];
799 dbg_log (_("error getting callers id: %s"),
800 strerror_r (errno, buf, sizeof (buf)));
801 break;
804 uid = caller.uid;
805 #else
806 /* Some systems have no SO_PEERCRED implementation. They don't
807 care about security so we don't as well. */
808 uid = 0;
809 #endif
812 /* Accept shutdown, getstat and invalidate only from root. For
813 the stat call also allow the user specified in the config file. */
814 if (req->type == GETSTAT)
816 if (uid == 0 || uid == stat_uid)
817 send_stats (fd, dbs);
819 else if (uid == 0)
821 if (req->type == INVALIDATE)
822 invalidate_cache (key);
823 else
824 termination_handler (0);
826 break;
828 case GETFDPW:
829 case GETFDGR:
830 case GETFDHST:
831 #ifdef SCM_RIGHTS
832 send_ro_fd (serv2db[req->type], key, fd);
833 #endif
834 break;
836 default:
837 /* Ignore the command, it's nothing we know. */
838 break;
843 /* Restart the process. */
844 static void
845 restart (void)
847 /* First determine the parameters. We do not use the parameters
848 passed to main() since in case nscd is started by running the
849 dynamic linker this will not work. Yes, this is not the usual
850 case but nscd is part of glibc and we occasionally do this. */
851 size_t buflen = 1024;
852 char *buf = alloca (buflen);
853 size_t readlen = 0;
854 int fd = open ("/proc/self/cmdline", O_RDONLY);
855 if (fd == -1)
857 dbg_log (_("\
858 cannot open /proc/self/cmdline: %s; disabling paranoia mode"),
859 strerror (errno));
861 paranoia = 0;
862 return;
865 while (1)
867 ssize_t n = TEMP_FAILURE_RETRY (read (fd, buf + readlen,
868 buflen - readlen));
869 if (n == -1)
871 dbg_log (_("\
872 cannot open /proc/self/cmdline: %s; disabling paranoia mode"),
873 strerror (errno));
875 close (fd);
876 paranoia = 0;
877 return;
880 readlen += n;
882 if (readlen < buflen)
883 break;
885 /* We might have to extend the buffer. */
886 size_t old_buflen = buflen;
887 char *newp = extend_alloca (buf, buflen, 2 * buflen);
888 buf = memmove (newp, buf, old_buflen);
891 close (fd);
893 /* Parse the command line. Worst case scenario: every two
894 characters form one parameter (one character plus NUL). */
895 char **argv = alloca ((readlen / 2 + 1) * sizeof (argv[0]));
896 int argc = 0;
898 char *cp = buf;
899 while (cp < buf + readlen)
901 argv[argc++] = cp;
902 cp = (char *) rawmemchr (cp, '\0') + 1;
904 argv[argc] = NULL;
906 /* Second, change back to the old user if we changed it. */
907 if (server_user != NULL)
909 if (setuid (old_uid) != 0)
911 dbg_log (_("\
912 cannot change to old UID: %s; disabling paranoia mode"),
913 strerror (errno));
915 paranoia = 0;
916 return;
919 if (setgid (old_gid) != 0)
921 dbg_log (_("\
922 cannot change to old GID: %s; disabling paranoia mode"),
923 strerror (errno));
925 setuid (server_uid);
926 paranoia = 0;
927 return;
931 /* Next change back to the old working directory. */
932 if (chdir (oldcwd) == -1)
934 dbg_log (_("\
935 cannot change to old working directory: %s; disabling paranoia mode"),
936 strerror (errno));
938 if (server_user != NULL)
940 setuid (server_uid);
941 setgid (server_gid);
943 paranoia = 0;
944 return;
947 /* Synchronize memory. */
948 for (int cnt = 0; cnt < lastdb; ++cnt)
950 /* Make sure nobody keeps using the database. */
951 dbs[cnt].head->timestamp = 0;
953 if (dbs[cnt].persistent)
954 // XXX async OK?
955 msync (dbs[cnt].head, dbs[cnt].memsize, MS_ASYNC);
958 /* The preparations are done. */
959 execv ("/proc/self/exe", argv);
961 /* If we come here, we will never be able to re-exec. */
962 dbg_log (_("re-exec failed: %s; disabling paranoia mode"),
963 strerror (errno));
965 if (server_user != NULL)
967 setuid (server_uid);
968 setgid (server_gid);
970 chdir ("/");
971 paranoia = 0;
975 /* List of file descriptors. */
976 struct fdlist
978 int fd;
979 struct fdlist *next;
981 /* Memory allocated for the list. */
982 static struct fdlist *fdlist;
983 /* List of currently ready-to-read file descriptors. */
984 static struct fdlist *readylist;
986 /* Conditional variable and mutex to signal availability of entries in
987 READYLIST. The condvar is initialized dynamically since we might
988 use a different clock depending on availability. */
989 static pthread_cond_t readylist_cond;
990 static pthread_mutex_t readylist_lock = PTHREAD_MUTEX_INITIALIZER;
992 /* The clock to use with the condvar. */
993 static clockid_t timeout_clock = CLOCK_REALTIME;
995 /* Number of threads ready to handle the READYLIST. */
996 static unsigned long int nready;
999 /* This is the main loop. It is replicated in different threads but the
1000 `poll' call makes sure only one thread handles an incoming connection. */
1001 static void *
1002 __attribute__ ((__noreturn__))
1003 nscd_run (void *p)
1005 const long int my_number = (long int) p;
1006 const int run_prune = my_number < lastdb && dbs[my_number].enabled;
1007 struct timespec prune_ts;
1008 int to = 0;
1009 char buf[256];
1011 if (run_prune)
1013 setup_thread (&dbs[my_number]);
1015 /* We are running. */
1016 dbs[my_number].head->timestamp = time (NULL);
1018 if (clock_gettime (timeout_clock, &prune_ts) == -1)
1019 /* Should never happen. */
1020 abort ();
1022 /* Compute timeout time. */
1023 prune_ts.tv_sec += CACHE_PRUNE_INTERVAL;
1026 /* Initial locking. */
1027 pthread_mutex_lock (&readylist_lock);
1029 /* One more thread available. */
1030 ++nready;
1032 while (1)
1034 while (readylist == NULL)
1036 if (run_prune)
1038 /* Wait, but not forever. */
1039 to = pthread_cond_timedwait (&readylist_cond, &readylist_lock,
1040 &prune_ts);
1042 /* If we were woken and there is no work to be done,
1043 just start pruning. */
1044 if (readylist == NULL && to == ETIMEDOUT)
1046 --nready;
1047 pthread_mutex_unlock (&readylist_lock);
1048 goto only_prune;
1051 else
1052 /* No need to timeout. */
1053 pthread_cond_wait (&readylist_cond, &readylist_lock);
1056 struct fdlist *it = readylist->next;
1057 if (readylist->next == readylist)
1058 /* Just one entry on the list. */
1059 readylist = NULL;
1060 else
1061 readylist->next = it->next;
1063 /* Extract the information and mark the record ready to be used
1064 again. */
1065 int fd = it->fd;
1066 it->next = NULL;
1068 /* One more thread available. */
1069 --nready;
1071 /* We are done with the list. */
1072 pthread_mutex_unlock (&readylist_lock);
1074 /* We do not want to block on a short read or so. */
1075 int fl = fcntl (fd, F_GETFL);
1076 if (fl == -1 || fcntl (fd, F_SETFL, fl | O_NONBLOCK) == -1)
1077 goto close_and_out;
1079 /* Now read the request. */
1080 request_header req;
1081 if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd, &req, sizeof (req)))
1082 != sizeof (req), 0))
1084 /* We failed to read data. Note that this also might mean we
1085 failed because we would have blocked. */
1086 if (debug_level > 0)
1087 dbg_log (_("short read while reading request: %s"),
1088 strerror_r (errno, buf, sizeof (buf)));
1089 goto close_and_out;
1092 /* Check whether this is a valid request type. */
1093 if (req.type < GETPWBYNAME || req.type >= LASTREQ)
1094 goto close_and_out;
1096 /* Some systems have no SO_PEERCRED implementation. They don't
1097 care about security so we don't as well. */
1098 uid_t uid = -1;
1099 #ifdef SO_PEERCRED
1100 pid_t pid = 0;
1102 if (secure_in_use)
1104 struct ucred caller;
1105 socklen_t optlen = sizeof (caller);
1107 if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) < 0)
1109 dbg_log (_("error getting callers id: %s"),
1110 strerror_r (errno, buf, sizeof (buf)));
1111 goto close_and_out;
1114 if (req.type < GETPWBYNAME || req.type > LASTDBREQ
1115 || serv2db[req.type]->secure)
1116 uid = caller.uid;
1118 pid = caller.pid;
1120 else if (__builtin_expect (debug_level > 0, 0))
1122 struct ucred caller;
1123 socklen_t optlen = sizeof (caller);
1125 if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) == 0)
1126 pid = caller.pid;
1128 #endif
1130 /* It should not be possible to crash the nscd with a silly
1131 request (i.e., a terribly large key). We limit the size to 1kb. */
1132 #define MAXKEYLEN 1024
1133 if (__builtin_expect (req.key_len, 1) < 0
1134 || __builtin_expect (req.key_len, 1) > MAXKEYLEN)
1136 if (debug_level > 0)
1137 dbg_log (_("key length in request too long: %d"), req.key_len);
1139 else
1141 /* Get the key. */
1142 char keybuf[MAXKEYLEN];
1144 if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd, keybuf,
1145 req.key_len))
1146 != req.key_len, 0))
1148 /* Again, this can also mean we would have blocked. */
1149 if (debug_level > 0)
1150 dbg_log (_("short read while reading request key: %s"),
1151 strerror_r (errno, buf, sizeof (buf)));
1152 goto close_and_out;
1155 if (__builtin_expect (debug_level, 0) > 0)
1157 #ifdef SO_PEERCRED
1158 if (pid != 0)
1159 dbg_log (_("\
1160 handle_request: request received (Version = %d) from PID %ld"),
1161 req.version, (long int) pid);
1162 else
1163 #endif
1164 dbg_log (_("\
1165 handle_request: request received (Version = %d)"), req.version);
1168 /* Phew, we got all the data, now process it. */
1169 handle_request (fd, &req, keybuf, uid);
1172 close_and_out:
1173 /* We are done. */
1174 close (fd);
1176 /* Check whether we should be pruning the cache. */
1177 assert (run_prune || to == 0);
1178 if (to == ETIMEDOUT)
1180 only_prune:
1181 /* The pthread_cond_timedwait() call timed out. It is time
1182 to clean up the cache. */
1183 assert (my_number < lastdb);
1184 prune_cache (&dbs[my_number], time (NULL));
1186 if (clock_gettime (timeout_clock, &prune_ts) == -1)
1187 /* Should never happen. */
1188 abort ();
1190 /* Compute next timeout time. */
1191 prune_ts.tv_sec += CACHE_PRUNE_INTERVAL;
1193 /* In case the list is emtpy we do not want to run the prune
1194 code right away again. */
1195 to = 0;
1198 /* Re-locking. */
1199 pthread_mutex_lock (&readylist_lock);
1201 /* One more thread available. */
1202 ++nready;
1207 static unsigned int nconns;
1209 static void
1210 fd_ready (int fd)
1212 pthread_mutex_lock (&readylist_lock);
1214 /* Find an empty entry in FDLIST. */
1215 size_t inner;
1216 for (inner = 0; inner < nconns; ++inner)
1217 if (fdlist[inner].next == NULL)
1218 break;
1219 assert (inner < nconns);
1221 fdlist[inner].fd = fd;
1223 if (readylist == NULL)
1224 readylist = fdlist[inner].next = &fdlist[inner];
1225 else
1227 fdlist[inner].next = readylist->next;
1228 readylist = readylist->next = &fdlist[inner];
1231 bool do_signal = true;
1232 if (__builtin_expect (nready == 0, 0))
1234 ++client_queued;
1235 do_signal = false;
1237 /* Try to start another thread to help out. */
1238 pthread_t th;
1239 if (nthreads < max_nthreads
1240 && pthread_create (&th, &attr, nscd_run,
1241 (void *) (long int) nthreads) == 0)
1243 /* We got another thread. */
1244 ++nthreads;
1245 /* The new thread might new a kick. */
1246 do_signal = true;
1251 pthread_mutex_unlock (&readylist_lock);
1253 /* Tell one of the worker threads there is work to do. */
1254 if (do_signal)
1255 pthread_cond_signal (&readylist_cond);
1259 /* Check whether restarting should happen. */
1260 static inline int
1261 restart_p (time_t now)
1263 return (paranoia && readylist == NULL && nready == nthreads
1264 && now >= restart_time);
1268 /* Array for times a connection was accepted. */
1269 static time_t *starttime;
1272 static void
1273 __attribute__ ((__noreturn__))
1274 main_loop_poll (void)
1276 struct pollfd *conns = (struct pollfd *) xmalloc (nconns
1277 * sizeof (conns[0]));
1279 conns[0].fd = sock;
1280 conns[0].events = POLLRDNORM;
1281 size_t nused = 1;
1282 size_t firstfree = 1;
1284 while (1)
1286 /* Wait for any event. We wait at most a couple of seconds so
1287 that we can check whether we should close any of the accepted
1288 connections since we have not received a request. */
1289 #define MAX_ACCEPT_TIMEOUT 30
1290 #define MIN_ACCEPT_TIMEOUT 5
1291 #define MAIN_THREAD_TIMEOUT \
1292 (MAX_ACCEPT_TIMEOUT * 1000 \
1293 - ((MAX_ACCEPT_TIMEOUT - MIN_ACCEPT_TIMEOUT) * 1000 * nused) / (2 * nconns))
1295 int n = poll (conns, nused, MAIN_THREAD_TIMEOUT);
1297 time_t now = time (NULL);
1299 /* If there is a descriptor ready for reading or there is a new
1300 connection, process this now. */
1301 if (n > 0)
1303 if (conns[0].revents != 0)
1305 /* We have a new incoming connection. Accept the connection. */
1306 int fd = TEMP_FAILURE_RETRY (accept (sock, NULL, NULL));
1308 /* use the descriptor if we have not reached the limit. */
1309 if (fd >= 0 && firstfree < nconns)
1311 conns[firstfree].fd = fd;
1312 conns[firstfree].events = POLLRDNORM;
1313 starttime[firstfree] = now;
1314 if (firstfree >= nused)
1315 nused = firstfree + 1;
1318 ++firstfree;
1319 while (firstfree < nused && conns[firstfree].fd != -1);
1322 --n;
1325 for (size_t cnt = 1; cnt < nused && n > 0; ++cnt)
1326 if (conns[cnt].revents != 0)
1328 fd_ready (conns[cnt].fd);
1330 /* Clean up the CONNS array. */
1331 conns[cnt].fd = -1;
1332 if (cnt < firstfree)
1333 firstfree = cnt;
1334 if (cnt == nused - 1)
1336 --nused;
1337 while (conns[nused - 1].fd == -1);
1339 --n;
1343 /* Now find entries which have timed out. */
1344 assert (nused > 0);
1346 /* We make the timeout length depend on the number of file
1347 descriptors currently used. */
1348 #define ACCEPT_TIMEOUT \
1349 (MAX_ACCEPT_TIMEOUT \
1350 - ((MAX_ACCEPT_TIMEOUT - MIN_ACCEPT_TIMEOUT) * nused) / nconns)
1351 time_t laststart = now - ACCEPT_TIMEOUT;
1353 for (size_t cnt = nused - 1; cnt > 0; --cnt)
1355 if (conns[cnt].fd != -1 && starttime[cnt] < laststart)
1357 /* Remove the entry, it timed out. */
1358 (void) close (conns[cnt].fd);
1359 conns[cnt].fd = -1;
1361 if (cnt < firstfree)
1362 firstfree = cnt;
1363 if (cnt == nused - 1)
1365 --nused;
1366 while (conns[nused - 1].fd == -1);
1370 if (restart_p (now))
1371 restart ();
1376 #ifdef HAVE_EPOLL
1377 static void
1378 main_loop_epoll (int efd)
1380 struct epoll_event ev = { 0, };
1381 int nused = 1;
1382 size_t highest = 0;
1384 /* Add the socket. */
1385 ev.events = EPOLLRDNORM;
1386 ev.data.fd = sock;
1387 if (epoll_ctl (efd, EPOLL_CTL_ADD, sock, &ev) == -1)
1388 /* We cannot use epoll. */
1389 return;
1391 while (1)
1393 struct epoll_event revs[100];
1394 # define nrevs (sizeof (revs) / sizeof (revs[0]))
1396 int n = epoll_wait (efd, revs, nrevs, MAIN_THREAD_TIMEOUT);
1398 time_t now = time (NULL);
1400 for (int cnt = 0; cnt < n; ++cnt)
1401 if (revs[cnt].data.fd == sock)
1403 /* A new connection. */
1404 int fd = TEMP_FAILURE_RETRY (accept (sock, NULL, NULL));
1406 if (fd >= 0)
1408 /* Try to add the new descriptor. */
1409 ev.data.fd = fd;
1410 if (fd >= nconns
1411 || epoll_ctl (efd, EPOLL_CTL_ADD, fd, &ev) == -1)
1412 /* The descriptor is too large or something went
1413 wrong. Close the descriptor. */
1414 close (fd);
1415 else
1417 /* Remember when we accepted the connection. */
1418 starttime[fd] = now;
1420 if (fd > highest)
1421 highest = fd;
1423 ++nused;
1427 else
1429 /* Remove the descriptor from the epoll descriptor. */
1430 struct epoll_event ev = { 0, };
1431 (void) epoll_ctl (efd, EPOLL_CTL_DEL, revs[cnt].data.fd, &ev);
1433 /* Get a worked to handle the request. */
1434 fd_ready (revs[cnt].data.fd);
1436 /* Reset the time. */
1437 starttime[revs[cnt].data.fd] = 0;
1438 if (revs[cnt].data.fd == highest)
1440 --highest;
1441 while (highest > 0 && starttime[highest] == 0);
1443 --nused;
1446 /* Now look for descriptors for accepted connections which have
1447 no reply in too long of a time. */
1448 time_t laststart = now - ACCEPT_TIMEOUT;
1449 for (int cnt = highest; cnt > STDERR_FILENO; --cnt)
1450 if (cnt != sock && starttime[cnt] != 0 && starttime[cnt] < laststart)
1452 /* We are waiting for this one for too long. Close it. */
1453 struct epoll_event ev = {0, };
1454 (void) epoll_ctl (efd, EPOLL_CTL_DEL, cnt, &ev);
1456 (void) close (cnt);
1458 starttime[cnt] = 0;
1459 if (cnt == highest)
1460 --highest;
1462 else if (cnt != sock && starttime[cnt] == 0 && cnt == highest)
1463 --highest;
1465 if (restart_p (now))
1466 restart ();
1469 #endif
1472 /* Start all the threads we want. The initial process is thread no. 1. */
1473 void
1474 start_threads (void)
1476 /* Initialize the conditional variable we will use. The only
1477 non-standard attribute we might use is the clock selection. */
1478 pthread_condattr_t condattr;
1479 pthread_condattr_init (&condattr);
1481 #if defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
1482 /* Determine whether the monotonous clock is available. */
1483 struct timespec dummy;
1484 # if _POSIX_MONOTONIC_CLOCK == 0
1485 if (sysconf (_SC_MONOTONIC_CLOCK) > 0)
1486 # endif
1488 # if defined _POSIX_CLOCK_SELECTION && _POSIX_CLOCK_SELECTION >= 0
1489 # if _POSIX_CLOCK_SELECTION == 0
1490 if (sysconf (_SC_CLOCK_SELECTION) > 0)
1491 # endif
1492 if (clock_getres (CLOCK_MONOTONIC, &dummy) == 0
1493 && pthread_condattr_setclock (&condattr, CLOCK_MONOTONIC) == 0)
1494 timeout_clock = CLOCK_MONOTONIC;
1495 # elif _POSIX_THREADS > 0
1496 if (sysconf (_SC_CLOCK_SELECTION) > 0)
1498 void *h = __libc_dlopen (LIBPTHREAD_SO);
1499 int (*condattr_setclock) (pthread_condattr_t *, __clockid_t) = NULL;
1501 if (h != NULL)
1502 condattr_setclock = __libc_dlsym (h, "pthread_condattr_setclock");
1504 if (condattr_setclock
1505 && clock_getres (CLOCK_MONOTONIC, &dummy) == 0
1506 && condattr_setclock (&condattr, CLOCK_MONOTONIC) == 0)
1507 timeout_clock = CLOCK_MONOTONIC;
1509 if (h != NULL)
1510 __libc_dlclose (h);
1512 # endif
1514 #endif
1516 pthread_cond_init (&readylist_cond, &condattr);
1517 pthread_condattr_destroy (&condattr);
1520 /* Create the attribute for the threads. They are all created
1521 detached. */
1522 pthread_attr_init (&attr);
1523 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
1524 /* Use 1MB stacks, twice as much for 64-bit architectures. */
1525 pthread_attr_setstacksize (&attr, 1024 * 1024 * (sizeof (void *) / 4));
1527 /* We allow less than LASTDB threads only for debugging. */
1528 if (debug_level == 0)
1529 nthreads = MAX (nthreads, lastdb);
1531 int nfailed = 0;
1532 for (long int i = 0; i < nthreads; ++i)
1534 pthread_t th;
1535 if (pthread_create (&th, &attr, nscd_run, (void *) (i - nfailed)) != 0)
1536 ++nfailed;
1538 if (nthreads - nfailed < lastdb)
1540 /* We could not start enough threads. */
1541 dbg_log (_("could only start %d threads; terminating"),
1542 nthreads - nfailed);
1543 exit (1);
1546 /* Determine how much room for descriptors we should initially
1547 allocate. This might need to change later if we cap the number
1548 with MAXCONN. */
1549 const long int nfds = sysconf (_SC_OPEN_MAX);
1550 #define MINCONN 32
1551 #define MAXCONN 16384
1552 if (nfds == -1 || nfds > MAXCONN)
1553 nconns = MAXCONN;
1554 else if (nfds < MINCONN)
1555 nconns = MINCONN;
1556 else
1557 nconns = nfds;
1559 /* We need memory to pass descriptors on to the worker threads. */
1560 fdlist = (struct fdlist *) xcalloc (nconns, sizeof (fdlist[0]));
1561 /* Array to keep track when connection was accepted. */
1562 starttime = (time_t *) xcalloc (nconns, sizeof (starttime[0]));
1564 /* In the main thread we execute the loop which handles incoming
1565 connections. */
1566 #ifdef HAVE_EPOLL
1567 int efd = epoll_create (100);
1568 if (efd != -1)
1570 main_loop_epoll (efd);
1571 close (efd);
1573 #endif
1575 main_loop_poll ();
1578 /* Look up the uid, gid, and supplementary groups to run nscd as. When
1579 this function is called, we are not listening on the nscd socket yet so
1580 we can just use the ordinary lookup functions without causing a lockup */
1581 static void
1582 begin_drop_privileges (void)
1584 struct passwd *pwd = getpwnam (server_user);
1586 if (pwd == NULL)
1588 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1589 error (EXIT_FAILURE, 0, _("Failed to run nscd as user '%s'"),
1590 server_user);
1593 server_uid = pwd->pw_uid;
1594 server_gid = pwd->pw_gid;
1596 /* Save the old UID/GID if we have to change back. */
1597 if (paranoia)
1599 old_uid = getuid ();
1600 old_gid = getgid ();
1603 if (getgrouplist (server_user, server_gid, NULL, &server_ngroups) == 0)
1605 /* This really must never happen. */
1606 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1607 error (EXIT_FAILURE, errno, _("initial getgrouplist failed"));
1610 server_groups = (gid_t *) xmalloc (server_ngroups * sizeof (gid_t));
1612 if (getgrouplist (server_user, server_gid, server_groups, &server_ngroups)
1613 == -1)
1615 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1616 error (EXIT_FAILURE, errno, _("getgrouplist failed"));
1621 /* Call setgroups(), setgid(), and setuid() to drop root privileges and
1622 run nscd as the user specified in the configuration file. */
1623 static void
1624 finish_drop_privileges (void)
1626 if (setgroups (server_ngroups, server_groups) == -1)
1628 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1629 error (EXIT_FAILURE, errno, _("setgroups failed"));
1632 if (setgid (server_gid) == -1)
1634 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1635 perror ("setgid");
1636 exit (1);
1639 if (setuid (server_uid) == -1)
1641 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1642 perror ("setuid");
1643 exit (1);
1647 /* Handle the HUP signal which will force a dump of the cache */
1648 void
1649 sighup_handler (int signum)
1651 /* Prune the password database */
1652 prune_cache (&dbs[pwddb], LONG_MAX);
1654 /* Prune the group database */
1655 prune_cache (&dbs[grpdb], LONG_MAX);
1657 /* Prune the host database */
1658 prune_cache (&dbs[hstdb], LONG_MAX);