* md5sum (GNU textutils; alternatively, Colin Plumb's, as shipped with
Debian in the `dpkg' package) - used during build only
-* GNU m4 (only if you need to change the m4 input)
+* GNU m4 [fixme: should ship the output]
* GNU make
* GNU flex [fixme: should ship the output]
* GCC is preferred but other compilers ought to work (though
The bug is actually in your system header files, for not specifying
the number and types of arguments to signal handler functions when
they cast in the SIG_IGN and SIG_DFL macros.
+
+DEBUGGING VERSION
+
+If you run configure with --enable-debug, a debugging version will be
+built. This will look in the current directory (the build directory)
+for the base of various things, including the IPC area (which you must
+therefore construct yourself). The debugging version will produce
+extra output at various points. It will not attempt to call
+setgroups(), instead just checking that the groups list is right, so
+it will work non-setuid if the daemon is invoked as the service user.
+The daemon won't fork for each request; instead, it will handle a
+single request and exit.
+
+There may be other changes. Consult the code for details. Making the
+debugging version of the client or daemon setuid root is probably a
+bad idea. They may not work if they are run as different users.
# userv - Makefile.in
#
-# Copyright (C)1996-1997 Ian Jackson
+# Copyright (C)1996-1997,1999 Ian Jackson
#
# This is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
CFLAGS=@CFLAGS@ $(XCFLAGS) -DVERSION='"$(VERSION)"' -DVEREXT='"$(VEREXT)"' $(WERROR)
OPTIMISE=@OPTIMISE@
CPPFLAGS=@DEBUGDEFS@ $(XCPPFLAGS)
-LDLIBS=@DEBUGLIBS@ $(XLDLIBS)
+LDLIBS=@DEBUGLIBS@ @LIBS@ $(XLDLIBS)
M4=m4
M4FLAGS=
$(INSTALL_PROGRAM) -s -o root -g root -m 4755 client $(bindir)/userv
$(INSTALL) -d -o root -g root -m 2755 $(etcsubdir) \
$(etcsubdir)/default.d $(etcsubdir)/services.d $(etcsubdir)/override.d
- if ! test -f $(etcsubdir)/system.default; then \
+ if test ! -f $(etcsubdir)/system.default; then \
$(INSTALL_DATA) -o root -g root system.default $(etcsubdir); fi
- if ! test -f $(etcsubdir)/system.override; then \
+ if test ! -f $(etcsubdir)/system.override; then \
$(INSTALL_DATA) -o root -g root system.override $(etcsubdir); fi
daemon: overlord.o process.o servexec.o parserlexer.o debug.o lib.o both.o
$(CC) -c $(CPPFLAGS) $(CFLAGS) lexer.c -o $@
pcsum.h: common.h config.h config.status Makefile
- cat $^ | md5sum | sed -e 's/../0x&,/g; s/,$$//;' >pcsum.h.new
+ cat $^ | md5sum | sed -e 's/ -$$//; s/../0x&,/g; s/,$$//;' >pcsum.h.new
cmp pcsum.h.new pcsum.h || mv -f pcsum.h.new pcsum.h
@rm -f pcsum.h.new
* userv - acconfig.h
* extra stuff for config.h.in (autoconf)
*
- * Copyright (C)1996-1997 Ian Jackson
+ * Copyright (C)1996-1997,1999 Ian Jackson
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
/* Define if EPROTO exists. */
#undef HAVE_EPROTO
+/* Define if LOG_AUTHPRIV exists. */
+#undef HAVE_LOG_AUTHPRIV
+
/* Define if function attributes a la GCC 2.5 and higher are available. */
#undef HAVE_GNUC25_ATTRIB
#define EPROTO 0
#endif
+/* LOG_AUTHPRIV */
+#ifndef HAVE_LOG_AUTHPRIV
+#define LOG_AUTHPRIV LOG_AUTH
+#endif
+
/* GNU C attributes. */
#ifndef FUNCATTR
#ifdef HAVE_GNUC25_ATTRIB
* userv - client.c
* client code
*
- * Copyright (C)1996-1997 Ian Jackson
+ * Copyright (C)1996-1997,1999 Ian Jackson
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
static gid_t mygid, spoofgid, *gidarray;
static int ngids;
static struct opening_msg opening_mbuf;
-static const char *logname;
+static const char *loginname;
static char *cwdbuf;
static size_t cwdbufsize;
static char *ovbuf;
spoofuid= myuid;
spoofgid= mygid;
- logname= getenv("LOGNAME");
- if (!logname) logname= getenv("USER");
- if (logname) {
- pw= getpwnam(logname);
- if (!pw || pw->pw_uid != myuid) logname= 0;
+ loginname= getenv("LOGNAME");
+ if (!loginname) loginname= getenv("USER");
+ if (loginname) {
+ pw= getpwnam(loginname);
+ if (!pw || pw->pw_uid != myuid) loginname= 0;
}
- if (!logname) {
+ if (!loginname) {
pw= getpwuid(myuid); if (!pw) miscerror("cannot determine your login name");
- logname= pw->pw_name;
+ loginname= pw->pw_name;
}
- if (!strcmp(serviceuser,"-")) serviceuser= logname;
+ if (!strcmp(serviceuser,"-")) serviceuser= loginname;
pw= getpwnam(serviceuser);
if (!pw) miscerror("requested service user `%s' is not a user",serviceuser);
serviceuid= pw->pw_uid;
" the user who will be providing the service");
if (spoofuser) {
- logname= spoofuser;
- pw= getpwnam(logname);
- if (!pw) miscerror("spoofed login name `%s' is not valid",logname);
+ loginname= spoofuser;
+ pw= getpwnam(loginname);
+ if (!pw) miscerror("spoofed login name `%s' is not valid",loginname);
spoofuid= pw->pw_uid;
spoofgid= pw->pw_gid;
ngidssize= ngids; ngids= 0;
}
gidarray[ngids++]= spoofgid;
while ((gr= getgrent())) { /* ouch! getgrent has no error behaviour! */
- for (mem= gr->gr_mem; *mem && strcmp(*mem,logname); mem++);
+ for (mem= gr->gr_mem; *mem && strcmp(*mem,loginname); mem++);
if (!*mem) continue;
if (ngids>=ngidssize) {
if (ngids>=MAX_GIDS) miscerror("spoofed user is member of too many groups");
request_mbuf.clientpid= getpid();
request_mbuf.serviceuserlen= strlen(serviceuser);
request_mbuf.servicelen= strlen(argv[0]);
- request_mbuf.lognamelen= strlen(logname);
+ request_mbuf.loginnamelen= strlen(loginname);
request_mbuf.spoofed= spoofuser ? 1 : 0;
request_mbuf.cwdlen= cwdbufsize;
request_mbuf.callinguid= spoofuid;
xfwrite(&request_mbuf,sizeof(request_mbuf),swfile);
xfwrite(serviceuser,sizeof(*serviceuser)*request_mbuf.serviceuserlen,swfile);
xfwrite(argv[0],sizeof(*argv[0])*request_mbuf.servicelen,swfile);
- xfwrite(logname,sizeof(*logname)*request_mbuf.lognamelen,swfile);
+ xfwrite(loginname,sizeof(*loginname)*request_mbuf.loginnamelen,swfile);
xfwrite(cwdbuf,sizeof(*cwdbuf)*request_mbuf.cwdlen,swfile);
if (ovused>=0) xfwrite(ovbuf,sizeof(*ovbuf)*ovused,swfile);
xfwrite(&spoofgid,sizeof(gid_t),swfile);
* userv - common.h
* definitions shared between client and daemon
*
- * Copyright (C)1996-1997 Ian Jackson
+ * Copyright (C)1996-1997,1999 Ian Jackson
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
pid_t clientpid; /* or -1 if no service is required and this was a version check */
int serviceuserlen;
int servicelen;
- int lognamelen, spoofed; /* spoofed is 0 or 1 */
+ int loginnamelen, spoofed; /* spoofed is 0 or 1 */
int cwdlen, overridelen;
uid_t callinguid;
int ngids, nreadfds, nwritefds, nargs, nvars;
/* Followed by:
* serviceuserlen bytes for the service user (unterminated)
* servicelen bytes for the service (unterminated)
- * lognamelen bytes for the login name (unterminated)
+ * loginnamelen bytes for the login name (unterminated)
* cwdlen bytes for the cwd (unterminated)
* overridelen bytes for the override data (with extra \n but unterminated),
* or nothing if overridelen==-1
# userv - configure.in
#
-# Copyright (C)1996-1997 Ian Jackson
+# Copyright (C)1996-1997,1999 Ian Jackson
#
# This is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
CFLAGS="$CFLAGS -D_GNU_SOURCE"
+AC_CHECK_LIB(socket,socket)
+AC_CHECK_FUNCS(setenv)
+
AC_CACHE_CHECK(for EPROTO,userv_cv_hdr_eproto,
AC_EGREP_CPP(yes,
[
AC_DEFINE(HAVE_EPROTO)
fi
+AC_CACHE_CHECK(for LOG_AUTHPRIV,userv_cv_hdr_logauthpriv,
+ AC_EGREP_CPP(yes,
+[
+#include <syslog.h>
+#ifdef LOG_AUTHPRIV
+ yes
+#endif
+],userv_cv_hdr_logauthpriv=yes,userv_cv_hdr_logauthpriv=no))
+if test $userv_cv_hdr_logauthpriv = yes
+then
+ AC_DEFINE(HAVE_LOG_AUTHPRIV)
+fi
+
AC_SUBST(OPTIMISE)
if test "${GCC-no}" = yes; then
OPTIMISE=-O2
* userv - daemon.h
* definitions used in the daemon's source code
*
- * Copyright (C)1996-1997 Ian Jackson
+ * Copyright (C)1996-1997,1999 Ian Jackson
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
extern int restfdwantstate, restfdwantrw;
extern int service_ngids;
extern char **argarray;
-extern char *serviceuser, *service, *logname, *cwd;
+extern char *serviceuser, *service, *loginname, *cwd;
extern char *overridedata, *userrcfile;
extern char *serviceuser_dir, *serviceuser_shell, *callinguser_shell;
extern gid_t *calling_gids, *service_gids;
-userv (0.61) unstable; urgency=low
-
- * Document locations of required programs in INSTALL.
-
- --
+userv (0.61.0) unreleased; urgency=low
+
+ INSTALL improvements:
+ * Document locations of required programs.
+ * Sort-of document debugging version.
+
+ Portability fixes for:
+ * md5sum with extra `-'.
+ * -lsocket required for socket().
+ * missing `LOG_AUTHPRIV'.
+ * `logname' name clash.
+ * missing setenv() (synthesize using putenv).
+ * various required #include's were omitted.
+ * install rule in Makefile `if ! test ...' changed to `if test ! ...'
+
+ -- Ian Jackson <ian@davenant.greenend.org.uk> Wed, 7 Apr 1999 23:32:45 +0100
userv (0.60.3) frozen unstable; urgency=medium
* userv - ddebug.c
* routines which are different for -DDEBUG
*
- * Copyright (C)1996-1997 Ian Jackson
+ * Copyright (C)1996-1997,1999 Ian Jackson
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
"calling uid: %ld\n"
"calling user shell: `%s'\n"
"calling groups:",
- logname, (long)request_mbuf.callinguid,
+ loginname, (long)request_mbuf.callinguid,
callinguser_shell);
groupsdump(request_mbuf.ngids,calling_gids,calling_groups);
printf("\n"
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
+#include <assert.h>
#include <sys/types.h>
#include "config.h"
vsnytprintfcat(buffer,size,fmt,al);
va_end(al);
}
+
+#ifndef HAVE_SETENV
+int setenv(const char *name, const char *value, int overwrite) {
+ static char *buffer= 0;
+ static int avail= 0;
+
+ int r;
+
+ assert(overwrite==1);
+ r= makeroom(&buffer,&avail,strlen(name)+strlen(value)+2);
+ if (r) { errno= EINVAL; return -1; }
+
+ sprintf(buffer,"%s=%s",name,value);
+ return putenv(buffer);
+}
+#endif /* HAVE_SETENV */
void snytprintfcat(char *buffer, size_t size, const char *fmt, ...) PRINTFFORMAT(3,4);
void strnytcat(char *dest, const char *src, size_t size);
+#ifndef HAVE_SETENV
+int setenv(const char *name, const char *value, int overwrite);
+#endif /* HAVE_SETENV */
+
#endif /* LIB_H */
* userv - overlord.c
* daemon main program, collects request and forks handlers
*
- * Copyright (C)1996-1997 Ian Jackson
+ * Copyright (C)1996-1997,1999 Ian Jackson
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
#include <fnmatch.h>
#include <sys/wait.h>
#include <sys/types.h>
-#include <sys/time.h>
#include <sys/stat.h>
#include <sys/socket.h>
-#include <sys/fcntl.h>
+#include <fcntl.h>
+#include <time.h>
#include <dirent.h>
#include <sys/un.h>
request_mbuf.clientpid= -1;
request_mbuf.serviceuserlen= 0;
request_mbuf.servicelen= 0;
- request_mbuf.lognamelen= 0;
+ request_mbuf.loginnamelen= 0;
request_mbuf.spoofed= 0;
request_mbuf.cwdlen= 0;
request_mbuf.overridelen= -1;
}
static int pf_callinguser(int ptoken, char ***rvalues) {
- return parm_usernameuid(rvalues,logname,request_mbuf.callinguid);
+ return parm_usernameuid(rvalues,loginname,request_mbuf.callinguid);
}
static int pf_serviceuser(int ptoken, char ***rvalues) {
#include <ctype.h>
#include <limits.h>
#include <sys/wait.h>
-#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
#include <sys/fcntl.h>
#include <sys/stat.h>
#include <sys/socket.h>
int restfdwantstate= tokv_word_rejectfd, restfdwantrw;
int service_ngids;
char **argarray;
-char *serviceuser, *service, *logname, *cwd;
+char *serviceuser, *service, *loginname, *cwd;
char *overridedata, *userrcfile;
char *serviceuser_dir, *serviceuser_shell, *callinguser_shell;
gid_t *calling_gids, *service_gids;
serviceuser= xfreadsetstring(request_mbuf.serviceuserlen);
service= xfreadsetstring(request_mbuf.servicelen);
assert(request_mbuf.spoofed==0 || request_mbuf.spoofed==1);
- logname= xfreadsetstring(request_mbuf.lognamelen);
+ loginname= xfreadsetstring(request_mbuf.loginnamelen);
cwd= xfreadsetstring(request_mbuf.cwdlen);
if (request_mbuf.overridelen >= 0) {
assert(request_mbuf.overridelen <= MAX_OVERRIDE_LEN);
static void lookup_uidsgids(void) {
struct passwd *pw;
- pw= getpwnam(logname);
+ pw= getpwnam(loginname);
if (!pw) miscerror("look up calling user");
- assert(!strcmp(pw->pw_name,logname));
+ assert(!strcmp(pw->pw_name,loginname));
callinguser_shell= xstrsave(pw->pw_shell);
pw= getpwnam(serviceuser);
debug_dumprequest(mypid);
syslog(LOG_INFO,"%s %s -> %s %c %s",
request_mbuf.spoofed ? "spoof" : "user",
- logname, serviceuser, overridedata?'!':':', service);
+ loginname, serviceuser, overridedata?'!':':', service);
if (overridedata)
r= parse_string(TOPLEVEL_OVERRIDDEN_CONFIGURATION,
if (sigaction(signo,&sig,0)) serv_syscallfail("reset signal handler");
}
-static const char *see_logname(void) { return serviceuser; }
+static const char *see_loginname(void) { return serviceuser; }
static const char *see_home(void) { return serviceuser_dir; }
static const char *see_shell(void) { return serviceuser_shell; }
static const char *see_service(void) { return service; }
static const char *see_c_cwd(void) { return cwd; }
-static const char *see_c_logname(void) { return logname; }
+static const char *see_c_loginname(void) { return loginname; }
static const char *see_c_uid(void) {
static char buf[CHAR_BIT*sizeof(uid_t)/3+4];
snyprintf(buf,sizeof(buf),"%lu",(unsigned long)request_mbuf.callinguid);
const char *name;
const char *(*fn)(void);
} serv_envinfos[]= {
- { "USER", see_logname },
- { "LOGNAME", see_logname },
- { "HOME", see_home },
- { "SHELL", see_shell },
- { "PATH", defaultpath },
- { "USERV_SERVICE", see_service },
- { "USERV_CWD", see_c_cwd },
- { "USERV_USER", see_c_logname },
- { "USERV_UID", see_c_uid },
- { "USERV_GROUP", see_c_group },
- { "USERV_GID", see_c_gid },
- { 0 }
+ { "USER", see_loginname },
+ { "LOGNAME", see_loginname },
+ { "HOME", see_home },
+ { "SHELL", see_shell },
+ { "PATH", defaultpath },
+ { "USERV_SERVICE", see_service },
+ { "USERV_CWD", see_c_cwd },
+ { "USERV_USER", see_c_loginname },
+ { "USERV_UID", see_c_uid },
+ { "USERV_GROUP", see_c_group },
+ { "USERV_GID", see_c_gid },
+ { 0 }
};
void execservice(const int synchsocket[], int clientfd) {