From 78032a78185e751a0bf0b77863f23d005359205f Mon Sep 17 00:00:00 2001 From: ian Date: Wed, 7 Apr 1999 22:33:33 +0000 Subject: [PATCH] Portability and doc fixes, including my own portability patches and some suggestions from Julian King. --- INSTALL | 18 +++++++++++++++++- Makefile.in | 10 +++++----- acconfig.h | 10 +++++++++- client.c | 32 ++++++++++++++++---------------- common.h | 6 +++--- configure.in | 18 +++++++++++++++++- daemon.h | 4 ++-- debian/changelog | 21 ++++++++++++++++----- debug.c | 4 ++-- lib.c | 17 +++++++++++++++++ lib.h | 4 ++++ overlord.c | 8 ++++---- parser.c | 2 +- process.c | 13 +++++++------ servexec.c | 28 ++++++++++++++-------------- 15 files changed, 134 insertions(+), 61 deletions(-) diff --git a/INSTALL b/INSTALL index 304f2a3..3fe9052 100644 --- a/INSTALL +++ b/INSTALL @@ -14,7 +14,7 @@ Programs: * 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 @@ -205,3 +205,19 @@ PROBLEMS 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. diff --git a/Makefile.in b/Makefile.in index 593daec..88d8bb5 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,6 +1,6 @@ # 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 @@ -23,7 +23,7 @@ CC=@CC@ CFLAGS=@CFLAGS@ $(XCFLAGS) -DVERSION='"$(VERSION)"' -DVEREXT='"$(VEREXT)"' $(WERROR) OPTIMISE=@OPTIMISE@ CPPFLAGS=@DEBUGDEFS@ $(XCPPFLAGS) -LDLIBS=@DEBUGLIBS@ $(XLDLIBS) +LDLIBS=@DEBUGLIBS@ @LIBS@ $(XLDLIBS) M4=m4 M4FLAGS= @@ -61,9 +61,9 @@ install: all $(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 @@ -95,7 +95,7 @@ parserlexer.o: lexer.c parser.c config.h common.h pcsum.h daemon.h lib.h tokens. $(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 diff --git a/acconfig.h b/acconfig.h index 6e2356e..80cec87 100644 --- a/acconfig.h +++ b/acconfig.h @@ -2,7 +2,7 @@ * 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 @@ -22,6 +22,9 @@ /* 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 @@ -41,6 +44,11 @@ #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 diff --git a/client.c b/client.c index 243a333..ff9de73 100644 --- a/client.c +++ b/client.c @@ -2,7 +2,7 @@ * 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 @@ -128,7 +128,7 @@ static uid_t myuid, spoofuid; 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; @@ -855,18 +855,18 @@ static void determine_users(void) { 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; @@ -876,9 +876,9 @@ static void determine_users(void) { " 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; @@ -888,7 +888,7 @@ static void determine_users(void) { } 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"); @@ -1050,7 +1050,7 @@ static void server_sendrequest(int argc, char *const *argv) { 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; @@ -1069,7 +1069,7 @@ static void server_sendrequest(int argc, char *const *argv) { 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); diff --git a/common.h b/common.h index f385fc9..6b287da 100644 --- a/common.h +++ b/common.h @@ -2,7 +2,7 @@ * 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 @@ -85,14 +85,14 @@ struct request_msg { 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 diff --git a/configure.in b/configure.in index 2c7bb2d..ae8f041 100644 --- a/configure.in +++ b/configure.in @@ -1,6 +1,6 @@ # 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 @@ -44,6 +44,9 @@ AC_PROG_INSTALL 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, [ @@ -57,6 +60,19 @@ then AC_DEFINE(HAVE_EPROTO) fi +AC_CACHE_CHECK(for LOG_AUTHPRIV,userv_cv_hdr_logauthpriv, + AC_EGREP_CPP(yes, +[ +#include +#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 diff --git a/daemon.h b/daemon.h index 945d651..7db8440 100644 --- a/daemon.h +++ b/daemon.h @@ -2,7 +2,7 @@ * 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 @@ -157,7 +157,7 @@ extern int fdarraysize, fdarrayused; 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; diff --git a/debian/changelog b/debian/changelog index 8abf253..02fd2e3 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,19 @@ -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 Wed, 7 Apr 1999 23:32:45 +0100 userv (0.60.3) frozen unstable; urgency=medium diff --git a/debug.c b/debug.c index 6612545..5ec6f94 100644 --- a/debug.c +++ b/debug.c @@ -2,7 +2,7 @@ * 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 @@ -160,7 +160,7 @@ void debug_dumprequest(pid_t mypid) { "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" diff --git a/lib.c b/lib.c index 7a22d19..bd40ee0 100644 --- a/lib.c +++ b/lib.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include "config.h" @@ -112,3 +113,19 @@ void snytprintfcat(char *buffer, size_t size, const char *fmt, ...) { 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 */ diff --git a/lib.h b/lib.h index c38f243..7d78cb9 100644 --- a/lib.h +++ b/lib.h @@ -56,4 +56,8 @@ void vsnytprintfcat(char *buffer, size_t size, const char *fmt, va_list al); 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 */ diff --git a/overlord.c b/overlord.c index b18102f..dfb58a2 100644 --- a/overlord.c +++ b/overlord.c @@ -2,7 +2,7 @@ * 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 @@ -29,10 +29,10 @@ #include #include #include -#include #include #include -#include +#include +#include #include #include @@ -228,7 +228,7 @@ static void NONRETURNING docheck(void) { 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; diff --git a/parser.c b/parser.c index b00baac..5f6ebad 100644 --- a/parser.c +++ b/parser.c @@ -499,7 +499,7 @@ static int pf_service(int ptoken, char ***rvalues) { } 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) { diff --git a/process.c b/process.c index 3ca468c..64afd5c 100644 --- a/process.c +++ b/process.c @@ -52,7 +52,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -74,7 +75,7 @@ int fdarraysize, fdarrayused; 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; @@ -414,7 +415,7 @@ static void receive_request(void) { 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); @@ -496,9 +497,9 @@ static void groupnames(int ngids, gid_t *gids, const char ***names_r) { 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); @@ -723,7 +724,7 @@ void servicerequest(int sfd) { 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, diff --git a/servexec.c b/servexec.c index 95c77a5..c1614f0 100644 --- a/servexec.c +++ b/servexec.c @@ -138,13 +138,13 @@ static void serv_resetsignal(int signo) { 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); @@ -184,18 +184,18 @@ static const struct serv_envinfo { 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) { -- 2.30.2