]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/cmd/cpu.c
fix fuckup
[plan9front.git] / sys / src / cmd / cpu.c
index 0d256c4078fd325a7549c59732ab8b35e28633c4..1994aaf282be381d4ff6823d1fcad69fa986d976 100644 (file)
@@ -7,7 +7,6 @@
 
 #include <u.h>
 #include <libc.h>
-#include <bio.h>
 #include <auth.h>
 #include <fcall.h>
 #include <libsec.h>
@@ -15,8 +14,8 @@
 #define        Maxfdata 8192
 #define MaxStr 128
 
-void   remoteside(int);
-void   fatal(int, char*, ...);
+void   remoteside(void);
+void   fatal(char*, ...);
 void   lclnoteproc(int);
 void   rmtnoteproc(void);
 void   catcher(void*, char*);
@@ -25,12 +24,13 @@ void        writestr(int, char*, char*, int);
 int    readstr(int, char*, int);
 char   *rexcall(int*, char*, char*);
 int    setamalg(char*);
-char *keyspec = "";
+char   *keyspec = "";
 
 int    notechan;
 int    exportpid;
 char   *system;
 int    cflag;
+int    nflag;
 int    dbg;
 char   *user;
 char   *patternfile;
@@ -43,6 +43,11 @@ char *ealgs = "rc4_256 sha1";
 /* message size for exportfs; may be larger so we can do big graphics in CPU window */
 int    msgsize = Maxfdata+IOHDRSZ;
 
+/* encryption mechanisms */
+static int     clear(int);
+
+int (*encryption)(int) = clear;
+
 /* authentication mechanisms */
 static int     netkeyauth(int);
 static int     netkeysrvauth(int, char*);
@@ -56,23 +61,26 @@ struct AuthMethod {
        char    *name;                  /* name of method */
        int     (*cf)(int);             /* client side authentication */
        int     (*sf)(int, char*);      /* server side authentication */
-} authmethod[] =
-{
+} authmethod[] = {
        { "p9",         p9auth,         srvp9auth,},
        { "netkey",     netkeyauth,     netkeysrvauth,},
-//     { "none",       noauth,         srvnoauth,},
+       { "none",       noauth,         srvnoauth,},
        { nil,  nil}
 };
 AuthMethod *am = authmethod;   /* default is p9 */
 
-char *p9authproto = "p9any";
-
 int setam(char*);
 
