Update.
authorUlrich Drepper <drepper@redhat.com>
Sun, 4 May 2003 07:00:44 +0000 (07:00 +0000)
committerUlrich Drepper <drepper@redhat.com>
Sun, 4 May 2003 07:00:44 +0000 (07:00 +0000)
2003-05-03  Ulrich Drepper  <drepper@redhat.com>

* nscd/nscd.c (main): Parse config file right after parsing
parameters.  Then, if get_stats is true, call receive_print_stats.
Drop parameter from nscd_init call.
(get_stats): New variable.
(parse_opt): Set get_stats, don't call receive_print_stats here.
* nscd/nscd.h: Declare dbs, stat_user, and stat_uid.  Adjust nscd_init
prototype.
* nscd/connections.c (stat_user, stat_uid): New variables.
(dbs): Make global.
(nscd_init): Don't read configuration file here.  Drop parameter.
(handle_request): Cleanup handling of non-database lookup requests.
* nscd/nscd_conf.c (nscd_parse_file): Recognize stat-user entry.
Get UID of the specified user.  Use xstrdup instead of strdup.
* nscd/nscd_stat.c (receive_print_stats): Check UID.  If not zero,
check stat_user.
* nscd/Makefile (nscd-modules): Add xstrdup.
* nscd/nscd.conf: Document stat-user entry.

2003-05-03  H.J. Lu  <hongjiu.lu@intel.com>

* sysdeps/unix/sysv/linux/ia64/sysdep.h (__NR_semtimedop): Define
if not defined.

ChangeLog
nscd/Makefile
nscd/connections.c
nscd/nscd.c
nscd/nscd.conf
nscd/nscd.h
nscd/nscd_conf.c
nscd/nscd_stat.c
sysdeps/unix/sysv/linux/ia64/sysdep.h

index 70f69a6..84181de 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+2003-05-03  Ulrich Drepper  <drepper@redhat.com>
+
+       * nscd/nscd.c (main): Parse config file right after parsing
+       parameters.  Then, if get_stats is true, call receive_print_stats.
+       Drop parameter from nscd_init call.
+       (get_stats): New variable.
+       (parse_opt): Set get_stats, don't call receive_print_stats here.
+       * nscd/nscd.h: Declare dbs, stat_user, and stat_uid.  Adjust nscd_init
+       prototype.
+       * nscd/connections.c (stat_user, stat_uid): New variables.
+       (dbs): Make global.
+       (nscd_init): Don't read configuration file here.  Drop parameter.
+       (handle_request): Cleanup handling of non-database lookup requests.
+       * nscd/nscd_conf.c (nscd_parse_file): Recognize stat-user entry.
+       Get UID of the specified user.  Use xstrdup instead of strdup.
+       * nscd/nscd_stat.c (receive_print_stats): Check UID.  If not zero,
+       check stat_user.
+       * nscd/Makefile (nscd-modules): Add xstrdup.
+       * nscd/nscd.conf: Document stat-user entry.
+
+2003-05-03  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * sysdeps/unix/sysv/linux/ia64/sysdep.h (__NR_semtimedop): Define
+       if not defined.
+
 2003-04-22  Roland McGrath  <roland@redhat.com>
 
        * elf/elf.h (AT_SYSINFO_EHDR): New macro, replaces AT_SYSINFO_EH_FRAME.
index e3c7af9..b79af9b 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (C) 1998, 2000, 2002 Free Software Foundation, Inc.
+# Copyright (C) 1998, 2000, 2002, 2003 Free Software Foundation, Inc.
 # This file is part of the GNU C Library.
 
 # The GNU C Library is free software; you can redistribute it and/or
@@ -30,7 +30,7 @@ vpath %.c ../locale/programs
 
 nscd-modules := nscd connections pwdcache getpwnam_r getpwuid_r grpcache \
                getgrnam_r getgrgid_r hstcache gethstbyad_r gethstbynm2_r \
-               dbg_log nscd_conf nscd_stat cache xmalloc
+               dbg_log nscd_conf nscd_stat cache xmalloc xstrdup
 
 ifeq ($(have-thread-library),yes)
 
index c80ba96..5cb73eb 100644 (file)
@@ -48,6 +48,8 @@ extern void *xrealloc (void *o, size_t n);
 const char *server_user;
 static uid_t server_uid;
 static gid_t server_gid;
+const char *stat_user;
+uid_t stat_uid;
 static gid_t *server_groups;
 #ifndef NGROUPS
 # define NGROUPS 32
@@ -88,7 +90,7 @@ const char *serv2str[LASTREQ] =
 };
 
 /* The control data structures for the services.  */
