PageRenderTime 54ms CodeModel.GetById 7ms RepoModel.GetById 1ms app.codeStats 0ms

/appl/cmd/auth/factotum/factotum.b

https://bitbucket.org/floren/inferno/
Brainfuck | 1066 lines | 979 code | 87 blank | 0 comment | 121 complexity | b13e49e91157e7c3b436551596478125 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, MPL-2.0-no-copyleft-exception
  1. implement Factotum, Authio;
  2. #
  3. # Copyright Š 2003-2004 Vita Nuova Holdings Limited
  4. #
  5. include "sys.m";
  6. sys: Sys;
  7. Rread, Rwrite: import Sys;
  8. include "draw.m";
  9. include "string.m";
  10. str: String;
  11. include "keyring.m";
  12. include "authio.m";
  13. include "arg.m";
  14. include "readdir.m";
  15. Factotum: module
  16. {
  17. init: fn(nil: ref Draw->Context, nil: list of string);
  18. };
  19. #confirm, log
  20. Files: adt {
  21. ctl: ref Sys->FileIO;
  22. rpc: ref Sys->FileIO;
  23. proto: ref Sys->FileIO;
  24. needkey: ref Sys->FileIO;
  25. };
  26. Debug: con 0;
  27. debug := Debug;
  28. files: Files;
  29. authio: Authio;
  30. keymanc: chan of (list of ref Attr, int, chan of (list of ref Key, string));
  31. init(nil: ref Draw->Context, args: list of string)
  32. {
  33. sys = load Sys Sys->PATH;
  34. str = load String String->PATH;
  35. authio = load Authio "$self";
  36. svcname := "#sfactotum";
  37. mntpt := "/mnt/factotum";
  38. arg := load Arg Arg->PATH;
  39. if(arg != nil){
  40. arg->init(args);
  41. arg->setusage("auth/factotum [-d] [-m /mnt/factotum] [-s factotum]");
  42. while((o := arg->opt()) != 0)
  43. case o {
  44. 'd' => debug++;
  45. 'm' => mntpt = arg->earg();
  46. 's' => svcname = "#s"+arg->earg();
  47. * => arg->usage();
  48. }
  49. args = arg->argv();
  50. if(args != nil)
  51. arg->usage();
  52. arg = nil;
  53. }
  54. sys->unmount(nil, mntpt);
  55. if(sys->bind(svcname, mntpt, Sys->MREPL) < 0)
  56. err(sys->sprint("can't bind %s on %s: %r", svcname, mntpt));
  57. files.ctl = sys->file2chan(mntpt, "ctl");
  58. files.rpc = sys->file2chan(mntpt, "rpc");
  59. files.proto = sys->file2chan(mntpt, "proto");
  60. files.needkey = sys->file2chan(mntpt, "needkey");
  61. if(files.ctl == nil || files.rpc == nil || files.proto == nil || files.needkey == nil)
  62. err(sys->sprint("can't create %s/*: %r", mntpt));
  63. keymanc = chan of (list of ref Attr, int, chan of (list of ref Key, string));
  64. spawn factotumsrv();
  65. }
  66. user(): string
  67. {
  68. fd := sys->open("/dev/user", Sys->OREAD);
  69. if(fd == nil)
  70. return nil;
  71. b := array[Sys->NAMEMAX] of byte;
  72. n := sys->read(fd, b, len b);
  73. if(n <= 0)
  74. return nil;
  75. return string b[0:n];
  76. }
  77. err(s: string)
  78. {
  79. sys->fprint(sys->fildes(2), "factotum: %s\n", s);
  80. raise "fail:error";
  81. }
  82. rlist: list of ref Fid;
  83. factotumsrv()
  84. {
  85. sys->pctl(Sys->NEWPGRP|Sys->FORKFD|Sys->FORKENV, nil);
  86. if(debug == 0)
  87. privacy();
  88. allkeys := array[0] of ref Key;
  89. pidc := chan of int;
  90. donec := chan of ref Fid;
  91. # keyc := chan of (list of ref Attr, chan of (ref Key, string));
  92. needfid := -1;
  93. needed, needy: list of (int, list of ref Attr, chan of (list of ref Key, string));
  94. needread: Sys->Rread;
  95. needtag := 0;
  96. for(;;) X: alt{
  97. r := <-donec =>
  98. r.pid = 0;
  99. cleanfid(r.fid);
  100. (off, nbytes, nil, rc) := <-files.ctl.read =>
  101. if(rc == nil)
  102. break;
  103. s := "";
  104. for(i := 0; i < len allkeys; i++)
  105. if((k := allkeys[i]) != nil)
  106. s += k.safetext()+"\n";
  107. rc <-= reads(s, off, nbytes);
  108. (nil, data, nil, wc) := <-files.ctl.write =>
  109. if(wc == nil)
  110. break;
  111. (nf, flds) := sys->tokenize(string data, "\n\r");
  112. if(nf > 1){
  113. # compatibility with plan 9; has the advantage you can tell which key is wrong
  114. wc <-= (0, "multiline write not allowed");
  115. break;
  116. }
  117. if(flds == nil || (hd flds)[0] == '#'){
  118. wc <-= (len data, nil);
  119. break;
  120. }
  121. s := hd flds;
  122. for(i := 0; i < len s && s[i] != ' '; i++){
  123. # skip
  124. }
  125. verb := s[0:i];
  126. if(i < len s)
  127. i++;
  128. s = s[i:];
  129. case verb {
  130. "key" =>
  131. k := Key.mk(parseline(s));
  132. if(k == nil){
  133. wc <-= (len data, nil); # ignore it
  134. break;
  135. }
  136. if(lookattrval(k.attrs, "proto") == nil){
  137. wc <-= (0, "key without proto");
  138. break;
  139. }
  140. allkeys = addkey(allkeys, k);
  141. wc <-= (len data, nil);
  142. "delkey" =>
  143. attrs := parseline(s);
  144. for(al := attrs; al != nil; al = tl al){
  145. a := hd al;
  146. if(a.name[0] == '!' && (a.val != nil || a.tag != Aquery)){
  147. wc <-= (0, "cannot specify values for private fields");
  148. break X;
  149. }
  150. }
  151. if(delkey(allkeys, attrs) == 0)
  152. wc <-= (0, "no matching keys");
  153. else
  154. wc <-= (len data, nil);
  155. "debug" =>
  156. wc <-= (len data, nil);
  157. * =>
  158. wc <-= (0, "unknown verb");
  159. }
  160. (nil, nbytes, fid, rc) := <-files.rpc.read =>
  161. if(rc == nil)
  162. break;
  163. r := findfid(fid);
  164. if(r == nil){
  165. rc <-= (nil, "no rpc pending");
  166. break;
  167. }
  168. alt{
  169. r.read <-= (nbytes, rc) =>
  170. ;
  171. * =>
  172. rc <-= (nil, "concurrent rpc read not allowed");
  173. }
  174. (nil, data, fid, wc) := <-files.rpc.write =>
  175. if(wc == nil){
  176. cleanfid(fid);
  177. break;
  178. }
  179. r := findfid(fid);
  180. if(r == nil){
  181. r = ref Fid(fid, 0, nil, nil, chan[1] of (array of byte, Rwrite), chan[1] of (int, Rread), 0, nil);
  182. spawn request(r, pidc, donec);
  183. r.pid = <-pidc;
  184. rlist = r :: rlist;
  185. }
  186. # this non-blocking write avoids a potential deadlock situation that
  187. # can happen when a proto module calls findkey at the same time
  188. # a client tries to write to the rpc file. this might not be the correct fix!
  189. alt{
  190. r.write <-= (data, wc) =>
  191. ;
  192. * =>
  193. wc <-= (-1, "concurrent rpc write not allowed");
  194. }
  195. (off, nbytes, nil, rc) := <-files.proto.read =>
  196. if(rc == nil)
  197. break;
  198. rc <-= reads(readprotos(), off, nbytes);
  199. (nil, nil, nil, wc) := <-files.proto.write =>
  200. if(wc != nil)
  201. wc <-= (0, "illegal operation");
  202. (nil, nil, fid, rc) := <-files.needkey.read =>
  203. if(rc == nil)
  204. break;
  205. if(needfid >= 0 && fid != needfid){
  206. rc <-= (nil, "file in use");
  207. break;
  208. }
  209. needfid = fid;
  210. if(needy != nil){
  211. (tag, attr, kc) := hd needy;
  212. needy = tl needy;
  213. needed = (tag, attr, kc) :: needed;
  214. rc <-= (sys->aprint("needkey tag=%ud %s", tag, attrtext(attr)), nil);
  215. break;
  216. }
  217. if(needread != nil){
  218. rc <-= (nil, "already reading");
  219. break;
  220. }
  221. needread = rc;
  222. (nil, data, fid, wc) := <-files.needkey.write =>
  223. if(wc == nil){
  224. if(needfid == fid){
  225. needfid = -1; # TO DO? give needkey errors back to request
  226. needread = nil;
  227. }
  228. break;
  229. }
  230. if(needfid >= 0 && fid != needfid){
  231. wc <-= (0, "file in use");
  232. break;
  233. }
  234. needfid = fid;
  235. tagline := parseline(string data);
  236. if(len tagline != 1 || (t := lookattrval(tagline, "tag")) == nil){
  237. wc <-= (0, "no tag");
  238. break;
  239. }
  240. tag := int t;
  241. nl: list of (int, list of ref Attr, chan of (list of ref Key, string));
  242. found := 0;
  243. for(l := needed; l != nil; l = tl l){
  244. (ntag, attrs, kc) := hd l;
  245. if(tag == ntag){
  246. found = 1;
  247. k := findkey(allkeys, attrs);
  248. if(k != nil)
  249. kc <-= (k :: nil, nil);
  250. else
  251. kc <-= (nil, "needkey "+attrtext(attrs));
  252. while((l = tl l) != nil)
  253. nl = hd l :: nl;
  254. break;
  255. }
  256. nl = hd l :: nl;
  257. }
  258. if(found)
  259. wc <-= (len data, nil);
  260. else
  261. wc <-= (0, "tag not found");
  262. (attrs, required, kc) := <-keymanc =>
  263. # look for key and reply
  264. kl := findkeys(allkeys, attrs);
  265. if(kl != nil){
  266. kc <-= (kl, nil);
  267. break;
  268. }else if(!required || needfid == -1){
  269. kc <-= (nil, "needkey "+attrtext(attrs));
  270. break;
  271. }
  272. # query surrounding environment using needkey
  273. if(needread != nil){
  274. needed = (needtag, attrs, kc) :: needed;
  275. needread <-= (sys->aprint("needkey tag=%ud %s", needtag, attrtext(attrs)), nil);
  276. needread = nil;
  277. needtag++;
  278. }else
  279. needy = (needtag++, attrs, kc) :: needy;
  280. }
  281. }
  282. findfid(fid: int): ref Fid
  283. {
  284. for(rl := rlist; rl != nil; rl = tl rl){
  285. r := hd rl;
  286. if(r.fid == fid)
  287. return r;
  288. }
  289. return nil;
  290. }
  291. cleanfid(fid: int)
  292. {
  293. rl := rlist;
  294. rlist = nil;
  295. for(; rl != nil; rl = tl rl){
  296. r := hd rl;
  297. if(r.fid != fid)
  298. rlist = r :: rlist;
  299. else if(r.pid)
  300. kill(r.pid);
  301. }
  302. }
  303. kill(pid: int)
  304. {
  305. fd := sys->open("/prog/"+string pid+"/ctl", Sys->OWRITE);
  306. if(fd != nil)
  307. sys->fprint(fd, "kill");
  308. }
  309. privacy()
  310. {
  311. fd := sys->open("#p/"+string sys->pctl(0, nil)+"/ctl", Sys->OWRITE);
  312. if(fd == nil || sys->fprint(fd, "private") < 0)
  313. sys->fprint(sys->fildes(2), "factotum: warning: unable to make memory private: %r\n");
  314. }
  315. reads(str: string, off, nbytes: int): (array of byte, string)
  316. {
  317. bstr := array of byte str;
  318. slen := len bstr;
  319. if(off < 0 || off >= slen)
  320. return (nil, nil);
  321. if(off + nbytes > slen)
  322. nbytes = slen - off;
  323. if(nbytes <= 0)
  324. return (nil, nil);
  325. return (bstr[off:off+nbytes], nil);
  326. }
  327. readprotos(): string
  328. {
  329. readdir := load Readdir Readdir->PATH;
  330. if(readdir == nil)
  331. return "unknown\n";
  332. (dirs, nil) := readdir->init("/dis/auth/proto", Readdir->NAME|Readdir->COMPACT);
  333. s := "";
  334. for(i := 0; i < len dirs; i++){
  335. n := dirs[i].name;
  336. if(len n > 4 && n[len n-4:] == ".dis")
  337. s += n[0: len n-4]+"\n";
  338. }
  339. return s;
  340. }
  341. Ogok, Ostart, Oread, Owrite, Oauthinfo, Oattr: con iota;
  342. ops := array[] of {
  343. (Ostart, "start"),
  344. (Oread, "read"),
  345. (Owrite, "write"),
  346. (Oauthinfo, "authinfo"),
  347. (Oattr, "attr"),
  348. };
  349. request(r: ref Fid, pidc: chan of int, donec: chan of ref Fid)
  350. {
  351. pidc <-= sys->pctl(0, nil);
  352. rpc := rio(r);
  353. while(rpc != nil){
  354. if(rpc.cmd == Ostart){
  355. (proto, attrs, e) := startproto(string rpc.arg);
  356. if(e != nil){
  357. reply(rpc, "error "+e);
  358. rpc = rio(r);
  359. continue;
  360. }
  361. r.attrs = attrs; # saved for attr request
  362. ok(rpc);
  363. io := ref IO(r, nil);
  364. {
  365. err := proto->interaction(attrs, io);
  366. if(debug && err != nil)
  367. sys->fprint(sys->fildes(2), "factotum: failure: %s\n", err);
  368. if(r.err == nil)
  369. r.err = err;
  370. r.done = 1;
  371. }exception ex{
  372. "*" =>
  373. r.done = 0;
  374. r.err = "exception "+ex;
  375. }
  376. if(r.err != nil)
  377. io.error(r.err);
  378. rpc = finish(r);
  379. r.attrs = nil;
  380. r.err = nil;
  381. r.done = 0;
  382. r.ai = nil;
  383. }else
  384. reply(rpc, "no current protocol");
  385. }
  386. flushreq(r, donec);
  387. }
  388. startproto(request: string): (Authproto, list of ref Attr, string)
  389. {
  390. attrs := parseline(request);
  391. if(debug > 1)
  392. sys->print("-> %s <-\n", attrtext(attrs));
  393. p := lookattrval(attrs, "proto");
  394. if(p == nil)
  395. return (nil, nil, "did not specify protocol");
  396. if(debug > 1)
  397. sys->print("proto=%s\n", p);
  398. if(any(p, "./")) # avoid unpleasantness
  399. return (nil, nil, "illegal protocol: "+p);
  400. proto := load Authproto "/dis/auth/proto/"+p+".dis";
  401. if(proto == nil)
  402. return (nil, nil, sys->sprint("protocol %s: %r", p));
  403. if(debug)
  404. sys->print("start %s\n", p);
  405. e: string;
  406. {
  407. e = proto->init(authio);
  408. }exception ex{
  409. "*" =>
  410. e = "exception "+ex;
  411. }
  412. if(e != nil)
  413. return (nil, nil, e);
  414. return (proto, attrs, nil);
  415. }
  416. finish(r: ref Fid): ref Rpc
  417. {
  418. while((rpc := rio(r)) != nil)
  419. case rpc.cmd {
  420. Owrite =>
  421. phase(rpc, "protocol phase error");
  422. Oread =>
  423. if(r.err != nil)
  424. reply(rpc, "error "+r.err);
  425. else
  426. done(rpc, r.ai);
  427. Oauthinfo =>
  428. if(r.done){
  429. if(r.ai == nil)
  430. reply(rpc, "error no authinfo available");
  431. else{
  432. a := packai(r.ai);
  433. if(rpc.nbytes-3 < len a)
  434. reply(rpc, sys->sprint("toosmall %d", len a + 3));
  435. else
  436. okdata(rpc, a);
  437. }
  438. }else
  439. reply(rpc, "error authentication unfinished");
  440. Ostart =>
  441. return rpc;
  442. * =>
  443. reply(rpc, "error unexpected request");
  444. }
  445. return nil;
  446. }
  447. flushreq(r: ref Fid, donec: chan of ref Fid)
  448. {
  449. for(;;) alt{
  450. donec <-= r =>
  451. exit;
  452. (nil, wc) := <-r.write =>
  453. wc <-= (0, "write rpc protocol error");
  454. (nil, rc) := <-r.read =>
  455. rc <-= (nil, "read rpc protocol error");
  456. }
  457. }
  458. rio(r: ref Fid): ref Rpc
  459. {
  460. req: array of byte;
  461. for(;;) alt{
  462. (data, wc) := <-r.write =>
  463. if(req != nil){
  464. wc <-= (0, "rpc pending; read to clear");
  465. break;
  466. }
  467. req = data;
  468. wc <-= (len data, nil);
  469. (nbytes, rc) := <-r.read =>
  470. if(req == nil){
  471. rc <-= (nil, "no rpc pending");
  472. break;
  473. }
  474. (cmd, arg) := op(req, ops);
  475. req = nil;
  476. rpc := ref Rpc(r, cmd, arg, nbytes, rc);
  477. case cmd {
  478. Ogok =>
  479. reply(rpc, "error unknown rpc");
  480. break;
  481. Oattr =>
  482. if(r.attrs == nil)
  483. reply(rpc, "error no attributes");
  484. else
  485. reply(rpc, "ok "+attrtext(r.attrs));
  486. break;
  487. * =>
  488. return rpc;
  489. }
  490. }
  491. }
  492. ok(rpc: ref Rpc)
  493. {
  494. reply(rpc, "ok");
  495. }
  496. okdata(rpc: ref Rpc, a: array of byte)
  497. {
  498. b := array[len a + 3] of byte;
  499. b[0] = byte 'o';
  500. b[1] = byte 'k';
  501. b[2] = byte ' ';
  502. b[3:] = a;
  503. rpc.rc <-= (b, nil);
  504. }
  505. done(rpc: ref Rpc, ai: ref Authinfo)
  506. {
  507. rpc.r.ai = ai;
  508. rpc.r.done = 1;
  509. if(ai != nil)
  510. reply(rpc, "done haveai");
  511. else
  512. reply(rpc, "done");
  513. }
  514. phase(rpc: ref Rpc, s: string)
  515. {
  516. reply(rpc, "phase "+s);
  517. }
  518. needkey(rpc: ref Rpc, attrs: list of ref Attr)
  519. {
  520. reply(rpc, "needkey "+attrtext(attrs));
  521. }
  522. reply(rpc: ref Rpc, s: string)
  523. {
  524. rpc.rc <-= reads(s, 0, rpc.nbytes);
  525. }
  526. puta(a: array of byte, n: int, v: array of byte): int
  527. {
  528. if(n < 0)
  529. return -1;
  530. c := len v;
  531. if(n+2+c > len a)
  532. return -1;
  533. a[n++] = byte c;
  534. a[n++] = byte (c>>8);
  535. a[n:] = v;
  536. return n + len v;
  537. }
  538. packai(ai: ref Authinfo): array of byte
  539. {
  540. a := array[1024] of byte;
  541. i := puta(a, 0, array of byte ai.cuid);
  542. i = puta(a, i, array of byte ai.suid);
  543. i = puta(a, i, array of byte ai.cap);
  544. i = puta(a, i, ai.secret);
  545. if(i < 0)
  546. return nil;
  547. return a[0:i];
  548. }
  549. op(a: array of byte, ops: array of (int, string)): (int, array of byte)
  550. {
  551. arg: array of byte;
  552. for(i := 0; i < len a; i++)
  553. if(a[i] == byte ' '){
  554. if(i+1 < len a)
  555. arg = a[i+1:];
  556. break;
  557. }
  558. s := string a[0:i];
  559. for(i = 0; i < len ops; i++){
  560. (cmd, name) := ops[i];
  561. if(s == name)
  562. return (cmd, arg);
  563. }
  564. return (Ogok, arg);
  565. }
  566. parseline(s: string): list of ref Attr
  567. {
  568. fld := str->unquoted(s);
  569. rfld := fld;
  570. for(fld = nil; rfld != nil; rfld = tl rfld)
  571. fld = (hd rfld) :: fld;
  572. attrs: list of ref Attr;
  573. for(; fld != nil; fld = tl fld){
  574. n := hd fld;
  575. a := "";
  576. tag := Aattr;
  577. for(i:=0; i<len n; i++)
  578. if(n[i] == '='){
  579. a = n[i+1:];
  580. n = n[0:i];
  581. tag = Aval;
  582. }
  583. if(len n == 0)
  584. continue;
  585. if(tag == Aattr && len n > 1 && n[len n-1] == '?'){
  586. tag = Aquery;
  587. n = n[0:len n-1];
  588. }
  589. attrs = ref Attr(tag, n, a) :: attrs;
  590. }
  591. return attrs;
  592. }
  593. Attr.text(a: self ref Attr): string
  594. {
  595. case a.tag {
  596. Aattr =>
  597. return a.name;
  598. Aval =>
  599. return a.name+"="+a.val;
  600. Aquery =>
  601. return a.name+"?";
  602. * =>
  603. return "??";
  604. }
  605. }
  606. attrtext(attrs: list of ref Attr): string
  607. {
  608. s := "";
  609. sp := 0;
  610. for(; attrs != nil; attrs = tl attrs){
  611. if(sp)
  612. s[len s] = ' ';
  613. sp = 1;
  614. s += (hd attrs).text();
  615. }
  616. return s;
  617. }
  618. lookattr(attrs: list of ref Attr, n: string): ref Attr
  619. {
  620. for(; attrs != nil; attrs = tl attrs)
  621. if((a := hd attrs).tag != Aquery && a.name == n)
  622. return a;
  623. return nil;
  624. }
  625. lookattrval(attrs: list of ref Attr, n: string): string
  626. {
  627. if((a := lookattr(attrs, n)) != nil)
  628. return a.val;
  629. return nil;
  630. }
  631. anyattr(attrs: list of ref Attr, n: string): ref Attr
  632. {
  633. for(; attrs != nil; attrs = tl attrs)
  634. if((a := hd attrs).name == n)
  635. return a;
  636. return nil;
  637. }
  638. reverse[T](l: list of T): list of T
  639. {
  640. r: list of T;
  641. for(; l != nil; l = tl l)
  642. r = hd l :: r;
  643. return r;
  644. }
  645. setattrs(lv: list of ref Attr, rv: list of ref Attr): list of ref Attr
  646. {
  647. # new attributes
  648. nl: list of ref Attr;
  649. for(rl := rv; rl != nil; rl = tl rl)
  650. if(anyattr(lv, (hd rl).name) == nil)
  651. nl = ref(*hd rl) :: nl;
  652. # new values
  653. for(; lv != nil; lv = tl lv){
  654. a := lookattr(rv, (hd lv).name); # won't take queries
  655. if(a != nil)
  656. nl = ref *a :: nl;
  657. }
  658. return reverse(nl);
  659. }
  660. delattrs(lv: list of ref Attr, rv: list of ref Attr): list of ref Attr
  661. {
  662. nl: list of ref Attr;
  663. for(; lv != nil; lv = tl lv)
  664. if(anyattr(rv, (hd lv).name) == nil)
  665. nl = hd lv :: nl;
  666. return reverse(nl);
  667. }
  668. ignored(s: string): int
  669. {
  670. return s == "role" || s == "disabled";
  671. }
  672. matchattr(attrs: list of ref Attr, pat: ref Attr): int
  673. {
  674. return (b := lookattr(attrs, pat.name)) != nil && (pat.tag == Aquery || b.val == pat.val) ||
  675. ignored(pat.name);
  676. }
  677. matchattrs(pub: list of ref Attr, secret: list of ref Attr, pats: list of ref Attr): int
  678. {
  679. for(pl := pats; pl != nil; pl = tl pl)
  680. if(!matchattr(pub, hd pl) && !matchattr(secret, hd pl))
  681. return 0;
  682. return 1;
  683. }
  684. sortattrs(attrs: list of ref Attr): list of ref Attr
  685. {
  686. a := array[len attrs] of ref Attr;
  687. i := 0;
  688. for(l := attrs; l != nil; l = tl l)
  689. a[i++] = hd l;
  690. shellsort(a);
  691. for(i = 0; i < len a; i++)
  692. l = a[i] :: l;
  693. return l;
  694. }
  695. # sort into decreasing order (we'll reverse the list)
  696. shellsort(a: array of ref Attr)
  697. {
  698. n := len a;
  699. for(gap := n; gap > 0; ) {
  700. gap /= 2;
  701. max := n-gap;
  702. ex: int;
  703. do{
  704. ex = 0;
  705. for(i := 0; i < max; i++) {
  706. j := i+gap;
  707. if(a[i].name > a[j].name || a[i].name == nil) {
  708. t := a[i]; a[i] = a[j]; a[j] = t;
  709. ex = 1;
  710. }
  711. }
  712. }while(ex);
  713. }
  714. }
  715. findkey(keys: array of ref Key, attrs: list of ref Attr): ref Key
  716. {
  717. if(debug)
  718. sys->print("findkey %q\n", attrtext(attrs));
  719. for(i := 0; i < len keys; i++)
  720. if((k := keys[i]) != nil && matchattrs(k.attrs, k.secrets, attrs))
  721. return k;
  722. return nil;
  723. }
  724. findkeys(keys: array of ref Key, attrs: list of ref Attr): list of ref Key
  725. {
  726. if(debug)
  727. sys->print("findkey %q\n", attrtext(attrs));
  728. kl: list of ref Key;
  729. for(i := 0; i < len keys; i++)
  730. if((k := keys[i]) != nil && matchattrs(k.attrs, k.secrets, attrs))
  731. kl = k :: kl;
  732. return reverse(kl);
  733. }
  734. delkey(keys: array of ref Key, attrs: list of ref Attr): int
  735. {
  736. nk := 0;
  737. for(i := 0; i < len keys; i++)
  738. if((k := keys[i]) != nil)
  739. if(matchattrs(k.attrs, k.secrets, attrs)){
  740. nk++;
  741. keys[i] = nil;
  742. }
  743. return nk;
  744. }
  745. Key.mk(attrs: list of ref Attr): ref Key
  746. {
  747. k := ref Key;
  748. for(; attrs != nil; attrs = tl attrs){
  749. a := hd attrs;
  750. if(a.name != nil){
  751. if(a.name[0] == '!')
  752. k.secrets = a :: k.secrets;
  753. else
  754. k.attrs = a :: k.attrs;
  755. }
  756. }
  757. if(k.attrs != nil || k.secrets != nil)
  758. return k;
  759. return nil;
  760. }
  761. addkey(keys: array of ref Key, k: ref Key): array of ref Key
  762. {
  763. for(i := 0; i < len keys; i++)
  764. if(keys[i] == nil){
  765. keys[i] = k;
  766. return keys;
  767. }
  768. n := array[len keys+1] of ref Key;
  769. n[0:] = keys;
  770. n[len keys] = k;
  771. return n;
  772. }
  773. Key.text(k: self ref Key): string
  774. {
  775. s := attrtext(k.attrs);
  776. if(s != nil && k.secrets != nil)
  777. s[len s] = ' ';
  778. return s + attrtext(k.secrets);
  779. }
  780. Key.safetext(k: self ref Key): string
  781. {
  782. s := attrtext(sortattrs(k.attrs));
  783. sp := s != nil;
  784. for(sl := k.secrets; sl != nil; sl = tl sl){
  785. if(sp)
  786. s[len s] = ' ';
  787. s += sys->sprint("%s?", (hd sl).name);
  788. }
  789. return s;
  790. }
  791. any(s: string, t: string): int
  792. {
  793. for(i := 0; i < len s; i++)
  794. for(j := 0; j < len t; j++)
  795. if(s[i] == t[j])
  796. return 1;
  797. return 0;
  798. }
  799. IO.findkey(io: self ref IO, attrs: list of ref Attr, extra: string): (ref Key, string)
  800. {
  801. (kl, err) := io.findkeys(attrs, extra);
  802. if(kl != nil)
  803. return (hd kl, err);
  804. return (nil, err);
  805. }
  806. IO.findkeys(nil: self ref IO, attrs: list of ref Attr, extra: string): (list of ref Key, string)
  807. {
  808. ea := parseline(extra);
  809. for(; ea != nil; ea = tl ea)
  810. attrs = hd ea :: attrs;
  811. kc := chan of (list of ref Key, string);
  812. keymanc <-= (attrs, 1, kc); # TO DO: 1 => 0 for not needed
  813. return <-kc;
  814. }
  815. IO.needkey(nil: self ref IO, attrs: list of ref Attr, extra: string): (ref Key, string)
  816. {
  817. ea := parseline(extra);
  818. for(; ea != nil; ea = tl ea)
  819. attrs = hd ea :: attrs;
  820. kc := chan of (list of ref Key, string);
  821. keymanc <-= (attrs, 1, kc);
  822. (kl, err) := <-kc;
  823. if(kl != nil)
  824. return (hd kl, err);
  825. return (nil, err);
  826. }
  827. IO.read(io: self ref IO): array of byte
  828. {
  829. io.ok();
  830. while((rpc := rio(io.f)) != nil)
  831. case rpc.cmd {
  832. * =>
  833. phase(rpc, "protocol phase error");
  834. Oauthinfo =>
  835. reply(rpc, "error authentication unfinished");
  836. Owrite =>
  837. io.rpc = rpc;
  838. if(rpc.arg == nil)
  839. rpc.arg = array[0] of byte;
  840. return rpc.arg;
  841. }
  842. exit;
  843. }
  844. IO.readn(io: self ref IO, n: int): array of byte
  845. {
  846. while((buf := io.read()) != nil && len buf < n)
  847. io.toosmall(n);
  848. return buf;
  849. }
  850. IO.write(io: self ref IO, buf: array of byte, n: int): int
  851. {
  852. io.ok();
  853. while((rpc := rio(io.f)) != nil)
  854. case rpc.cmd {
  855. Oread =>
  856. if(rpc.nbytes-3 >= n){
  857. okdata(rpc, buf[0:n]);
  858. return n;
  859. }
  860. io.rpc = rpc;
  861. io.toosmall(n+3);
  862. Oauthinfo =>
  863. reply(rpc, "error authentication unfinished");
  864. * =>
  865. phase(rpc, "protocol phase error");
  866. }
  867. exit;
  868. }
  869. IO.rdwr(io: self ref IO): array of byte
  870. {
  871. io.ok();
  872. while((rpc := rio(io.f)) != nil)
  873. case rpc.cmd {
  874. Oread =>
  875. io.rpc = rpc;
  876. if(rpc.nbytes >= 3)
  877. return nil;
  878. io.toosmall(128+3); # make them read something
  879. Owrite =>
  880. io.rpc = rpc;
  881. if(rpc.arg == nil)
  882. rpc.arg = array[0] of byte;
  883. return rpc.arg;
  884. Oauthinfo =>
  885. reply(rpc, "error authentication unfinished");
  886. * =>
  887. phase(rpc, "protocol phase error");
  888. }
  889. exit;
  890. }
  891. IO.reply2read(io: self ref IO, buf: array of byte, n: int): int
  892. {
  893. if(io.rpc == nil)
  894. return 0;
  895. rpc := io.rpc;
  896. if(rpc.cmd != Oread){
  897. io.rpc = nil;
  898. phase(rpc, "internal phase error");
  899. return 0;
  900. }
  901. if(rpc.nbytes-3 < n){
  902. io.toosmall(n+3);
  903. return 0;
  904. }
  905. io.rpc = nil;
  906. okdata(rpc, buf[0:n]);
  907. return 1;
  908. }
  909. IO.ok(io: self ref IO)
  910. {
  911. if(io.rpc != nil){
  912. reply(io.rpc, "ok");
  913. io.rpc = nil;
  914. }
  915. }
  916. IO.toosmall(io: self ref IO, n: int)
  917. {
  918. if(io.rpc != nil){
  919. reply(io.rpc, sys->sprint("toosmall %d", n));
  920. io.rpc = nil;
  921. }
  922. }
  923. IO.error(io: self ref IO, s: string)
  924. {
  925. if(io.rpc != nil){
  926. io.rpc.rc <-= (nil, "error "+s);
  927. io.rpc = nil;
  928. }
  929. }
  930. IO.done(io: self ref IO, ai: ref Authinfo)
  931. {
  932. io.f.ai = ai;
  933. io.ok();
  934. while((rpc := rio(io.f)) != nil)
  935. case rpc.cmd {
  936. Oread or Owrite =>
  937. done(rpc, ai);
  938. return;
  939. * =>
  940. phase(rpc, "protocol phase error");
  941. }
  942. }
  943. memrandom(a: array of byte, n: int)
  944. {
  945. if(0){
  946. # speed up testing
  947. for(i := 0; i < len a; i++)
  948. a[i] = byte i;
  949. return;
  950. }
  951. fd := sys->open("/dev/notquiterandom", Sys->OREAD);
  952. if(fd == nil)
  953. err("can't open /dev/notquiterandom");
  954. if(sys->read(fd, a, n) != n)
  955. err("can't read /dev/notquiterandom");
  956. }
  957. eqbytes(a, b: array of byte): int
  958. {
  959. if(len a != len b)
  960. return 0;
  961. for(i := 0; i < len a; i++)
  962. if(a[i] != b[i])
  963. return 0;
  964. return 1;
  965. }
  966. netmkaddr(addr, net, svc: string): string
  967. {
  968. if(net == nil)
  969. net = "net";
  970. (n, nil) := sys->tokenize(addr, "!");
  971. if(n <= 1){
  972. if(svc== nil)
  973. return sys->sprint("%s!%s", net, addr);
  974. return sys->sprint("%s!%s!%s", net, addr, svc);
  975. }
  976. if(svc == nil || n > 2)
  977. return addr;
  978. return sys->sprint("%s!%s", addr, svc);
  979. }