+char   *aan = "/bin/aan";
+char   *anstring = "tcp!*!0";
+char   *filterp = nil;
+
+int filter(int fd, char *host);
+
 void
 usage(void)
 {
-       fprint(2, "usage: cpu [-h system] [-u user] [-a authmethod] "
+       fprint(2, "usage: cpu [-p] [-h system] [-u user] [-a authmethod] "
                "[-e 'crypt hash'] [-k keypattern] [-P patternfile] "
                "[-c cmd arg ...]\n");
        exits("usage");
@@ -136,7 +144,7 @@ procsetname(char *fmt, ...)
 void
 main(int argc, char **argv)
 {
-       char dat[MaxStr], buf[MaxStr], cmd[MaxStr], *p, *err;
+       char dat[MaxStr], buf[MaxStr], cmd[MaxStr], *p, *s, *err;
        int ac, fd, ms, data;
        char *av[10];
 
@@ -153,12 +161,12 @@ main(int argc, char **argv)
 
        user = getuser();
        if(user == nil)
-               fatal(1, "can't read user name");
+               fatal("can't read user name: %r");
        ARGBEGIN{
        case 'a':
                p = EARGF(usage());
                if(setam(p) < 0)
-                       fatal(0, "unknown auth method %s", p);
+                       fatal("unknown auth method %s", p);
                break;
        case 'e':
                ealgs = EARGF(usage());
@@ -171,24 +179,26 @@ main(int argc, char **argv)
        case 'f':
                /* ignored but accepted for compatibility */
                break;
-       case 'O':
-               p9authproto = "p9sk2";
-               remoteside(1);                          /* From listen */
+       case 'n':
+               /* must be specified before -R/-O */
+               nflag++;
+               break;
+       case 'A':
+               anstring = EARGF(usage());
                break;
        case 'R':                               /* From listen */
-               remoteside(0);
+               remoteside();
                break;
        case 'h':
                system = EARGF(usage());
                break;
        case 'c':
                cflag++;
-               cmd[0] = '!';
-               cmd[1] = '\0';
-               while(p = ARGF()) {
-                       strcat(cmd, " ");
-                       strcat(cmd, p);
-               }
+               s = cmd;
+               *s++ = '!';
+               *s = 0;
+               while(p = ARGF())
+                       s = seprint(s, cmd+sizeof(cmd), " %s", p);
                break;
        case 'k':
                keyspec = smprint("%s %s", keyspec, EARGF(usage()));
@@ -200,6 +210,9 @@ main(int argc, char **argv)
                user = EARGF(usage());
                keyspec = smprint("%s user=%s", keyspec, user);
                break;
+       case 'p':
+               filterp = aan;
+               break;
        default:
                usage();
        }ARGEND;
@@ -211,12 +224,12 @@ main(int argc, char **argv)
        if(system == nil) {
                p = getenv("cpu");
                if(p == 0)
-                       fatal(0, "set $cpu");
+                       fatal("set $cpu");
                system = p;
        }
 
        if(err = rexcall(&data, system, srvname))
-               fatal(1, "%s: %s", err, system);
+               fatal("%s: %s: %r", err, system);
 
        procsetname("%s", origargs);
        /* Tell the remote side the command to execute and where our working directory is */
@@ -235,7 +248,7 @@ main(int argc, char **argv)
         *  of /mnt/term
         */
        if(readstr(data, buf, sizeof(buf)) < 0)
-               fatal(1, "waiting for FS: %r");
+               fatal("waiting for FS: %r");
        if(strncmp("FS", buf, 2) != 0) {
                print("remote cpu: %s", buf);
                exits(buf);
@@ -259,77 +272,30 @@ main(int argc, char **argv)
        }
        av[ac] = nil;
        exec(exportfs, av);
-       fatal(1, "starting exportfs");
+       fatal("starting exportfs: %r");
 }
 
 void
-fatal(int syserr, char *fmt, ...)
+fatal(char *fmt, ...)
 {
-       Fmt f;
-       char *str;
+       char buf[1024];
        va_list arg;
 
-       fmtstrinit(&f);
-       fmtprint(&f, "cpu: ");
        va_start(arg, fmt);
-       fmtvprint(&f, fmt, arg);
+       vsnprint(buf, sizeof(buf), fmt, arg);
        va_end(arg);
-       if(syserr)
-               fmtprint(&f, ": %r");
-       str = fmtstrflush(&f);
-
-       fprint(2, "%s\n", str);
-       syslog(0, "cpu", str);
-       exits(str);
+       fprint(2, "cpu: %s\n", buf);
+       syslog(0, "cpu", "%s", buf);
+       exits(buf);
 }
 
 char *negstr = "negotiating authentication method";
 
-char bug[256];
-
-int
-old9p(int fd)
-{
-       int p[2];
-
-       if(pipe(p) < 0)
-               fatal(1, "pipe");
-
-       switch(rfork(RFPROC|RFFDG|RFNAMEG)) {
-       case -1:
-               fatal(1, "rfork srvold9p");
-       case 0:
-               if(fd != 1){
-                       dup(fd, 1);
-                       close(fd);
-               }
-               if(p[0] != 0){
-                       dup(p[0], 0);
-                       close(p[0]);
-               }
-               close(p[1]);
-               if(0){
-                       fd = open("/sys/log/cpu", OWRITE);
-                       if(fd != 2){
-                               dup(fd, 2);
-                               close(fd);
-                       }
-                       execl("/bin/srvold9p", "srvold9p", "-ds", nil);
-               } else
-                       execl("/bin/srvold9p", "srvold9p", "-s", nil);
-               fatal(1, "exec srvold9p");
-       default:
-               close(fd);
-               close(p[0]);
-       }
-       return p[1];    
-}
-
-/* Invoked with stdin, stdout and stderr connected to the network connection */
+/* Invoked with stdin and stdout connected to the network connection */
 void
-remoteside(int old)
+remoteside(void)
 {
-       char user[MaxStr], home[MaxStr], buf[MaxStr], xdir[MaxStr], cmd[MaxStr];
+       char user[MaxStr], buf[MaxStr], xdir[MaxStr], cmd[MaxStr];
        int i, n, fd, badchdir, gotcmd;
 
        rfork(RFENVG);
@@ -339,42 +305,44 @@ remoteside(int old)
        /* negotiate authentication mechanism */
        n = readstr(fd, cmd, sizeof(cmd));
        if(n < 0)
-               fatal(1, "authenticating");
-       if(setamalg(cmd) < 0){
+               fatal("authenticating: %r");
+       filterp = nil;
+       if(strcmp(cmd, "aan") == 0){
+               filterp = aan;
+               writestr(fd, "", nil, 1);
+               n = readstr(fd, cmd, sizeof(cmd));
+               if(n < 0)
+                       fatal("authenticating: %r");
+       }
+       if(setamalg(cmd) < 0 || (nflag == 0 && am->sf == srvnoauth)) {
                writestr(fd, "unsupported auth method", nil, 0);
-               fatal(1, "bad auth method %s", cmd);
+               fatal("bad auth method %s", cmd);
        } else
                writestr(fd, "", "", 1);
 
-       fd = (*am->sf)(fd, user);
-       if(fd < 0)
-               fatal(1, "srvauth");
-
-       /* Set environment values for the user */
-       putenv("user", user);
-       sprint(home, "/usr/%s", user);
-       putenv("home", home);
+       if((fd = (*am->sf)(fd, user)) < 0)
+               fatal("srvauth: %r");
+       if((fd = filter(fd, nil)) < 0)
+               fatal("filter: %r");
+       if((fd = encryption(fd)) < 0)
+               fatal("encrypt: %r");
 
        /* Now collect invoking cpu's current directory or possibly a command */
        gotcmd = 0;
        if(readstr(fd, xdir, sizeof(xdir)) < 0)
-               fatal(1, "dir/cmd");
+               fatal("dir/cmd: %r");
        if(xdir[0] == '!') {
                strcpy(cmd, &xdir[1]);
                gotcmd = 1;
                if(readstr(fd, xdir, sizeof(xdir)) < 0)
-                       fatal(1, "dir");
+                       fatal("dir: %r");
        }
 
-       /* Establish the new process at the current working directory of the
-        * gnot */
+       /* Establish the new process at the current working directory of the gnot */
        badchdir = 0;
-       if(strcmp(xdir, "NO") == 0)
-               chdir(home);
-       else if(chdir(xdir) < 0) {
-               badchdir = 1;
-               chdir(home);
-       }
+       if(strcmp(xdir, "NO") != 0)
+               if(chdir(xdir) < 0)
+                       badchdir = 1;
 
        /* Start the gnot serving its namespace */
        writestr(fd, "FS", "FS", 0);
@@ -384,9 +352,6 @@ remoteside(int old)
        if(n != 2 || buf[0] != 'O' || buf[1] != 'K')
                exits("remote tree");
 
-       if(old)
-               fd = old9p(fd);
-
        /* make sure buffers are big by doing fversion explicitly; pick a huge number; other side will trim */
        strcpy(buf, VERSION9P);
        if(fversion(fd, 64*1024, buf, sizeof buf) < 0)
@@ -415,23 +380,34 @@ remoteside(int old)
                execl("/bin/rc", "rc", "-lc", cmd, nil);
        else
                execl("/bin/rc", "rc", "-li", nil);
-       fatal(1, "exec shell");
+       fatal("exec shell: %r");
 }
 
 char*
 rexcall(int *fd, char *host, char *service)
 {
        char *na;
-       char dir[MaxStr];
        char err[ERRMAX];
        char msg[MaxStr];
        int n;
 
        na = netmkaddr(host, 0, service);
        procsetname("dialing %s", na);
-       if((*fd = dial(na, 0, dir, 0)) < 0)
+       if((*fd = dial(na, 0, 0, 0)) < 0)
                return "can't dial";
 
+       /* negotiate aan filter extension */
+       if(filterp == aan){
+               writestr(*fd, "aan", "negotiating aan", 0);
+               n = readstr(*fd, err, sizeof err);
+               if(n < 0)
+                       return "negotiating aan";
+               if(*err){
+                       errstr(err, sizeof err);
+                       return negstr;
+               }
+       }
+
        /* negotiate authentication mechanism */
        if(ealgs != nil)
                snprint(msg, sizeof(msg), "%s %s", am->name, ealgs);
@@ -444,16 +420,19 @@ rexcall(int *fd, char *host, char *service)
        if(n < 0)
                return negstr;
        if(*err){
-               werrstr(err);
+               errstr(err, sizeof err);
                return negstr;
        }
 
        /* authenticate */
        procsetname("%s: auth via %s", origargs, am->name);
-       *fd = (*am->cf)(*fd);
-       if(*fd < 0)
+       if((*fd = (*am->cf)(*fd)) < 0)
                return "can't authenticate";
-       return 0;
+       if((*fd = filter(*fd, system)) < 0)
+               return "can't filter";
+       if((*fd = encryption(*fd)) < 0)
+               return "can't encrypt";
+       return nil;
 }
 
 void
@@ -464,7 +443,7 @@ writestr(int fd, char *str, char *thing, int ignore)
        l = strlen(str);
        n = write(fd, str, l+1);
        if(!ignore && n < 0)
-               fatal(1, "writing network: %s", thing);
+               fatal("writing network: %s: %r", thing);
 }
 
 int
@@ -541,7 +520,7 @@ netkeysrvauth(int fd, char *user)
        int tries;
        AuthInfo *ai;
 
-       if(readstr(fd, user, 32) < 0)
+       if(readstr(fd, user, MaxStr) < 0)
                return -1;
 
        ai = nil;
@@ -562,11 +541,25 @@ netkeysrvauth(int fd, char *user)
                return -1;
        writestr(fd, "", "challenge", 1);
        if(auth_chuid(ai, 0) < 0)
-               fatal(1, "newns");
+               fatal("newns: %r");
        auth_freeAI(ai);
        return fd;
 }
 
+static int
+clear(int fd)
+{
+       return fd;
+}
+
+static char sslsecret[2][21];
+
+static int
+sslencrypt(int fd)
+{
+       return pushssl(fd, ealgs, sslsecret[0], sslsecret[1], nil);
+}
+
 static void
 mksecret(char *t, uchar *f)
 {
@@ -574,50 +567,64 @@ mksecret(char *t, uchar *f)
                f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7], f[8], f[9]);
 }
 
