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 }