-static struct database dbs[lastdb] =
+struct database dbs[lastdb] =
 {
   [pwddb] = {
     .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
@@ -137,20 +139,11 @@ unsigned long int client_queued;
 
 /* Initialize database information structures.  */
 void
-nscd_init (const char *conffile)
+nscd_init (void)
 {
   struct sockaddr_un sock_addr;
   size_t cnt;
 
-  /* Read the configuration file.  */
-  if (nscd_parse_file (conffile, dbs) != 0)
-    {
-      /* We couldn't read the configuration file.  Disable all services
-        by shutting down the srever.  */
-      dbg_log (_("cannot read configuration file; this is fatal"));
-      exit (1);
-    }
-
   /* Secure mode and unprivileged mode are incompatible */
   if (server_user != NULL && secure_in_use)
     {
@@ -237,6 +230,7 @@ close_sockets (void)
   close (sock);
 }
 
+
 static void
 invalidate_cache (char *key)
 {
@@ -384,20 +378,9 @@ cannot handle old request version %d; current version is %d"),
     case GETSTAT:
     case SHUTDOWN:
     case INVALIDATE:
-      /* Accept shutdown, getstat and invalidate only from root */
-      if (secure_in_use && uid == 0)
+      if (! secure_in_use)
        {
-         if (req->type == GETSTAT)
-           send_stats (fd, dbs);
-         else if (req->type == INVALIDATE)
-           invalidate_cache (key);
-         else
-           termination_handler (0);
-       }
-      else
-       {
-         /* Some systems have no SO_PEERCRED implementation.  They don't
-            care about security so we don't as well.  */
+         /* Get the callers credentials.  */
 #ifdef SO_PEERCRED
          struct ucred caller;
          socklen_t optlen = sizeof (caller);
@@ -408,18 +391,30 @@ cannot handle old request version %d; current version is %d"),
 
              dbg_log (_("error getting callers id: %s"),
                       strerror_r (errno, buf, sizeof (buf)));
+             break;
            }
-         else
-           if (caller.uid == 0)
+
+         uid = caller.uid;
+#else
+         /* Some systems have no SO_PEERCRED implementation.  They don't
+            care about security so we don't as well.  */
+         uid = 0;
 #endif
-             {
-               if (req->type == GETSTAT)
-                 send_stats (fd, dbs);
-               else if (req->type == INVALIDATE)
-                 invalidate_cache (key);
-               else
-                 termination_handler (0);
-             }
+       }
+
+      /* Accept shutdown, getstat and invalidate only from root.  For
+        the stat call also allow the user specified in the config file.  */
+      if (req->type == GETSTAT)
+       {
+         if (uid == 0 || uid == stat_uid)
+           send_stats (fd, dbs);
+       }
+      else if (uid == 0)
+       {
+         if (req->type == INVALIDATE)
+           invalidate_cache (key);
+         else
+           termination_handler (0);
        }
       break;
 
@@ -480,7 +475,7 @@ nscd_run (void *p)
       int fd = TEMP_FAILURE_RETRY (accept (conn.fd, NULL, NULL));
       request_header req;
       char buf[256];
-      uid_t uid = 0;
+      uid_t uid = -1;
 #ifdef SO_PEERCRED
       pid_t pid = 0;
 #endif
@@ -526,7 +521,7 @@ nscd_run (void *p)
              || secure[serv2db[req.type]])
            uid = caller.uid;
 
-             pid = caller.pid;
+         pid = caller.pid;
        }
       else if (__builtin_expect (debug_level > 0, 0))
        {
index 3d55741..69cfa90 100644 (file)
@@ -30,6 +30,7 @@
 #include <paths.h>
 #include <pthread.h>
 #include <signal.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -109,6 +110,9 @@ static struct argp argp =
   options, parse_opt, NULL, doc,
 };
 
+/* True if only statistics are requested.  */
+static bool get_stats;
+
 int
 main (int argc, char **argv)
 {
@@ -129,6 +133,20 @@ main (int argc, char **argv)
       exit (EXIT_FAILURE);
     }
 
+  /* Read the configuration file.  */
+  if (nscd_parse_file (conffile, dbs) != 0)
+    {
+      /* We couldn't read the configuration file.  We don't start the
+        server.  */
+      dbg_log (_("cannot read configuration file; this is fatal"));
+      exit (1);
+    }
+
+  /* Do we only get statistics?  */
+  if (get_stats)
+    /* Does not return.  */
+    receive_print_stats ();
+
   /* Check if we are already running. */
   if (check_pid (_PATH_NSCDPID))
     error (EXIT_FAILURE, 0, _("already running"));
@@ -223,7 +241,7 @@ main (int argc, char **argv)
   __nss_disable_nscd ();
 
   /* Init databases.  */
-  nscd_init (conffile);
+  nscd_init ();
 
   /* Handle incoming requests */
   start_threads ();
@@ -268,10 +286,8 @@ parse_opt (int key, char *arg, struct argp_state *state)
       }
 
     case 'g':
