182 lines · 2.8 KB · C
RawDownload
/* * as user cmd [arg...] - run cmd with args as user on this cpu server. *	must be hostowner for this to work. *	needs #¤/caphash and #¤/capuse. */#include <u.h>#include <libc.h>#include <bio.h>#include <libsec.h>#include <auth.h>#include "authcmdlib.h" int	debug; int	becomeuser(char*);void	createuser(void);void	*emalloc(ulong);void	*erealloc(void*, ulong);void	initcap(void);int	mkcmd(char*, char*, int);int	myauth(int, char*);int	qidcmp(Qid, Qid);void	runas(char *, char *);void	usage(void); #pragma varargck	argpos clog 1#pragma varargck	argpos fatal 1 static voidfatal(char *fmt, ...){	char msg[256];	va_list arg; 	va_start(arg, fmt);	vseprint(msg, msg + sizeof msg, fmt, arg);	va_end(arg);	error("%s", msg);} voidmain(int argc, char *argv[]){	debug = 0;	ARGBEGIN{	case 'd':		debug = 1;		break;	default:		usage();	}ARGEND 	initcap();	srand(getpid()*time(0));	runas(argv[0], argv[1]);} voidrunas(char *user, char *cmd){	if(becomeuser(user) < 0)		sysfatal("can't change uid for %s: %r", user);	putenv("service", "rx");	execl("/bin/rc", "rc", "-lc", cmd, nil);	sysfatal("exec /bin/rc: %r");} void *emalloc(ulong n){	void *p; 	if(p = mallocz(n, 1))		return p;	fatal("out of memory");	return 0;} void *erealloc(void *p, ulong n){	if(p = realloc(p, n))		return p;	fatal("out of memory");	return 0;} voidusage(void){	fprint(2, "usage: %s [-c]\n", argv0);	exits("usage");} voidmemrandom(void *p, int n){	uchar *cp; 	for(cp = (uchar*)p; n > 0; n--)		*cp++ = fastrand();} /* *  keep caphash fd open since opens of it could be disabled */static int caphashfd; voidinitcap(void){	caphashfd = open("#¤/caphash", OCEXEC|OWRITE);	if(caphashfd < 0)		fprint(2, "%s: opening #¤/caphash: %r\n", argv0);} /* *  create a change uid capability  */char*mkcap(char *from, char *to){	uchar rand[20];	char *cap;	char *key;	int nfrom, nto, ncap;	uchar hash[SHA1dlen]; 	if(caphashfd < 0)		return nil; 	/* create the capability */	nto = strlen(to);	nfrom = strlen(from);	ncap = nfrom + 1 + nto + 1 + sizeof(rand)*3 + 1;	cap = emalloc(ncap);	snprint(cap, ncap, "%s@%s", from, to);	memrandom(rand, sizeof(rand));	key = cap+nfrom+1+nto+1;	enc64(key, sizeof(rand)*3, rand, sizeof(rand)); 	/* hash the capability */	hmac_sha1((uchar*)cap, strlen(cap), (uchar*)key, strlen(key), hash, nil); 	/* give the kernel the hash */	key[-1] = '@';	if(write(caphashfd, hash, SHA1dlen) < 0){		free(cap);		return nil;	} 	return cap;} intusecap(char *cap){	int fd, rv; 	fd = open("#¤/capuse", OWRITE);	if(fd < 0)		return -1;	rv = write(fd, cap, strlen(cap));	close(fd);	return rv;} intbecomeuser(char *new){	char *cap;	int rv; 	cap = mkcap(getuser(), new);	if(cap == nil)		return -1;	rv = usecap(cap);	free(cap); 	newns(new, nil);	return rv;}