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 'k':
45 keypattern = EARGF(usage());
46 break;
47 default:
48 usage();
49 }ARGEND
51 if(argc != 1 && argc != 2)
52 usage();
54 addr = netmkaddr(argv[0], "tcp", "9fs");
55 if((fd = dial(addr, nil, nil, nil)) < 0)
56 sysfatal("dial %s: %r", addr);
58 if(doauth)
59 xauth();
61 if(argc == 2)
62 service = argv[1];
63 else
64 service = argv[0];
66 if(post9pservice(fd, service) < 0)
67 sysfatal("post9pservice: %r");
69 threadexitsall(0);
70 }
72 void
73 do9p(Fcall *tx, Fcall *rx)
74 {
75 static uchar buf[9000];
76 static char ebuf[200];
77 int n;
79 n = convS2M(tx, buf, sizeof buf);
80 if(n == BIT16SZ){
81 werrstr("convS2M failed");
82 goto err;
83 }
84 if(debug)
85 fprint(2, "<- %F\n", tx);
86 if(write(fd, buf, n) != n)
87 goto err;
88 if((n = read9pmsg(fd, buf, sizeof buf)) < 0)
89 goto err;
90 if(n == 0){
91 werrstr("unexpected eof");
92 goto err;
93 }
94 if(convM2S(buf, n, rx) != n){
95 werrstr("convM2S failed");
96 goto err;
97 }
98 if(debug)
99 fprint(2, "-> %F\n", rx);
100 if(rx->type != Rerror && rx->type != tx->type+1){
101 werrstr("unexpected type");
102 goto err;
104 if(rx->tag != tx->tag){
105 werrstr("unexpected tag");
106 goto err;
108 return;
110 err:
111 rerrstr(ebuf, sizeof ebuf);
112 rx->ename = ebuf;
113 rx->type = Rerror;
114 return;
117 void
118 xauth(void)
120 Fcall tx, rx;
122 afid = 0;
123 tx.type = Tversion;
124 tx.tag = NOTAG;
125 tx.version = "9P2000";
126 tx.msize = 8192;
127 do9p(&tx, &rx);
128 if(rx.type == Rerror)
129 sysfatal("Tversion: %s", rx.ename);
130 msize = rx.msize;
132 tx.type = Tauth;
133 tx.tag = 1;
134 tx.afid = afid;
135 tx.uname = getuser();
136 tx.aname = aname;
137 do9p(&tx, &rx);
138 if(rx.type == Rerror){
139 fprint(2, "rx: %s\n", rx.ename);
140 afid = NOFID;
141 return;
144 if(xauth_proxy(auth_getkey, "proto=p9any role=client %s", keypattern) == nil)
145 sysfatal("authproxy: %r");
148 int
149 xread(void *buf, int n)
151 Fcall tx, rx;
153 tx.type = Tread;
154 tx.tag = 1;
155 tx.fid = 0; /* afid above */
156 tx.count = n;
157 tx.offset = 0;
158 do9p(&tx, &rx);
159 if(rx.type == Rerror){
160 werrstr("%s", rx.ename);
161 return -1;
164 if(rx.count > n){
165 werrstr("too much data returned");
166 return -1;
168 memmove(buf, rx.data, rx.count);
169 return rx.count;
172 int
173 xwrite(void *buf, int n)
175 Fcall tx, rx;
177 tx.type = Twrite;
178 tx.tag = 1;
179 tx.fid = 0; /* afid above */
180 tx.data = buf;
181 tx.count = n;
182 tx.offset = 0;
183 do9p(&tx, &rx);
184 if(rx.type == Rerror){
185 werrstr("%s", rx.ename);
186 return -1;
188 return n;
192 /*
193 * changed to add -A below
194 */
195 #undef _exits
196 int
197 post9pservice(int fd, char *name)
199 int i;
200 char *ns, *s;
201 Waitmsg *w;
203 if((ns = getns()) == nil)
204 return -1;
206 s = smprint("unix!%s/%s", ns, name);
207 free(ns);
208 if(s == nil)
209 return -1;
210 switch(fork()){
211 case -1:
212 return -1;
213 case 0:
214 dup(fd, 0);
215 dup(fd, 1);
216 for(i=3; i<20; i++)
217 close(i);
218 if(doauth)
219 execlp("9pserve", "9pserve", "-u",
220 "-M",
221 smprint("%d", msize),
222 "-A",
223 aname,
224 smprint("%d", afid),
225 s, (char*)0);
226 else
227 execlp("9pserve", "9pserve", "-u", s, (char*)0);
228 fprint(2, "exec 9pserve: %r\n");
229 _exits("exec");
230 default:
231 w = wait();
232 if(w == nil)
233 return -1;
234 close(fd);
235 free(s);
236 if(w->msg && w->msg[0]){
237 free(w);
238 werrstr("9pserve failed");
239 return -1;
241 free(w);
242 return 0;
246 enum { ARgiveup = 100 };
247 static int
248 dorpc(AuthRpc *rpc, char *verb, char *val, int len, AuthGetkey *getkey)
250 int ret;
252 for(;;){
253 if((ret = auth_rpc(rpc, verb, val, len)) != ARneedkey && ret != ARbadkey)
254 return ret;
255 if(getkey == nil)
256 return ARgiveup; /* don't know how */
257 if((*getkey)(rpc->arg) < 0)
258 return ARgiveup; /* user punted */
263 /*
264 * this just proxies what the factotum tells it to.
265 */
266 AuthInfo*
267 xfauth_proxy(AuthRpc *rpc, AuthGetkey *getkey, char *params)
269 char *buf;
270 int m, n, ret;
271 AuthInfo *a;
272 char oerr[ERRMAX];
274 rerrstr(oerr, sizeof oerr);
275 werrstr("UNKNOWN AUTH ERROR");
277 if(dorpc(rpc, "start", params, strlen(params), getkey) != ARok){
278 werrstr("fauth_proxy start: %r");
279 return nil;
282 buf = malloc(AuthRpcMax);
283 if(buf == nil)
284 return nil;
285 for(;;){
286 switch(dorpc(rpc, "read", nil, 0, getkey)){
287 case ARdone:
288 free(buf);
289 a = auth_getinfo(rpc);
290 errstr(oerr, sizeof oerr); /* no error, restore whatever was there */
291 return a;
292 case ARok:
293 if(xwrite(rpc->arg, rpc->narg) != rpc->narg){
294 werrstr("auth_proxy write fid: %r");
295 goto Error;
297 break;
298 case ARphase:
299 n = 0;
300 memset(buf, 0, AuthRpcMax);
301 while((ret = dorpc(rpc, "write", buf, n, getkey)) == ARtoosmall){
302 if(atoi(rpc->arg) > AuthRpcMax)
303 break;
304 m = xread(buf+n, atoi(rpc->arg)-n);
305 if(m <= 0){
306 if(m == 0)
307 werrstr("auth_proxy short read: %s", buf);
308 goto Error;
310 n += m;
312 if(ret != ARok){
313 werrstr("auth_proxy rpc write: %s: %r", buf);
314 goto Error;
316 break;
317 default:
318 werrstr("auth_proxy rpc: %r");
319 goto Error;
322 Error:
323 free(buf);
324 return nil;
327 AuthInfo*
328 xauth_proxy(AuthGetkey *getkey, char *fmt, ...)
330 char *p;
331 va_list arg;
332 AuthInfo *ai;
333 AuthRpc *rpc;
335 quotefmtinstall(); /* just in case */
336 va_start(arg, fmt);
337 p = vsmprint(fmt, arg);
338 va_end(arg);
340 rpc = auth_allocrpc();
341 if(rpc == nil){
342 free(p);
343 return nil;
346 ai = xfauth_proxy(rpc, getkey, p);
347 free(p);
348 auth_freerpc(rpc);
349 return ai;