+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.
-# 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
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)
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
};
/* The control data structures for the services. */
-static struct database dbs[lastdb] =
+struct database dbs[lastdb] =
{
[pwddb] = {
.lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
/* 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)
{
close (sock);
}
+
static void
invalidate_cache (char *key)
{
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);
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;
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
|| secure[serv2db[req.type]])
uid = caller.uid;
- pid = caller.pid;
+ pid = caller.pid;
}
else if (__builtin_expect (debug_level > 0, 0))
{
#include <paths.h>
#include <pthread.h>
#include <signal.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
options, parse_opt, NULL, doc,
};
+/* True if only statistics are requested. */
+static bool get_stats;
+
int
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"));
__nss_disable_nscd ();
/* Init databases. */
- nscd_init (conffile);
+ nscd_init ();
/* Handle incoming requests */
start_threads ();
}
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)
# 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>
# logfile /var/log/nscd.log
# threads 6
# server-user nobody
+# stat-user somebody
debug-level 0
enable-cache passwd yes
/* Global variables. */
+extern struct database dbs[lastdb];
extern const char *dbnames[lastdb];
extern const char *serv2str[LASTREQ];
/* 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;
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__));
-/* 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.
#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] =
{
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);
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 ();
# 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