/* * cpu.c - Make a connection to a cpu server * * Invoked by listen as 'cpu -R | -N service net netdir' * by users as 'cpu [-h system] [-c cmd args ...]' */ #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 Maxfdata 8192#define MaxStr 128 static void fatal(int, char*, ...);static void usage(void);static void writestr(int, char*, char*, int);static int readstr(int, char*, int);static char *rexcall(int*, char*, char*);static char *keyspec = "";static AuthInfo *p9any(int); #define system csystemstatic char *system;static int cflag;extern int dbg;extern char* base; // fs base for devroot static char *srvname = "ncpu";static char *ealgs = "rc4_256 sha1"; /* message size for exportfs; may be larger so we can do big graphics in CPU window */static int msgsize = Maxfdata+IOHDRSZ; /* authentication mechanisms */static int netkeyauth(int);static int netkeysrvauth(int, char*);static int p9auth(int);static int srvp9auth(int, char*); char *authserver; typedef struct AuthMethod AuthMethod;struct AuthMethod { char *name; /* name of method */ int (*cf)(int); /* client side authentication */ int (*sf)(int, char*); /* server side authentication */} authmethod[] ={ { "p9", p9auth, srvp9auth,}, { "netkey", netkeyauth, netkeysrvauth,},// { "none", noauth, srvnoauth,}, { 0 }};AuthMethod *am = authmethod; /* default is p9 */ char *p9authproto = "p9any"; int setam(char*); voidexits(char *s){ print("\ngoodbye\n"); for(;;) osyield();} voidusage(void){ fprint(2, "usage: drawterm [-a authserver] [-c cpuserver] [-s secstore] [-u user]\n"); exits("usage");}int fdd; 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;} voidcpumain(int argc, char **argv){ char dat[MaxStr], buf[MaxStr], cmd[MaxStr], *err, *secstoreserver, *p, *s; int fd, ms, data; /* see if we should use a larger message size */ fd = open("/dev/draw", OREAD); if(fd > 0){ ms = iounit(fd); if(msgsize < ms+IOHDRSZ) msgsize = ms+IOHDRSZ; close(fd); } user = getenv("USER"); secstoreserver = nil; authserver = getenv("auth"); if(authserver == nil) authserver = "auth"; system = getenv("cpu"); if(system == nil) system = "cpu"; ARGBEGIN{ case 'a': authserver = EARGF(usage()); break; case 'c': system = EARGF(usage()); break; case 'd': dbg++; break; case 'e': ealgs = EARGF(usage()); if(*ealgs == 0 || strcmp(ealgs, "clear") == 0) ealgs = nil; break; case 'C': cflag++; cmd[0] = '!'; cmd[1] = '\0'; while((p = ARGF()) != nil) { strcat(cmd, " "); strcat(cmd, p); } break; case 'k': keyspec = EARGF(usage()); break; case 'r': base = EARGF(usage()); break; case 's': secstoreserver = EARGF(usage()); break; case 'u': user = EARGF(usage()); break; default: usage(); }ARGEND; if(argc != 0) usage(); if(user == nil) user = readcons("user", nil, 0); if(mountfactotum() < 0){ if(secstoreserver == nil) secstoreserver = authserver; if(havesecstore(secstoreserver, user)){ s = secstorefetch(secstoreserver, user, nil); if(s){ if(strlen(s) >= sizeof secstorebuf) sysfatal("secstore data too big"); strcpy(secstorebuf, s); } } } if((err = rexcall(&data, system, srvname))) fatal(1, "%s: %s", err, system); /* Tell the remote side the command to execute and where our working directory is */ if(cflag) writestr(data, cmd, "command", 0); if(getcwd(dat, sizeof(dat)) == 0) writestr(data, "NO", "dir", 0); else writestr(data, dat, "dir", 0); /* * Wait for the other end to execute and start our file service * of /mnt/term */ if(readstr(data, buf, sizeof(buf)) < 0) fatal(1, "waiting for FS: %r"); if(strncmp("FS", buf, 2) != 0) { print("remote cpu: %s", buf); exits(buf); } if(readstr(data, buf, sizeof buf) < 0) fatal(1, "waiting for remote export: %r"); if(strcmp(buf, "/") != 0){ print("remote cpu: %s" , buf); exits(buf); } write(data, "OK", 2); /* Begin serving the gnot namespace */ exportfs(data, msgsize); fatal(1, "starting exportfs");} voidfatal(int syserr, char *fmt, ...){ Fmt f; char *str; va_list arg; fmtstrinit(&f); fmtprint(&f, "cpu: "); va_start(arg, fmt); fmtvprint(&f, fmt, arg); va_end(arg); if(syserr) fmtprint(&f, ": %r"); fmtprint(&f, "\n"); str = fmtstrflush(&f); write(2, str, strlen(str)); exits(str);} char *negstr = "negotiating authentication method"; char bug[256]; char*rexcall(int *fd, char *host, char *service){ char *na; char dir[MaxStr]; char err[ERRMAX]; char msg[MaxStr]; int n; na = netmkaddr(host, "tcp", "17010"); if((*fd = dial(na, 0, dir, 0)) < 0) return "can't dial"; /* negotiate authentication mechanism */ if(ealgs != nil) snprint(msg, sizeof(msg), "%s %s", am->name, ealgs); else snprint(msg, sizeof(msg), "%s", am->name); writestr(*fd, msg, negstr, 0); n = readstr(*fd, err, sizeof err); if(n < 0) return negstr; if(*err){ werrstr(err); return negstr; } /* authenticate */ *fd = (*am->cf)(*fd); if(*fd < 0) return "can't authenticate"; return 0;} 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) fatal(1, "writing network: %s", 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 intreadln(char *buf, int n){ int i; char *p; n--; /* room for \0 */ p = buf; for(i=0; i<n; i++){ if(read(0, p, 1) != 1) break; if(*p == '\n' || *p == '\r') break; p++; } *p = '\0'; return p-buf;} /* * user level challenge/response */static intnetkeyauth(int fd){ char chall[32]; char resp[32]; strecpy(chall, chall+sizeof chall, getuser()); print("user[%s]: ", chall); if(readln(resp, sizeof(resp)) < 0) return -1; if(*resp != 0) strcpy(chall, resp); writestr(fd, chall, "challenge/response", 1); for(;;){ if(readstr(fd, chall, sizeof chall) < 0) break; if(*chall == 0) return fd; print("challenge: %s\nresponse: ", chall); if(readln(resp, sizeof(resp)) < 0) break; writestr(fd, resp, "challenge/response", 1); } return -1;} static intnetkeysrvauth(int fd, char *user){ 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 intp9auth(int fd){ uchar key[16]; uchar digest[SHA1dlen]; char fromclientsecret[21]; char fromserversecret[21]; int i; AuthInfo *ai; ai = p9any(fd); if(ai == nil) return -1; memmove(key+4, ai->secret, ai->nsecret); if(ealgs == nil) return fd; /* exchange random numbers */ for(i = 0; i < 4; i++) key[i] = fastrand(); if(write(fd, key, 4) != 4) return -1; if(readn(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, fromclientsecret, fromserversecret, nil); if(i < 0) werrstr("can't establish ssl connection: %r"); return i;} intauthdial(char *net, char *dom){ int fd; fd = dial(netmkaddr(authserver, "tcp", "567"), 0, 0, 0); //print("authdial %d\n", fd); return fd;} static intgetastickets(Ticketreq *tr, char *trbuf, char *tbuf){ int asfd, rv; char *dom; dom = tr->authdom; asfd = authdial(nil, dom); if(asfd < 0) return -1; rv = _asgetticket(asfd, trbuf, tbuf); close(asfd); return rv;} static intmkserverticket(Ticketreq *tr, char *authkey, char *tbuf){ int i; Ticket t; if(strcmp(tr->authid, tr->hostid) != 0) return -1; memset(&t, 0, sizeof(t)); memmove(t.chal, tr->chal, CHALLEN); strcpy(t.cuid, tr->uid); strcpy(t.suid, tr->uid); for(i=0; i<DESKEYLEN; i++) t.key[i] = fastrand(); t.num = AuthTc; convT2M(&t, tbuf, authkey); t.num = AuthTs; convT2M(&t, tbuf+TICKETLEN, authkey); return 0;} static intgettickets(Ticketreq *tr, char *key, char *trbuf, char *tbuf){ if(getastickets(tr, trbuf, tbuf) >= 0) return 0; return mkserverticket(tr, key, tbuf);} /* * prompt user for a key. don't care about memory leaks, runs standalone */static Attr*promptforkey(char *params){ char *v; int fd; Attr *a, *attr; char *def; fd = open("/dev/cons", ORDWR); if(fd < 0) sysfatal("opening /dev/cons: %r"); attr = _parseattr(params); fprint(fd, "\n!Adding key:"); for(a=attr; a; a=a->next) if(a->type != AttrQuery && a->name[0] != '!') fprint(fd, " %q=%q", a->name, a->val); fprint(fd, "\n"); for(a=attr; a; a=a->next){ v = a->name; if(a->type != AttrQuery || v[0]=='!') continue; def = nil; if(strcmp(v, "user") == 0) def = getuser(); a->val = readcons(v, def, 0); if(a->val == nil) sysfatal("user terminated key input"); a->type = AttrNameval; } for(a=attr; a; a=a->next){ v = a->name; if(a->type != AttrQuery || v[0]!='!') continue; def = nil; if(strcmp(v+1, "user") == 0) def = getuser(); a->val = readcons(v+1, def, 1); if(a->val == nil)Lines 1–500 of 732. Load more
/* * cpu.c - Make a connection to a cpu server * * Invoked by listen as 'cpu -R | -N service net netdir' * by users as 'cpu [-h system] [-c cmd args ...]' */ #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 Maxfdata 8192 #define MaxStr 128 static void fatal(int, char*, ...); static void usage(void); static void writestr(int, char*, char*, int); static int readstr(int, char*, int); static char *rexcall(int*, char*, char*); static char *keyspec = ""; static AuthInfo *p9any(int); #define system csystem static char *system; static int cflag; extern int dbg; extern char* base; // fs base for devroot static char *srvname = "ncpu"; static char *ealgs = "rc4_256 sha1"; /* message size for exportfs; may be larger so we can do big graphics in CPU window */ static int msgsize = Maxfdata+IOHDRSZ; /* authentication mechanisms */ static int netkeyauth(int); static int netkeysrvauth(int, char*); static int p9auth(int); static int srvp9auth(int, char*); char *authserver; typedef struct AuthMethod AuthMethod; struct AuthMethod { char *name; /* name of method */ int (*cf)(int); /* client side authentication */ int (*sf)(int, char*); /* server side authentication */ } authmethod[] = { { "p9", p9auth, srvp9auth,}, { "netkey", netkeyauth, netkeysrvauth,}, // { "none", noauth, srvnoauth,}, { 0 } }; AuthMethod *am = authmethod; /* default is p9 */ char *p9authproto = "p9any"; int setam(char*); void exits(char *s) { print("\ngoodbye\n"); for(;;) osyield(); } void usage(void) { fprint(2, "usage: drawterm [-a authserver] [-c cpuserver] [-s secstore] [-u user]\n"); exits("usage"); } int fdd; 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; } void cpumain(int argc, char **argv) { char dat[MaxStr], buf[MaxStr], cmd[MaxStr], *err, *secstoreserver, *p, *s; int fd, ms, data; /* see if we should use a larger message size */ fd = open("/dev/draw", OREAD); if(fd > 0){ ms = iounit(fd); if(msgsize < ms+IOHDRSZ) msgsize = ms+IOHDRSZ; close(fd); } user = getenv("USER"); secstoreserver = nil; authserver = getenv("auth"); if(authserver == nil) authserver = "auth"; system = getenv("cpu"); if(system == nil) system = "cpu"; ARGBEGIN{ case 'a': authserver = EARGF(usage()); break; case 'c': system = EARGF(usage()); break; case 'd': dbg++; break; case 'e': ealgs = EARGF(usage()); if(*ealgs == 0 || strcmp(ealgs, "clear") == 0) ealgs = nil; break; case 'C': cflag++; cmd[0] = '!'; cmd[1] = '\0'; while((p = ARGF()) != nil) { strcat(cmd, " "); strcat(cmd, p); } break; case 'k': keyspec = EARGF(usage()); break; case 'r': base = EARGF(usage()); break; case 's': secstoreserver = EARGF(usage()); break; case 'u': user = EARGF(usage()); break; default: usage(); }ARGEND; if(argc != 0) usage(); if(user == nil) user = readcons("user", nil, 0); if(mountfactotum() < 0){ if(secstoreserver == nil) secstoreserver = authserver; if(havesecstore(secstoreserver, user)){ s = secstorefetch(secstoreserver, user, nil); if(s){ if(strlen(s) >= sizeof secstorebuf) sysfatal("secstore data too big"); strcpy(secstorebuf, s); } } } if((err = rexcall(&data, system, srvname))) fatal(1, "%s: %s", err, system); /* Tell the remote side the command to execute and where our working directory is */ if(cflag) writestr(data, cmd, "command", 0); if(getcwd(dat, sizeof(dat)) == 0) writestr(data, "NO", "dir", 0); else writestr(data, dat, "dir", 0); /* * Wait for the other end to execute and start our file service * of /mnt/term */ if(readstr(data, buf, sizeof(buf)) < 0) fatal(1, "waiting for FS: %r"); if(strncmp("FS", buf, 2) != 0) { print("remote cpu: %s", buf); exits(buf); } if(readstr(data, buf, sizeof buf) < 0) fatal(1, "waiting for remote export: %r"); if(strcmp(buf, "/") != 0){ print("remote cpu: %s" , buf); exits(buf); } write(data, "OK", 2); /* Begin serving the gnot namespace */ exportfs(data, msgsize); fatal(1, "starting exportfs"); } void fatal(int syserr, char *fmt, ...) { Fmt f; char *str; va_list arg; fmtstrinit(&f); fmtprint(&f, "cpu: "); va_start(arg, fmt); fmtvprint(&f, fmt, arg); va_end(arg); if(syserr) fmtprint(&f, ": %r"); fmtprint(&f, "\n"); str = fmtstrflush(&f); write(2, str, strlen(str)); exits(str); } char *negstr = "negotiating authentication method"; char bug[256]; char* rexcall(int *fd, char *host, char *service) { char *na; char dir[MaxStr]; char err[ERRMAX]; char msg[MaxStr]; int n; na = netmkaddr(host, "tcp", "17010"); if((*fd = dial(na, 0, dir, 0)) < 0) return "can't dial"; /* negotiate authentication mechanism */ if(ealgs != nil) snprint(msg, sizeof(msg), "%s %s", am->name, ealgs); else snprint(msg, sizeof(msg), "%s", am->name); writestr(*fd, msg, negstr, 0); n = readstr(*fd, err, sizeof err); if(n < 0) return negstr; if(*err){ werrstr(err); return negstr; } /* authenticate */ *fd = (*am->cf)(*fd); if(*fd < 0) return "can't authenticate"; return 0; } 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) fatal(1, "writing network: %s", 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 int readln(char *buf, int n) { int i; char *p; n--; /* room for \0 */ p = buf; for(i=0; i<n; i++){ if(read(0, p, 1) != 1) break; if(*p == '\n' || *p == '\r') break; p++; } *p = '\0'; return p-buf; } /* * user level challenge/response */ static int netkeyauth(int fd) { char chall[32]; char resp[32]; strecpy(chall, chall+sizeof chall, getuser()); print("user[%s]: ", chall); if(readln(resp, sizeof(resp)) < 0) return -1; if(*resp != 0) strcpy(chall, resp); writestr(fd, chall, "challenge/response", 1); for(;;){ if(readstr(fd, chall, sizeof chall) < 0) break; if(*chall == 0) return fd; print("challenge: %s\nresponse: ", chall); if(readln(resp, sizeof(resp)) < 0) break; writestr(fd, resp, "challenge/response", 1); } return -1; } static int netkeysrvauth(int fd, char *user) { 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 p9auth(int fd) { uchar key[16]; uchar digest[SHA1dlen]; char fromclientsecret[21]; char fromserversecret[21]; int i; AuthInfo *ai; ai = p9any(fd); if(ai == nil) return -1; memmove(key+4, ai->secret, ai->nsecret); if(ealgs == nil) return fd; /* exchange random numbers */ for(i = 0; i < 4; i++) key[i] = fastrand(); if(write(fd, key, 4) != 4) return -1; if(readn(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, fromclientsecret, fromserversecret, nil); if(i < 0) werrstr("can't establish ssl connection: %r"); return i; } int authdial(char *net, char *dom) { int fd; fd = dial(netmkaddr(authserver, "tcp", "567"), 0, 0, 0); //print("authdial %d\n", fd); return fd; } static int getastickets(Ticketreq *tr, char *trbuf, char *tbuf) { int asfd, rv; char *dom; dom = tr->authdom; asfd = authdial(nil, dom); if(asfd < 0) return -1; rv = _asgetticket(asfd, trbuf, tbuf); close(asfd); return rv; } static int mkserverticket(Ticketreq *tr, char *authkey, char *tbuf) { int i; Ticket t; if(strcmp(tr->authid, tr->hostid) != 0) return -1; memset(&t, 0, sizeof(t)); memmove(t.chal, tr->chal, CHALLEN); strcpy(t.cuid, tr->uid); strcpy(t.suid, tr->uid); for(i=0; i<DESKEYLEN; i++) t.key[i] = fastrand(); t.num = AuthTc; convT2M(&t, tbuf, authkey); t.num = AuthTs; convT2M(&t, tbuf+TICKETLEN, authkey); return 0; } static int gettickets(Ticketreq *tr, char *key, char *trbuf, char *tbuf) { if(getastickets(tr, trbuf, tbuf) >= 0) return 0; return mkserverticket(tr, key, tbuf); } /* * prompt user for a key. don't care about memory leaks, runs standalone */ static Attr* promptforkey(char *params) { char *v; int fd; Attr *a, *attr; char *def; fd = open("/dev/cons", ORDWR); if(fd < 0) sysfatal("opening /dev/cons: %r"); attr = _parseattr(params); fprint(fd, "\n!Adding key:"); for(a=attr; a; a=a->next) if(a->type != AttrQuery && a->name[0] != '!') fprint(fd, " %q=%q", a->name, a->val); fprint(fd, "\n"); for(a=attr; a; a=a->next){ v = a->name; if(a->type != AttrQuery || v[0]=='!') continue; def = nil; if(strcmp(v, "user") == 0) def = getuser(); a->val = readcons(v, def, 0); if(a->val == nil) sysfatal("user terminated key input"); a->type = AttrNameval; } for(a=attr; a; a=a->next){ v = a->name; if(a->type != AttrQuery || v[0]!='!') continue; def = nil; if(strcmp(v+1, "user") == 0) def = getuser(); a->val = readcons(v+1, def, 1); if(a->val == nil)