#include <u.h> #include <libc.h> #include <auth.h> #include <thread.h> enum { Encnone, Encssl, Enctls, }; static char *encprotos[] = { [Encnone] = "clear", [Encssl] = "ssl", [Enctls] = "tls", nil, }; char *keyspec = ""; char *filterp; char *ealgs = "rc4_256 sha1"; int encproto = Encnone; AuthInfo *ai; int debug; int doauth = 1; int timedout; int connectez(char*, char*); void sysfatal(char*, ...); void usage(void); int filter(int, char *, char *); int catcher(void *v, char *msg) { timedout = 1; if(strcmp(msg, "alarm") == 0) return 1; return 0; } static int lookup(char *s, char *l[]) { int i; for (i = 0; l[i] != 0; i++) if (strcmp(l[i], s) == 0) return i; return -1; } static char* srvname(char *addr) { int i; for(i=0; i<strlen(addr); i++){ if(addr[i] == '!') addr[i] = ':'; } return addr; } void threadmain(int argc, char **argv) { char *mntpt, *srvpost, srvfile[64]; int fd; quotefmtinstall(); srvpost = nil; ARGBEGIN{ case 'A': doauth = 0; break; case 'd': debug++; break; case 'E': if ((encproto = lookup(EARGF(usage()), encprotos)) < 0) usage(); break; case 'e': ealgs = EARGF(usage()); if(*ealgs == 0 || strcmp(ealgs, "clear") == 0) ealgs = nil; break; case 'k': keyspec = EARGF(usage()); break; case 'p': filterp = unsharp("#9/bin/aan"); break; case 's': srvpost = EARGF(usage()); break; default: usage(); }ARGEND; mntpt = 0; /* to shut up compiler */ switch(argc) { case 2: mntpt = argv[1]; break; case 3: mntpt = argv[2]; break; default: usage(); } if(encproto != Encnone) sysfatal("%s: tls and ssl have not yet been implemented", argv[0]); threadnotify(catcher, 1); alarm(60*1000); fd = connectez(argv[0], argv[1]); fprint(fd, "impo %s %s\n", filterp? "aan": "nofilter", encprotos[encproto]); if (filterp) fd = filter(fd, filterp, argv[0]); if(srvpost == nil) srvpost = srvname(argv[0]); sprint(srvfile, "%s", srvpost); if(post9pservice(fd, srvfile, mntpt) < 0) sysfatal("can't post %s: %r", argv[1]); alarm(0); threadexitsall(0); } /* the name "connect" is special */ int connectez(char *system, char *tree) { char buf[ERRMAX], *na; int fd, n; char *authp; na = netmkaddr(system, "tcp", "exportfs"); threadsetname("dial %s", na); if((fd = dial(na, nil, nil, nil)) < 0) sysfatal("can't dial %s: %r", system); if(doauth){ authp = "p9any"; threadsetname("auth_proxy auth_getkey proto=%q role=client %s", authp, keyspec); ai = auth_proxy(fd, auth_getkey, "proto=%q role=client %s", authp, keyspec); if(ai == nil) sysfatal("%r: %s", system); } threadsetname("writing tree name %s", tree); n = write(fd, tree, strlen(tree)); if(n < 0) sysfatal("can't write tree: %r"); strcpy(buf, "can't read tree"); threadsetname("awaiting OK for %s", tree); n = read(fd, buf, sizeof buf - 1); if(n!=2 || buf[0]!='O' || buf[1]!='K'){ if (timedout) sysfatal("timed out connecting to %s", na); buf[sizeof buf - 1] = '\0'; sysfatal("bad remote tree: %s", buf); } return fd; } void usage(void) { fprint(2, "usage: 9import [-A] [-E clear|ssl|tls] " "[-e 'crypt auth'|clear] [-k keypattern] [-p] [-s srv] host remotefs [mountpoint]\n"); threadexitsall("usage"); } /* Network on fd1, mount driver on fd0 */ int filter(int fd, char *cmd, char *host) { int p[2], len, argc; char newport[256], buf[256], *s; char *argv[16], *file, *pbuf; if ((len = read(fd, newport, sizeof newport - 1)) < 0) sysfatal("filter: cannot write port; %r"); newport[len] = '\0'; if ((s = strchr(newport, '!')) == nil) sysfatal("filter: illegally formatted port %s", newport); strecpy(buf, buf+sizeof buf, netmkaddr(host, "tcp", "0")); pbuf = strrchr(buf, '!'); strecpy(pbuf, buf+sizeof buf, s); if(debug) fprint(2, "filter: remote port %s\n", newport); argc = tokenize(cmd, argv, nelem(argv)-2); if (argc == 0) sysfatal("filter: empty command"); argv[argc++] = "-c"; argv[argc++] = buf; argv[argc] = nil; file = argv[0]; if (s = strrchr(argv[0], '/')) argv[0] = s+1; if(pipe(p) < 0) sysfatal("pipe: %r"); switch(rfork(RFNOWAIT|RFPROC|RFFDG)) { case -1: sysfatal("rfork record module: %r"); case 0: dup(p[0], 1); dup(p[0], 0); close(p[0]); close(p[1]); exec(file, argv); sysfatal("exec record module: %r"); default: close(fd); close(p[0]); } return p[1]; }