keyfs.c 19 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123
  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. * keyfs
  11. */
  12. #include <u.h>
  13. #include <libc.h>
  14. #include <ctype.h>
  15. #include <authsrv.h>
  16. #include <fcall.h>
  17. #include <bio.h>
  18. #include <mp.h>
  19. #include <libsec.h>
  20. #include "authcmdlib.h"
  21. #pragma varargck type "W" char*
  22. char authkey[8];
  23. typedef struct Fid Fid;
  24. typedef struct User User;
  25. enum {
  26. Qroot,
  27. Quser,
  28. Qkey,
  29. Qsecret,
  30. Qlog,
  31. Qstatus,
  32. Qexpire,
  33. Qwarnings,
  34. Qmax,
  35. Nuser = 512,
  36. MAXBAD = 10, /* max # of bad attempts before disabling the account */
  37. /* file must be randomly addressible, so names have fixed length */
  38. Namelen = ANAMELEN,
  39. };
  40. enum {
  41. Sok,
  42. Sdisabled,
  43. Smax,
  44. };
  45. struct Fid {
  46. int fid;
  47. uint32_t qtype;
  48. User *user;
  49. int busy;
  50. Fid *next;
  51. };
  52. struct User {
  53. char *name;
  54. char key[DESKEYLEN];
  55. char secret[SECRETLEN];
  56. uint32_t expire; /* 0 == never */
  57. uint8_t status;
  58. uint32_t bad; /* # of consecutive bad authentication attempts */
  59. int ref;
  60. char removed;
  61. uint8_t warnings;
  62. int32_t purgatory; /* time purgatory ends */
  63. uint32_t uniq;
  64. User *link;
  65. };
  66. char *qinfo[Qmax] = {
  67. [Qroot] = "keys",
  68. [Quser] = ".",
  69. [Qkey] = "key",
  70. [Qsecret] = "secret",
  71. [Qlog] = "log",
  72. [Qexpire] = "expire",
  73. [Qstatus] = "status",
  74. [Qwarnings] = "warnings",
  75. };
  76. char *status[Smax] = {
  77. [Sok] = "ok",
  78. [Sdisabled] = "disabled",
  79. };
  80. Fid *fids;
  81. User *users[Nuser];
  82. char *userkeys;
  83. int nuser;
  84. uint32_t uniq = 1;
  85. Fcall rhdr,
  86. thdr;
  87. int usepass;
  88. char *warnarg;
  89. uint8_t mdata[8192 + IOHDRSZ];
  90. int messagesize = sizeof mdata;
  91. int readusers(void);
  92. uint32_t hash(char*);
  93. Fid *findfid(int);
  94. User *finduser(char*);
  95. User *installuser(char*);
  96. int removeuser(User*);
  97. void insertuser(User*);
  98. void writeusers(void);
  99. void io(int, int);
  100. void *emalloc(uint32_t);
  101. Qid mkqid(User*, uint32_t);
  102. int dostat(User*, uint32_t, void*, int);
  103. int newkeys(void);
  104. void warning(void);
  105. int weirdfmt(Fmt *f);
  106. char *Auth(Fid*), *Attach(Fid*), *Version(Fid*),
  107. *Flush(Fid*), *Walk(Fid*),
  108. *Open(Fid*), *Create(Fid*),
  109. *Read(Fid *), *Write(Fid*), *Clunk(Fid*),
  110. *Remove(Fid *), *Stat(Fid*), *Wstat(Fid*);
  111. char *(*fcalls[])(Fid*) = {
  112. [Tattach] = Attach,
  113. [Tauth] = Auth,
  114. [Tclunk] = Clunk,
  115. [Tcreate] = Create,
  116. [Tflush] = Flush,
  117. [Topen] = Open,
  118. [Tread] = Read,
  119. [Tremove] = Remove,
  120. [Tstat] = Stat,
  121. [Tversion] = Version,
  122. [Twalk] = Walk,
  123. [Twrite] = Write,
  124. [Twstat] = Wstat,
  125. };
  126. static void
  127. usage(void)
  128. {
  129. fprint(2, "usage: %s [-p] [-m mtpt] [-w warn] [keyfile]\n", argv0);
  130. exits("usage");
  131. }
  132. void
  133. main(int argc, char *argv[])
  134. {
  135. char *mntpt;
  136. int p[2];
  137. fmtinstall('W', weirdfmt);
  138. mntpt = "/mnt/keys";
  139. ARGBEGIN{
  140. case 'm':
  141. mntpt = EARGF(usage());
  142. break;
  143. case 'p':
  144. usepass = 1;
  145. break;
  146. case 'w':
  147. warnarg = EARGF(usage());
  148. break;
  149. default:
  150. usage();
  151. break;
  152. }ARGEND
  153. argv0 = "keyfs";
  154. userkeys = "/adm/keys";
  155. if(argc > 1)
  156. usage();
  157. if(argc == 1)
  158. userkeys = argv[0];
  159. if(pipe(p) < 0)
  160. error("can't make pipe: %r");
  161. if(usepass) {
  162. getpass(authkey, nil, 0, 0);
  163. } else {
  164. if(!getauthkey(authkey))
  165. print("keyfs: warning: can't read NVRAM\n");
  166. }
  167. switch(rfork(RFPROC|RFNAMEG|RFNOTEG|RFNOWAIT|RFENVG|RFFDG)){
  168. case 0:
  169. close(p[0]);
  170. io(p[1], p[1]);
  171. exits(0);
  172. case -1:
  173. error("fork");
  174. default:
  175. close(p[1]);
  176. if(mount(p[0], -1, mntpt, MREPL|MCREATE, "", 'M') < 0)
  177. error("can't mount: %r");
  178. exits(0);
  179. }
  180. }
  181. char *
  182. Flush(Fid *f)
  183. {
  184. USED(f);
  185. return 0;
  186. }
  187. char *
  188. Auth(Fid *f)
  189. {
  190. return "keyfs: authentication not required";
  191. }
  192. char *
  193. Attach(Fid *f)
  194. {
  195. if(f->busy)
  196. Clunk(f);
  197. f->user = 0;
  198. f->qtype = Qroot;
  199. f->busy = 1;
  200. thdr.qid = mkqid(f->user, f->qtype);
  201. return 0;
  202. }
  203. char*
  204. Version(Fid *g)
  205. {
  206. Fid *f;
  207. for(f = fids; f; f = f->next)
  208. if(f->busy)
  209. Clunk(f);
  210. if(rhdr.msize > sizeof mdata)
  211. thdr.msize = sizeof mdata;
  212. else
  213. thdr.msize = rhdr.msize;
  214. messagesize = thdr.msize;
  215. if(strncmp(rhdr.version, "9P2000", 6) != 0)
  216. return "bad 9P version";
  217. thdr.version = "9P2000";
  218. return 0;
  219. }
  220. char *
  221. Walk(Fid *f)
  222. {
  223. char *name, *err;
  224. int i, j, max;
  225. Fid *nf;
  226. uint32_t qtype;
  227. User *user;
  228. if(!f->busy)
  229. return "walk of unused fid";
  230. nf = nil;
  231. qtype = f->qtype;
  232. user = f->user;
  233. if(rhdr.fid != rhdr.newfid){
  234. nf = findfid(rhdr.newfid);
  235. if(nf->busy)
  236. return "fid in use";
  237. f = nf; /* walk f */
  238. }
  239. err = nil;
  240. i = 0;
  241. if(rhdr.nwname > 0){
  242. for(; i<rhdr.nwname; i++){
  243. if(i >= MAXWELEM){
  244. err = "too many path name elements";
  245. break;
  246. }
  247. name = rhdr.wname[i];
  248. switch(qtype){
  249. case Qroot:
  250. if(strcmp(name, "..") == 0)
  251. goto Accept;
  252. user = finduser(name);
  253. if(!user)
  254. goto Out;
  255. qtype = Quser;
  256. Accept:
  257. thdr.wqid[i] = mkqid(user, qtype);
  258. break;
  259. case Quser:
  260. if(strcmp(name, "..") == 0) {
  261. qtype = Qroot;
  262. user = 0;
  263. goto Accept;
  264. }
  265. max = Qmax;
  266. for(j = Quser + 1; j < Qmax; j++)
  267. if(strcmp(name, qinfo[j]) == 0){
  268. qtype = j;
  269. break;
  270. }
  271. if(j < max)
  272. goto Accept;
  273. goto Out;
  274. default:
  275. err = "file is not a directory";
  276. goto Out;
  277. }
  278. }
  279. Out:
  280. if(i < rhdr.nwname && err == nil)
  281. err = "file not found";
  282. }
  283. if(err != nil){
  284. return err;
  285. }
  286. /* if we cloned and then completed the walk, update new fid */
  287. if(rhdr.fid != rhdr.newfid && i == rhdr.nwname){
  288. nf->busy = 1;
  289. nf->qtype = qtype;
  290. if(nf->user = user)
  291. nf->user->ref++;
  292. }else if(nf == nil && rhdr.nwname > 0){ /* walk without clone (rare) */
  293. Clunk(f);
  294. f->busy = 1;
  295. f->qtype = qtype;
  296. if(f->user = user)
  297. f->user->ref++;
  298. }
  299. thdr.nwqid = i;
  300. return 0;
  301. }
  302. char *
  303. Clunk(Fid *f)
  304. {
  305. f->busy = 0;
  306. if(f->user && --f->user->ref == 0 && f->user->removed) {
  307. free(f->user->name);
  308. free(f->user);
  309. }
  310. f->user = 0;
  311. return 0;
  312. }
  313. char *
  314. Open(Fid *f)
  315. {
  316. int mode;
  317. if(!f->busy)
  318. return "open of unused fid";
  319. mode = rhdr.mode;
  320. if(f->qtype == Quser && (mode & (OWRITE|OTRUNC)))
  321. return "user already exists";
  322. thdr.qid = mkqid(f->user, f->qtype);
  323. thdr.iounit = messagesize - IOHDRSZ;
  324. return 0;
  325. }
  326. char *
  327. Create(Fid *f)
  328. {
  329. char *name;
  330. int32_t perm;
  331. if(!f->busy)
  332. return "create of unused fid";
  333. name = rhdr.name;
  334. if(f->user){
  335. return "permission denied";
  336. }else{
  337. perm = rhdr.perm;
  338. if(!(perm & DMDIR))
  339. return "permission denied";
  340. if(strcmp(name, "") == 0)
  341. return "empty file name";
  342. if(strlen(name) >= Namelen)
  343. return "file name too long";
  344. if(finduser(name))
  345. return "user already exists";
  346. f->user = installuser(name);
  347. f->user->ref++;
  348. f->qtype = Quser;
  349. }
  350. thdr.qid = mkqid(f->user, f->qtype);
  351. thdr.iounit = messagesize - IOHDRSZ;
  352. writeusers();
  353. return 0;
  354. }
  355. char *
  356. Read(Fid *f)
  357. {
  358. User *u;
  359. char *data;
  360. uint32_t off, n, m;
  361. int i, j, max;
  362. if(!f->busy)
  363. return "read of unused fid";
  364. n = rhdr.count;
  365. off = rhdr.offset;
  366. thdr.count = 0;
  367. data = thdr.data;
  368. switch(f->qtype){
  369. case Qroot:
  370. j = 0;
  371. for(i = 0; i < Nuser; i++)
  372. for(u = users[i]; u; j += m, u = u->link){
  373. m = dostat(u, Quser, data, n);
  374. if(m <= BIT16SZ)
  375. break;
  376. if(j < off)
  377. continue;
  378. data += m;
  379. n -= m;
  380. }
  381. thdr.count = data - thdr.data;
  382. return 0;
  383. case Quser:
  384. max = Qmax;
  385. max -= Quser + 1;
  386. j = 0;
  387. for(i = 0; i < max; j += m, i++){
  388. m = dostat(f->user, i + Quser + 1, data, n);
  389. if(m <= BIT16SZ)
  390. break;
  391. if(j < off)
  392. continue;
  393. data += m;
  394. n -= m;
  395. }
  396. thdr.count = data - thdr.data;
  397. return 0;
  398. case Qkey:
  399. if(f->user->status != Sok)
  400. return "user disabled";
  401. if(f->user->purgatory > time(0))
  402. return "user in purgatory";
  403. if(f->user->expire != 0 && f->user->expire < time(0))
  404. return "user expired";
  405. if(off != 0)
  406. return 0;
  407. if(n > DESKEYLEN)
  408. n = DESKEYLEN;
  409. memmove(thdr.data, f->user->key, n);
  410. thdr.count = n;
  411. return 0;
  412. case Qsecret:
  413. if(f->user->status != Sok)
  414. return "user disabled";
  415. if(f->user->purgatory > time(0))
  416. return "user in purgatory";
  417. if(f->user->expire != 0 && f->user->expire < time(0))
  418. return "user expired";
  419. if(off != 0)
  420. return 0;
  421. if(n > strlen(f->user->secret))
  422. n = strlen(f->user->secret);
  423. memmove(thdr.data, f->user->secret, n);
  424. thdr.count = n;
  425. return 0;
  426. case Qstatus:
  427. if(off != 0){
  428. thdr.count = 0;
  429. return 0;
  430. }
  431. if(f->user->status == Sok && f->user->expire && f->user->expire < time(0))
  432. sprint(thdr.data, "expired\n");
  433. else
  434. sprint(thdr.data, "%s\n", status[f->user->status]);
  435. thdr.count = strlen(thdr.data);
  436. return 0;
  437. case Qexpire:
  438. if(off != 0){
  439. thdr.count = 0;
  440. return 0;
  441. }
  442. if(!f->user->expire)
  443. strcpy(data, "never\n");
  444. else
  445. sprint(data, "%lu\n", f->user->expire);
  446. if(n > strlen(data))
  447. n = strlen(data);
  448. thdr.count = n;
  449. return 0;
  450. case Qlog:
  451. if(off != 0){
  452. thdr.count = 0;
  453. return 0;
  454. }
  455. sprint(data, "%lu\n", f->user->bad);
  456. if(n > strlen(data))
  457. n = strlen(data);
  458. thdr.count = n;
  459. return 0;
  460. case Qwarnings:
  461. if(off != 0){
  462. thdr.count = 0;
  463. return 0;
  464. }
  465. sprint(data, "%u\n", f->user->warnings);
  466. if(n > strlen(data))
  467. n = strlen(data);
  468. thdr.count = n;
  469. return 0;
  470. default:
  471. return "permission denied: unknown qid";
  472. }
  473. }
  474. char *
  475. Write(Fid *f)
  476. {
  477. char *data, *p;
  478. uint32_t n, expire;
  479. int i;
  480. if(!f->busy)
  481. return "permission denied";
  482. n = rhdr.count;
  483. data = rhdr.data;
  484. switch(f->qtype){
  485. case Qkey:
  486. if(n != DESKEYLEN)
  487. return "garbled write data";
  488. memmove(f->user->key, data, DESKEYLEN);
  489. thdr.count = DESKEYLEN;
  490. break;
  491. case Qsecret:
  492. if(n >= SECRETLEN)
  493. return "garbled write data";
  494. memmove(f->user->secret, data, n);
  495. f->user->secret[n] = 0;
  496. thdr.count = n;
  497. break;
  498. case Qstatus:
  499. data[n] = '\0';
  500. if(p = strchr(data, '\n'))
  501. *p = '\0';
  502. for(i = 0; i < Smax; i++)
  503. if(strcmp(data, status[i]) == 0){
  504. f->user->status = i;
  505. break;
  506. }
  507. if(i == Smax)
  508. return "unknown status";
  509. f->user->bad = 0;
  510. thdr.count = n;
  511. break;
  512. case Qexpire:
  513. data[n] = '\0';
  514. if(p = strchr(data, '\n'))
  515. *p = '\0';
  516. else
  517. p = &data[n];
  518. if(strcmp(data, "never") == 0)
  519. expire = 0;
  520. else{
  521. expire = strtoul(data, &data, 10);
  522. if(data != p)
  523. return "bad expiration date";
  524. }
  525. f->user->expire = expire;
  526. f->user->warnings = 0;
  527. thdr.count = n;
  528. break;
  529. case Qlog:
  530. data[n] = '\0';
  531. if(strcmp(data, "good") == 0)
  532. f->user->bad = 0;
  533. else
  534. f->user->bad++;
  535. if(f->user->bad && ((f->user->bad)%MAXBAD) == 0)
  536. f->user->purgatory = time(0) + f->user->bad;
  537. return 0;
  538. case Qwarnings:
  539. data[n] = '\0';
  540. f->user->warnings = strtoul(data, 0, 10);
  541. thdr.count = n;
  542. break;
  543. case Qroot:
  544. case Quser:
  545. default:
  546. return "permission denied";
  547. }
  548. writeusers();
  549. return 0;
  550. }
  551. char *
  552. Remove(Fid *f)
  553. {
  554. if(!f->busy)
  555. return "permission denied";
  556. if(f->qtype == Qwarnings)
  557. f->user->warnings = 0;
  558. else if(f->qtype == Quser)
  559. removeuser(f->user);
  560. else {
  561. Clunk(f);
  562. return "permission denied";
  563. }
  564. Clunk(f);
  565. writeusers();
  566. return 0;
  567. }
  568. char *
  569. Stat(Fid *f)
  570. {
  571. static uint8_t statbuf[1024];
  572. if(!f->busy)
  573. return "stat on unattached fid";
  574. thdr.nstat = dostat(f->user, f->qtype, statbuf, sizeof statbuf);
  575. if(thdr.nstat <= BIT16SZ)
  576. return "stat buffer too small";
  577. thdr.stat = statbuf;
  578. return 0;
  579. }
  580. char *
  581. Wstat(Fid *f)
  582. {
  583. Dir d;
  584. int n;
  585. char buf[1024];
  586. if(!f->busy || f->qtype != Quser)
  587. return "permission denied";
  588. if(rhdr.nstat > sizeof buf)
  589. return "wstat buffer too big";
  590. if(convM2D(rhdr.stat, rhdr.nstat, &d, buf) == 0)
  591. return "bad stat buffer";
  592. n = strlen(d.name);
  593. if(n == 0 || n >= Namelen)
  594. return "bad user name";
  595. if(finduser(d.name))
  596. return "user already exists";
  597. if(!removeuser(f->user))
  598. return "user previously removed";
  599. free(f->user->name);
  600. f->user->name = strdup(d.name);
  601. if(f->user->name == nil)
  602. error("wstat: malloc failed: %r");
  603. insertuser(f->user);
  604. writeusers();
  605. return 0;
  606. }
  607. Qid
  608. mkqid(User *u, uint32_t qtype)
  609. {
  610. Qid q;
  611. q.vers = 0;
  612. q.path = qtype;
  613. if(u)
  614. q.path |= u->uniq * 0x100;
  615. if(qtype == Quser || qtype == Qroot)
  616. q.type = QTDIR;
  617. else
  618. q.type = QTFILE;
  619. return q;
  620. }
  621. int
  622. dostat(User *user, uint32_t qtype, void *p, int n)
  623. {
  624. Dir d;
  625. if(qtype == Quser)
  626. d.name = user->name;
  627. else
  628. d.name = qinfo[qtype];
  629. d.uid = d.gid = d.muid = "auth";
  630. d.qid = mkqid(user, qtype);
  631. if(d.qid.type & QTDIR)
  632. d.mode = 0777|DMDIR;
  633. else
  634. d.mode = 0666;
  635. d.atime = d.mtime = time(0);
  636. d.length = 0;
  637. return convD2M(&d, p, n);
  638. }
  639. int
  640. passline(Biobuf *b, void *vbuf)
  641. {
  642. char *buf = vbuf;
  643. if(Bread(b, buf, KEYDBLEN) != KEYDBLEN)
  644. return 0;
  645. decrypt(authkey, buf, KEYDBLEN);
  646. buf[Namelen-1] = '\0';
  647. return 1;
  648. }
  649. void
  650. randombytes(uint8_t *p, int len)
  651. {
  652. int i, fd;
  653. fd = open("/dev/random", OREAD);
  654. if(fd < 0){
  655. fprint(2, "keyfs: can't open /dev/random, using rand()\n");
  656. srand(time(0));
  657. for(i = 0; i < len; i++)
  658. p[i] = rand();
  659. return;
  660. }
  661. read(fd, p, len);
  662. close(fd);
  663. }
  664. void
  665. oldCBCencrypt(char *key7, uint8_t *p, int len)
  666. {
  667. uint8_t ivec[8];
  668. uint8_t key[8];
  669. DESstate s;
  670. memset(ivec, 0, 8);
  671. des56to64((uint8_t*)key7, key);
  672. setupDESstate(&s, key, ivec);
  673. desCBCencrypt((uint8_t*)p, len, &s);
  674. }
  675. void
  676. oldCBCdecrypt(char *key7, uint8_t *p, int len)
  677. {
  678. uint8_t ivec[8];
  679. uint8_t key[8];
  680. DESstate s;
  681. memset(ivec, 0, 8);
  682. des56to64((uint8_t*)key7, key);
  683. setupDESstate(&s, key, ivec);
  684. desCBCdecrypt((uint8_t*)p, len, &s);
  685. }
  686. void
  687. writeusers(void)
  688. {
  689. int fd, i, nu;
  690. User *u;
  691. uint8_t *p, *buf;
  692. uint32_t expire;
  693. /* count users */
  694. nu = 0;
  695. for(i = 0; i < Nuser; i++)
  696. for(u = users[i]; u; u = u->link)
  697. nu++;
  698. /* pack into buffer */
  699. buf = malloc(KEYDBOFF + nu*KEYDBLEN);
  700. if(buf == 0){
  701. fprint(2, "keyfs: can't write keys file, out of memory\n");
  702. return;
  703. }
  704. p = buf;
  705. randombytes(p, KEYDBOFF);
  706. p += KEYDBOFF;
  707. for(i = 0; i < Nuser; i++)
  708. for(u = users[i]; u; u = u->link){
  709. strncpy((char*)p, u->name, Namelen);
  710. p += Namelen;
  711. memmove(p, u->key, DESKEYLEN);
  712. p += DESKEYLEN;
  713. *p++ = u->status;
  714. *p++ = u->warnings;
  715. expire = u->expire;
  716. *p++ = expire;
  717. *p++ = expire >> 8;
  718. *p++ = expire >> 16;
  719. *p++ = expire >> 24;
  720. memmove(p, u->secret, SECRETLEN);
  721. p += SECRETLEN;
  722. }
  723. /* encrypt */
  724. oldCBCencrypt(authkey, buf, p - buf);
  725. /* write file */
  726. fd = create(userkeys, OWRITE, 0660);
  727. if(fd < 0){
  728. free(buf);
  729. fprint(2, "keyfs: can't write keys file\n");
  730. return;
  731. }
  732. if(write(fd, buf, p - buf) != (p - buf))
  733. fprint(2, "keyfs: can't write keys file\n");
  734. free(buf);
  735. close(fd);
  736. }
  737. int
  738. weirdfmt(Fmt *f)
  739. {
  740. char *s, *p, *ep, buf[ANAMELEN*4 + 1];
  741. int i, n;
  742. Rune r;
  743. s = va_arg(f->args, char*);
  744. p = buf;
  745. ep = buf + sizeof buf;
  746. for(i = 0; i < ANAMELEN; i += n){
  747. n = chartorune(&r, s + i);
  748. if(r == Runeerror)
  749. p = seprint(p, ep, "[%.2x]", buf[i]);
  750. else if(isascii(r) && iscntrl(r))
  751. p = seprint(p, ep, "[%.2x]", r);
  752. else if(r == ' ' || r == '/')
  753. p = seprint(p, ep, "[%c]", r);
  754. else
  755. p = seprint(p, ep, "%C", r);
  756. }
  757. return fmtstrcpy(f, buf);
  758. }
  759. int
  760. userok(char *user, int nu)
  761. {
  762. int i, n, rv;
  763. Rune r;
  764. char buf[ANAMELEN+1];
  765. memset(buf, 0, sizeof buf);
  766. memmove(buf, user, ANAMELEN);
  767. if(buf[ANAMELEN-1] != 0){
  768. fprint(2, "keyfs: %d: no termination: %W\n", nu, buf);
  769. return -1;
  770. }
  771. rv = 0;
  772. for(i = 0; buf[i]; i += n){
  773. n = chartorune(&r, buf+i);
  774. if(r == Runeerror){
  775. // fprint(2, "keyfs: name %W bad rune byte %d\n", buf, i);
  776. rv = -1;
  777. } else if(isascii(r) && iscntrl(r) || r == ' ' || r == '/'){
  778. // fprint(2, "keyfs: name %W bad char %C\n", buf, r);
  779. rv = -1;
  780. }
  781. }
  782. if(i == 0){
  783. fprint(2, "keyfs: %d: nil name\n", nu);
  784. return -1;
  785. }
  786. if(rv == -1)
  787. fprint(2, "keyfs: %d: bad syntax: %W\n", nu, buf);
  788. return rv;
  789. }
  790. int
  791. readusers(void)
  792. {
  793. int fd, i, n, nu;
  794. uint8_t *p, *buf, *ep;
  795. User *u;
  796. Dir *d;
  797. /* read file into an array */
  798. fd = open(userkeys, OREAD);
  799. if(fd < 0)
  800. return 0;
  801. d = dirfstat(fd);
  802. if(d == nil){
  803. close(fd);
  804. return 0;
  805. }
  806. buf = malloc(d->length);
  807. if(buf == 0){
  808. close(fd);
  809. free(d);
  810. return 0;
  811. }
  812. n = readn(fd, buf, d->length);
  813. close(fd);
  814. free(d);
  815. if(n != d->length){
  816. free(buf);
  817. return 0;
  818. }
  819. /* decrypt */
  820. n -= n % KEYDBLEN;
  821. oldCBCdecrypt(authkey, buf, n);
  822. /* unpack */
  823. nu = 0;
  824. for(i = KEYDBOFF; i < n; i += KEYDBLEN){
  825. ep = buf + i;
  826. if(userok((char*)ep, i/KEYDBLEN) < 0)
  827. continue;
  828. u = finduser((char*)ep);
  829. if(u == 0)
  830. u = installuser((char*)ep);
  831. memmove(u->key, ep + Namelen, DESKEYLEN);
  832. p = ep + Namelen + DESKEYLEN;
  833. u->status = *p++;
  834. u->warnings = *p++;
  835. if(u->status >= Smax)
  836. fprint(2, "keyfs: warning: bad status in key file\n");
  837. u->expire = p[0] + (p[1]<<8) + (p[2]<<16) + (p[3]<<24);
  838. p += 4;
  839. memmove(u->secret, p, SECRETLEN);
  840. u->secret[SECRETLEN-1] = 0;
  841. nu++;
  842. }
  843. free(buf);
  844. print("%d keys read\n", nu);
  845. return 1;
  846. }
  847. User *
  848. installuser(char *name)
  849. {
  850. User *u;
  851. int h;
  852. h = hash(name);
  853. u = emalloc(sizeof *u);
  854. u->name = strdup(name);
  855. if(u->name == nil)
  856. error("malloc failed: %r");
  857. u->removed = 0;
  858. u->ref = 0;
  859. u->purgatory = 0;
  860. u->expire = 0;
  861. u->status = Sok;
  862. u->bad = 0;
  863. u->warnings = 0;
  864. u->uniq = uniq++;
  865. u->link = users[h];
  866. users[h] = u;
  867. return u;
  868. }
  869. User *
  870. finduser(char *name)
  871. {
  872. User *u;
  873. for(u = users[hash(name)]; u; u = u->link)
  874. if(strcmp(name, u->name) == 0)
  875. return u;
  876. return 0;
  877. }
  878. int
  879. removeuser(User *user)
  880. {
  881. User *u, **last;
  882. char *name;
  883. user->removed = 1;
  884. name = user->name;
  885. last = &users[hash(name)];
  886. for(u = *last; u; u = *last){
  887. if(strcmp(name, u->name) == 0){
  888. *last = u->link;
  889. return 1;
  890. }
  891. last = &u->link;
  892. }
  893. return 0;
  894. }
  895. void
  896. insertuser(User *user)
  897. {
  898. int h;
  899. user->removed = 0;
  900. h = hash(user->name);
  901. user->link = users[h];
  902. users[h] = user;
  903. }
  904. uint32_t
  905. hash(char *s)
  906. {
  907. uint32_t h;
  908. h = 0;
  909. while(*s)
  910. h = (h << 1) ^ *s++;
  911. return h % Nuser;
  912. }
  913. Fid *
  914. findfid(int fid)
  915. {
  916. Fid *f, *ff;
  917. ff = 0;
  918. for(f = fids; f; f = f->next)
  919. if(f->fid == fid)
  920. return f;
  921. else if(!ff && !f->busy)
  922. ff = f;
  923. if(ff){
  924. ff->fid = fid;
  925. return ff;
  926. }
  927. f = emalloc(sizeof *f);
  928. f->fid = fid;
  929. f->busy = 0;
  930. f->user = 0;
  931. f->next = fids;
  932. fids = f;
  933. return f;
  934. }
  935. void
  936. io(int in, int out)
  937. {
  938. char *err;
  939. int n;
  940. int32_t now, lastwarning;
  941. /* after restart, let the system settle for 5 mins before warning */
  942. lastwarning = time(0) - 24*60*60 + 5*60;
  943. for(;;){
  944. n = read9pmsg(in, mdata, messagesize);
  945. if(n == 0)
  946. continue;
  947. if(n < 0)
  948. error("mount read %d", n);
  949. if(convM2S(mdata, n, &rhdr) == 0)
  950. continue;
  951. if(newkeys())
  952. readusers();
  953. thdr.data = (char*)mdata + IOHDRSZ;
  954. thdr.fid = rhdr.fid;
  955. if(!fcalls[rhdr.type])
  956. err = "fcall request";
  957. else
  958. err = (*fcalls[rhdr.type])(findfid(rhdr.fid));
  959. thdr.tag = rhdr.tag;
  960. thdr.type = rhdr.type+1;
  961. if(err){
  962. thdr.type = Rerror;
  963. thdr.ename = err;
  964. }
  965. n = convS2M(&thdr, mdata, messagesize);
  966. if(write(out, mdata, n) != n)
  967. error("mount write");
  968. now = time(0);
  969. if(warnarg && (now - lastwarning > 24*60*60)){
  970. syslog(0, "auth", "keyfs starting warnings: %lux %lux",
  971. now, lastwarning);
  972. warning();
  973. lastwarning = now;
  974. }
  975. }
  976. }
  977. int
  978. newkeys(void)
  979. {
  980. Dir *d;
  981. static int32_t ftime;
  982. d = dirstat(userkeys);
  983. if(d == nil)
  984. return 0;
  985. if(d->mtime > ftime){
  986. ftime = d->mtime;
  987. free(d);
  988. return 1;
  989. }
  990. free(d);
  991. return 0;
  992. }
  993. void *
  994. emalloc(uint32_t n)
  995. {
  996. void *p;
  997. if(p = malloc(n))
  998. return p;
  999. error("out of memory");
  1000. return 0; /* not reached */
  1001. }
  1002. void
  1003. warning(void)
  1004. {
  1005. int i;
  1006. char buf[64];
  1007. snprint(buf, sizeof buf, "-%s", warnarg);
  1008. switch(rfork(RFPROC|RFNAMEG|RFNOTEG|RFNOWAIT|RFENVG|RFFDG)){
  1009. case 0:
  1010. i = open("/sys/log/auth", OWRITE);
  1011. if(i >= 0){
  1012. dup(i, 2);
  1013. seek(2, 0, 2);
  1014. close(i);
  1015. }
  1016. execl("/bin/auth/warning", "warning", warnarg, nil);
  1017. error("can't exec warning");
  1018. }
  1019. }