345 lines · 5.7 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <auth.h>#include <fcall.h>#include <thread.h> int post9p(int, char*);int debug;char *aname = "";char *keypattern = "";int fd;int msize;int doauth;u32int afid = NOFID;extern char *post9parg;	/* clumsy hack */void xauth(void);AuthInfo* xauth_proxy(AuthGetkey *getkey, char *fmt, ...); voidusage(void){	fprint(2, "usage: srv [-a] [-A aname] [-k keypattern] addr [srvname]\n");	threadexitsall("usage");} int	mainstacksize = 640000; voidthreadmain(int argc, char **argv){	char *addr, *service; 	fmtinstall('F', fcallfmt);	fmtinstall('M', dirmodefmt);		ARGBEGIN{	case 'D':		debug = 1;		break;	case 'A':		/* BUG: should be able to repeat this and establish multiple afids */		aname = EARGF(usage());		break;	case 'a':		doauth = 1;		break;	case 'n':		doauth = -1;		break;	case 'k':		keypattern = EARGF(usage());		break;	default:		usage();	}ARGEND		if(argc != 1 && argc != 2)		usage(); 	addr = netmkaddr(argv[0], "tcp", "9fs");	if((fd = dial(addr, nil, nil, nil)) < 0)		sysfatal("dial %s: %r", addr); 	if(doauth > 0)		xauth(); 	if(argc == 2)		service = argv[1];	else		service = argv[0]; //	rfork(RFNOTEG);	if(post9p(fd, service) < 0)		sysfatal("post9p: %r"); 	threadexits(0);} voiddo9p(Fcall *tx, Fcall *rx){	static uchar buf[9000];	static char ebuf[200];	int n;		n = convS2M(tx, buf, sizeof buf);	if(n == BIT16SZ){		werrstr("convS2M failed");		goto err;	}	if(debug)		fprint(2, "<- %F\n", tx);	if(write(fd, buf, n) != n)		goto err;	if((n = read9pmsg(fd, buf, sizeof buf)) < 0)		goto err;	if(n == 0){		werrstr("unexpected eof");		goto err;	}	if(convM2S(buf, n, rx) != n){		werrstr("convM2S failed");		goto err;	}	if(debug)		fprint(2, "-> %F\n", rx);	if(rx->type != Rerror && rx->type != tx->type+1){		werrstr("unexpected type");		goto err;	}	if(rx->tag != tx->tag){		werrstr("unexpected tag");		goto err;	}	return; err:	rerrstr(ebuf, sizeof ebuf);	rx->ename = ebuf;	rx->type = Rerror;	return;} voidxauth(void){	Fcall tx, rx; 	afid = 0;	tx.type = Tversion;	tx.tag = NOTAG;	tx.version = "9P2000";	tx.msize = 8192;	do9p(&tx, &rx);	if(rx.type == Rerror)		sysfatal("Tversion: %s", rx.ename);	msize = rx.msize;		tx.type = Tauth;	tx.tag = 1;	tx.afid = afid;	tx.uname = getuser();	tx.aname = aname;	do9p(&tx, &rx);	if(rx.type == Rerror){		fprint(2, "rx: %s\n", rx.ename);		afid = NOFID;		return;	} 	if(xauth_proxy(auth_getkey, "proto=p9any role=client %s", keypattern) == nil)		sysfatal("authproxy: %r");} intxread(void *buf, int n){	Fcall tx, rx;		tx.type = Tread;	tx.tag = 1;	tx.fid = 0;	/* afid above */	tx.count = n;	tx.offset = 0;	do9p(&tx, &rx);	if(rx.type == Rerror){		werrstr("%s", rx.ename);		return -1;	}		if(rx.count > n){		werrstr("too much data returned");		return -1;	}	memmove(buf, rx.data, rx.count);	return rx.count;} intxwrite(void *buf, int n){	Fcall tx, rx;		tx.type = Twrite;	tx.tag = 1;	tx.fid = 0;	/* afid above */	tx.data = buf;	tx.count = n;	tx.offset = 0;	do9p(&tx, &rx);	if(rx.type == Rerror){		werrstr("%s", rx.ename);		return -1;	}	return n;}  /* * changed to add -A below */intpost9p(int fd, char *name){	int fds[3];	char *ns, *s;	Waitmsg *w;	Channel *cwait; 	if((ns = getns()) == nil)		return -1; 	s = smprint("unix!%s/%s", ns, name);	free(ns);	if(s == nil)		return -1; 	cwait = threadwaitchan(); 	fds[0] = fd;	fds[1] = fd;	fds[2] = dup(2, -1);	if (threadspawnl(fds, "9pserve", "9pserve",				doauth < 0 ? "-nu" : "-u", s, (char*)0) <0)		return -1;		w = recvp(cwait);	if(w == nil)		return -1;	free(s);	if(w->msg && w->msg[0]){		free(w);		werrstr("9pserve failed");		return -1;	}	free(w);	return 0;} enum { ARgiveup = 100 };static intdorpc(AuthRpc *rpc, char *verb, char *val, int len, AuthGetkey *getkey){	int ret; 	for(;;){		if((ret = auth_rpc(rpc, verb, val, len)) != ARneedkey && ret != ARbadkey)			return ret;		if(getkey == nil)			return ARgiveup;	/* don't know how */		if((*getkey)(rpc->arg) < 0)			return ARgiveup;	/* user punted */	}}  /* *  this just proxies what the factotum tells it to. */AuthInfo*xfauth_proxy(AuthRpc *rpc, AuthGetkey *getkey, char *params){	char *buf;	int m, n, ret;	AuthInfo *a;	char oerr[ERRMAX]; 	rerrstr(oerr, sizeof oerr);	werrstr("UNKNOWN AUTH ERROR"); 	if(dorpc(rpc, "start", params, strlen(params), getkey) != ARok){		werrstr("fauth_proxy start: %r");		return nil;	} 	buf = malloc(AuthRpcMax);	if(buf == nil)		return nil;	for(;;){		switch(dorpc(rpc, "read", nil, 0, getkey)){		case ARdone:			free(buf);			a = auth_getinfo(rpc);			errstr(oerr, sizeof oerr);	/* no error, restore whatever was there */			return a;		case ARok:			if(xwrite(rpc->arg, rpc->narg) != rpc->narg){				werrstr("auth_proxy write fid: %r");				goto Error;			}			break;		case ARphase:			n = 0;			memset(buf, 0, AuthRpcMax);			while((ret = dorpc(rpc, "write", buf, n, getkey)) == ARtoosmall){				if(atoi(rpc->arg) > AuthRpcMax)					break;				m = xread(buf+n, atoi(rpc->arg)-n);				if(m <= 0){					if(m == 0)						werrstr("auth_proxy short read: %s", buf);					goto Error;				}				n += m;			}			if(ret != ARok){				werrstr("auth_proxy rpc write: %s: %r", buf);				goto Error;			}			break;		default:			werrstr("auth_proxy rpc: %r");			goto Error;		}	}Error:	free(buf);	return nil;} AuthInfo*xauth_proxy(AuthGetkey *getkey, char *fmt, ...){	char *p;	va_list arg;	AuthInfo *ai;	AuthRpc *rpc; 	quotefmtinstall();	/* just in case */	va_start(arg, fmt);	p = vsmprint(fmt, arg);	va_end(arg); 	rpc = auth_allocrpc();	if(rpc == nil){		free(p);		return nil;	} 	ai = xfauth_proxy(rpc, getkey, p);	free(p);	auth_freerpc(rpc);	return ai;}