Update,
[glibc.git] / nscd / connections.c
blobb658fddb25d2e60152ab7f6df7cc5ccddf172f13
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 <assert.h>
22 #include <atomic.h>
23 #include <error.h>
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <grp.h>
27 #include <libintl.h>
28 #include <pthread.h>
29 #include <pwd.h>
30 #include <resolv.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <arpa/inet.h>
35 #include <sys/mman.h>
36 #include <sys/param.h>
37 #include <sys/poll.h>
38 #include <sys/socket.h>
39 #include <sys/stat.h>
40 #include <sys/un.h>
42 #include "nscd.h"
43 #include "dbg_log.h"
44 #include "selinux.h"
47 /* Number of bytes of data we initially reserve for each hash table bucket. */
48 #define DEFAULT_DATASIZE_PER_BUCKET 1024
51 /* Wrapper functions with error checking for standard functions. */
52 extern void *xmalloc (size_t n);
53 extern void *xcalloc (size_t n, size_t s);
54 extern void *xrealloc (void *o, size_t n);
56 /* Support to run nscd as an unprivileged user */
57 const char *server_user;
58 static uid_t server_uid;
59 static gid_t server_gid;
60 const char *stat_user;
61 uid_t stat_uid;
62 static gid_t *server_groups;
63 #ifndef NGROUPS
64 # define NGROUPS 32
65 #endif
66 static int server_ngroups;
68 static void begin_drop_privileges (void);
69 static void finish_drop_privileges (void);
71 /* Map request type to a string. */
72 const char *serv2str[LASTREQ] =
74 [GETPWBYNAME] = "GETPWBYNAME",
75 [GETPWBYUID] = "GETPWBYUID",
76 [GETGRBYNAME] = "GETGRBYNAME",
77 [GETGRBYGID] = "GETGRBYGID",
78 [GETHOSTBYNAME] = "GETHOSTBYNAME",
79 [GETHOSTBYNAMEv6] = "GETHOSTBYNAMEv6",
80 [GETHOSTBYADDR] = "GETHOSTBYADDR",
81 [GETHOSTBYADDRv6] = "GETHOSTBYADDRv6",
82 [SHUTDOWN] = "SHUTDOWN",
83 [GETSTAT] = "GETSTAT",
84 [INVALIDATE] = "INVALIDATE",
85 [GETFDPW] = "GETFDPW",
86 [GETFDGR] = "GETFDGR",
87 [GETFDHST] = "GETFDHST",
88 [GETAI] = "GETAI",
89 [INITGROUPS] = "INITGROUPS"
92 /* The control data structures for the services. */
93 struct database_dyn dbs[lastdb] =
95 [pwddb] = {
96 .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
97 .enabled = 0,
98 .check_file = 1,
99 .persistent = 0,
100 .shared = 0,
101 .filename = "/etc/passwd",
102 .db_filename = _PATH_NSCD_PASSWD_DB,
103 .disabled_iov = &pwd_iov_disabled,
104 .postimeout = 3600,
105 .negtimeout = 20,
106 .wr_fd = -1,
107 .ro_fd = -1,
108 .mmap_used = false
110 [grpdb] = {
111 .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
112 .enabled = 0,
113 .check_file = 1,
114 .persistent = 0,
115 .shared = 0,
116 .filename = "/etc/group",
117 .db_filename = _PATH_NSCD_GROUP_DB,
118 .disabled_iov = &grp_iov_disabled,
119 .postimeout = 3600,
120 .negtimeout = 60,
121 .wr_fd = -1,
122 .ro_fd = -1,
123 .mmap_used = false
125 [hstdb] = {
126 .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
127 .enabled = 0,
128 .check_file = 1,
129 .persistent = 0,
130 .shared = 0,
131 .filename = "/etc/hosts",
132 .db_filename = _PATH_NSCD_HOSTS_DB,
133 .disabled_iov = &hst_iov_disabled,
134 .postimeout = 3600,
135 .negtimeout = 20,
136 .wr_fd = -1,
137 .ro_fd = -1,
138 .mmap_used = false
143 /* Mapping of request type to database. */
144 static struct database_dyn *const serv2db[LASTREQ] =
146 [GETPWBYNAME] = &dbs[pwddb],
147 [GETPWBYUID] = &dbs[pwddb],
148 [GETGRBYNAME] = &dbs[grpdb],
149 [GETGRBYGID] = &dbs[grpdb],
150 [GETHOSTBYNAME] = &dbs[hstdb],
151 [GETHOSTBYNAMEv6] = &dbs[hstdb],
152 [GETHOSTBYADDR] = &dbs[hstdb],
153 [GETHOSTBYADDRv6] = &dbs[hstdb],
154 [GETFDPW] = &dbs[pwddb],
155 [GETFDGR] = &dbs[grpdb],
156 [GETFDHST] = &dbs[hstdb],
157 [GETAI] = &dbs[hstdb],
158 [INITGROUPS] = &dbs[grpdb]
162 /* Number of seconds between two cache pruning runs. */
163 #define CACHE_PRUNE_INTERVAL 15
166 /* Number of threads to use. */
167 int nthreads = -1;
169 /* Socket for incoming connections. */
170 static int sock;
172 /* Number of times clients had to wait. */
173 unsigned long int client_queued;
176 /* Initialize database information structures. */
177 void
178 nscd_init (void)
180 struct sockaddr_un sock_addr;
181 size_t cnt;
183 /* Secure mode and unprivileged mode are incompatible */
184 if (server_user != NULL && secure_in_use)
186 dbg_log (_("Cannot run nscd in secure mode as unprivileged user"));
187 exit (1);
190 /* Look up unprivileged uid/gid/groups before we start listening on the
191 socket */
192 if (server_user != NULL)
193 begin_drop_privileges ();
195 if (nthreads == -1)
196 /* No configuration for this value, assume a default. */
197 nthreads = 2 * lastdb;
199 for (cnt = 0; cnt < lastdb; ++cnt)
200 if (dbs[cnt].enabled)
202 pthread_rwlock_init (&dbs[cnt].lock, NULL);
203 pthread_mutex_init (&dbs[cnt].memlock, NULL);
205 if (dbs[cnt].persistent)
207 /* Try to open the appropriate file on disk. */
208 int fd = open (dbs[cnt].db_filename, O_RDWR);
209 if (fd != -1)
211 struct stat64 st;
212 void *mem;
213 size_t total;
214 struct database_pers_head head;
215 ssize_t n = TEMP_FAILURE_RETRY (read (fd, &head,
216 sizeof (head)));
217 if (n != sizeof (head) || fstat64 (fd, &st) != 0)
219 fail_db:
220 dbg_log (_("invalid persistent database file \"%s\": %s"),
221 dbs[cnt].db_filename, strerror (errno));
222 dbs[cnt].persistent = 0;
224 else if (head.module == 0 && head.data_size == 0)
226 /* The file has been created, but the head has not been
227 initialized yet. Remove the old file. */
228 unlink (dbs[cnt].db_filename);
230 else if (head.header_size != (int) sizeof (head))
232 dbg_log (_("invalid persistent database file \"%s\": %s"),
233 dbs[cnt].db_filename,
234 _("header size does not match"));
235 dbs[cnt].persistent = 0;
237 else if ((total = (sizeof (head)
238 + roundup (head.module * sizeof (ref_t),
239 ALIGN)
240 + head.data_size))
241 > st.st_size)
243 dbg_log (_("invalid persistent database file \"%s\": %s"),
244 dbs[cnt].db_filename,
245 _("file size does not match"));
246 dbs[cnt].persistent = 0;
248 else if ((mem = mmap (NULL, total, PROT_READ | PROT_WRITE,
249 MAP_SHARED, fd, 0)) == MAP_FAILED)
250 goto fail_db;
251 else
253 /* Success. We have the database. */
254 dbs[cnt].head = mem;
255 dbs[cnt].memsize = total;
256 dbs[cnt].data = (char *)
257 &dbs[cnt].head->array[roundup (dbs[cnt].head->module,
258 ALIGN / sizeof (ref_t))];
259 dbs[cnt].mmap_used = true;
261 if (dbs[cnt].suggested_module > head.module)
262 dbg_log (_("suggested size of table for database %s larger than the persistent database's table"),
263 dbnames[cnt]);
265 dbs[cnt].wr_fd = fd;
266 fd = -1;
267 /* We also need a read-only descriptor. */
268 if (dbs[cnt].shared)
270 dbs[cnt].ro_fd = open (dbs[cnt].db_filename, O_RDONLY);
271 if (dbs[cnt].ro_fd == -1)
272 dbg_log (_("\
273 cannot create read-only descriptor for \"%s\"; no mmap"),
274 dbs[cnt].db_filename);
277 // XXX Shall we test whether the descriptors actually
278 // XXX point to the same file?
281 /* Close the file descriptors in case something went
282 wrong in which case the variable have not been
283 assigned -1. */
284 if (fd != -1)
285 close (fd);
289 if (dbs[cnt].head == NULL)
291 /* No database loaded. Allocate the data structure,
292 possibly on disk. */
293 struct database_pers_head head;
294 size_t total = (sizeof (head)
295 + roundup (dbs[cnt].suggested_module
296 * sizeof (ref_t), ALIGN)
297 + (dbs[cnt].suggested_module
298 * DEFAULT_DATASIZE_PER_BUCKET));
300 /* Try to create the database. If we do not need a
301 persistent database create a temporary file. */
302 int fd;
303 int ro_fd = -1;
304 if (dbs[cnt].persistent)
306 fd = open (dbs[cnt].db_filename,
307 O_RDWR | O_CREAT | O_EXCL | O_TRUNC,
308 S_IRUSR | S_IWUSR);
309 if (fd != -1 && dbs[cnt].shared)
310 ro_fd = open (dbs[cnt].db_filename, O_RDONLY);
312 else
314 size_t slen = strlen (dbs[cnt].db_filename);
315 char fname[slen + 8];
316 strcpy (mempcpy (fname, dbs[cnt].db_filename, slen),
317 ".XXXXXX");
318 fd = mkstemp (fname);
320 /* We do not need the file name anymore after we
321 opened another file descriptor in read-only mode. */
322 if (fd != -1 && dbs[cnt].shared)
324 ro_fd = open (fname, O_RDONLY);
326 unlink (fname);
330 if (fd == -1)
332 if (errno == EEXIST)
334 dbg_log (_("database for %s corrupted or simultaneously used; remove %s manually if necessary and restart"),
335 dbnames[cnt], dbs[cnt].db_filename);
336 // XXX Correct way to terminate?
337 exit (1);
340 if (dbs[cnt].persistent)
341 dbg_log (_("cannot create %s; no persistent database used"),
342 dbs[cnt].db_filename);
343 else
344 dbg_log (_("cannot create %s; no sharing possible"),
345 dbs[cnt].db_filename);
347 dbs[cnt].persistent = 0;
348 // XXX remember: no mmap
350 else
352 /* Tell the user if we could not create the read-only
353 descriptor. */
354 if (ro_fd == -1 && dbs[cnt].shared)
355 dbg_log (_("\
356 cannot create read-only descriptor for \"%s\"; no mmap"),
357 dbs[cnt].db_filename);
359 /* Before we create the header, initialiye the hash
360 table. So that if we get interrupted if writing
361 the header we can recognize a partially initialized
362 database. */
363 size_t ps = sysconf (_SC_PAGESIZE);
364 char tmpbuf[ps];
365 assert (~ENDREF == 0);
366 memset (tmpbuf, '\xff', ps);
368 size_t remaining = dbs[cnt].suggested_module * sizeof (ref_t);
369 off_t offset = sizeof (head);
371 size_t towrite;
372 if (offset % ps != 0)
374 towrite = MIN (remaining, ps - (offset % ps));
375 pwrite (fd, tmpbuf, towrite, offset);
376 offset += towrite;
377 remaining -= towrite;
380 while (remaining > ps)
382 pwrite (fd, tmpbuf, ps, offset);
383 offset += ps;
384 remaining -= ps;
387 if (remaining > 0)
388 pwrite (fd, tmpbuf, remaining, offset);
390 /* Create the header of the file. */
391 struct database_pers_head head =
393 .version = DB_VERSION,
394 .header_size = sizeof (head),
395 .module = dbs[cnt].suggested_module,
396 .data_size = (dbs[cnt].suggested_module
397 * DEFAULT_DATASIZE_PER_BUCKET),
398 .first_free = 0
400 void *mem;
402 if ((TEMP_FAILURE_RETRY (write (fd, &head, sizeof (head)))
403 != sizeof (head))
404 || ftruncate (fd, total) != 0
405 || (mem = mmap (NULL, total, PROT_READ | PROT_WRITE,
406 MAP_SHARED, fd, 0)) == MAP_FAILED)
408 unlink (dbs[cnt].db_filename);
409 dbg_log (_("cannot write to database file %s: %s"),
410 dbs[cnt].db_filename, strerror (errno));
411 dbs[cnt].persistent = 0;
413 else
415 /* Success. */
416 dbs[cnt].head = mem;
417 dbs[cnt].data = (char *)
418 &dbs[cnt].head->array[roundup (dbs[cnt].head->module,
419 ALIGN / sizeof (ref_t))];
420 dbs[cnt].memsize = total;
421 dbs[cnt].mmap_used = true;
423 /* Remember the descriptors. */
424 dbs[cnt].wr_fd = fd;
425 dbs[cnt].ro_fd = ro_fd;
426 fd = -1;
427 ro_fd = -1;
430 if (fd != -1)
431 close (fd);
432 if (ro_fd != -1)
433 close (ro_fd);
437 if (dbs[cnt].head == NULL)
439 /* We do not use the persistent database. Just
440 create an in-memory data structure. */
441 assert (! dbs[cnt].persistent);
443 dbs[cnt].head = xmalloc (sizeof (struct database_pers_head)
444 + (dbs[cnt].suggested_module
445 * sizeof (ref_t)));
446 memset (dbs[cnt].head, '\0', sizeof (dbs[cnt].head));
447 assert (~ENDREF == 0);
448 memset (dbs[cnt].head->array, '\xff',
449 dbs[cnt].suggested_module * sizeof (ref_t));
450 dbs[cnt].head->module = dbs[cnt].suggested_module;
451 dbs[cnt].head->data_size = (DEFAULT_DATASIZE_PER_BUCKET
452 * dbs[cnt].head->module);
453 dbs[cnt].data = xmalloc (dbs[cnt].head->data_size);
454 dbs[cnt].head->first_free = 0;
456 dbs[cnt].shared = 0;
457 assert (dbs[cnt].ro_fd == -1);
460 if (dbs[cnt].check_file)
462 /* We need the modification date of the file. */
463 struct stat st;
465 if (stat (dbs[cnt].filename, &st) < 0)
467 /* We cannot stat() the file, disable file checking. */
468 dbg_log (_("cannot stat() file `%s': %s"),
469 dbs[cnt].filename, strerror (errno));
470 dbs[cnt].check_file = 0;
472 else
473 dbs[cnt].file_mtime = st.st_mtime;
477 /* Create the socket. */
478 sock = socket (AF_UNIX, SOCK_STREAM, 0);
479 if (sock < 0)
481 dbg_log (_("cannot open socket: %s"), strerror (errno));
482 exit (1);
484 /* Bind a name to the socket. */
485 sock_addr.sun_family = AF_UNIX;
486 strcpy (sock_addr.sun_path, _PATH_NSCDSOCKET);
487 if (bind (sock, (struct sockaddr *) &sock_addr, sizeof (sock_addr)) < 0)
489 dbg_log ("%s: %s", _PATH_NSCDSOCKET, strerror (errno));
490 exit (1);
493 /* We don't wait for data otherwise races between threads can get
494 them stuck on accept. */
495 int fl = fcntl (sock, F_GETFL);
496 if (fl != -1)
497 fcntl (sock, F_SETFL, fl | O_NONBLOCK);
499 /* Set permissions for the socket. */
500 chmod (_PATH_NSCDSOCKET, DEFFILEMODE);
502 /* Set the socket up to accept connections. */
503 if (listen (sock, SOMAXCONN) < 0)
505 dbg_log (_("cannot enable socket to accept connections: %s"),
506 strerror (errno));
507 exit (1);
510 /* Change to unprivileged uid/gid/groups if specifed in config file */
511 if (server_user != NULL)
512 finish_drop_privileges ();
516 /* Close the connections. */
517 void
518 close_sockets (void)
520 close (sock);
524 static void
525 invalidate_cache (char *key)
527 dbtype number;
529 if (strcmp (key, "passwd") == 0)
530 number = pwddb;
531 else if (strcmp (key, "group") == 0)
532 number = grpdb;
533 else if (__builtin_expect (strcmp (key, "hosts"), 0) == 0)
535 number = hstdb;
537 /* Re-initialize the resolver. resolv.conf might have changed. */
538 res_init ();
540 else
541 return;
543 if (dbs[number].enabled)
544 prune_cache (&dbs[number], LONG_MAX);
548 #ifdef SCM_RIGHTS
549 static void
550 send_ro_fd (struct database_dyn *db, char *key, int fd)
552 /* If we do not have an read-only file descriptor do nothing. */
553 if (db->ro_fd == -1)
554 return;
556 /* We need to send some data along with the descriptor. */
557 struct iovec iov[1];
558 iov[0].iov_base = key;
559 iov[0].iov_len = strlen (key) + 1;
561 /* Prepare the control message to transfer the descriptor. */
562 char buf[CMSG_SPACE (sizeof (int))];
563 struct msghdr msg = { .msg_iov = iov, .msg_iovlen = 1,
564 .msg_control = buf, .msg_controllen = sizeof (buf) };
565 struct cmsghdr *cmsg = CMSG_FIRSTHDR (&msg);
567 cmsg->cmsg_level = SOL_SOCKET;
568 cmsg->cmsg_type = SCM_RIGHTS;
569 cmsg->cmsg_len = CMSG_LEN (sizeof (int));
571 *(int *) CMSG_DATA (cmsg) = db->ro_fd;
573 msg.msg_controllen = cmsg->cmsg_len;
575 /* Send the control message. We repeat when we are interrupted but
576 everything else is ignored. */
577 (void) TEMP_FAILURE_RETRY (sendmsg (fd, &msg, 0));
579 if (__builtin_expect (debug_level > 0, 0))
580 dbg_log (_("provide access to FD %d, for %s"), db->ro_fd, key);
582 #endif /* SCM_RIGHTS */
585 /* Handle new request. */
586 static void
587 handle_request (int fd, request_header *req, void *key, uid_t uid)
589 if (__builtin_expect (req->version, NSCD_VERSION) != NSCD_VERSION)
591 if (debug_level > 0)
592 dbg_log (_("\
593 cannot handle old request version %d; current version is %d"),
594 req->version, NSCD_VERSION);
595 return;
598 /* Make the SELinux check before we go on to the standard checks. We
599 need to verify that the request type is valid, since it has not
600 yet been checked at this point. */
601 if (selinux_enabled
602 && __builtin_expect (req->type, GETPWBYNAME) >= GETPWBYNAME
603 && __builtin_expect (req->type, LASTREQ) < LASTREQ
604 && nscd_request_avc_has_perm (fd, req->type) != 0)
605 return;
607 struct database_dyn *db = serv2db[req->type];
609 // XXX Clean up so that each new command need not introduce a
610 // XXX new conditional.
611 if ((__builtin_expect (req->type, GETPWBYNAME) >= GETPWBYNAME
612 && __builtin_expect (req->type, LASTDBREQ) <= LASTDBREQ)
613 || req->type == GETAI || req->type == INITGROUPS)
615 if (__builtin_expect (debug_level, 0) > 0)
617 if (req->type == GETHOSTBYADDR || req->type == GETHOSTBYADDRv6)
619 char buf[INET6_ADDRSTRLEN];
621 dbg_log ("\t%s (%s)", serv2str[req->type],
622 inet_ntop (req->type == GETHOSTBYADDR
623 ? AF_INET : AF_INET6,
624 key, buf, sizeof (buf)));
626 else
627 dbg_log ("\t%s (%s)", serv2str[req->type], (char *) key);
630 /* Is this service enabled? */
631 if (!db->enabled)
633 /* No, sent the prepared record. */
634 if (TEMP_FAILURE_RETRY (write (fd, db->disabled_iov->iov_base,
635 db->disabled_iov->iov_len))
636 != (ssize_t) db->disabled_iov->iov_len
637 && __builtin_expect (debug_level, 0) > 0)
639 /* We have problems sending the result. */
640 char buf[256];
641 dbg_log (_("cannot write result: %s"),
642 strerror_r (errno, buf, sizeof (buf)));
645 return;
648 /* Be sure we can read the data. */
649 if (__builtin_expect (pthread_rwlock_tryrdlock (&db->lock) != 0, 0))
651 ++db->head->rdlockdelayed;
652 pthread_rwlock_rdlock (&db->lock);
655 /* See whether we can handle it from the cache. */
656 struct datahead *cached;
657 cached = (struct datahead *) cache_search (req->type, key, req->key_len,
658 db, uid);
659 if (cached != NULL)
661 /* Hurray it's in the cache. */
662 if (TEMP_FAILURE_RETRY (write (fd, cached->data, cached->recsize))
663 != cached->recsize
664 && __builtin_expect (debug_level, 0) > 0)
666 /* We have problems sending the result. */
667 char buf[256];
668 dbg_log (_("cannot write result: %s"),
669 strerror_r (errno, buf, sizeof (buf)));
672 pthread_rwlock_unlock (&db->lock);
674 return;
677 pthread_rwlock_unlock (&db->lock);
679 else if (__builtin_expect (debug_level, 0) > 0)
681 if (req->type == INVALIDATE)
682 dbg_log ("\t%s (%s)", serv2str[req->type], (char *) key);
683 else
684 dbg_log ("\t%s", serv2str[req->type]);
687 /* Handle the request. */
688 switch (req->type)
690 case GETPWBYNAME:
691 addpwbyname (db, fd, req, key, uid);
692 break;
694 case GETPWBYUID:
695 addpwbyuid (db, fd, req, key, uid);
696 break;
698 case GETGRBYNAME:
699 addgrbyname (db, fd, req, key, uid);
700 break;
702 case GETGRBYGID:
703 addgrbygid (db, fd, req, key, uid);
704 break;
706 case GETHOSTBYNAME:
707 addhstbyname (db, fd, req, key, uid);
708 break;
710 case GETHOSTBYNAMEv6:
711 addhstbynamev6 (db, fd, req, key, uid);
712 break;
714 case GETHOSTBYADDR:
715 addhstbyaddr (db, fd, req, key, uid);
716 break;
718 case GETHOSTBYADDRv6:
719 addhstbyaddrv6 (db, fd, req, key, uid);
720 break;
722 case GETAI:
723 addhstai (db, fd, req, key, uid);
724 break;
726 case INITGROUPS:
727 addinitgroups (db, fd, req, key, uid);
728 break;
730 case GETSTAT:
731 case SHUTDOWN:
732 case INVALIDATE:
733 if (! secure_in_use)
735 /* Get the callers credentials. */
736 #ifdef SO_PEERCRED
737 struct ucred caller;
738 socklen_t optlen = sizeof (caller);
740 if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) < 0)
742 char buf[256];
744 dbg_log (_("error getting callers id: %s"),
745 strerror_r (errno, buf, sizeof (buf)));
746 break;
749 uid = caller.uid;
750 #else
751 /* Some systems have no SO_PEERCRED implementation. They don't
752 care about security so we don't as well. */
753 uid = 0;
754 #endif
757 /* Accept shutdown, getstat and invalidate only from root. For
758 the stat call also allow the user specified in the config file. */
759 if (req->type == GETSTAT)
761 if (uid == 0 || uid == stat_uid)
762 send_stats (fd, dbs);
764 else if (uid == 0)
766 if (req->type == INVALIDATE)
767 invalidate_cache (key);
768 else
769 termination_handler (0);
771 break;
773 case GETFDPW:
774 case GETFDGR:
775 case GETFDHST:
776 #ifdef SCM_RIGHTS
777 send_ro_fd (serv2db[req->type], key, fd);
778 #endif
779 break;
781 default:
782 /* Ignore the command, it's nothing we know. */
783 break;
788 /* List of file descriptors. */
789 struct fdlist
791 int fd;
792 struct fdlist *next;
794 /* Memory allocated for the list. */
795 static struct fdlist *fdlist;
796 /* List of currently ready-to-read file descriptors. */
797 static struct fdlist *readylist;
799 /* Conditional variable and mutex to signal availability of entries in
800 READYLIST. The condvar is initialized dynamically since we might
801 use a different clock depending on availability. */
802 static pthread_cond_t readylist_cond;
803 static pthread_mutex_t readylist_lock = PTHREAD_MUTEX_INITIALIZER;
805 /* The clock to use with the condvar. */
806 static clockid_t timeout_clock = CLOCK_REALTIME;
808 /* Number of threads ready to handle the READYLIST. */
809 static unsigned long int nready;
812 /* This is the main loop. It is replicated in different threads but the
813 `poll' call makes sure only one thread handles an incoming connection. */
814 static void *
815 __attribute__ ((__noreturn__))
816 nscd_run (void *p)
818 const long int my_number = (long int) p;
819 const int run_prune = my_number < lastdb && dbs[my_number].enabled;
820 struct timespec prune_ts;
821 int to = 0;
822 char buf[256];
824 if (run_prune)
826 setup_thread (&dbs[my_number]);
828 /* We are running. */
829 dbs[my_number].head->timestamp = time (NULL);
831 if (clock_gettime (timeout_clock, &prune_ts) == -1)
832 /* Should never happen. */
833 abort ();
835 /* Compute timeout time. */
836 prune_ts.tv_sec += CACHE_PRUNE_INTERVAL;
839 /* Initial locking. */
840 pthread_mutex_lock (&readylist_lock);
842 /* One more thread available. */
843 ++nready;
845 while (1)
847 while (readylist == NULL)
849 if (run_prune)
851 /* Wait, but not forever. */
852 to = pthread_cond_timedwait (&readylist_cond, &readylist_lock,
853 &prune_ts);
855 /* If we were woken and there is no work to be done,
856 just start pruning. */
857 if (readylist == NULL && to == ETIMEDOUT)
859 pthread_mutex_unlock (&readylist_lock);
860 goto only_prune;
863 else
864 /* No need to timeout. */
865 pthread_cond_wait (&readylist_cond, &readylist_lock);
868 struct fdlist *it = readylist->next;
869 if (readylist->next == readylist)
870 /* Just one entry on the list. */
871 readylist = NULL;
872 else
873 readylist->next = it->next;
875 /* Extract the information and mark the record ready to be used
876 again. */
877 int fd = it->fd;
878 it->next = NULL;
880 /* One more thread available. */
881 --nready;
883 /* We are done with the list. */
884 pthread_mutex_unlock (&readylist_lock);
886 /* We do not want to block on a short read or so. */
887 int fl = fcntl (fd, F_GETFL);
888 if (fl == -1 || fcntl (fd, F_SETFL, fl | O_NONBLOCK) == -1)
889 goto close_and_out;
891 /* Now read the request. */
892 request_header req;
893 if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd, &req, sizeof (req)))
894 != sizeof (req), 0))
896 /* We failed to read data. Note that this also might mean we
897 failed because we would have blocked. */
898 if (debug_level > 0)
899 dbg_log (_("short read while reading request: %s"),
900 strerror_r (errno, buf, sizeof (buf)));
901 goto close_and_out;
904 /* Check whether this is a valid request type. */
905 if (req.type < GETPWBYNAME || req.type >= LASTREQ)
906 goto close_and_out;
908 /* Some systems have no SO_PEERCRED implementation. They don't
909 care about security so we don't as well. */
910 uid_t uid = -1;
911 #ifdef SO_PEERCRED
912 pid_t pid = 0;
914 if (secure_in_use)
916 struct ucred caller;
917 socklen_t optlen = sizeof (caller);
919 if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) < 0)
921 dbg_log (_("error getting callers id: %s"),
922 strerror_r (errno, buf, sizeof (buf)));
923 goto close_and_out;
926 if (req.type < GETPWBYNAME || req.type > LASTDBREQ
927 || serv2db[req.type]->secure)
928 uid = caller.uid;
930 pid = caller.pid;
932 else if (__builtin_expect (debug_level > 0, 0))
934 struct ucred caller;
935 socklen_t optlen = sizeof (caller);
937 if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) == 0)
938 pid = caller.pid;
940 #endif
942 /* It should not be possible to crash the nscd with a silly
943 request (i.e., a terribly large key). We limit the size to 1kb. */
944 #define MAXKEYLEN 1024
945 if (__builtin_expect (req.key_len, 1) < 0
946 || __builtin_expect (req.key_len, 1) > MAXKEYLEN)
948 if (debug_level > 0)
949 dbg_log (_("key length in request too long: %d"), req.key_len);
951 else
953 /* Get the key. */
954 char keybuf[MAXKEYLEN];
956 if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd, keybuf,
957 req.key_len))
958 != req.key_len, 0))
960 /* Again, this can also mean we would have blocked. */
961 if (debug_level > 0)
962 dbg_log (_("short read while reading request key: %s"),
963 strerror_r (errno, buf, sizeof (buf)));
964 goto close_and_out;
967 if (__builtin_expect (debug_level, 0) > 0)
969 #ifdef SO_PEERCRED
970 if (pid != 0)
971 dbg_log (_("\
972 handle_request: request received (Version = %d) from PID %ld"),
973 req.version, (long int) pid);
974 else
975 #endif
976 dbg_log (_("\
977 handle_request: request received (Version = %d)"), req.version);
980 /* Phew, we got all the data, now process it. */
981 handle_request (fd, &req, keybuf, uid);
984 close_and_out:
985 /* We are done. */
986 close (fd);
988 /* Check whether we should be pruning the cache. */
989 assert (run_prune || to == 0);
990 if (to == ETIMEDOUT)
992 only_prune:
993 /* The pthread_cond_timedwait() call timed out. It is time
994 to clean up the cache. */
995 assert (my_number < lastdb);
996 prune_cache (&dbs[my_number],
997 prune_ts.tv_sec + (prune_ts.tv_nsec >= 500000000));
999 if (clock_gettime (timeout_clock, &prune_ts) == -1)
1000 /* Should never happen. */
1001 abort ();
1003 /* Compute next timeout time. */
1004 prune_ts.tv_sec += CACHE_PRUNE_INTERVAL;
1006 /* In case the list is emtpy we do not want to run the prune
1007 code right away again. */
1008 to = 0;
1011 /* Re-locking. */
1012 pthread_mutex_lock (&readylist_lock);
1014 /* One more thread available. */
1015 ++nready;
1020 static void
1021 __attribute__ ((__noreturn__))
1022 main_loop (void)
1024 /* Determine how much room for descriptors we should initially
1025 allocate. This might need to change later if we cap the number
1026 with MAXCONN. */
1027 const long int nfds = sysconf (_SC_OPEN_MAX);
1028 unsigned int nconns;
1029 #define MINCONN 32
1030 #define MAXCONN 16384
1031 if (nfds == -1 || nfds > MAXCONN)
1032 nconns = MAXCONN;
1033 else if (nfds < MINCONN)
1034 nconns = MINCONN;
1035 else
1036 nconns = nfds;
1038 struct pollfd *conns = (struct pollfd *) xmalloc (nconns
1039 * sizeof (conns[0]));
1041 /* We need two mirroring arrays filled with the times the connection
1042 was accepted and a place to pass descriptors on to the worker
1043 threads. We cannot put this in the same data structure as the
1044 CONNS data since CONNS is passed as an array to poll(). */
1045 time_t *starttime = (time_t *) xmalloc (nconns * sizeof (starttime[0]));
1046 fdlist = (struct fdlist *) xcalloc (nconns, sizeof (fdlist[0]));
1048 conns[0].fd = sock;
1049 conns[0].events = POLLRDNORM;
1050 size_t nused = 1;
1051 size_t firstfree = 1;
1053 while (1)
1055 /* Wait for any event. We wait at most a couple of seconds so
1056 that we can check whether we should close any of the accepted
1057 connections since we have not received a request. */
1058 #define MAX_ACCEPT_TIMEOUT 30
1059 #define MIN_ACCEPT_TIMEOUT 5
1060 #define MAIN_THREAD_TIMEOUT \
1061 (MAX_ACCEPT_TIMEOUT * 1000 \
1062 - ((MAX_ACCEPT_TIMEOUT - MIN_ACCEPT_TIMEOUT) * 1000 * nused) / (2 * nconns))
1064 int n = poll (conns, nused, MAIN_THREAD_TIMEOUT);
1066 time_t now = time (NULL);
1068 /* If there is a descriptor ready for reading or there is a new
1069 connection, process this now. */
1070 if (n > 0)
1072 if (conns[0].revents != 0)
1074 /* We have a new incoming connection. Accept the connection. */
1075 int fd = TEMP_FAILURE_RETRY (accept (sock, NULL, NULL));
1077 if (fd >= 0)
1079 /* We have a new file descriptor. Keep it around
1080 and wait until data becomes available. */
1081 if (firstfree == nconns)
1083 // XXX Maybe extend array. For now, reject
1084 close (fd);
1085 goto reject_out;
1088 conns[firstfree].fd = fd;
1089 conns[firstfree].events = POLLRDNORM;
1090 starttime[firstfree] = now;
1091 if (firstfree >= nused)
1092 nused = firstfree + 1;
1095 ++firstfree;
1096 while (firstfree < nused && conns[firstfree].fd != -1);
1099 reject_out:
1100 --n;
1103 for (size_t cnt = 1; cnt < nused && n > 0; ++cnt)
1104 if (conns[cnt].revents != 0)
1106 pthread_mutex_lock (&readylist_lock);
1108 /* Find an empty entry in FDLIST. */
1109 size_t inner;
1110 for (inner = 0; inner < nconns; ++inner)
1111 if (fdlist[inner].next == NULL)
1112 break;
1113 assert (inner < nconns);
1115 fdlist[inner].fd = conns[cnt].fd;
1117 if (readylist == NULL)
1118 readylist = fdlist[inner].next = &fdlist[inner];
1119 else
1121 fdlist[inner].next = readylist->next;
1122 readylist = readylist->next = &fdlist[inner];
1125 bool do_signal = true;
1126 if (__builtin_expect (nready == 0, 0))
1128 ++client_queued;
1129 do_signal = false;
1132 pthread_mutex_unlock (&readylist_lock);
1134 /* Tell one of the worker threads there is work to do. */
1135 if (do_signal)
1136 pthread_cond_signal (&readylist_cond);
1138 /* Clean up the CONNS array. */
1139 conns[cnt].fd = -1;
1140 if (cnt < firstfree)
1141 firstfree = cnt;
1142 if (cnt == nused - 1)
1144 --nused;
1145 while (conns[nused - 1].fd == -1);
1147 --n;
1151 /* Now find entries which have timed out. */
1152 assert (nused > 0);
1153 for (size_t cnt = nused - 1; cnt > 0; --cnt)
1155 /* We make the timeout length depend on the number of file
1156 descriptors currently used. */
1157 #define ACCEPT_TIMEOUT \
1158 (MAX_ACCEPT_TIMEOUT \
1159 - ((MAX_ACCEPT_TIMEOUT - MIN_ACCEPT_TIMEOUT) * nused) / nconns)
1161 time_t laststart = now - ACCEPT_TIMEOUT;
1162 if (conns[cnt].fd != -1 && starttime[cnt] < laststart)
1164 /* Remove the entry, it timed out. */
1165 (void) close (conns[cnt].fd);
1166 conns[cnt].fd = -1;
1168 if (cnt < firstfree)
1169 firstfree = cnt;
1170 if (cnt == nused - 1)
1172 --nused;
1173 while (conns[nused - 1].fd == -1);
1180 /* Start all the threads we want. The initial process is thread no. 1. */
1181 void
1182 start_threads (void)
1184 /* Initialize the conditional variable we will use. The only
1185 non-standard attribute we might use is the clock selection. */
1186 pthread_condattr_t condattr;
1187 pthread_condattr_init (&condattr);
1189 #if _POSIX_CLOCK_SELECTION >= 0 && _POSIX_MONOTONIC_CLOCK >= 0
1190 /* Determine whether the monotonous clock is available. */
1191 struct timespec dummy;
1192 if (clock_getres (CLOCK_MONOTONIC, &dummy) == 0
1193 && pthread_condattr_setclock (&condattr, CLOCK_MONOTONIC) == 0)
1194 timeout_clock = CLOCK_MONOTONIC;
1195 #endif
1197 pthread_cond_init (&readylist_cond, &condattr);
1198 pthread_condattr_destroy (&condattr);
1201 /* Create the attribute for the threads. They are all created
1202 detached. */
1203 pthread_attr_t attr;
1204 pthread_attr_init (&attr);
1205 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
1207 /* We allow less than LASTDB threads only for debugging. */
1208 if (debug_level == 0)
1209 nthreads = MAX (nthreads, lastdb);
1211 for (long int i = 0; i < nthreads; ++i)
1213 pthread_t th;
1214 pthread_create (&th, &attr, nscd_run, (void *) i);
1217 pthread_attr_destroy (&attr);
1219 /* In the main thread we execute the loop which handles incoming
1220 connections. */
1221 main_loop ();
1225 /* Look up the uid, gid, and supplementary groups to run nscd as. When
1226 this function is called, we are not listening on the nscd socket yet so
1227 we can just use the ordinary lookup functions without causing a lockup */
1228 static void
1229 begin_drop_privileges (void)
1231 struct passwd *pwd = getpwnam (server_user);
1233 if (pwd == NULL)
1235 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1236 error (EXIT_FAILURE, 0, _("Failed to run nscd as user '%s'"),
1237 server_user);
1240 server_uid = pwd->pw_uid;
1241 server_gid = pwd->pw_gid;
1243 if (getgrouplist (server_user, server_gid, NULL, &server_ngroups) == 0)
1245 /* This really must never happen. */
1246 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1247 error (EXIT_FAILURE, errno, _("initial getgrouplist failed"));
1250 server_groups = (gid_t *) xmalloc (server_ngroups * sizeof (gid_t));
1252 if (getgrouplist (server_user, server_gid, server_groups, &server_ngroups)
1253 == -1)
1255 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1256 error (EXIT_FAILURE, errno, _("getgrouplist failed"));
1261 /* Call setgroups(), setgid(), and setuid() to drop root privileges and
1262 run nscd as the user specified in the configuration file. */
1263 static void
1264 finish_drop_privileges (void)
1266 if (setgroups (server_ngroups, server_groups) == -1)
1268 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1269 error (EXIT_FAILURE, errno, _("setgroups failed"));
1272 if (setgid (server_gid) == -1)
1274 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1275 perror ("setgid");
1276 exit (1);
1279 if (setuid (server_uid) == -1)
1281 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1282 perror ("setuid");
1283 exit (1);