diff options
-rw-r--r-- | ChangeLog | 25 | ||||
-rw-r--r-- | nscd/Makefile | 4 | ||||
-rw-r--r-- | nscd/connections.c | 67 | ||||
-rw-r--r-- | nscd/nscd.c | 26 | ||||
-rw-r--r-- | nscd/nscd.conf | 2 | ||||
-rw-r--r-- | nscd/nscd.h | 13 | ||||
-rw-r--r-- | nscd/nscd_conf.c | 22 | ||||
-rw-r--r-- | nscd/nscd_stat.c | 18 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/ia64/sysdep.h | 6 |
9 files changed, 134 insertions, 49 deletions
@@ -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. diff --git a/nscd/Makefile b/nscd/Makefile index e3c7af9c0a..b79af9b355 100644 --- a/nscd/Makefile +++ b/nscd/Makefile @@ -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) diff --git a/nscd/connections.c b/nscd/connections.c index c80ba96dc5..5cb73eb252 100644 --- a/nscd/connections.c +++ b/nscd/connections.c @@ -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)) { diff --git a/nscd/nscd.c b/nscd/nscd.c index 3d55741df1..69cfa90ab5 100644 --- a/nscd/nscd.c +++ b/nscd/nscd.c @@ -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) diff --git a/nscd/nscd.conf b/nscd/nscd.conf index 226dda377f..ed05ba495f 100644 --- a/nscd/nscd.conf +++ b/nscd/nscd.conf @@ -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 diff --git a/nscd/nscd.h b/nscd/nscd.h index 73c94a5035..af7ae9a7e5 100644 --- a/nscd/nscd.h +++ b/nscd/nscd.h @@ -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__)); diff --git a/nscd/nscd_conf.c b/nscd/nscd_conf.c index 7de38d9d25..23c28ceef0 100644 --- a/nscd/nscd_conf.c +++ b/nscd/nscd_conf.c @@ -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> @@ -29,6 +30,10 @@ #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); diff --git a/nscd/nscd_stat.c b/nscd/nscd_stat.c index 7cfde982f6..f04e1972b5 100644 --- a/nscd/nscd_stat.c +++ b/nscd/nscd_stat.c @@ -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 (); diff --git a/sysdeps/unix/sysv/linux/ia64/sysdep.h b/sysdeps/unix/sysv/linux/ia64/sysdep.h index 86dd371389..0f729a3c3e 100644 --- a/sysdeps/unix/sysv/linux/ia64/sysdep.h +++ b/sysdeps/unix/sysv/linux/ia64/sysdep.h @@ -45,6 +45,12 @@ # 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 |