7 * Must be paired write/read cycles on /mnt/factotum/rpc.
8 * The format of a request is verb, single space, data.
9 * Data format is verb-dependent; in particular, it can be binary.
10 * The format of a response is the same. The write only sets up
11 * the RPC. The read tries to execute it. If the /mnt/factotum/key
12 * file is open, we ask for new keys using that instead of returning
13 * an error in the RPC. This means the read blocks.
14 * Textual arguments are parsed with tokenize, so rc-style quoting
17 * Only authentication protocol messages go here. Configuration
18 * is still via ctl (below).
21 * start attrs - initializes protocol for authentication, can fail.
22 * returns "ok read" or "ok write" on success.
23 * read - execute protocol read
24 * write - execute protocol write
25 * authinfo - if the protocol is finished, return the AI if any
26 * attr - return protocol information
28 * error message - an error happened.
29 * ok [data] - success, possible data is request dependent.
30 * needkey attrs - request aborted, get me this key and try again
31 * badkey attrs - request aborted, this key might be bad
32 * done [haveai] - authentication is done [haveai: you can get an ai with authinfo]
52 for(i=1; i<nelem(rpcname); i++)
53 if(strcmp(s, rpcname[i]) == 0)
59 rpcwrite(Conv *c, void *data, int count)
65 werrstr("rpc too large");
69 /* cancel any current rpc */
70 c->rpc.op = RpcUnknown;
74 memmove(c->rpcbuf, data, count);
76 if(p = (uchar*)strchr((char*)c->rpcbuf, ' ')){
79 c->rpc.count = count - (p - (uchar*)c->rpcbuf);
84 op = classify(c->rpcbuf);
86 werrstr("bad rpc verb: %s", c->rpcbuf);
104 a = parseattr(c->rpc.data);
106 werrstr("empty attr");
110 proto = strfindattr(a, "proto");
111 role = strfindattr(a, "role");
114 werrstr("no proto in attrs");
118 werrstr("no role in attrs");
122 p = protolookup(proto);
124 werrstr("unknown proto %s", proto);
129 for(r=p->roles; r->name; r++){
130 if(strcmp(r->name, role) != 0)
134 if((*r->fn)(c) == 0){
136 werrstr("protocol finished");
138 werrstr("%s %s %s: %r", p->name, r->name, c->state);
141 werrstr("unknown role");
146 rerrstr(c->err, sizeof c->err);
147 rpcrespond(c, "error %r");
151 static uchar* convAI2M(uchar *p, int n, char *cuid, char *suid, char *cap, char *hex);
161 c->rpc.op = RpcWrite;
162 if(dec16(c->rpc.data, c->rpc.count, c->rpc.data, c->rpc.count) != c->rpc.count/2){
163 rpcrespond(c, "bad hex");
173 if(c->rpc.count > 0){
174 rpcrespond(c, "error read takes no parameters");
182 rpcrespond(c, "done");
184 rpcrespond(c, "error %s", c->err);
187 nbsendp(c->rpcwait, 0);
194 rpcrespond(c, "error conversation still active");
196 rpcrespond(c, "error conversation not successful");
198 /* make up an auth info using the attr */
199 p = convAI2M((uchar*)c->reply+3, sizeof c->reply-3,
200 strfindattr(c->attr, "cuid"),
201 strfindattr(c->attr, "suid"),
202 strfindattr(c->attr, "cap"),
203 strfindattr(c->attr, "secret"));
205 rpcrespond(c, "error %r");
207 rpcrespondn(c, "ok", c->reply+3, p-(uchar*)(c->reply+3));
211 rpcrespond(c, "ok %A", c->attr);
216 threadcreate(convthread, c, STACK);
222 rpcrespond(Conv *c, char *fmt, ...)
233 c->nreply = vsnprint(c->reply, sizeof c->reply, fmt, arg);
236 c->rpc.op = RpcUnknown;
240 rpcrespondn(Conv *c, char *verb, void *data, int count)
248 need = strlen(verb)+1+count;
250 if(c->rpc.hex && strcmp(verb, "ok") == 0){
254 if(need > sizeof c->reply){
255 print("RPC response too large; caller %#lux", getcallerpc(&c));
259 strcpy(c->reply, verb);
260 p = c->reply + strlen(c->reply);
263 enc16(p, 2*count+1, data, count);
266 memmove(p, data, count);
269 c->nreply = p - c->reply;
271 c->rpc.op = RpcUnknown;
276 pstring(uchar *p, uchar *e, char *s)
295 pcarray(uchar *p, uchar *e, uchar *s, uint n)
314 convAI2M(uchar *p, int n, char *cuid, char *suid, char *cap, char *hex)
328 nsecret = strlen(hex)/2;
329 secret = emalloc(nsecret);
330 if(hexparse(hex, secret, nsecret) < 0){
331 werrstr("hexparse %s failed", hex); /* can't happen */
335 p = pstring(p, e, cuid);
336 p = pstring(p, e, suid);
337 p = pstring(p, e, cap);
338 p = pcarray(p, e, secret, nsecret);
341 werrstr("authinfo too big");