Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <auth.h>
4 #include <fcall.h>
5 #include <thread.h>
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, ...);
19 void
20 usage(void)
21 {
22 fprint(2, "usage: srv [-a] [-A aname] [-k keypattern] addr [srvname]\n");
23 threadexitsall("usage");
24 }
26 void
27 threadmain(int argc, char **argv)
28 {
29 char *addr, *service;
31 fmtinstall('F', fcallfmt);
32 fmtinstall('M', dirmodefmt);
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
55 if(argc != 1 && argc != 2)
56 usage();
58 addr = netmkaddr(argv[0], "tcp", "9fs");
59 if((fd = dial(addr, nil, nil, nil)) < 0)
60 sysfatal("dial %s: %r", addr);
62 if(doauth > 0)
63 xauth();
65 if(argc == 2)
66 service = argv[1];
67 else
68 service = argv[0];
70 rfork(RFNOTEG);
71 if(post9p(fd, service) < 0)
72 sysfatal("post9p: %r");
74 threadexitsall(0);
75 }
77 void
78 do9p(Fcall *tx, Fcall *rx)
79 {
80 static uchar buf[9000];
81 static char ebuf[200];
82 int n;
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;
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;
109 if(rx->tag != tx->tag){
110 werrstr("unexpected tag");
111 goto err;
113 return;
115 err:
116 rerrstr(ebuf, sizeof ebuf);
117 rx->ename = ebuf;
118 rx->type = Rerror;
119 return;
122 void
123 xauth(void)
125 Fcall tx, rx;
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;
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;
149 if(xauth_proxy(auth_getkey, "proto=p9any role=client %s", keypattern) == nil)
150 sysfatal("authproxy: %r");
153 int
154 xread(void *buf, int n)
156 Fcall tx, rx;
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;
169 if(rx.count > n){
170 werrstr("too much data returned");
171 return -1;
173 memmove(buf, rx.data, rx.count);
174 return rx.count;
177 int
178 xwrite(void *buf, int n)
180 Fcall tx, rx;
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;
193 return n;
197 /*
198 * changed to add -A below
199 */
200 #undef _exits
201 int
202 post9p(int fd, char *name)
204 int i;
205 char *ns, *s;
206 Waitmsg *w;
208 if((ns = getns()) == nil)
209 return -1;
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;
247 free(w);
248 return 0;
252 enum { ARgiveup = 100 };
253 static int
254 dorpc(AuthRpc *rpc, char *verb, char *val, int len, AuthGetkey *getkey)
256 int ret;
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 */
269 /*
270 * this just proxies what the factotum tells it to.
271 */
272 AuthInfo*
273 xfauth_proxy(AuthRpc *rpc, AuthGetkey *getkey, char *params)
275 char *buf;
276 int m, n, ret;
277 AuthInfo *a;
278 char oerr[ERRMAX];
280 rerrstr(oerr, sizeof oerr);
281 werrstr("UNKNOWN AUTH ERROR");
283 if(dorpc(rpc, "start", params, strlen(params), getkey) != ARok){
284 werrstr("fauth_proxy start: %r");
285 return nil;
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;
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;
316 n += m;
318 if(ret != ARok){
319 werrstr("auth_proxy rpc write: %s: %r", buf);
320 goto Error;
322 break;
323 default:
324 werrstr("auth_proxy rpc: %r");
325 goto Error;
328 Error:
329 free(buf);
330 return nil;
333 AuthInfo*
334 xauth_proxy(AuthGetkey *getkey, char *fmt, ...)
336 char *p;
337 va_list arg;
338 AuthInfo *ai;
339 AuthRpc *rpc;
341 quotefmtinstall(); /* just in case */
342 va_start(arg, fmt);
343 p = vsmprint(fmt, arg);
344 va_end(arg);
346 rpc = auth_allocrpc();
347 if(rpc == nil){
348 free(p);
349 return nil;
352 ai = xfauth_proxy(rpc, getkey, p);
353 free(p);
354 auth_freerpc(rpc);
355 return ai;