util.c 19 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013
  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. #include "dat.h"
  10. static char secstore[100]; /* server name */
  11. /* bind in the default network and cs */
  12. static int
  13. bindnetcs(void)
  14. {
  15. int srvfd;
  16. if(access("/net/tcp", AEXIST) < 0)
  17. bind("#I", "/net", MBEFORE);
  18. if(access("/net/cs", AEXIST) < 0){
  19. if((srvfd = open("#s/cs", ORDWR)) >= 0){
  20. if(mount(srvfd, -1, "/net", MBEFORE, "", 'M') >= 0)
  21. return 0;
  22. close(srvfd);
  23. }
  24. return -1;
  25. }
  26. return 0;
  27. }
  28. int
  29. _authdial(char *net, char *authdom)
  30. {
  31. int fd, vanilla;
  32. vanilla = net==nil || strcmp(net, "/net")==0;
  33. if(!vanilla || bindnetcs()>=0)
  34. return authdial(net, authdom);
  35. /*
  36. * If we failed to mount /srv/cs, assume that
  37. * we're still bootstrapping the system and dial
  38. * the one auth server passed to us on the command line.
  39. * In normal operation, it is important *not* to do this,
  40. * because the bootstrap auth server is only good for
  41. * a single auth domain.
  42. *
  43. * The ticket request code should really check the
  44. * remote authentication domain too.
  45. */
  46. /* use the auth server passed to us as an arg */
  47. if(authaddr == nil)
  48. return -1;
  49. fd = dial(netmkaddr(authaddr, "tcp", "567"), 0, 0, 0);
  50. if(fd >= 0)
  51. return fd;
  52. return dial(netmkaddr(authaddr, "il", "566"), 0, 0, 0);
  53. }
  54. int
  55. secdial(void)
  56. {
  57. char *p, buf[80], *f[3];
  58. int fd, nf;
  59. p = secstore; /* take it from writehostowner, if set there */
  60. if(*p == 0) /* else use the authserver */
  61. p = "$auth";
  62. if(bindnetcs() >= 0)
  63. return dial(netmkaddr(p, "net", "secstore"), 0, 0, 0);
  64. /* translate $auth ourselves.
  65. * authaddr is something like il!host!566 or tcp!host!567.
  66. * extract host, accounting for a change of format to something
  67. * like il!host or tcp!host or host.
  68. */
  69. if(strcmp(p, "$auth")==0){
  70. if(authaddr == nil)
  71. return -1;
  72. safecpy(buf, authaddr, sizeof buf);
  73. nf = getfields(buf, f, nelem(f), 0, "!");
  74. switch(nf){
  75. default:
  76. return -1;
  77. case 1:
  78. p = f[0];
  79. break;
  80. case 2:
  81. case 3:
  82. p = f[1];
  83. break;
  84. }
  85. }
  86. fd = dial(netmkaddr(p, "tcp", "5356"), 0, 0, 0);
  87. if(fd >= 0)
  88. return fd;
  89. return -1;
  90. }
  91. /*
  92. * prompt user for a key. don't care about memory leaks, runs standalone
  93. */
  94. static Attr*
  95. promptforkey(char *params)
  96. {
  97. char *v;
  98. int fd;
  99. Attr *a, *attr;
  100. char *def;
  101. fd = open("/dev/cons", ORDWR);
  102. if(fd < 0)
  103. sysfatal("opening /dev/cons: %r");
  104. attr = _parseattr(params);
  105. fprint(fd, "\n!Adding key:");
  106. for(a=attr; a; a=a->next)
  107. if(a->type != AttrQuery && a->name[0] != '!')
  108. fprint(fd, " %q=%q", a->name, a->val);
  109. fprint(fd, "\n");
  110. for(a=attr; a; a=a->next){
  111. v = a->name;
  112. if(a->type != AttrQuery || v[0]=='!')
  113. continue;
  114. def = nil;
  115. if(strcmp(v, "user") == 0)
  116. def = getuser();
  117. a->val = readcons(v, def, 0);
  118. if(a->val == nil)
  119. sysfatal("user terminated key input");
  120. a->type = AttrNameval;
  121. }
  122. for(a=attr; a; a=a->next){
  123. v = a->name;
  124. if(a->type != AttrQuery || v[0]!='!')
  125. continue;
  126. def = nil;
  127. if(strcmp(v+1, "user") == 0)
  128. def = getuser();
  129. a->val = readcons(v+1, def, 1);
  130. if(a->val == nil)
  131. sysfatal("user terminated key input");
  132. a->type = AttrNameval;
  133. }
  134. fprint(fd, "!\n");
  135. close(fd);
  136. return attr;
  137. }
  138. /*
  139. * send a key to the mounted factotum
  140. */
  141. static int
  142. sendkey(Attr *attr)
  143. {
  144. int fd, rv;
  145. char buf[1024];
  146. fd = open("/mnt/factotum/ctl", ORDWR);
  147. if(fd < 0)
  148. sysfatal("opening /mnt/factotum/ctl: %r");
  149. rv = fprint(fd, "key %A\n", attr);
  150. read(fd, buf, sizeof buf);
  151. close(fd);
  152. return rv;
  153. }
  154. /* askuser */
  155. void
  156. askuser(char *params)
  157. {
  158. Attr *attr;
  159. attr = promptforkey(params);
  160. if(attr == nil)
  161. sysfatal("no key supplied");
  162. if(sendkey(attr) < 0)
  163. sysfatal("sending key to factotum: %r");
  164. }
  165. uint32_t conftaggen;
  166. int
  167. canusekey(Fsstate *fss, Key *k)
  168. {
  169. int i;
  170. if(_strfindattr(k->attr, "confirm")){
  171. for(i=0; i<fss->nconf; i++)
  172. if(fss->conf[i].key == k)
  173. return fss->conf[i].canuse;
  174. if(fss->nconf%16 == 0)
  175. fss->conf = erealloc(fss->conf, (fss->nconf+16)*(sizeof(fss->conf[0])));
  176. fss->conf[fss->nconf].key = k;
  177. k->ref++;
  178. fss->conf[fss->nconf].canuse = -1;
  179. fss->conf[fss->nconf].tag = conftaggen++;
  180. fss->nconf++;
  181. return -1;
  182. }
  183. return 1;
  184. }
  185. /* closekey */
  186. void
  187. closekey(Key *k)
  188. {
  189. if(k == nil)
  190. return;
  191. if(--k->ref != 0)
  192. return;
  193. if(k->proto && k->proto->closekey)
  194. (*k->proto->closekey)(k);
  195. _freeattr(k->attr);
  196. _freeattr(k->privattr);
  197. k->attr = (void*)~1;
  198. k->privattr = (void*)~1;
  199. k->proto = nil;
  200. free(k);
  201. }
  202. static uint8_t*
  203. pstring(uint8_t *p, uint8_t *e, char *s)
  204. {
  205. uint n;
  206. if(p == nil)
  207. return nil;
  208. if(s == nil)
  209. s = "";
  210. n = strlen(s);
  211. if(p+n+BIT16SZ >= e)
  212. return nil;
  213. PBIT16(p, n);
  214. p += BIT16SZ;
  215. memmove(p, s, n);
  216. p += n;
  217. return p;
  218. }
  219. static uint8_t*
  220. pcarray(uint8_t *p, uint8_t *e, uint8_t *s, uint n)
  221. {
  222. if(p == nil)
  223. return nil;
  224. if(s == nil){
  225. if(n > 0)
  226. sysfatal("pcarray");
  227. s = (uint8_t*)"";
  228. }
  229. if(p+n+BIT16SZ >= e)
  230. return nil;
  231. PBIT16(p, n);
  232. p += BIT16SZ;
  233. memmove(p, s, n);
  234. p += n;
  235. return p;
  236. }
  237. uint8_t*
  238. convAI2M(AuthInfo *ai, uint8_t *p, int n)
  239. {
  240. uint8_t *e = p+n;
  241. p = pstring(p, e, ai->cuid);
  242. p = pstring(p, e, ai->suid);
  243. p = pstring(p, e, ai->cap);
  244. p = pcarray(p, e, ai->secret, ai->nsecret);
  245. return p;
  246. }
  247. int
  248. failure(Fsstate *s, char *fmt, ...)
  249. {
  250. char e[ERRMAX];
  251. va_list arg;
  252. if(fmt == nil)
  253. rerrstr(s->err, sizeof(s->err));
  254. else {
  255. va_start(arg, fmt);
  256. vsnprint(e, sizeof e, fmt, arg);
  257. va_end(arg);
  258. strecpy(s->err, s->err+sizeof(s->err), e);
  259. werrstr(e);
  260. }
  261. flog("%d: failure %s", s->seqnum, s->err);
  262. return RpcFailure;
  263. }
  264. static int
  265. hasqueries(Attr *a)
  266. {
  267. for(; a; a=a->next)
  268. if(a->type == AttrQuery)
  269. return 1;
  270. return 0;
  271. }
  272. char *ignored[] = {
  273. "role",
  274. "disabled",
  275. };
  276. static int
  277. ignoreattr(char *s)
  278. {
  279. int i;
  280. for(i=0; i<nelem(ignored); i++)
  281. if(strcmp(ignored[i], s)==0)
  282. return 1;
  283. return 0;
  284. }
  285. Keyinfo*
  286. mkkeyinfo(Keyinfo *k, Fsstate *fss, Attr *attr)
  287. {
  288. memset(k, 0, sizeof *k);
  289. k->fss = fss;
  290. k->user = fss->sysuser;
  291. if(attr)
  292. k->attr = attr;
  293. else
  294. k->attr = fss->attr;
  295. return k;
  296. }
  297. int
  298. findkey(Key **ret, Keyinfo *ki, char *fmt, ...)
  299. {
  300. int i, s, nmatch;
  301. char buf[1024], *p, *who;
  302. va_list arg;
  303. Attr *a, *attr0, *attr1, *attr2, *attr3, **l;
  304. Key *k;
  305. *ret = nil;
  306. who = ki->user;
  307. attr0 = ki->attr;
  308. if(fmt){
  309. va_start(arg, fmt);
  310. vseprint(buf, buf+sizeof buf, fmt, arg);
  311. va_end(arg);
  312. attr1 = _parseattr(buf);
  313. }else
  314. attr1 = nil;
  315. if(who && strcmp(who, owner) == 0)
  316. who = nil;
  317. if(who){
  318. snprint(buf, sizeof buf, "owner=%q", who);
  319. attr2 = _parseattr(buf);
  320. attr3 = _parseattr("owner=*");
  321. }else
  322. attr2 = attr3 = nil;
  323. p = _strfindattr(attr0, "proto");
  324. if(p == nil)
  325. p = _strfindattr(attr1, "proto");
  326. if(p && findproto(p) == nil){
  327. werrstr("unknown protocol %s", p);
  328. _freeattr(attr1);
  329. _freeattr(attr2);
  330. _freeattr(attr3);
  331. return failure(ki->fss, nil);
  332. }
  333. nmatch = 0;
  334. for(i=0; i<ring->nkey; i++){
  335. k = ring->key[i];
  336. if(_strfindattr(k->attr, "disabled") && !ki->usedisabled)
  337. continue;
  338. if(matchattr(attr0, k->attr, k->privattr) && matchattr(attr1, k->attr, k->privattr)){
  339. /* check ownership */
  340. if(!matchattr(attr2, k->attr, nil) && !matchattr(attr3, k->attr, nil))
  341. continue;
  342. if(nmatch++ < ki->skip)
  343. continue;
  344. if(!ki->noconf){
  345. switch(canusekey(ki->fss, k)){
  346. case -1:
  347. _freeattr(attr1);
  348. return RpcConfirm;
  349. case 0:
  350. continue;
  351. case 1:
  352. break;
  353. }
  354. }
  355. _freeattr(attr1);
  356. _freeattr(attr2);
  357. _freeattr(attr3);
  358. k->ref++;
  359. *ret = k;
  360. return RpcOk;
  361. }
  362. }
  363. flog("%d: no key matches %A %A %A %A", ki->fss->seqnum, attr0, attr1, attr2, attr3);
  364. werrstr("no key matches %A %A", attr0, attr1);
  365. _freeattr(attr2);
  366. _freeattr(attr3);
  367. s = RpcFailure;
  368. if(askforkeys && who==nil && (hasqueries(attr0) || hasqueries(attr1))){
  369. if(nmatch == 0){
  370. attr0 = _copyattr(attr0);
  371. for(l=&attr0; *l; l=&(*l)->next)
  372. ;
  373. *l = attr1;
  374. for(l=&attr0; *l; ){
  375. if(ignoreattr((*l)->name)){
  376. a = *l;
  377. *l = (*l)->next;
  378. a->next = nil;
  379. _freeattr(a);
  380. }else
  381. l = &(*l)->next;
  382. }
  383. attr0 = sortattr(attr0);
  384. snprint(ki->fss->keyinfo, sizeof ki->fss->keyinfo, "%A", attr0);
  385. _freeattr(attr0);
  386. attr1 = nil; /* attr1 was linked to attr0 */
  387. }else
  388. ki->fss->keyinfo[0] = '\0';
  389. s = RpcNeedkey;
  390. }
  391. _freeattr(attr1);
  392. if(s == RpcFailure)
  393. return failure(ki->fss, nil); /* loads error string */
  394. return s;
  395. }
  396. int
  397. findp9authkey(Key **k, Fsstate *fss)
  398. {
  399. char *dom;
  400. Keyinfo ki;
  401. /*
  402. * We don't use fss->attr here because we don't
  403. * care about what the user name is set to, for instance.
  404. */
  405. mkkeyinfo(&ki, fss, nil);
  406. ki.attr = nil;
  407. ki.user = nil;
  408. if((dom = _strfindattr(fss->attr, "dom")) != nil)
  409. return findkey(k, &ki, "proto=p9sk1 dom=%q role=server user?", dom);
  410. else
  411. return findkey(k, &ki, "proto=p9sk1 role=server dom? user?");
  412. }
  413. Proto*
  414. findproto(char *name)
  415. {
  416. int i;
  417. for(i=0; prototab[i]; i++)
  418. if(strcmp(name, prototab[i]->name) == 0)
  419. return prototab[i];
  420. return nil;
  421. }
  422. char*
  423. getnvramkey(int flag, char **secstorepw)
  424. {
  425. char *s;
  426. Nvrsafe safe;
  427. char spw[CONFIGLEN+1];
  428. int i;
  429. memset(&safe, 0, sizeof safe);
  430. /*
  431. * readnvram can return -1 meaning nvram wasn't written,
  432. * but safe still holds good data.
  433. */
  434. if(readnvram(&safe, flag)<0 && safe.authid[0]==0)
  435. return nil;
  436. /*
  437. * we're using the config area to hold the secstore
  438. * password. if there's anything there, return it.
  439. */
  440. memmove(spw, safe.config, CONFIGLEN);
  441. spw[CONFIGLEN] = 0;
  442. if(spw[0] != 0)
  443. *secstorepw = estrdup(spw);
  444. /*
  445. * only use nvram key if it is non-zero
  446. */
  447. for(i = 0; i < DESKEYLEN; i++)
  448. if(safe.machkey[i] != 0)
  449. break;
  450. if(i == DESKEYLEN)
  451. return nil;
  452. s = emalloc(512);
  453. fmtinstall('H', encodefmt);
  454. snprint(s, 512, "key proto=p9sk1 user=%q dom=%q !hex=%.*H !password=______",
  455. safe.authid, safe.authdom, DESKEYLEN, safe.machkey);
  456. writehostowner(safe.authid);
  457. return s;
  458. }
  459. int
  460. isclient(char *role)
  461. {
  462. if(role == nil){
  463. werrstr("role not specified");
  464. return -1;
  465. }
  466. if(strcmp(role, "server") == 0)
  467. return 0;
  468. if(strcmp(role, "client") == 0)
  469. return 1;
  470. werrstr("unknown role %q", role);
  471. return -1;
  472. }
  473. static int
  474. hasname(Attr *a0, Attr *a1, char *name)
  475. {
  476. return _findattr(a0, name) || _findattr(a1, name);
  477. }
  478. static int
  479. hasnameval(Attr *a0, Attr *a1, char *name, char *val)
  480. {
  481. Attr *a;
  482. for(a=_findattr(a0, name); a; a=_findattr(a->next, name))
  483. if(strcmp(a->val, val) == 0)
  484. return 1;
  485. for(a=_findattr(a1, name); a; a=_findattr(a->next, name))
  486. if(strcmp(a->val, val) == 0)
  487. return 1;
  488. return 0;
  489. }
  490. int
  491. matchattr(Attr *pat, Attr *a0, Attr *a1)
  492. {
  493. int type;
  494. for(; pat; pat=pat->next){
  495. type = pat->type;
  496. if(ignoreattr(pat->name))
  497. type = AttrDefault;
  498. switch(type){
  499. case AttrQuery: /* name=something be present */
  500. if(!hasname(a0, a1, pat->name))
  501. return 0;
  502. break;
  503. case AttrNameval: /* name=val must be present */
  504. if(!hasnameval(a0, a1, pat->name, pat->val))
  505. return 0;
  506. break;
  507. case AttrDefault: /* name=val must be present if name=anything is present */
  508. if(hasname(a0, a1, pat->name) && !hasnameval(a0, a1, pat->name, pat->val))
  509. return 0;
  510. break;
  511. }
  512. }
  513. return 1;
  514. }
  515. void
  516. memrandom(void *p, int n)
  517. {
  518. uint8_t *cp;
  519. for(cp = (uint8_t*)p; n > 0; n--)
  520. *cp++ = fastrand();
  521. }
  522. /*
  523. * keep caphash fd open since opens of it could be disabled
  524. */
  525. static int caphashfd;
  526. void
  527. initcap(void)
  528. {
  529. caphashfd = open("#¤/caphash", OWRITE);
  530. // if(caphashfd < 0)
  531. // fprint(2, "%s: opening #¤/caphash: %r\n", argv0);
  532. }
  533. /*
  534. * create a change uid capability
  535. */
  536. char*
  537. mkcap(char *from, char *to)
  538. {
  539. uint8_t rand[20];
  540. char *cap;
  541. char *key;
  542. int nfrom, nto, ncap;
  543. uint8_t hash[SHA1dlen];
  544. if(caphashfd < 0)
  545. return nil;
  546. /* create the capability */
  547. nto = strlen(to);
  548. nfrom = strlen(from);
  549. ncap = nfrom + 1 + nto + 1 + sizeof(rand)*3 + 1;
  550. cap = emalloc(ncap);
  551. snprint(cap, ncap, "%s@%s", from, to);
  552. memrandom(rand, sizeof(rand));
  553. key = cap+nfrom+1+nto+1;
  554. enc64(key, sizeof(rand)*3, rand, sizeof(rand));
  555. /* hash the capability */
  556. hmac_sha1((uint8_t*)cap, strlen(cap), (uint8_t*)key, strlen(key),
  557. hash, nil);
  558. /* give the kernel the hash */
  559. key[-1] = '@';
  560. if(write(caphashfd, hash, SHA1dlen) < 0){
  561. free(cap);
  562. return nil;
  563. }
  564. return cap;
  565. }
  566. int
  567. phaseerror(Fsstate *s, char *op)
  568. {
  569. char tmp[32];
  570. werrstr("protocol phase error: %s in state %s", op, phasename(s, s->phase, tmp));
  571. return RpcPhase;
  572. }
  573. char*
  574. phasename(Fsstate *fss, int phase, char *tmp)
  575. {
  576. char *name;
  577. if(fss->phase == Broken)
  578. name = "Broken";
  579. else if(phase == Established)
  580. name = "Established";
  581. else if(phase == Notstarted)
  582. name = "Notstarted";
  583. else if(phase < 0 || phase >= fss->maxphase
  584. || (name = fss->phasename[phase]) == nil){
  585. sprint(tmp, "%d", phase);
  586. name = tmp;
  587. }
  588. return name;
  589. }
  590. static int
  591. outin(char *prompt, char *def, int len)
  592. {
  593. char *s;
  594. s = readcons(prompt, def, 0);
  595. if(s == nil)
  596. return -1;
  597. if(s == nil)
  598. sysfatal("s==nil???");
  599. strncpy(def, s, len);
  600. def[len-1] = 0;
  601. free(s);
  602. return strlen(def);
  603. }
  604. /*
  605. * get host owner and set it
  606. */
  607. void
  608. promptforhostowner(void)
  609. {
  610. char owner[64], *p;
  611. /* hack for bitsy; can't prompt during boot */
  612. if((p = getenv("user")) != nil){
  613. writehostowner(p);
  614. free(p);
  615. return;
  616. }
  617. free(p);
  618. strcpy(owner, "none");
  619. do{
  620. outin("user", owner, sizeof(owner));
  621. } while(*owner == 0);
  622. writehostowner(owner);
  623. }
  624. char*
  625. estrappend(char *s, char *fmt, ...)
  626. {
  627. char *t;
  628. va_list arg;
  629. va_start(arg, fmt);
  630. t = vsmprint(fmt, arg);
  631. if(t == nil)
  632. sysfatal("out of memory");
  633. va_end(arg);
  634. s = erealloc(s, strlen(s)+strlen(t)+1);
  635. strcat(s, t);
  636. free(t);
  637. return s;
  638. }
  639. /*
  640. * prompt for a string with a possible default response
  641. */
  642. char*
  643. readcons(char *prompt, char *def, int raw)
  644. {
  645. int fdin, fdout, ctl, n;
  646. char line[10];
  647. char *s;
  648. fdin = open("/dev/cons", OREAD);
  649. if(fdin < 0)
  650. fdin = 0;
  651. fdout = open("/dev/cons", OWRITE);
  652. if(fdout < 0)
  653. fdout = 1;
  654. if(def != nil)
  655. fprint(fdout, "%s[%s]: ", prompt, def);
  656. else
  657. fprint(fdout, "%s: ", prompt);
  658. if(raw){
  659. ctl = open("/dev/consctl", OWRITE);
  660. if(ctl >= 0)
  661. write(ctl, "rawon", 5);
  662. } else
  663. ctl = -1;
  664. s = estrdup("");
  665. for(;;){
  666. n = read(fdin, line, 1);
  667. if(n == 0){
  668. Error:
  669. close(fdin);
  670. close(fdout);
  671. if(ctl >= 0)
  672. close(ctl);
  673. free(s);
  674. return nil;
  675. }
  676. if(n < 0)
  677. goto Error;
  678. if(line[0] == 0x7f)
  679. goto Error;
  680. if(n == 0 || line[0] == '\n' || line[0] == '\r'){
  681. if(raw){
  682. write(ctl, "rawoff", 6);
  683. write(fdout, "\n", 1);
  684. }
  685. close(ctl);
  686. close(fdin);
  687. close(fdout);
  688. if(*s == 0 && def != nil)
  689. s = estrappend(s, "%s", def);
  690. return s;
  691. }
  692. if(line[0] == '\b'){
  693. if(strlen(s) > 0)
  694. s[strlen(s)-1] = 0;
  695. } else if(line[0] == 0x15) { /* ^U: line kill */
  696. if(def != nil)
  697. fprint(fdout, "\n%s[%s]: ", prompt, def);
  698. else
  699. fprint(fdout, "\n%s: ", prompt);
  700. s[0] = 0;
  701. } else {
  702. s = estrappend(s, "%c", line[0]);
  703. }
  704. }
  705. }
  706. /*
  707. * Insert a key into the keyring.
  708. * If the public attributes are identical to some other key, replace that one.
  709. */
  710. int
  711. replacekey(Key *kn, int before)
  712. {
  713. int i;
  714. Key *k;
  715. for(i=0; i<ring->nkey; i++){
  716. k = ring->key[i];
  717. if(matchattr(kn->attr, k->attr, nil) && matchattr(k->attr, kn->attr, nil)){
  718. closekey(k);
  719. kn->ref++;
  720. ring->key[i] = kn;
  721. return 0;
  722. }
  723. }
  724. if(ring->nkey%16 == 0)
  725. ring->key = erealloc(ring->key, (ring->nkey+16)*sizeof(ring->key[0]));
  726. kn->ref++;
  727. if(before){
  728. memmove(ring->key+1, ring->key, ring->nkey*sizeof ring->key[0]);
  729. ring->key[0] = kn;
  730. ring->nkey++;
  731. }else
  732. ring->key[ring->nkey++] = kn;
  733. return 0;
  734. }
  735. char*
  736. safecpy(char *to, char *from, int n)
  737. {
  738. memset(to, 0, n);
  739. if(n == 1)
  740. return to;
  741. if(from==nil)
  742. sysfatal("safecpy called with from==nil, pc=%#p",
  743. getcallerpc());
  744. strncpy(to, from, n-1);
  745. return to;
  746. }
  747. Attr*
  748. setattr(Attr *a, char *fmt, ...)
  749. {
  750. char buf[1024];
  751. va_list arg;
  752. Attr *b;
  753. va_start(arg, fmt);
  754. vseprint(buf, buf+sizeof buf, fmt, arg);
  755. va_end(arg);
  756. b = _parseattr(buf);
  757. a = setattrs(a, b);
  758. setmalloctag(a, getcallerpc());
  759. _freeattr(b);
  760. return a;
  761. }
  762. /*
  763. * add attributes in list b to list a. If any attributes are in
  764. * both lists, replace those in a by those in b.
  765. */
  766. Attr*
  767. setattrs(Attr *a, Attr *b)
  768. {
  769. int found;
  770. Attr **l, *freea;
  771. for(; b; b=b->next){
  772. found = 0;
  773. for(l=&a; *l; ){
  774. if(strcmp(b->name, (*l)->name) == 0){
  775. switch(b->type){
  776. case AttrNameval:
  777. if(!found){
  778. found = 1;
  779. free((*l)->val);
  780. (*l)->val = estrdup(b->val);
  781. (*l)->type = AttrNameval;
  782. l = &(*l)->next;
  783. }else{
  784. freea = *l;
  785. *l = (*l)->next;
  786. freea->next = nil;
  787. _freeattr(freea);
  788. }
  789. break;
  790. case AttrQuery:
  791. goto continue2;
  792. }
  793. }else
  794. l = &(*l)->next;
  795. }
  796. if(found == 0){
  797. *l = _mkattr(b->type, b->name, b->val, nil);
  798. setmalloctag(*l, getcallerpc());
  799. }
  800. continue2:;
  801. }
  802. return a;
  803. }
  804. void
  805. setmalloctaghere(void *v)
  806. {
  807. setmalloctag(v, getcallerpc());
  808. }
  809. Attr*
  810. sortattr(Attr *a)
  811. {
  812. int i;
  813. Attr *anext, *a0, *a1, **l;
  814. if(a == nil || a->next == nil)
  815. return a;
  816. /* cut list in halves */
  817. a0 = nil;
  818. a1 = nil;
  819. i = 0;
  820. for(; a; a=anext){
  821. anext = a->next;
  822. if(i++%2){
  823. a->next = a0;
  824. a0 = a;
  825. }else{
  826. a->next = a1;
  827. a1 = a;
  828. }
  829. }
  830. /* sort */
  831. a0 = sortattr(a0);
  832. a1 = sortattr(a1);
  833. /* merge */
  834. l = &a;
  835. while(a0 || a1){
  836. if(a1==nil){
  837. anext = a0;
  838. a0 = a0->next;
  839. }else if(a0==nil){
  840. anext = a1;
  841. a1 = a1->next;
  842. }else if(strcmp(a0->name, a1->name) < 0){
  843. anext = a0;
  844. a0 = a0->next;
  845. }else{
  846. anext = a1;
  847. a1 = a1->next;
  848. }
  849. *l = anext;
  850. l = &(*l)->next;
  851. }
  852. *l = nil;
  853. return a;
  854. }
  855. int
  856. toosmall(Fsstate *fss, uint n)
  857. {
  858. fss->rpc.nwant = n;
  859. return RpcToosmall;
  860. }
  861. void
  862. writehostowner(char *owner)
  863. {
  864. int fd;
  865. char *s;
  866. if((s = strchr(owner,'@')) != nil){
  867. *s++ = 0;
  868. strncpy(secstore, s, (sizeof secstore)-1);
  869. }
  870. fd = open("#c/hostowner", OWRITE);
  871. if(fd >= 0){
  872. if(fprint(fd, "%s", owner) < 0)
  873. fprint(2, "factotum: setting #c/hostowner to %q: %r\n",
  874. owner);
  875. close(fd);
  876. }
  877. }
  878. int
  879. attrnamefmt(Fmt *fmt)
  880. {
  881. char *b, buf[1024], *ebuf;
  882. Attr *a;
  883. ebuf = buf+sizeof buf;
  884. b = buf;
  885. strcpy(buf, " ");
  886. for(a=va_arg(fmt->args, Attr*); a; a=a->next){
  887. if(a->name == nil)
  888. continue;
  889. b = seprint(b, ebuf, " %q?", a->name);
  890. }
  891. return fmtstrcpy(fmt, buf+1);
  892. }
  893. void
  894. disablekey(Key *k)
  895. {
  896. Attr *a;
  897. if(sflag) /* not on servers */
  898. return;
  899. for(a=k->attr; a; a=a->next){
  900. if(a->type==AttrNameval && strcmp(a->name, "disabled") == 0)
  901. return;
  902. if(a->next == nil)
  903. break;
  904. }
  905. if(a)
  906. a->next = _mkattr(AttrNameval, "disabled", "by.factotum", nil);
  907. else
  908. k->attr = _mkattr(AttrNameval, "disabled", "by.factotum", nil); /* not reached: always a proto attribute */
  909. }