chiark / gitweb /
Add --spoof-user. Tidy up servicepw &c in daemon.
authorian <ian>
Mon, 25 Aug 1997 00:41:32 +0000 (00:41 +0000)
committerian <ian>
Mon, 25 Aug 1997 00:41:32 +0000 (00:41 +0000)
Makefile.in
client.c
daemon.c
daemon.h
parser.c

index 9448969..5b5ba96 100644 (file)
@@ -44,7 +44,7 @@ SOURCES=      Makefile.in configure.in acconfig.h                     \
 ALSOSHIP=      system.default system.override \
                spec.sgml overview.fig overview.ps \
                COPYING buildship install-sh .cvsignore
-GENSHIP=       lexer.l lexer.c tokens.h pcsum.h configure config.h.in \
+GENSHIP=       lexer.l lexer.c tokens.h configure config.h.in \
                spec.html spec.ps overview.ps
 
 SHIPTARGETS=   $(SOURCES) $(ALSOSHIP) $(GENSHIP)
@@ -77,7 +77,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 version.h config.h config.status Makefile
-               cat $^ | md5sum | perl -pe 's/../0x$$&,/g; s/,$$//;' >pcsum.h.new
+               cat $^ | md5sum | sed -e 's/../0x&,/g; s/,$$//;' >pcsum.h.new
                cmp pcsum.h.new pcsum.h || mv -f pcsum.h.new pcsum.h
 
 tokens.h:      language.i4
index 8ef35a5..9d12491 100644 (file)
--- a/client.c
+++ b/client.c
@@ -29,6 +29,7 @@
 #include <unistd.h>
 #include <ctype.h>
 #include <pwd.h>
+#include <grp.h>
 #include <signal.h>
 #include <limits.h>
 #include <sys/time.h>
@@ -144,7 +145,7 @@ static unsigned long timeout=0;
 static int signalsexit=254;
 static int sigpipeok=0, hidecwd=0;
 static int overridetype= ot_none;
-static const char *overridevalue;
+static const char *overridevalue, *spoofuser=0;
 
 static FILE *srfile, *swfile;
 
@@ -280,12 +281,13 @@ static void usage(void) {
     "         -S|--signals <status>|number|number-nocore|highbit|stdout\n"
     "         -w|--fdwait <fd>=wait|nowait|close\n"
     "         -P|--sigpipe  -H|--hidecwd  -h|--help  --copyright\n"
-    "         --override <configuration-data> } available only to\n"
-    "         --override-file <filename>      } root or same user\n"
+    "         --override <configuration-data> } available only\n"
+    "         --override-file <filename>      }  to root\n"
+    "         --spoof-user <username>         }  or same user\n"
     "fdmodifiers:            read    write  overwrite    trunc[ate]\n"
     "(separate with commas)  append  sync   excl[usive]  creat[e]  fd\n\n"
     "userv and uservd version " VERSION "; copyright (C)1996-1997 Ian Jackson.\n"
-    "They come with NO WARRANTY; type `userv --copyright' for details.\n")
+    "there is NO WARRANTY; type `userv --copyright' for details.\n")
       == EOF) syscallerror("write usage to stderr");
 }
 
@@ -494,6 +496,11 @@ static void of_overridefile(const struct optioninfo *oip,
   overridevalue= value;
 }
 