-      if (getuid () != 0)
-       error (EXIT_FAILURE, 0, _("Only root is allowed to use this option!"));
-      receive_print_stats ();
-      /* Does not return.  */
+      get_stats = true;
+      break;
 
     case 'i':
       if (getuid () != 0)
index 226dda3..ed05ba4 100644 (file)
@@ -10,6 +10,7 @@
 #      threads                 <#threads to use>
 #      server-user             <user to run server as instead of root>
 #              server-user is ignored if nscd is started with -S parameters
+#       stat-user               <user who is allowed to request statistics>
 #
 #       enable-cache           <service> <yes|no>
 #      positive-time-to-live   <service> <time in seconds>
@@ -24,6 +25,7 @@
 #      logfile                 /var/log/nscd.log
 #      threads                 6
 #      server-user             nobody
+#      stat-user               somebody
        debug-level             0
 
        enable-cache            passwd          yes
index 73c94a5..af7ae9a 100644 (file)
@@ -89,6 +89,7 @@ struct database
 
 
 /* Global variables.  */
+extern struct database dbs[lastdb];
 extern const char *dbnames[lastdb];
 extern const char *serv2str[LASTREQ];
 
@@ -99,13 +100,17 @@ extern const struct iovec hst_iov_disabled;
 /* Number of threads to run.  */
 extern int nthreads;
 
-/* Tables for which we cache data with uid */
+/* Tables for which we cache data with uid */
 extern int secure[lastdb];
-extern int secure_in_use; /* Is one of the above 1 ? */
+extern int secure_in_use; /* Is one of the above 1 */
 
-/* User name to run server processes as */
+/* User name to run server processes as */
 extern const char *server_user;
 
+/* Name and UID of user who is allowed to request statistics.  */
+extern const char *stat_user;
+extern uid_t stat_uid;
+
 /* Time the server was started.  */
 extern time_t start_time;
 
@@ -119,7 +124,7 @@ extern void termination_handler (int signum) __attribute__ ((__noreturn__));
 extern int nscd_open_socket (void);
 
 /* connections.c */
-extern void nscd_init (const char *conffile);
+extern void nscd_init (void);
 extern void close_sockets (void);
 extern void start_threads (void) __attribute__ ((__noreturn__));
 
index 7de38d9..23c28ce 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 1998, 2000 Free Software Foundation, Inc.
+/* Copyright (c) 1998, 2000, 2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998.
 
@@ -19,6 +19,7 @@
 
 #include <ctype.h>
 #include <malloc.h>
+#include <pwd.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "dbg_log.h"
 #include "nscd.h"
 
+/* Wrapper functions with error checking for standard functions.  */
+extern char *xstrdup (const char *s);
+
+
 /* Names of the databases.  */
 const char *dbnames[lastdb] =
 {
@@ -181,7 +186,20 @@ nscd_parse_file (const char *fname, struct database dbs[lastdb])
           if (!arg1)
             dbg_log (_("Must specify user name for server-user option"));
           else
-            server_user = strdup (arg1);
+            server_user = xstrdup (arg1);
+        }
+      else if (strcmp (entry, "stat-user") == 0)
+        {
+          if (!arg1)
+            dbg_log (_("Must specify user name for stat-user option"));
+          else
+           {
+             stat_user = xstrdup (arg1);
+
+             struct passwd *pw = getpwnam (stat_user);
+             if (pw != NULL)
+               stat_uid = pw->pw_uid;
+           }
         }
       else
        dbg_log (_("Unknown option: %s %s %s"), entry, arg1, arg2);
index 7cfde98..f04e197 100644 (file)
@@ -114,6 +114,24 @@ receive_print_stats (void)
   ssize_t nbytes;
   int fd;
   int i;
+  uid_t uid = getuid ();
+
+  /* Find out whether there is another user but root allowed to
+     request statistics.  */
+  if (uid != 0)
+    {
+      /* User specified?  */
+      if(stat_user == NULL || stat_uid != uid)
+       {
+         if (stat_user != NULL)
+           error (EXIT_FAILURE, 0,
+                  _("Only root or %s is allowed to use this option!"),
+                  stat_user);
+         else
+           error (EXIT_FAILURE, 0,
+                  _("Only root is allowed to use this option!"));
+       }
+    }
 
   /* Open a socket to the running nscd.  */
   fd = nscd_open_socket ();
index 86dd371..0f729a3 100644 (file)
 # define __NR_pwrite __NR_pwrite64
 #endif
 
+/* This is to help the old kernel headers where __NR_semtimedop is not
+   available.  */
+#ifndef __NR_semtimedop
+# define __NR_semtimedop 1247
+#endif
+
 #ifdef __ASSEMBLER__
 
 #undef CALL_MCOUNT