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