-/*
- *  plan9 authentication followed by rc4 encryption
- */
 static int
-p9auth(int fd)
+sslsetup(int fd, uchar *secret, int nsecret, int isclient)
 {
-       uchar key[16];
-       uchar digest[SHA1dlen];
-       char fromclientsecret[21];
-       char fromserversecret[21];
+       uchar key[16], digest[SHA1dlen];
        int i;
-       AuthInfo *ai;
 
-       procsetname("%s: auth_proxy proto=%q role=client %s",
-               origargs, p9authproto, keyspec);
-       ai = auth_proxy(fd, auth_getkey, "proto=%q role=client %s", p9authproto, keyspec);
-       if(ai == nil)
-               return -1;
-       memmove(key+4, ai->secret, ai->nsecret);
        if(ealgs == nil)
                return fd;
 
+       if(nsecret < 8){
+               werrstr("secret too small to ssl");
+               return -1;
+       }
+       memmove(key+4, secret, 8);
+
        /* exchange random numbers */
        srand(truerand());
-       for(i = 0; i < 4; i++)
-               key[i] = rand();
-       procsetname("writing p9 key");
-       if(write(fd, key, 4) != 4)
-               return -1;
-       procsetname("reading p9 key");
-       if(readn(fd, key+12, 4) != 4)
-               return -1;
+
+       if(isclient){
+               for(i = 0; i < 4; i++)
+                       key[i] = rand();
+               if(write(fd, key, 4) != 4)
+                       return -1;
+               if(readn(fd, key+12, 4) != 4)
+                       return -1;
+       } else {
+               for(i = 0; i < 4; i++)
+                       key[i+12] = rand();
+               if(readn(fd, key, 4) != 4)
+                       return -1;
+               if(write(fd, key+12, 4) != 4)
+                       return -1;
+       }
 
        /* scramble into two secrets */
        sha1(key, sizeof(key), digest, nil);
-       mksecret(fromclientsecret, digest);
-       mksecret(fromserversecret, digest+10);
-
-       /* set up encryption */
-       procsetname("pushssl");
-       i = pushssl(fd, ealgs, fromclientsecret, fromserversecret, nil);
-       if(i < 0)
-               werrstr("can't establish ssl connection: %r");
-       return i;
+       mksecret(sslsecret[isclient == 0], digest);
+       mksecret(sslsecret[isclient != 0], digest+10);
+
+       encryption = sslencrypt;
+
+       return fd;
+}
+
+/*
+ *  plan9 authentication followed by rc4 encryption
+ */
+static int
+p9auth(int fd)
+{
+       AuthInfo *ai;
+
+       ai = auth_proxy(fd, auth_getkey, "proto=p9any role=client %s", keyspec);
+       if(ai == nil)
+               return -1;
+       fd = sslsetup(fd, ai->secret, ai->nsecret, 1);
+       auth_freeAI(ai);
+       return fd;
 }
 
 static int
