rpc.c 11 KB

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