From: ian Date: Mon, 25 Aug 1997 00:41:32 +0000 (+0000) Subject: Add --spoof-user. Tidy up servicepw &c in daemon. X-Git-Tag: release-0-50~7 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=userv.git;a=commitdiff_plain;h=b613cadfdf189af1f4ee0b5bdc12cedda052c672;ds=inline Add --spoof-user. Tidy up servicepw &c in daemon. --- diff --git a/Makefile.in b/Makefile.in index 9448969..5b5ba96 100644 --- a/Makefile.in +++ b/Makefile.in @@ -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 diff --git a/client.c b/client.c index 8ef35a5..9d12491 100644 --- a/client.c +++ b/client.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -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 |number|number-nocore|highbit|stdout\n" " -w|--fdwait =wait|nowait|close\n" " -P|--sigpipe -H|--hidecwd -h|--help --copyright\n" - " --override } available only to\n" - " --override-file } root or same user\n" + " --override } available only\n" + " --override-file } to root\n" + " --spoof-user } 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); diff --git a/daemon.c b/daemon.c index 49fff81..97bffa5 100644 --- 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; igr_name); } diff --git a/daemon.h b/daemon.h index 45bb102..e37b862 100644 --- 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 */ diff --git a/parser.c b/parser.c index e173e3a..2395837 100644 --- 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) {