@@ -636,57 +643,20 @@ srvnoauth(int fd, char *user)
        return fd;
 }
 
-void
-loghex(uchar *p, int n)
-{
-       char buf[100];
-       int i;
-
-       for(i = 0; i < n; i++)
-               sprint(buf+2*i, "%2.2ux", p[i]);
-       syslog(0, "cpu", buf);
-}
-
 static int
 srvp9auth(int fd, char *user)
 {
-       uchar key[16];
-       uchar digest[SHA1dlen];
-       char fromclientsecret[21];
-       char fromserversecret[21];
-       int i;
        AuthInfo *ai;
 
-       ai = auth_proxy(0, nil, "proto=%q role=server %s", p9authproto, keyspec);
+       ai = auth_proxy(fd, nil, "proto=p9any role=server %s", keyspec);
        if(ai == nil)
                return -1;
        if(auth_chuid(ai, nil) < 0)
-               return -1;
-       strecpy(user, user+MaxStr, ai->cuid);
-       memmove(key+4, ai->secret, ai->nsecret);
-
-       if(ealgs == nil)
-               return fd;
-
-       /* exchange random numbers */
-       srand(truerand());
-       for(i = 0; i < 4; i++)
-               key[i+12] = rand();
-       if(readn(fd, key, 4) != 4)
-               return -1;
-       if(write(fd, key+12, 4) != 4)
-               return -1;
-
-       /* scramble into two secrets */
-       sha1(key, sizeof(key), digest, nil);
-       mksecret(fromclientsecret, digest);
-       mksecret(fromserversecret, digest+10);
-
-       /* set up encryption */
-       i = pushssl(fd, ealgs, fromserversecret, fromclientsecret, nil);
-       if(i < 0)
-               werrstr("can't establish ssl connection: %r");
-       return i;
+               fatal("newns: %r");
+       snprint(user, MaxStr, "%s", ai->cuid);
+       fd = sslsetup(fd, ai->secret, ai->nsecret, 0);
+       auth_freeAI(ai);
+       return fd;
 }
 
 /*
@@ -714,6 +684,76 @@ setamalg(char *s)
        return setam(s);
 }
 
+int
+filter(int fd, char *host)
+{
+       char addr[128], buf[256], *s, *file, *argv[16];
+       int p[2], lfd, flags, len, argc;
+
+       if(filterp == nil)
+               return fd;
+       procsetname("filter %s", filterp);
+       flags = RFNOWAIT|RFPROC|RFMEM|RFFDG|RFREND;
+       if(host == nil){
+               /* remote side */
+               if(announce(anstring, addr) < 0)
+                       fatal("filter: Cannot announce %s: %r", anstring);
+               snprint(buf, sizeof(buf), "%s/local", addr);
+               if((lfd = open(buf, OREAD)) < 0)
+                       fatal("filter: Cannot open %s: %r", buf);
+               if((len = read(lfd, buf, sizeof buf - 1)) < 0)
+                       fatal("filter: Cannot read %s: %r", buf);
+               close(lfd);
+               buf[len] = 0;
+               if(s = strchr(buf, '\n'))
+                       len = s - buf;
+               if(write(fd, buf, len) != len) 
+                       fatal("filter: cannot write port; %r");
+       } else {
+               /* client side */
+               flags |= RFNOTEG;
+               if((len = read(fd, buf, sizeof buf - 1)) < 0)
+                       fatal("filter: cannot read port; %r");
+               buf[len] = '\0';
+               if((s = strrchr(buf, '!')) == nil)
+                       fatal("filter: malformed remote port: %s", buf);
+               strecpy(addr, addr+sizeof(addr), netmkaddr(host, "tcp", s+1));
+               strecpy(strrchr(addr, '!'), addr+sizeof(addr), s);
+       }
+
+       snprint(buf, sizeof(buf), "%s", filterp);
+       if((argc = tokenize(buf, argv, nelem(argv)-3)) <= 0)
+               fatal("filter: empty command");
+       if(host)
+               argv[argc++] = "-c";
+       argv[argc++] = addr;
+       argv[argc] = nil;
+       file = argv[0];
+       if(s = strrchr(argv[0], '/'))
+               argv[0] = s+1;
+
+       if(pipe(p) < 0)
+               fatal("filter: pipe; %r");
+
+       switch(rfork(flags)) {
+       case -1:
+               fatal("filter: rfork; %r\n");
+       case 0:
+               if (dup(p[0], 1) < 0)
+                       fatal("filter: Cannot dup to 1; %r");
+               if (dup(p[0], 0) < 0)
+                       fatal("filter: Cannot dup to 0; %r");
+               close(p[0]);
+               close(p[1]);
+               exec(file, argv);
+               fatal("filter: exec; %r");
+       default:
+               close(fd);
+               close(p[0]);
+       }
+       return p[1];    
+}
+
 char *rmtnotefile = "/mnt/term/dev/cpunote";
 
 /*
@@ -988,11 +1028,13 @@ notefs(int fd)
        ncpunote = 0;
        for(;;){
                n = read9pmsg(fd, buf, sizeof(buf));
-               if(n <= 0){
+               if(n < 0){
                        if(dbg)
                                fprint(2, "read9pmsg(%d) returns %d: %r\n", fd, n);
                        break;
                }
+               if(n == 0)
+                       continue;
                if(convM2S(buf, n, &f) <= BIT16SZ)
                        break;
                if(dbg)