Update copyright dates not handled by scripts/update-copyrights.
[platform/upstream/glibc.git] / nscd / nscd.c
1 /* Copyright (c) 1998-2017 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998.
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published
7    by the Free Software Foundation; version 2 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, see <http://www.gnu.org/licenses/>.  */
17
18 /* nscd - Name Service Cache Daemon. Caches passwd, group, and hosts.  */
19
20 #include <argp.h>
21 #include <assert.h>
22 #include <dirent.h>
23 #include <errno.h>
24 #include <error.h>
25 #include <fcntl.h>
26 #include <libintl.h>
27 #include <locale.h>
28 #include <paths.h>
29 #include <pthread.h>
30 #include <signal.h>
31 #include <stdbool.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <syslog.h>
36 #include <unistd.h>
37 #include <sys/mman.h>
38 #include <sys/socket.h>
39 #include <sys/stat.h>
40 #include <sys/uio.h>
41 #include <sys/un.h>
42 #include <sys/wait.h>
43 #include <stdarg.h>
44
45 #include "dbg_log.h"
46 #include "nscd.h"
47 #include "selinux.h"
48 #include "../nss/nsswitch.h"
49 #include <device-nrs.h>
50 #ifdef HAVE_INOTIFY
51 # include <sys/inotify.h>
52 #endif
53 #include <kernel-features.h>
54
55 /* Get libc version number.  */
56 #include <version.h>
57
58 #define PACKAGE _libc_intl_domainname
59
60 int do_shutdown;
61 int disabled_passwd;
62 int disabled_group;
63
64 typedef enum
65 {
66   /* Running in background as daemon.  */
67   RUN_DAEMONIZE,
68   /* Running in foreground but otherwise behave like a daemon,
69      i.e., detach from terminal and use syslog.  This allows
70      better integration with services like systemd.  */
71   RUN_FOREGROUND,
72   /* Run in foreground in debug mode.  */
73   RUN_DEBUG
74 } run_modes;
75
76 static run_modes run_mode = RUN_DAEMONIZE;
77
78 static const char *conffile = _PATH_NSCDCONF;
79
80 time_t start_time;
81
82 uintptr_t pagesize_m1;
83
84 int paranoia;
85 time_t restart_time;
86 time_t restart_interval = RESTART_INTERVAL;
87 const char *oldcwd;
88 uid_t old_uid;
89 gid_t old_gid;
90
91 static int check_pid (const char *file);
92 static int write_pid (const char *file);
93 static int monitor_child (int fd);
94
95 /* Name and version of program.  */
96 static void print_version (FILE *stream, struct argp_state *state);
97 void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
98
99 /* Function to print some extra text in the help message.  */
100 static char *more_help (int key, const char *text, void *input);
101
102 /* Definitions of arguments for argp functions.  */
103 static const struct argp_option options[] =
104 {
105   { "config-file", 'f', N_("NAME"), 0,
106     N_("Read configuration data from NAME") },
107   { "debug", 'd', NULL, 0,
108     N_("Do not fork and display messages on the current tty") },
109   { "foreground", 'F', NULL, 0,
110     N_("Do not fork, but otherwise behave like a daemon") },
111   { "nthreads", 't', N_("NUMBER"), 0, N_("Start NUMBER threads") },
112   { "shutdown", 'K', NULL, 0, N_("Shut the server down") },
113   { "statistics", 'g', NULL, 0, N_("Print current configuration statistics") },
114   { "invalidate", 'i', N_("TABLE"), 0,
115     N_("Invalidate the specified cache") },
116   { "secure", 'S', N_("TABLE,yes"), OPTION_HIDDEN,
117     N_("Use separate cache for each user")},
118   { NULL, 0, NULL, 0, NULL }
119 };
120
121 /* Short description of program.  */
122 static const char doc[] = N_("Name Service Cache Daemon.");
123
124 /* Prototype for option handler.  */
125 static error_t parse_opt (int key, char *arg, struct argp_state *state);
126
127 /* Data structure to communicate with argp functions.  */
128 static struct argp argp =
129 {
130   options, parse_opt, NULL, doc, NULL, more_help
131 };
132
133 /* True if only statistics are requested.  */
134 static bool get_stats;
135 static int parent_fd = -1;
136
137 int
138 main (int argc, char **argv)
139 {
140   int remaining;
141
142   /* Set locale via LC_ALL.  */
143   setlocale (LC_ALL, "");
144   /* Set the text message domain.  */
145   textdomain (PACKAGE);
146
147   /* Determine if the kernel has SELinux support.  */
148   nscd_selinux_enabled (&selinux_enabled);
149
150   /* Parse and process arguments.  */
151   argp_parse (&argp, argc, argv, 0, &remaining, NULL);
152
153   if (remaining != argc)
154     {
155       error (0, 0, gettext ("wrong number of arguments"));
156       argp_help (&argp, stdout, ARGP_HELP_SEE, program_invocation_short_name);
157       exit (1);
158     }
159
160   /* Read the configuration file.  */
161   if (nscd_parse_file (conffile, dbs) != 0)
162     /* We couldn't read the configuration file.  We don't start the
163        server.  */
164     error (EXIT_FAILURE, 0,
165            _("failure while reading configuration file; this is fatal"));
166
167   /* Do we only get statistics?  */
168   if (get_stats)
169     /* Does not return.  */
170     receive_print_stats ();
171
172   /* Check if we are already running. */
173   if (check_pid (_PATH_NSCDPID))
174     error (EXIT_FAILURE, 0, _("already running"));
175
176   /* Remember when we started.  */
177   start_time = time (NULL);
178
179   /* Determine page size.  */
180   pagesize_m1 = getpagesize () - 1;
181
182   if (run_mode == RUN_DAEMONIZE || run_mode == RUN_FOREGROUND)
183     {
184       int i;
185       pid_t pid;
186
187       /* Behave like a daemon.  */
188       if (run_mode == RUN_DAEMONIZE)
189         {
190           int fd[2];
191
192           if (pipe (fd) != 0)
193             error (EXIT_FAILURE, errno,
194                    _("cannot create a pipe to talk to the child"));
195
196           pid = fork ();
197           if (pid == -1)
198             error (EXIT_FAILURE, errno, _("cannot fork"));
199           if (pid != 0)
200             {
201               /* The parent only reads from the child.  */
202               close (fd[1]);
203               exit (monitor_child (fd[0]));
204             }
205           else
206             {
207               /* The child only writes to the parent.  */
208               close (fd[0]);
209               parent_fd = fd[1];
210             }
211         }
212
213       int nullfd = open (_PATH_DEVNULL, O_RDWR);
214       if (nullfd != -1)
215         {
216           struct stat64 st;
217
218           if (fstat64 (nullfd, &st) == 0 && S_ISCHR (st.st_mode) != 0
219 #if defined DEV_NULL_MAJOR && defined DEV_NULL_MINOR
220               && st.st_rdev == makedev (DEV_NULL_MAJOR, DEV_NULL_MINOR)
221 #endif
222               )
223             {
224               /* It is the /dev/null special device alright.  */
225               (void) dup2 (nullfd, STDIN_FILENO);
226               (void) dup2 (nullfd, STDOUT_FILENO);
227               (void) dup2 (nullfd, STDERR_FILENO);
228
229               if (nullfd > 2)
230                 close (nullfd);
231             }
232           else
233             {
234               /* Ugh, somebody is trying to play a trick on us.  */
235               close (nullfd);
236               nullfd = -1;
237             }
238         }
239       int min_close_fd = nullfd == -1 ? 0 : STDERR_FILENO + 1;
240
241       DIR *d = opendir ("/proc/self/fd");
242       if (d != NULL)
243         {
244           struct dirent64 *dirent;
245           int dfdn = dirfd (d);
246
247           while ((dirent = readdir64 (d)) != NULL)
248             {
249               char *endp;
250               long int fdn = strtol (dirent->d_name, &endp, 10);
251
252               if (*endp == '\0' && fdn != dfdn && fdn >= min_close_fd
253                   && fdn != parent_fd)
254                 close ((int) fdn);
255             }
256
257           closedir (d);
258         }
259       else
260         for (i = min_close_fd; i < getdtablesize (); i++)
261           if (i != parent_fd)
262             close (i);
263
264       setsid ();
265
266       if (chdir ("/") != 0)
267         do_exit (EXIT_FAILURE, errno,
268                  _("cannot change current working directory to \"/\""));
269
270       openlog ("nscd", LOG_CONS | LOG_ODELAY, LOG_DAEMON);
271
272       if (write_pid (_PATH_NSCDPID) < 0)
273         dbg_log ("%s: %s", _PATH_NSCDPID, strerror (errno));
274
275       if (!init_logfile ())
276         dbg_log (_("Could not create log file"));
277
278       /* Ignore job control signals.  */
279       signal (SIGTTOU, SIG_IGN);
280       signal (SIGTTIN, SIG_IGN);
281       signal (SIGTSTP, SIG_IGN);
282     }
283   else
284     /* In debug mode we are not paranoid.  */
285     paranoia = 0;
286
287   signal (SIGINT, termination_handler);
288   signal (SIGQUIT, termination_handler);
289   signal (SIGTERM, termination_handler);
290   signal (SIGPIPE, SIG_IGN);
291
292   /* Cleanup files created by a previous 'bind'.  */
293   unlink (_PATH_NSCDSOCKET);
294
295 #ifdef HAVE_INOTIFY
296   /* Use inotify to recognize changed files.  */
297   inotify_fd = inotify_init1 (IN_NONBLOCK);
298 # ifndef __ASSUME_IN_NONBLOCK
299   if (inotify_fd == -1 && errno == ENOSYS)
300     {
301       inotify_fd = inotify_init ();
302       if (inotify_fd != -1)
303         fcntl (inotify_fd, F_SETFL, O_RDONLY | O_NONBLOCK);
304     }
305 # endif
306 #endif
307
308 #ifdef USE_NSCD
309   /* Make sure we do not get recursive calls.  */
310   __nss_disable_nscd (register_traced_file);
311 #endif
312
313   /* Init databases.  */
314   nscd_init ();
315
316   /* Start the SELinux AVC.  */
317   if (selinux_enabled)
318     nscd_avc_init ();
319
320   /* Handle incoming requests */
321   start_threads ();
322
323   return 0;
324 }
325
326
327 static void __attribute__ ((noreturn))
328 invalidate_db (const char *dbname)
329 {
330   int sock = nscd_open_socket ();
331
332   if (sock == -1)
333     exit (EXIT_FAILURE);
334
335   size_t dbname_len = strlen (dbname) + 1;
336   size_t reqlen = sizeof (request_header) + dbname_len;
337   struct
338   {
339     request_header req;
340     char dbname[];
341   } *reqdata = alloca (reqlen);
342
343   reqdata->req.key_len = dbname_len;
344   reqdata->req.version = NSCD_VERSION;
345   reqdata->req.type = INVALIDATE;
346   memcpy (reqdata->dbname, dbname, dbname_len);
347
348   ssize_t nbytes = TEMP_FAILURE_RETRY (send (sock, reqdata, reqlen,
349                                              MSG_NOSIGNAL));
350
351   if (nbytes != reqlen)
352     {
353       int err = errno;
354       close (sock);
355       error (EXIT_FAILURE, err, _("write incomplete"));
356     }
357
358   /* Wait for ack.  Older nscd just closed the socket when
359      prune_cache finished, silently ignore that.  */
360   int32_t resp = 0;
361   nbytes = TEMP_FAILURE_RETRY (read (sock, &resp, sizeof (resp)));
362   if (nbytes != 0 && nbytes != sizeof (resp))
363     {
364       int err = errno;
365       close (sock);
366       error (EXIT_FAILURE, err, _("cannot read invalidate ACK"));
367     }
368
369   close (sock);
370
371   if (resp != 0)
372     error (EXIT_FAILURE, resp, _("invalidation failed"));
373
374   exit (0);
375 }
376
377 static void __attribute__ ((noreturn))
378 send_shutdown (void)
379 {
380   int sock = nscd_open_socket ();
381
382   if (sock == -1)
383     exit (EXIT_FAILURE);
384
385   request_header req;
386   req.version = NSCD_VERSION;
387   req.type = SHUTDOWN;
388   req.key_len = 0;
389
390   ssize_t nbytes = TEMP_FAILURE_RETRY (send (sock, &req, sizeof req,
391                                              MSG_NOSIGNAL));
392   close (sock);
393   exit (nbytes != sizeof (request_header) ? EXIT_FAILURE : EXIT_SUCCESS);
394 }
395
396 /* Handle program arguments.  */
397 static error_t
398 parse_opt (int key, char *arg, struct argp_state *state)
399 {
400   switch (key)
401     {
402     case 'd':
403       ++debug_level;
404       run_mode = RUN_DEBUG;
405       break;
406
407     case 'F':
408       run_mode = RUN_FOREGROUND;
409       break;
410
411     case 'f':
412       conffile = arg;
413       break;
414
415     case 'K':
416       if (getuid () != 0)
417         error (4, 0, _("Only root is allowed to use this option!"));
418       else
419         send_shutdown ();
420       break;
421
422     case 'g':
423       get_stats = true;
424       break;
425
426     case 'i':
427       {
428         /* Validate the database name.  */
429
430         dbtype cnt;
431         for (cnt = pwddb; cnt < lastdb; ++cnt)
432           if (strcmp (arg, dbnames[cnt]) == 0)
433             break;
434
435         if (cnt == lastdb)
436           {
437             argp_error (state, _("'%s' is not a known database"), arg);
438             return EINVAL;
439           }
440       }
441       if (getuid () != 0)
442         error (4, 0, _("Only root is allowed to use this option!"));
443       else
444         invalidate_db (arg);
445       break;
446
447     case 't':
448       nthreads = atol (arg);
449       break;
450
451     case 'S':
452       error (0, 0, _("secure services not implemented anymore"));
453       break;
454
455     default:
456       return ARGP_ERR_UNKNOWN;
457     }
458
459   return 0;
460 }
461
462 /* Print bug-reporting information in the help message.  */
463 static char *
464 more_help (int key, const char *text, void *input)
465 {
466   switch (key)
467     {
468     case ARGP_KEY_HELP_EXTRA:
469       {
470         /* We print some extra information.  */
471
472         char *tables = xstrdup (dbnames[0]);
473         for (dbtype i = 1; i < lastdb; ++i)
474           {
475             char *more_tables;
476             if (asprintf (&more_tables, "%s %s", tables, dbnames[i]) < 0)
477               more_tables = NULL;
478             free (tables);
479             if (more_tables == NULL)
480               return NULL;
481             tables = more_tables;
482           }
483
484         char *tp;
485         if (asprintf (&tp, gettext ("\
486 Supported tables:\n\
487 %s\n\
488 \n\
489 For bug reporting instructions, please see:\n\
490 %s.\n\
491 "), tables, REPORT_BUGS_TO) < 0)
492           tp = NULL;
493         free (tables);
494         return tp;
495       }
496
497     default:
498       break;
499     }
500
501   return (char *) text;
502 }
503
504 /* Print the version information.  */
505 static void
506 print_version (FILE *stream, struct argp_state *state)
507 {
508   fprintf (stream, "nscd %s%s\n", PKGVERSION, VERSION);
509   fprintf (stream, gettext ("\
510 Copyright (C) %s Free Software Foundation, Inc.\n\
511 This is free software; see the source for copying conditions.  There is NO\n\
512 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
513 "), "2017");
514   fprintf (stream, gettext ("Written by %s.\n"),
515            "Thorsten Kukuk and Ulrich Drepper");
516 }
517
518
519 /* Create a socket connected to a name.  */
520 int
521 nscd_open_socket (void)
522 {
523   struct sockaddr_un addr;
524   int sock;
525
526   sock = socket (PF_UNIX, SOCK_STREAM, 0);
527   if (sock < 0)
528     return -1;
529
530   addr.sun_family = AF_UNIX;
531   assert (sizeof (addr.sun_path) >= sizeof (_PATH_NSCDSOCKET));
532   strcpy (addr.sun_path, _PATH_NSCDSOCKET);
533   if (connect (sock, (struct sockaddr *) &addr, sizeof (addr)) < 0)
534     {
535       close (sock);
536       return -1;
537     }
538
539   return sock;
540 }
541
542
543 /* Cleanup.  */
544 void
545 termination_handler (int signum)
546 {
547   close_sockets ();
548
549   /* Clean up the file created by 'bind'.  */
550   unlink (_PATH_NSCDSOCKET);
551
552   /* Clean up pid file.  */
553   unlink (_PATH_NSCDPID);
554
555   // XXX Terminate threads.
556
557   /* Synchronize memory.  */
558   for (int cnt = 0; cnt < lastdb; ++cnt)
559     {
560       if (!dbs[cnt].enabled || dbs[cnt].head == NULL)
561         continue;
562
563       /* Make sure nobody keeps using the database.  */
564       dbs[cnt].head->timestamp = 0;
565
566       if (dbs[cnt].persistent)
567         // XXX async OK?
568         msync (dbs[cnt].head, dbs[cnt].memsize, MS_ASYNC);
569     }
570
571   _exit (EXIT_SUCCESS);
572 }
573
574 /* Returns 1 if the process in pid file FILE is running, 0 if not.  */
575 static int
576 check_pid (const char *file)
577 {
578   FILE *fp;
579
580   fp = fopen (file, "r");
581   if (fp)
582     {
583       pid_t pid;
584       int n;
585
586       n = fscanf (fp, "%d", &pid);
587       fclose (fp);
588
589       /* If we cannot parse the file default to assuming nscd runs.
590          If the PID is alive, assume it is running.  That all unless
591          the PID is the same as the current process' since tha latter
592          can mean we re-exec.  */
593       if ((n != 1 || kill (pid, 0) == 0) && pid != getpid ())
594         return 1;
595     }
596
597   return 0;
598 }
599
600 /* Write the current process id to the file FILE.
601    Returns 0 if successful, -1 if not.  */
602 static int
603 write_pid (const char *file)
604 {
605   FILE *fp;
606
607   fp = fopen (file, "w");
608   if (fp == NULL)
609     return -1;
610
611   fprintf (fp, "%d\n", getpid ());
612
613   int result = fflush (fp) || ferror (fp) ? -1 : 0;
614
615   fclose (fp);
616
617   return result;
618 }
619
620 static int
621 monitor_child (int fd)
622 {
623   int child_ret = 0;
624   int ret = read (fd, &child_ret, sizeof (child_ret));
625
626   /* The child terminated with an error, either via exit or some other abnormal
627      method, like a segfault.  */
628   if (ret <= 0 || child_ret != 0)
629     {
630       int status;
631       int err = wait (&status);
632
633       if (err < 0)
634         {
635           fprintf (stderr, _("'wait' failed\n"));
636           return 1;
637         }
638
639       if (WIFEXITED (status))
640         {
641           child_ret = WEXITSTATUS (status);
642           fprintf (stderr, _("child exited with status %d\n"), child_ret);
643         }
644       if (WIFSIGNALED (status))
645         {
646           child_ret = WTERMSIG (status);
647           fprintf (stderr, _("child terminated by signal %d\n"), child_ret);
648         }
649     }
650
651   /* We have the child status, so exit with that code.  */
652   close (fd);
653
654   return child_ret;
655 }
656
657 void
658 do_exit (int child_ret, int errnum, const char *format, ...)
659 {
660   if (parent_fd != -1)
661     {
662       int ret __attribute__ ((unused));
663       ret = write (parent_fd, &child_ret, sizeof (child_ret));
664       assert (ret == sizeof (child_ret));
665       close (parent_fd);
666     }
667
668   if (format != NULL)
669     {
670       /* Emulate error() since we don't have a va_list variant for it.  */
671       va_list argp;
672
673       fflush (stdout);
674
675       fprintf (stderr, "%s: ", program_invocation_name);
676
677       va_start (argp, format);
678       vfprintf (stderr, format, argp);
679       va_end (argp);
680
681       fprintf (stderr, ": %s\n", strerror (errnum));
682       fflush (stderr);
683     }
684
685   /* Finally, exit.  */
686   exit (child_ret);
687 }
688
689 void
690 notify_parent (int child_ret)
691 {
692   if (parent_fd == -1)
693     return;
694
695   int ret __attribute__ ((unused));
696   ret = write (parent_fd, &child_ret, sizeof (child_ret));
697   assert (ret == sizeof (child_ret));
698   close (parent_fd);
699   parent_fd = -1;
700 }