diff options
author | Carlos Perelló Marín <carlos@gnome.org> | 2003-10-19 16:55:56 +0000 |
---|---|---|
committer | Carlos Perelló Marín <carlos@src.gnome.org> | 2003-10-19 16:55:56 +0000 |
commit | 4c8ae9e25c1940d8876ca3f2330426863cae4737 (patch) | |
tree | c43f97bc0647546b0ed87022db0749c137f24edc /src | |
parent | bae16b467f90df94d80feae41dceb7e816f16c61 (diff) | |
download | libgtop-4c8ae9e25c1940d8876ca3f2330426863cae4737.tar.gz |
Reverted libgtop changes. It's a common module and I should not modify it.
2003-10-19 Carlos Perelló Marín <carlos@gnome.org>
* support/*: Reverted libgtop changes. It's a common module
and I should not modify it.
* Added/removed files. Now the move should be done.
Diffstat (limited to 'src')
-rw-r--r-- | src/daemon/.cvsignore | 7 | ||||
-rw-r--r-- | src/daemon/ChangeLog | 104 | ||||
-rw-r--r-- | src/daemon/Makefile.am | 53 | ||||
-rw-r--r-- | src/daemon/daemon.h | 81 | ||||
-rw-r--r-- | src/daemon/gnuserv.c | 643 | ||||
-rw-r--r-- | src/daemon/io.c | 98 | ||||
-rw-r--r-- | src/daemon/main.c | 237 | ||||
-rw-r--r-- | src/daemon/server.c | 110 | ||||
-rw-r--r-- | src/daemon/server_config.h | 11 | ||||
-rw-r--r-- | src/daemon/server_config.h.in | 44 | ||||
-rwxr-xr-x | src/daemon/server_config.pl | 111 | ||||
-rw-r--r-- | src/daemon/slave.c | 256 | ||||
-rw-r--r-- | src/daemon/version.c | 62 | ||||
-rw-r--r-- | src/inodedb/file_by_inode2.c (renamed from src/inodedb/file_by_inode.c) | 46 | ||||
-rw-r--r-- | src/inodedb/mkinodedb.c | 137 | ||||
-rw-r--r-- | src/inodedb/mkinodedb2.c | 135 |
16 files changed, 1974 insertions, 161 deletions
diff --git a/src/daemon/.cvsignore b/src/daemon/.cvsignore new file mode 100644 index 00000000..ccdb1c11 --- /dev/null +++ b/src/daemon/.cvsignore @@ -0,0 +1,7 @@ +Makefile.in +Makefile +libgtop_daemon2 +libgtop_server2 +server.conf +.libs +.deps diff --git a/src/daemon/ChangeLog b/src/daemon/ChangeLog new file mode 100644 index 00000000..2ddb846e --- /dev/null +++ b/src/daemon/ChangeLog @@ -0,0 +1,104 @@ +2003-05-11 Andrew Sobala <aes@gnome.org> + + * gnuserv.c: (permitted): fix buffer overflow vulnerability + +2001-02-14 Martin Baulig <baulig@suse.de> + + * Makefile.am (libgtop_server_LDADD): Removed @LIBSUPPORT@. + +1999-11-28 Martin Baulig <martin@home-of-linux.org> + + * gnuserv.c (setup_table): Don't dump core when the table of + permitted host names contains a NULL pointer. + +1999-07-29 Martin Baulig <martin@home-of-linux.org> + + * Makefile.am: Link the `libgtop_daemon' and the `libgtop_server' + statically if possible. + +1999-05-07 Martin Baulig <martin@home-of-linux.org> + + * server.c (main): There's some problem with uname () - some systems + like Solaris or Digital Unix return a nonnegative value on success, + some others like Linux return 0. Since all known systems seem to return + a negative value on failure, we simply check whether the return value is + not negative here. + +1999-02-19 Martin Baulig <martin@home-of-linux.org> + + * Makefile.am (LIBGTOP_COMPILE_SYSTEM): Hardcoded system name. + (LIBGTOP_COMPILE_RELEASE): Hardcoded system release. + (LIBGTOP_COMPILE_MACHINE): Hardcoded machine type. + + * src/daemon/Makefile.am (libgtop_server_SOURCES): Don't use + `@INTLLIBS@' for the server. + + * server.c (main): Abort if not running on the system the server + was compiled on. + +1999-02-10 Martin Baulig <martin@home-of-linux.org> + + * gnuserv.c (program_invocation_*_name): Declare this as `extern' + if necessary. + +1998-12-17 Martin Baulig <baulig@merkur.uni-trier.de> + + * gnuserv.c: Don't include <gnome-argp.h>. + (program_invocation_name, program_invocation_short_name): Define + this here. + +1998-12-09 Martin Baulig <martin@home-of-linux.org> + + Larger changes to the daemon: + + - Dropped all the unix domain socket stuff - we don't need it for + connections on the local host, here we behave just like any normal + application. + - Added poptimization: use the --help parameter to get usage info + - Made it a real daemon, fork into background and write to syslog. + - It's now possible to invoke the daemon from inetd, you'll get + GNU_SECURE authentication in this case. + - Don't make this executable suid/sgid - if invoked as root it + sets uid/gid to SERVER_UID/SERVER_GID as defined in server_config.h + - Added missing features, so you can now really use this thing. + +1998-11-11 Martin Baulig <martin@home-of-linux.org> + + * gnuserv.c (main): Set `server->features' directly rather than + calling glibtop_set_parameter_l () since this function no longer + allows to modify the features. + + * gnuserv.c, main.c: Use LIBGTOP_ENABLE_DEBUG rather than DEBUG. + +1998-11-01 Marc Ewing <marc@tasmanian.redhat.com> + + * Makefile.am: Added $(GLIB_LIBS) to libs. Not sure + how it ever built without it. + +1998-10-20 Martin Baulig <martin@home-of-linux.org> + + * Makefile.am: Added a notice that this file *requires* + libtool 1.2. It may work with 1.1 as well, but that's untested. + +1998-10-11 Martin Baulig <martin@home-of-linux.org> + + * Makefile.am (install-exec-hook): Always run `libgtop_postinstall', + it's `:' if there's nothing to do since the empty string is no + valid shell syntax here. + +1998-10-01 Martin Baulig <martin@home-of-linux.org> + + * Makefile.am (install-exec-hook): Use `libgtop_postinstall' + here to make the server suid root or sgid kmem if required. + +1998-08-25 Martin Baulig <martin@home-of-linux.org> + + * daemon.h (handle_parent_connection): Added prototype. + * write.c, io.c: Added cast to `const void *' in calls to + `write' and `send' to avoid compiler warnings. + * gnuserv.c (handle_signal): Declared static. + (main): Casting return value of `getuid' to `int' in + debugging statement. + + * ChangeLog: New file. + diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am new file mode 100644 index 00000000..7b1e457a --- /dev/null +++ b/src/daemon/Makefile.am @@ -0,0 +1,53 @@ +## You need libtool 1.2 or newer for this Makefile.am to work. +## +## It _may_ work with an older version of libtool, but it also may fail. +## So if you get any undefined symbols here, please make sure you really +## have libtool 1.2 or better before reporting this as bug. +## +## You'll require libtool 1.2 for other parts of GNOME anyway. +## +## Get ftp://ftp.gnu.org/pub/gnu/libtool-1.2.tar.gz +## (or a newer version if it is available) +## +## Martin <martin@home-of-linux.org> +## + +LINK = $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -o $@ + +INCLUDES = $(LIBGTOP_CFLAGS) @INCLUDES@ -D_BSD \ + -DLIBGTOP_COMPILE_SYSTEM="\"`uname -s`\"" \ + -DLIBGTOP_COMPILE_RELEASE="\"`uname -r`\"" \ + -DLIBGTOP_COMPILE_VERSION="\"`uname -v`\"" \ + -DLIBGTOP_COMPILE_MACHINE="\"`uname -m`\"" + +if NEED_LIBGTOP +suid_sysdeps = $(top_builddir)/sysdeps/@sysdeps_dir@/libgtop_sysdeps_suid-2.0.la +suid_common = $(top_builddir)/sysdeps/common/libgtop_suid_common-2.0.la +else +suid_sysdeps = +suid_common = +endif + +bin_PROGRAMS = libgtop_daemon2 @server_programs@ + +EXTRA_PROGRAMS = libgtop_server2 + +libgtop_daemon2_SOURCES = gnuserv.c slave.c main.c io.c version.c \ + daemon.h server_config.h +libgtop_daemon2_LDADD = $(top_builddir)/lib/libgtop-2.0.la \ + $(top_builddir)/sysdeps/common/libgtop_common-2.0.la \ + $(top_builddir)/sysdeps/@sysdeps_dir@/libgtop_sysdeps-2.0.la \ + @sysdeps_suid_lib@ \ + $(suid_sysdeps) $(suid_common)\ + $(LIBGTOP_LIBS)\ + @LIBSUPPORT@ @INTLLIBS@ @libs_xauth@ + +libgtop_server2_SOURCES = server.c slave.c io.c version.c daemon.h +libgtop_server2_LDADD = $(top_builddir)/sysdeps/@sysdeps_dir@/libgtop_sysdeps_suid-2.0.la \ + $(top_builddir)/sysdeps/common/libgtop_suid_common-2.0.la + +EXTRA_DIST = server_config.h.in server_config.pl + +install-exec-hook: + -@libgtop_postinstall@ + diff --git a/src/daemon/daemon.h b/src/daemon/daemon.h new file mode 100644 index 00000000..9539db37 --- /dev/null +++ b/src/daemon/daemon.h @@ -0,0 +1,81 @@ +/* $Id$ */ + +/* Copyright (C) 1998-99 Martin Baulig + This file is part of LibGTop 1.0. + + Contributed by Martin Baulig <martin@home-of-linux.org>, April 1998. + + LibGTop is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + LibGTop is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with LibGTop; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __GLIBTOP_DAEMON_H__ +#define __GLIBTOP_DAEMON_H__ + +#include <glibtop.h> +#include <glibtop/error.h> +#include <glibtop/gnuserv.h> + +#include <glibtop/open.h> +#include <glibtop/union.h> +#include <glibtop/xmalloc.h> +#include <glibtop/version.h> +#include <glibtop/command.h> +#include <glibtop/parameter.h> + +#include <fcntl.h> +#include <sys/wait.h> +#include <sys/socket.h> +#include <syslog.h> + +BEGIN_LIBGTOP_DECLS + +/* Some don't have LOG_PERROR */ +#ifndef LOG_PERROR +#define LOG_PERROR 0 +#endif + +#if defined(HAVE_GETDTABLESIZE) +#define GET_MAX_FDS() getdtablesize() +#else +/* Fallthrough case - please add other #elif cases above + for different OS's as necessary */ +#define GET_MAX_FDS() 256 +#endif + +#define _offset_union(p) ((char *) &resp->u.p - (char *) resp) +#define _offset_data(p) _offset_union (data.p) + +#define MSG_BUFSZ sizeof (struct _glibtop_ipc_message) +#define MSG_MSGSZ (MSG_BUFSZ - sizeof (long)) + +void handle_parent_connection (int s); +void handle_slave_connection (int input, int output); +void handle_slave_command (glibtop_command *cmnd, glibtop_response *resp, + const void *parameter); + +void do_output (int s, glibtop_response *resp, off_t offset, + size_t data_size, const void *data); +int do_read (int s, void *ptr, size_t total_size); + +void syslog_message (int priority, char *format, ...); +void syslog_io_message (int priority, char *format, ...); + +extern int enable_debug; +extern int verbose_output; + +END_LIBGTOP_DECLS + +#endif diff --git a/src/daemon/gnuserv.c b/src/daemon/gnuserv.c new file mode 100644 index 00000000..2be6659e --- /dev/null +++ b/src/daemon/gnuserv.c @@ -0,0 +1,643 @@ +/* -*-C-*- + * Server code for handling requests from clients and forwarding them + * on to the GNU Emacs process. + * + * This file is part of GNU Emacs. + * + * Copying is permitted under those conditions described by the GNU + * General Public License. + * + * Copyright (C) 1989 Free Software Foundation, Inc. + * + * Author: Andy Norman (ange@hplb.hpl.hp.com), based on 'etc/server.c' + * from the 18.52 GNU Emacs distribution. + * + * Please mail bugs and suggestions to the author at the above address. + */ + +/* HISTORY + * 11-Nov-1990 bristor@simba + * Added EOT stuff. + */ + +/* + * This file incorporates new features added by Bob Weiner <weiner@mot.com>, + * Darrell Kindred <dkindred@cmu.edu> and Arup Mukherjee <arup@cmu.edu>. + * Please see the note at the end of the README file for details. + * + * (If gnuserv came bundled with your emacs, the README file is probably + * ../etc/gnuserv.README relative to the directory containing this file) + */ + +#include <glibtop.h> +#include <glibtop/open.h> +#include <glibtop/close.h> +#include <glibtop/command.h> +#include <glibtop/xmalloc.h> + +#include <glibtop/parameter.h> + +#include "server_config.h" + +#include <glibtop/gnuserv.h> + +#include <errno.h> +#include <popt-gnome.h> + +#include "daemon.h" + +#ifdef AIX +#include <sys/select.h> +#endif + +#ifdef NEED_DECLARATION_PROGRAM_INVOCATION_NAME +extern char *program_invocation_name, *program_invocation_short_name; +#endif + +#ifndef HAVE_PROGRAM_INVOCATION_SHORT_NAME +char *program_invocation_short_name; +#endif + +#ifndef HAVE_PROGRAM_INVOCATION_NAME +char *program_invocation_name; +#endif + +void handle_parent_connection (int s); +void handle_slave_connection (int input, int output); + +#if !defined(INTERNET_DOMAIN_SOCKETS) +#error "Internet Domain sockets are required" +#endif + +#ifdef AUTH_MAGIC_COOKIE +#include <X11/X.h> +#include <X11/Xauth.h> + +static Xauth *server_xauth = NULL; + +#endif /* AUTH_MAGIC_COOKIE */ + +int enable_debug = 0; +int verbose_output = 0; +static int no_daemon = 0; +static int invoked_from_inetd = 0; +static int changed_uid = 0; + +void +syslog_message (int priority, char *format, ...) +{ + va_list ap; + char buffer [BUFSIZ]; + + va_start (ap, format); + vsnprintf (buffer, BUFSIZ-1, format, ap); + va_end (ap); + + syslog (priority, "%s", buffer); +} + +void +syslog_io_message (int priority, char *format, ...) +{ + va_list ap; + char buffer [BUFSIZ]; + char buffer2 [BUFSIZ]; + + va_start (ap, format); + vsnprintf (buffer, BUFSIZ-1, format, ap); + va_end (ap); + + snprintf (buffer2, BUFSIZ-1, "%s: %s", buffer, strerror (errno)); + syslog (priority, "%s", buffer2); +} + +/* + * timed_read - Read with timeout. + */ + +static int +timed_read (int fd, char *buf, int max, int timeout, int one_line) +{ + fd_set rmask; + struct timeval tv; /* = {timeout, 0}; */ + char c = 0; + int nbytes = 0; + int r; + + tv.tv_sec = timeout; + tv.tv_usec = 0; + + FD_ZERO (&rmask); + FD_SET (fd, &rmask); + + do { + r = select (fd + 1, &rmask, NULL, NULL, &tv); + + if (r > 0) { + if (read (fd, &c, 1) == 1) { + *buf++ = c; + ++nbytes; + } else { + syslog_io_message (LOG_WARNING, "read error on socket"); + return -1; + } + } else if (r == 0) { + syslog_io_message (LOG_WARNING, "read timed out"); + return -1; + } else { + syslog_io_message (LOG_WARNING, "error in select"); + return -1; + } + } while ((nbytes < max) && !(one_line && (c == '\n'))); + + --buf; + if (one_line && *buf == '\n') { + *buf = 0; + } + return nbytes; +} + + +/* + * permitted -- return whether a given host is allowed to connect to the server. + */ + +static int +permitted (u_long host_addr, int fd) +{ + int i; + + char auth_protocol[128]; + char buf[1024]; + int auth_data_len; + + /* Read auth protocol name */ + + if (timed_read (fd, auth_protocol, AUTH_NAMESZ, AUTH_TIMEOUT, 1) <= 0) + return FALSE; + + if (enable_debug) + syslog_message (LOG_DEBUG, + "Client sent authenticatin protocol '%s'.", + auth_protocol); + + if (strcmp (auth_protocol, DEFAUTH_NAME) && + strcmp (auth_protocol, MCOOKIE_NAME)) { + syslog_message (LOG_WARNING, + "Invalid authentication protocol " + "'%s' from client", + auth_protocol); + return FALSE; + } + + if (!strcmp (auth_protocol, MCOOKIE_NAME)) { + /* + * doing magic cookie auth + */ + + if (timed_read (fd, buf, 10, AUTH_TIMEOUT, 1) <= 0) + return FALSE; + + auth_data_len = atoi (buf); + + if (auth_data_len < 1 || auth_data_len > sizeof(buf)) { + syslog_message(LOG_WARNING, "Invalid data length supplied by client"); + return FALSE; + } + + if (timed_read (fd, buf, auth_data_len, AUTH_TIMEOUT, 0) != auth_data_len) + return FALSE; + +#ifdef AUTH_MAGIC_COOKIE + if (!invoked_from_inetd && server_xauth && server_xauth->data && + !memcmp (buf, server_xauth->data, auth_data_len)) { + return TRUE; + } +#else + syslog_message (LOG_WARNING, + "Client tried Xauth, but server is " + "not compiled with Xauth"); +#endif + + /* + * auth failed, but allow this to fall through to the + * GNU_SECURE protocol.... + */ + + if (verbose_output) { + if (changed_uid || invoked_from_inetd) + syslog_message (LOG_WARNING, + "Xauth authentication not allowed, " + "trying GNU_SECURE ..."); + else + syslog_message (LOG_WARNING, + "Xauth authentication failed, " + "trying GNU_SECURE auth..."); + } + } + + /* Other auth protocols go here, and should execute only if + * the * auth_protocol name matches. */ + + /* Now, try the old GNU_SECURE stuff... */ + + if (enable_debug) + syslog_message (LOG_DEBUG, "Doing GNU_SECURE auth ..."); + + /* Now check the chain for that hash key */ + for (i = 0; i < HOST_TABLE_ENTRIES; i++) { + if (enable_debug) + syslog_message (LOG_DEBUG, "Trying %lx - %lx", + host_addr, permitted_hosts [i]); + if (permitted_hosts [i] == 0L) + return (FALSE); + if (host_addr == permitted_hosts [i]) + return (TRUE); + } + + return (FALSE); +} + + +/* + * setup_table -- initialise the table of hosts allowed to contact the server, + * by reading from the file specified by the GNU_SECURE + * environment variable + * Put in the local machine, and, if a security file is specifed, + * add each host that is named in the file. + * Return the number of hosts added. + */ + +static int +setup_table (void) +{ + char hostname [HOSTNAMSZ], screen [BUFSIZ]; + long host_addr; + int i, hosts = 0; + + /* Make sure every entry is null */ + for (i = 0; i < HOST_TABLE_ENTRIES; i++) + permitted_hosts [i] = 0; + + gethostname (hostname, HOSTNAMSZ); + + if ((host_addr = glibtop_internet_addr (hostname)) == -1) { + syslog_io_message (LOG_ERR, "Can't resolve '%s'", hostname); + exit (1); + } + +#ifdef AUTH_MAGIC_COOKIE + + sprintf (screen, "%d", SERVER_PORT); + + server_xauth = XauGetAuthByAddr + (FamilyInternet, + sizeof (host_addr), (char *) &host_addr, + strlen (screen), screen, + strlen (MCOOKIE_X_NAME), MCOOKIE_X_NAME); + hosts++; + +#endif /* AUTH_MAGIC_COOKIE */ + + /* Resolv host names from permitted_host_names []. */ + + for (i = 0; i < HOST_TABLE_ENTRIES; i++) { + if (!permitted_host_names [i]) + continue; + if (enable_debug) + syslog_message (LOG_DEBUG, "Resolving %s ...", + permitted_host_names [i]); + permitted_hosts [i] = + glibtop_internet_addr (permitted_host_names [i]); + if ((long) permitted_hosts [i] == -1) { + syslog_io_message (LOG_ERR, "Can't resolve '%s'", + permitted_host_names [i]); + exit (1); + } + } + + if (enable_debug) + for (i = 0; i < HOST_TABLE_ENTRIES; i++) + syslog_message (LOG_DEBUG, "Host %s - %lx", + permitted_host_names [i], + permitted_hosts [i]); + + hosts += HOST_TABLE_ENTRIES; + + return hosts; +} /* setup_table */ + +/* + * internet_init -- initialize server, returning an internet socket that can + * be listened on. + */ + +static int +internet_init (void) +{ + int ls; /* socket descriptor */ + struct sockaddr_in server; /* for local socket address */ + + if (setup_table () == 0) + return -1; + + /* clear out address structure */ + memset ((char *) &server, 0, sizeof (struct sockaddr_in)); + + /* Set up address structure for the listen socket. */ + server.sin_family = AF_INET; + server.sin_addr.s_addr = INADDR_ANY; + + /* We use a fixed port given in the config file. */ + server.sin_port = htons (SERVER_PORT); + + if (verbose_output) + syslog_message (LOG_INFO, "Using port %u.", SERVER_PORT); + + /* Create the listen socket. */ + if ((ls = socket (AF_INET, SOCK_STREAM, 0)) == -1) { + syslog_io_message (LOG_ERR, "unable to create socket"); + exit (1); + } + + /* Bind the listen address to the socket. */ + if (bind (ls, (struct sockaddr *) &server, + sizeof (struct sockaddr_in)) == -1) { + syslog_io_message (LOG_ERR, "bind"); + exit (1); + } + + /* Initiate the listen on the socket so remote users * can connect. */ + if (listen (ls, 20) == -1) { + syslog_io_message (LOG_ERR, "listen"); + exit (1); + } + + return (ls); +} /* internet_init */ + + +/* + * handle_internet_request -- accept a request from a client and send the + * information to stdout (the gnu process). + */ + +static void +handle_internet_request (int ls) +{ + int s; + size_t addrlen = sizeof (struct sockaddr_in); + struct sockaddr_in peer; /* for peer socket address */ + pid_t pid; + + memset ((char *) &peer, 0, sizeof (struct sockaddr_in)); + + if ((s = accept (ls, (struct sockaddr *) &peer, (void *) &addrlen)) == -1) { + syslog_io_message (LOG_ERR, "accept"); + exit (1); + } + + if (verbose_output) + syslog_message (LOG_INFO, "Connection was made from %s port %u.", + inet_ntoa (peer.sin_addr), ntohs (peer.sin_port)); + + /* Check that access is allowed - if not return crud to the client */ + if (!permitted (peer.sin_addr.s_addr, s)) { + close (s); + syslog_message (LOG_CRIT, "Refused connection from %s.", + inet_ntoa (peer.sin_addr)); + return; + } /* if */ + + if (verbose_output) + syslog_message (LOG_INFO, "Accepted connection from %s port %u.", + inet_ntoa (peer.sin_addr), ntohs (peer.sin_port)); + + pid = fork (); + + if (pid == -1) { + syslog_io_message (LOG_ERR, "fork failed"); + exit (1); + } + + if (pid) { + if (verbose_output) + syslog_message (LOG_INFO, "Child pid is %d.", pid); + return; + } + + handle_parent_connection (s); + + close (s); + + if (verbose_output) + syslog_message (LOG_INFO, "Closed connection to %s port %u.", + inet_ntoa (peer.sin_addr), ntohs (peer.sin_port)); + + _exit (0); +} /* handle_internet_request */ + +static void +handle_signal (int sig) +{ + if (sig == SIGCHLD) + return; + + syslog_message (LOG_ERR, "Catched signal %d.\n", sig); + exit (1); +} + +const struct poptOption popt_options [] = { + POPT_AUTOHELP + { "debug", 'd', POPT_ARG_NONE, &enable_debug, 0, + N_("Enable debugging"), N_("DEBUG") }, + { "verbose", 'v', POPT_ARG_NONE, &verbose_output, 0, + N_("Enable verbose output"), N_("VERBOSE") }, + { "no-daemon", 'f', POPT_ARG_NONE, &no_daemon, 0, + N_("Don't fork into background"), N_("NO-DAEMON") }, + { "inetd", 'i', POPT_ARG_NONE, &invoked_from_inetd, 0, + N_("Invoked from inetd"), N_("INETD") }, + { NULL, '\0', 0, NULL, 0 } +}; + +int +main (int argc, char *argv []) +{ + const unsigned method = GLIBTOP_METHOD_PIPE; + const unsigned long features = GLIBTOP_SYSDEPS_ALL; + glibtop *server = glibtop_global_server; + poptContext context; + int nextopt; + + int ils = -1; /* internet domain listen socket */ + + /* On non-glibc systems, this is not set up for us. */ + if (!program_invocation_name) { + char *arg; + + program_invocation_name = argv[0]; + arg = strrchr (argv[0], '/'); + program_invocation_short_name = + arg ? (arg + 1) : program_invocation_name; + } + + context = poptGetContext ("libgtop-daemon", argc, argv, + popt_options, 0); + + poptReadDefaultConfig (context, TRUE); + + while ((nextopt = poptGetNextOpt (context)) > 0) + /* do nothing */ ; + + if(nextopt != -1) { + printf (_("Error on option %s: %s.\n" + "Run '%s --help' to see a full list of " + "available command line options.\n"), + poptBadOption (context, 0), + poptStrerror (nextopt), + argv[0]); + exit(1); + } + + if (enable_debug) + verbose_output = 1; + + if (no_daemon) { + openlog ("libgtop-daemon", LOG_PERROR | LOG_PID, LOG_LOCAL0); + } else { + openlog ("libgtop-daemon", LOG_PID, LOG_LOCAL0); + } + + if (!no_daemon && !invoked_from_inetd) { + pid_t pid = fork (); + + if (pid == -1) { + syslog_io_message (LOG_ERR, "fork failed"); + exit (1); + } else if (pid) + exit (0); + + close (0); + + setsid (); + } + + glibtop_init_r (&glibtop_global_server, 0, GLIBTOP_INIT_NO_INIT); + + signal (SIGCHLD, handle_signal); + + /* If we are root, completely switch to SERVER_UID and + * SERVER_GID. Otherwise we completely drop any priviledges. + */ + + if (enable_debug) + syslog_message (LOG_DEBUG, "Parent ID: (%d, %d) - (%d, %d)", + getuid (), geteuid (), getgid (), getegid ()); + + if (geteuid () == 0) { + changed_uid = 1; + if (setregid (SERVER_GID, SERVER_GID)) { + syslog_io_message (LOG_ERR, "setregid (SERVER_GID)"); + exit (1); + } + if (setreuid (SERVER_UID, SERVER_UID)) { + syslog_io_message (LOG_ERR, "setreuid (SERVER_UID)"); + exit (1); + } + } else { + if (setreuid (geteuid (), geteuid ())) { + syslog_io_message (LOG_ERR, "setreuid (euid)"); + exit (1); + } + } + + if (enable_debug) + syslog_message (LOG_DEBUG, "Parent ID: (%d, %d) - (%d, %d)", + getuid (), geteuid (), getgid (), getegid ()); + + if (invoked_from_inetd) { + size_t addrlen = sizeof (struct sockaddr_in); + struct sockaddr_in peer; + + memset ((char *) &peer, 0, sizeof (struct sockaddr_in)); + + if (getpeername (0, (struct sockaddr *) &peer, (void *) &addrlen)) { + syslog_io_message (LOG_ERR, "getpeername"); + exit (1); + } + + if (verbose_output) + syslog_message (LOG_INFO, "Connection was made from %s port %u.", + inet_ntoa (peer.sin_addr), ntohs (peer.sin_port)); + + /* Check that access is allowed - if not return crud to the client */ + if (!permitted (peer.sin_addr.s_addr, 0)) { + close (0); + syslog_message (LOG_CRIT, "Refused connection from %s.", + inet_ntoa (peer.sin_addr)); + exit (1); + } + + handle_parent_connection (0); + exit (0); + } + + /* get a internet domain socket to listen on. */ + ils = internet_init (); + + if (ils <= 0) { + syslog_message (LOG_ERR, "Unable to get internet domain socket."); + exit (1); + } + + glibtop_set_parameter_l (server, GLIBTOP_PARAM_METHOD, + &method, sizeof (method)); + + server->features = features; + + glibtop_init_r (&server, 0, 0); + + while (1) { + fd_set rmask; + int status, ret; + + while ((ret = wait3 (&status, WNOHANG, NULL)) != 0) { + if ((ret == -1) && (errno == ECHILD)) + break; + + if ((ret == -1) && ((errno == EAGAIN))) + continue; + if (ret == 0) { + syslog_io_message (LOG_WARNING, "wait3"); + continue; + } + + if (verbose_output) + syslog_message (LOG_INFO, "Child %d exited.", ret); + } + + FD_ZERO (&rmask); + + /* Only the child accepts connections from standard + * input made by its parent. */ + + FD_SET (ils, &rmask); + + if (enable_debug) + syslog_message (LOG_DEBUG, + "Server ready and waiting for connections."); + + if (select (ils+1, &rmask, (fd_set *) NULL, (fd_set *) NULL, + (struct timeval *) NULL) < 0) { + if (errno == EINTR) + continue; + syslog_io_message (LOG_ERR, "select"); + exit (1); + } + + if (FD_ISSET (ils, &rmask)) + handle_internet_request (ils); + } + + return 0; +} diff --git a/src/daemon/io.c b/src/daemon/io.c new file mode 100644 index 00000000..aa38dd40 --- /dev/null +++ b/src/daemon/io.c @@ -0,0 +1,98 @@ +/* $Id$ */ + +/* Copyright (C) 1998-99 Martin Baulig + This file is part of LibGTop 1.0. + + Contributed by Martin Baulig <martin@home-of-linux.org>, April 1998. + + LibGTop is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + LibGTop is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with LibGTop; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "daemon.h" + +void +do_output (int s, glibtop_response *resp, off_t offset, + size_t data_size, const void *data) +{ +#ifdef REAL_DEBUG + fprintf (stderr, "Really writing %d bytes at offset %lu.\n", + sizeof (glibtop_response), offset); +#endif + + resp->offset = offset; + resp->data_size = data_size; + + if (s == 0) { + if (write (1, (const void *) resp, sizeof (glibtop_response)) < 0) + glibtop_warn_io ("write"); + } else { + if (send (s, (const void *) resp, sizeof (glibtop_response), 0) < 0) + glibtop_warn_io ("send"); + } + + if (resp->data_size) { +#ifdef REAL_DEBUG + fprintf (stderr, "Writing %d bytes of data.\n", resp->data_size); +#endif + + if (s == 0) { + if (write (1, data, resp->data_size) < 0) + glibtop_warn_io ("write"); + } else { + if (send (s, data, resp->data_size, 0) , 0) + glibtop_warn_io ("send"); + } + } +} + +int +do_read (int s, void *ptr, size_t total_size) +{ + int nread; + char *tmp_ptr; + size_t already_read = 0, remaining = total_size; + + while (already_read < total_size) { + if (s) + nread = recv (s, ptr, remaining, 0); + else + nread = read (0, ptr, remaining); + + if ((already_read == 0) && (nread == 0)) { + glibtop_warn ("pid %d received eof.", getpid ()); + return 0; + } + + if (nread <= 0) { + glibtop_warn_io ("recv"); + return 0; + } + + already_read += nread; + remaining -= nread; + /* (char *) ptr += nread; */ + tmp_ptr = ptr; + tmp_ptr += nread; + ptr = tmp_ptr; + +#ifdef REAL_DEBUG + fprintf (stderr, "READ (%d): %d - %d - %d\n", + nread, already_read, remaining, total_size); +#endif + } + + return already_read; +} diff --git a/src/daemon/main.c b/src/daemon/main.c new file mode 100644 index 00000000..36154cfe --- /dev/null +++ b/src/daemon/main.c @@ -0,0 +1,237 @@ +/* $Id$ */ + +/* Copyright (C) 1998-99 Martin Baulig + This file is part of LibGTop 1.0. + + Contributed by Martin Baulig <martin@home-of-linux.org>, April 1998. + + LibGTop is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + LibGTop is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with LibGTop; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "daemon.h" + +#ifdef LIBGTOP_ENABLE_DEBUG +#ifndef PARENT_DEBUG +#define PARENT_DEBUG 1 +#endif +#ifndef DEBUG +#define DEBUG 1 +#endif +#endif + +void +handle_parent_connection (int s) +{ + glibtop *server = glibtop_global_server; + glibtop_response _resp, *resp = &_resp; + glibtop_command _cmnd, *cmnd = &_cmnd; + glibtop_mountentry *mount_list; + char parameter [BUFSIZ]; + unsigned short device; + int64_t *param_ptr; + int all_fs; + pid_t pid; + void *ptr; + + glibtop_send_version (glibtop_global_server, s); + + if (verbose_output) + syslog_message (LOG_INFO, "Parent features = %lu", + glibtop_server_features); + + if (enable_debug) + syslog_message (LOG_DEBUG, "SIZEOF: %u - %u - %u - %u - %u - %u", + sizeof (glibtop_command), sizeof (glibtop_response), + sizeof (glibtop_mountentry), sizeof (glibtop_union), + sizeof (glibtop_sysdeps), + sizeof (glibtop_response_union)); + + while (do_read (s, cmnd, sizeof (glibtop_command))) { + if (enable_debug) + syslog_message (LOG_DEBUG, + "Parent (%d) received command %d from client.", + getpid (), (int) cmnd->command); + + if (cmnd->data_size >= BUFSIZ) { + syslog_message (LOG_WARNING, + "Client sent %d bytes, but buffer is %d", + cmnd->data_size, BUFSIZ); + return; + } + + memset (resp, 0, sizeof (glibtop_response)); + + memset (parameter, 0, sizeof (parameter)); + + if (cmnd->data_size) { + if (enable_debug) + syslog_message (LOG_DEBUG, "Client has %d bytes of data.", + (int) cmnd->data_size); + + do_read (s, parameter, cmnd->data_size); + + } else if (cmnd->size) { + memcpy (parameter, cmnd->parameter, cmnd->size); + } + + switch (cmnd->command) { + case GLIBTOP_CMND_QUIT: + do_output (s, resp, 0, 0, NULL); + return; + case GLIBTOP_CMND_SYSDEPS: + memcpy (&resp->u.sysdeps, &server->sysdeps, + sizeof (glibtop_sysdeps)); + resp->u.sysdeps.features = GLIBTOP_SYSDEPS_ALL; + do_output (s, resp, _offset_union (sysdeps), 0, NULL); + break; + case GLIBTOP_CMND_CPU: + glibtop_get_cpu_l (server, &resp->u.data.cpu); + do_output (s, resp, _offset_data (cpu), 0, NULL); + break; + case GLIBTOP_CMND_MEM: + glibtop_get_mem_l (server, &resp->u.data.mem); + do_output (s, resp, _offset_data (mem), 0, NULL); + break; + case GLIBTOP_CMND_SWAP: + glibtop_get_swap_l (server, &resp->u.data.swap); + do_output (s, resp, _offset_data (swap), 0, NULL); + break; + case GLIBTOP_CMND_UPTIME: + glibtop_get_uptime_l (server, &resp->u.data.uptime); + do_output (s, resp, _offset_data (uptime), 0, NULL); + break; + case GLIBTOP_CMND_LOADAVG: + glibtop_get_loadavg_l (server, &resp->u.data.loadavg); + do_output (s, resp, _offset_data (loadavg), 0, NULL); + break; + case GLIBTOP_CMND_SHM_LIMITS: + glibtop_get_shm_limits_l + (server, &resp->u.data.shm_limits); + do_output (s, resp, _offset_data (shm_limits), 0, NULL); + break; + case GLIBTOP_CMND_MSG_LIMITS: + glibtop_get_msg_limits_l + (server, &resp->u.data.msg_limits); + do_output (s, resp, _offset_data (msg_limits), 0, NULL); + break; + case GLIBTOP_CMND_SEM_LIMITS: + glibtop_get_sem_limits_l + (server, &resp->u.data.sem_limits); + do_output (s, resp, _offset_data (sem_limits), 0, NULL); + break; + case GLIBTOP_CMND_PROCLIST: + param_ptr = (int64_t *) parameter; + ptr = glibtop_get_proclist_l (server, + &resp->u.data.proclist, + param_ptr [0], + param_ptr [1]); + do_output (s, resp, _offset_data (proclist), + resp->u.data.proclist.total, ptr); + glibtop_free_r (server, ptr); + break; + case GLIBTOP_CMND_PROC_MAP: + memcpy (&pid, parameter, sizeof (pid_t)); + ptr = glibtop_get_proc_map_l (server, + &resp->u.data.proc_map, + pid); + do_output (s, resp, _offset_data (proc_map), + resp->u.data.proc_map.total, ptr); + glibtop_free_r (server, ptr); + break; + case GLIBTOP_CMND_PROC_ARGS: + memcpy (&pid, parameter, sizeof (pid_t)); + ptr = glibtop_get_proc_args_l (server, + &resp->u.data.proc_args, + pid, 0); + do_output (s, resp, _offset_data (proc_args), + ptr ? resp->u.data.proc_args.size+1 : 0, ptr); + glibtop_free_r (server, ptr); + break; + case GLIBTOP_CMND_PROC_STATE: + memcpy (&pid, parameter, sizeof (pid_t)); + glibtop_get_proc_state_l + (server, &resp->u.data.proc_state, pid); + do_output (s, resp, _offset_data (proc_state), 0, NULL); + break; + case GLIBTOP_CMND_PROC_UID: + memcpy (&pid, parameter, sizeof (pid_t)); + glibtop_get_proc_uid_l + (server, &resp->u.data.proc_uid, pid); + do_output (s, resp, _offset_data (proc_uid), 0, NULL); + break; + case GLIBTOP_CMND_PROC_MEM: + memcpy (&pid, parameter, sizeof (pid_t)); + glibtop_get_proc_mem_l + (server, &resp->u.data.proc_mem, pid); + do_output (s, resp, _offset_data (proc_mem), 0, NULL); + break; + case GLIBTOP_CMND_PROC_TIME: + memcpy (&pid, parameter, sizeof (pid_t)); + glibtop_get_proc_time_l + (server, &resp->u.data.proc_time, pid); + do_output (s, resp, _offset_data (proc_time), 0, NULL); + break; + case GLIBTOP_CMND_PROC_SIGNAL: + memcpy (&pid, parameter, sizeof (pid_t)); + glibtop_get_proc_signal_l + (server, &resp->u.data.proc_signal, pid); + do_output (s, resp, _offset_data (proc_signal), 0, NULL); + break; + case GLIBTOP_CMND_PROC_KERNEL: + memcpy (&pid, parameter, sizeof (pid_t)); + glibtop_get_proc_kernel_l + (server, &resp->u.data.proc_kernel, pid); + do_output (s, resp, _offset_data (proc_kernel), 0, NULL); + break; + case GLIBTOP_CMND_PROC_SEGMENT: + memcpy (&pid, parameter, sizeof (pid_t)); + glibtop_get_proc_segment_l + (server, &resp->u.data.proc_segment, pid); + do_output (s, resp, _offset_data (proc_segment), 0, NULL); + break; + case GLIBTOP_CMND_MOUNTLIST: + memcpy (&all_fs, parameter, sizeof (all_fs)); + mount_list = glibtop_get_mountlist_l + (server, &resp->u.data.mountlist, all_fs); + do_output (s, resp, _offset_data (mountlist), + resp->u.data.mountlist.total, mount_list); + glibtop_free_r (server, mount_list); + break; + case GLIBTOP_CMND_FSUSAGE: + glibtop_get_fsusage_l + (server, &resp->u.data.fsusage, parameter); + do_output (s, resp, _offset_data (fsusage), + 0, NULL); + break; + case GLIBTOP_CMND_PPP: + memcpy (&device, parameter, sizeof (device)); + glibtop_get_ppp_l + (server, &resp->u.data.ppp, device); + do_output (s, resp, _offset_data (ppp), 0, NULL); + break; + case GLIBTOP_CMND_NETLOAD: + glibtop_get_netload_l + (server, &resp->u.data.netload, parameter); + do_output (s, resp, _offset_data (netload), + 0, NULL); + break; + default: + syslog_message (LOG_ERR, "Parent received unknown command %u.", + cmnd->command); + break; + } + } +} diff --git a/src/daemon/server.c b/src/daemon/server.c new file mode 100644 index 00000000..0657d5e9 --- /dev/null +++ b/src/daemon/server.c @@ -0,0 +1,110 @@ +/* $Id$ */ + +/* Copyright (C) 1998-99 Martin Baulig + This file is part of LibGTop 1.0. + + Contributed by Martin Baulig <martin@home-of-linux.org>, April 1998. + + LibGTop is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + LibGTop is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with LibGTop; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "daemon.h" + +static glibtop _glibtop_global_server; +glibtop *glibtop_global_server = &_glibtop_global_server; + +#include <glibtop.h> +#include <glibtop/union.h> +#include <glibtop/sysdeps.h> + +#include <sys/utsname.h> + +const unsigned long glibtop_server_features = +GLIBTOP_SUID_CPU + +GLIBTOP_SUID_MEM + +GLIBTOP_SUID_SWAP + +GLIBTOP_SUID_UPTIME + +GLIBTOP_SUID_LOADAVG + +GLIBTOP_SUID_SHM_LIMITS + +GLIBTOP_SUID_MSG_LIMITS + +GLIBTOP_SUID_SEM_LIMITS + +GLIBTOP_SUID_PROCLIST + +GLIBTOP_SUID_PROC_STATE + +GLIBTOP_SUID_PROC_UID + +GLIBTOP_SUID_PROC_MEM + +GLIBTOP_SUID_PROC_TIME + +GLIBTOP_SUID_PROC_SIGNAL + +GLIBTOP_SUID_PROC_KERNEL + +GLIBTOP_SUID_PROC_SEGMENT + +GLIBTOP_SUID_PROC_ARGS + +GLIBTOP_SUID_PROC_MAP + +GLIBTOP_SUID_NETLOAD + +GLIBTOP_SUID_PPP; + +#include <fcntl.h> +#include <locale.h> + +int +main(int argc, char *argv[]) +{ + struct utsname uts; + int uid, euid, gid, egid; + + /* !!! WE ARE ROOT HERE - CHANGE WITH CAUTION !!! */ + + uid = getuid (); euid = geteuid (); + gid = getgid (); egid = getegid (); + + if (uname (&uts) < 0) _exit (1); + +#ifdef _AIX + /* + * [FIXME]: should be in sysdeps part ? + */ + + if ((strcmp (uts.sysname, LIBGTOP_COMPILE_SYSTEM) != 0) || + ((atol(uts.version) < atol(LIBGTOP_COMPILE_VERSION)) && + (atol(uts.release) < atol(LIBGTOP_COMPILE_RELEASE))) ) { + fprintf (stderr, "Can only run on %s %s.%s and upper\n", + LIBGTOP_COMPILE_SYSTEM, + LIBGTOP_COMPILE_VERSION, + LIBGTOP_COMPILE_RELEASE); + _exit (1); + } +#else + if (strcmp (uts.sysname, LIBGTOP_COMPILE_SYSTEM) || + strcmp (uts.release, LIBGTOP_COMPILE_RELEASE) || + strcmp (uts.machine, LIBGTOP_COMPILE_MACHINE)) { + fprintf (stderr, "Can only run on %s %s %s\n", + LIBGTOP_COMPILE_SYSTEM, + LIBGTOP_COMPILE_RELEASE, + LIBGTOP_COMPILE_MACHINE); + _exit (1); + } +#endif + + glibtop_init_p (glibtop_global_server, 0, 0); + + if (setreuid (euid, uid)) _exit (1); + + if (setregid (egid, gid)) _exit (1); + + /* !!! END OF SUID ROOT PART !!! */ + + handle_slave_connection (0, 0); + + _exit (0); +} diff --git a/src/daemon/server_config.h b/src/daemon/server_config.h new file mode 100644 index 00000000..09ae9ae8 --- /dev/null +++ b/src/daemon/server_config.h @@ -0,0 +1,11 @@ +#define SERVER_PORT 42800 + +#define SERVER_UID 99 +#define SERVER_GID 99 + +#define HOST_TABLE_ENTRIES 1 + +const char *permitted_host_names [HOST_TABLE_ENTRIES] = +{ NULL }; + +unsigned long permitted_hosts [HOST_TABLE_ENTRIES]; diff --git a/src/daemon/server_config.h.in b/src/daemon/server_config.h.in new file mode 100644 index 00000000..f7884c8d --- /dev/null +++ b/src/daemon/server_config.h.in @@ -0,0 +1,44 @@ +/* -*-c-*- */ + +/* This is a sample config file. + * + * Copy this file to 'server_config.h' and edit it to fix your needs ! + * + * You can also use the 'server_config.pl' script to create 'server_config.h'. + * + */ + +#define SERVER_PORT 42800 /* Port the server should listen on. */ + +/* NOTE: On RedHat 5.1 nobody is UID 99 and GID 99. + * + * The 'server_config.pl' script will use the real UID and GID of 'nobody' + * on your system as default. + * + * NOTE: This only works if the server is started as root or SUID to root. + */ + +#define SERVER_UID 99 /* User ID the server should run as. */ +#define SERVER_GID 99 /* Group ID the server should run as. */ + +#define HOST_TABLE_ENTRIES 1 /* Number of entries in the host table. */ + +/* List of hosts that should be authorized to connect to the server. + * + * SECURITY WARNING: + * Enabling access for a particular hosts means the ALL USERS on this host + * will be allowed to connect to the server ! + * + * If you want security, let this table empty and use the 'xauth' method + * instead. + * + * Look at the manpage of gnuserv (1) as shipped with GNU Emacs for more + * details about security. The server uses the same security mechanisms + * like gnuserv from XEmacs 20.3. + */ + +const char *permitted_host_names [HOST_TABLE_ENTRIES] = +{ NULL }; + +unsigned long permitted_hosts [HOST_TABLE_ENTRIES]; + diff --git a/src/daemon/server_config.pl b/src/daemon/server_config.pl new file mode 100755 index 00000000..3e78ca8f --- /dev/null +++ b/src/daemon/server_config.pl @@ -0,0 +1,111 @@ +#!/usr/bin/perl -w + +require 5.004; +use strict; + +print "Enter port the server should listen on [42800]: "; + +my $port = <stdin>; chop $port; +$port = 42800 unless $port =~ /^\d+$/; + +print "\nUser name or UID to run as [nobody]: "; + +my $user = <stdin>; chop $user; $user = 'nobody' if $user eq ''; + +my ($login, $pass, $uid, $gid); + +unless ($user =~ /^\d+$/) { + ($login, $pass, $uid, $gid) = getpwnam ($user) or + die "User '$user' not in passwd file."; +} + +my $g_default = (defined $gid) ? $gid : 'nogroup'; + +print "Group name or GID to run as [$g_default]: "; + +my $group = <stdin>; chop $group; $group = $g_default if $group eq ''; + +unless ($group =~ /^\d+$/) { + $gid = getgrnam ($group) or + die "Group '$group' not in group file."; +} + +print "\nEnter list of hosts which should be authorized to"; +print "\nconnect to the server (terminate with a blank line):\n\n"; + +print "SECURITY WARNING:\n"; +print " Enabling access for a particular hosts means the ALL USERS on this host will\n"; +print " be allowed to connect to the server !\n\n"; + +print " If you want security, let this table empty and use the 'xauth' method instead.\n"; +print " Look at the manpage of gnuserv (1) as shipped with GNU Emacs for more details\n"; +print " about security. The server uses the same security mechanisms like gnuserv from\n"; +print " XEmacs 20.3\n\n"; + +my @hosts = (); +my @host_addrs = (); +my @host_names = (); + +while (1) { + print "Host: "; + + my $host = <stdin>; chop $host; + last if $host eq ''; + + my ($name,$aliases,$addrtype,$length,@addrs) = gethostbyname ($host) or + die "gethostbyname (): Can't resolve '$host'"; + + my ($a,$b,$c,$d) = unpack('C4',$addrs[0]); + + push @hosts, sprintf ("0x%02X%02X%02X%02X", $d, $c, $b, $a); + push @host_addrs, sprintf ("%d.%d.%d.%d", $a, $b, $c, $d); + push @host_names, $name; +}; + +print "\n"; +print "This is your config:\n"; +print "====================\n\n"; + +printf qq[%-30s: %d\n\n], 'Port', $port; +printf qq[%-30s: %d\n], 'UID', $uid; +printf qq[%-30s: %d\n\n], 'GID', $gid; + +foreach (0..$#hosts) { + printf qq[%-30s (%s - %s)\n], $host_names[$_], $hosts[$_], $host_addrs [$_]; +} + +print "\n"; + +print "Accept? (yes/no) "; + +my $accept = <stdin>; chop $accept; + +exit unless $accept eq 'yes'; + +print "\n"; + +open CONFIG, "> server_config.h" or + die "open (server_config.h): $!"; +select CONFIG; + +printf qq[\#define SERVER_PORT\t\t%d\n\n], $port; + +printf qq[\#define SERVER_UID\t\t%d\n], $uid; +printf qq[\#define SERVER_GID\t\t%d\n\n], $gid; + +printf qq[\#define HOST_TABLE_ENTRIES\t%d\n\n], $#hosts + 1; + +foreach (@host_names) { + $_ = qq["$_"]; +} + +printf qq[const char *permitted_host_names [HOST_TABLE_ENTRIES] = \n]; +printf qq[{ %s };\n\n], join (', ', @host_names); + +printf qq[unsigned long permitted_hosts [HOST_TABLE_ENTRIES];\n]; + +close CONFIG; + +select STDOUT; + +print "Your config has successfully been written to 'server_config.h'.\n"; diff --git a/src/daemon/slave.c b/src/daemon/slave.c new file mode 100644 index 00000000..f8d5a492 --- /dev/null +++ b/src/daemon/slave.c @@ -0,0 +1,256 @@ +/* $Id$ */ + +/* Copyright (C) 1998-99 Martin Baulig + This file is part of LibGTop 1.0. + + Contributed by Martin Baulig <martin@home-of-linux.org>, April 1998. + + LibGTop is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + LibGTop is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with LibGTop; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "daemon.h" + +void +handle_slave_connection (int input, int output) +{ + glibtop *server G_GNUC_UNUSED = glibtop_global_server; + int64_t *param_ptr G_GNUC_UNUSED; + const void *ptr G_GNUC_UNUSED; + + unsigned short max_len G_GNUC_UNUSED; + pid_t pid G_GNUC_UNUSED; + + glibtop_response _resp, *resp = &_resp; + glibtop_command _cmnd, *cmnd = &_cmnd; + char parameter [BUFSIZ]; + + glibtop_send_version (glibtop_global_server, output); + + while (do_read (input, cmnd, sizeof (glibtop_command))) { +#ifdef SLAVE_DEBUG + fprintf (stderr, "Slave %d received command " + "%d from client.\n", getpid (), cmnd->command); +#endif + + if (cmnd->data_size >= BUFSIZ) + glibtop_error ("Client sent %d bytes, " + "but buffer is %d", + cmnd->size, BUFSIZ); + + memset (resp, 0, sizeof (glibtop_response)); + + memset (parameter, 0, sizeof (parameter)); + + if (cmnd->data_size) { +#ifdef SLAVE_DEBUG + fprintf (stderr, "Client has %d bytes of data.\n", + cmnd->data_size); +#endif + + do_read (input, parameter, cmnd->data_size); + + } else if (cmnd->size) { + memcpy (parameter, cmnd->parameter, cmnd->size); + } + + switch (cmnd->command) { + case GLIBTOP_CMND_QUIT: + do_output (output, resp, 0, 0, NULL); + return; +#if GLIBTOP_SUID_PROCLIST + case GLIBTOP_CMND_PROCLIST: + param_ptr = (int64_t *) parameter; + ptr = glibtop_get_proclist_p + (server, &resp->u.data.proclist, + param_ptr [0], param_ptr [1]); + do_output (output, resp, _offset_data (proclist), + resp->u.data.proclist.total, ptr); + glibtop_free_r (server, ptr); + break; +#endif +#if GLIBTOP_SUID_PROC_ARGS + case GLIBTOP_CMND_PROC_ARGS: + memcpy (&pid, parameter, sizeof (pid_t)); + memcpy (&max_len, parameter + sizeof (pid_t), + sizeof (max_len)); + ptr = glibtop_get_proc_args_p (server, + &resp->u.data.proc_args, + pid, max_len); + do_output (output, resp, _offset_data (proc_args), + ptr ? resp->u.data.proc_args.size+1 : 0, + ptr); + glibtop_free_r (server, ptr); + break; +#endif +#if GLIBTOP_SUID_PROC_MAP + case GLIBTOP_CMND_PROC_MAP: + memcpy (&pid, parameter, sizeof (pid_t)); + ptr = glibtop_get_proc_map_p (server, + &resp->u.data.proc_map, + pid); + do_output (output, resp, _offset_data (proc_map), + resp->u.data.proc_map.total, ptr); + glibtop_free_r (server, ptr); + break; +#endif + default: + handle_slave_command (cmnd, resp, parameter); + do_output (output, resp, resp->offset, 0, NULL); + break; + } + } +} + +void +handle_slave_command (glibtop_command *cmnd, glibtop_response *resp, + const void *parameter) +{ + glibtop *server = glibtop_global_server; + unsigned device G_GNUC_UNUSED; + pid_t pid G_GNUC_UNUSED; + + switch (cmnd->command) { + case GLIBTOP_CMND_SYSDEPS: + memcpy (&resp->u.sysdeps, &server->sysdeps, + sizeof (glibtop_sysdeps)); + resp->u.sysdeps.features = glibtop_server_features; + resp->u.sysdeps.flags = glibtop_server_features | + (1L << GLIBTOP_SYSDEPS_FEATURES); + resp->offset = _offset_union (sysdeps); + break; +#if GLIBTOP_SUID_CPU + case GLIBTOP_CMND_CPU: + glibtop_get_cpu_p (server, &resp->u.data.cpu); + resp->offset = _offset_data (cpu); + break; +#endif +#if GLIBTOP_SUID_MEM + case GLIBTOP_CMND_MEM: + glibtop_get_mem_p (server, &resp->u.data.mem); + resp->offset = _offset_data (mem); + break; +#endif +#if GLIBTOP_SUID_SWAP + case GLIBTOP_CMND_SWAP: + glibtop_get_swap_p (server, &resp->u.data.swap); + resp->offset = _offset_data (swap); + break; +#endif +#if GLIBTOP_SUID_UPTIME + case GLIBTOP_CMND_UPTIME: + glibtop_get_uptime_p (server, &resp->u.data.uptime); + resp->offset = _offset_data (uptime); + break; +#endif +#if GLIBTOP_SUID_LOADAVG + case GLIBTOP_CMND_LOADAVG: + glibtop_get_loadavg_p (server, &resp->u.data.loadavg); + resp->offset = _offset_data (loadavg); + break; +#endif +#if GLIBTOP_SUID_SHM_LIMITS + case GLIBTOP_CMND_SHM_LIMITS: + glibtop_get_shm_limits_p (server, &resp->u.data.shm_limits); + resp->offset = _offset_data (shm_limits); + break; +#endif +#if GLIBTOP_SUID_MSG_LIMITS + case GLIBTOP_CMND_MSG_LIMITS: + glibtop_get_msg_limits_p (server, &resp->u.data.msg_limits); + resp->offset = _offset_data (msg_limits); + break; +#endif +#if GLIBTOP_SUID_SEM_LIMITS + case GLIBTOP_CMND_SEM_LIMITS: + glibtop_get_sem_limits_p (server, &resp->u.data.sem_limits); + resp->offset = _offset_data (sem_limits); + break; +#endif +#if GLIBTOP_SUID_PROC_STATE + case GLIBTOP_CMND_PROC_STATE: + memcpy (&pid, parameter, sizeof (pid_t)); + glibtop_get_proc_state_p + (server, &resp->u.data.proc_state, pid); + resp->offset = _offset_data (proc_state); + break; +#endif +#if GLIBTOP_SUID_PROC_UID + case GLIBTOP_CMND_PROC_UID: + memcpy (&pid, parameter, sizeof (pid_t)); + glibtop_get_proc_uid_p + (server, &resp->u.data.proc_uid, pid); + resp->offset = _offset_data (proc_uid); + break; +#endif +#if GLIBTOP_SUID_PROC_MEM + case GLIBTOP_CMND_PROC_MEM: + memcpy (&pid, parameter, sizeof (pid_t)); + glibtop_get_proc_mem_p + (server, &resp->u.data.proc_mem, pid); + resp->offset = _offset_data (proc_mem); + break; +#endif +#if GLIBTOP_SUID_PROC_TIME + case GLIBTOP_CMND_PROC_TIME: + memcpy (&pid, parameter, sizeof (pid_t)); + glibtop_get_proc_time_p + (server, &resp->u.data.proc_time, pid); + resp->offset = _offset_data (proc_time); + break; +#endif +#if GLIBTOP_SUID_PROC_SIGNAL + case GLIBTOP_CMND_PROC_SIGNAL: + memcpy (&pid, parameter, sizeof (pid_t)); + glibtop_get_proc_signal_p + (server, &resp->u.data.proc_signal, pid); + resp->offset = _offset_data (proc_signal); + break; +#endif +#if GLIBTOP_SUID_PROC_KERNEL + case GLIBTOP_CMND_PROC_KERNEL: + memcpy (&pid, parameter, sizeof (pid_t)); + glibtop_get_proc_kernel_p + (server, &resp->u.data.proc_kernel, pid); + resp->offset = _offset_data (proc_kernel); + break; +#endif +#if GLIBTOP_SUID_PROC_SEGMENT + case GLIBTOP_CMND_PROC_SEGMENT: + memcpy (&pid, parameter, sizeof (pid_t)); + glibtop_get_proc_segment_p + (server, &resp->u.data.proc_segment, pid); + resp->offset = _offset_data (proc_segment); + break; +#endif +#if GLIBTOP_SUID_NETLOAD + case GLIBTOP_CMND_NETLOAD: + glibtop_get_netload_p (server, &resp->u.data.netload, parameter); + resp->offset = _offset_data (netload); + break; +#endif +#if GLIBTOP_SUID_PPP + case GLIBTOP_CMND_PPP: + memcpy (&device, parameter, sizeof (unsigned short)); + glibtop_get_ppp_p (server, &resp->u.data.ppp, device); + resp->offset = _offset_data (ppp); + break; +#endif + default: + glibtop_error ("Child received unknown command %u", + cmnd->command); + break; + } +} diff --git a/src/daemon/version.c b/src/daemon/version.c new file mode 100644 index 00000000..d80d6412 --- /dev/null +++ b/src/daemon/version.c @@ -0,0 +1,62 @@ +/* $Id$ */ + +/* Copyright (C) 1998-99 Martin Baulig + This file is part of LibGTop 1.0. + + Contributed by Martin Baulig <martin@home-of-linux.org>, April 1998. + + LibGTop is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + LibGTop is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with LibGTop; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <glibtop.h> +#include <glibtop/error.h> +#include <glibtop/version.h> + +void +glibtop_send_version (glibtop *server, int fd) +{ + char buffer [BUFSIZ]; + size_t size; + + sprintf (buffer, LIBGTOP_VERSION_STRING, + LIBGTOP_VERSION, LIBGTOP_SERVER_VERSION, + sizeof (glibtop_command), + sizeof (glibtop_response), + sizeof (glibtop_union), + sizeof (glibtop_sysdeps)); + + size = strlen (buffer) + 1; + +#ifdef DEBUG + fprintf (stderr, "SERVER ID: |%s|\n", buffer); +#endif + + if (fd == 0) { + if (write (1, (const void *) &size, sizeof (size)) < 0) + glibtop_warn_io_r (server, "write"); + } else { + if (send (fd, (const void *) &size, sizeof (size), 0) < 0) + glibtop_warn_io_r (server, "send"); + } + + if (fd == 0) { + if (write (1, (const void *) buffer, size) < 0) + glibtop_warn_io_r (server, "write"); + } else { + if (send (fd, (const void *) buffer, size, 0) < 0) + glibtop_warn_io_r (server, "send"); + } +} diff --git a/src/inodedb/file_by_inode.c b/src/inodedb/file_by_inode2.c index 5d87c7b1..8e4370fe 100644 --- a/src/inodedb/file_by_inode.c +++ b/src/inodedb/file_by_inode2.c @@ -1,5 +1,3 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ - /* $Id$ */ /* Copyright (C) 1998-99 Martin Baulig @@ -35,33 +33,33 @@ int main (int argc, const char *argv []) { - glibtop_inodedb *inodedb; - const char *filename; - unsigned device, inode; + glibtop_inodedb *inodedb; + const char *filename; + unsigned device, inode; - if (argc != 3) { - fprintf (stderr, "Usage: %s device inode\n", argv [0]); - exit (1); - } + if (argc != 3) { + fprintf (stderr, "Usage: %s device inode\n", argv [0]); + exit (1); + } - if (sscanf (argv [1], "%d", &device) != 1) { - fprintf (stderr, "Usage: %s device inode\n", argv [0]); - exit (1); - } + if (sscanf (argv [1], "%d", &device) != 1) { + fprintf (stderr, "Usage: %s device inode\n", argv [0]); + exit (1); + } - if (sscanf (argv [2], "%d", &inode) != 1) { - fprintf (stderr, "Usage: %s device inode\n", argv [0]); - exit (1); - } + if (sscanf (argv [2], "%d", &inode) != 1) { + fprintf (stderr, "Usage: %s device inode\n", argv [0]); + exit (1); + } - inodedb = glibtop_inodedb_open (0, 0); - if (!inodedb) exit (1); + inodedb = glibtop_inodedb_open (0, 0); + if (!inodedb) exit (1); - filename = glibtop_inodedb_lookup (inodedb, device, inode); - if (!filename) exit (2); + filename = glibtop_inodedb_lookup (inodedb, device, inode); + if (!filename) exit (2); - fprintf (stderr, "FILENAME: %d - %d - '%s'\n", - (int) device, (int) inode, filename); + fprintf (stderr, "FILENAME: %d - %d - '%s'\n", + (int) device, (int) inode, filename); - exit (0); + exit (0); } diff --git a/src/inodedb/mkinodedb.c b/src/inodedb/mkinodedb.c deleted file mode 100644 index 678b5ce7..00000000 --- a/src/inodedb/mkinodedb.c +++ /dev/null @@ -1,137 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ - -/* $Id$ */ - -/* Copyright (C) 1998-99 Martin Baulig - This file is part of LibGTop 1.0. - - Contributed by Martin Baulig <martin@home-of-linux.org>, April 1998. - - LibGTop is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. - - LibGTop is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License - along with LibGTop; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -#include <glibtop.h> -#include <glibtop/error.h> -#include <glibtop/inodedb.h> - -#include <pwd.h> -#include <dirent.h> - -#include <sys/stat.h> - -int -main (int argc, char *argv []) -{ - GDBM_FILE dbf; - char dirname [BUFSIZ]; - FILE *f; - - if (argc != 3) { - fprintf (stderr, "Usage: %s database filename\n", argv [0]); - exit (1); - } - - f = fopen (argv [2], "rt"); - if (!f) - glibtop_error_io ("fopen (%s)", argv [2]); - - dbf = gdbm_open (argv [1], 512, GDBM_WRCREAT, 0600, 0); - if (!dbf) - glibtop_error_io ("gdbm_open (%s)", argv [1]); - - while (fgets (dirname, BUFSIZ-1, f)) { - struct dirent *entry; - struct stat statb; - DIR *directory; - size_t len; - - len = strlen (dirname); - if (!len) continue; - - if (dirname [len-1] == '\n') - dirname [len-1] = 0; - - if (stat (dirname, &statb)) - continue; - - if (S_ISREG (statb.st_mode)) { - glibtop_inodedb_key key; - datum d_key, d_content; - - d_key.dptr = (void *) &key; - d_key.dsize = sizeof (key); - - d_content.dptr = dirname; - d_content.dsize = strlen (dirname) + 1; - - key.device = (u_int64_t) statb.st_dev; - key.inode = (u_int64_t) statb.st_ino; - - if (gdbm_store (dbf, d_key, d_content, GDBM_REPLACE)) - glibtop_error_io ("gdbm_store (%s)", dirname); - - printf ("%-52s - %8lu - %8lu\n", - dirname, (unsigned long) statb.st_dev, - (unsigned long) statb.st_ino); - - continue; - } - - if (!S_ISDIR (statb.st_mode)) - continue; - - directory = opendir (dirname); - if (!directory) continue; - - while ((entry = readdir (directory))) { - glibtop_inodedb_key key; - char filename [BUFSIZ]; - datum d_key, d_content; - - sprintf (filename, "%s/%s", dirname, entry->d_name); - - if (stat (filename, &statb)) - continue; - - if (!S_ISREG (statb.st_mode)) - continue; - - d_key.dptr = (void *) &key; - d_key.dsize = sizeof (key); - - d_content.dptr = filename; - d_content.dsize = strlen (filename) + 1; - - key.device = (u_int64_t) statb.st_dev; - key.inode = (u_int64_t) statb.st_ino; - - if (gdbm_store (dbf, d_key, d_content, GDBM_REPLACE)) - glibtop_error_io ("gdbm_store (%s)", filename); - - printf ("%-52s - %8lu - %8lu\n", - filename, (unsigned long) statb.st_dev, - (unsigned long) statb.st_ino); - } - - closedir (directory); - } - - gdbm_close (dbf); - - fclose (f); - - exit (0); -} diff --git a/src/inodedb/mkinodedb2.c b/src/inodedb/mkinodedb2.c new file mode 100644 index 00000000..a338d322 --- /dev/null +++ b/src/inodedb/mkinodedb2.c @@ -0,0 +1,135 @@ +/* $Id$ */ + +/* Copyright (C) 1998-99 Martin Baulig + This file is part of LibGTop 1.0. + + Contributed by Martin Baulig <martin@home-of-linux.org>, April 1998. + + LibGTop is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + LibGTop is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with LibGTop; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <glibtop.h> +#include <glibtop/error.h> +#include <glibtop/inodedb.h> + +#include <pwd.h> +#include <dirent.h> + +#include <sys/stat.h> + +int +main (int argc, char *argv []) +{ + GDBM_FILE dbf; + char dirname [BUFSIZ]; + FILE *f; + + if (argc != 3) { + fprintf (stderr, "Usage: %s database filename\n", argv [0]); + exit (1); + } + + f = fopen (argv [2], "rt"); + if (!f) + glibtop_error_io ("fopen (%s)", argv [2]); + + dbf = gdbm_open (argv [1], 512, GDBM_WRCREAT, 0600, 0); + if (!dbf) + glibtop_error_io ("gdbm_open (%s)", argv [1]); + + while (fgets (dirname, BUFSIZ-1, f)) { + struct dirent *entry; + struct stat statb; + DIR *directory; + size_t len; + + len = strlen (dirname); + if (!len) continue; + + if (dirname [len-1] == '\n') + dirname [len-1] = 0; + + if (stat (dirname, &statb)) + continue; + + if (S_ISREG (statb.st_mode)) { + glibtop_inodedb_key key; + datum d_key, d_content; + + d_key.dptr = (void *) &key; + d_key.dsize = sizeof (key); + + d_content.dptr = dirname; + d_content.dsize = strlen (dirname) + 1; + + key.device = (u_int64_t) statb.st_dev; + key.inode = (u_int64_t) statb.st_ino; + + if (gdbm_store (dbf, d_key, d_content, GDBM_REPLACE)) + glibtop_error_io ("gdbm_store (%s)", dirname); + + printf ("%-52s - %8lu - %8lu\n", + dirname, (unsigned long) statb.st_dev, + (unsigned long) statb.st_ino); + + continue; + } + + if (!S_ISDIR (statb.st_mode)) + continue; + + directory = opendir (dirname); + if (!directory) continue; + + while ((entry = readdir (directory))) { + glibtop_inodedb_key key; + char filename [BUFSIZ]; + datum d_key, d_content; + + sprintf (filename, "%s/%s", dirname, entry->d_name); + + if (stat (filename, &statb)) + continue; + + if (!S_ISREG (statb.st_mode)) + continue; + + d_key.dptr = (void *) &key; + d_key.dsize = sizeof (key); + + d_content.dptr = filename; + d_content.dsize = strlen (filename) + 1; + + key.device = (u_int64_t) statb.st_dev; + key.inode = (u_int64_t) statb.st_ino; + + if (gdbm_store (dbf, d_key, d_content, GDBM_REPLACE)) + glibtop_error_io ("gdbm_store (%s)", filename); + + printf ("%-52s - %8lu - %8lu\n", + filename, (unsigned long) statb.st_dev, + (unsigned long) statb.st_ino); + } + + closedir (directory); + } + + gdbm_close (dbf); + + fclose (f); + + exit (0); +} |