(CFLAGS-nscd_setup_thread.c): Set to -fpie.
[kopensolaris-gnu/glibc.git] / nscd / connections.c
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.
5
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.
10
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.
15
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.  */
20
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>
41
42 #include "nscd.h"
43 #include "dbg_log.h"
44
45
46 /* Number of bytes of data we initially reserve for each hash table bucket.  */
47 #define DEFAULT_DATASIZE_PER_BUCKET 1024
48
49
50 /* Wrapper functions with error checking for standard functions.  */
51 extern void *xmalloc (size_t n);
52 extern void *xcalloc (size_t n, size_t s);
53 extern void *xrealloc (void *o, size_t n);
54
55 /* Support to run nscd as an unprivileged user */
56 const char *server_user;
57 static uid_t server_uid;
58 static gid_t server_gid;
59 const char *stat_user;
60 uid_t stat_uid;
61 static gid_t *server_groups;
62 #ifndef NGROUPS
63 # define NGROUPS 32
64 #endif
65 static int server_ngroups;
66
67 static void begin_drop_privileges (void);
68 static void finish_drop_privileges (void);
69
70 /* Map request type to a string.  */
71 const char *serv2str[LASTREQ] =
72 {
73   [GETPWBYNAME] = "GETPWBYNAME",
74   [GETPWBYUID] = "GETPWBYUID",
75   [GETGRBYNAME] = "GETGRBYNAME",
76   [GETGRBYGID] = "GETGRBYGID",
77   [GETHOSTBYNAME] = "GETHOSTBYNAME",
78   [GETHOSTBYNAMEv6] = "GETHOSTBYNAMEv6",
79   [GETHOSTBYADDR] = "GETHOSTBYADDR",
80   [GETHOSTBYADDRv6] = "GETHOSTBYADDRv6",
81   [SHUTDOWN] = "SHUTDOWN",
82   [GETSTAT] = "GETSTAT",
83   [INVALIDATE] = "INVALIDATE",
84   [GETFDPW] = "GETFDPW",
85   [GETFDGR] = "GETFDGR",
86   [GETFDHST] = "GETFDHST"
87 };
88
89 /* The control data structures for the services.  */
90 struct database_dyn dbs[lastdb] =
91 {
92   [pwddb] = {
93     .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
94     .enabled = 0,
95     .check_file = 1,
96     .persistent = 0,
97     .shared = 0,
98     .filename = "/etc/passwd",
99     .db_filename = _PATH_NSCD_PASSWD_DB,
100     .disabled_iov = &pwd_iov_disabled,
101     .postimeout = 3600,
102     .negtimeout = 20,
103     .wr_fd = -1,
104     .ro_fd = -1,
105     .mmap_used = false
106   },
107   [grpdb] = {
108     .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
109     .enabled = 0,
110     .check_file = 1,
111     .persistent = 0,
112     .shared = 0,
113     .filename = "/etc/group",
114     .db_filename = _PATH_NSCD_GROUP_DB,
115     .disabled_iov = &grp_iov_disabled,
116     .postimeout = 3600,
117     .negtimeout = 60,
118     .wr_fd = -1,
119     .ro_fd = -1,
120     .mmap_used = false
121   },
122   [hstdb] = {
123     .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
124     .enabled = 0,
125     .check_file = 1,
126     .persistent = 0,
127     .shared = 0,
128     .filename = "/etc/hosts",
129     .db_filename = _PATH_NSCD_HOSTS_DB,
130     .disabled_iov = &hst_iov_disabled,
131     .postimeout = 3600,
132     .negtimeout = 20,
133     .wr_fd = -1,
134     .ro_fd = -1,
135     .mmap_used = false
136   }
137 };
138
139
140 /* Mapping of request type to database.  */
141 static struct database_dyn *const serv2db[LASTREQ] =
142 {
143   [GETPWBYNAME] = &dbs[pwddb],
144   [GETPWBYUID] = &dbs[pwddb],
145   [GETGRBYNAME] = &dbs[grpdb],
146   [GETGRBYGID] = &dbs[grpdb],
147   [GETHOSTBYNAME] = &dbs[hstdb],
148   [GETHOSTBYNAMEv6] = &dbs[hstdb],
149   [GETHOSTBYADDR] = &dbs[hstdb],
150   [GETHOSTBYADDRv6] = &dbs[hstdb],
151   [GETFDPW] = &dbs[pwddb],
152   [GETFDGR] = &dbs[grpdb],
153   [GETFDHST] = &dbs[hstdb],
154 };
155
156
157 /* Number of seconds between two cache pruning runs.  */
158 #define CACHE_PRUNE_INTERVAL    15
159
160
161 /* Number of threads to use.  */
162 int nthreads = -1;
163
164 /* Socket for incoming connections.  */
165 static int sock;
166
167 /* Number of times clients had to wait.  */
168 unsigned long int client_queued;
169
170
171 /* Initialize database information structures.  */
172 void
173 nscd_init (void)
174 {
175   struct sockaddr_un sock_addr;
176   size_t cnt;
177
178   /* Secure mode and unprivileged mode are incompatible */
179   if (server_user != NULL && secure_in_use)
180     {
181       dbg_log (_("Cannot run nscd in secure mode as unprivileged user"));
182       exit (1);
183     }
184
185   /* Look up unprivileged uid/gid/groups before we start listening on the
186      socket  */
187   if (server_user != NULL)
188     begin_drop_privileges ();
189
190   if (nthreads == -1)
191     /* No configuration for this value, assume a default.  */
192     nthreads = 2 * lastdb;
193
194   for (cnt = 0; cnt < lastdb; ++cnt)
195     if (dbs[cnt].enabled)
196       {
197         pthread_rwlock_init (&dbs[cnt].lock, NULL);
198         pthread_mutex_init (&dbs[cnt].memlock, NULL);
199
200         if (dbs[cnt].persistent)
201           {
202             /* Try to open the appropriate file on disk.  */
203             int fd = open (dbs[cnt].db_filename, O_RDWR);
204             if (fd != -1)
205               {
206                 struct stat64 st;
207                 void *mem;
208                 size_t total;
209                 struct database_pers_head head;
210                 ssize_t n = TEMP_FAILURE_RETRY (read (fd, &head,
211                                                       sizeof (head)));
212                 if (n != sizeof (head) || fstat64 (fd, &st) != 0)
213                   {
214                   fail_db:
215                     dbg_log (_("invalid persistent database file \"%s\": %s"),
216                              dbs[cnt].db_filename, strerror (errno));
217                     dbs[cnt].persistent = 0;
218                   }
219                 else if (head.module == 0 && head.data_size == 0)
220                   {
221                     /* The file has been created, but the head has not been
222                        initialized yet.  Remove the old file.  */
223                     unlink (dbs[cnt].db_filename);
224                   }
225                 else if (head.header_size != (int) sizeof (head))
226                   {
227                     dbg_log (_("invalid persistent database file \"%s\": %s"),
228                              dbs[cnt].db_filename,
229                              _("header size does not match"));
230                     dbs[cnt].persistent = 0;
231                   }
232                 else if ((total = (sizeof (head)
233                                    + roundup (head.module * sizeof (ref_t),
234                                               ALIGN)
235                                    + head.data_size))
236                          > st.st_size)
237                   {
238                     dbg_log (_("invalid persistent database file \"%s\": %s"),
239                              dbs[cnt].db_filename,
240                              _("file size does not match"));
241                     dbs[cnt].persistent = 0;
242                   }
243                 else if ((mem = mmap (NULL, total, PROT_READ | PROT_WRITE,
244                                       MAP_SHARED, fd, 0)) == MAP_FAILED)
245                   goto fail_db;
246                 else
247                   {
248                     /* Success.  We have the database.  */
249                     dbs[cnt].head = mem;
250                     dbs[cnt].memsize = total;
251                     dbs[cnt].data = (char *)
252                       &dbs[cnt].head->array[roundup (dbs[cnt].head->module,
253                                                      ALIGN / sizeof (ref_t))];
254                     dbs[cnt].mmap_used = true;
255
256                     if (dbs[cnt].suggested_module > head.module)
257                       dbg_log (_("suggested size of table for database %s larger than the persistent database's table"),
258                                dbnames[cnt]);
259
260                     dbs[cnt].wr_fd = fd;
261                     dbs[cnt].ro_fd = open (dbs[cnt].db_filename, O_RDONLY);
262                     fd = -1;
263                     /* We also need a read-only descriptor.  */
264                     dbs[cnt].ro_fd = open (dbs[cnt].db_filename, O_RDONLY);
265                     if (dbs[cnt].ro_fd == -1)
266                       dbg_log (_("\
267 cannot create read-only descriptor for \"%s\"; no mmap"),
268                                dbs[cnt].db_filename);
269
270                     // XXX Shall we test whether the descriptors actually
271                     // XXX point to the same file?
272                   }
273
274                 /* Close the file descriptors in case something went
275                    wrong in which case the variable have not been
276                    assigned -1.  */
277                 if (fd != -1)
278                   close (fd);
279               }
280           }
281
282         if (dbs[cnt].head == NULL)
283           {
284             /* No database loaded.  Allocate the data structure,
285                possibly on disk.  */
286             struct database_pers_head head;
287             size_t total = (sizeof (head)
288                             + roundup (dbs[cnt].suggested_module
289                                        * sizeof (ref_t), ALIGN)
290                             + (dbs[cnt].suggested_module
291                                * DEFAULT_DATASIZE_PER_BUCKET));
292
293             /* Try to create the database.  If we do not need a
294                persistent database create a temporary file.  */
295             int fd;
296             int ro_fd = -1;
297             if (dbs[cnt].persistent)
298               {
299                 fd = open (dbs[cnt].db_filename,
300                            O_RDWR | O_CREAT | O_EXCL | O_TRUNC,
301                            S_IRUSR | S_IWUSR);
302                 if (fd != -1)
303                   ro_fd = open (dbs[cnt].db_filename, O_RDONLY);
304               }
305             else
306               {
307                 size_t slen = strlen (dbs[cnt].db_filename);
308                 char fname[slen + 8];
309                 strcpy (mempcpy (fname, dbs[cnt].db_filename, slen),
310                         ".XXXXXX");
311                 fd = mkstemp (fname);
312
313                 /* We do not need the file name anymore after we
314                    opened another file descriptor in read-only mode.  */
315                 if (fd != -1)
316                   {
317                     ro_fd = open (fname, O_RDONLY);
318
319                     unlink (fname);
320                   }
321               }
322
323             if (fd == -1)
324               {
325                 if (errno == EEXIST)
326                   {
327                     dbg_log (_("database for %s corrupted or simultaneously used; remove %s manually if necessary and restart"),
328                              dbnames[cnt], dbs[cnt].db_filename);
329                     // XXX Correct way to terminate?
330                     exit (1);
331                   }
332
333                 if  (dbs[cnt].persistent)
334                   dbg_log (_("cannot create %s; no persistent database used"),
335                            dbs[cnt].db_filename);
336                 else
337                   dbg_log (_("cannot create %s; no sharing possible"),
338                            dbs[cnt].db_filename);
339
340                 dbs[cnt].persistent = 0;
341                 // XXX remember: no mmap
342               }
343             else
344               {
345                 /* Tell the user if we could not create the read-only
346                    descriptor.  */
347                 if (ro_fd == -1)
348                   dbg_log (_("\
349 cannot create read-only descriptor for \"%s\"; no mmap"),
350                            dbs[cnt].db_filename);
351
352                 /* Before we create the header, initialiye the hash
353                    table.  So that if we get interrupted if writing
354                    the header we can recognize a partially initialized
355                    database.  */
356                 size_t ps = sysconf (_SC_PAGESIZE);
357                 char tmpbuf[ps];
358                 assert (~ENDREF == 0);
359                 memset (tmpbuf, '\xff', ps);
360
361                 size_t remaining = dbs[cnt].suggested_module * sizeof (ref_t);
362                 off_t offset = sizeof (head);
363
364                 size_t towrite;
365                 if (offset % ps != 0)
366                   {
367                     towrite = MIN (remaining, ps - (offset % ps));
368                     pwrite (fd, tmpbuf, towrite, offset);
369                     offset += towrite;
370                     remaining -= towrite;
371                   }
372
373                 while (remaining > ps)
374                   {
375                     pwrite (fd, tmpbuf, ps, offset);
376                     offset += ps;
377                     remaining -= ps;
378                   }
379
380                 if (remaining > 0)
381                   pwrite (fd, tmpbuf, remaining, offset);
382
383                 /* Create the header of the file.  */
384                 struct database_pers_head head =
385                   {
386                     .version = DB_VERSION,
387                     .header_size = sizeof (head),
388                     .module = dbs[cnt].suggested_module,
389                     .data_size = (dbs[cnt].suggested_module
390                                   * DEFAULT_DATASIZE_PER_BUCKET),
391                     .first_free = 0
392                   };
393                 void *mem;
394
395                 if ((TEMP_FAILURE_RETRY (write (fd, &head, sizeof (head)))
396                      != sizeof (head))
397                     || ftruncate (fd, total) != 0
398                     || (mem = mmap (NULL, total, PROT_READ | PROT_WRITE,
399                                     MAP_SHARED, fd, 0)) == MAP_FAILED)
400                   {
401                     unlink (dbs[cnt].db_filename);
402                     dbg_log (_("cannot write to database file %s: %s"),
403                              dbs[cnt].db_filename, strerror (errno));
404                     dbs[cnt].persistent = 0;
405                   }
406                 else
407                   {
408                     /* Success.  */
409                     dbs[cnt].head = mem;
410                     dbs[cnt].data = (char *)
411                       &dbs[cnt].head->array[roundup (dbs[cnt].head->module,
412                                                      ALIGN / sizeof (ref_t))];
413                     dbs[cnt].memsize = total;
414                     dbs[cnt].mmap_used = true;
415
416                     /* Remember the descriptors.  */
417                     dbs[cnt].wr_fd = fd;
418                     dbs[cnt].ro_fd = ro_fd;
419                     fd = -1;
420                     ro_fd = -1;
421                   }
422
423                 if (fd != -1)
424                   close (fd);
425                 if (ro_fd != -1)
426                   close (ro_fd);
427               }
428           }
429
430         if (dbs[cnt].head == NULL)
431           {
432             /* We do not use the persistent database.  Just
433                create an in-memory data structure.  */
434             assert (! dbs[cnt].persistent);
435
436             dbs[cnt].head = xmalloc (sizeof (struct database_pers_head)
437                                      + (dbs[cnt].suggested_module
438                                         * sizeof (ref_t)));
439             memset (dbs[cnt].head, '\0', sizeof (dbs[cnt].head));
440             assert (~ENDREF == 0);
441             memset (dbs[cnt].head->array, '\xff',
442                     dbs[cnt].suggested_module * sizeof (ref_t));
443             dbs[cnt].head->module = dbs[cnt].suggested_module;
444             dbs[cnt].head->data_size = (DEFAULT_DATASIZE_PER_BUCKET
445                                         * dbs[cnt].head->module);
446             dbs[cnt].data = xmalloc (dbs[cnt].head->data_size);
447             dbs[cnt].head->first_free = 0;
448
449             dbs[cnt].shared = 0;
450             assert (dbs[cnt].ro_fd == -1);
451           }
452
453         if (dbs[cnt].check_file)
454           {
455             /* We need the modification date of the file.  */
456             struct stat st;
457
458             if (stat (dbs[cnt].filename, &st) < 0)
459               {
460                 /* We cannot stat() the file, disable file checking.  */
461                 dbg_log (_("cannot stat() file `%s': %s"),
462                          dbs[cnt].filename, strerror (errno));
463                 dbs[cnt].check_file = 0;
464               }
465             else
466               dbs[cnt].file_mtime = st.st_mtime;
467           }
468       }
469
470   /* Create the socket.  */
471   sock = socket (AF_UNIX, SOCK_STREAM, 0);
472   if (sock < 0)
473     {
474       dbg_log (_("cannot open socket: %s"), strerror (errno));
475       exit (1);
476     }
477   /* Bind a name to the socket.  */
478   sock_addr.sun_family = AF_UNIX;
479   strcpy (sock_addr.sun_path, _PATH_NSCDSOCKET);
480   if (bind (sock, (struct sockaddr *) &sock_addr, sizeof (sock_addr)) < 0)
481     {
482       dbg_log ("%s: %s", _PATH_NSCDSOCKET, strerror (errno));
483       exit (1);
484     }
485
486   /* We don't wait for data otherwise races between threads can get
487      them stuck on accept.  */
488   int fl = fcntl (sock, F_GETFL);
489   if (fl != -1)
490     fcntl (sock, F_SETFL, fl | O_NONBLOCK);
491
492   /* Set permissions for the socket.  */
493   chmod (_PATH_NSCDSOCKET, DEFFILEMODE);
494
495   /* Set the socket up to accept connections.  */
496   if (listen (sock, SOMAXCONN) < 0)
497     {
498       dbg_log (_("cannot enable socket to accept connections: %s"),
499                strerror (errno));
500       exit (1);
501     }
502
503   /* Change to unprivileged uid/gid/groups if specifed in config file */
504   if (server_user != NULL)
505     finish_drop_privileges ();
506 }
507
508
509 /* Close the connections.  */
510 void
511 close_sockets (void)
512 {
513   close (sock);
514 }
515
516
517 static void
518 invalidate_cache (char *key)
519 {
520   dbtype number;
521
522   if (strcmp (key, "passwd") == 0)
523     number = pwddb;
524   else if (strcmp (key, "group") == 0)
525     number = grpdb;
526   else if (__builtin_expect (strcmp (key, "hosts"), 0) == 0)
527     {
528       number = hstdb;
529
530       /* Re-initialize the resolver.  resolv.conf might have changed.  */
531       res_init ();
532     }
533   else
534     return;
535
536   if (dbs[number].enabled)
537     prune_cache (&dbs[number], LONG_MAX);
538 }
539
540
541 #ifdef SCM_RIGHTS
542 static void
543 send_ro_fd (struct database_dyn *db, char *key, int fd)
544 {
545   /* If we do not have an read-only file descriptor do nothing.  */
546   if (db->ro_fd == -1)
547     return;
548
549   /* We need to send some data along with the descriptor.  */
550   struct iovec iov[1];
551   iov[0].iov_base = key;
552   iov[0].iov_len = strlen (key) + 1;
553
554   /* Prepare the control message to transfer the descriptor.  */
555   char buf[CMSG_SPACE (sizeof (int))];
556   struct msghdr msg = { .msg_iov = iov, .msg_iovlen = 1,
557                         .msg_control = buf, .msg_controllen = sizeof (buf) };
558   struct cmsghdr *cmsg = CMSG_FIRSTHDR (&msg);
559
560   cmsg->cmsg_level = SOL_SOCKET;
561   cmsg->cmsg_type = SCM_RIGHTS;
562   cmsg->cmsg_len = CMSG_LEN (sizeof (int));
563
564   *(int *) CMSG_DATA (cmsg) = db->ro_fd;
565
566   msg.msg_controllen = cmsg->cmsg_len;
567
568   /* Send the control message.  We repeat when we are interrupted but
569      everything else is ignored.  */
570   (void) TEMP_FAILURE_RETRY (sendmsg (fd, &msg, 0));
571
572   if (__builtin_expect (debug_level > 0, 0))
573     dbg_log (_("provide access to FD %d, for %s"), db->ro_fd, key);
574 }
575 #endif  /* SCM_RIGHTS */
576
577
578 /* Handle new request.  */
579 static void
580 handle_request (int fd, request_header *req, void *key, uid_t uid)
581 {
582   if (__builtin_expect (req->version, NSCD_VERSION) != NSCD_VERSION)
583     {
584       if (debug_level > 0)
585         dbg_log (_("\
586 cannot handle old request version %d; current version is %d"),
587                  req->version, NSCD_VERSION);
588       return;
589     }
590
591   struct database_dyn *db = serv2db[req->type];
592
593   if (__builtin_expect (req->type, GETPWBYNAME) >= GETPWBYNAME
594       && __builtin_expect (req->type, LASTDBREQ) <= LASTDBREQ)
595     {
596       if (__builtin_expect (debug_level, 0) > 0)
597         {
598           if (req->type == GETHOSTBYADDR || req->type == GETHOSTBYADDRv6)
599             {
600               char buf[INET6_ADDRSTRLEN];
601
602               dbg_log ("\t%s (%s)", serv2str[req->type],
603                        inet_ntop (req->type == GETHOSTBYADDR
604                                   ? AF_INET : AF_INET6,
605                                   key, buf, sizeof (buf)));
606             }
607           else
608             dbg_log ("\t%s (%s)", serv2str[req->type], (char *) key);
609         }
610
611       /* Is this service enabled?  */
612       if (!db->enabled)
613         {
614           /* No, sent the prepared record.  */
615           if (TEMP_FAILURE_RETRY (write (fd, db->disabled_iov->iov_base,
616                                          db->disabled_iov->iov_len))
617               != (ssize_t) db->disabled_iov->iov_len
618               && __builtin_expect (debug_level, 0) > 0)
619             {
620               /* We have problems sending the result.  */
621               char buf[256];
622               dbg_log (_("cannot write result: %s"),
623                        strerror_r (errno, buf, sizeof (buf)));
624             }
625
626           return;
627         }
628
629       /* Be sure we can read the data.  */
630       if (__builtin_expect (pthread_rwlock_tryrdlock (&db->lock) != 0, 0))
631         {
632           ++db->head->rdlockdelayed;
633           pthread_rwlock_rdlock (&db->lock);
634         }
635
636       /* See whether we can handle it from the cache.  */
637       struct datahead *cached;
638       cached = (struct datahead *) cache_search (req->type, key, req->key_len,
639                                                  db, uid);
640       if (cached != NULL)
641         {
642           /* Hurray it's in the cache.  */
643           if (TEMP_FAILURE_RETRY (write (fd, cached->data, cached->recsize))
644               != cached->recsize
645               && __builtin_expect (debug_level, 0) > 0)
646             {
647               /* We have problems sending the result.  */
648               char buf[256];
649               dbg_log (_("cannot write result: %s"),
650                        strerror_r (errno, buf, sizeof (buf)));
651             }
652
653           pthread_rwlock_unlock (&db->lock);
654
655           return;
656         }
657
658       pthread_rwlock_unlock (&db->lock);
659     }
660   else if (__builtin_expect (debug_level, 0) > 0)
661     {
662       if (req->type == INVALIDATE)
663         dbg_log ("\t%s (%s)", serv2str[req->type], (char *) key);
664       else
665         dbg_log ("\t%s", serv2str[req->type]);
666     }
667
668   /* Handle the request.  */
669   switch (req->type)
670     {
671     case GETPWBYNAME:
672       addpwbyname (db, fd, req, key, uid);
673       break;
674
675     case GETPWBYUID:
676       addpwbyuid (db, fd, req, key, uid);
677       break;
678
679     case GETGRBYNAME:
680       addgrbyname (db, fd, req, key, uid);
681       break;
682
683     case GETGRBYGID:
684       addgrbygid (db, fd, req, key, uid);
685       break;
686
687     case GETHOSTBYNAME:
688       addhstbyname (db, fd, req, key, uid);
689       break;
690
691     case GETHOSTBYNAMEv6:
692       addhstbynamev6 (db, fd, req, key, uid);
693       break;
694
695     case GETHOSTBYADDR:
696       addhstbyaddr (db, fd, req, key, uid);
697       break;
698
699     case GETHOSTBYADDRv6:
700       addhstbyaddrv6 (db, fd, req, key, uid);
701       break;
702
703     case GETSTAT:
704     case SHUTDOWN:
705     case INVALIDATE:
706       if (! secure_in_use)
707         {
708           /* Get the callers credentials.  */
709 #ifdef SO_PEERCRED
710           struct ucred caller;
711           socklen_t optlen = sizeof (caller);
712
713           if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) < 0)
714             {
715               char buf[256];
716
717               dbg_log (_("error getting callers id: %s"),
718                        strerror_r (errno, buf, sizeof (buf)));
719               break;
720             }
721
722           uid = caller.uid;
723 #else
724           /* Some systems have no SO_PEERCRED implementation.  They don't
725              care about security so we don't as well.  */
726           uid = 0;
727 #endif
728         }
729
730       /* Accept shutdown, getstat and invalidate only from root.  For
731          the stat call also allow the user specified in the config file.  */
732       if (req->type == GETSTAT)
733         {
734           if (uid == 0 || uid == stat_uid)
735             send_stats (fd, dbs);
736         }
737       else if (uid == 0)
738         {
739           if (req->type == INVALIDATE)
740             invalidate_cache (key);
741           else
742             termination_handler (0);
743         }
744       break;
745
746     case GETFDPW:
747     case GETFDGR:
748     case GETFDHST:
749 #ifdef SCM_RIGHTS
750       send_ro_fd (serv2db[req->type], key, fd);
751 #endif
752       break;
753
754     default:
755       /* Ignore the command, it's nothing we know.  */
756       break;
757     }
758 }
759
760
761 /* This is the main loop.  It is replicated in different threads but the
762    `poll' call makes sure only one thread handles an incoming connection.  */
763 static void *
764 __attribute__ ((__noreturn__))
765 nscd_run (void *p)
766 {
767   long int my_number = (long int) p;
768   struct pollfd conn;
769   int run_prune = my_number < lastdb && dbs[my_number].enabled;
770   time_t next_prune = run_prune ? time (NULL) + CACHE_PRUNE_INTERVAL : 0;
771   static unsigned long int nready;
772
773   if (my_number < lastdb)
774     setup_thread (&dbs[my_number]);
775
776   conn.fd = sock;
777   conn.events = POLLRDNORM;
778
779   while (1)
780     {
781       int nr;
782       time_t now = 0;
783
784       /* One more thread available.  */
785       atomic_increment (&nready);
786
787     no_conn:
788       do
789         {
790           int timeout = -1;
791           if (run_prune)
792             {
793               /* NB: we do not flush the timestamp update using msync since
794                  this value doesnot matter on disk.  */
795               dbs[my_number].head->timestamp = now = time (NULL);
796               timeout = now < next_prune ? 1000 * (next_prune - now) : 0;
797             }
798
799           nr = poll (&conn, 1, timeout);
800
801           if (nr == 0)
802             {
803               /* The `poll' call timed out.  It's time to clean up the
804                  cache.  */
805               atomic_decrement (&nready);
806               assert (my_number < lastdb);
807               prune_cache (&dbs[my_number], time(NULL));
808               now = time (NULL);
809               next_prune = now + CACHE_PRUNE_INTERVAL;
810
811               goto try_get;
812             }
813         }
814       while ((conn.revents & POLLRDNORM) == 0);
815
816     got_data:;
817       /* We have a new incoming connection.  Accept the connection.  */
818       int fd = TEMP_FAILURE_RETRY (accept (conn.fd, NULL, NULL));
819       request_header req;
820       char buf[256];
821       uid_t uid = -1;
822 #ifdef SO_PEERCRED
823       pid_t pid = 0;
824 #endif
825
826       if (__builtin_expect (fd, 0) < 0)
827         {
828           if (errno != EAGAIN && errno != EWOULDBLOCK)
829             dbg_log (_("while accepting connection: %s"),
830                      strerror_r (errno, buf, sizeof (buf)));
831           goto no_conn;
832         }
833
834       /* This thread is busy.  */
835       atomic_decrement (&nready);
836
837       /* Now read the request.  */
838       if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd, &req, sizeof (req)))
839                             != sizeof (req), 0))
840         {
841           if (debug_level > 0)
842             dbg_log (_("short read while reading request: %s"),
843                      strerror_r (errno, buf, sizeof (buf)));
844           close (fd);
845           continue;
846         }
847
848       /* Check whether this is a valid request type.  */
849       if (req.type < GETPWBYNAME || req.type >= LASTREQ)
850         goto close_and_out;
851
852       /* Some systems have no SO_PEERCRED implementation.  They don't
853          care about security so we don't as well.  */
854 #ifdef SO_PEERCRED
855       if (secure_in_use)
856         {
857           struct ucred caller;
858           socklen_t optlen = sizeof (caller);
859
860           if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) < 0)
861             {
862               dbg_log (_("error getting callers id: %s"),
863                        strerror_r (errno, buf, sizeof (buf)));
864               goto close_and_out;
865             }
866
867           if (req.type < GETPWBYNAME || req.type > LASTDBREQ
868               || serv2db[req.type]->secure)
869             uid = caller.uid;
870
871           pid = caller.pid;
872         }
873       else if (__builtin_expect (debug_level > 0, 0))
874         {
875           struct ucred caller;
876           socklen_t optlen = sizeof (caller);
877
878           if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) == 0)
879             pid = caller.pid;
880         }
881 #endif
882
883       /* It should not be possible to crash the nscd with a silly
884          request (i.e., a terribly large key).  We limit the size to 1kb.  */
885       if (__builtin_expect (req.key_len, 1) < 0
886           || __builtin_expect (req.key_len, 1) > 1024)
887         {
888           if (debug_level > 0)
889             dbg_log (_("key length in request too long: %d"), req.key_len);
890         }
891       else
892         {
893           /* Get the key.  */
894           char keybuf[req.key_len];
895
896           if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd, keybuf,
897                                                           req.key_len))
898                                 != req.key_len, 0))
899             {
900               if (debug_level > 0)
901                 dbg_log (_("short read while reading request key: %s"),
902                          strerror_r (errno, buf, sizeof (buf)));
903               close (fd);
904               continue;
905             }
906
907           if (__builtin_expect (debug_level, 0) > 0)
908             {
909 #ifdef SO_PEERCRED
910               if (pid != 0)
911                 dbg_log (_("\
912 handle_request: request received (Version = %d) from PID %ld"),
913                          req.version, (long int) pid);
914               else
915 #endif
916                 dbg_log (_("\
917 handle_request: request received (Version = %d)"), req.version);
918             }
919
920           /* Phew, we got all the data, now process it.  */
921           handle_request (fd, &req, keybuf, uid);
922         }
923
924     close_and_out:
925       /* We are done.  */
926       close (fd);
927
928       /* Just determine whether any data is present.  We do this to
929          measure whether clients are queued up.  */
930     try_get:
931       nr = poll (&conn, 1, 0);
932       if (nr != 0)
933         {
934           if (nready == 0)
935             ++client_queued;
936
937           atomic_increment (&nready);
938
939           goto got_data;
940         }
941     }
942 }
943
944
945 /* Start all the threads we want.  The initial process is thread no. 1.  */
946 void
947 start_threads (void)
948 {
949   long int i;
950   pthread_attr_t attr;
951   pthread_t th;
952
953   pthread_attr_init (&attr);
954   pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
955
956   /* We allow less than LASTDB threads only for debugging.  */
957   if (debug_level == 0)
958     nthreads = MAX (nthreads, lastdb);
959
960   for (i = 1; i < nthreads; ++i)
961     pthread_create (&th, &attr, nscd_run, (void *) i);
962
963   pthread_attr_destroy (&attr);
964
965   nscd_run ((void *) 0);
966 }
967
968
969 /* Look up the uid, gid, and supplementary groups to run nscd as. When
970    this function is called, we are not listening on the nscd socket yet so
971    we can just use the ordinary lookup functions without causing a lockup  */
972 static void
973 begin_drop_privileges (void)
974 {
975   struct passwd *pwd = getpwnam (server_user);
976
977   if (pwd == NULL)
978     {
979       dbg_log (_("Failed to run nscd as user '%s'"), server_user);
980       error (EXIT_FAILURE, 0, _("Failed to run nscd as user '%s'"),
981              server_user);
982     }
983
984   server_uid = pwd->pw_uid;
985   server_gid = pwd->pw_gid;
986
987   if (getgrouplist (server_user, server_gid, NULL, &server_ngroups) == 0)
988     {
989       /* This really must never happen.  */
990       dbg_log (_("Failed to run nscd as user '%s'"), server_user);
991       error (EXIT_FAILURE, errno, _("initial getgrouplist failed"));
992     }
993
994   server_groups = (gid_t *) xmalloc (server_ngroups * sizeof (gid_t));
995
996   if (getgrouplist (server_user, server_gid, server_groups, &server_ngroups)
997       == -1)
998     {
999       dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1000       error (EXIT_FAILURE, errno, _("getgrouplist failed"));
1001     }
1002 }
1003
1004
1005 /* Call setgroups(), setgid(), and setuid() to drop root privileges and
1006    run nscd as the user specified in the configuration file.  */
1007 static void
1008 finish_drop_privileges (void)
1009 {
1010   if (setgroups (server_ngroups, server_groups) == -1)
1011     {
1012       dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1013       error (EXIT_FAILURE, errno, _("setgroups failed"));
1014     }
1015
1016   if (setgid (server_gid) == -1)
1017     {
1018       dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1019       perror ("setgid");
1020       exit (1);
1021     }
1022
1023   if (setuid (server_uid) == -1)
1024     {
1025       dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1026       perror ("setuid");
1027       exit (1);
1028     }
1029 }