18ccd4a63SDavid du Colombier /* 28ccd4a63SDavid du Colombier * cpu.c - Make a connection to a cpu server 38ccd4a63SDavid du Colombier * 48ccd4a63SDavid du Colombier * Invoked by listen as 'cpu -R | -N service net netdir' 58ccd4a63SDavid du Colombier * by users as 'cpu [-h system] [-c cmd args ...]' 68ccd4a63SDavid du Colombier */ 78ccd4a63SDavid du Colombier 88ccd4a63SDavid du Colombier #include <u.h> 98ccd4a63SDavid du Colombier #include <libc.h> 108ccd4a63SDavid du Colombier #include <auth.h> 118ccd4a63SDavid du Colombier #include <fcall.h> 128ccd4a63SDavid du Colombier #include <authsrv.h> 138ccd4a63SDavid du Colombier #include <libsec.h> 148ccd4a63SDavid du Colombier #include "args.h" 158ccd4a63SDavid du Colombier #include "drawterm.h" 168ccd4a63SDavid du Colombier 178ccd4a63SDavid du Colombier #define Maxfdata 8192 188ccd4a63SDavid du Colombier #define MaxStr 128 198ccd4a63SDavid du Colombier 208ccd4a63SDavid du Colombier static void fatal(int, char*, ...); 218ccd4a63SDavid du Colombier static void usage(void); 228ccd4a63SDavid du Colombier static void writestr(int, char*, char*, int); 238ccd4a63SDavid du Colombier static int readstr(int, char*, int); 248ccd4a63SDavid du Colombier static char *rexcall(int*, char*, char*); 258ccd4a63SDavid du Colombier static char *keyspec = ""; 268ccd4a63SDavid du Colombier static AuthInfo *p9any(int); 278ccd4a63SDavid du Colombier 288ccd4a63SDavid du Colombier #define system csystem 298ccd4a63SDavid du Colombier static char *system; 308ccd4a63SDavid du Colombier static int cflag; 318ccd4a63SDavid du Colombier extern int dbg; 328ccd4a63SDavid du Colombier 338ccd4a63SDavid du Colombier static char *srvname = "ncpu"; 348ccd4a63SDavid du Colombier static char *ealgs = "rc4_256 sha1"; 358ccd4a63SDavid du Colombier 368ccd4a63SDavid du Colombier /* message size for exportfs; may be larger so we can do big graphics in CPU window */ 378ccd4a63SDavid du Colombier static int msgsize = Maxfdata+IOHDRSZ; 388ccd4a63SDavid du Colombier 398ccd4a63SDavid du Colombier /* authentication mechanisms */ 408ccd4a63SDavid du Colombier static int netkeyauth(int); 418ccd4a63SDavid du Colombier static int netkeysrvauth(int, char*); 428ccd4a63SDavid du Colombier static int p9auth(int); 438ccd4a63SDavid du Colombier static int srvp9auth(int, char*); 448ccd4a63SDavid du Colombier 458ccd4a63SDavid du Colombier char *authserver; 468ccd4a63SDavid du Colombier 478ccd4a63SDavid du Colombier typedef struct AuthMethod AuthMethod; 488ccd4a63SDavid du Colombier struct AuthMethod { 498ccd4a63SDavid du Colombier char *name; /* name of method */ 508ccd4a63SDavid du Colombier int (*cf)(int); /* client side authentication */ 518ccd4a63SDavid du Colombier int (*sf)(int, char*); /* server side authentication */ 528ccd4a63SDavid du Colombier } authmethod[] = 538ccd4a63SDavid du Colombier { 548ccd4a63SDavid du Colombier { "p9", p9auth, srvp9auth,}, 558ccd4a63SDavid du Colombier { "netkey", netkeyauth, netkeysrvauth,}, 568ccd4a63SDavid du Colombier // { "none", noauth, srvnoauth,}, 57ec59a3ddSDavid du Colombier { 0 } 588ccd4a63SDavid du Colombier }; 598ccd4a63SDavid du Colombier AuthMethod *am = authmethod; /* default is p9 */ 608ccd4a63SDavid du Colombier 618ccd4a63SDavid du Colombier char *p9authproto = "p9any"; 628ccd4a63SDavid du Colombier 638ccd4a63SDavid du Colombier int setam(char*); 648ccd4a63SDavid du Colombier 658ccd4a63SDavid du Colombier void 668ccd4a63SDavid du Colombier exits(char *s) 678ccd4a63SDavid du Colombier { 688ccd4a63SDavid du Colombier print("\ngoodbye\n"); 698ccd4a63SDavid du Colombier for(;;) osyield(); 708ccd4a63SDavid du Colombier } 718ccd4a63SDavid du Colombier 728ccd4a63SDavid du Colombier void 738ccd4a63SDavid du Colombier usage(void) 748ccd4a63SDavid du Colombier { 758ccd4a63SDavid du Colombier fprint(2, "usage: drawterm [-a authserver] [-c cpuserver] [-s secstore] [-u user]\n"); 768ccd4a63SDavid du Colombier exits("usage"); 778ccd4a63SDavid du Colombier } 788ccd4a63SDavid du Colombier int fdd; 798ccd4a63SDavid du Colombier 808ccd4a63SDavid du Colombier int 818ccd4a63SDavid du Colombier mountfactotum(void) 828ccd4a63SDavid du Colombier { 838ccd4a63SDavid du Colombier int fd; 848ccd4a63SDavid du Colombier 858ccd4a63SDavid du Colombier if((fd = dialfactotum()) < 0) 868ccd4a63SDavid du Colombier return -1; 878ccd4a63SDavid du Colombier if(sysmount(fd, -1, "/mnt/factotum", MREPL, "") < 0){ 888ccd4a63SDavid du Colombier fprint(2, "mount factotum: %r\n"); 898ccd4a63SDavid du Colombier return -1; 908ccd4a63SDavid du Colombier } 918ccd4a63SDavid du Colombier if((fd = open("/mnt/factotum/ctl", OREAD)) < 0){ 928ccd4a63SDavid du Colombier fprint(2, "open /mnt/factotum/ctl: %r\n"); 938ccd4a63SDavid du Colombier return -1; 948ccd4a63SDavid du Colombier } 958ccd4a63SDavid du Colombier close(fd); 968ccd4a63SDavid du Colombier return 0; 978ccd4a63SDavid du Colombier } 988ccd4a63SDavid du Colombier 998ccd4a63SDavid du Colombier void 1008ccd4a63SDavid du Colombier cpumain(int argc, char **argv) 1018ccd4a63SDavid du Colombier { 1028ccd4a63SDavid du Colombier char dat[MaxStr], buf[MaxStr], cmd[MaxStr], *err, *secstoreserver, *p, *s; 1038ccd4a63SDavid du Colombier int fd, ms, data; 1048ccd4a63SDavid du Colombier 1058ccd4a63SDavid du Colombier /* see if we should use a larger message size */ 1068ccd4a63SDavid du Colombier fd = open("/dev/draw", OREAD); 1078ccd4a63SDavid du Colombier if(fd > 0){ 1088ccd4a63SDavid du Colombier ms = iounit(fd); 1098ccd4a63SDavid du Colombier if(msgsize < ms+IOHDRSZ) 1108ccd4a63SDavid du Colombier msgsize = ms+IOHDRSZ; 1118ccd4a63SDavid du Colombier close(fd); 1128ccd4a63SDavid du Colombier } 1138ccd4a63SDavid du Colombier 1148ccd4a63SDavid du Colombier user = getenv("USER"); 1158ccd4a63SDavid du Colombier if(user == nil) 1168ccd4a63SDavid du Colombier user = readcons("user", nil, 0); 1178ccd4a63SDavid du Colombier secstoreserver = nil; 1188ccd4a63SDavid du Colombier authserver = getenv("auth"); 1198ccd4a63SDavid du Colombier if(authserver == nil) 1208ccd4a63SDavid du Colombier authserver = "auth"; 1218ccd4a63SDavid du Colombier system = getenv("cpu"); 1228ccd4a63SDavid du Colombier if(system == nil) 1238ccd4a63SDavid du Colombier system = "cpu"; 1248ccd4a63SDavid du Colombier ARGBEGIN{ 1258ccd4a63SDavid du Colombier case 'a': 1268ccd4a63SDavid du Colombier authserver = EARGF(usage()); 1278ccd4a63SDavid du Colombier break; 1288ccd4a63SDavid du Colombier case 'c': 1298ccd4a63SDavid du Colombier system = EARGF(usage()); 1308ccd4a63SDavid du Colombier break; 1318ccd4a63SDavid du Colombier case 'C': 1328ccd4a63SDavid du Colombier cflag++; 1338ccd4a63SDavid du Colombier cmd[0] = '!'; 1348ccd4a63SDavid du Colombier cmd[1] = '\0'; 1358ccd4a63SDavid du Colombier while((p = ARGF()) != nil) { 1368ccd4a63SDavid du Colombier strcat(cmd, " "); 1378ccd4a63SDavid du Colombier strcat(cmd, p); 1388ccd4a63SDavid du Colombier } 1398ccd4a63SDavid du Colombier break; 140*238ca1feSDavid du Colombier case 'd': 141*238ca1feSDavid du Colombier dbg++; 142*238ca1feSDavid du Colombier break; 143*238ca1feSDavid du Colombier case 'e': 144*238ca1feSDavid du Colombier ealgs = EARGF(usage()); 145*238ca1feSDavid du Colombier if(*ealgs == 0 || strcmp(ealgs, "clear") == 0) 146*238ca1feSDavid du Colombier ealgs = nil; 147*238ca1feSDavid du Colombier break; 1488ccd4a63SDavid du Colombier case 'k': 1498ccd4a63SDavid du Colombier keyspec = EARGF(usage()); 1508ccd4a63SDavid du Colombier break; 1518ccd4a63SDavid du Colombier case 's': 1528ccd4a63SDavid du Colombier secstoreserver = EARGF(usage()); 1538ccd4a63SDavid du Colombier break; 154*238ca1feSDavid du Colombier case 'u': 155*238ca1feSDavid du Colombier user = EARGF(usage()); 156*238ca1feSDavid du Colombier break; 1578ccd4a63SDavid du Colombier default: 1588ccd4a63SDavid du Colombier usage(); 1598ccd4a63SDavid du Colombier }ARGEND; 1608ccd4a63SDavid du Colombier 1618ccd4a63SDavid du Colombier if(argc != 0) 1628ccd4a63SDavid du Colombier usage(); 1638ccd4a63SDavid du Colombier 1648ccd4a63SDavid du Colombier if(mountfactotum() < 0){ 1658ccd4a63SDavid du Colombier if(secstoreserver == nil) 1668ccd4a63SDavid du Colombier secstoreserver = authserver; 1678ccd4a63SDavid du Colombier if(havesecstore(secstoreserver, user)){ 1688ccd4a63SDavid du Colombier s = secstorefetch(secstoreserver, user, nil); 1698ccd4a63SDavid du Colombier if(s){ 1708ccd4a63SDavid du Colombier if(strlen(s) >= sizeof secstorebuf) 1718ccd4a63SDavid du Colombier sysfatal("secstore data too big"); 1728ccd4a63SDavid du Colombier strcpy(secstorebuf, s); 1738ccd4a63SDavid du Colombier } 1748ccd4a63SDavid du Colombier } 1758ccd4a63SDavid du Colombier } 1768ccd4a63SDavid du Colombier 1778ccd4a63SDavid du Colombier if((err = rexcall(&data, system, srvname))) 1788ccd4a63SDavid du Colombier fatal(1, "%s: %s", err, system); 1798ccd4a63SDavid du Colombier 1808ccd4a63SDavid du Colombier /* Tell the remote side the command to execute and where our working directory is */ 1818ccd4a63SDavid du Colombier if(cflag) 1828ccd4a63SDavid du Colombier writestr(data, cmd, "command", 0); 1838ccd4a63SDavid du Colombier if(getcwd(dat, sizeof(dat)) == 0) 1848ccd4a63SDavid du Colombier writestr(data, "NO", "dir", 0); 1858ccd4a63SDavid du Colombier else 1868ccd4a63SDavid du Colombier writestr(data, dat, "dir", 0); 1878ccd4a63SDavid du Colombier 1888ccd4a63SDavid du Colombier /* 1898ccd4a63SDavid du Colombier * Wait for the other end to execute and start our file service 1908ccd4a63SDavid du Colombier * of /mnt/term 1918ccd4a63SDavid du Colombier */ 1928ccd4a63SDavid du Colombier if(readstr(data, buf, sizeof(buf)) < 0) 1938ccd4a63SDavid du Colombier fatal(1, "waiting for FS: %r"); 1948ccd4a63SDavid du Colombier if(strncmp("FS", buf, 2) != 0) { 1958ccd4a63SDavid du Colombier print("remote cpu: %s", buf); 1968ccd4a63SDavid du Colombier exits(buf); 1978ccd4a63SDavid du Colombier } 1988ccd4a63SDavid du Colombier 1998ccd4a63SDavid du Colombier if(readstr(data, buf, sizeof buf) < 0) 2008ccd4a63SDavid du Colombier fatal(1, "waiting for remote export: %r"); 2018ccd4a63SDavid du Colombier if(strcmp(buf, "/") != 0){ 2028ccd4a63SDavid du Colombier print("remote cpu: %s" , buf); 2038ccd4a63SDavid du Colombier exits(buf); 2048ccd4a63SDavid du Colombier } 2058ccd4a63SDavid du Colombier write(data, "OK", 2); 2068ccd4a63SDavid du Colombier 2078ccd4a63SDavid du Colombier /* Begin serving the gnot namespace */ 2088ccd4a63SDavid du Colombier exportfs(data, msgsize); 2098ccd4a63SDavid du Colombier fatal(1, "starting exportfs"); 2108ccd4a63SDavid du Colombier } 2118ccd4a63SDavid du Colombier 2128ccd4a63SDavid du Colombier void 2138ccd4a63SDavid du Colombier fatal(int syserr, char *fmt, ...) 2148ccd4a63SDavid du Colombier { 2158ccd4a63SDavid du Colombier Fmt f; 2168ccd4a63SDavid du Colombier char *str; 2178ccd4a63SDavid du Colombier va_list arg; 2188ccd4a63SDavid du Colombier 2198ccd4a63SDavid du Colombier fmtstrinit(&f); 2208ccd4a63SDavid du Colombier fmtprint(&f, "cpu: "); 2218ccd4a63SDavid du Colombier va_start(arg, fmt); 2228ccd4a63SDavid du Colombier fmtvprint(&f, fmt, arg); 2238ccd4a63SDavid du Colombier va_end(arg); 2248ccd4a63SDavid du Colombier if(syserr) 2258ccd4a63SDavid du Colombier fmtprint(&f, ": %r"); 2268ccd4a63SDavid du Colombier fmtprint(&f, "\n"); 2278ccd4a63SDavid du Colombier str = fmtstrflush(&f); 2288ccd4a63SDavid du Colombier write(2, str, strlen(str)); 2298ccd4a63SDavid du Colombier exits(str); 2308ccd4a63SDavid du Colombier } 2318ccd4a63SDavid du Colombier 2328ccd4a63SDavid du Colombier char *negstr = "negotiating authentication method"; 2338ccd4a63SDavid du Colombier 2348ccd4a63SDavid du Colombier char bug[256]; 2358ccd4a63SDavid du Colombier 2368ccd4a63SDavid du Colombier char* 2378ccd4a63SDavid du Colombier rexcall(int *fd, char *host, char *service) 2388ccd4a63SDavid du Colombier { 2398ccd4a63SDavid du Colombier char *na; 2408ccd4a63SDavid du Colombier char dir[MaxStr]; 2418ccd4a63SDavid du Colombier char err[ERRMAX]; 2428ccd4a63SDavid du Colombier char msg[MaxStr]; 2438ccd4a63SDavid du Colombier int n; 2448ccd4a63SDavid du Colombier 2458ccd4a63SDavid du Colombier na = netmkaddr(host, "tcp", "17010"); 2468ccd4a63SDavid du Colombier if((*fd = dial(na, 0, dir, 0)) < 0) 2478ccd4a63SDavid du Colombier return "can't dial"; 2488ccd4a63SDavid du Colombier 2498ccd4a63SDavid du Colombier /* negotiate authentication mechanism */ 2508ccd4a63SDavid du Colombier if(ealgs != nil) 2518ccd4a63SDavid du Colombier snprint(msg, sizeof(msg), "%s %s", am->name, ealgs); 2528ccd4a63SDavid du Colombier else 2538ccd4a63SDavid du Colombier snprint(msg, sizeof(msg), "%s", am->name); 2548ccd4a63SDavid du Colombier writestr(*fd, msg, negstr, 0); 2558ccd4a63SDavid du Colombier n = readstr(*fd, err, sizeof err); 2568ccd4a63SDavid du Colombier if(n < 0) 2578ccd4a63SDavid du Colombier return negstr; 2588ccd4a63SDavid du Colombier if(*err){ 2598ccd4a63SDavid du Colombier werrstr(err); 2608ccd4a63SDavid du Colombier return negstr; 2618ccd4a63SDavid du Colombier } 2628ccd4a63SDavid du Colombier 2638ccd4a63SDavid du Colombier /* authenticate */ 2648ccd4a63SDavid du Colombier *fd = (*am->cf)(*fd); 2658ccd4a63SDavid du Colombier if(*fd < 0) 2668ccd4a63SDavid du Colombier return "can't authenticate"; 2678ccd4a63SDavid du Colombier return 0; 2688ccd4a63SDavid du Colombier } 2698ccd4a63SDavid du Colombier 2708ccd4a63SDavid du Colombier void 2718ccd4a63SDavid du Colombier writestr(int fd, char *str, char *thing, int ignore) 2728ccd4a63SDavid du Colombier { 2738ccd4a63SDavid du Colombier int l, n; 2748ccd4a63SDavid du Colombier 2758ccd4a63SDavid du Colombier l = strlen(str); 2768ccd4a63SDavid du Colombier n = write(fd, str, l+1); 2778ccd4a63SDavid du Colombier if(!ignore && n < 0) 2788ccd4a63SDavid du Colombier fatal(1, "writing network: %s", thing); 2798ccd4a63SDavid du Colombier } 2808ccd4a63SDavid du Colombier 2818ccd4a63SDavid du Colombier int 2828ccd4a63SDavid du Colombier readstr(int fd, char *str, int len) 2838ccd4a63SDavid du Colombier { 2848ccd4a63SDavid du Colombier int n; 2858ccd4a63SDavid du Colombier 2868ccd4a63SDavid du Colombier while(len) { 2878ccd4a63SDavid du Colombier n = read(fd, str, 1); 2888ccd4a63SDavid du Colombier if(n < 0) 2898ccd4a63SDavid du Colombier return -1; 2908ccd4a63SDavid du Colombier if(*str == '\0') 2918ccd4a63SDavid du Colombier return 0; 2928ccd4a63SDavid du Colombier str++; 2938ccd4a63SDavid du Colombier len--; 2948ccd4a63SDavid du Colombier } 2958ccd4a63SDavid du Colombier return -1; 2968ccd4a63SDavid du Colombier } 2978ccd4a63SDavid du Colombier 2988ccd4a63SDavid du Colombier static int 2998ccd4a63SDavid du Colombier readln(char *buf, int n) 3008ccd4a63SDavid du Colombier { 3018ccd4a63SDavid du Colombier int i; 3028ccd4a63SDavid du Colombier char *p; 3038ccd4a63SDavid du Colombier 3048ccd4a63SDavid du Colombier n--; /* room for \0 */ 3058ccd4a63SDavid du Colombier p = buf; 3068ccd4a63SDavid du Colombier for(i=0; i<n; i++){ 3078ccd4a63SDavid du Colombier if(read(0, p, 1) != 1) 3088ccd4a63SDavid du Colombier break; 3098ccd4a63SDavid du Colombier if(*p == '\n' || *p == '\r') 3108ccd4a63SDavid du Colombier break; 3118ccd4a63SDavid du Colombier p++; 3128ccd4a63SDavid du Colombier } 3138ccd4a63SDavid du Colombier *p = '\0'; 3148ccd4a63SDavid du Colombier return p-buf; 3158ccd4a63SDavid du Colombier } 3168ccd4a63SDavid du Colombier 3178ccd4a63SDavid du Colombier /* 3188ccd4a63SDavid du Colombier * user level challenge/response 3198ccd4a63SDavid du Colombier */ 3208ccd4a63SDavid du Colombier static int 3218ccd4a63SDavid du Colombier netkeyauth(int fd) 3228ccd4a63SDavid du Colombier { 3238ccd4a63SDavid du Colombier char chall[32]; 3248ccd4a63SDavid du Colombier char resp[32]; 3258ccd4a63SDavid du Colombier 3268ccd4a63SDavid du Colombier strecpy(chall, chall+sizeof chall, getuser()); 3278ccd4a63SDavid du Colombier print("user[%s]: ", chall); 3288ccd4a63SDavid du Colombier if(readln(resp, sizeof(resp)) < 0) 3298ccd4a63SDavid du Colombier return -1; 3308ccd4a63SDavid du Colombier if(*resp != 0) 3318ccd4a63SDavid du Colombier strcpy(chall, resp); 3328ccd4a63SDavid du Colombier writestr(fd, chall, "challenge/response", 1); 3338ccd4a63SDavid du Colombier 3348ccd4a63SDavid du Colombier for(;;){ 3358ccd4a63SDavid du Colombier if(readstr(fd, chall, sizeof chall) < 0) 3368ccd4a63SDavid du Colombier break; 3378ccd4a63SDavid du Colombier if(*chall == 0) 3388ccd4a63SDavid du Colombier return fd; 3398ccd4a63SDavid du Colombier print("challenge: %s\nresponse: ", chall); 3408ccd4a63SDavid du Colombier if(readln(resp, sizeof(resp)) < 0) 3418ccd4a63SDavid du Colombier break; 3428ccd4a63SDavid du Colombier writestr(fd, resp, "challenge/response", 1); 3438ccd4a63SDavid du Colombier } 3448ccd4a63SDavid du Colombier return -1; 3458ccd4a63SDavid du Colombier } 3468ccd4a63SDavid du Colombier 3478ccd4a63SDavid du Colombier static int 3488ccd4a63SDavid du Colombier netkeysrvauth(int fd, char *user) 3498ccd4a63SDavid du Colombier { 3508ccd4a63SDavid du Colombier return -1; 3518ccd4a63SDavid du Colombier } 3528ccd4a63SDavid du Colombier 3538ccd4a63SDavid du Colombier static void 3548ccd4a63SDavid du Colombier mksecret(char *t, uchar *f) 3558ccd4a63SDavid du Colombier { 3568ccd4a63SDavid du Colombier sprint(t, "%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux", 3578ccd4a63SDavid du Colombier f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7], f[8], f[9]); 3588ccd4a63SDavid du Colombier } 3598ccd4a63SDavid du Colombier 3608ccd4a63SDavid du Colombier /* 3618ccd4a63SDavid du Colombier * plan9 authentication followed by rc4 encryption 3628ccd4a63SDavid du Colombier */ 3638ccd4a63SDavid du Colombier static int 3648ccd4a63SDavid du Colombier p9auth(int fd) 3658ccd4a63SDavid du Colombier { 3668ccd4a63SDavid du Colombier uchar key[16]; 3678ccd4a63SDavid du Colombier uchar digest[SHA1dlen]; 3688ccd4a63SDavid du Colombier char fromclientsecret[21]; 3698ccd4a63SDavid du Colombier char fromserversecret[21]; 3708ccd4a63SDavid du Colombier int i; 3718ccd4a63SDavid du Colombier AuthInfo *ai; 3728ccd4a63SDavid du Colombier 3738ccd4a63SDavid du Colombier ai = p9any(fd); 3748ccd4a63SDavid du Colombier if(ai == nil) 3758ccd4a63SDavid du Colombier return -1; 3768ccd4a63SDavid du Colombier memmove(key+4, ai->secret, ai->nsecret); 3778ccd4a63SDavid du Colombier if(ealgs == nil) 3788ccd4a63SDavid du Colombier return fd; 3798ccd4a63SDavid du Colombier 3808ccd4a63SDavid du Colombier /* exchange random numbers */ 3818ccd4a63SDavid du Colombier for(i = 0; i < 4; i++) 3828ccd4a63SDavid du Colombier key[i] = fastrand(); 3838ccd4a63SDavid du Colombier if(write(fd, key, 4) != 4) 3848ccd4a63SDavid du Colombier return -1; 3858ccd4a63SDavid du Colombier if(readn(fd, key+12, 4) != 4) 3868ccd4a63SDavid du Colombier return -1; 3878ccd4a63SDavid du Colombier 3888ccd4a63SDavid du Colombier /* scramble into two secrets */ 3898ccd4a63SDavid du Colombier sha1(key, sizeof(key), digest, nil); 3908ccd4a63SDavid du Colombier mksecret(fromclientsecret, digest); 3918ccd4a63SDavid du Colombier mksecret(fromserversecret, digest+10); 3928ccd4a63SDavid du Colombier 3938ccd4a63SDavid du Colombier /* set up encryption */ 3948ccd4a63SDavid du Colombier i = pushssl(fd, ealgs, fromclientsecret, fromserversecret, nil); 3958ccd4a63SDavid du Colombier if(i < 0) 3968ccd4a63SDavid du Colombier werrstr("can't establish ssl connection: %r"); 3978ccd4a63SDavid du Colombier return i; 3988ccd4a63SDavid du Colombier } 3998ccd4a63SDavid du Colombier 4008ccd4a63SDavid du Colombier int 4018ccd4a63SDavid du Colombier authdial(char *net, char *dom) 4028ccd4a63SDavid du Colombier { 4038ccd4a63SDavid du Colombier int fd; 4048ccd4a63SDavid du Colombier fd = dial(netmkaddr(authserver, "tcp", "567"), 0, 0, 0); 4058ccd4a63SDavid du Colombier //print("authdial %d\n", fd); 4068ccd4a63SDavid du Colombier return fd; 4078ccd4a63SDavid du Colombier } 4088ccd4a63SDavid du Colombier 4098ccd4a63SDavid du Colombier static int 4108ccd4a63SDavid du Colombier getastickets(Ticketreq *tr, char *trbuf, char *tbuf) 4118ccd4a63SDavid du Colombier { 4128ccd4a63SDavid du Colombier int asfd, rv; 4138ccd4a63SDavid du Colombier char *dom; 4148ccd4a63SDavid du Colombier 4158ccd4a63SDavid du Colombier dom = tr->authdom; 4168ccd4a63SDavid du Colombier asfd = authdial(nil, dom); 4178ccd4a63SDavid du Colombier if(asfd < 0) 4188ccd4a63SDavid du Colombier return -1; 4198ccd4a63SDavid du Colombier rv = _asgetticket(asfd, trbuf, tbuf); 4208ccd4a63SDavid du Colombier close(asfd); 4218ccd4a63SDavid du Colombier return rv; 4228ccd4a63SDavid du Colombier } 4238ccd4a63SDavid du Colombier 4248ccd4a63SDavid du Colombier static int 4258ccd4a63SDavid du Colombier mkserverticket(Ticketreq *tr, char *authkey, char *tbuf) 4268ccd4a63SDavid du Colombier { 4278ccd4a63SDavid du Colombier int i; 4288ccd4a63SDavid du Colombier Ticket t; 4298ccd4a63SDavid du Colombier 4308ccd4a63SDavid du Colombier if(strcmp(tr->authid, tr->hostid) != 0) 4318ccd4a63SDavid du Colombier return -1; 4328ccd4a63SDavid du Colombier memset(&t, 0, sizeof(t)); 4338ccd4a63SDavid du Colombier memmove(t.chal, tr->chal, CHALLEN); 4348ccd4a63SDavid du Colombier strcpy(t.cuid, tr->uid); 4358ccd4a63SDavid du Colombier strcpy(t.suid, tr->uid); 4368ccd4a63SDavid du Colombier for(i=0; i<DESKEYLEN; i++) 4378ccd4a63SDavid du Colombier t.key[i] = fastrand(); 4388ccd4a63SDavid du Colombier t.num = AuthTc; 4398ccd4a63SDavid du Colombier convT2M(&t, tbuf, authkey); 4408ccd4a63SDavid du Colombier t.num = AuthTs; 4418ccd4a63SDavid du Colombier convT2M(&t, tbuf+TICKETLEN, authkey); 4428ccd4a63SDavid du Colombier return 0; 4438ccd4a63SDavid du Colombier } 4448ccd4a63SDavid du Colombier 4458ccd4a63SDavid du Colombier static int 4468ccd4a63SDavid du Colombier gettickets(Ticketreq *tr, char *key, char *trbuf, char *tbuf) 4478ccd4a63SDavid du Colombier { 4488ccd4a63SDavid du Colombier if(getastickets(tr, trbuf, tbuf) >= 0) 4498ccd4a63SDavid du Colombier return 0; 4508ccd4a63SDavid du Colombier return mkserverticket(tr, key, tbuf); 4518ccd4a63SDavid du Colombier } 4528ccd4a63SDavid du Colombier 4538ccd4a63SDavid du Colombier /* 4548ccd4a63SDavid du Colombier * prompt user for a key. don't care about memory leaks, runs standalone 4558ccd4a63SDavid du Colombier */ 4568ccd4a63SDavid du Colombier static Attr* 4578ccd4a63SDavid du Colombier promptforkey(char *params) 4588ccd4a63SDavid du Colombier { 4598ccd4a63SDavid du Colombier char *v; 4608ccd4a63SDavid du Colombier int fd; 4618ccd4a63SDavid du Colombier Attr *a, *attr; 4628ccd4a63SDavid du Colombier char *def; 4638ccd4a63SDavid du Colombier 4648ccd4a63SDavid du Colombier fd = open("/dev/cons", ORDWR); 4658ccd4a63SDavid du Colombier if(fd < 0) 4668ccd4a63SDavid du Colombier sysfatal("opening /dev/cons: %r"); 4678ccd4a63SDavid du Colombier 4688ccd4a63SDavid du Colombier attr = _parseattr(params); 4698ccd4a63SDavid du Colombier fprint(fd, "\n!Adding key:"); 4708ccd4a63SDavid du Colombier for(a=attr; a; a=a->next) 4718ccd4a63SDavid du Colombier if(a->type != AttrQuery && a->name[0] != '!') 4728ccd4a63SDavid du Colombier fprint(fd, " %q=%q", a->name, a->val); 4738ccd4a63SDavid du Colombier fprint(fd, "\n"); 4748ccd4a63SDavid du Colombier 4758ccd4a63SDavid du Colombier for(a=attr; a; a=a->next){ 4768ccd4a63SDavid du Colombier v = a->name; 4778ccd4a63SDavid du Colombier if(a->type != AttrQuery || v[0]=='!') 4788ccd4a63SDavid du Colombier continue; 4798ccd4a63SDavid du Colombier def = nil; 4808ccd4a63SDavid du Colombier if(strcmp(v, "user") == 0) 4818ccd4a63SDavid du Colombier def = getuser(); 4828ccd4a63SDavid du Colombier a->val = readcons(v, def, 0); 4838ccd4a63SDavid du Colombier if(a->val == nil) 4848ccd4a63SDavid du Colombier sysfatal("user terminated key input"); 4858ccd4a63SDavid du Colombier a->type = AttrNameval; 4868ccd4a63SDavid du Colombier } 4878ccd4a63SDavid du Colombier for(a=attr; a; a=a->next){ 4888ccd4a63SDavid du Colombier v = a->name; 4898ccd4a63SDavid du Colombier if(a->type != AttrQuery || v[0]!='!') 4908ccd4a63SDavid du Colombier continue; 4918ccd4a63SDavid du Colombier def = nil; 4928ccd4a63SDavid du Colombier if(strcmp(v+1, "user") == 0) 4938ccd4a63SDavid du Colombier def = getuser(); 4948ccd4a63SDavid du Colombier a->val = readcons(v+1, def, 1); 4958ccd4a63SDavid du Colombier if(a->val == nil) 4968ccd4a63SDavid du Colombier sysfatal("user terminated key input"); 4978ccd4a63SDavid du Colombier a->type = AttrNameval; 4988ccd4a63SDavid du Colombier } 4998ccd4a63SDavid du Colombier fprint(fd, "!\n"); 5008ccd4a63SDavid du Colombier close(fd); 5018ccd4a63SDavid du Colombier return attr; 5028ccd4a63SDavid du Colombier } 5038ccd4a63SDavid du Colombier 5048ccd4a63SDavid du Colombier /* 5058ccd4a63SDavid du Colombier * send a key to the mounted factotum 5068ccd4a63SDavid du Colombier */ 5078ccd4a63SDavid du Colombier static int 5088ccd4a63SDavid du Colombier sendkey(Attr *attr) 5098ccd4a63SDavid du Colombier { 5108ccd4a63SDavid du Colombier int fd, rv; 5118ccd4a63SDavid du Colombier char buf[1024]; 5128ccd4a63SDavid du Colombier 5138ccd4a63SDavid du Colombier fd = open("/mnt/factotum/ctl", ORDWR); 5148ccd4a63SDavid du Colombier if(fd < 0) 5158ccd4a63SDavid du Colombier sysfatal("opening /mnt/factotum/ctl: %r"); 5168ccd4a63SDavid du Colombier rv = fprint(fd, "key %A\n", attr); 5178ccd4a63SDavid du Colombier read(fd, buf, sizeof buf); 5188ccd4a63SDavid du Colombier close(fd); 5198ccd4a63SDavid du Colombier return rv; 5208ccd4a63SDavid du Colombier } 5218ccd4a63SDavid du Colombier 5228ccd4a63SDavid du Colombier int 5238ccd4a63SDavid du Colombier askuser(char *params) 5248ccd4a63SDavid du Colombier { 5258ccd4a63SDavid du Colombier Attr *attr; 5268ccd4a63SDavid du Colombier 5278ccd4a63SDavid du Colombier fmtinstall('A', _attrfmt); 5288ccd4a63SDavid du Colombier 5298ccd4a63SDavid du Colombier attr = promptforkey(params); 5308ccd4a63SDavid du Colombier if(attr == nil) 5318ccd4a63SDavid du Colombier sysfatal("no key supplied"); 5328ccd4a63SDavid du Colombier if(sendkey(attr) < 0) 5338ccd4a63SDavid du Colombier sysfatal("sending key to factotum: %r"); 5348ccd4a63SDavid du Colombier return 0; 5358ccd4a63SDavid du Colombier } 5368ccd4a63SDavid du Colombier 5378ccd4a63SDavid du Colombier AuthInfo* 5388ccd4a63SDavid du Colombier p9anyfactotum(int fd, int afd) 5398ccd4a63SDavid du Colombier { 5408ccd4a63SDavid du Colombier return auth_proxy(fd, askuser, "proto=p9any role=client %s", keyspec); 5418ccd4a63SDavid du Colombier } 5428ccd4a63SDavid du Colombier 5438ccd4a63SDavid du Colombier AuthInfo* 5448ccd4a63SDavid du Colombier p9any(int fd) 5458ccd4a63SDavid du Colombier { 5468ccd4a63SDavid du Colombier char buf[1024], buf2[1024], cchal[CHALLEN], *bbuf, *p, *dom, *u; 5478ccd4a63SDavid du Colombier char *pass; 5488ccd4a63SDavid du Colombier char tbuf[TICKETLEN+TICKETLEN+AUTHENTLEN], trbuf[TICKREQLEN]; 5498ccd4a63SDavid du Colombier char authkey[DESKEYLEN]; 5508ccd4a63SDavid du Colombier Authenticator auth; 5518ccd4a63SDavid du Colombier int afd, i, v2; 5528ccd4a63SDavid du Colombier Ticketreq tr; 5538ccd4a63SDavid du Colombier Ticket t; 5548ccd4a63SDavid du Colombier AuthInfo *ai; 5558ccd4a63SDavid du Colombier 5568ccd4a63SDavid du Colombier if((afd = open("/mnt/factotum/ctl", ORDWR)) >= 0) 5578ccd4a63SDavid du Colombier return p9anyfactotum(fd, afd); 5588ccd4a63SDavid du Colombier 5598ccd4a63SDavid du Colombier if(readstr(fd, buf, sizeof buf) < 0) 5608ccd4a63SDavid du Colombier fatal(1, "cannot read p9any negotiation"); 5618ccd4a63SDavid du Colombier bbuf = buf; 5628ccd4a63SDavid du Colombier v2 = 0; 5638ccd4a63SDavid du Colombier if(strncmp(buf, "v.2 ", 4) == 0){ 5648ccd4a63SDavid du Colombier v2 = 1; 5658ccd4a63SDavid du Colombier bbuf += 4; 5668ccd4a63SDavid du Colombier } 5678ccd4a63SDavid du Colombier if((p = strchr(bbuf, ' '))) 5688ccd4a63SDavid du Colombier *p = 0; 5698ccd4a63SDavid du Colombier p = bbuf; 5708ccd4a63SDavid du Colombier if((dom = strchr(p, '@')) == nil) 5718ccd4a63SDavid du Colombier fatal(1, "bad p9any domain"); 5728ccd4a63SDavid du Colombier *dom++ = 0; 5738ccd4a63SDavid du Colombier if(strcmp(p, "p9sk1") != 0) 5748ccd4a63SDavid du Colombier fatal(1, "server did not offer p9sk1"); 5758ccd4a63SDavid du Colombier 5768ccd4a63SDavid du Colombier sprint(buf2, "%s %s", p, dom); 5778ccd4a63SDavid du Colombier if(write(fd, buf2, strlen(buf2)+1) != strlen(buf2)+1) 5788ccd4a63SDavid du Colombier fatal(1, "cannot write user/domain choice in p9any"); 5798ccd4a63SDavid du Colombier if(v2){ 5808ccd4a63SDavid du Colombier if(readstr(fd, buf, sizeof buf) != 3) 5818ccd4a63SDavid du Colombier fatal(1, "cannot read OK in p9any"); 5828ccd4a63SDavid du Colombier if(memcmp(buf, "OK\0", 3) != 0) 5838ccd4a63SDavid du Colombier fatal(1, "did not get OK in p9any"); 5848ccd4a63SDavid du Colombier } 5858ccd4a63SDavid du Colombier for(i=0; i<CHALLEN; i++) 5868ccd4a63SDavid du Colombier cchal[i] = fastrand(); 5878ccd4a63SDavid du Colombier if(write(fd, cchal, 8) != 8) 5888ccd4a63SDavid du Colombier fatal(1, "cannot write p9sk1 challenge"); 5898ccd4a63SDavid du Colombier 5908ccd4a63SDavid du Colombier if(readn(fd, trbuf, TICKREQLEN) != TICKREQLEN) 5918ccd4a63SDavid du Colombier fatal(1, "cannot read ticket request in p9sk1"); 5928ccd4a63SDavid du Colombier 5938ccd4a63SDavid du Colombier 5948ccd4a63SDavid du Colombier convM2TR(trbuf, &tr); 5958ccd4a63SDavid du Colombier u = user; 5968ccd4a63SDavid du Colombier pass = findkey(&u, tr.authdom); 5978ccd4a63SDavid du Colombier if(pass == nil) 5988ccd4a63SDavid du Colombier again: 5998ccd4a63SDavid du Colombier pass = getkey(u, tr.authdom); 6008ccd4a63SDavid du Colombier if(pass == nil) 6018ccd4a63SDavid du Colombier fatal(1, "no password"); 6028ccd4a63SDavid du Colombier 6038ccd4a63SDavid du Colombier passtokey(authkey, pass); 6048ccd4a63SDavid du Colombier memset(pass, 0, strlen(pass)); 6058ccd4a63SDavid du Colombier 6068ccd4a63SDavid du Colombier tr.type = AuthTreq; 6078ccd4a63SDavid du Colombier strecpy(tr.hostid, tr.hostid+sizeof tr.hostid, u); 6088ccd4a63SDavid du Colombier strecpy(tr.uid, tr.uid+sizeof tr.uid, u); 6098ccd4a63SDavid du Colombier convTR2M(&tr, trbuf); 6108ccd4a63SDavid du Colombier 6118ccd4a63SDavid du Colombier if(gettickets(&tr, authkey, trbuf, tbuf) < 0) 6128ccd4a63SDavid du Colombier fatal(1, "cannot get auth tickets in p9sk1"); 6138ccd4a63SDavid du Colombier 6148ccd4a63SDavid du Colombier convM2T(tbuf, &t, authkey); 6158ccd4a63SDavid du Colombier if(t.num != AuthTc){ 6168ccd4a63SDavid du Colombier print("?password mismatch with auth server\n"); 6178ccd4a63SDavid du Colombier goto again; 6188ccd4a63SDavid du Colombier } 6198ccd4a63SDavid du Colombier memmove(tbuf, tbuf+TICKETLEN, TICKETLEN); 6208ccd4a63SDavid du Colombier 6218ccd4a63SDavid du Colombier auth.num = AuthAc; 6228ccd4a63SDavid du Colombier memmove(auth.chal, tr.chal, CHALLEN); 6238ccd4a63SDavid du Colombier auth.id = 0; 6248ccd4a63SDavid du Colombier convA2M(&auth, tbuf+TICKETLEN, t.key); 6258ccd4a63SDavid du Colombier 6268ccd4a63SDavid du Colombier if(write(fd, tbuf, TICKETLEN+AUTHENTLEN) != TICKETLEN+AUTHENTLEN) 6278ccd4a63SDavid du Colombier fatal(1, "cannot send ticket and authenticator back in p9sk1"); 6288ccd4a63SDavid du Colombier 6298ccd4a63SDavid du Colombier if(readn(fd, tbuf, AUTHENTLEN) != AUTHENTLEN) 6308ccd4a63SDavid du Colombier fatal(1, "cannot read authenticator in p9sk1"); 6318ccd4a63SDavid du Colombier 6328ccd4a63SDavid du Colombier convM2A(tbuf, &auth, t.key); 6338ccd4a63SDavid du Colombier if(auth.num != AuthAs 6348ccd4a63SDavid du Colombier || memcmp(auth.chal, cchal, CHALLEN) != 0 6358ccd4a63SDavid du Colombier || auth.id != 0){ 6368ccd4a63SDavid du Colombier print("?you and auth server agree about password.\n"); 6378ccd4a63SDavid du Colombier print("?server is confused.\n"); 6388ccd4a63SDavid du Colombier fatal(1, "server lies got %llux.%d want %llux.%d", *(vlong*)auth.chal, auth.id, *(vlong*)cchal, 0); 6398ccd4a63SDavid du Colombier } 6408ccd4a63SDavid du Colombier //print("i am %s there.\n", t.suid); 6418ccd4a63SDavid du Colombier ai = mallocz(sizeof(AuthInfo), 1); 6428ccd4a63SDavid du Colombier ai->secret = mallocz(8, 1); 6438ccd4a63SDavid du Colombier des56to64((uchar*)t.key, ai->secret); 6448ccd4a63SDavid du Colombier ai->nsecret = 8; 6458ccd4a63SDavid du Colombier ai->suid = strdup(t.suid); 6468ccd4a63SDavid du Colombier ai->cuid = strdup(t.cuid); 6478ccd4a63SDavid du Colombier memset(authkey, 0, sizeof authkey); 6488ccd4a63SDavid du Colombier return ai; 6498ccd4a63SDavid du Colombier } 6508ccd4a63SDavid du Colombier 6518ccd4a63SDavid du Colombier /* 6528ccd4a63SDavid du Colombier static int 6538ccd4a63SDavid du Colombier noauth(int fd) 6548ccd4a63SDavid du Colombier { 6558ccd4a63SDavid du Colombier ealgs = nil; 6568ccd4a63SDavid du Colombier return fd; 6578ccd4a63SDavid du Colombier } 6588ccd4a63SDavid du Colombier 6598ccd4a63SDavid du Colombier static int 6608ccd4a63SDavid du Colombier srvnoauth(int fd, char *user) 6618ccd4a63SDavid du Colombier { 6628ccd4a63SDavid du Colombier strecpy(user, user+MaxStr, getuser()); 6638ccd4a63SDavid du Colombier ealgs = nil; 6648ccd4a63SDavid du Colombier return fd; 6658ccd4a63SDavid du Colombier } 6668ccd4a63SDavid du Colombier */ 6678ccd4a63SDavid du Colombier 6688ccd4a63SDavid du Colombier void 6698ccd4a63SDavid du Colombier loghex(uchar *p, int n) 6708ccd4a63SDavid du Colombier { 6718ccd4a63SDavid du Colombier char buf[100]; 6728ccd4a63SDavid du Colombier int i; 6738ccd4a63SDavid du Colombier 6748ccd4a63SDavid du Colombier for(i = 0; i < n; i++) 6758ccd4a63SDavid du Colombier sprint(buf+2*i, "%2.2ux", p[i]); 6768ccd4a63SDavid du Colombier // syslog(0, "cpu", buf); 6778ccd4a63SDavid du Colombier } 6788ccd4a63SDavid du Colombier 6798ccd4a63SDavid du Colombier static int 6808ccd4a63SDavid du Colombier srvp9auth(int fd, char *user) 6818ccd4a63SDavid du Colombier { 6828ccd4a63SDavid du Colombier return -1; 6838ccd4a63SDavid du Colombier } 6848ccd4a63SDavid du Colombier 6858ccd4a63SDavid du Colombier /* 6868ccd4a63SDavid du Colombier * set authentication mechanism 6878ccd4a63SDavid du Colombier */ 6888ccd4a63SDavid du Colombier int 6898ccd4a63SDavid du Colombier setam(char *name) 6908ccd4a63SDavid du Colombier { 6918ccd4a63SDavid du Colombier for(am = authmethod; am->name != nil; am++) 6928ccd4a63SDavid du Colombier if(strcmp(am->name, name) == 0) 6938ccd4a63SDavid du Colombier return 0; 6948ccd4a63SDavid du Colombier am = authmethod; 6958ccd4a63SDavid du Colombier return -1; 6968ccd4a63SDavid du Colombier } 6978ccd4a63SDavid du Colombier 6988ccd4a63SDavid du Colombier /* 6998ccd4a63SDavid du Colombier * set authentication mechanism and encryption/hash algs 7008ccd4a63SDavid du Colombier * 7018ccd4a63SDavid du Colombier int 7028ccd4a63SDavid du Colombier setamalg(char *s) 7038ccd4a63SDavid du Colombier { 7048ccd4a63SDavid du Colombier ealgs = strchr(s, ' '); 7058ccd4a63SDavid du Colombier if(ealgs != nil) 7068ccd4a63SDavid du Colombier *ealgs++ = 0; 7078ccd4a63SDavid du Colombier return setam(s); 7088ccd4a63SDavid du Colombier } 7098ccd4a63SDavid du Colombier 7108ccd4a63SDavid du Colombier */ 711