import.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  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 <u.h>
  10. #include <libc.h>
  11. #include <auth.h>
  12. #include <mp.h>
  13. #include <libsec.h>
  14. enum {
  15. Encnone,
  16. Encssl,
  17. Enctls,
  18. };
  19. static char *encprotos[] = {
  20. [Encnone] = "clear",
  21. [Encssl] = "ssl",
  22. [Enctls] = "tls",
  23. nil,
  24. };
  25. char *keyspec = "";
  26. char *filterp;
  27. char *ealgs = "rc4_256 sha1";
  28. int encproto = Encnone;
  29. char *aan = "/bin/aan";
  30. AuthInfo *ai;
  31. int debug;
  32. int doauth = 1;
  33. int timedout;
  34. int connect(char*, char*, int);
  35. int passive(void);
  36. int old9p(int);
  37. void catcher(void *c, char*);
  38. void sysfatal(char*, ...);
  39. void usage(void);
  40. int filter(int, char *, char *);
  41. static void mksecret(char *, uint8_t *);
  42. /*
  43. * based on libthread's threadsetname, but drags in less library code.
  44. * actually just sets the arguments displayed.
  45. */
  46. void
  47. procsetname(char *fmt, ...)
  48. {
  49. int fd;
  50. char *cmdname;
  51. char buf[128];
  52. va_list arg;
  53. va_start(arg, fmt);
  54. cmdname = vsmprint(fmt, arg);
  55. va_end(arg);
  56. if (cmdname == nil)
  57. return;
  58. snprint(buf, sizeof buf, "#p/%d/args", getpid());
  59. if((fd = open(buf, OWRITE)) >= 0){
  60. write(fd, cmdname, strlen(cmdname)+1);
  61. close(fd);
  62. }
  63. free(cmdname);
  64. }
  65. void
  66. post(char *name, char *envname, int srvfd)
  67. {
  68. int fd;
  69. char buf[32];
  70. fd = create(name, OWRITE, 0600);
  71. if(fd < 0)
  72. return;
  73. sprint(buf, "%d",srvfd);
  74. if(write(fd, buf, strlen(buf)) != strlen(buf))
  75. sysfatal("srv write: %r");
  76. close(fd);
  77. putenv(envname, name);
  78. }
  79. static int
  80. lookup(char *s, char *l[])
  81. {
  82. int i;
  83. for (i = 0; l[i] != 0; i++)
  84. if (strcmp(l[i], s) == 0)
  85. return i;
  86. return -1;
  87. }
  88. void
  89. main(int argc, char **argv)
  90. {
  91. char *mntpt, *srvpost, srvfile[64];
  92. int backwards = 0, fd, mntflags, oldserver, notree;
  93. quotefmtinstall();
  94. srvpost = nil;
  95. oldserver = 0;
  96. notree = 0;
  97. mntflags = MREPL;
  98. ARGBEGIN{
  99. case 'A':
  100. doauth = 0;
  101. break;
  102. case 'a':
  103. mntflags = MAFTER;
  104. break;
  105. case 'b':
  106. mntflags = MBEFORE;
  107. break;
  108. case 'c':
  109. mntflags |= MCREATE;
  110. break;
  111. case 'C':
  112. mntflags |= MCACHE;
  113. break;
  114. case 'd':
  115. debug++;
  116. break;
  117. case 'f':
  118. /* ignored but allowed for compatibility */
  119. break;
  120. case 'O':
  121. case 'o':
  122. oldserver = 1;
  123. break;
  124. case 'E':
  125. if ((encproto = lookup(EARGF(usage()), encprotos)) < 0)
  126. usage();
  127. break;
  128. case 'e':
  129. ealgs = EARGF(usage());
  130. if(*ealgs == 0 || strcmp(ealgs, "clear") == 0)
  131. ealgs = nil;
  132. break;
  133. case 'k':
  134. keyspec = EARGF(usage());
  135. break;
  136. case 'p':
  137. filterp = aan;
  138. break;
  139. case 's':
  140. srvpost = EARGF(usage());
  141. break;
  142. case 'B':
  143. backwards = 1;
  144. break;
  145. case 'm':
  146. notree = 1;
  147. break;
  148. default:
  149. usage();
  150. }ARGEND;
  151. mntpt = 0; /* to shut up compiler */
  152. if(backwards){
  153. switch(argc) {
  154. default:
  155. mntpt = argv[0];
  156. break;
  157. case 0:
  158. usage();
  159. }
  160. } else {
  161. switch(argc) {
  162. case 2:
  163. mntpt = argv[1];
  164. break;
  165. case 3:
  166. if(notree)
  167. usage();
  168. mntpt = argv[2];
  169. break;
  170. default:
  171. usage();
  172. }
  173. }
  174. if (encproto == Enctls)
  175. sysfatal("%s: tls has not yet been implemented", argv[0]);
  176. notify(catcher);
  177. alarm(60*1000);
  178. if(backwards)
  179. fd = passive();
  180. else if(notree)
  181. fd = connect(argv[0], nil, oldserver);
  182. else
  183. fd = connect(argv[0], argv[1], oldserver);
  184. if (!oldserver)
  185. fprint(fd, "impo %s %s\n", filterp? "aan": "nofilter",
  186. encprotos[encproto]);
  187. if (encproto != Encnone && ealgs && ai) {
  188. unsigned char key[16];
  189. unsigned char digest[SHA1dlen];
  190. char fromclientsecret[21];
  191. char fromserversecret[21];
  192. int i;
  193. memmove(key+4, ai->secret, ai->nsecret);
  194. /* exchange random numbers */
  195. srand(truerand());
  196. for(i = 0; i < 4; i++)
  197. key[i] = rand();
  198. if(write(fd, key, 4) != 4)
  199. sysfatal("can't write key part: %r");
  200. if(readn(fd, key+12, 4) != 4)
  201. sysfatal("can't read key part: %r");
  202. /* scramble into two secrets */
  203. sha1(key, sizeof(key), digest, nil);
  204. mksecret(fromclientsecret, digest);
  205. mksecret(fromserversecret, digest+10);
  206. if (filterp)
  207. fd = filter(fd, filterp, argv[0]);
  208. /* set up encryption */
  209. procsetname("pushssl");
  210. fd = pushssl(fd, ealgs, fromclientsecret, fromserversecret, nil);
  211. if(fd < 0)
  212. sysfatal("can't establish ssl connection: %r");
  213. }
  214. else if (filterp)
  215. fd = filter(fd, filterp, argv[0]);
  216. if(srvpost){
  217. sprint(srvfile, "/srv/%s", srvpost);
  218. remove(srvfile);
  219. post(srvfile, srvpost, fd);
  220. }
  221. procsetname("mount on %s", mntpt);
  222. if(mount(fd, -1, mntpt, mntflags, "", 'M') < 0)
  223. sysfatal("can't mount %s: %r", argv[1]);
  224. alarm(0);
  225. if(backwards && argc > 1){
  226. exec(argv[1], &argv[1]);
  227. sysfatal("exec: %r");
  228. }
  229. exits(0);
  230. }
  231. void
  232. catcher(void *v, char *msg)
  233. {
  234. timedout = 1;
  235. if(strcmp(msg, "alarm") == 0)
  236. noted(NCONT);
  237. noted(NDFLT);
  238. }
  239. int
  240. old9p(int fd)
  241. {
  242. int p[2];
  243. procsetname("old9p");
  244. if(pipe(p) < 0)
  245. sysfatal("pipe: %r");
  246. switch(rfork(RFPROC|RFFDG|RFNAMEG)) {
  247. case -1:
  248. sysfatal("rfork srvold9p: %r");
  249. case 0:
  250. if(fd != 1){
  251. dup(fd, 1);
  252. close(fd);
  253. }
  254. if(p[0] != 0){
  255. dup(p[0], 0);
  256. close(p[0]);
  257. }
  258. close(p[1]);
  259. if(0){
  260. fd = open("/sys/log/cpu", OWRITE);
  261. if(fd != 2){
  262. dup(fd, 2);
  263. close(fd);
  264. }
  265. execl("/bin/srvold9p", "srvold9p", "-ds", nil);
  266. } else
  267. execl("/bin/srvold9p", "srvold9p", "-s", nil);
  268. sysfatal("exec srvold9p: %r");
  269. default:
  270. close(fd);
  271. close(p[0]);
  272. }
  273. return p[1];
  274. }
  275. int
  276. connect(char *system, char *tree, int oldserver)
  277. {
  278. char buf[ERRMAX], dir[128], *na;
  279. int fd, n;
  280. char *authp;
  281. na = netmkaddr(system, 0, "exportfs");
  282. procsetname("dial %s", na);
  283. if((fd = dial(na, 0, dir, 0)) < 0)
  284. sysfatal("can't dial %s: %r", system);
  285. if(doauth){
  286. if(oldserver)
  287. authp = "p9sk2";
  288. else
  289. authp = "p9any";
  290. procsetname("auth_proxy auth_getkey proto=%q role=client %s",
  291. authp, keyspec);
  292. ai = auth_proxy(fd, auth_getkey, "proto=%q role=client %s",
  293. authp, keyspec);
  294. if(ai == nil)
  295. sysfatal("%r: %s", system);
  296. }
  297. if(tree != nil){
  298. procsetname("writing tree name %s", tree);
  299. n = write(fd, tree, strlen(tree));
  300. if(n < 0)
  301. sysfatal("can't write tree: %r");
  302. strcpy(buf, "can't read tree");
  303. procsetname("awaiting OK for %s", tree);
  304. n = read(fd, buf, sizeof buf - 1);
  305. if(n!=2 || buf[0]!='O' || buf[1]!='K'){
  306. if (timedout)
  307. sysfatal("timed out connecting to %s", na);
  308. buf[sizeof buf - 1] = '\0';
  309. sysfatal("bad remote tree: %s", buf);
  310. }
  311. }
  312. if(oldserver)
  313. return old9p(fd);
  314. return fd;
  315. }
  316. int
  317. passive(void)
  318. {
  319. int fd;
  320. /*
  321. * Ignore doauth==0 on purpose. Is it useful here?
  322. */
  323. procsetname("auth_proxy auth_getkey proto=p9any role=server");
  324. ai = auth_proxy(0, auth_getkey, "proto=p9any role=server");
  325. if(ai == nil)
  326. sysfatal("auth_proxy: %r");
  327. if(auth_chuid(ai, nil) < 0)
  328. sysfatal("auth_chuid: %r");
  329. putenv("service", "import");
  330. fd = dup(0, -1);
  331. close(0);
  332. open("/dev/null", ORDWR);
  333. close(1);
  334. open("/dev/null", ORDWR);
  335. return fd;
  336. }
  337. void
  338. usage(void)
  339. {
  340. fprint(2, "usage: import [-abcCm] [-A] [-E clear|ssl|tls] "
  341. "[-e 'crypt auth'|clear] [-k keypattern] [-p] host remotefs [mountpoint]\n");
  342. exits("usage");
  343. }
  344. /* Network on fd1, mount driver on fd0 */
  345. int
  346. filter(int fd, char *cmd, char *host)
  347. {
  348. int p[2], len, argc;
  349. char newport[256], buf[256], *s;
  350. char *argv[16], *file, *pbuf;
  351. if ((len = read(fd, newport, sizeof newport - 1)) < 0)
  352. sysfatal("filter: cannot write port; %r");
  353. newport[len] = '\0';
  354. if ((s = strchr(newport, '!')) == nil)
  355. sysfatal("filter: illegally formatted port %s", newport);
  356. strecpy(buf, buf+sizeof buf, netmkaddr(host, "tcp", "0"));
  357. pbuf = strrchr(buf, '!');
  358. strecpy(pbuf, buf+sizeof buf, s);
  359. if(debug)
  360. fprint(2, "filter: remote port %s\n", newport);
  361. argc = tokenize(cmd, argv, nelem(argv)-2);
  362. if (argc == 0)
  363. sysfatal("filter: empty command");
  364. argv[argc++] = "-c";
  365. argv[argc++] = buf;
  366. argv[argc] = nil;
  367. file = argv[0];
  368. if ((s = strrchr(argv[0], '/')) != nil)
  369. argv[0] = s+1;
  370. if(pipe(p) < 0)
  371. sysfatal("pipe: %r");
  372. switch(rfork(RFNOWAIT|RFPROC|RFFDG)) {
  373. case -1:
  374. sysfatal("rfork record module: %r");
  375. case 0:
  376. dup(p[0], 1);
  377. dup(p[0], 0);
  378. close(p[0]);
  379. close(p[1]);
  380. exec(file, argv);
  381. sysfatal("exec record module: %r");
  382. default:
  383. close(fd);
  384. close(p[0]);
  385. }
  386. return p[1];
  387. }
  388. static void
  389. mksecret(char *t, uint8_t *f)
  390. {
  391. sprint(t, "%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x",
  392. f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7], f[8], f[9]);
  393. }