Blob


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