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;
324e17d7c8SDavid 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
exits(char * s)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
usage(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
mountfactotum(void)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
cpumain(int argc,char ** argv)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;
1304e17d7c8SDavid du Colombier case 'd':
1314e17d7c8SDavid du Colombier dbg++;
1324e17d7c8SDavid du Colombier break;
1334e17d7c8SDavid du Colombier case 'e':
1344e17d7c8SDavid du Colombier ealgs = EARGF(usage());
1354e17d7c8SDavid du Colombier if(*ealgs == 0 || strcmp(ealgs, "clear") == 0)
1364e17d7c8SDavid du Colombier ealgs = nil;
1374e17d7c8SDavid 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;
1504e17d7c8SDavid du Colombier case 'r':
1514e17d7c8SDavid du Colombier base = EARGF(usage());
1524e17d7c8SDavid 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
1664e17d7c8SDavid du Colombier if(user == nil)
1674e17d7c8SDavid du Colombier user = readcons("user", nil, 0);
1684e17d7c8SDavid 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
fatal(int syserr,char * fmt,...)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*
rexcall(int * fd,char * host,char * service)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
writestr(int fd,char * str,char * thing,int ignore)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
readstr(int fd,char * str,int len)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
readln(char * buf,int n)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
netkeyauth(int fd)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
netkeysrvauth(int fd,char * user)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
mksecret(char * t,uchar * f)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
p9auth(int fd)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
authdial(char * net,char * dom)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
getastickets(Ticketreq * tr,char * trbuf,char * tbuf)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
mkserverticket(Ticketreq * tr,char * authkey,char * tbuf)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
gettickets(Ticketreq * tr,char * key,char * trbuf,char * tbuf)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*
promptforkey(char * params)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
sendkey(Attr * attr)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
askuser(char * params)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*
p9anyfactotum(int fd,int afd)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*
p9any(int fd)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;
5564e17d7c8SDavid 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);
563*58da3067SDavid du Colombier werrstr("");
5648ccd4a63SDavid du Colombier
5658ccd4a63SDavid du Colombier if(readstr(fd, buf, sizeof buf) < 0)
5668ccd4a63SDavid du Colombier fatal(1, "cannot read p9any negotiation");
5678ccd4a63SDavid du Colombier bbuf = buf;
5688ccd4a63SDavid du Colombier v2 = 0;
5698ccd4a63SDavid du Colombier if(strncmp(buf, "v.2 ", 4) == 0){
5708ccd4a63SDavid du Colombier v2 = 1;
5718ccd4a63SDavid du Colombier bbuf += 4;
5728ccd4a63SDavid du Colombier }
5738ccd4a63SDavid du Colombier if((p = strchr(bbuf, ' ')))
5748ccd4a63SDavid du Colombier *p = 0;
5758ccd4a63SDavid du Colombier p = bbuf;
5768ccd4a63SDavid du Colombier if((dom = strchr(p, '@')) == nil)
5778ccd4a63SDavid du Colombier fatal(1, "bad p9any domain");
5788ccd4a63SDavid du Colombier *dom++ = 0;
5798ccd4a63SDavid du Colombier if(strcmp(p, "p9sk1") != 0)
5808ccd4a63SDavid du Colombier fatal(1, "server did not offer p9sk1");
5818ccd4a63SDavid du Colombier
5828ccd4a63SDavid du Colombier sprint(buf2, "%s %s", p, dom);
5838ccd4a63SDavid du Colombier if(write(fd, buf2, strlen(buf2)+1) != strlen(buf2)+1)
5848ccd4a63SDavid du Colombier fatal(1, "cannot write user/domain choice in p9any");
5858ccd4a63SDavid du Colombier if(v2){
586*58da3067SDavid du Colombier if(readstr(fd, buf, sizeof buf) < 0)
587*58da3067SDavid du Colombier fatal(1, "cannot read OK in p9any: got %d %s", n, buf);
5888ccd4a63SDavid du Colombier if(memcmp(buf, "OK\0", 3) != 0)
5898ccd4a63SDavid du Colombier fatal(1, "did not get OK in p9any");
5908ccd4a63SDavid du Colombier }
5918ccd4a63SDavid du Colombier for(i=0; i<CHALLEN; i++)
5928ccd4a63SDavid du Colombier cchal[i] = fastrand();
5938ccd4a63SDavid du Colombier if(write(fd, cchal, 8) != 8)
5948ccd4a63SDavid du Colombier fatal(1, "cannot write p9sk1 challenge");
5958ccd4a63SDavid du Colombier
5968ccd4a63SDavid du Colombier if(readn(fd, trbuf, TICKREQLEN) != TICKREQLEN)
5978ccd4a63SDavid du Colombier fatal(1, "cannot read ticket request in p9sk1");
5988ccd4a63SDavid du Colombier
5998ccd4a63SDavid du Colombier
6008ccd4a63SDavid du Colombier convM2TR(trbuf, &tr);
6018ccd4a63SDavid du Colombier u = user;
6028ccd4a63SDavid du Colombier pass = findkey(&u, tr.authdom);
6038ccd4a63SDavid du Colombier if(pass == nil)
6048ccd4a63SDavid du Colombier again:
6058ccd4a63SDavid du Colombier pass = getkey(u, tr.authdom);
6068ccd4a63SDavid du Colombier if(pass == nil)
6078ccd4a63SDavid du Colombier fatal(1, "no password");
6088ccd4a63SDavid du Colombier
6098ccd4a63SDavid du Colombier passtokey(authkey, pass);
6108ccd4a63SDavid du Colombier memset(pass, 0, strlen(pass));
6118ccd4a63SDavid du Colombier
6128ccd4a63SDavid du Colombier tr.type = AuthTreq;
6138ccd4a63SDavid du Colombier strecpy(tr.hostid, tr.hostid+sizeof tr.hostid, u);
6148ccd4a63SDavid du Colombier strecpy(tr.uid, tr.uid+sizeof tr.uid, u);
6158ccd4a63SDavid du Colombier convTR2M(&tr, trbuf);
6168ccd4a63SDavid du Colombier
6178ccd4a63SDavid du Colombier if(gettickets(&tr, authkey, trbuf, tbuf) < 0)
6188ccd4a63SDavid du Colombier fatal(1, "cannot get auth tickets in p9sk1");
6198ccd4a63SDavid du Colombier
6208ccd4a63SDavid du Colombier convM2T(tbuf, &t, authkey);
6218ccd4a63SDavid du Colombier if(t.num != AuthTc){
6228ccd4a63SDavid du Colombier print("?password mismatch with auth server\n");
6238ccd4a63SDavid du Colombier goto again;
6248ccd4a63SDavid du Colombier }
6258ccd4a63SDavid du Colombier memmove(tbuf, tbuf+TICKETLEN, TICKETLEN);
6268ccd4a63SDavid du Colombier
6278ccd4a63SDavid du Colombier auth.num = AuthAc;
6288ccd4a63SDavid du Colombier memmove(auth.chal, tr.chal, CHALLEN);
6298ccd4a63SDavid du Colombier auth.id = 0;
6308ccd4a63SDavid du Colombier convA2M(&auth, tbuf+TICKETLEN, t.key);
6318ccd4a63SDavid du Colombier
6328ccd4a63SDavid du Colombier if(write(fd, tbuf, TICKETLEN+AUTHENTLEN) != TICKETLEN+AUTHENTLEN)
6338ccd4a63SDavid du Colombier fatal(1, "cannot send ticket and authenticator back in p9sk1");
6348ccd4a63SDavid du Colombier
6354e17d7c8SDavid du Colombier if((n=readn(fd, tbuf, AUTHENTLEN)) != AUTHENTLEN ||
6364e17d7c8SDavid du Colombier memcmp(tbuf, "cpu:", 4) == 0){
6374e17d7c8SDavid du Colombier if(n <= 4)
6388ccd4a63SDavid du Colombier fatal(1, "cannot read authenticator in p9sk1");
6398ccd4a63SDavid du Colombier
6404e17d7c8SDavid du Colombier /*
6414e17d7c8SDavid du Colombier * didn't send back authenticator:
6424e17d7c8SDavid du Colombier * sent back fatal error message.
6434e17d7c8SDavid du Colombier */
6444e17d7c8SDavid du Colombier memmove(buf, tbuf, n);
6454e17d7c8SDavid du Colombier i = readn(fd, buf+n, sizeof buf-n-1);
6464e17d7c8SDavid du Colombier if(i > 0)
6474e17d7c8SDavid du Colombier n += i;
6484e17d7c8SDavid du Colombier buf[n] = 0;
6494e17d7c8SDavid du Colombier werrstr("");
6504e17d7c8SDavid du Colombier fatal(0, "server says: %s", buf);
6514e17d7c8SDavid du Colombier }
6524e17d7c8SDavid du Colombier
6538ccd4a63SDavid du Colombier convM2A(tbuf, &auth, t.key);
6548ccd4a63SDavid du Colombier if(auth.num != AuthAs
6558ccd4a63SDavid du Colombier || memcmp(auth.chal, cchal, CHALLEN) != 0
6568ccd4a63SDavid du Colombier || auth.id != 0){
6578ccd4a63SDavid du Colombier print("?you and auth server agree about password.\n");
6588ccd4a63SDavid du Colombier print("?server is confused.\n");
6594e17d7c8SDavid du Colombier fatal(0, "server lies got %llux.%d want %llux.%d", *(vlong*)auth.chal, auth.id, *(vlong*)cchal, 0);
6608ccd4a63SDavid du Colombier }
6618ccd4a63SDavid du Colombier //print("i am %s there.\n", t.suid);
6628ccd4a63SDavid du Colombier ai = mallocz(sizeof(AuthInfo), 1);
6638ccd4a63SDavid du Colombier ai->secret = mallocz(8, 1);
6648ccd4a63SDavid du Colombier des56to64((uchar*)t.key, ai->secret);
6658ccd4a63SDavid du Colombier ai->nsecret = 8;
6668ccd4a63SDavid du Colombier ai->suid = strdup(t.suid);
6678ccd4a63SDavid du Colombier ai->cuid = strdup(t.cuid);
6688ccd4a63SDavid du Colombier memset(authkey, 0, sizeof authkey);
6698ccd4a63SDavid du Colombier return ai;
6708ccd4a63SDavid du Colombier }
6718ccd4a63SDavid du Colombier
6728ccd4a63SDavid du Colombier /*
6738ccd4a63SDavid du Colombier static int
6748ccd4a63SDavid du Colombier noauth(int fd)
6758ccd4a63SDavid du Colombier {
6768ccd4a63SDavid du Colombier ealgs = nil;
6778ccd4a63SDavid du Colombier return fd;
6788ccd4a63SDavid du Colombier }
6798ccd4a63SDavid du Colombier
6808ccd4a63SDavid du Colombier static int
6818ccd4a63SDavid du Colombier srvnoauth(int fd, char *user)
6828ccd4a63SDavid du Colombier {
6838ccd4a63SDavid du Colombier strecpy(user, user+MaxStr, getuser());
6848ccd4a63SDavid du Colombier ealgs = nil;
6858ccd4a63SDavid du Colombier return fd;
6868ccd4a63SDavid du Colombier }
6878ccd4a63SDavid du Colombier */
6888ccd4a63SDavid du Colombier
6898ccd4a63SDavid du Colombier void
loghex(uchar * p,int n)6908ccd4a63SDavid du Colombier loghex(uchar *p, int n)
6918ccd4a63SDavid du Colombier {
6928ccd4a63SDavid du Colombier char buf[100];
6938ccd4a63SDavid du Colombier int i;
6948ccd4a63SDavid du Colombier
6958ccd4a63SDavid du Colombier for(i = 0; i < n; i++)
6968ccd4a63SDavid du Colombier sprint(buf+2*i, "%2.2ux", p[i]);
6978ccd4a63SDavid du Colombier // syslog(0, "cpu", buf);
6988ccd4a63SDavid du Colombier }
6998ccd4a63SDavid du Colombier
7008ccd4a63SDavid du Colombier static int
srvp9auth(int fd,char * user)7018ccd4a63SDavid du Colombier srvp9auth(int fd, char *user)
7028ccd4a63SDavid du Colombier {
7038ccd4a63SDavid du Colombier return -1;
7048ccd4a63SDavid du Colombier }
7058ccd4a63SDavid du Colombier
7068ccd4a63SDavid du Colombier /*
7078ccd4a63SDavid du Colombier * set authentication mechanism
7088ccd4a63SDavid du Colombier */
7098ccd4a63SDavid du Colombier int
setam(char * name)7108ccd4a63SDavid du Colombier setam(char *name)
7118ccd4a63SDavid du Colombier {
7128ccd4a63SDavid du Colombier for(am = authmethod; am->name != nil; am++)
7138ccd4a63SDavid du Colombier if(strcmp(am->name, name) == 0)
7148ccd4a63SDavid du Colombier return 0;
7158ccd4a63SDavid du Colombier am = authmethod;
7168ccd4a63SDavid du Colombier return -1;
7178ccd4a63SDavid du Colombier }
7188ccd4a63SDavid du Colombier
7198ccd4a63SDavid du Colombier /*
7208ccd4a63SDavid du Colombier * set authentication mechanism and encryption/hash algs
7218ccd4a63SDavid du Colombier *
7228ccd4a63SDavid du Colombier int
7238ccd4a63SDavid du Colombier setamalg(char *s)
7248ccd4a63SDavid du Colombier {
7258ccd4a63SDavid du Colombier ealgs = strchr(s, ' ');
7268ccd4a63SDavid du Colombier if(ealgs != nil)
7278ccd4a63SDavid du Colombier *ealgs++ = 0;
7288ccd4a63SDavid du Colombier return setam(s);
7298ccd4a63SDavid du Colombier }
7308ccd4a63SDavid du Colombier
7318ccd4a63SDavid du Colombier */
732