From 5c84c448b82c7bfdfeaae533783aa09317656e86 Mon Sep 17 00:00:00 2001 From: rsc Date: Mon, 21 Mar 2005 17:24:21 +0000 Subject: add srv -a option --- src/cmd/srv.c | 318 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 314 insertions(+), 4 deletions(-) (limited to 'src/cmd/srv.c') diff --git a/src/cmd/srv.c b/src/cmd/srv.c index 95dfef88..01c05e64 100644 --- a/src/cmd/srv.c +++ b/src/cmd/srv.c @@ -4,20 +4,46 @@ #include #include +int debug; +char *aname = ""; +char *keypattern = ""; +int fd; +int msize; +int doauth; +int afid = NOFID; +extern char *post9parg; /* clumsy hack */ +void xauth(void); +AuthInfo* xauth_proxy(AuthGetkey *getkey, char *fmt, ...); + void usage(void) { - fprint(2, "usage: srv addr [srvname]\n"); + fprint(2, "usage: srv [-a] [-A aname] [-k keypattern] addr [srvname]\n"); threadexitsall("usage"); } void threadmain(int argc, char **argv) { - int fd; 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 'k': + keypattern = EARGF(usage()); + break; default: usage(); }ARGEND @@ -28,14 +54,298 @@ threadmain(int argc, char **argv) addr = netmkaddr(argv[0], "tcp", "9fs"); if((fd = dial(addr, nil, nil, nil)) < 0) sysfatal("dial %s: %r", addr); - + + if(doauth) + xauth(); + if(argc == 2) service = argv[1]; else service = argv[0]; - + if(post9pservice(fd, service) < 0) sysfatal("post9pservice: %r"); threadexitsall(0); } + +void +do9p(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; +} + +void +xauth(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) < 0) + sysfatal("authproxy: %r"); +} + +int +xread(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; +} + +int +xwrite(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 + */ +#undef _exits +int +post9pservice(int fd, char *name) +{ + int i; + char *ns, *s; + Waitmsg *w; + + if((ns = getns()) == nil) + return -1; + + s = smprint("unix!%s/%s", ns, name); + free(ns); + if(s == nil) + return -1; + switch(fork()){ + case -1: + return -1; + case 0: + dup(fd, 0); + dup(fd, 1); + for(i=3; i<20; i++) + close(i); + if(doauth) + execlp("9pserve", "9pserve", "-u", + "-M", + smprint("%d", msize), + "-A", + aname, + smprint("%d", afid), + s, (char*)0); + else + execlp("9pserve", "9pserve", "-u", s, (char*)0); + fprint(2, "exec 9pserve: %r\n"); + _exits("exec"); + default: + w = wait(); + if(w == nil) + return -1; + close(fd); + free(s); + if(w->msg && w->msg[0]){ + free(w); + werrstr("9pserve failed"); + return -1; + } + free(w); + return 0; + } +} + +enum { ARgiveup = 100 }; +static int +dorpc(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; +} + -- cgit v1.2.3