plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

srv.c (6001B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <auth.h>
      4 #include <fcall.h>
      5 #include <thread.h>
      6 
      7 int post9p(int, char*);
      8 int debug;
      9 char *aname = "";
     10 char *keypattern = "";
     11 int fd;
     12 int msize;
     13 int doauth;
     14 u32int afid = NOFID;
     15 extern char *post9parg;	/* clumsy hack */
     16 void xauth(void);
     17 AuthInfo* xauth_proxy(AuthGetkey *getkey, char *fmt, ...);
     18 
     19 void
     20 usage(void)
     21 {
     22 	fprint(2, "usage: srv [-a] [-A aname] [-k keypattern] addr [srvname]\n");
     23 	threadexitsall("usage");
     24 }
     25 
     26 void
     27 threadmain(int argc, char **argv)
     28 {
     29 	char *addr, *service;
     30 
     31 	fmtinstall('F', fcallfmt);
     32 	fmtinstall('M', dirmodefmt);
     33 
     34 	ARGBEGIN{
     35 	case 'D':
     36 		debug = 1;
     37 		break;
     38 	case 'A':
     39 		/* BUG: should be able to repeat this and establish multiple afids */
     40 		aname = EARGF(usage());
     41 		break;
     42 	case 'a':
     43 		doauth = 1;
     44 		break;
     45 	case 'n':
     46 		doauth = -1;
     47 		break;
     48 	case 'k':
     49 		keypattern = EARGF(usage());
     50 		break;
     51 	default:
     52 		usage();
     53 	}ARGEND
     54 
     55 	if(argc != 1 && argc != 2)
     56 		usage();
     57 
     58 	addr = netmkaddr(argv[0], "tcp", "9fs");
     59 	if((fd = dial(addr, nil, nil, nil)) < 0)
     60 		sysfatal("dial %s: %r", addr);
     61 
     62 	if(doauth > 0)
     63 		xauth();
     64 
     65 	if(argc == 2)
     66 		service = argv[1];
     67 	else
     68 		service = argv[0];
     69 
     70 	rfork(RFNOTEG);
     71 	if(post9p(fd, service) < 0)
     72 		sysfatal("post9p: %r");
     73 
     74 	threadexitsall(0);
     75 }
     76 
     77 void
     78 do9p(Fcall *tx, Fcall *rx)
     79 {
     80 	static uchar buf[9000];
     81 	static char ebuf[200];
     82 	int n;
     83 
     84 	n = convS2M(tx, buf, sizeof buf);
     85 	if(n == BIT16SZ){
     86 		werrstr("convS2M failed");
     87 		goto err;
     88 	}
     89 	if(debug)
     90 		fprint(2, "<- %F\n", tx);
     91 	if(write(fd, buf, n) != n)
     92 		goto err;
     93 	if((n = read9pmsg(fd, buf, sizeof buf)) < 0)
     94 		goto err;
     95 	if(n == 0){
     96 		werrstr("unexpected eof");
     97 		goto err;
     98 	}
     99 	if(convM2S(buf, n, rx) != n){
    100 		werrstr("convM2S failed");
    101 		goto err;
    102 	}
    103 	if(debug)
    104 		fprint(2, "-> %F\n", rx);
    105 	if(rx->type != Rerror && rx->type != tx->type+1){
    106 		werrstr("unexpected type");
    107 		goto err;
    108 	}
    109 	if(rx->tag != tx->tag){
    110 		werrstr("unexpected tag");
    111 		goto err;
    112 	}
    113 	return;
    114 
    115 err:
    116 	rerrstr(ebuf, sizeof ebuf);
    117 	rx->ename = ebuf;
    118 	rx->type = Rerror;
    119 	return;
    120 }
    121 
    122 void
    123 xauth(void)
    124 {
    125 	Fcall tx, rx;
    126 
    127 	afid = 0;
    128 	tx.type = Tversion;
    129 	tx.tag = NOTAG;
    130 	tx.version = "9P2000";
    131 	tx.msize = 8192;
    132 	do9p(&tx, &rx);
    133 	if(rx.type == Rerror)
    134 		sysfatal("Tversion: %s", rx.ename);
    135 	msize = rx.msize;
    136 
    137 	tx.type = Tauth;
    138 	tx.tag = 1;
    139 	tx.afid = afid;
    140 	tx.uname = getuser();
    141 	tx.aname = aname;
    142 	do9p(&tx, &rx);
    143 	if(rx.type == Rerror){
    144 		fprint(2, "rx: %s\n", rx.ename);
    145 		afid = NOFID;
    146 		return;
    147 	}
    148 
    149 	if(xauth_proxy(auth_getkey, "proto=p9any role=client %s", keypattern) == nil)
    150 		sysfatal("authproxy: %r");
    151 }
    152 
    153 int
    154 xread(void *buf, int n)
    155 {
    156 	Fcall tx, rx;
    157 
    158 	tx.type = Tread;
    159 	tx.tag = 1;
    160 	tx.fid = 0;	/* afid above */
    161 	tx.count = n;
    162 	tx.offset = 0;
    163 	do9p(&tx, &rx);
    164 	if(rx.type == Rerror){
    165 		werrstr("%s", rx.ename);
    166 		return -1;
    167 	}
    168 
    169 	if(rx.count > n){
    170 		werrstr("too much data returned");
    171 		return -1;
    172 	}
    173 	memmove(buf, rx.data, rx.count);
    174 	return rx.count;
    175 }
    176 
    177 int
    178 xwrite(void *buf, int n)
    179 {
    180 	Fcall tx, rx;
    181 
    182 	tx.type = Twrite;
    183 	tx.tag = 1;
    184 	tx.fid = 0;	/* afid above */
    185 	tx.data = buf;
    186 	tx.count = n;
    187 	tx.offset = 0;
    188 	do9p(&tx, &rx);
    189 	if(rx.type == Rerror){
    190 		werrstr("%s", rx.ename);
    191 		return -1;
    192 	}
    193 	return n;
    194 }
    195 
    196 
    197 /*
    198  * changed to add -A below
    199  */
    200 #undef _exits
    201 int
    202 post9p(int fd, char *name)
    203 {
    204 	int i;
    205 	char *ns, *s;
    206 	Waitmsg *w;
    207 
    208 	if((ns = getns()) == nil)
    209 		return -1;
    210 
    211 	s = smprint("unix!%s/%s", ns, name);
    212 	free(ns);
    213 	if(s == nil)
    214 		return -1;
    215 	switch(fork()){
    216 	case -1:
    217 		return -1;
    218 	case 0:
    219 		dup(fd, 0);
    220 		dup(fd, 1);
    221 		for(i=3; i<20; i++)
    222 			close(i);
    223 		if(doauth > 0)
    224 			execlp("9pserve", "9pserve", "-u",
    225 				"-M",
    226 					smprint("%d", msize),
    227 				"-A",
    228 					aname,
    229 					smprint("%d", afid),
    230 				s, (char*)0);
    231 		else
    232 			execlp("9pserve", "9pserve",
    233 				doauth < 0 ? "-nu" : "-u", s, (char*)0);
    234 		fprint(2, "exec 9pserve: %r\n");
    235 		_exits("exec");
    236 	default:
    237 		w = wait();
    238 		if(w == nil)
    239 			return -1;
    240 		close(fd);
    241 		free(s);
    242 		if(w->msg && w->msg[0]){
    243 			free(w);
    244 			werrstr("9pserve failed");
    245 			return -1;
    246 		}
    247 		free(w);
    248 		return 0;
    249 	}
    250 }
    251 
    252 enum { ARgiveup = 100 };
    253 static int
    254 dorpc(AuthRpc *rpc, char *verb, char *val, int len, AuthGetkey *getkey)
    255 {
    256 	int ret;
    257 
    258 	for(;;){
    259 		if((ret = auth_rpc(rpc, verb, val, len)) != ARneedkey && ret != ARbadkey)
    260 			return ret;
    261 		if(getkey == nil)
    262 			return ARgiveup;	/* don't know how */
    263 		if((*getkey)(rpc->arg) < 0)
    264 			return ARgiveup;	/* user punted */
    265 	}
    266 }
    267 
    268 
    269 /*
    270  *  this just proxies what the factotum tells it to.
    271  */
    272 AuthInfo*
    273 xfauth_proxy(AuthRpc *rpc, AuthGetkey *getkey, char *params)
    274 {
    275 	char *buf;
    276 	int m, n, ret;
    277 	AuthInfo *a;
    278 	char oerr[ERRMAX];
    279 
    280 	rerrstr(oerr, sizeof oerr);
    281 	werrstr("UNKNOWN AUTH ERROR");
    282 
    283 	if(dorpc(rpc, "start", params, strlen(params), getkey) != ARok){
    284 		werrstr("fauth_proxy start: %r");
    285 		return nil;
    286 	}
    287 
    288 	buf = malloc(AuthRpcMax);
    289 	if(buf == nil)
    290 		return nil;
    291 	for(;;){
    292 		switch(dorpc(rpc, "read", nil, 0, getkey)){
    293 		case ARdone:
    294 			free(buf);
    295 			a = auth_getinfo(rpc);
    296 			errstr(oerr, sizeof oerr);	/* no error, restore whatever was there */
    297 			return a;
    298 		case ARok:
    299 			if(xwrite(rpc->arg, rpc->narg) != rpc->narg){
    300 				werrstr("auth_proxy write fid: %r");
    301 				goto Error;
    302 			}
    303 			break;
    304 		case ARphase:
    305 			n = 0;
    306 			memset(buf, 0, AuthRpcMax);
    307 			while((ret = dorpc(rpc, "write", buf, n, getkey)) == ARtoosmall){
    308 				if(atoi(rpc->arg) > AuthRpcMax)
    309 					break;
    310 				m = xread(buf+n, atoi(rpc->arg)-n);
    311 				if(m <= 0){
    312 					if(m == 0)
    313 						werrstr("auth_proxy short read: %s", buf);
    314 					goto Error;
    315 				}
    316 				n += m;
    317 			}
    318 			if(ret != ARok){
    319 				werrstr("auth_proxy rpc write: %s: %r", buf);
    320 				goto Error;
    321 			}
    322 			break;
    323 		default:
    324 			werrstr("auth_proxy rpc: %r");
    325 			goto Error;
    326 		}
    327 	}
    328 Error:
    329 	free(buf);
    330 	return nil;
    331 }
    332 
    333 AuthInfo*
    334 xauth_proxy(AuthGetkey *getkey, char *fmt, ...)
    335 {
    336 	char *p;
    337 	va_list arg;
    338 	AuthInfo *ai;
    339 	AuthRpc *rpc;
    340 
    341 	quotefmtinstall();	/* just in case */
    342 	va_start(arg, fmt);
    343 	p = vsmprint(fmt, arg);
    344 	va_end(arg);
    345 
    346 	rpc = auth_allocrpc();
    347 	if(rpc == nil){
    348 		free(p);
    349 		return nil;
    350 	}
    351 
    352 	ai = xfauth_proxy(rpc, getkey, p);
    353 	free(p);
    354 	auth_freerpc(rpc);
    355 	return ai;
    356 }