1*3ff48bf5SDavid du Colombier /* 2*3ff48bf5SDavid du Colombier * Test various aspects of the authentication setup. 3*3ff48bf5SDavid du Colombier */ 4*3ff48bf5SDavid du Colombier 5*3ff48bf5SDavid du Colombier #include <u.h> 6*3ff48bf5SDavid du Colombier #include <libc.h> 7*3ff48bf5SDavid du Colombier #include <bio.h> 8*3ff48bf5SDavid du Colombier #include <ndb.h> 9*3ff48bf5SDavid du Colombier #include <auth.h> 10*3ff48bf5SDavid du Colombier #include <authsrv.h> 11*3ff48bf5SDavid du Colombier 12*3ff48bf5SDavid du Colombier void 13*3ff48bf5SDavid du Colombier usage(void) 14*3ff48bf5SDavid du Colombier { 15*3ff48bf5SDavid du Colombier fprint(2, "usage: auth/debug\n"); 16*3ff48bf5SDavid du Colombier exits("usage"); 17*3ff48bf5SDavid du Colombier } 18*3ff48bf5SDavid du Colombier 19*3ff48bf5SDavid du Colombier static char* 20*3ff48bf5SDavid du Colombier readcons(char *prompt, char *def, int raw, char *buf, int nbuf) 21*3ff48bf5SDavid du Colombier { 22*3ff48bf5SDavid du Colombier int fdin, fdout, ctl, n, m; 23*3ff48bf5SDavid du Colombier char line[10]; 24*3ff48bf5SDavid du Colombier 25*3ff48bf5SDavid du Colombier fdin = open("/dev/cons", OREAD); 26*3ff48bf5SDavid du Colombier if(fdin < 0) 27*3ff48bf5SDavid du Colombier fdin = 0; 28*3ff48bf5SDavid du Colombier fdout = open("/dev/cons", OWRITE); 29*3ff48bf5SDavid du Colombier if(fdout < 0) 30*3ff48bf5SDavid du Colombier fdout = 1; 31*3ff48bf5SDavid du Colombier if(def != nil) 32*3ff48bf5SDavid du Colombier fprint(fdout, "%s[%s]: ", prompt, def); 33*3ff48bf5SDavid du Colombier else 34*3ff48bf5SDavid du Colombier fprint(fdout, "%s: ", prompt); 35*3ff48bf5SDavid du Colombier if(raw){ 36*3ff48bf5SDavid du Colombier ctl = open("/dev/consctl", OWRITE); 37*3ff48bf5SDavid du Colombier if(ctl >= 0) 38*3ff48bf5SDavid du Colombier write(ctl, "rawon", 5); 39*3ff48bf5SDavid du Colombier } else 40*3ff48bf5SDavid du Colombier ctl = -1; 41*3ff48bf5SDavid du Colombier 42*3ff48bf5SDavid du Colombier m = 0; 43*3ff48bf5SDavid du Colombier for(;;){ 44*3ff48bf5SDavid du Colombier n = read(fdin, line, 1); 45*3ff48bf5SDavid du Colombier if(n == 0){ 46*3ff48bf5SDavid du Colombier close(ctl); 47*3ff48bf5SDavid du Colombier werrstr("readcons: EOF"); 48*3ff48bf5SDavid du Colombier return nil; 49*3ff48bf5SDavid du Colombier } 50*3ff48bf5SDavid du Colombier if(n < 0){ 51*3ff48bf5SDavid du Colombier close(ctl); 52*3ff48bf5SDavid du Colombier werrstr("can't read cons"); 53*3ff48bf5SDavid du Colombier return nil; 54*3ff48bf5SDavid du Colombier } 55*3ff48bf5SDavid du Colombier if(line[0] == 0x7f) 56*3ff48bf5SDavid du Colombier exits(0); 57*3ff48bf5SDavid du Colombier if(n == 0 || line[0] == '\n' || line[0] == '\r'){ 58*3ff48bf5SDavid du Colombier if(raw){ 59*3ff48bf5SDavid du Colombier write(ctl, "rawoff", 6); 60*3ff48bf5SDavid du Colombier write(fdout, "\n", 1); 61*3ff48bf5SDavid du Colombier close(ctl); 62*3ff48bf5SDavid du Colombier } 63*3ff48bf5SDavid du Colombier buf[m] = '\0'; 64*3ff48bf5SDavid du Colombier if(buf[0]=='\0' && def) 65*3ff48bf5SDavid du Colombier strcpy(buf, def); 66*3ff48bf5SDavid du Colombier return buf; 67*3ff48bf5SDavid du Colombier } 68*3ff48bf5SDavid du Colombier if(line[0] == '\b'){ 69*3ff48bf5SDavid du Colombier if(m > 0) 70*3ff48bf5SDavid du Colombier m--; 71*3ff48bf5SDavid du Colombier }else if(line[0] == 0x15){ /* ^U: line kill */ 72*3ff48bf5SDavid du Colombier m = 0; 73*3ff48bf5SDavid du Colombier if(def != nil) 74*3ff48bf5SDavid du Colombier fprint(fdout, "%s[%s]: ", prompt, def); 75*3ff48bf5SDavid du Colombier else 76*3ff48bf5SDavid du Colombier fprint(fdout, "%s: ", prompt); 77*3ff48bf5SDavid du Colombier }else{ 78*3ff48bf5SDavid du Colombier if(m >= nbuf-1){ 79*3ff48bf5SDavid du Colombier fprint(fdout, "line too long\n"); 80*3ff48bf5SDavid du Colombier m = 0; 81*3ff48bf5SDavid du Colombier if(def != nil) 82*3ff48bf5SDavid du Colombier fprint(fdout, "%s[%s]: ", prompt, def); 83*3ff48bf5SDavid du Colombier else 84*3ff48bf5SDavid du Colombier fprint(fdout, "%s: ", prompt); 85*3ff48bf5SDavid du Colombier }else 86*3ff48bf5SDavid du Colombier buf[m++] = line[0]; 87*3ff48bf5SDavid du Colombier } 88*3ff48bf5SDavid du Colombier } 89*3ff48bf5SDavid du Colombier return buf; /* how does this happen */ 90*3ff48bf5SDavid du Colombier } 91*3ff48bf5SDavid du Colombier 92*3ff48bf5SDavid du Colombier void authdialfutz(char*, char*); 93*3ff48bf5SDavid du Colombier void authfutz(char*, char*); 94*3ff48bf5SDavid du Colombier 95*3ff48bf5SDavid du Colombier /* scan factotum for p9sk1 keys; check them */ 96*3ff48bf5SDavid du Colombier void 97*3ff48bf5SDavid du Colombier debugfactotumkeys(void) 98*3ff48bf5SDavid du Colombier { 99*3ff48bf5SDavid du Colombier char *s, *dom, *proto, *user; 100*3ff48bf5SDavid du Colombier int found; 101*3ff48bf5SDavid du Colombier Attr *a; 102*3ff48bf5SDavid du Colombier Biobuf *b; 103*3ff48bf5SDavid du Colombier 104*3ff48bf5SDavid du Colombier b = Bopen("/mnt/factotum/ctl", OREAD); 105*3ff48bf5SDavid du Colombier if(b == nil){ 106*3ff48bf5SDavid du Colombier fprint(2, "cannot open /mnt/factotum/ctl"); 107*3ff48bf5SDavid du Colombier return; 108*3ff48bf5SDavid du Colombier } 109*3ff48bf5SDavid du Colombier found = 0; 110*3ff48bf5SDavid du Colombier while((s = Brdstr(b, '\n', 1)) != nil){ 111*3ff48bf5SDavid du Colombier if(strncmp(s, "key ", 4) != 0){ 112*3ff48bf5SDavid du Colombier print("malformed ctl line: %s\n", s); 113*3ff48bf5SDavid du Colombier free(s); 114*3ff48bf5SDavid du Colombier continue; 115*3ff48bf5SDavid du Colombier } 116*3ff48bf5SDavid du Colombier a = _parseattr(s+4); 117*3ff48bf5SDavid du Colombier free(s); 118*3ff48bf5SDavid du Colombier proto = _str_findattr(a, "proto"); 119*3ff48bf5SDavid du Colombier if(proto==nil || strcmp(proto, "p9sk1")!=0) 120*3ff48bf5SDavid du Colombier continue; 121*3ff48bf5SDavid du Colombier dom = _str_findattr(a, "dom"); 122*3ff48bf5SDavid du Colombier if(dom == nil){ 123*3ff48bf5SDavid du Colombier print("p9sk1 key with no dom: %A\n", a); 124*3ff48bf5SDavid du Colombier _freeattr(a); 125*3ff48bf5SDavid du Colombier continue; 126*3ff48bf5SDavid du Colombier } 127*3ff48bf5SDavid du Colombier user = _str_findattr(a, "user"); 128*3ff48bf5SDavid du Colombier if(user == nil){ 129*3ff48bf5SDavid du Colombier print("p9sk1 key with no user: %A\n", a); 130*3ff48bf5SDavid du Colombier _freeattr(a); 131*3ff48bf5SDavid du Colombier continue; 132*3ff48bf5SDavid du Colombier } 133*3ff48bf5SDavid du Colombier print("p9sk1 key: %A\n", a); 134*3ff48bf5SDavid du Colombier found = 1; 135*3ff48bf5SDavid du Colombier authdialfutz(dom, user); 136*3ff48bf5SDavid du Colombier _freeattr(a); 137*3ff48bf5SDavid du Colombier } 138*3ff48bf5SDavid du Colombier if(!found) 139*3ff48bf5SDavid du Colombier print("no p9sk1 keys found in factotum\n"); 140*3ff48bf5SDavid du Colombier } 141*3ff48bf5SDavid du Colombier 142*3ff48bf5SDavid du Colombier void 143*3ff48bf5SDavid du Colombier authdialfutz(char *dom, char *user) 144*3ff48bf5SDavid du Colombier { 145*3ff48bf5SDavid du Colombier int fd; 146*3ff48bf5SDavid du Colombier Ndbtuple *nt; 147*3ff48bf5SDavid du Colombier char server[Ndbvlen]; 148*3ff48bf5SDavid du Colombier char *addr; 149*3ff48bf5SDavid du Colombier 150*3ff48bf5SDavid du Colombier fd = authdial(nil, dom); 151*3ff48bf5SDavid du Colombier if(fd >= 0){ 152*3ff48bf5SDavid du Colombier print("\tsuccessfully dialed auth server\n"); 153*3ff48bf5SDavid du Colombier close(fd); 154*3ff48bf5SDavid du Colombier authfutz(dom, user); 155*3ff48bf5SDavid du Colombier return; 156*3ff48bf5SDavid du Colombier } 157*3ff48bf5SDavid du Colombier print("\tcannot dial auth server: %r\n"); 158*3ff48bf5SDavid du Colombier nt = csgetval(nil, "authdom", dom, "auth", server); 159*3ff48bf5SDavid du Colombier if(nt){ 160*3ff48bf5SDavid du Colombier print("\tcsquery authdom=%q auth=%s\n", dom, server); 161*3ff48bf5SDavid du Colombier return; 162*3ff48bf5SDavid du Colombier } 163*3ff48bf5SDavid du Colombier print("\tcsquery authdom=%q auth=* failed\n", dom); 164*3ff48bf5SDavid du Colombier nt = csgetval(nil, "dom", dom, "auth", server); 165*3ff48bf5SDavid du Colombier if(nt){ 166*3ff48bf5SDavid du Colombier print("\tcsquery dom=%q auth=%q\n", dom, server); 167*3ff48bf5SDavid du Colombier return; 168*3ff48bf5SDavid du Colombier } 169*3ff48bf5SDavid du Colombier print("\tcsquery dom=%q auth=%q\n", dom, server); 170*3ff48bf5SDavid du Colombier 171*3ff48bf5SDavid du Colombier fd = dial(addr=netmkaddr(server, nil, "ticket"), 0, 0, 0); 172*3ff48bf5SDavid du Colombier if(fd >= 0){ 173*3ff48bf5SDavid du Colombier print("\tdial %s succeeded\n", addr); 174*3ff48bf5SDavid du Colombier close(fd); 175*3ff48bf5SDavid du Colombier return; 176*3ff48bf5SDavid du Colombier } 177*3ff48bf5SDavid du Colombier print("\tdial %s failed: %r\n", addr); 178*3ff48bf5SDavid du Colombier } 179*3ff48bf5SDavid du Colombier 180*3ff48bf5SDavid du Colombier void 181*3ff48bf5SDavid du Colombier authfutz(char *dom, char *user) 182*3ff48bf5SDavid du Colombier { 183*3ff48bf5SDavid du Colombier int fd, nobootes; 184*3ff48bf5SDavid du Colombier char pw[128], prompt[128], key[DESKEYLEN], booteskey[DESKEYLEN], tbuf[2*TICKETLEN], 185*3ff48bf5SDavid du Colombier trbuf[TICKREQLEN]; 186*3ff48bf5SDavid du Colombier Ticket t; 187*3ff48bf5SDavid du Colombier Ticketreq tr; 188*3ff48bf5SDavid du Colombier 189*3ff48bf5SDavid du Colombier snprint(prompt, sizeof prompt, "\tpassword for %s@%s [hit enter to skip test]", user, dom); 190*3ff48bf5SDavid du Colombier readcons(prompt, nil, 1, pw, sizeof pw); 191*3ff48bf5SDavid du Colombier if(pw[0] == '\0') 192*3ff48bf5SDavid du Colombier return; 193*3ff48bf5SDavid du Colombier passtokey(key, pw); 194*3ff48bf5SDavid du Colombier 195*3ff48bf5SDavid du Colombier fd = authdial(nil, dom); 196*3ff48bf5SDavid du Colombier if(fd < 0){ 197*3ff48bf5SDavid du Colombier print("\tauthdial failed(!): %r\n"); 198*3ff48bf5SDavid du Colombier return; 199*3ff48bf5SDavid du Colombier } 200*3ff48bf5SDavid du Colombier 201*3ff48bf5SDavid du Colombier /* try ticket request using just user key */ 202*3ff48bf5SDavid du Colombier tr.type = AuthTreq; 203*3ff48bf5SDavid du Colombier strecpy(tr.authid, tr.authid+sizeof tr.authid, user); 204*3ff48bf5SDavid du Colombier strecpy(tr.authdom, tr.authdom+sizeof tr.authdom, dom); 205*3ff48bf5SDavid du Colombier strecpy(tr.hostid, tr.hostid+sizeof tr.hostid, user); 206*3ff48bf5SDavid du Colombier strecpy(tr.uid, tr.uid+sizeof tr.uid, user); 207*3ff48bf5SDavid du Colombier memset(tr.chal, 0xAA, sizeof tr.chal); 208*3ff48bf5SDavid du Colombier convTR2M(&tr, trbuf); 209*3ff48bf5SDavid du Colombier if(_asgetticket(fd, trbuf, tbuf) < 0){ 210*3ff48bf5SDavid du Colombier close(fd); 211*3ff48bf5SDavid du Colombier print("\t_asgetticket failed: %r\n"); 212*3ff48bf5SDavid du Colombier return; 213*3ff48bf5SDavid du Colombier } 214*3ff48bf5SDavid du Colombier convM2T(tbuf, &t, key); 215*3ff48bf5SDavid du Colombier if(t.num != AuthTc){ 216*3ff48bf5SDavid du Colombier print("\tcannot decrypt ticket1 from auth server (bad t.num=0x%.2ux)\n", t.num); 217*3ff48bf5SDavid du Colombier print("\tauth server and you do not agree on key for %s@%s\n", user, dom); 218*3ff48bf5SDavid du Colombier return; 219*3ff48bf5SDavid du Colombier } 220*3ff48bf5SDavid du Colombier if(memcmp(t.chal, tr.chal, sizeof tr.chal) != 0){ 221*3ff48bf5SDavid du Colombier print("\tbad challenge1 from auth server got %.*H wanted %.*H\n", 222*3ff48bf5SDavid du Colombier sizeof t.chal, t.chal, sizeof tr.chal, tr.chal); 223*3ff48bf5SDavid du Colombier print("\tauth server is rogue\n"); 224*3ff48bf5SDavid du Colombier return; 225*3ff48bf5SDavid du Colombier } 226*3ff48bf5SDavid du Colombier 227*3ff48bf5SDavid du Colombier convM2T(tbuf+TICKETLEN, &t, key); 228*3ff48bf5SDavid du Colombier if(t.num != AuthTs){ 229*3ff48bf5SDavid du Colombier print("\tcannot decrypt ticket2 from auth server (bad t.num=0x%.2ux)\n", t.num); 230*3ff48bf5SDavid du Colombier print("\tauth server and you do not agree on key for %s@%s\n", user, dom); 231*3ff48bf5SDavid du Colombier return; 232*3ff48bf5SDavid du Colombier } 233*3ff48bf5SDavid du Colombier if(memcmp(t.chal, tr.chal, sizeof tr.chal) != 0){ 234*3ff48bf5SDavid du Colombier print("\tbad challenge2 from auth server got %.*H wanted %.*H\n", 235*3ff48bf5SDavid du Colombier sizeof t.chal, t.chal, sizeof tr.chal, tr.chal); 236*3ff48bf5SDavid du Colombier print("\tauth server is rogue\n"); 237*3ff48bf5SDavid du Colombier return; 238*3ff48bf5SDavid du Colombier } 239*3ff48bf5SDavid du Colombier print("\tticket request using %s@%s key succeeded\n", user, dom); 240*3ff48bf5SDavid du Colombier 241*3ff48bf5SDavid du Colombier /* try ticket request using bootes key */ 242*3ff48bf5SDavid du Colombier snprint(prompt, sizeof prompt, "\tcpu server owner for domain %s ", dom); 243*3ff48bf5SDavid du Colombier readcons(prompt, "bootes", 0, tr.authid, sizeof tr.authid); 244*3ff48bf5SDavid du Colombier convTR2M(&tr, trbuf); 245*3ff48bf5SDavid du Colombier if(_asgetticket(fd, trbuf, tbuf) < 0){ 246*3ff48bf5SDavid du Colombier close(fd); 247*3ff48bf5SDavid du Colombier print("\t_asgetticket failed: %r\n"); 248*3ff48bf5SDavid du Colombier return; 249*3ff48bf5SDavid du Colombier } 250*3ff48bf5SDavid du Colombier convM2T(tbuf, &t, key); 251*3ff48bf5SDavid du Colombier if(t.num != AuthTc){ 252*3ff48bf5SDavid du Colombier print("\tcannot decrypt ticket1 from auth server (bad t.num=0x%.2ux)\n", t.num); 253*3ff48bf5SDavid du Colombier print("\tauth server and you do not agree on key for %s@%s\n", user, dom); 254*3ff48bf5SDavid du Colombier return; 255*3ff48bf5SDavid du Colombier } 256*3ff48bf5SDavid du Colombier if(memcmp(t.chal, tr.chal, sizeof tr.chal) != 0){ 257*3ff48bf5SDavid du Colombier print("\tbad challenge1 from auth server got %.*H wanted %.*H\n", 258*3ff48bf5SDavid du Colombier sizeof t.chal, t.chal, sizeof tr.chal, tr.chal); 259*3ff48bf5SDavid du Colombier print("\tauth server is rogue\n"); 260*3ff48bf5SDavid du Colombier return; 261*3ff48bf5SDavid du Colombier } 262*3ff48bf5SDavid du Colombier 263*3ff48bf5SDavid du Colombier snprint(prompt, sizeof prompt, "\tpassword for %s@%s [hit enter to skip test]", tr.authid, dom); 264*3ff48bf5SDavid du Colombier readcons(prompt, nil, 1, pw, sizeof pw); 265*3ff48bf5SDavid du Colombier if(pw[0] == '\0'){ 266*3ff48bf5SDavid du Colombier nobootes=1; 267*3ff48bf5SDavid du Colombier goto Nobootes; 268*3ff48bf5SDavid du Colombier } 269*3ff48bf5SDavid du Colombier nobootes = 0; 270*3ff48bf5SDavid du Colombier passtokey(booteskey, pw); 271*3ff48bf5SDavid du Colombier 272*3ff48bf5SDavid du Colombier convM2T(tbuf+TICKETLEN, &t, booteskey); 273*3ff48bf5SDavid du Colombier if(t.num != AuthTs){ 274*3ff48bf5SDavid du Colombier print("\tcannot decrypt ticket2 from auth server (bad t.num=0x%.2ux)\n", t.num); 275*3ff48bf5SDavid du Colombier print("\tauth server and you do not agree on key for %s@%s\n", tr.authid, dom); 276*3ff48bf5SDavid du Colombier return; 277*3ff48bf5SDavid du Colombier } 278*3ff48bf5SDavid du Colombier if(memcmp(t.chal, tr.chal, sizeof tr.chal) != 0){ 279*3ff48bf5SDavid du Colombier print("\tbad challenge2 from auth server got %.*H wanted %.*H\n", 280*3ff48bf5SDavid du Colombier sizeof t.chal, t.chal, sizeof tr.chal, tr.chal); 281*3ff48bf5SDavid du Colombier print("\tauth server is rogue\n"); 282*3ff48bf5SDavid du Colombier return; 283*3ff48bf5SDavid du Colombier } 284*3ff48bf5SDavid du Colombier print("\tticket request using %s@%s key succeeded\n", tr.authid, dom); 285*3ff48bf5SDavid du Colombier 286*3ff48bf5SDavid du Colombier Nobootes:; 287*3ff48bf5SDavid du Colombier 288*3ff48bf5SDavid du Colombier /* try p9sk1 exchange with local factotum to test that key is right */ 289*3ff48bf5SDavid du Colombier 290*3ff48bf5SDavid du Colombier 291*3ff48bf5SDavid du Colombier /* 292*3ff48bf5SDavid du Colombier * try p9sk1 exchange with factotum on 293*3ff48bf5SDavid du Colombier * auth server (assumes running cpu service) 294*3ff48bf5SDavid du Colombier * to test that bootes key is right over there 295*3ff48bf5SDavid du Colombier */ 296*3ff48bf5SDavid du Colombier 297*3ff48bf5SDavid du Colombier } 298*3ff48bf5SDavid du Colombier 299*3ff48bf5SDavid du Colombier void 300*3ff48bf5SDavid du Colombier main(int argc, char **argv) 301*3ff48bf5SDavid du Colombier { 302*3ff48bf5SDavid du Colombier quotefmtinstall(); 303*3ff48bf5SDavid du Colombier fmtinstall('A', _attrfmt); 304*3ff48bf5SDavid du Colombier fmtinstall('H', encodefmt); 305*3ff48bf5SDavid du Colombier 306*3ff48bf5SDavid du Colombier ARGBEGIN{ 307*3ff48bf5SDavid du Colombier default: 308*3ff48bf5SDavid du Colombier usage(); 309*3ff48bf5SDavid du Colombier }ARGEND 310*3ff48bf5SDavid du Colombier 311*3ff48bf5SDavid du Colombier if(argc != 0) 312*3ff48bf5SDavid du Colombier usage(); 313*3ff48bf5SDavid du Colombier 314*3ff48bf5SDavid du Colombier debugfactotumkeys(); 315*3ff48bf5SDavid du Colombier } 316