/* * cpu.c - Make a connection to a cpu server */ #include <u.h>#include <libc.h>#include <auth.h>#include <fcall.h>#include <authsrv.h>#include <libsec.h>#include "args.h"#include "drawterm.h" #define MaxStr 128 static void usage(void);static void writestr(int, char*, char*, int);static int readstr(int, char*, int);static char *keyspec = "";static AuthInfo *p9any(int);static int getkey(Authkey*, char*, char*, char*, char*);static int findkey(Authkey*, char*, char*, char*); static char *host;static int aanfilter;static int aanto = 3600 * 24;static int norcpu;static int nokbd;static int nogfx; static char *ealgs = "rc4_256 sha1"; /* authentication mechanisms */static int p9authssl(int);static int p9authtls(int); char *authserver;char *secstore;char *user, *pass;char secstorebuf[65536]; char*estrdup(char *s){ s = strdup(s); if(s == nil) sysfatal("out of memory"); return s;} static voidending(void){ panic("ending");} intmountfactotum(void){ int fd; if((fd = dialfactotum()) < 0) return -1; if(sysmount(fd, -1, "/mnt/factotum", MREPL, "") < 0){ fprint(2, "mount factotum: %r\n"); return -1; } if((fd = open("/mnt/factotum/ctl", OREAD)) < 0){ fprint(2, "open /mnt/factotum/ctl: %r\n"); return -1; } close(fd); return 0;} static intstartaan(char *host, int fd){ static char script[] ="~ $#netdir 1 || netdir=/net/tcp/clone\n""netdir=`{basename -d $netdir} || exit\n""<>$netdir/clone {\n"" netdir=$netdir/`{read} || exit\n"" >[3] $netdir/ctl {\n"" echo -n 'announce *!0' >[1=3]\n"" echo `{cat $netdir/local} || exit\n"" bind '#|' /mnt/aan || exit\n"" exec aan -m $aanto $netdir <>/mnt/aan/data1 >[1=0] >[2]/dev/null &\n"" }\n""}\n""<>/mnt/aan/data >[1=0] >[2]/dev/null {\n"" rfork n\n"" fn server {\n"" echo -n aanserver $netdir >/proc/$pid/args\n"" rm -f /env/^('fn#server' aanto)\n"" . <{n=`{read} && ! ~ $#n 0 && read -c $n} >[2=1]\n"" }\n"" exec tlssrv -A /bin/rc -c server\n"" exit\n""}\n"; char buf[128], *p, *na; int n; snprint(buf, sizeof buf, "aanto=%d\n", aanto); if(fprint(fd, "%7ld\n%s%s", strlen(buf)+strlen(script), buf, script) < 0) sysfatal("sending aan script: %r"); n = read(fd, buf, sizeof(buf)-1); close(fd); while(n > 0 && buf[n-1] == '\n') n--; if(n <= 0) return -1; buf[n] = 0; if((p = strrchr(buf, '!')) != nil) na = strdup(netmkaddr(host, "tcp", p+1)); else na = strdup(buf); return aanclient(na, aanto);} voidrcpu(char *host, char *cmd){ static char script[] = "syscall fversion 0 65536 buf 256 >/dev/null >[2=1]\n""mount -nc /fd/0 /mnt/term || exit\n""bind -q /mnt/term/dev/cons /dev/cons\n""if(test -r /mnt/term/dev/kbd){\n"" </dev/cons >/dev/cons >[2=1] aux/kbdfs -dq -m /mnt/term/dev\n"" bind -q /mnt/term/dev/cons /dev/cons\n""}\n""</dev/cons >/dev/cons >[2=1] service=cpu %s\n""echo -n hangup >/proc/$pid/notepg\n"; int fd; if((fd = dial(netmkaddr(host, "tcp", "rcpu"), nil, nil, nil)) < 0) return; /* provide /dev/kbd for kbdfs */ if(!nokbd) bind("#b", "/dev", MAFTER); fd = p9authtls(fd); if(aanfilter){ fd = startaan(host, fd); if(fd < 0) sysfatal("startaan: %r"); fd = p9authtls(fd); } memset(secstorebuf, 0, sizeof(secstorebuf)); /* forget secstore secrets */ if(cmd == nil) cmd = smprint(script, "rc -li"); else { char *run = smprint("rc -lc %q", cmd); cmd = smprint(script, run); free(run); } if(fprint(fd, "%7ld\n%s", strlen(cmd), cmd) < 0) sysfatal("sending script: %r"); free(cmd); /* Begin serving the namespace */ exportfs(fd);} voidncpu(char *host, char *cmd){ char buf[MaxStr]; int fd; if((fd = dial(netmkaddr(host, "tcp", "ncpu"), nil, nil, nil)) < 0) return; /* negotiate authentication mechanism */ strcpy(buf, "p9"); if(ealgs != nil){ strcat(buf, " "); strcat(buf, ealgs); } writestr(fd, buf, "negotiating authentication method", 0); if(readstr(fd, buf, sizeof buf) < 0) sysfatal("can't negotiate authentication method: %r"); if(*buf) sysfatal("%s", buf); /* authenticate and encrypt the channel */ fd = p9authssl(fd); /* tell remote side the command */ if(cmd != nil){ cmd = smprint("!%s", cmd); writestr(fd, cmd, "cmd", 0); free(cmd); } /* Tell the remote side where our working directory is */ if(getcwd(buf, sizeof(buf)) == 0) writestr(fd, "NO", "dir", 0); else writestr(fd, buf, "dir", 0); /* * Wait for the other end to execute and start our file service * of /mnt/term */ if(readstr(fd, buf, sizeof(buf)) < 0) sysfatal("waiting for FS: %r"); if(strncmp("FS", buf, 2) != 0) { print("remote cpu: %s", buf); exits(buf); } if(readstr(fd, buf, sizeof(buf)) < 0) sysfatal("waiting for remote export: %r"); if(strcmp(buf, "/") != 0){ print("remote cpu: %s", buf); exits(buf); } write(fd, "OK", 2); /* Begin serving the gnot namespace */ exportfs(fd);} voidusage(void){ fprint(2, "usage: %s [-GBO] " "[-h host] [-u user] [-a authserver] [-s secstore] " "[-e 'crypt hash'] [-k keypattern] " "[-p] [-t timeout] " "[-r root] [-c cmd ...]\n", argv0); exits("usage");} voidcpumain(int argc, char **argv){ char *s, *cmd = nil; user = getenv("USER"); pass = getenv("PASS"); host = getenv("cpu"); authserver = getenv("auth"); ARGBEGIN{ case 'G': nogfx = 1; /* wet floor */ case 'B': nokbd = 1; break; case 'O': norcpu = 1; break; case 'p': aanfilter = 1; break; case 't': aanto = (int)strtol(EARGF(usage()), nil, 0); break; case 'h': host = EARGF(usage()); break; case 'a': authserver = EARGF(usage()); break; case 's': secstore = EARGF(usage()); break; case 'e': ealgs = EARGF(usage()); if(*ealgs == 0 || strcmp(ealgs, "clear") == 0) ealgs = nil; break; case 'k': keyspec = EARGF(usage()); break; case 'u': user = EARGF(usage()); break; case 'r': s = smprint("/root/%s", EARGF(usage())); cleanname(s); if(bind(s, "/root", MREPL) < 0) panic("bind /root: %r"); free(s); break; case 'c': cmd = estrdup(EARGF(usage())); while((s = ARGF()) != nil){ char *old = cmd; cmd = smprint("%s %q", cmd, s); free(old); } break; default: usage(); }ARGEND; if(argc != 0) usage(); if(!nogfx) { if(bind("#i", "/dev", MBEFORE) < 0) panic("bind #i: %r"); if(bind("#m", "/dev", MBEFORE) < 0) panic("bind #m: %r"); if(cmd == nil) atexit(ending); } if(bind("/root", "/", MAFTER) < 0) panic("bind /root: %r"); if(host == nil) if((host = readcons("cpu", "cpu", 0)) == nil) sysfatal("user terminated input"); if(authserver == nil) if((authserver = readcons("auth", host, 0)) == nil) sysfatal("user terminated input"); if(user == nil) if((user = readcons("user", "glenda", 0)) == nil) sysfatal("user terminated input"); if(mountfactotum() < 0){ if(secstore == nil) secstore = authserver; if(havesecstore(secstore, user)){ s = secstorefetch(secstore, user, pass); if(s){ if(strlen(s) >= sizeof secstorebuf) sysfatal("secstore data too big"); strcpy(secstorebuf, s); } } } if(!norcpu) rcpu(host, cmd); ncpu(host, cmd); sysfatal("can't dial %s: %r", host);} voidwritestr(int fd, char *str, char *thing, int ignore){ int l, n; l = strlen(str); n = write(fd, str, l+1); if(!ignore && n < 0) sysfatal("writing network: %s: %r", thing);} intreadstr(int fd, char *str, int len){ int n; while(len) { n = read(fd, str, 1); if(n < 0) return -1; if(*str == '\0') return 0; str++; len--; } return -1;} static voidmksecret(char *t, uchar *f){ sprint(t, "%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux", 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 intp9authssl(int fd){ uchar key[16]; uchar digest[SHA1dlen]; char fromclientsecret[21]; char fromserversecret[21]; AuthInfo *ai; ai = p9any(fd); memset(secstorebuf, 0, sizeof(secstorebuf)); /* forget secstore secrets */ if(ai == nil) sysfatal("can't authenticate: %r"); if(ealgs == nil) return fd; if(ai->nsecret < 8){ sysfatal("p9authssl: secret too small"); return -1; } memmove(key+4, ai->secret, 8); /* exchange random numbers */ genrandom(key, 4); if(write(fd, key, 4) != 4){ sysfatal("p9authssl: write random: %r"); return -1; } if(readn(fd, key+12, 4) != 4){ sysfatal("p9authssl: read random: %r"); return -1; } /* scramble into two secrets */ sha1(key, sizeof(key), digest, nil); mksecret(fromclientsecret, digest); mksecret(fromserversecret, digest+10); /* set up encryption */ fd = pushssl(fd, ealgs, fromclientsecret, fromserversecret, nil); if(fd < 0) sysfatal("p9authssl: pushssl: %r"); return fd;} /* * p9any authentication followed by tls-psk encryption */static intp9authtls(int fd){ AuthInfo *ai; TLSconn *conn; ai = p9any(fd); if(ai == nil) sysfatal("can't authenticate: %r"); conn = mallocz(sizeof(TLSconn), 1); conn->pskID = "p9secret"; conn->psk = ai->secret; conn->psklen = ai->nsecret; fd = tlsClient(fd, conn); if(fd < 0) sysfatal("tlsClient: %r"); auth_freeAI(ai); free(conn->sessionID); free(conn); return fd;} intauthdial(char *net, char *dom){ return dial(netmkaddr(authserver, "tcp", "ticket"), 0, 0, 0);} static intgetastickets(Authkey *key, Ticketreq *tr, uchar *y, char *tbuf, int tbuflen){ int asfd, rv; char *dom; dom = tr->authdom; asfd = authdial(nil, dom); if(asfd < 0) return -1; if(y != nil){ PAKpriv p; rv = -1; tr->type = AuthPAK; if(_asrequest(asfd, tr) != 0 || write(asfd, y, PAKYLEN) != PAKYLEN) goto Out; authpak_new(&p, key, (uchar*)tbuf, 1); if(write(asfd, tbuf, PAKYLEN) != PAKYLEN) goto Out; if(_asrdresp(asfd, tbuf, 2*PAKYLEN) != 2*PAKYLEN) goto Out; memmove(y, tbuf, PAKYLEN); if(authpak_finish(&p, key, (uchar*)tbuf+PAKYLEN)) goto Out; } tr->type = AuthTreq;Lines 1–500 of 885. Load more
/* * cpu.c - Make a connection to a cpu server */ #include <u.h> #include <libc.h> #include <auth.h> #include <fcall.h> #include <authsrv.h> #include <libsec.h> #include "args.h" #include "drawterm.h" #define MaxStr 128 static void usage(void); static void writestr(int, char*, char*, int); static int readstr(int, char*, int); static char *keyspec = ""; static AuthInfo *p9any(int); static int getkey(Authkey*, char*, char*, char*, char*); static int findkey(Authkey*, char*, char*, char*); static char *host; static int aanfilter; static int aanto = 3600 * 24; static int norcpu; static int nokbd; static int nogfx; static char *ealgs = "rc4_256 sha1"; /* authentication mechanisms */ static int p9authssl(int); static int p9authtls(int); char *authserver; char *secstore; char *user, *pass; char secstorebuf[65536]; char* estrdup(char *s) { s = strdup(s); if(s == nil) sysfatal("out of memory"); return s; } static void ending(void) { panic("ending"); } int mountfactotum(void) { int fd; if((fd = dialfactotum()) < 0) return -1; if(sysmount(fd, -1, "/mnt/factotum", MREPL, "") < 0){ fprint(2, "mount factotum: %r\n"); return -1; } if((fd = open("/mnt/factotum/ctl", OREAD)) < 0){ fprint(2, "open /mnt/factotum/ctl: %r\n"); return -1; } close(fd); return 0; } static int startaan(char *host, int fd) { static char script[] = "~ $#netdir 1 || netdir=/net/tcp/clone\n" "netdir=`{basename -d $netdir} || exit\n" "<>$netdir/clone {\n" " netdir=$netdir/`{read} || exit\n" " >[3] $netdir/ctl {\n" " echo -n 'announce *!0' >[1=3]\n" " echo `{cat $netdir/local} || exit\n" " bind '#|' /mnt/aan || exit\n" " exec aan -m $aanto $netdir <>/mnt/aan/data1 >[1=0] >[2]/dev/null &\n" " }\n" "}\n" "<>/mnt/aan/data >[1=0] >[2]/dev/null {\n" " rfork n\n" " fn server {\n" " echo -n aanserver $netdir >/proc/$pid/args\n" " rm -f /env/^('fn#server' aanto)\n" " . <{n=`{read} && ! ~ $#n 0 && read -c $n} >[2=1]\n" " }\n" " exec tlssrv -A /bin/rc -c server\n" " exit\n" "}\n"; char buf[128], *p, *na; int n; snprint(buf, sizeof buf, "aanto=%d\n", aanto); if(fprint(fd, "%7ld\n%s%s", strlen(buf)+strlen(script), buf, script) < 0) sysfatal("sending aan script: %r"); n = read(fd, buf, sizeof(buf)-1); close(fd); while(n > 0 && buf[n-1] == '\n') n--; if(n <= 0) return -1; buf[n] = 0; if((p = strrchr(buf, '!')) != nil) na = strdup(netmkaddr(host, "tcp", p+1)); else na = strdup(buf); return aanclient(na, aanto); } void rcpu(char *host, char *cmd) { static char script[] = "syscall fversion 0 65536 buf 256 >/dev/null >[2=1]\n" "mount -nc /fd/0 /mnt/term || exit\n" "bind -q /mnt/term/dev/cons /dev/cons\n" "if(test -r /mnt/term/dev/kbd){\n" " </dev/cons >/dev/cons >[2=1] aux/kbdfs -dq -m /mnt/term/dev\n" " bind -q /mnt/term/dev/cons /dev/cons\n" "}\n" "</dev/cons >/dev/cons >[2=1] service=cpu %s\n" "echo -n hangup >/proc/$pid/notepg\n"; int fd; if((fd = dial(netmkaddr(host, "tcp", "rcpu"), nil, nil, nil)) < 0) return; /* provide /dev/kbd for kbdfs */ if(!nokbd) bind("#b", "/dev", MAFTER); fd = p9authtls(fd); if(aanfilter){ fd = startaan(host, fd); if(fd < 0) sysfatal("startaan: %r"); fd = p9authtls(fd); } memset(secstorebuf, 0, sizeof(secstorebuf)); /* forget secstore secrets */ if(cmd == nil) cmd = smprint(script, "rc -li"); else { char *run = smprint("rc -lc %q", cmd); cmd = smprint(script, run); free(run); } if(fprint(fd, "%7ld\n%s", strlen(cmd), cmd) < 0) sysfatal("sending script: %r"); free(cmd); /* Begin serving the namespace */ exportfs(fd); } void ncpu(char *host, char *cmd) { char buf[MaxStr]; int fd; if((fd = dial(netmkaddr(host, "tcp", "ncpu"), nil, nil, nil)) < 0) return; /* negotiate authentication mechanism */ strcpy(buf, "p9"); if(ealgs != nil){ strcat(buf, " "); strcat(buf, ealgs); } writestr(fd, buf, "negotiating authentication method", 0); if(readstr(fd, buf, sizeof buf) < 0) sysfatal("can't negotiate authentication method: %r"); if(*buf) sysfatal("%s", buf); /* authenticate and encrypt the channel */ fd = p9authssl(fd); /* tell remote side the command */ if(cmd != nil){ cmd = smprint("!%s", cmd); writestr(fd, cmd, "cmd", 0); free(cmd); } /* Tell the remote side where our working directory is */ if(getcwd(buf, sizeof(buf)) == 0) writestr(fd, "NO", "dir", 0); else writestr(fd, buf, "dir", 0); /* * Wait for the other end to execute and start our file service * of /mnt/term */ if(readstr(fd, buf, sizeof(buf)) < 0) sysfatal("waiting for FS: %r"); if(strncmp("FS", buf, 2) != 0) { print("remote cpu: %s", buf); exits(buf); } if(readstr(fd, buf, sizeof(buf)) < 0) sysfatal("waiting for remote export: %r"); if(strcmp(buf, "/") != 0){ print("remote cpu: %s", buf); exits(buf); } write(fd, "OK", 2); /* Begin serving the gnot namespace */ exportfs(fd); } void usage(void) { fprint(2, "usage: %s [-GBO] " "[-h host] [-u user] [-a authserver] [-s secstore] " "[-e 'crypt hash'] [-k keypattern] " "[-p] [-t timeout] " "[-r root] [-c cmd ...]\n", argv0); exits("usage"); } void cpumain(int argc, char **argv) { char *s, *cmd = nil; user = getenv("USER"); pass = getenv("PASS"); host = getenv("cpu"); authserver = getenv("auth"); ARGBEGIN{ case 'G': nogfx = 1; /* wet floor */ case 'B': nokbd = 1; break; case 'O': norcpu = 1; break; case 'p': aanfilter = 1; break; case 't': aanto = (int)strtol(EARGF(usage()), nil, 0); break; case 'h': host = EARGF(usage()); break; case 'a': authserver = EARGF(usage()); break; case 's': secstore = EARGF(usage()); break; case 'e': ealgs = EARGF(usage()); if(*ealgs == 0 || strcmp(ealgs, "clear") == 0) ealgs = nil; break; case 'k': keyspec = EARGF(usage()); break; case 'u': user = EARGF(usage()); break; case 'r': s = smprint("/root/%s", EARGF(usage())); cleanname(s); if(bind(s, "/root", MREPL) < 0) panic("bind /root: %r"); free(s); break; case 'c': cmd = estrdup(EARGF(usage())); while((s = ARGF()) != nil){ char *old = cmd; cmd = smprint("%s %q", cmd, s); free(old); } break; default: usage(); }ARGEND; if(argc != 0) usage(); if(!nogfx) { if(bind("#i", "/dev", MBEFORE) < 0) panic("bind #i: %r"); if(bind("#m", "/dev", MBEFORE) < 0) panic("bind #m: %r"); if(cmd == nil) atexit(ending); } if(bind("/root", "/", MAFTER) < 0) panic("bind /root: %r"); if(host == nil) if((host = readcons("cpu", "cpu", 0)) == nil) sysfatal("user terminated input"); if(authserver == nil) if((authserver = readcons("auth", host, 0)) == nil) sysfatal("user terminated input"); if(user == nil) if((user = readcons("user", "glenda", 0)) == nil) sysfatal("user terminated input"); if(mountfactotum() < 0){ if(secstore == nil) secstore = authserver; if(havesecstore(secstore, user)){ s = secstorefetch(secstore, user, pass); if(s){ if(strlen(s) >= sizeof secstorebuf) sysfatal("secstore data too big"); strcpy(secstorebuf, s); } } } if(!norcpu) rcpu(host, cmd); ncpu(host, cmd); sysfatal("can't dial %s: %r", host); } void writestr(int fd, char *str, char *thing, int ignore) { int l, n; l = strlen(str); n = write(fd, str, l+1); if(!ignore && n < 0) sysfatal("writing network: %s: %r", thing); } int readstr(int fd, char *str, int len) { int n; while(len) { n = read(fd, str, 1); if(n < 0) return -1; if(*str == '\0') return 0; str++; len--; } return -1; } static void mksecret(char *t, uchar *f) { sprint(t, "%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux", 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 p9authssl(int fd) { uchar key[16]; uchar digest[SHA1dlen]; char fromclientsecret[21]; char fromserversecret[21]; AuthInfo *ai; ai = p9any(fd); memset(secstorebuf, 0, sizeof(secstorebuf)); /* forget secstore secrets */ if(ai == nil) sysfatal("can't authenticate: %r"); if(ealgs == nil) return fd; if(ai->nsecret < 8){ sysfatal("p9authssl: secret too small"); return -1; } memmove(key+4, ai->secret, 8); /* exchange random numbers */ genrandom(key, 4); if(write(fd, key, 4) != 4){ sysfatal("p9authssl: write random: %r"); return -1; } if(readn(fd, key+12, 4) != 4){ sysfatal("p9authssl: read random: %r"); return -1; } /* scramble into two secrets */ sha1(key, sizeof(key), digest, nil); mksecret(fromclientsecret, digest); mksecret(fromserversecret, digest+10); /* set up encryption */ fd = pushssl(fd, ealgs, fromclientsecret, fromserversecret, nil); if(fd < 0) sysfatal("p9authssl: pushssl: %r"); return fd; } /* * p9any authentication followed by tls-psk encryption */ static int p9authtls(int fd) { AuthInfo *ai; TLSconn *conn; ai = p9any(fd); if(ai == nil) sysfatal("can't authenticate: %r"); conn = mallocz(sizeof(TLSconn), 1); conn->pskID = "p9secret"; conn->psk = ai->secret; conn->psklen = ai->nsecret; fd = tlsClient(fd, conn); if(fd < 0) sysfatal("tlsClient: %r"); auth_freeAI(ai); free(conn->sessionID); free(conn); return fd; } int authdial(char *net, char *dom) { return dial(netmkaddr(authserver, "tcp", "ticket"), 0, 0, 0); } static int getastickets(Authkey *key, Ticketreq *tr, uchar *y, char *tbuf, int tbuflen) { int asfd, rv; char *dom; dom = tr->authdom; asfd = authdial(nil, dom); if(asfd < 0) return -1; if(y != nil){ PAKpriv p; rv = -1; tr->type = AuthPAK; if(_asrequest(asfd, tr) != 0 || write(asfd, y, PAKYLEN) != PAKYLEN) goto Out; authpak_new(&p, key, (uchar*)tbuf, 1); if(write(asfd, tbuf, PAKYLEN) != PAKYLEN) goto Out; if(_asrdresp(asfd, tbuf, 2*PAKYLEN) != 2*PAKYLEN) goto Out; memmove(y, tbuf, PAKYLEN); if(authpak_finish(&p, key, (uchar*)tbuf+PAKYLEN)) goto Out; } tr->type = AuthTreq;