keyfs.c 19 KB

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