misc.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  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 "ratfs.h"
  10. #include <ip.h>
  11. enum {
  12. Maxdoms = 10, /* max domains in a path */
  13. Timeout = 2*60*60, /* seconds until temporarily trusted addr times out */
  14. };
  15. static int accountmatch(char*, char**, int, char*);
  16. static Node* acctwalk(char*, Node*);
  17. static int dommatch(char*, char*);
  18. static Address* ipsearch(uint32_t, Address*, int);
  19. static Node* ipwalk(char*, Node*);
  20. static Node* trwalk(char*, Node*);
  21. static int usermatch(char*, char*);
  22. /*
  23. * Do a walk
  24. */
  25. char*
  26. walk(char *name, Fid *fidp)
  27. {
  28. Node *np;
  29. if((fidp->node->d.mode & DMDIR) == 0)
  30. return "not a directory";
  31. if(strcmp(name, ".") == 0)
  32. return 0;
  33. if(strcmp(name, "..") == 0){
  34. fidp->node = fidp->node->parent;
  35. fidp->name = 0;
  36. return 0;
  37. }
  38. switch(fidp->node->d.type){
  39. case Directory:
  40. case Addrdir:
  41. np = dirwalk(name, fidp->node);
  42. break;
  43. case Trusted:
  44. np = trwalk(name, fidp->node);
  45. break;
  46. case IPaddr:
  47. np = ipwalk(name, fidp->node);
  48. break;
  49. case Acctaddr:
  50. np = acctwalk(name, fidp->node);
  51. break;
  52. default:
  53. return "directory botch in walk";
  54. }
  55. if(np) {
  56. fidp->node = np;
  57. fidp->name = np->d.name;
  58. return 0;
  59. }
  60. return "file does not exist";
  61. }
  62. /*
  63. * Walk to a subdirectory
  64. */
  65. Node*
  66. dirwalk(char *name, Node *np)
  67. {
  68. Node *p;
  69. for(p = np->children; p; p = p->sibs)
  70. if(strcmp(name, p->d.name) == 0)
  71. break;
  72. return p;
  73. }
  74. /*
  75. * Walk the directory of trusted files
  76. */
  77. static Node*
  78. trwalk(char *name, Node *np)
  79. {
  80. Node *p;
  81. uint32_t peerip;
  82. uint8_t addr[IPv4addrlen];
  83. v4parseip(addr, name);
  84. peerip = nhgetl(addr);
  85. for(p = np->children; p; p = p->sibs)
  86. if((peerip&p->ip.mask) == p->ip.ipaddr)
  87. break;
  88. return p;
  89. }
  90. /*
  91. * Walk a directory of IP addresses
  92. */
  93. static Node*
  94. ipwalk(char *name, Node *np)
  95. {
  96. Address *ap;
  97. uint32_t peerip;
  98. uint8_t addr[IPv4addrlen];
  99. v4parseip(addr, name);
  100. peerip = nhgetl(addr);
  101. if(debugfd >= 0)
  102. fprint(debugfd, "%d.%d.%d.%d - ", addr[0]&0xff, addr[1]&0xff,
  103. addr[2]&0xff, addr[3]&0xff);
  104. ap = ipsearch(peerip, np->addrs, np->count);
  105. if(ap == 0)
  106. return 0;
  107. dummy.d.name = ap->name;
  108. return &dummy;
  109. }
  110. /*
  111. * Walk a directory of account names
  112. */
  113. static Node*
  114. acctwalk(char *name, Node *np)
  115. {
  116. int i, n;
  117. Address *ap;
  118. char *p, *cp, *user;
  119. char buf[512];
  120. char *doms[Maxdoms];
  121. strecpy(buf, buf+sizeof buf, name);
  122. subslash(buf);
  123. p = buf;
  124. for(n = 0; n < Maxdoms; n++) {
  125. cp = strchr(p, '!');
  126. if(cp == 0)
  127. break;
  128. *cp = 0;
  129. doms[n] = p;
  130. p = cp+1;
  131. }
  132. user = p;
  133. for(i = 0; i < np->count; i++){
  134. ap = &np->addrs[i];
  135. if (accountmatch(ap->name, doms, n, user)) {
  136. dummy.d.name = ap->name;
  137. return &dummy;
  138. }
  139. }
  140. return 0;
  141. }
  142. /*
  143. * binary search sorted IP address list
  144. */
  145. static Address*
  146. ipsearch(uint32_t addr, Address *base, int n)
  147. {
  148. uint32_t top, bot, mid;
  149. Address *ap;
  150. bot = 0;
  151. top = n;
  152. for (mid = (bot+top)/2; mid < top; mid = (bot+top)/2) {
  153. ap = &base[mid];
  154. if((addr&ap->ip.mask) == ap->ip.ipaddr)
  155. return ap;
  156. if(addr < ap->ip.ipaddr)
  157. top = mid;
  158. else if(mid != n-1 && addr >= base[mid+1].ip.ipaddr)
  159. bot = mid;
  160. else
  161. break;
  162. }
  163. return 0;
  164. }
  165. /*
  166. * Read a directory
  167. */
  168. int
  169. dread(Fid *fidp, int cnt)
  170. {
  171. uint8_t *q, *eq, *oq;
  172. int n, skip;
  173. Node *np;
  174. if(debugfd >= 0)
  175. fprint(debugfd, "dread %d\n", cnt);
  176. np = fidp->node;
  177. oq = q = rbuf+IOHDRSZ;
  178. eq = q+cnt;
  179. if(fidp->dirindex >= np->count)
  180. return 0;
  181. skip = fidp->dirindex;
  182. for(np = np->children; skip > 0 && np; np = np->sibs)
  183. skip--;
  184. if(np == 0)
  185. return 0;
  186. for(; q < eq && np; np = np->sibs){
  187. if(debugfd >= 0)
  188. printnode(np);
  189. if((n=convD2M(&np->d, q, eq-q)) <= BIT16SZ)
  190. break;
  191. q += n;
  192. fidp->dirindex++;
  193. }
  194. return q - oq;
  195. }
  196. /*
  197. * Read a directory of IP addresses or account names
  198. */
  199. int
  200. hread(Fid *fidp, int cnt)
  201. {
  202. uint8_t *q, *eq, *oq;
  203. int i, n, path;
  204. Address *p;
  205. Node *np;
  206. if(debugfd >= 0)
  207. fprint(debugfd, "hread %d\n", cnt);
  208. np = fidp->node;
  209. oq = q = rbuf+IOHDRSZ;
  210. eq = q+cnt;
  211. if(fidp->dirindex >= np->count)
  212. return 0;
  213. path = np->baseqid;
  214. for(i = fidp->dirindex; q < eq && i < np->count; i++){
  215. p = &np->addrs[i];
  216. dummy.d.name = p->name;
  217. dummy.d.qid.path = path++;
  218. if((n=convD2M(&dummy.d, q, eq-q)) <= BIT16SZ)
  219. break;
  220. q += n;
  221. }
  222. fidp->dirindex = i;
  223. return q - oq;
  224. }
  225. /*
  226. * Find a directory node by type
  227. */
  228. Node*
  229. finddir(int type)
  230. {
  231. Node *np;
  232. for(np = root->children; np; np = np->sibs)
  233. if (np->d.type == type)
  234. return np;
  235. return 0;
  236. }
  237. /*
  238. * Remove temporary pseudo-files that have timed-out
  239. * from the trusted directory
  240. */
  241. void
  242. cleantrusted(void)
  243. {
  244. Node *np, **l;
  245. uint32_t t;
  246. np = finddir(Trusted);
  247. if (np == 0)
  248. return;
  249. t = time(0)-Timeout;
  250. l = &np->children;
  251. for (np = np->children; np; np = *l) {
  252. if(np->d.type == Trustedtemp && t >= np->d.mtime) {
  253. *l = np->sibs;
  254. if(debugfd >= 0)
  255. fprint(debugfd, "Deleting %s\n", np->d.name);
  256. np->parent->count--;
  257. free(np);
  258. } else
  259. l = &np->sibs;
  260. }
  261. }
  262. /*
  263. * match path components to prohibited domain & user specifications. patterns include:
  264. * domain, domain! or domain!* - all users in domain
  265. * *.domain, *.domain! or *.domain!* - all users in domain and its subdomains
  266. * !user or *!user - user in all domains
  267. * domain!user - user in domain
  268. * *.domain!user - user in domain and its subdomains
  269. *
  270. * if "user" has a trailing '*', it matches all user names beginning with "user"
  271. *
  272. * there are special semantics for the "domain, domain! or domain!*" specifications:
  273. * the first two forms match when the domain is anywhere in at list of source-routed
  274. * domains while the latter matches only when the domain is the last hop. the same is
  275. * true for the *.domain!* form of the pattern.
  276. */
  277. static int
  278. accountmatch(char *spec, char **doms, int ndoms, char *user)
  279. {
  280. char *cp, *userp;
  281. int i, ret;
  282. userp = 0;
  283. ret = 0;
  284. cp = strchr(spec, '!');
  285. if(cp){
  286. *cp++ = 0; /* restored below */
  287. if(*cp)
  288. if(strcmp(cp, "*")) /* "!*" is the same as no user field */
  289. userp = cp; /* there is a user name */
  290. }
  291. if(userp == 0){ /* no user field - domain match only */
  292. for(i = 0; i < ndoms && doms[i]; i++)
  293. if(dommatch(doms[i], spec) == 0)
  294. ret = 1;
  295. } else {
  296. /* check for "!user", "*!user" or "domain!user" */
  297. if(usermatch(user, userp) == 0){
  298. if(*spec == 0 || strcmp(spec, "*") == 0)
  299. ret = 1;
  300. else if(ndoms > 0 && dommatch(doms[ndoms-1], spec) == 0)
  301. ret = 1;
  302. }
  303. }
  304. if(cp)
  305. cp[-1] = '!';
  306. return ret;
  307. }
  308. /*
  309. * match a user name. the only meta-char is '*' which matches all
  310. * characters. we only allow it as "*", which matches anything or
  311. * an * at the end of the name (e.g., "username*") which matches
  312. * trailing characters.
  313. */
  314. static int
  315. usermatch(char *pathuser, char *specuser)
  316. {
  317. int n;
  318. n = strlen(specuser)-1;
  319. if(specuser[n] == '*'){
  320. if(n == 0) /* match everything */
  321. return 0;
  322. return strncmp(pathuser, specuser, n);
  323. }
  324. return strcmp(pathuser, specuser);
  325. }
  326. /*
  327. * Match a domain specification
  328. */
  329. static int
  330. dommatch(char *pathdom, char *specdom)
  331. {
  332. int n;
  333. if (*specdom == '*'){
  334. if (specdom[1] == '.' && specdom[2]){
  335. specdom += 2;
  336. n = strlen(pathdom)-strlen(specdom);
  337. if(n == 0 || (n > 0 && pathdom[n-1] == '.'))
  338. return strcmp(pathdom+n, specdom);
  339. return n;
  340. }
  341. }
  342. return strcmp(pathdom, specdom);
  343. }
  344. /*
  345. * Custom allocators to avoid malloc overheads on small objects.
  346. * We never free these. (See below.)
  347. */
  348. typedef struct Stringtab Stringtab;
  349. struct Stringtab {
  350. Stringtab *link;
  351. char *str;
  352. };
  353. static Stringtab*
  354. taballoc(void)
  355. {
  356. static Stringtab *t;
  357. static uint nt;
  358. if(nt == 0){
  359. t = malloc(64*sizeof(Stringtab));
  360. if(t == 0)
  361. fatal("out of memory");
  362. nt = 64;
  363. }
  364. nt--;
  365. return t++;
  366. }
  367. static char*
  368. xstrdup(char *s)
  369. {
  370. char *r;
  371. int len;
  372. static char *t;
  373. static int nt;
  374. len = strlen(s)+1;
  375. if(len >= 8192)
  376. fatal("strdup big string");
  377. if(nt < len){
  378. t = malloc(8192);
  379. if(t == 0)
  380. fatal("out of memory");
  381. nt = 8192;
  382. }
  383. r = t;
  384. t += len;
  385. nt -= len;
  386. strcpy(r, s);
  387. return r;
  388. }
  389. /*
  390. * Return a uniquely allocated copy of a string.
  391. * Don't free these -- they stay in the table for the
  392. * next caller who wants that particular string.
  393. * String comparison can be done with pointer comparison
  394. * if you know both strings are atoms.
  395. */
  396. static Stringtab *stab[1024];
  397. static uint
  398. hash(char *s)
  399. {
  400. uint h;
  401. uint8_t *p;
  402. h = 0;
  403. for(p=(uint8_t*)s; *p; p++)
  404. h = h*37 + *p;
  405. return h;
  406. }
  407. char*
  408. atom(char *str)
  409. {
  410. uint h;
  411. Stringtab *tab;
  412. h = hash(str) % nelem(stab);
  413. for(tab=stab[h]; tab; tab=tab->link)
  414. if(strcmp(str, tab->str) == 0)
  415. return tab->str;
  416. tab = taballoc();
  417. tab->str = xstrdup(str);
  418. tab->link = stab[h];
  419. stab[h] = tab;
  420. return tab->str;
  421. }