1*8ccd4a63SDavid du Colombier /* 2*8ccd4a63SDavid du Colombier * cpu.c - Make a connection to a cpu server 3*8ccd4a63SDavid du Colombier * 4*8ccd4a63SDavid du Colombier * Invoked by listen as 'cpu -R | -N service net netdir' 5*8ccd4a63SDavid du Colombier * by users as 'cpu [-h system] [-c cmd args ...]' 6*8ccd4a63SDavid du Colombier */ 7*8ccd4a63SDavid du Colombier 8*8ccd4a63SDavid du Colombier #include <u.h> 9*8ccd4a63SDavid du Colombier #include <libc.h> 10*8ccd4a63SDavid du Colombier #include <auth.h> 11*8ccd4a63SDavid du Colombier #include <fcall.h> 12*8ccd4a63SDavid du Colombier #include <authsrv.h> 13*8ccd4a63SDavid du Colombier #include <libsec.h> 14*8ccd4a63SDavid du Colombier #include "args.h" 15*8ccd4a63SDavid du Colombier #include "drawterm.h" 16*8ccd4a63SDavid du Colombier 17*8ccd4a63SDavid du Colombier #define Maxfdata 8192 18*8ccd4a63SDavid du Colombier #define MaxStr 128 19*8ccd4a63SDavid du Colombier 20*8ccd4a63SDavid du Colombier static void fatal(int, char*, ...); 21*8ccd4a63SDavid du Colombier static void usage(void); 22*8ccd4a63SDavid du Colombier static void writestr(int, char*, char*, int); 23*8ccd4a63SDavid du Colombier static int readstr(int, char*, int); 24*8ccd4a63SDavid du Colombier static char *rexcall(int*, char*, char*); 25*8ccd4a63SDavid du Colombier static char *keyspec = ""; 26*8ccd4a63SDavid du Colombier static AuthInfo *p9any(int); 27*8ccd4a63SDavid du Colombier 28*8ccd4a63SDavid du Colombier #define system csystem 29*8ccd4a63SDavid du Colombier static char *system; 30*8ccd4a63SDavid du Colombier static int cflag; 31*8ccd4a63SDavid du Colombier extern int dbg; 32*8ccd4a63SDavid du Colombier 33*8ccd4a63SDavid du Colombier static char *srvname = "ncpu"; 34*8ccd4a63SDavid du Colombier static char *ealgs = "rc4_256 sha1"; 35*8ccd4a63SDavid du Colombier 36*8ccd4a63SDavid du Colombier /* message size for exportfs; may be larger so we can do big graphics in CPU window */ 37*8ccd4a63SDavid du Colombier static int msgsize = Maxfdata+IOHDRSZ; 38*8ccd4a63SDavid du Colombier 39*8ccd4a63SDavid du Colombier /* authentication mechanisms */ 40*8ccd4a63SDavid du Colombier static int netkeyauth(int); 41*8ccd4a63SDavid du Colombier static int netkeysrvauth(int, char*); 42*8ccd4a63SDavid du Colombier static int p9auth(int); 43*8ccd4a63SDavid du Colombier static int srvp9auth(int, char*); 44*8ccd4a63SDavid du Colombier 45*8ccd4a63SDavid du Colombier char *authserver; 46*8ccd4a63SDavid du Colombier 47*8ccd4a63SDavid du Colombier typedef struct AuthMethod AuthMethod; 48*8ccd4a63SDavid du Colombier struct AuthMethod { 49*8ccd4a63SDavid du Colombier char *name; /* name of method */ 50*8ccd4a63SDavid du Colombier int (*cf)(int); /* client side authentication */ 51*8ccd4a63SDavid du Colombier int (*sf)(int, char*); /* server side authentication */ 52*8ccd4a63SDavid du Colombier } authmethod[] = 53*8ccd4a63SDavid du Colombier { 54*8ccd4a63SDavid du Colombier { "p9", p9auth, srvp9auth,}, 55*8ccd4a63SDavid du Colombier { "netkey", netkeyauth, netkeysrvauth,}, 56*8ccd4a63SDavid du Colombier // { "none", noauth, srvnoauth,}, 57*8ccd4a63SDavid du Colombier { nil, nil} 58*8ccd4a63SDavid du Colombier }; 59*8ccd4a63SDavid du Colombier AuthMethod *am = authmethod; /* default is p9 */ 60*8ccd4a63SDavid du Colombier 61*8ccd4a63SDavid du Colombier char *p9authproto = "p9any"; 62*8ccd4a63SDavid du Colombier 63*8ccd4a63SDavid du Colombier int setam(char*); 64*8ccd4a63SDavid du Colombier 65*8ccd4a63SDavid du Colombier void 66*8ccd4a63SDavid du Colombier exits(char *s) 67*8ccd4a63SDavid du Colombier { 68*8ccd4a63SDavid du Colombier print("\ngoodbye\n"); 69*8ccd4a63SDavid du Colombier for(;;) osyield(); 70*8ccd4a63SDavid du Colombier } 71*8ccd4a63SDavid du Colombier 72*8ccd4a63SDavid du Colombier void 73*8ccd4a63SDavid du Colombier usage(void) 74*8ccd4a63SDavid du Colombier { 75*8ccd4a63SDavid du Colombier fprint(2, "usage: drawterm [-a authserver] [-c cpuserver] [-s secstore] [-u user]\n"); 76*8ccd4a63SDavid du Colombier exits("usage"); 77*8ccd4a63SDavid du Colombier } 78*8ccd4a63SDavid du Colombier int fdd; 79*8ccd4a63SDavid du Colombier 80*8ccd4a63SDavid du Colombier int 81*8ccd4a63SDavid du Colombier mountfactotum(void) 82*8ccd4a63SDavid du Colombier { 83*8ccd4a63SDavid du Colombier int fd; 84*8ccd4a63SDavid du Colombier 85*8ccd4a63SDavid du Colombier if((fd = dialfactotum()) < 0) 86*8ccd4a63SDavid du Colombier return -1; 87*8ccd4a63SDavid du Colombier if(sysmount(fd, -1, "/mnt/factotum", MREPL, "") < 0){ 88*8ccd4a63SDavid du Colombier fprint(2, "mount factotum: %r\n"); 89*8ccd4a63SDavid du Colombier return -1; 90*8ccd4a63SDavid du Colombier } 91*8ccd4a63SDavid du Colombier if((fd = open("/mnt/factotum/ctl", OREAD)) < 0){ 92*8ccd4a63SDavid du Colombier fprint(2, "open /mnt/factotum/ctl: %r\n"); 93*8ccd4a63SDavid du Colombier return -1; 94*8ccd4a63SDavid du Colombier } 95*8ccd4a63SDavid du Colombier close(fd); 96*8ccd4a63SDavid du Colombier return 0; 97*8ccd4a63SDavid du Colombier } 98*8ccd4a63SDavid du Colombier 99*8ccd4a63SDavid du Colombier void 100*8ccd4a63SDavid du Colombier cpumain(int argc, char **argv) 101*8ccd4a63SDavid du Colombier { 102*8ccd4a63SDavid du Colombier char dat[MaxStr], buf[MaxStr], cmd[MaxStr], *err, *secstoreserver, *p, *s; 103*8ccd4a63SDavid du Colombier int fd, ms, data; 104*8ccd4a63SDavid du Colombier 105*8ccd4a63SDavid du Colombier /* see if we should use a larger message size */ 106*8ccd4a63SDavid du Colombier fd = open("/dev/draw", OREAD); 107*8ccd4a63SDavid du Colombier if(fd > 0){ 108*8ccd4a63SDavid du Colombier ms = iounit(fd); 109*8ccd4a63SDavid du Colombier if(msgsize < ms+IOHDRSZ) 110*8ccd4a63SDavid du Colombier msgsize = ms+IOHDRSZ; 111*8ccd4a63SDavid du Colombier close(fd); 112*8ccd4a63SDavid du Colombier } 113*8ccd4a63SDavid du Colombier 114*8ccd4a63SDavid du Colombier user = getenv("USER"); 115*8ccd4a63SDavid du Colombier if(user == nil) 116*8ccd4a63SDavid du Colombier user = readcons("user", nil, 0); 117*8ccd4a63SDavid du Colombier secstoreserver = nil; 118*8ccd4a63SDavid du Colombier authserver = getenv("auth"); 119*8ccd4a63SDavid du Colombier if(authserver == nil) 120*8ccd4a63SDavid du Colombier authserver = "lookout.cs.bell-labs.com"; 121*8ccd4a63SDavid du Colombier system = getenv("cpu"); 122*8ccd4a63SDavid du Colombier if(system == nil) 123*8ccd4a63SDavid du Colombier system = "anna.cs.bell-labs.com"; 124*8ccd4a63SDavid du Colombier ARGBEGIN{ 125*8ccd4a63SDavid du Colombier case 'o': 126*8ccd4a63SDavid du Colombier authserver = "plan9.bell-labs.com"; 127*8ccd4a63SDavid du Colombier system = "plan9.bell-labs.com"; 128*8ccd4a63SDavid du Colombier break; 129*8ccd4a63SDavid du Colombier case 'a': 130*8ccd4a63SDavid du Colombier authserver = EARGF(usage()); 131*8ccd4a63SDavid du Colombier break; 132*8ccd4a63SDavid du Colombier case 'c': 133*8ccd4a63SDavid du Colombier system = EARGF(usage()); 134*8ccd4a63SDavid du Colombier break; 135*8ccd4a63SDavid du Colombier case 'd': 136*8ccd4a63SDavid du Colombier dbg++; 137*8ccd4a63SDavid du Colombier break; 138*8ccd4a63SDavid du Colombier case 'e': 139*8ccd4a63SDavid du Colombier ealgs = EARGF(usage()); 140*8ccd4a63SDavid du Colombier if(*ealgs == 0 || strcmp(ealgs, "clear") == 0) 141*8ccd4a63SDavid du Colombier ealgs = nil; 142*8ccd4a63SDavid du Colombier break; 143*8ccd4a63SDavid du Colombier case 'C': 144*8ccd4a63SDavid du Colombier cflag++; 145*8ccd4a63SDavid du Colombier cmd[0] = '!'; 146*8ccd4a63SDavid du Colombier cmd[1] = '\0'; 147*8ccd4a63SDavid du Colombier while((p = ARGF()) != nil) { 148*8ccd4a63SDavid du Colombier strcat(cmd, " "); 149*8ccd4a63SDavid du Colombier strcat(cmd, p); 150*8ccd4a63SDavid du Colombier } 151*8ccd4a63SDavid du Colombier break; 152*8ccd4a63SDavid du Colombier case 'k': 153*8ccd4a63SDavid du Colombier keyspec = EARGF(usage()); 154*8ccd4a63SDavid du Colombier break; 155*8ccd4a63SDavid du Colombier case 'u': 156*8ccd4a63SDavid du Colombier user = EARGF(usage()); 157*8ccd4a63SDavid du Colombier break; 158*8ccd4a63SDavid du Colombier case 's': 159*8ccd4a63SDavid du Colombier secstoreserver = EARGF(usage()); 160*8ccd4a63SDavid du Colombier break; 161*8ccd4a63SDavid du Colombier default: 162*8ccd4a63SDavid du Colombier usage(); 163*8ccd4a63SDavid du Colombier }ARGEND; 164*8ccd4a63SDavid du Colombier 165*8ccd4a63SDavid du Colombier if(argc != 0) 166*8ccd4a63SDavid du Colombier usage(); 167*8ccd4a63SDavid du Colombier 168*8ccd4a63SDavid du Colombier if(mountfactotum() < 0){ 169*8ccd4a63SDavid du Colombier if(secstoreserver == nil) 170*8ccd4a63SDavid du Colombier secstoreserver = authserver; 171*8ccd4a63SDavid du Colombier if(havesecstore(secstoreserver, user)){ 172*8ccd4a63SDavid du Colombier s = secstorefetch(secstoreserver, user, nil); 173*8ccd4a63SDavid du Colombier if(s){ 174*8ccd4a63SDavid du Colombier if(strlen(s) >= sizeof secstorebuf) 175*8ccd4a63SDavid du Colombier sysfatal("secstore data too big"); 176*8ccd4a63SDavid du Colombier strcpy(secstorebuf, s); 177*8ccd4a63SDavid du Colombier } 178*8ccd4a63SDavid du Colombier } 179*8ccd4a63SDavid du Colombier } 180*8ccd4a63SDavid du Colombier 181*8ccd4a63SDavid du Colombier if((err = rexcall(&data, system, srvname))) 182*8ccd4a63SDavid du Colombier fatal(1, "%s: %s", err, system); 183*8ccd4a63SDavid du Colombier 184*8ccd4a63SDavid du Colombier /* Tell the remote side the command to execute and where our working directory is */ 185*8ccd4a63SDavid du Colombier if(cflag) 186*8ccd4a63SDavid du Colombier writestr(data, cmd, "command", 0); 187*8ccd4a63SDavid du Colombier if(getcwd(dat, sizeof(dat)) == 0) 188*8ccd4a63SDavid du Colombier writestr(data, "NO", "dir", 0); 189*8ccd4a63SDavid du Colombier else 190*8ccd4a63SDavid du Colombier writestr(data, dat, "dir", 0); 191*8ccd4a63SDavid du Colombier 192*8ccd4a63SDavid du Colombier /* 193*8ccd4a63SDavid du Colombier * Wait for the other end to execute and start our file service 194*8ccd4a63SDavid du Colombier * of /mnt/term 195*8ccd4a63SDavid du Colombier */ 196*8ccd4a63SDavid du Colombier if(readstr(data, buf, sizeof(buf)) < 0) 197*8ccd4a63SDavid du Colombier fatal(1, "waiting for FS: %r"); 198*8ccd4a63SDavid du Colombier if(strncmp("FS", buf, 2) != 0) { 199*8ccd4a63SDavid du Colombier print("remote cpu: %s", buf); 200*8ccd4a63SDavid du Colombier exits(buf); 201*8ccd4a63SDavid du Colombier } 202*8ccd4a63SDavid du Colombier 203*8ccd4a63SDavid du Colombier if(readstr(data, buf, sizeof buf) < 0) 204*8ccd4a63SDavid du Colombier fatal(1, "waiting for remote export: %r"); 205*8ccd4a63SDavid du Colombier if(strcmp(buf, "/") != 0){ 206*8ccd4a63SDavid du Colombier print("remote cpu: %s" , buf); 207*8ccd4a63SDavid du Colombier exits(buf); 208*8ccd4a63SDavid du Colombier } 209*8ccd4a63SDavid du Colombier write(data, "OK", 2); 210*8ccd4a63SDavid du Colombier 211*8ccd4a63SDavid du Colombier /* Begin serving the gnot namespace */ 212*8ccd4a63SDavid du Colombier exportfs(data, msgsize); 213*8ccd4a63SDavid du Colombier fatal(1, "starting exportfs"); 214*8ccd4a63SDavid du Colombier } 215*8ccd4a63SDavid du Colombier 216*8ccd4a63SDavid du Colombier void 217*8ccd4a63SDavid du Colombier fatal(int syserr, char *fmt, ...) 218*8ccd4a63SDavid du Colombier { 219*8ccd4a63SDavid du Colombier Fmt f; 220*8ccd4a63SDavid du Colombier char *str; 221*8ccd4a63SDavid du Colombier va_list arg; 222*8ccd4a63SDavid du Colombier 223*8ccd4a63SDavid du Colombier fmtstrinit(&f); 224*8ccd4a63SDavid du Colombier fmtprint(&f, "cpu: "); 225*8ccd4a63SDavid du Colombier va_start(arg, fmt); 226*8ccd4a63SDavid du Colombier fmtvprint(&f, fmt, arg); 227*8ccd4a63SDavid du Colombier va_end(arg); 228*8ccd4a63SDavid du Colombier if(syserr) 229*8ccd4a63SDavid du Colombier fmtprint(&f, ": %r"); 230*8ccd4a63SDavid du Colombier fmtprint(&f, "\n"); 231*8ccd4a63SDavid du Colombier str = fmtstrflush(&f); 232*8ccd4a63SDavid du Colombier write(2, str, strlen(str)); 233*8ccd4a63SDavid du Colombier exits(str); 234*8ccd4a63SDavid du Colombier } 235*8ccd4a63SDavid du Colombier 236*8ccd4a63SDavid du Colombier char *negstr = "negotiating authentication method"; 237*8ccd4a63SDavid du Colombier 238*8ccd4a63SDavid du Colombier char bug[256]; 239*8ccd4a63SDavid du Colombier 240*8ccd4a63SDavid du Colombier char* 241*8ccd4a63SDavid du Colombier rexcall(int *fd, char *host, char *service) 242*8ccd4a63SDavid du Colombier { 243*8ccd4a63SDavid du Colombier char *na; 244*8ccd4a63SDavid du Colombier char dir[MaxStr]; 245*8ccd4a63SDavid du Colombier char err[ERRMAX]; 246*8ccd4a63SDavid du Colombier char msg[MaxStr]; 247*8ccd4a63SDavid du Colombier int n; 248*8ccd4a63SDavid du Colombier 249*8ccd4a63SDavid du Colombier na = netmkaddr(host, "tcp", "17010"); 250*8ccd4a63SDavid du Colombier if((*fd = dial(na, 0, dir, 0)) < 0) 251*8ccd4a63SDavid du Colombier return "can't dial"; 252*8ccd4a63SDavid du Colombier 253*8ccd4a63SDavid du Colombier /* negotiate authentication mechanism */ 254*8ccd4a63SDavid du Colombier if(ealgs != nil) 255*8ccd4a63SDavid du Colombier snprint(msg, sizeof(msg), "%s %s", am->name, ealgs); 256*8ccd4a63SDavid du Colombier else 257*8ccd4a63SDavid du Colombier snprint(msg, sizeof(msg), "%s", am->name); 258*8ccd4a63SDavid du Colombier writestr(*fd, msg, negstr, 0); 259*8ccd4a63SDavid du Colombier n = readstr(*fd, err, sizeof err); 260*8ccd4a63SDavid du Colombier if(n < 0) 261*8ccd4a63SDavid du Colombier return negstr; 262*8ccd4a63SDavid du Colombier if(*err){ 263*8ccd4a63SDavid du Colombier werrstr(err); 264*8ccd4a63SDavid du Colombier return negstr; 265*8ccd4a63SDavid du Colombier } 266*8ccd4a63SDavid du Colombier 267*8ccd4a63SDavid du Colombier /* authenticate */ 268*8ccd4a63SDavid du Colombier *fd = (*am->cf)(*fd); 269*8ccd4a63SDavid du Colombier if(*fd < 0) 270*8ccd4a63SDavid du Colombier return "can't authenticate"; 271*8ccd4a63SDavid du Colombier return 0; 272*8ccd4a63SDavid du Colombier } 273*8ccd4a63SDavid du Colombier 274*8ccd4a63SDavid du Colombier void 275*8ccd4a63SDavid du Colombier writestr(int fd, char *str, char *thing, int ignore) 276*8ccd4a63SDavid du Colombier { 277*8ccd4a63SDavid du Colombier int l, n; 278*8ccd4a63SDavid du Colombier 279*8ccd4a63SDavid du Colombier l = strlen(str); 280*8ccd4a63SDavid du Colombier n = write(fd, str, l+1); 281*8ccd4a63SDavid du Colombier if(!ignore && n < 0) 282*8ccd4a63SDavid du Colombier fatal(1, "writing network: %s", thing); 283*8ccd4a63SDavid du Colombier } 284*8ccd4a63SDavid du Colombier 285*8ccd4a63SDavid du Colombier int 286*8ccd4a63SDavid du Colombier readstr(int fd, char *str, int len) 287*8ccd4a63SDavid du Colombier { 288*8ccd4a63SDavid du Colombier int n; 289*8ccd4a63SDavid du Colombier 290*8ccd4a63SDavid du Colombier while(len) { 291*8ccd4a63SDavid du Colombier n = read(fd, str, 1); 292*8ccd4a63SDavid du Colombier if(n < 0) 293*8ccd4a63SDavid du Colombier return -1; 294*8ccd4a63SDavid du Colombier if(*str == '\0') 295*8ccd4a63SDavid du Colombier return 0; 296*8ccd4a63SDavid du Colombier str++; 297*8ccd4a63SDavid du Colombier len--; 298*8ccd4a63SDavid du Colombier } 299*8ccd4a63SDavid du Colombier return -1; 300*8ccd4a63SDavid du Colombier } 301*8ccd4a63SDavid du Colombier 302*8ccd4a63SDavid du Colombier static int 303*8ccd4a63SDavid du Colombier readln(char *buf, int n) 304*8ccd4a63SDavid du Colombier { 305*8ccd4a63SDavid du Colombier int i; 306*8ccd4a63SDavid du Colombier char *p; 307*8ccd4a63SDavid du Colombier 308*8ccd4a63SDavid du Colombier n--; /* room for \0 */ 309*8ccd4a63SDavid du Colombier p = buf; 310*8ccd4a63SDavid du Colombier for(i=0; i<n; i++){ 311*8ccd4a63SDavid du Colombier if(read(0, p, 1) != 1) 312*8ccd4a63SDavid du Colombier break; 313*8ccd4a63SDavid du Colombier if(*p == '\n' || *p == '\r') 314*8ccd4a63SDavid du Colombier break; 315*8ccd4a63SDavid du Colombier p++; 316*8ccd4a63SDavid du Colombier } 317*8ccd4a63SDavid du Colombier *p = '\0'; 318*8ccd4a63SDavid du Colombier return p-buf; 319*8ccd4a63SDavid du Colombier } 320*8ccd4a63SDavid du Colombier 321*8ccd4a63SDavid du Colombier /* 322*8ccd4a63SDavid du Colombier * user level challenge/response 323*8ccd4a63SDavid du Colombier */ 324*8ccd4a63SDavid du Colombier static int 325*8ccd4a63SDavid du Colombier netkeyauth(int fd) 326*8ccd4a63SDavid du Colombier { 327*8ccd4a63SDavid du Colombier char chall[32]; 328*8ccd4a63SDavid du Colombier char resp[32]; 329*8ccd4a63SDavid du Colombier 330*8ccd4a63SDavid du Colombier strecpy(chall, chall+sizeof chall, getuser()); 331*8ccd4a63SDavid du Colombier print("user[%s]: ", chall); 332*8ccd4a63SDavid du Colombier if(readln(resp, sizeof(resp)) < 0) 333*8ccd4a63SDavid du Colombier return -1; 334*8ccd4a63SDavid du Colombier if(*resp != 0) 335*8ccd4a63SDavid du Colombier strcpy(chall, resp); 336*8ccd4a63SDavid du Colombier writestr(fd, chall, "challenge/response", 1); 337*8ccd4a63SDavid du Colombier 338*8ccd4a63SDavid du Colombier for(;;){ 339*8ccd4a63SDavid du Colombier if(readstr(fd, chall, sizeof chall) < 0) 340*8ccd4a63SDavid du Colombier break; 341*8ccd4a63SDavid du Colombier if(*chall == 0) 342*8ccd4a63SDavid du Colombier return fd; 343*8ccd4a63SDavid du Colombier print("challenge: %s\nresponse: ", chall); 344*8ccd4a63SDavid du Colombier if(readln(resp, sizeof(resp)) < 0) 345*8ccd4a63SDavid du Colombier break; 346*8ccd4a63SDavid du Colombier writestr(fd, resp, "challenge/response", 1); 347*8ccd4a63SDavid du Colombier } 348*8ccd4a63SDavid du Colombier return -1; 349*8ccd4a63SDavid du Colombier } 350*8ccd4a63SDavid du Colombier 351*8ccd4a63SDavid du Colombier static int 352*8ccd4a63SDavid du Colombier netkeysrvauth(int fd, char *user) 353*8ccd4a63SDavid du Colombier { 354*8ccd4a63SDavid du Colombier return -1; 355*8ccd4a63SDavid du Colombier } 356*8ccd4a63SDavid du Colombier 357*8ccd4a63SDavid du Colombier static void 358*8ccd4a63SDavid du Colombier mksecret(char *t, uchar *f) 359*8ccd4a63SDavid du Colombier { 360*8ccd4a63SDavid du Colombier sprint(t, "%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux", 361*8ccd4a63SDavid du Colombier f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7], f[8], f[9]); 362*8ccd4a63SDavid du Colombier } 363*8ccd4a63SDavid du Colombier 364*8ccd4a63SDavid du Colombier /* 365*8ccd4a63SDavid du Colombier * plan9 authentication followed by rc4 encryption 366*8ccd4a63SDavid du Colombier */ 367*8ccd4a63SDavid du Colombier static int 368*8ccd4a63SDavid du Colombier p9auth(int fd) 369*8ccd4a63SDavid du Colombier { 370*8ccd4a63SDavid du Colombier uchar key[16]; 371*8ccd4a63SDavid du Colombier uchar digest[SHA1dlen]; 372*8ccd4a63SDavid du Colombier char fromclientsecret[21]; 373*8ccd4a63SDavid du Colombier char fromserversecret[21]; 374*8ccd4a63SDavid du Colombier int i; 375*8ccd4a63SDavid du Colombier AuthInfo *ai; 376*8ccd4a63SDavid du Colombier 377*8ccd4a63SDavid du Colombier ai = p9any(fd); 378*8ccd4a63SDavid du Colombier if(ai == nil) 379*8ccd4a63SDavid du Colombier return -1; 380*8ccd4a63SDavid du Colombier memmove(key+4, ai->secret, ai->nsecret); 381*8ccd4a63SDavid du Colombier if(ealgs == nil) 382*8ccd4a63SDavid du Colombier return fd; 383*8ccd4a63SDavid du Colombier 384*8ccd4a63SDavid du Colombier /* exchange random numbers */ 385*8ccd4a63SDavid du Colombier for(i = 0; i < 4; i++) 386*8ccd4a63SDavid du Colombier key[i] = fastrand(); 387*8ccd4a63SDavid du Colombier if(write(fd, key, 4) != 4) 388*8ccd4a63SDavid du Colombier return -1; 389*8ccd4a63SDavid du Colombier if(readn(fd, key+12, 4) != 4) 390*8ccd4a63SDavid du Colombier return -1; 391*8ccd4a63SDavid du Colombier 392*8ccd4a63SDavid du Colombier /* scramble into two secrets */ 393*8ccd4a63SDavid du Colombier sha1(key, sizeof(key), digest, nil); 394*8ccd4a63SDavid du Colombier mksecret(fromclientsecret, digest); 395*8ccd4a63SDavid du Colombier mksecret(fromserversecret, digest+10); 396*8ccd4a63SDavid du Colombier 397*8ccd4a63SDavid du Colombier /* set up encryption */ 398*8ccd4a63SDavid du Colombier i = pushssl(fd, ealgs, fromclientsecret, fromserversecret, nil); 399*8ccd4a63SDavid du Colombier if(i < 0) 400*8ccd4a63SDavid du Colombier werrstr("can't establish ssl connection: %r"); 401*8ccd4a63SDavid du Colombier return i; 402*8ccd4a63SDavid du Colombier } 403*8ccd4a63SDavid du Colombier 404*8ccd4a63SDavid du Colombier int 405*8ccd4a63SDavid du Colombier authdial(char *net, char *dom) 406*8ccd4a63SDavid du Colombier { 407*8ccd4a63SDavid du Colombier int fd; 408*8ccd4a63SDavid du Colombier fd = dial(netmkaddr(authserver, "tcp", "567"), 0, 0, 0); 409*8ccd4a63SDavid du Colombier //print("authdial %d\n", fd); 410*8ccd4a63SDavid du Colombier return fd; 411*8ccd4a63SDavid du Colombier } 412*8ccd4a63SDavid du Colombier 413*8ccd4a63SDavid du Colombier static int 414*8ccd4a63SDavid du Colombier getastickets(Ticketreq *tr, char *trbuf, char *tbuf) 415*8ccd4a63SDavid du Colombier { 416*8ccd4a63SDavid du Colombier int asfd, rv; 417*8ccd4a63SDavid du Colombier char *dom; 418*8ccd4a63SDavid du Colombier 419*8ccd4a63SDavid du Colombier dom = tr->authdom; 420*8ccd4a63SDavid du Colombier asfd = authdial(nil, dom); 421*8ccd4a63SDavid du Colombier if(asfd < 0) 422*8ccd4a63SDavid du Colombier return -1; 423*8ccd4a63SDavid du Colombier rv = _asgetticket(asfd, trbuf, tbuf); 424*8ccd4a63SDavid du Colombier close(asfd); 425*8ccd4a63SDavid du Colombier return rv; 426*8ccd4a63SDavid du Colombier } 427*8ccd4a63SDavid du Colombier 428*8ccd4a63SDavid du Colombier static int 429*8ccd4a63SDavid du Colombier mkserverticket(Ticketreq *tr, char *authkey, char *tbuf) 430*8ccd4a63SDavid du Colombier { 431*8ccd4a63SDavid du Colombier int i; 432*8ccd4a63SDavid du Colombier Ticket t; 433*8ccd4a63SDavid du Colombier 434*8ccd4a63SDavid du Colombier if(strcmp(tr->authid, tr->hostid) != 0) 435*8ccd4a63SDavid du Colombier return -1; 436*8ccd4a63SDavid du Colombier memset(&t, 0, sizeof(t)); 437*8ccd4a63SDavid du Colombier memmove(t.chal, tr->chal, CHALLEN); 438*8ccd4a63SDavid du Colombier strcpy(t.cuid, tr->uid); 439*8ccd4a63SDavid du Colombier strcpy(t.suid, tr->uid); 440*8ccd4a63SDavid du Colombier for(i=0; i<DESKEYLEN; i++) 441*8ccd4a63SDavid du Colombier t.key[i] = fastrand(); 442*8ccd4a63SDavid du Colombier t.num = AuthTc; 443*8ccd4a63SDavid du Colombier convT2M(&t, tbuf, authkey); 444*8ccd4a63SDavid du Colombier t.num = AuthTs; 445*8ccd4a63SDavid du Colombier convT2M(&t, tbuf+TICKETLEN, authkey); 446*8ccd4a63SDavid du Colombier return 0; 447*8ccd4a63SDavid du Colombier } 448*8ccd4a63SDavid du Colombier 449*8ccd4a63SDavid du Colombier static int 450*8ccd4a63SDavid du Colombier gettickets(Ticketreq *tr, char *key, char *trbuf, char *tbuf) 451*8ccd4a63SDavid du Colombier { 452*8ccd4a63SDavid du Colombier if(getastickets(tr, trbuf, tbuf) >= 0) 453*8ccd4a63SDavid du Colombier return 0; 454*8ccd4a63SDavid du Colombier return mkserverticket(tr, key, tbuf); 455*8ccd4a63SDavid du Colombier } 456*8ccd4a63SDavid du Colombier 457*8ccd4a63SDavid du Colombier /* 458*8ccd4a63SDavid du Colombier * prompt user for a key. don't care about memory leaks, runs standalone 459*8ccd4a63SDavid du Colombier */ 460*8ccd4a63SDavid du Colombier static Attr* 461*8ccd4a63SDavid du Colombier promptforkey(char *params) 462*8ccd4a63SDavid du Colombier { 463*8ccd4a63SDavid du Colombier char *v; 464*8ccd4a63SDavid du Colombier int fd; 465*8ccd4a63SDavid du Colombier Attr *a, *attr; 466*8ccd4a63SDavid du Colombier char *def; 467*8ccd4a63SDavid du Colombier 468*8ccd4a63SDavid du Colombier fd = open("/dev/cons", ORDWR); 469*8ccd4a63SDavid du Colombier if(fd < 0) 470*8ccd4a63SDavid du Colombier sysfatal("opening /dev/cons: %r"); 471*8ccd4a63SDavid du Colombier 472*8ccd4a63SDavid du Colombier attr = _parseattr(params); 473*8ccd4a63SDavid du Colombier fprint(fd, "\n!Adding key:"); 474*8ccd4a63SDavid du Colombier for(a=attr; a; a=a->next) 475*8ccd4a63SDavid du Colombier if(a->type != AttrQuery && a->name[0] != '!') 476*8ccd4a63SDavid du Colombier fprint(fd, " %q=%q", a->name, a->val); 477*8ccd4a63SDavid du Colombier fprint(fd, "\n"); 478*8ccd4a63SDavid du Colombier 479*8ccd4a63SDavid du Colombier for(a=attr; a; a=a->next){ 480*8ccd4a63SDavid du Colombier v = a->name; 481*8ccd4a63SDavid du Colombier if(a->type != AttrQuery || v[0]=='!') 482*8ccd4a63SDavid du Colombier continue; 483*8ccd4a63SDavid du Colombier def = nil; 484*8ccd4a63SDavid du Colombier if(strcmp(v, "user") == 0) 485*8ccd4a63SDavid du Colombier def = getuser(); 486*8ccd4a63SDavid du Colombier a->val = readcons(v, def, 0); 487*8ccd4a63SDavid du Colombier if(a->val == nil) 488*8ccd4a63SDavid du Colombier sysfatal("user terminated key input"); 489*8ccd4a63SDavid du Colombier a->type = AttrNameval; 490*8ccd4a63SDavid du Colombier } 491*8ccd4a63SDavid du Colombier for(a=attr; a; a=a->next){ 492*8ccd4a63SDavid du Colombier v = a->name; 493*8ccd4a63SDavid du Colombier if(a->type != AttrQuery || v[0]!='!') 494*8ccd4a63SDavid du Colombier continue; 495*8ccd4a63SDavid du Colombier def = nil; 496*8ccd4a63SDavid du Colombier if(strcmp(v+1, "user") == 0) 497*8ccd4a63SDavid du Colombier def = getuser(); 498*8ccd4a63SDavid du Colombier a->val = readcons(v+1, def, 1); 499*8ccd4a63SDavid du Colombier if(a->val == nil) 500*8ccd4a63SDavid du Colombier sysfatal("user terminated key input"); 501*8ccd4a63SDavid du Colombier a->type = AttrNameval; 502*8ccd4a63SDavid du Colombier } 503*8ccd4a63SDavid du Colombier fprint(fd, "!\n"); 504*8ccd4a63SDavid du Colombier close(fd); 505*8ccd4a63SDavid du Colombier return attr; 506*8ccd4a63SDavid du Colombier } 507*8ccd4a63SDavid du Colombier 508*8ccd4a63SDavid du Colombier /* 509*8ccd4a63SDavid du Colombier * send a key to the mounted factotum 510*8ccd4a63SDavid du Colombier */ 511*8ccd4a63SDavid du Colombier static int 512*8ccd4a63SDavid du Colombier sendkey(Attr *attr) 513*8ccd4a63SDavid du Colombier { 514*8ccd4a63SDavid du Colombier int fd, rv; 515*8ccd4a63SDavid du Colombier char buf[1024]; 516*8ccd4a63SDavid du Colombier 517*8ccd4a63SDavid du Colombier fd = open("/mnt/factotum/ctl", ORDWR); 518*8ccd4a63SDavid du Colombier if(fd < 0) 519*8ccd4a63SDavid du Colombier sysfatal("opening /mnt/factotum/ctl: %r"); 520*8ccd4a63SDavid du Colombier rv = fprint(fd, "key %A\n", attr); 521*8ccd4a63SDavid du Colombier read(fd, buf, sizeof buf); 522*8ccd4a63SDavid du Colombier close(fd); 523*8ccd4a63SDavid du Colombier return rv; 524*8ccd4a63SDavid du Colombier } 525*8ccd4a63SDavid du Colombier 526*8ccd4a63SDavid du Colombier int 527*8ccd4a63SDavid du Colombier askuser(char *params) 528*8ccd4a63SDavid du Colombier { 529*8ccd4a63SDavid du Colombier Attr *attr; 530*8ccd4a63SDavid du Colombier 531*8ccd4a63SDavid du Colombier fmtinstall('A', _attrfmt); 532*8ccd4a63SDavid du Colombier 533*8ccd4a63SDavid du Colombier attr = promptforkey(params); 534*8ccd4a63SDavid du Colombier if(attr == nil) 535*8ccd4a63SDavid du Colombier sysfatal("no key supplied"); 536*8ccd4a63SDavid du Colombier if(sendkey(attr) < 0) 537*8ccd4a63SDavid du Colombier sysfatal("sending key to factotum: %r"); 538*8ccd4a63SDavid du Colombier return 0; 539*8ccd4a63SDavid du Colombier } 540*8ccd4a63SDavid du Colombier 541*8ccd4a63SDavid du Colombier AuthInfo* 542*8ccd4a63SDavid du Colombier p9anyfactotum(int fd, int afd) 543*8ccd4a63SDavid du Colombier { 544*8ccd4a63SDavid du Colombier return auth_proxy(fd, askuser, "proto=p9any role=client %s", keyspec); 545*8ccd4a63SDavid du Colombier } 546*8ccd4a63SDavid du Colombier 547*8ccd4a63SDavid du Colombier AuthInfo* 548*8ccd4a63SDavid du Colombier p9any(int fd) 549*8ccd4a63SDavid du Colombier { 550*8ccd4a63SDavid du Colombier char buf[1024], buf2[1024], cchal[CHALLEN], *bbuf, *p, *dom, *u; 551*8ccd4a63SDavid du Colombier char *pass; 552*8ccd4a63SDavid du Colombier char tbuf[TICKETLEN+TICKETLEN+AUTHENTLEN], trbuf[TICKREQLEN]; 553*8ccd4a63SDavid du Colombier char authkey[DESKEYLEN]; 554*8ccd4a63SDavid du Colombier Authenticator auth; 555*8ccd4a63SDavid du Colombier int afd, i, v2; 556*8ccd4a63SDavid du Colombier Ticketreq tr; 557*8ccd4a63SDavid du Colombier Ticket t; 558*8ccd4a63SDavid du Colombier AuthInfo *ai; 559*8ccd4a63SDavid du Colombier 560*8ccd4a63SDavid du Colombier if((afd = open("/mnt/factotum/ctl", ORDWR)) >= 0) 561*8ccd4a63SDavid du Colombier return p9anyfactotum(fd, afd); 562*8ccd4a63SDavid du Colombier 563*8ccd4a63SDavid du Colombier if(readstr(fd, buf, sizeof buf) < 0) 564*8ccd4a63SDavid du Colombier fatal(1, "cannot read p9any negotiation"); 565*8ccd4a63SDavid du Colombier bbuf = buf; 566*8ccd4a63SDavid du Colombier v2 = 0; 567*8ccd4a63SDavid du Colombier if(strncmp(buf, "v.2 ", 4) == 0){ 568*8ccd4a63SDavid du Colombier v2 = 1; 569*8ccd4a63SDavid du Colombier bbuf += 4; 570*8ccd4a63SDavid du Colombier } 571*8ccd4a63SDavid du Colombier if((p = strchr(bbuf, ' '))) 572*8ccd4a63SDavid du Colombier *p = 0; 573*8ccd4a63SDavid du Colombier p = bbuf; 574*8ccd4a63SDavid du Colombier if((dom = strchr(p, '@')) == nil) 575*8ccd4a63SDavid du Colombier fatal(1, "bad p9any domain"); 576*8ccd4a63SDavid du Colombier *dom++ = 0; 577*8ccd4a63SDavid du Colombier if(strcmp(p, "p9sk1") != 0) 578*8ccd4a63SDavid du Colombier fatal(1, "server did not offer p9sk1"); 579*8ccd4a63SDavid du Colombier 580*8ccd4a63SDavid du Colombier sprint(buf2, "%s %s", p, dom); 581*8ccd4a63SDavid du Colombier if(write(fd, buf2, strlen(buf2)+1) != strlen(buf2)+1) 582*8ccd4a63SDavid du Colombier fatal(1, "cannot write user/domain choice in p9any"); 583*8ccd4a63SDavid du Colombier if(v2){ 584*8ccd4a63SDavid du Colombier if(readstr(fd, buf, sizeof buf) != 3) 585*8ccd4a63SDavid du Colombier fatal(1, "cannot read OK in p9any"); 586*8ccd4a63SDavid du Colombier if(memcmp(buf, "OK\0", 3) != 0) 587*8ccd4a63SDavid du Colombier fatal(1, "did not get OK in p9any"); 588*8ccd4a63SDavid du Colombier } 589*8ccd4a63SDavid du Colombier for(i=0; i<CHALLEN; i++) 590*8ccd4a63SDavid du Colombier cchal[i] = fastrand(); 591*8ccd4a63SDavid du Colombier if(write(fd, cchal, 8) != 8) 592*8ccd4a63SDavid du Colombier fatal(1, "cannot write p9sk1 challenge"); 593*8ccd4a63SDavid du Colombier 594*8ccd4a63SDavid du Colombier if(readn(fd, trbuf, TICKREQLEN) != TICKREQLEN) 595*8ccd4a63SDavid du Colombier fatal(1, "cannot read ticket request in p9sk1"); 596*8ccd4a63SDavid du Colombier 597*8ccd4a63SDavid du Colombier 598*8ccd4a63SDavid du Colombier convM2TR(trbuf, &tr); 599*8ccd4a63SDavid du Colombier u = user; 600*8ccd4a63SDavid du Colombier pass = findkey(&u, tr.authdom); 601*8ccd4a63SDavid du Colombier if(pass == nil) 602*8ccd4a63SDavid du Colombier again: 603*8ccd4a63SDavid du Colombier pass = getkey(u, tr.authdom); 604*8ccd4a63SDavid du Colombier if(pass == nil) 605*8ccd4a63SDavid du Colombier fatal(1, "no password"); 606*8ccd4a63SDavid du Colombier 607*8ccd4a63SDavid du Colombier passtokey(authkey, pass); 608*8ccd4a63SDavid du Colombier memset(pass, 0, strlen(pass)); 609*8ccd4a63SDavid du Colombier 610*8ccd4a63SDavid du Colombier tr.type = AuthTreq; 611*8ccd4a63SDavid du Colombier strecpy(tr.hostid, tr.hostid+sizeof tr.hostid, u); 612*8ccd4a63SDavid du Colombier strecpy(tr.uid, tr.uid+sizeof tr.uid, u); 613*8ccd4a63SDavid du Colombier convTR2M(&tr, trbuf); 614*8ccd4a63SDavid du Colombier 615*8ccd4a63SDavid du Colombier if(gettickets(&tr, authkey, trbuf, tbuf) < 0) 616*8ccd4a63SDavid du Colombier fatal(1, "cannot get auth tickets in p9sk1"); 617*8ccd4a63SDavid du Colombier 618*8ccd4a63SDavid du Colombier convM2T(tbuf, &t, authkey); 619*8ccd4a63SDavid du Colombier if(t.num != AuthTc){ 620*8ccd4a63SDavid du Colombier print("?password mismatch with auth server\n"); 621*8ccd4a63SDavid du Colombier goto again; 622*8ccd4a63SDavid du Colombier } 623*8ccd4a63SDavid du Colombier memmove(tbuf, tbuf+TICKETLEN, TICKETLEN); 624*8ccd4a63SDavid du Colombier 625*8ccd4a63SDavid du Colombier auth.num = AuthAc; 626*8ccd4a63SDavid du Colombier memmove(auth.chal, tr.chal, CHALLEN); 627*8ccd4a63SDavid du Colombier auth.id = 0; 628*8ccd4a63SDavid du Colombier convA2M(&auth, tbuf+TICKETLEN, t.key); 629*8ccd4a63SDavid du Colombier 630*8ccd4a63SDavid du Colombier if(write(fd, tbuf, TICKETLEN+AUTHENTLEN) != TICKETLEN+AUTHENTLEN) 631*8ccd4a63SDavid du Colombier fatal(1, "cannot send ticket and authenticator back in p9sk1"); 632*8ccd4a63SDavid du Colombier 633*8ccd4a63SDavid du Colombier if(readn(fd, tbuf, AUTHENTLEN) != AUTHENTLEN) 634*8ccd4a63SDavid du Colombier fatal(1, "cannot read authenticator in p9sk1"); 635*8ccd4a63SDavid du Colombier 636*8ccd4a63SDavid du Colombier convM2A(tbuf, &auth, t.key); 637*8ccd4a63SDavid du Colombier if(auth.num != AuthAs 638*8ccd4a63SDavid du Colombier || memcmp(auth.chal, cchal, CHALLEN) != 0 639*8ccd4a63SDavid du Colombier || auth.id != 0){ 640*8ccd4a63SDavid du Colombier print("?you and auth server agree about password.\n"); 641*8ccd4a63SDavid du Colombier print("?server is confused.\n"); 642*8ccd4a63SDavid du Colombier fatal(1, "server lies got %llux.%d want %llux.%d", *(vlong*)auth.chal, auth.id, *(vlong*)cchal, 0); 643*8ccd4a63SDavid du Colombier } 644*8ccd4a63SDavid du Colombier //print("i am %s there.\n", t.suid); 645*8ccd4a63SDavid du Colombier ai = mallocz(sizeof(AuthInfo), 1); 646*8ccd4a63SDavid du Colombier ai->secret = mallocz(8, 1); 647*8ccd4a63SDavid du Colombier des56to64((uchar*)t.key, ai->secret); 648*8ccd4a63SDavid du Colombier ai->nsecret = 8; 649*8ccd4a63SDavid du Colombier ai->suid = strdup(t.suid); 650*8ccd4a63SDavid du Colombier ai->cuid = strdup(t.cuid); 651*8ccd4a63SDavid du Colombier memset(authkey, 0, sizeof authkey); 652*8ccd4a63SDavid du Colombier return ai; 653*8ccd4a63SDavid du Colombier } 654*8ccd4a63SDavid du Colombier 655*8ccd4a63SDavid du Colombier /* 656*8ccd4a63SDavid du Colombier static int 657*8ccd4a63SDavid du Colombier noauth(int fd) 658*8ccd4a63SDavid du Colombier { 659*8ccd4a63SDavid du Colombier ealgs = nil; 660*8ccd4a63SDavid du Colombier return fd; 661*8ccd4a63SDavid du Colombier } 662*8ccd4a63SDavid du Colombier 663*8ccd4a63SDavid du Colombier static int 664*8ccd4a63SDavid du Colombier srvnoauth(int fd, char *user) 665*8ccd4a63SDavid du Colombier { 666*8ccd4a63SDavid du Colombier strecpy(user, user+MaxStr, getuser()); 667*8ccd4a63SDavid du Colombier ealgs = nil; 668*8ccd4a63SDavid du Colombier return fd; 669*8ccd4a63SDavid du Colombier } 670*8ccd4a63SDavid du Colombier */ 671*8ccd4a63SDavid du Colombier 672*8ccd4a63SDavid du Colombier void 673*8ccd4a63SDavid du Colombier loghex(uchar *p, int n) 674*8ccd4a63SDavid du Colombier { 675*8ccd4a63SDavid du Colombier char buf[100]; 676*8ccd4a63SDavid du Colombier int i; 677*8ccd4a63SDavid du Colombier 678*8ccd4a63SDavid du Colombier for(i = 0; i < n; i++) 679*8ccd4a63SDavid du Colombier sprint(buf+2*i, "%2.2ux", p[i]); 680*8ccd4a63SDavid du Colombier // syslog(0, "cpu", buf); 681*8ccd4a63SDavid du Colombier } 682*8ccd4a63SDavid du Colombier 683*8ccd4a63SDavid du Colombier static int 684*8ccd4a63SDavid du Colombier srvp9auth(int fd, char *user) 685*8ccd4a63SDavid du Colombier { 686*8ccd4a63SDavid du Colombier return -1; 687*8ccd4a63SDavid du Colombier } 688*8ccd4a63SDavid du Colombier 689*8ccd4a63SDavid du Colombier /* 690*8ccd4a63SDavid du Colombier * set authentication mechanism 691*8ccd4a63SDavid du Colombier */ 692*8ccd4a63SDavid du Colombier int 693*8ccd4a63SDavid du Colombier setam(char *name) 694*8ccd4a63SDavid du Colombier { 695*8ccd4a63SDavid du Colombier for(am = authmethod; am->name != nil; am++) 696*8ccd4a63SDavid du Colombier if(strcmp(am->name, name) == 0) 697*8ccd4a63SDavid du Colombier return 0; 698*8ccd4a63SDavid du Colombier am = authmethod; 699*8ccd4a63SDavid du Colombier return -1; 700*8ccd4a63SDavid du Colombier } 701*8ccd4a63SDavid du Colombier 702*8ccd4a63SDavid du Colombier /* 703*8ccd4a63SDavid du Colombier * set authentication mechanism and encryption/hash algs 704*8ccd4a63SDavid du Colombier * 705*8ccd4a63SDavid du Colombier int 706*8ccd4a63SDavid du Colombier setamalg(char *s) 707*8ccd4a63SDavid du Colombier { 708*8ccd4a63SDavid du Colombier ealgs = strchr(s, ' '); 709*8ccd4a63SDavid du Colombier if(ealgs != nil) 710*8ccd4a63SDavid du Colombier *ealgs++ = 0; 711*8ccd4a63SDavid du Colombier return setam(s); 712*8ccd4a63SDavid du Colombier } 713*8ccd4a63SDavid du Colombier 714*8ccd4a63SDavid du Colombier */ 715