+static void of_spoofuser(const struct optioninfo *oip,
+                        const char *value, char *key) {
+  spoofuser= value;
+}
+
 const struct optioninfo optioninfos[]= {
   { 'f', "file",          2, of_file         },
   { 'w', "fdwait",        2, of_fdwait       },
@@ -506,6 +513,7 @@ const struct optioninfo optioninfos[]= {
   {  0,  "copyright",     0, of_copyright    },
   {  0,  "override",      1, of_override     },
   {  0,  "override-file", 1, of_overridefile },
+  {  0,  "spoof-user",    1, of_spoofuser    },
   {  0,   0                                  }
 };
 
@@ -662,17 +670,19 @@ int main(int argc, char *const *argv) {
   char *argp;
   const struct optioninfo *oip;
   struct sockaddr_un ssockname;
-  int sfd, ngids, i, j, tempfd, l, c, reading, fd, r, status;
+  int sfd, ngids, i, j, tempfd, l, c, reading, fd, r, status, ngidssize;
   sigset_t sset;
   unsigned long ul;
   size_t cwdbufsize;
-  char *cwdbuf;
+  char *cwdbuf, **mem;
   struct opening_msg opening_mbuf;
   struct request_msg request_mbuf;
   struct progress_msg progress_mbuf;
   struct event_msg event_mbuf;
   struct passwd *pw;
-  gid_t mygid, *gidarray;
+  struct group *gr;
+  gid_t mygid, spoofgid, *gidarray;
+  uid_t spoofuid;
   pid_t mypid;
   const char *logname;
   FILE *ovfile;
@@ -756,19 +766,44 @@ int main(int argc, char *const *argv) {
   if (!pw) miscerror("requested service user `%s' is not a user",serviceuser);
   serviceuid= pw->pw_uid;
 
-  if (overridetype != ot_none && myuid != 0 && myuid != serviceuid)
-    miscerror("--override options only available to root or to"
+  if ((overridetype != ot_none || spoofuser) && myuid != 0 && myuid != serviceuid)
+    miscerror("--override and --spoof options only available to root or to"
               " the user who will be providing the service");
 
-  logname= getenv("LOGNAME");
-  if (!logname) logname= getenv("USER");
-  if (logname) {
+  if (spoofuser) {
+    logname= spoofuser;
     pw= getpwnam(logname);
-    if (!pw || pw->pw_uid != myuid) logname= 0;
-  }
-  if (!logname) {
-    pw= getpwuid(myuid); if (!pw) syscallerror("cannot determine your login name");
-    logname= pw->pw_name;
+    if (!pw) miscerror("spoofed login name `%s' is not valid",logname);
+    spoofuid= pw->pw_uid;
+    spoofgid= pw->pw_gid;
+    ngidssize= ngids; ngids= 0;
+    if (ngidssize<5) {
+      ngidssize= 5;
+      gidarray= xrealloc(gidarray,sizeof(gid_t)*ngidssize);
+    }
+    gidarray[ngids++]= spoofgid;
+    while ((gr= getgrent())) { /* ouch! getgrent has no error behaviour! */
+      for (mem= gr->gr_mem; *mem && strcmp(*mem,logname); mem++);
+      if (!*mem) continue;
+      if (ngids>=ngidssize) {
+       ngidssize= (ngids+5)<<1;
+       gidarray= xrealloc(gidarray,sizeof(gid_t)*ngidssize);
+      }
+      gidarray[ngids++]= gr->gr_gid;
+    }
+  } else {
+    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;
+    }
+    if (!logname) {
+      pw= getpwuid(myuid); if (!pw) miscerror("cannot determine your login name");
+      logname= pw->pw_name;
+    }
   }
 
   cwdbufsize= 0; cwdbuf= 0;
@@ -877,7 +912,7 @@ int main(int argc, char *const *argv) {
   request_mbuf.servicelen= strlen(argv[0]);
   request_mbuf.lognamelen= strlen(logname);
   request_mbuf.cwdlen= cwdbufsize;
-  request_mbuf.callinguid= myuid;
+  request_mbuf.callinguid= spoofuid;
   request_mbuf.ngids= ngids+1;
   request_mbuf.nreadfds= 0;
   request_mbuf.nwritefds= 0;
@@ -896,7 +931,7 @@ int main(int argc, char *const *argv) {
   xfwrite(logname,sizeof(*logname)*request_mbuf.lognamelen,swfile);
   xfwrite(cwdbuf,sizeof(*cwdbuf)*request_mbuf.cwdlen,swfile);
   if (ovused>=0) xfwrite(ovbuf,sizeof(*ovbuf)*ovused,swfile);
-  xfwrite(&mygid,sizeof(gid_t),swfile);
+  xfwrite(&spoofgid,sizeof(gid_t),swfile);
   xfwrite(gidarray,sizeof(gid_t)*ngids,swfile);
   xfwritefds(fdm_read,request_mbuf.nreadfds,swfile);
   xfwritefds(fdm_write,request_mbuf.nwritefds,swfile);
index 49fff81..97bffa5 100644 (file)
--- a/daemon.c
+++ b/daemon.c
@@ -56,7 +56,7 @@ int restfdwantstate= tokv_word_rejectfd, restfdwantrw= 0;
 struct request_msg request_mbuf;
 char *serviceuser=0, *service=0, *logname=0, *cwd=0;
 char *overridedata=0, *userrcfile=0;
-char *serviceuser_dir=0, *serviceuser_shell=0;
+char *serviceuser_dir=0, *serviceuser_shell=0, *callinguser_shell;
 uid_t serviceuser_uid=-1;
 gid_t serviceuser_gid=-1;
 char *execpath=0, **execargs=0;
@@ -67,8 +67,6 @@ char *ehfilename=0;
 
 static FILE *swfile= 0, *srfile= 0;
 static pid_t child= -1, childtokill= -1;
-
-static struct passwd *servicepw, *callingpw;
 static const char **grouparray;
 
 static void sigchildhandler(int x) {
@@ -285,12 +283,12 @@ static int synchread(int fd, int ch) {
   return 0;
 }
 
-static const char *see_logname(void) { return servicepw->pw_name; }
-static const char *see_home(void) { return servicepw->pw_dir; }
-static const char *see_shell(void) { return servicepw->pw_shell; }
+static const char *see_logname(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_path(void) {
-  return servicepw->pw_uid ?
+  return serviceuser_uid ?
     "/usr/local/bin:/bin:/usr/bin" :
     "/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin";
 }
@@ -300,7 +298,7 @@ static const char *see_c_cwd(void) { return cwd; }
 static const char *see_c_logname(void) { return logname; }
 static const char *see_c_uid(void) {
   static char buf[CHAR_BIT*sizeof(uid_t)/3+4];
-  snyprintf(buf,sizeof(buf),"%lu",(unsigned long)callingpw->pw_uid);
+  snyprintf(buf,sizeof(buf),"%lu",(unsigned long)request_mbuf.callinguid);
   return buf;
 }
 
@@ -503,6 +501,7 @@ static void NONRETURNING servicerequest(int sfd) {
   struct stat stab;
   struct sigaction sig;
   struct group *cgrp;
+  struct passwd *pw;
 
   ensurelogopen(USERVD_LOGFACILITY);
   syslog(LOG_DEBUG,"call connected");
@@ -574,28 +573,26 @@ static void NONRETURNING servicerequest(int sfd) {
     if (close(tempfd)) syscallerror("close prelim fd onto pipe");
   }
 
-  servicepw= getpwnam(serviceuser);
-  if (!servicepw) syscallerror("look up service user");
-  assert(!strcmp(servicepw->pw_name,serviceuser));
-  serviceuser_dir= xstrdup(nondebug_serviceuserdir(servicepw->pw_dir));
-  serviceuser_shell= xstrdup(servicepw->pw_shell);
-  serviceuser_uid= servicepw->pw_uid;
-  serviceuser_gid= servicepw->pw_gid;
-  if (initgroups(servicepw->pw_name,servicepw->pw_gid)) syscallerror("initgroups");
-  if (setreuid(servicepw->pw_uid,servicepw->pw_uid)) syscallerror("setreuid 1");
-  if (setreuid(servicepw->pw_uid,servicepw->pw_uid)) syscallerror("setreuid 2");
-  if (servicepw->pw_uid)
-    if (!setreuid(servicepw->pw_uid,0)) miscerror("setreuid 3 unexpectedly succeeded");
+  pw= getpwnam(serviceuser);
+  if (!pw) miscerror("look up service user");
+  assert(!strcmp(pw->pw_name,serviceuser));
+  serviceuser_dir= xstrdup(nondebug_serviceuserdir(pw->pw_dir));
+  serviceuser_shell= xstrdup(pw->pw_shell);
+  serviceuser_uid= pw->pw_uid;
+  serviceuser_gid= pw->pw_gid;
+  if (initgroups(pw->pw_name,pw->pw_gid)) syscallerror("initgroups");
+  if (setreuid(pw->pw_uid,pw->pw_uid)) syscallerror("setreuid 1");
+  if (setreuid(pw->pw_uid,pw->pw_uid)) syscallerror("setreuid 2");
+  if (pw->pw_uid)
+    if (!setreuid(pw->pw_uid,0)) miscerror("setreuid 3 unexpectedly succeeded");
   if (errno != EPERM) syscallerror("setreuid 3 failed in unexpected way");
 
   debug_dumprequest(mypid);
 
-  callingpw= getpwnam(logname);
-  if (!callingpw) syscallerror("get passwd entry for calling user");
   grouparray= xmalloc(sizeof(char*)*request_mbuf.ngids);
   for (i=0; i<request_mbuf.ngids; i++) {
     cgrp= getgrgid(gidarray[i]);
-    if (!cgrp) syscallerror("get group entry for calling group");
+    if (!cgrp) miscerror("get group entry for calling group");
     grouparray[i]= xmstrsave(cgrp->gr_name);
   }
 
index 45bb102..e37b862 100644 (file)
--- a/daemon.h
+++ b/daemon.h
@@ -129,8 +129,8 @@ extern int restfdwantstate, restfdwantrw;
 extern struct request_msg request_mbuf;
 extern char *serviceuser, *service, *logname, *cwd;
 extern char *overridedata, *userrcfile;
-extern char *serviceuser_dir, *serviceuser_shell;
-extern uid_t serviceuser_uid;
+extern char *serviceuser_dir, *serviceuser_shell, *callinguser_shell;
+extern uid_t serviceuser_uid, callinguser_uid;
 extern gid_t serviceuser_gid;
 extern char *execpath, **execargs;
 extern int execute; /* One of the execution modes tokt_execmode */
index e173e3a..2395837 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -694,10 +694,7 @@ int pf_servicegroup(int ptoken, char ***rvalues) {
 }
 
 int pf_callingusershell(int ptoken, char ***rvalues) {
-  struct passwd *pw;
-
-  pw= getpwnam(logname); if (!pw) syscallerror("looking up calling user");
-  parm_1string(rvalues,pw->pw_shell); return 0;
+  parm_1string(rvalues,callinguser_shell); return 0;
 }
 
 int pf_serviceusershell(int ptoken, char ***rvalues) {