rpc.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. /*
  10. * Factotum RPC
  11. *
  12. * Must be paired write/read cycles on /mnt/factotum/rpc.
  13. * The format of a request is verb, single space, data.
  14. * Data format is verb-dependent; in particular, it can be binary.
  15. * The format of a response is the same. The write only sets up
  16. * the RPC. The read tries to execute it. If the /mnt/factotum/key
  17. * file is open, we ask for new keys using that instead of returning
  18. * an error in the RPC. This means the read blocks.
  19. * Textual arguments are parsed with tokenize, so rc-style quoting
  20. * rules apply.
  21. *
  22. * Only authentication protocol messages go here. Configuration
  23. * is still via ctl (below).
  24. *
  25. * Return values are:
  26. * error message - an error happened.
  27. * ok [data] - success, possible data is request dependent.
  28. * needkey proto domain user - request aborted, get me this key and try again
  29. * badkey proto domain user - request aborted, this key might be bad
  30. * done [haveai] - authentication is done [haveai: you can get an ai with authinfo]
  31. * Request RPCs are:
  32. * start attrs - initializes protocol for authentication, can fail.
  33. * returns "ok read" or "ok write" on success.
  34. * read - execute protocol read
  35. * write - execute protocol write
  36. * authinfo - if the protocol is finished, return the AI if any
  37. * attr - return protocol information
  38. */
  39. #include "dat.h"
  40. Req *rpcwait;
  41. typedef struct Verb Verb;
  42. struct Verb {
  43. char *verb;
  44. int iverb;
  45. };
  46. enum {
  47. Vunknown = -1,
  48. Vauthinfo = 0,
  49. Vread,
  50. Vstart,
  51. Vwrite,
  52. Vattr,
  53. };
  54. Verb rpctab[] = {
  55. "authinfo", Vauthinfo,
  56. "read", Vread,
  57. "start", Vstart,
  58. "write", Vwrite,
  59. "attr", Vattr,
  60. };
  61. static int
  62. classify(char *s, Verb *verbtab, int nverbtab)
  63. {
  64. int i;
  65. for(i=0; i<nverbtab; i++)
  66. if(strcmp(s, verbtab[i].verb) == 0)
  67. return verbtab[i].iverb;
  68. return Vunknown;
  69. }
  70. void
  71. rpcwrite(Req *r)
  72. {
  73. Fsstate *fss;
  74. if(r->ifcall.count >= Maxrpc){
  75. respond(r, Etoolarge);
  76. return;
  77. }
  78. fss = r->fid->aux;
  79. if(fss->pending){
  80. respond(r, "rpc already pending; read to clear");
  81. return;
  82. }
  83. memmove(fss->rpc.buf, r->ifcall.data, r->ifcall.count);
  84. fss->rpc.buf[r->ifcall.count] = '\0';
  85. fss->rpc.verb = fss->rpc.buf;
  86. if(fss->rpc.arg = strchr(fss->rpc.buf, ' ')){
  87. *fss->rpc.arg++ = '\0';
  88. fss->rpc.narg = r->ifcall.count - (fss->rpc.arg - fss->rpc.buf);
  89. }else{
  90. fss->rpc.arg = "";
  91. fss->rpc.narg = 0;
  92. }
  93. fss->rpc.iverb = classify(fss->rpc.verb, rpctab, nelem(rpctab));
  94. r->ofcall.count = r->ifcall.count;
  95. fss->pending = 1;
  96. respond(r, nil);
  97. }
  98. static void
  99. retstring(Req *r, Fsstate *fss, char *s)
  100. {
  101. int n;
  102. n = strlen(s);
  103. if(n > r->ifcall.count)
  104. n = r->ifcall.count;
  105. memmove(r->ofcall.data, s, n);
  106. r->ofcall.count = n;
  107. fss->pending = 0;
  108. respond(r, nil);
  109. return;
  110. }
  111. static void
  112. retrpc(Req *r, int ret, Fsstate *fss)
  113. {
  114. switch(ret){
  115. default:
  116. snprint(fss->rpc.buf, Maxrpc, "internal error %d", ret);
  117. retstring(r, fss, fss->rpc.buf);
  118. return;
  119. case RpcErrstr:
  120. snprint(fss->rpc.buf, Maxrpc, "error %r");
  121. retstring(r, fss, fss->rpc.buf);
  122. return;
  123. case RpcFailure:
  124. snprint(fss->rpc.buf, Maxrpc, "error %s", fss->err);
  125. retstring(r, fss, fss->rpc.buf);
  126. return;
  127. case RpcNeedkey:
  128. if(needkeyqueue(r, fss) < 0){
  129. snprint(fss->rpc.buf, Maxrpc, "needkey %s", fss->keyinfo);
  130. retstring(r, fss, fss->rpc.buf);
  131. }
  132. return;
  133. case RpcOk:
  134. retstring(r, fss, "ok");
  135. return;
  136. case RpcToosmall:
  137. snprint(fss->rpc.buf, Maxrpc, "toosmall %d", fss->rpc.nwant);
  138. retstring(r, fss, fss->rpc.buf);
  139. return;
  140. case RpcPhase:
  141. snprint(fss->rpc.buf, Maxrpc, "phase %r");
  142. retstring(r, fss, fss->rpc.buf);
  143. return;
  144. case RpcConfirm:
  145. confirmqueue(r, fss);
  146. return;
  147. }
  148. }
  149. int
  150. rdwrcheck(Req *r, Fsstate *fss)
  151. {
  152. if(fss->ps == nil){
  153. retstring(r, fss, "error no current protocol");
  154. return -1;
  155. }
  156. if(fss->phase == Notstarted){
  157. retstring(r, fss, "protocol not started");
  158. return -1;
  159. }
  160. if(fss->phase == Broken){
  161. snprint(fss->rpc.buf, Maxrpc, "error %s", fss->err);
  162. retstring(r, fss, fss->rpc.buf);
  163. return -1;
  164. }
  165. if(fss->phase == Established){
  166. if(fss->haveai)
  167. retstring(r, fss, "done haveai");
  168. else
  169. retstring(r, fss, "done");
  170. return -1;
  171. }
  172. return 0;
  173. }
  174. static void
  175. logret(char *pre, Fsstate *fss, int ret)
  176. {
  177. switch(ret){
  178. default:
  179. flog("%s: code %d", pre, ret);
  180. break;
  181. case RpcErrstr:
  182. flog("%s: error %r", pre);
  183. break;
  184. case RpcFailure:
  185. flog("%s: failure %s", pre, fss->err);
  186. break;
  187. case RpcNeedkey:
  188. flog("%s: needkey %s", pre, fss->keyinfo);
  189. break;
  190. case RpcOk:
  191. flog("%s: ok", pre);
  192. break;
  193. case RpcToosmall:
  194. flog("%s: toosmall %d", pre, fss->rpc.nwant);
  195. break;
  196. case RpcPhase:
  197. flog("%s: phase: %r", pre);
  198. break;
  199. case RpcConfirm:
  200. flog("%s: waiting for confirm", pre);
  201. break;
  202. }
  203. }
  204. void
  205. rpcrdwrlog(Fsstate *fss, char *rdwr, uint n, int ophase, int ret)
  206. {
  207. char buf0[40], buf1[40], pre[300];
  208. if(!debug)
  209. return;
  210. snprint(pre, sizeof pre, "%d: %s %ud in phase %s yields phase %s",
  211. fss->seqnum, rdwr, n, phasename(fss, ophase, buf0), phasename(fss, fss->phase, buf1));
  212. logret(pre, fss, ret);
  213. }
  214. void
  215. rpcstartlog(Attr *attr, Fsstate *fss, int ret)
  216. {
  217. char pre[300], tmp[40];
  218. if(!debug)
  219. return;
  220. snprint(pre, sizeof pre, "%d: start %A yields phase %s", fss->seqnum,
  221. attr, phasename(fss, fss->phase, tmp));
  222. logret(pre, fss, ret);
  223. }
  224. int seqnum;
  225. void
  226. rpcread(Req *r)
  227. {
  228. Attr *attr;
  229. char *p;
  230. int ophase, ret;
  231. uint8_t *e;
  232. uint count;
  233. Fsstate *fss;
  234. Proto *proto;
  235. if(r->ifcall.count < 64){
  236. respond(r, "rpc read too small");
  237. return;
  238. }
  239. fss = r->fid->aux;
  240. if(!fss->pending){
  241. respond(r, "no rpc pending");
  242. return;
  243. }
  244. switch(fss->rpc.iverb){
  245. default:
  246. case Vunknown:
  247. retstring(r, fss, "error unknown verb");
  248. break;
  249. case Vstart:
  250. if(fss->phase != Notstarted){
  251. flog("%d: implicit close due to second start; old attr '%A'", fss->seqnum, fss->attr);
  252. if(fss->proto && fss->ps)
  253. (*fss->proto->close)(fss);
  254. fss->ps = nil;
  255. fss->proto = nil;
  256. _freeattr(fss->attr);
  257. fss->attr = nil;
  258. fss->phase = Notstarted;
  259. }
  260. attr = _parseattr(fss->rpc.arg);
  261. if((p = _strfindattr(attr, "proto")) == nil){
  262. retstring(r, fss, "error did not specify proto");
  263. _freeattr(attr);
  264. break;
  265. }
  266. if((proto = findproto(p)) == nil){
  267. snprint(fss->rpc.buf, Maxrpc, "error unknown protocol %q", p);
  268. retstring(r, fss, fss->rpc.buf);
  269. _freeattr(attr);
  270. break;
  271. }
  272. fss->attr = attr;
  273. fss->proto = proto;
  274. fss->seqnum = ++seqnum;
  275. ret = (*proto->init)(proto, fss);
  276. rpcstartlog(attr, fss, ret);
  277. if(ret != RpcOk){
  278. _freeattr(fss->attr);
  279. fss->attr = nil;
  280. fss->phase = Notstarted;
  281. }
  282. retrpc(r, ret, fss);
  283. break;
  284. case Vread:
  285. if(fss->rpc.arg && fss->rpc.arg[0]){
  286. retstring(r, fss, "error read needs no parameters");
  287. break;
  288. }
  289. if(rdwrcheck(r, fss) < 0)
  290. break;
  291. count = r->ifcall.count - 3;
  292. ophase = fss->phase;
  293. ret = fss->proto->read(fss, (uint8_t*)r->ofcall.data+3,
  294. &count);
  295. rpcrdwrlog(fss, "read", count, ophase, ret);
  296. if(ret == RpcOk){
  297. memmove(r->ofcall.data, "ok ", 3);
  298. if(count == 0)
  299. r->ofcall.count = 2;
  300. else
  301. r->ofcall.count = 3+count;
  302. fss->pending = 0;
  303. respond(r, nil);
  304. }else
  305. retrpc(r, ret, fss);
  306. break;
  307. case Vwrite:
  308. if(rdwrcheck(r, fss) < 0)
  309. break;
  310. ophase = fss->phase;
  311. ret = fss->proto->write(fss, fss->rpc.arg, fss->rpc.narg);
  312. rpcrdwrlog(fss, "write", fss->rpc.narg, ophase, ret);
  313. retrpc(r, ret, fss);
  314. break;
  315. case Vauthinfo:
  316. if(fss->phase != Established){
  317. retstring(r, fss, "error authentication unfinished");
  318. break;
  319. }
  320. if(!fss->haveai){
  321. retstring(r, fss, "error no authinfo available");
  322. break;
  323. }
  324. memmove(r->ofcall.data, "ok ", 3);
  325. fss->ai.cap = mkcap(r->fid->uid, fss->ai.suid);
  326. e = convAI2M(&fss->ai, (uint8_t*)r->ofcall.data+3,
  327. r->ifcall.count-3);
  328. free(fss->ai.cap);
  329. fss->ai.cap = nil;
  330. if(e == nil){
  331. retstring(r, fss, "error read too small");
  332. break;
  333. }
  334. r->ofcall.count = e - (uint8_t*)r->ofcall.data;
  335. fss->pending = 0;
  336. respond(r, nil);
  337. break;
  338. case Vattr:
  339. snprint(fss->rpc.buf, Maxrpc, "ok %A", fss->attr);
  340. retstring(r, fss, fss->rpc.buf);
  341. break;
  342. }
  343. }
  344. enum {
  345. Vdelkey,
  346. Vaddkey,
  347. Vdebug,
  348. };
  349. Verb ctltab[] = {
  350. "delkey", Vdelkey,
  351. "key", Vaddkey,
  352. "debug", Vdebug,
  353. };
  354. /*
  355. * key attr=val... - add a key
  356. * the attr=val pairs are protocol-specific.
  357. * for example, both of these are valid:
  358. * key p9sk1 gre cs.bell-labs.com mysecret
  359. * key p9sk1 gre cs.bell-labs.com 11223344556677 fmt=des7hex
  360. * delkey ... - delete a key
  361. * if given, the attr=val pairs are used to narrow the search
  362. * [maybe should require a password?]
  363. */
  364. int
  365. ctlwrite(char *a, int atzero)
  366. {
  367. char *p;
  368. int i, nmatch, ret;
  369. Attr *attr, **l, **lpriv, **lprotos, *pa, *priv, *protos;
  370. Key *k;
  371. Proto *proto;
  372. if(a[0] == '#' || a[0] == '\0')
  373. return 0;
  374. /*
  375. * it would be nice to emit a warning of some sort here.
  376. * we ignore all but the first line of the write. this helps
  377. * both with things like "echo delkey >/mnt/factotum/ctl"
  378. * and writes that (incorrectly) contain multiple key lines.
  379. */
  380. if(p = strchr(a, '\n')){
  381. if(p[1] != '\0'){
  382. werrstr("multiline write not allowed");
  383. return -1;
  384. }
  385. *p = '\0';
  386. }
  387. if((p = strchr(a, ' ')) == nil)
  388. p = "";
  389. else
  390. *p++ = '\0';
  391. switch(classify(a, ctltab, nelem(ctltab))){
  392. default:
  393. case Vunknown:
  394. werrstr("unknown verb");
  395. return -1;
  396. case Vdebug:
  397. debug ^= 1;
  398. return 0;
  399. case Vdelkey:
  400. nmatch = 0;
  401. attr = _parseattr(p);
  402. for(pa=attr; pa; pa=pa->next){
  403. if(pa->type != AttrQuery && pa->name[0]=='!'){
  404. werrstr("only !private? patterns are allowed for private fields");
  405. _freeattr(attr);
  406. return -1;
  407. }
  408. }
  409. for(i=0; i<ring->nkey; ){
  410. if(matchattr(attr, ring->key[i]->attr, ring->key[i]->privattr)){
  411. nmatch++;
  412. closekey(ring->key[i]);
  413. ring->nkey--;
  414. memmove(&ring->key[i], &ring->key[i+1], (ring->nkey-i)*sizeof(ring->key[0]));
  415. }else
  416. i++;
  417. }
  418. _freeattr(attr);
  419. if(nmatch == 0){
  420. werrstr("found no keys to delete");
  421. return -1;
  422. }
  423. return 0;
  424. case Vaddkey:
  425. attr = _parseattr(p);
  426. /* separate out proto= attributes */
  427. lprotos = &protos;
  428. for(l=&attr; (*l); ){
  429. if(strcmp((*l)->name, "proto") == 0){
  430. *lprotos = *l;
  431. lprotos = &(*l)->next;
  432. *l = (*l)->next;
  433. }else
  434. l = &(*l)->next;
  435. }
  436. *lprotos = nil;
  437. if(protos == nil){
  438. werrstr("key without protos");
  439. _freeattr(attr);
  440. return -1;
  441. }
  442. /* separate out private attributes */
  443. lpriv = &priv;
  444. for(l=&attr; (*l); ){
  445. if((*l)->name[0] == '!'){
  446. *lpriv = *l;
  447. lpriv = &(*l)->next;
  448. *l = (*l)->next;
  449. }else
  450. l = &(*l)->next;
  451. }
  452. *lpriv = nil;
  453. /* add keys */
  454. ret = 0;
  455. for(pa=protos; pa; pa=pa->next){
  456. if((proto = findproto(pa->val)) == nil){
  457. werrstr("unknown proto %s", pa->val);
  458. ret = -1;
  459. continue;
  460. }
  461. if(proto->addkey == nil){
  462. werrstr("proto %s doesn't take keys", proto->name);
  463. ret = -1;
  464. continue;
  465. }
  466. k = emalloc(sizeof(Key));
  467. k->attr = _mkattr(AttrNameval, "proto", proto->name, _copyattr(attr));
  468. k->privattr = _copyattr(priv);
  469. k->ref = 1;
  470. k->proto = proto;
  471. if(proto->addkey(k, atzero) < 0){
  472. ret = -1;
  473. closekey(k);
  474. continue;
  475. }
  476. closekey(k);
  477. }
  478. _freeattr(attr);
  479. _freeattr(priv);
  480. _freeattr(protos);
  481. return ret;
  482. }
  483. }