2005-02-25 Roland McGrath <roland@redhat.com>
[glibc.git] / nscd / connections.c
blob86069b237a425fe3d7f9fef44558b412c240bd2a
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 <error.h>
25 #include <errno.h>
26 #include <fcntl.h>
27 #include <grp.h>
28 #include <libintl.h>
29 #include <pthread.h>
30 #include <pwd.h>
31 #include <resolv.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <arpa/inet.h>
36 #ifdef HAVE_EPOLL
37 # include <sys/epoll.h>
38 #endif
39 #include <sys/mman.h>
40 #include <sys/param.h>
41 #include <sys/poll.h>
42 #include <sys/socket.h>
43 #include <sys/stat.h>
44 #include <sys/un.h>
46 #include "nscd.h"
47 #include "dbg_log.h"
48 #include "selinux.h"
51 /* Number of bytes of data we initially reserve for each hash table bucket. */
52 #define DEFAULT_DATASIZE_PER_BUCKET 1024
55 /* Wrapper functions with error checking for standard functions. */
56 extern void *xmalloc (size_t n);
57 extern void *xcalloc (size_t n, size_t s);
58 extern void *xrealloc (void *o, size_t n);
60 /* Support to run nscd as an unprivileged user */
61 const char *server_user;
62 static uid_t server_uid;
63 static gid_t server_gid;
64 const char *stat_user;
65 uid_t stat_uid;
66 static gid_t *server_groups;
67 #ifndef NGROUPS
68 # define NGROUPS 32
69 #endif
70 static int server_ngroups;
72 static pthread_attr_t attr;
74 static void begin_drop_privileges (void);
75 static void finish_drop_privileges (void);
77 /* Map request type to a string. */
78 const char *serv2str[LASTREQ] =
80 [GETPWBYNAME] = "GETPWBYNAME",
81 [GETPWBYUID] = "GETPWBYUID",
82 [GETGRBYNAME] = "GETGRBYNAME",
83 [GETGRBYGID] = "GETGRBYGID",
84 [GETHOSTBYNAME] = "GETHOSTBYNAME",
85 [GETHOSTBYNAMEv6] = "GETHOSTBYNAMEv6",
86 [GETHOSTBYADDR] = "GETHOSTBYADDR",
87 [GETHOSTBYADDRv6] = "GETHOSTBYADDRv6",
88 [SHUTDOWN] = "SHUTDOWN",
89 [GETSTAT] = "GETSTAT",
90 [INVALIDATE] = "INVALIDATE",
91 [GETFDPW] = "GETFDPW",
92 [GETFDGR] = "GETFDGR",
93 [GETFDHST] = "GETFDHST",
94 [GETAI] = "GETAI",
95 [INITGROUPS] = "INITGROUPS"
98 /* The control data structures for the services. */
99 struct database_dyn dbs[lastdb] =
101 [pwddb] = {
102 .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
103 .enabled = 0,
104 .check_file = 1,
105 .persistent = 0,
106 .shared = 0,
107 .filename = "/etc/passwd",
108 .db_filename = _PATH_NSCD_PASSWD_DB,
109 .disabled_iov = &pwd_iov_disabled,
110 .postimeout = 3600,
111 .negtimeout = 20,
112 .wr_fd = -1,
113 .ro_fd = -1,
114 .mmap_used = false
116 [grpdb] = {
117 .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
118 .enabled = 0,
119 .check_file = 1,
120 .persistent = 0,
121 .shared = 0,
122 .filename = "/etc/group",
123 .db_filename = _PATH_NSCD_GROUP_DB,
124 .disabled_iov = &grp_iov_disabled,
125 .postimeout = 3600,
126 .negtimeout = 60,
127 .wr_fd = -1,
128 .ro_fd = -1,
129 .mmap_used = false
131 [hstdb] = {
132 .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
133 .enabled = 0,
134 .check_file = 1,
135 .persistent = 0,
136 .shared = 0,
137 .filename = "/etc/hosts",
138 .db_filename = _PATH_NSCD_HOSTS_DB,
139 .disabled_iov = &hst_iov_disabled,
140 .postimeout = 3600,
141 .negtimeout = 20,
142 .wr_fd = -1,
143 .ro_fd = -1,
144 .mmap_used = false
149 /* Mapping of request type to database. */
150 static struct database_dyn *const serv2db[LASTREQ] =
152 [GETPWBYNAME] = &dbs[pwddb],
153 [GETPWBYUID] = &dbs[pwddb],
154 [GETGRBYNAME] = &dbs[grpdb],
155 [GETGRBYGID] = &dbs[grpdb],
156 [GETHOSTBYNAME] = &dbs[hstdb],
157 [GETHOSTBYNAMEv6] = &dbs[hstdb],
158 [GETHOSTBYADDR] = &dbs[hstdb],
159 [GETHOSTBYADDRv6] = &dbs[hstdb],
160 [GETFDPW] = &dbs[pwddb],
161 [GETFDGR] = &dbs[grpdb],
162 [GETFDHST] = &dbs[hstdb],
163 [GETAI] = &dbs[hstdb],
164 [INITGROUPS] = &dbs[grpdb]
168 /* Number of seconds between two cache pruning runs. */
169 #define CACHE_PRUNE_INTERVAL 15
172 /* Initial number of threads to use. */
173 int nthreads = -1;
174 /* Maximum number of threads to use. */
175 int max_nthreads = 32;
177 /* Socket for incoming connections. */
178 static int sock;
180 /* Number of times clients had to wait. */
181 unsigned long int client_queued;
184 ssize_t
185 writeall (int fd, const void *buf, size_t len)
187 size_t n = len;
188 ssize_t ret;
191 ret = TEMP_FAILURE_RETRY (write (fd, buf, n));
192 if (ret <= 0)
193 break;
194 buf = (const char *) buf + ret;
195 n -= ret;
197 while (n > 0);
198 return ret < 0 ? ret : len - n;
202 /* Initialize database information structures. */
203 void
204 nscd_init (void)
206 /* Secure mode and unprivileged mode are incompatible */
207 if (server_user != NULL && secure_in_use)
209 dbg_log (_("Cannot run nscd in secure mode as unprivileged user"));
210 exit (1);
213 /* Look up unprivileged uid/gid/groups before we start listening on the
214 socket */
215 if (server_user != NULL)
216 begin_drop_privileges ();
218 if (nthreads == -1)
219 /* No configuration for this value, assume a default. */
220 nthreads = 2 * lastdb;
222 for (size_t cnt = 0; cnt < lastdb; ++cnt)
223 if (dbs[cnt].enabled)
225 pthread_rwlock_init (&dbs[cnt].lock, NULL);
226 pthread_mutex_init (&dbs[cnt].memlock, NULL);
228 if (dbs[cnt].persistent)
230 /* Try to open the appropriate file on disk. */
231 int fd = open (dbs[cnt].db_filename, O_RDWR);
232 if (fd != -1)
234 struct stat64 st;
235 void *mem;
236 size_t total;
237 struct database_pers_head head;
238 ssize_t n = TEMP_FAILURE_RETRY (read (fd, &head,
239 sizeof (head)));
240 if (n != sizeof (head) || fstat64 (fd, &st) != 0)
242 fail_db:
243 dbg_log (_("invalid persistent database file \"%s\": %s"),
244 dbs[cnt].db_filename, strerror (errno));
245 dbs[cnt].persistent = 0;
247 else if (head.module == 0 && head.data_size == 0)
249 /* The file has been created, but the head has not been
250 initialized yet. Remove the old file. */
251 unlink (dbs[cnt].db_filename);
253 else if (head.header_size != (int) sizeof (head))
255 dbg_log (_("invalid persistent database file \"%s\": %s"),
256 dbs[cnt].db_filename,
257 _("header size does not match"));
258 dbs[cnt].persistent = 0;
260 else if ((total = (sizeof (head)
261 + roundup (head.module * sizeof (ref_t),
262 ALIGN)
263 + head.data_size))
264 > st.st_size)
266 dbg_log (_("invalid persistent database file \"%s\": %s"),
267 dbs[cnt].db_filename,
268 _("file size does not match"));
269 dbs[cnt].persistent = 0;
271 else if ((mem = mmap (NULL, total, PROT_READ | PROT_WRITE,
272 MAP_SHARED, fd, 0)) == MAP_FAILED)
273 goto fail_db;
274 else
276 /* Success. We have the database. */
277 dbs[cnt].head = mem;
278 dbs[cnt].memsize = total;
279 dbs[cnt].data = (char *)
280 &dbs[cnt].head->array[roundup (dbs[cnt].head->module,
281 ALIGN / sizeof (ref_t))];
282 dbs[cnt].mmap_used = true;
284 if (dbs[cnt].suggested_module > head.module)
285 dbg_log (_("suggested size of table for database %s larger than the persistent database's table"),
286 dbnames[cnt]);
288 dbs[cnt].wr_fd = fd;
289 fd = -1;
290 /* We also need a read-only descriptor. */
291 if (dbs[cnt].shared)
293 dbs[cnt].ro_fd = open (dbs[cnt].db_filename, O_RDONLY);
294 if (dbs[cnt].ro_fd == -1)
295 dbg_log (_("\
296 cannot create read-only descriptor for \"%s\"; no mmap"),
297 dbs[cnt].db_filename);
300 // XXX Shall we test whether the descriptors actually
301 // XXX point to the same file?
304 /* Close the file descriptors in case something went
305 wrong in which case the variable have not been
306 assigned -1. */
307 if (fd != -1)
308 close (fd);
312 if (dbs[cnt].head == NULL)
314 /* No database loaded. Allocate the data structure,
315 possibly on disk. */
316 struct database_pers_head head;
317 size_t total = (sizeof (head)
318 + roundup (dbs[cnt].suggested_module
319 * sizeof (ref_t), ALIGN)
320 + (dbs[cnt].suggested_module
321 * DEFAULT_DATASIZE_PER_BUCKET));
323 /* Try to create the database. If we do not need a
324 persistent database create a temporary file. */
325 int fd;
326 int ro_fd = -1;
327 if (dbs[cnt].persistent)
329 fd = open (dbs[cnt].db_filename,
330 O_RDWR | O_CREAT | O_EXCL | O_TRUNC,
331 S_IRUSR | S_IWUSR);
332 if (fd != -1 && dbs[cnt].shared)
333 ro_fd = open (dbs[cnt].db_filename, O_RDONLY);
335 else
337 char fname[] = _PATH_NSCD_XYZ_DB_TMP;
338 fd = mkstemp (fname);
340 /* We do not need the file name anymore after we
341 opened another file descriptor in read-only mode. */
342 if (fd != -1)
344 if (dbs[cnt].shared)
345 ro_fd = open (fname, O_RDONLY);
347 unlink (fname);
351 if (fd == -1)
353 if (errno == EEXIST)
355 dbg_log (_("database for %s corrupted or simultaneously used; remove %s manually if necessary and restart"),
356 dbnames[cnt], dbs[cnt].db_filename);
357 // XXX Correct way to terminate?
358 exit (1);
361 if (dbs[cnt].persistent)
362 dbg_log (_("cannot create %s; no persistent database used"),
363 dbs[cnt].db_filename);
364 else
365 dbg_log (_("cannot create %s; no sharing possible"),
366 dbs[cnt].db_filename);
368 dbs[cnt].persistent = 0;
369 // XXX remember: no mmap
371 else
373 /* Tell the user if we could not create the read-only
374 descriptor. */
375 if (ro_fd == -1 && dbs[cnt].shared)
376 dbg_log (_("\
377 cannot create read-only descriptor for \"%s\"; no mmap"),
378 dbs[cnt].db_filename);
380 /* Before we create the header, initialiye the hash
381 table. So that if we get interrupted if writing
382 the header we can recognize a partially initialized
383 database. */
384 size_t ps = sysconf (_SC_PAGESIZE);
385 char tmpbuf[ps];
386 assert (~ENDREF == 0);
387 memset (tmpbuf, '\xff', ps);
389 size_t remaining = dbs[cnt].suggested_module * sizeof (ref_t);
390 off_t offset = sizeof (head);
392 size_t towrite;
393 if (offset % ps != 0)
395 towrite = MIN (remaining, ps - (offset % ps));
396 pwrite (fd, tmpbuf, towrite, offset);
397 offset += towrite;
398 remaining -= towrite;
401 while (remaining > ps)
403 pwrite (fd, tmpbuf, ps, offset);
404 offset += ps;
405 remaining -= ps;
408 if (remaining > 0)
409 pwrite (fd, tmpbuf, remaining, offset);
411 /* Create the header of the file. */
412 struct database_pers_head head =
414 .version = DB_VERSION,
415 .header_size = sizeof (head),
416 .module = dbs[cnt].suggested_module,
417 .data_size = (dbs[cnt].suggested_module
418 * DEFAULT_DATASIZE_PER_BUCKET),
419 .first_free = 0
421 void *mem;
423 if ((TEMP_FAILURE_RETRY (write (fd, &head, sizeof (head)))
424 != sizeof (head))
425 || ftruncate (fd, total) != 0
426 || (mem = mmap (NULL, total, PROT_READ | PROT_WRITE,
427 MAP_SHARED, fd, 0)) == MAP_FAILED)
429 unlink (dbs[cnt].db_filename);
430 dbg_log (_("cannot write to database file %s: %s"),
431 dbs[cnt].db_filename, strerror (errno));
432 dbs[cnt].persistent = 0;
434 else
436 /* Success. */
437 dbs[cnt].head = mem;
438 dbs[cnt].data = (char *)
439 &dbs[cnt].head->array[roundup (dbs[cnt].head->module,
440 ALIGN / sizeof (ref_t))];
441 dbs[cnt].memsize = total;
442 dbs[cnt].mmap_used = true;
444 /* Remember the descriptors. */
445 dbs[cnt].wr_fd = fd;
446 dbs[cnt].ro_fd = ro_fd;
447 fd = -1;
448 ro_fd = -1;
451 if (fd != -1)
452 close (fd);
453 if (ro_fd != -1)
454 close (ro_fd);
458 if (paranoia
459 && ((dbs[cnt].wr_fd != -1
460 && fcntl (dbs[cnt].wr_fd, F_SETFD, FD_CLOEXEC) == -1)
461 || (dbs[cnt].ro_fd != -1
462 && fcntl (dbs[cnt].ro_fd, F_SETFD, FD_CLOEXEC) == -1)))
464 dbg_log (_("\
465 cannot set socket to close on exec: %s; disabling paranoia mode"),
466 strerror (errno));
467 paranoia = 0;
470 if (dbs[cnt].head == NULL)
472 /* We do not use the persistent database. Just
473 create an in-memory data structure. */
474 assert (! dbs[cnt].persistent);
476 dbs[cnt].head = xmalloc (sizeof (struct database_pers_head)
477 + (dbs[cnt].suggested_module
478 * sizeof (ref_t)));
479 memset (dbs[cnt].head, '\0', sizeof (dbs[cnt].head));
480 assert (~ENDREF == 0);
481 memset (dbs[cnt].head->array, '\xff',
482 dbs[cnt].suggested_module * sizeof (ref_t));
483 dbs[cnt].head->module = dbs[cnt].suggested_module;
484 dbs[cnt].head->data_size = (DEFAULT_DATASIZE_PER_BUCKET
485 * dbs[cnt].head->module);
486 dbs[cnt].data = xmalloc (dbs[cnt].head->data_size);
487 dbs[cnt].head->first_free = 0;
489 dbs[cnt].shared = 0;
490 assert (dbs[cnt].ro_fd == -1);
493 if (dbs[cnt].check_file)
495 /* We need the modification date of the file. */
496 struct stat st;
498 if (stat (dbs[cnt].filename, &st) < 0)
500 /* We cannot stat() the file, disable file checking. */
501 dbg_log (_("cannot stat() file `%s': %s"),
502 dbs[cnt].filename, strerror (errno));
503 dbs[cnt].check_file = 0;
505 else
506 dbs[cnt].file_mtime = st.st_mtime;
510 /* Create the socket. */
511 sock = socket (AF_UNIX, SOCK_STREAM, 0);
512 if (sock < 0)
514 dbg_log (_("cannot open socket: %s"), strerror (errno));
515 exit (1);
517 /* Bind a name to the socket. */
518 struct sockaddr_un sock_addr;
519 sock_addr.sun_family = AF_UNIX;
520 strcpy (sock_addr.sun_path, _PATH_NSCDSOCKET);
521 if (bind (sock, (struct sockaddr *) &sock_addr, sizeof (sock_addr)) < 0)
523 dbg_log ("%s: %s", _PATH_NSCDSOCKET, strerror (errno));
524 exit (1);
527 /* We don't want to get stuck on accept. */
528 int fl = fcntl (sock, F_GETFL);
529 if (fl == -1 || fcntl (sock, F_SETFL, fl | O_NONBLOCK) == -1)
531 dbg_log (_("cannot change socket to nonblocking mode: %s"),
532 strerror (errno));
533 exit (1);
536 /* The descriptor needs to be closed on exec. */
537 if (paranoia && fcntl (sock, F_SETFD, FD_CLOEXEC) == -1)
539 dbg_log (_("cannot set socket to close on exec: %s"),
540 strerror (errno));
541 exit (1);
544 /* Set permissions for the socket. */
545 chmod (_PATH_NSCDSOCKET, DEFFILEMODE);
547 /* Set the socket up to accept connections. */
548 if (listen (sock, SOMAXCONN) < 0)
550 dbg_log (_("cannot enable socket to accept connections: %s"),
551 strerror (errno));
552 exit (1);
555 /* Change to unprivileged uid/gid/groups if specifed in config file */
556 if (server_user != NULL)
557 finish_drop_privileges ();
561 /* Close the connections. */
562 void
563 close_sockets (void)
565 close (sock);
569 static void
570 invalidate_cache (char *key)
572 dbtype number;
574 if (strcmp (key, "passwd") == 0)
575 number = pwddb;
576 else if (strcmp (key, "group") == 0)
577 number = grpdb;
578 else if (__builtin_expect (strcmp (key, "hosts"), 0) == 0)
580 number = hstdb;
582 /* Re-initialize the resolver. resolv.conf might have changed. */
583 res_init ();
585 else
586 return;
588 if (dbs[number].enabled)
589 prune_cache (&dbs[number], LONG_MAX);
593 #ifdef SCM_RIGHTS
594 static void
595 send_ro_fd (struct database_dyn *db, char *key, int fd)
597 /* If we do not have an read-only file descriptor do nothing. */
598 if (db->ro_fd == -1)
599 return;
601 /* We need to send some data along with the descriptor. */
602 struct iovec iov[1];
603 iov[0].iov_base = key;
604 iov[0].iov_len = strlen (key) + 1;
606 /* Prepare the control message to transfer the descriptor. */
607 char buf[CMSG_SPACE (sizeof (int))];
608 struct msghdr msg = { .msg_iov = iov, .msg_iovlen = 1,
609 .msg_control = buf, .msg_controllen = sizeof (buf) };
610 struct cmsghdr *cmsg = CMSG_FIRSTHDR (&msg);
612 cmsg->cmsg_level = SOL_SOCKET;
613 cmsg->cmsg_type = SCM_RIGHTS;
614 cmsg->cmsg_len = CMSG_LEN (sizeof (int));
616 *(int *) CMSG_DATA (cmsg) = db->ro_fd;
618 msg.msg_controllen = cmsg->cmsg_len;
620 /* Send the control message. We repeat when we are interrupted but
621 everything else is ignored. */
622 #ifndef MSG_NOSIGNAL
623 # define MSG_NOSIGNAL 0
624 #endif
625 (void) TEMP_FAILURE_RETRY (sendmsg (fd, &msg, MSG_NOSIGNAL));
627 if (__builtin_expect (debug_level > 0, 0))
628 dbg_log (_("provide access to FD %d, for %s"), db->ro_fd, key);
630 #endif /* SCM_RIGHTS */
633 /* Handle new request. */
634 static void
635 handle_request (int fd, request_header *req, void *key, uid_t uid)
637 if (__builtin_expect (req->version, NSCD_VERSION) != NSCD_VERSION)
639 if (debug_level > 0)
640 dbg_log (_("\
641 cannot handle old request version %d; current version is %d"),
642 req->version, NSCD_VERSION);
643 return;
646 /* Make the SELinux check before we go on to the standard checks. We
647 need to verify that the request type is valid, since it has not
648 yet been checked at this point. */
649 if (selinux_enabled
650 && __builtin_expect (req->type, GETPWBYNAME) >= GETPWBYNAME
651 && __builtin_expect (req->type, LASTREQ) < LASTREQ
652 && nscd_request_avc_has_perm (fd, req->type) != 0)
653 return;
655 struct database_dyn *db = serv2db[req->type];
657 // XXX Clean up so that each new command need not introduce a
658 // XXX new conditional.
659 if ((__builtin_expect (req->type, GETPWBYNAME) >= GETPWBYNAME
660 && __builtin_expect (req->type, LASTDBREQ) <= LASTDBREQ)
661 || req->type == GETAI || req->type == INITGROUPS)
663 if (__builtin_expect (debug_level, 0) > 0)
665 if (req->type == GETHOSTBYADDR || req->type == GETHOSTBYADDRv6)
667 char buf[INET6_ADDRSTRLEN];
669 dbg_log ("\t%s (%s)", serv2str[req->type],
670 inet_ntop (req->type == GETHOSTBYADDR
671 ? AF_INET : AF_INET6,
672 key, buf, sizeof (buf)));
674 else
675 dbg_log ("\t%s (%s)", serv2str[req->type], (char *) key);
678 /* Is this service enabled? */
679 if (!db->enabled)
681 /* No, sent the prepared record. */
682 if (TEMP_FAILURE_RETRY (write (fd, db->disabled_iov->iov_base,
683 db->disabled_iov->iov_len))
684 != (ssize_t) db->disabled_iov->iov_len
685 && __builtin_expect (debug_level, 0) > 0)
687 /* We have problems sending the result. */
688 char buf[256];
689 dbg_log (_("cannot write result: %s"),
690 strerror_r (errno, buf, sizeof (buf)));
693 return;
696 /* Be sure we can read the data. */
697 if (__builtin_expect (pthread_rwlock_tryrdlock (&db->lock) != 0, 0))
699 ++db->head->rdlockdelayed;
700 pthread_rwlock_rdlock (&db->lock);
703 /* See whether we can handle it from the cache. */
704 struct datahead *cached;
705 cached = (struct datahead *) cache_search (req->type, key, req->key_len,
706 db, uid);
707 if (cached != NULL)
709 /* Hurray it's in the cache. */
710 if (writeall (fd, cached->data, cached->recsize)
711 != cached->recsize
712 && __builtin_expect (debug_level, 0) > 0)
714 /* We have problems sending the result. */
715 char buf[256];
716 dbg_log (_("cannot write result: %s"),
717 strerror_r (errno, buf, sizeof (buf)));
720 pthread_rwlock_unlock (&db->lock);
722 return;
725 pthread_rwlock_unlock (&db->lock);
727 else if (__builtin_expect (debug_level, 0) > 0)
729 if (req->type == INVALIDATE)
730 dbg_log ("\t%s (%s)", serv2str[req->type], (char *) key);
731 else
732 dbg_log ("\t%s", serv2str[req->type]);
735 /* Handle the request. */
736 switch (req->type)
738 case GETPWBYNAME:
739 addpwbyname (db, fd, req, key, uid);
740 break;
742 case GETPWBYUID:
743 addpwbyuid (db, fd, req, key, uid);
744 break;
746 case GETGRBYNAME:
747 addgrbyname (db, fd, req, key, uid);
748 break;
750 case GETGRBYGID:
751 addgrbygid (db, fd, req, key, uid);
752 break;
754 case GETHOSTBYNAME:
755 addhstbyname (db, fd, req, key, uid);
756 break;
758 case GETHOSTBYNAMEv6:
759 addhstbynamev6 (db, fd, req, key, uid);
760 break;
762 case GETHOSTBYADDR:
763 addhstbyaddr (db, fd, req, key, uid);
764 break;
766 case GETHOSTBYADDRv6:
767 addhstbyaddrv6 (db, fd, req, key, uid);
768 break;
770 case GETAI:
771 addhstai (db, fd, req, key, uid);
772 break;
774 case INITGROUPS:
775 addinitgroups (db, fd, req, key, uid);
776 break;
778 case GETSTAT:
779 case SHUTDOWN:
780 case INVALIDATE:
781 if (! secure_in_use)
783 /* Get the callers credentials. */
784 #ifdef SO_PEERCRED
785 struct ucred caller;
786 socklen_t optlen = sizeof (caller);
788 if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) < 0)
790 char buf[256];
792 dbg_log (_("error getting callers id: %s"),
793 strerror_r (errno, buf, sizeof (buf)));
794 break;
797 uid = caller.uid;
798 #else
799 /* Some systems have no SO_PEERCRED implementation. They don't
800 care about security so we don't as well. */
801 uid = 0;
802 #endif
805 /* Accept shutdown, getstat and invalidate only from root. For
806 the stat call also allow the user specified in the config file. */
807 if (req->type == GETSTAT)
809 if (uid == 0 || uid == stat_uid)
810 send_stats (fd, dbs);
812 else if (uid == 0)
814 if (req->type == INVALIDATE)
815 invalidate_cache (key);
816 else
817 termination_handler (0);
819 break;
821 case GETFDPW:
822 case GETFDGR:
823 case GETFDHST:
824 #ifdef SCM_RIGHTS
825 send_ro_fd (serv2db[req->type], key, fd);
826 #endif
827 break;
829 default:
830 /* Ignore the command, it's nothing we know. */
831 break;
836 /* Restart the process. */
837 static void
838 restart (void)
840 /* First determine the parameters. We do not use the parameters
841 passed to main() since in case nscd is started by running the
842 dynamic linker this will not work. Yes, this is not the usual
843 case but nscd is part of glibc and we occasionally do this. */
844 size_t buflen = 1024;
845 char *buf = alloca (buflen);
846 size_t readlen = 0;
847 int fd = open ("/proc/self/cmdline", O_RDONLY);
848 if (fd == -1)
850 dbg_log (_("\
851 cannot open /proc/self/cmdline: %s; disabling paranoia mode"),
852 strerror (errno));
854 paranoia = 0;
855 return;
858 while (1)
860 ssize_t n = TEMP_FAILURE_RETRY (read (fd, buf + readlen,
861 buflen - readlen));
862 if (n == -1)
864 dbg_log (_("\
865 cannot open /proc/self/cmdline: %s; disabling paranoia mode"),
866 strerror (errno));
868 close (fd);
869 paranoia = 0;
870 return;
873 readlen += n;
875 if (readlen < buflen)
876 break;
878 /* We might have to extend the buffer. */
879 size_t old_buflen = buflen;
880 char *newp = extend_alloca (buf, buflen, 2 * buflen);
881 buf = memmove (newp, buf, old_buflen);
884 close (fd);
886 /* Parse the command line. Worst case scenario: every two
887 characters form one parameter (one character plus NUL). */
888 char **argv = alloca ((readlen / 2 + 1) * sizeof (argv[0]));
889 int argc = 0;
891 char *cp = buf;
892 while (cp < buf + readlen)
894 argv[argc++] = cp;
895 cp = (char *) rawmemchr (cp, '\0') + 1;
897 argv[argc] = NULL;
899 /* Second, change back to the old user if we changed it. */
900 if (server_user != NULL)
902 if (setuid (old_uid) != 0)
904 dbg_log (_("\
905 cannot change to old UID: %s; disabling paranoia mode"),
906 strerror (errno));
908 paranoia = 0;
909 return;
912 if (setgid (old_gid) != 0)
914 dbg_log (_("\
915 cannot change to old GID: %s; disabling paranoia mode"),
916 strerror (errno));
918 setuid (server_uid);
919 paranoia = 0;
920 return;
924 /* Next change back to the old working directory. */
925 if (chdir (oldcwd) == -1)
927 dbg_log (_("\
928 cannot change to old working directory: %s; disabling paranoia mode"),
929 strerror (errno));
931 if (server_user != NULL)
933 setuid (server_uid);
934 setgid (server_gid);
936 paranoia = 0;
937 return;
940 /* Synchronize memory. */
941 for (int cnt = 0; cnt < lastdb; ++cnt)
943 /* Make sure nobody keeps using the database. */
944 dbs[cnt].head->timestamp = 0;
946 if (dbs[cnt].persistent)
947 // XXX async OK?
948 msync (dbs[cnt].head, dbs[cnt].memsize, MS_ASYNC);
951 /* The preparations are done. */
952 execv ("/proc/self/exe", argv);
954 /* If we come here, we will never be able to re-exec. */
955 dbg_log (_("re-exec failed: %s; disabling paranoia mode"),
956 strerror (errno));
958 if (server_user != NULL)
960 setuid (server_uid);
961 setgid (server_gid);
963 chdir ("/");
964 paranoia = 0;
968 /* List of file descriptors. */
969 struct fdlist
971 int fd;
972 struct fdlist *next;
974 /* Memory allocated for the list. */
975 static struct fdlist *fdlist;
976 /* List of currently ready-to-read file descriptors. */
977 static struct fdlist *readylist;
979 /* Conditional variable and mutex to signal availability of entries in
980 READYLIST. The condvar is initialized dynamically since we might
981 use a different clock depending on availability. */
982 static pthread_cond_t readylist_cond;
983 static pthread_mutex_t readylist_lock = PTHREAD_MUTEX_INITIALIZER;
985 /* The clock to use with the condvar. */
986 static clockid_t timeout_clock = CLOCK_REALTIME;
988 /* Number of threads ready to handle the READYLIST. */
989 static unsigned long int nready;
992 /* This is the main loop. It is replicated in different threads but the
993 `poll' call makes sure only one thread handles an incoming connection. */
994 static void *
995 __attribute__ ((__noreturn__))
996 nscd_run (void *p)
998 const long int my_number = (long int) p;
999 const int run_prune = my_number < lastdb && dbs[my_number].enabled;
1000 struct timespec prune_ts;
1001 int to = 0;
1002 char buf[256];
1004 if (run_prune)
1006 setup_thread (&dbs[my_number]);
1008 /* We are running. */
1009 dbs[my_number].head->timestamp = time (NULL);
1011 if (clock_gettime (timeout_clock, &prune_ts) == -1)
1012 /* Should never happen. */
1013 abort ();
1015 /* Compute timeout time. */
1016 prune_ts.tv_sec += CACHE_PRUNE_INTERVAL;
1019 /* Initial locking. */
1020 pthread_mutex_lock (&readylist_lock);
1022 /* One more thread available. */
1023 ++nready;
1025 while (1)
1027 while (readylist == NULL)
1029 if (run_prune)
1031 /* Wait, but not forever. */
1032 to = pthread_cond_timedwait (&readylist_cond, &readylist_lock,
1033 &prune_ts);
1035 /* If we were woken and there is no work to be done,
1036 just start pruning. */
1037 if (readylist == NULL && to == ETIMEDOUT)
1039 --nready;
1040 pthread_mutex_unlock (&readylist_lock);
1041 goto only_prune;
1044 else
1045 /* No need to timeout. */
1046 pthread_cond_wait (&readylist_cond, &readylist_lock);
1049 struct fdlist *it = readylist->next;
1050 if (readylist->next == readylist)
1051 /* Just one entry on the list. */
1052 readylist = NULL;
1053 else
1054 readylist->next = it->next;
1056 /* Extract the information and mark the record ready to be used
1057 again. */
1058 int fd = it->fd;
1059 it->next = NULL;
1061 /* One more thread available. */
1062 --nready;
1064 /* We are done with the list. */
1065 pthread_mutex_unlock (&readylist_lock);
1067 /* We do not want to block on a short read or so. */
1068 int fl = fcntl (fd, F_GETFL);
1069 if (fl == -1 || fcntl (fd, F_SETFL, fl | O_NONBLOCK) == -1)
1070 goto close_and_out;
1072 /* Now read the request. */
1073 request_header req;
1074 if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd, &req, sizeof (req)))
1075 != sizeof (req), 0))
1077 /* We failed to read data. Note that this also might mean we
1078 failed because we would have blocked. */
1079 if (debug_level > 0)
1080 dbg_log (_("short read while reading request: %s"),
1081 strerror_r (errno, buf, sizeof (buf)));
1082 goto close_and_out;
1085 /* Check whether this is a valid request type. */
1086 if (req.type < GETPWBYNAME || req.type >= LASTREQ)
1087 goto close_and_out;
1089 /* Some systems have no SO_PEERCRED implementation. They don't
1090 care about security so we don't as well. */
1091 uid_t uid = -1;
1092 #ifdef SO_PEERCRED
1093 pid_t pid = 0;
1095 if (secure_in_use)
1097 struct ucred caller;
1098 socklen_t optlen = sizeof (caller);
1100 if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) < 0)
1102 dbg_log (_("error getting callers id: %s"),
1103 strerror_r (errno, buf, sizeof (buf)));
1104 goto close_and_out;
1107 if (req.type < GETPWBYNAME || req.type > LASTDBREQ
1108 || serv2db[req.type]->secure)
1109 uid = caller.uid;
1111 pid = caller.pid;
1113 else if (__builtin_expect (debug_level > 0, 0))
1115 struct ucred caller;
1116 socklen_t optlen = sizeof (caller);
1118 if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) == 0)
1119 pid = caller.pid;
1121 #endif
1123 /* It should not be possible to crash the nscd with a silly
1124 request (i.e., a terribly large key). We limit the size to 1kb. */
1125 #define MAXKEYLEN 1024
1126 if (__builtin_expect (req.key_len, 1) < 0
1127 || __builtin_expect (req.key_len, 1) > MAXKEYLEN)
1129 if (debug_level > 0)
1130 dbg_log (_("key length in request too long: %d"), req.key_len);
1132 else
1134 /* Get the key. */
1135 char keybuf[MAXKEYLEN];
1137 if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd, keybuf,
1138 req.key_len))
1139 != req.key_len, 0))
1141 /* Again, this can also mean we would have blocked. */
1142 if (debug_level > 0)
1143 dbg_log (_("short read while reading request key: %s"),
1144 strerror_r (errno, buf, sizeof (buf)));
1145 goto close_and_out;
1148 if (__builtin_expect (debug_level, 0) > 0)
1150 #ifdef SO_PEERCRED
1151 if (pid != 0)
1152 dbg_log (_("\
1153 handle_request: request received (Version = %d) from PID %ld"),
1154 req.version, (long int) pid);
1155 else
1156 #endif
1157 dbg_log (_("\
1158 handle_request: request received (Version = %d)"), req.version);
1161 /* Phew, we got all the data, now process it. */
1162 handle_request (fd, &req, keybuf, uid);
1165 close_and_out:
1166 /* We are done. */
1167 close (fd);
1169 /* Check whether we should be pruning the cache. */
1170 assert (run_prune || to == 0);
1171 if (to == ETIMEDOUT)
1173 only_prune:
1174 /* The pthread_cond_timedwait() call timed out. It is time
1175 to clean up the cache. */
1176 assert (my_number < lastdb);
1177 prune_cache (&dbs[my_number],
1178 prune_ts.tv_sec + (prune_ts.tv_nsec >= 500000000));
1180 if (clock_gettime (timeout_clock, &prune_ts) == -1)
1181 /* Should never happen. */
1182 abort ();
1184 /* Compute next timeout time. */
1185 prune_ts.tv_sec += CACHE_PRUNE_INTERVAL;
1187 /* In case the list is emtpy we do not want to run the prune
1188 code right away again. */
1189 to = 0;
1192 /* Re-locking. */
1193 pthread_mutex_lock (&readylist_lock);
1195 /* One more thread available. */
1196 ++nready;
1201 static unsigned int nconns;
1203 static void
1204 fd_ready (int fd)
1206 pthread_mutex_lock (&readylist_lock);
1208 /* Find an empty entry in FDLIST. */
1209 size_t inner;
1210 for (inner = 0; inner < nconns; ++inner)
1211 if (fdlist[inner].next == NULL)
1212 break;
1213 assert (inner < nconns);
1215 fdlist[inner].fd = fd;
1217 if (readylist == NULL)
1218 readylist = fdlist[inner].next = &fdlist[inner];
1219 else
1221 fdlist[inner].next = readylist->next;
1222 readylist = readylist->next = &fdlist[inner];
1225 bool do_signal = true;
1226 if (__builtin_expect (nready == 0, 0))
1228 ++client_queued;
1229 do_signal = false;
1231 /* Try to start another thread to help out. */
1232 pthread_t th;
1233 if (nthreads < max_nthreads
1234 && pthread_create (&th, &attr, nscd_run,
1235 (void *) (long int) nthreads) == 0)
1237 /* We got another thread. */
1238 ++nthreads;
1239 /* The new thread might new a kick. */
1240 do_signal = true;
1245 pthread_mutex_unlock (&readylist_lock);
1247 /* Tell one of the worker threads there is work to do. */
1248 if (do_signal)
1249 pthread_cond_signal (&readylist_cond);
1253 /* Check whether restarting should happen. */
1254 static inline int
1255 restart_p (time_t now)
1257 return (paranoia && readylist == NULL && nready == nthreads
1258 && now >= restart_time);
1262 /* Array for times a connection was accepted. */
1263 static time_t *starttime;
1266 static void
1267 __attribute__ ((__noreturn__))
1268 main_loop_poll (void)
1270 struct pollfd *conns = (struct pollfd *) xmalloc (nconns
1271 * sizeof (conns[0]));
1273 conns[0].fd = sock;
1274 conns[0].events = POLLRDNORM;
1275 size_t nused = 1;
1276 size_t firstfree = 1;
1278 while (1)
1280 /* Wait for any event. We wait at most a couple of seconds so
1281 that we can check whether we should close any of the accepted
1282 connections since we have not received a request. */
1283 #define MAX_ACCEPT_TIMEOUT 30
1284 #define MIN_ACCEPT_TIMEOUT 5
1285 #define MAIN_THREAD_TIMEOUT \
1286 (MAX_ACCEPT_TIMEOUT * 1000 \
1287 - ((MAX_ACCEPT_TIMEOUT - MIN_ACCEPT_TIMEOUT) * 1000 * nused) / (2 * nconns))
1289 int n = poll (conns, nused, MAIN_THREAD_TIMEOUT);
1291 time_t now = time (NULL);
1293 /* If there is a descriptor ready for reading or there is a new
1294 connection, process this now. */
1295 if (n > 0)
1297 if (conns[0].revents != 0)
1299 /* We have a new incoming connection. Accept the connection. */
1300 int fd = TEMP_FAILURE_RETRY (accept (sock, NULL, NULL));
1302 /* use the descriptor if we have not reached the limit. */
1303 if (fd >= 0 && firstfree < nconns)
1305 conns[firstfree].fd = fd;
1306 conns[firstfree].events = POLLRDNORM;
1307 starttime[firstfree] = now;
1308 if (firstfree >= nused)
1309 nused = firstfree + 1;
1312 ++firstfree;
1313 while (firstfree < nused && conns[firstfree].fd != -1);
1316 --n;
1319 for (size_t cnt = 1; cnt < nused && n > 0; ++cnt)
1320 if (conns[cnt].revents != 0)
1322 fd_ready (conns[cnt].fd);
1324 /* Clean up the CONNS array. */
1325 conns[cnt].fd = -1;
1326 if (cnt < firstfree)
1327 firstfree = cnt;
1328 if (cnt == nused - 1)
1330 --nused;
1331 while (conns[nused - 1].fd == -1);
1333 --n;
1337 /* Now find entries which have timed out. */
1338 assert (nused > 0);
1340 /* We make the timeout length depend on the number of file
1341 descriptors currently used. */
1342 #define ACCEPT_TIMEOUT \
1343 (MAX_ACCEPT_TIMEOUT \
1344 - ((MAX_ACCEPT_TIMEOUT - MIN_ACCEPT_TIMEOUT) * nused) / nconns)
1345 time_t laststart = now - ACCEPT_TIMEOUT;
1347 for (size_t cnt = nused - 1; cnt > 0; --cnt)
1349 if (conns[cnt].fd != -1 && starttime[cnt] < laststart)
1351 /* Remove the entry, it timed out. */
1352 (void) close (conns[cnt].fd);
1353 conns[cnt].fd = -1;
1355 if (cnt < firstfree)
1356 firstfree = cnt;
1357 if (cnt == nused - 1)
1359 --nused;
1360 while (conns[nused - 1].fd == -1);
1364 if (restart_p (now))
1365 restart ();
1370 #ifdef HAVE_EPOLL
1371 static void
1372 main_loop_epoll (int efd)
1374 struct epoll_event ev = { 0, };
1375 int nused = 1;
1376 size_t highest = 0;
1378 /* Add the socket. */
1379 ev.events = EPOLLRDNORM;
1380 ev.data.fd = sock;
1381 if (epoll_ctl (efd, EPOLL_CTL_ADD, sock, &ev) == -1)
1382 /* We cannot use epoll. */
1383 return;
1385 while (1)
1387 struct epoll_event revs[100];
1388 # define nrevs (sizeof (revs) / sizeof (revs[0]))
1390 int n = epoll_wait (efd, revs, nrevs, MAIN_THREAD_TIMEOUT);
1392 time_t now = time (NULL);
1394 for (int cnt = 0; cnt < n; ++cnt)
1395 if (revs[cnt].data.fd == sock)
1397 /* A new connection. */
1398 int fd = TEMP_FAILURE_RETRY (accept (sock, NULL, NULL));
1400 if (fd >= 0)
1402 /* Try to add the new descriptor. */
1403 ev.data.fd = fd;
1404 if (fd >= nconns
1405 || epoll_ctl (efd, EPOLL_CTL_ADD, fd, &ev) == -1)
1406 /* The descriptor is too large or something went
1407 wrong. Close the descriptor. */
1408 close (fd);
1409 else
1411 /* Remember when we accepted the connection. */
1412 starttime[fd] = now;
1414 if (fd > highest)
1415 highest = fd;
1417 ++nused;
1421 else
1423 /* Remove the descriptor from the epoll descriptor. */
1424 struct epoll_event ev = { 0, };
1425 (void) epoll_ctl (efd, EPOLL_CTL_DEL, revs[cnt].data.fd, &ev);
1427 /* Get a worked to handle the request. */
1428 fd_ready (revs[cnt].data.fd);
1430 /* Reset the time. */
1431 starttime[revs[cnt].data.fd] = 0;
1432 if (revs[cnt].data.fd == highest)
1434 --highest;
1435 while (highest > 0 && starttime[highest] == 0);
1437 --nused;
1440 /* Now look for descriptors for accepted connections which have
1441 no reply in too long of a time. */
1442 time_t laststart = now - ACCEPT_TIMEOUT;
1443 for (int cnt = highest; cnt > STDERR_FILENO; --cnt)
1444 if (cnt != sock && starttime[cnt] != 0 && starttime[cnt] < laststart)
1446 /* We are waiting for this one for too long. Close it. */
1447 struct epoll_event ev = {0, };
1448 (void) epoll_ctl (efd, EPOLL_CTL_DEL, cnt, &ev);
1450 (void) close (cnt);
1452 starttime[cnt] = 0;
1453 if (cnt == highest)
1454 --highest;
1456 else if (cnt != sock && starttime[cnt] == 0 && cnt == highest)
1457 --highest;
1459 if (restart_p (now))
1460 restart ();
1463 #endif
1466 /* Start all the threads we want. The initial process is thread no. 1. */
1467 void
1468 start_threads (void)
1470 /* Initialize the conditional variable we will use. The only
1471 non-standard attribute we might use is the clock selection. */
1472 pthread_condattr_t condattr;
1473 pthread_condattr_init (&condattr);
1475 #if defined _POSIX_CLOCK_SELECTION && _POSIX_CLOCK_SELECTION >= 0 \
1476 && 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
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 #endif
1490 pthread_cond_init (&readylist_cond, &condattr);
1491 pthread_condattr_destroy (&condattr);
1494 /* Create the attribute for the threads. They are all created
1495 detached. */
1496 pthread_attr_init (&attr);
1497 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
1498 /* Use 1MB stacks, twice as much for 64-bit architectures. */
1499 pthread_attr_setstacksize (&attr, 1024 * 1024 * (sizeof (void *) / 4));
1501 /* We allow less than LASTDB threads only for debugging. */
1502 if (debug_level == 0)
1503 nthreads = MAX (nthreads, lastdb);
1505 int nfailed = 0;
1506 for (long int i = 0; i < nthreads; ++i)
1508 pthread_t th;
1509 if (pthread_create (&th, &attr, nscd_run, (void *) (i - nfailed)) != 0)
1510 ++nfailed;
1512 if (nthreads - nfailed < lastdb)
1514 /* We could not start enough threads. */
1515 dbg_log (_("could only start %d threads; terminating"),
1516 nthreads - nfailed);
1517 exit (1);
1520 /* Determine how much room for descriptors we should initially
1521 allocate. This might need to change later if we cap the number
1522 with MAXCONN. */
1523 const long int nfds = sysconf (_SC_OPEN_MAX);
1524 #define MINCONN 32
1525 #define MAXCONN 16384
1526 if (nfds == -1 || nfds > MAXCONN)
1527 nconns = MAXCONN;
1528 else if (nfds < MINCONN)
1529 nconns = MINCONN;
1530 else
1531 nconns = nfds;
1533 /* We need memory to pass descriptors on to the worker threads. */
1534 fdlist = (struct fdlist *) xcalloc (nconns, sizeof (fdlist[0]));
1535 /* Array to keep track when connection was accepted. */
1536 starttime = (time_t *) xcalloc (nconns, sizeof (starttime[0]));
1538 /* In the main thread we execute the loop which handles incoming
1539 connections. */
1540 #ifdef HAVE_EPOLL
1541 int efd = epoll_create (100);
1542 if (efd != -1)
1544 main_loop_epoll (efd);
1545 close (efd);
1547 #endif
1549 main_loop_poll ();
1553 /* Look up the uid, gid, and supplementary groups to run nscd as. When
1554 this function is called, we are not listening on the nscd socket yet so
1555 we can just use the ordinary lookup functions without causing a lockup */
1556 static void
1557 begin_drop_privileges (void)
1559 struct passwd *pwd = getpwnam (server_user);
1561 if (pwd == NULL)
1563 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1564 error (EXIT_FAILURE, 0, _("Failed to run nscd as user '%s'"),
1565 server_user);
1568 server_uid = pwd->pw_uid;
1569 server_gid = pwd->pw_gid;
1571 /* Save the old UID/GID if we have to change back. */
1572 if (paranoia)
1574 old_uid = getuid ();
1575 old_gid = getgid ();
1578 if (getgrouplist (server_user, server_gid, NULL, &server_ngroups) == 0)
1580 /* This really must never happen. */
1581 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1582 error (EXIT_FAILURE, errno, _("initial getgrouplist failed"));
1585 server_groups = (gid_t *) xmalloc (server_ngroups * sizeof (gid_t));
1587 if (getgrouplist (server_user, server_gid, server_groups, &server_ngroups)
1588 == -1)
1590 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1591 error (EXIT_FAILURE, errno, _("getgrouplist failed"));
1596 /* Call setgroups(), setgid(), and setuid() to drop root privileges and
1597 run nscd as the user specified in the configuration file. */
1598 static void
1599 finish_drop_privileges (void)
1601 if (setgroups (server_ngroups, server_groups) == -1)
1603 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1604 error (EXIT_FAILURE, errno, _("setgroups failed"));
1607 if (setgid (server_gid) == -1)
1609 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1610 perror ("setgid");
1611 exit (1);
1614 if (setuid (server_uid) == -1)
1616 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1617 perror ("setuid");
1618 exit (1);