13ff48bf5SDavid du Colombier /*
23ff48bf5SDavid du Colombier * Test various aspects of the authentication setup.
33ff48bf5SDavid du Colombier */
43ff48bf5SDavid du Colombier
53ff48bf5SDavid du Colombier #include <u.h>
63ff48bf5SDavid du Colombier #include <libc.h>
73ff48bf5SDavid du Colombier #include <bio.h>
83ff48bf5SDavid du Colombier #include <ndb.h>
93ff48bf5SDavid du Colombier #include <auth.h>
103ff48bf5SDavid du Colombier #include <authsrv.h>
113ff48bf5SDavid du Colombier
12*4727cc49SDavid du Colombier /* private copy with added debugging */
13*4727cc49SDavid du Colombier int
authdial(char * netroot,char * dom)14*4727cc49SDavid du Colombier authdial(char *netroot, char *dom)
15*4727cc49SDavid du Colombier {
16*4727cc49SDavid du Colombier char *p;
17*4727cc49SDavid du Colombier int rv;
18*4727cc49SDavid du Colombier
19*4727cc49SDavid du Colombier if(dom != nil){
20*4727cc49SDavid du Colombier /* look up an auth server in an authentication domain */
21*4727cc49SDavid du Colombier p = csgetvalue(netroot, "authdom", dom, "auth", nil);
22*4727cc49SDavid du Colombier
23*4727cc49SDavid du Colombier /* if that didn't work, just try the IP domain */
24*4727cc49SDavid du Colombier if(p == nil)
25*4727cc49SDavid du Colombier p = csgetvalue(netroot, "dom", dom, "auth", nil);
26*4727cc49SDavid du Colombier if(p == nil){
27*4727cc49SDavid du Colombier werrstr("no auth server found for %s", dom);
28*4727cc49SDavid du Colombier return -1;
29*4727cc49SDavid du Colombier }
30*4727cc49SDavid du Colombier print("\tdialing auth server %s\n",
31*4727cc49SDavid du Colombier netmkaddr(p, netroot, "ticket"));
32*4727cc49SDavid du Colombier rv = dial(netmkaddr(p, netroot, "ticket"), 0, 0, 0);
33*4727cc49SDavid du Colombier free(p);
34*4727cc49SDavid du Colombier return rv;
35*4727cc49SDavid du Colombier } else
36*4727cc49SDavid du Colombier /* look for one relative to my machine */
37*4727cc49SDavid du Colombier return dial(netmkaddr("$auth", netroot, "ticket"), 0, 0, 0);
38*4727cc49SDavid du Colombier }
39*4727cc49SDavid du Colombier
403ff48bf5SDavid du Colombier void
usage(void)413ff48bf5SDavid du Colombier usage(void)
423ff48bf5SDavid du Colombier {
433ff48bf5SDavid du Colombier fprint(2, "usage: auth/debug\n");
443ff48bf5SDavid du Colombier exits("usage");
453ff48bf5SDavid du Colombier }
463ff48bf5SDavid du Colombier
473ff48bf5SDavid du Colombier static char*
readcons(char * prompt,char * def,int raw,char * buf,int nbuf)483ff48bf5SDavid du Colombier readcons(char *prompt, char *def, int raw, char *buf, int nbuf)
493ff48bf5SDavid du Colombier {
503ff48bf5SDavid du Colombier int fdin, fdout, ctl, n, m;
513ff48bf5SDavid du Colombier char line[10];
523ff48bf5SDavid du Colombier
533ff48bf5SDavid du Colombier fdin = open("/dev/cons", OREAD);
543ff48bf5SDavid du Colombier if(fdin < 0)
553ff48bf5SDavid du Colombier fdin = 0;
563ff48bf5SDavid du Colombier fdout = open("/dev/cons", OWRITE);
573ff48bf5SDavid du Colombier if(fdout < 0)
583ff48bf5SDavid du Colombier fdout = 1;
593ff48bf5SDavid du Colombier if(def != nil)
603ff48bf5SDavid du Colombier fprint(fdout, "%s[%s]: ", prompt, def);
613ff48bf5SDavid du Colombier else
623ff48bf5SDavid du Colombier fprint(fdout, "%s: ", prompt);
633ff48bf5SDavid du Colombier if(raw){
643ff48bf5SDavid du Colombier ctl = open("/dev/consctl", OWRITE);
653ff48bf5SDavid du Colombier if(ctl >= 0)
663ff48bf5SDavid du Colombier write(ctl, "rawon", 5);
673ff48bf5SDavid du Colombier } else
683ff48bf5SDavid du Colombier ctl = -1;
693ff48bf5SDavid du Colombier
703ff48bf5SDavid du Colombier m = 0;
713ff48bf5SDavid du Colombier for(;;){
723ff48bf5SDavid du Colombier n = read(fdin, line, 1);
733ff48bf5SDavid du Colombier if(n == 0){
743ff48bf5SDavid du Colombier close(ctl);
753ff48bf5SDavid du Colombier werrstr("readcons: EOF");
763ff48bf5SDavid du Colombier return nil;
773ff48bf5SDavid du Colombier }
783ff48bf5SDavid du Colombier if(n < 0){
793ff48bf5SDavid du Colombier close(ctl);
803ff48bf5SDavid du Colombier werrstr("can't read cons");
813ff48bf5SDavid du Colombier return nil;
823ff48bf5SDavid du Colombier }
833ff48bf5SDavid du Colombier if(line[0] == 0x7f)
843ff48bf5SDavid du Colombier exits(0);
853ff48bf5SDavid du Colombier if(n == 0 || line[0] == '\n' || line[0] == '\r'){
863ff48bf5SDavid du Colombier if(raw){
873ff48bf5SDavid du Colombier write(ctl, "rawoff", 6);
883ff48bf5SDavid du Colombier write(fdout, "\n", 1);
893ff48bf5SDavid du Colombier close(ctl);
903ff48bf5SDavid du Colombier }
913ff48bf5SDavid du Colombier buf[m] = '\0';
923ff48bf5SDavid du Colombier if(buf[0]=='\0' && def)
933ff48bf5SDavid du Colombier strcpy(buf, def);
943ff48bf5SDavid du Colombier return buf;
953ff48bf5SDavid du Colombier }
963ff48bf5SDavid du Colombier if(line[0] == '\b'){
973ff48bf5SDavid du Colombier if(m > 0)
983ff48bf5SDavid du Colombier m--;
993ff48bf5SDavid du Colombier }else if(line[0] == 0x15){ /* ^U: line kill */
1003ff48bf5SDavid du Colombier m = 0;
1013ff48bf5SDavid du Colombier if(def != nil)
1023ff48bf5SDavid du Colombier fprint(fdout, "%s[%s]: ", prompt, def);
1033ff48bf5SDavid du Colombier else
1043ff48bf5SDavid du Colombier fprint(fdout, "%s: ", prompt);
1053ff48bf5SDavid du Colombier }else{
1063ff48bf5SDavid du Colombier if(m >= nbuf-1){
1073ff48bf5SDavid du Colombier fprint(fdout, "line too long\n");
1083ff48bf5SDavid du Colombier m = 0;
1093ff48bf5SDavid du Colombier if(def != nil)
1103ff48bf5SDavid du Colombier fprint(fdout, "%s[%s]: ", prompt, def);
1113ff48bf5SDavid du Colombier else
1123ff48bf5SDavid du Colombier fprint(fdout, "%s: ", prompt);
1133ff48bf5SDavid du Colombier }else
1143ff48bf5SDavid du Colombier buf[m++] = line[0];
1153ff48bf5SDavid du Colombier }
1163ff48bf5SDavid du Colombier }
1173ff48bf5SDavid du Colombier }
1183ff48bf5SDavid du Colombier
1193ff48bf5SDavid du Colombier void authdialfutz(char*, char*);
1203ff48bf5SDavid du Colombier void authfutz(char*, char*);
1213ff48bf5SDavid du Colombier
1223ff48bf5SDavid du Colombier /* scan factotum for p9sk1 keys; check them */
1233ff48bf5SDavid du Colombier void
debugfactotumkeys(void)1243ff48bf5SDavid du Colombier debugfactotumkeys(void)
1253ff48bf5SDavid du Colombier {
1263ff48bf5SDavid du Colombier char *s, *dom, *proto, *user;
1273ff48bf5SDavid du Colombier int found;
1283ff48bf5SDavid du Colombier Attr *a;
1293ff48bf5SDavid du Colombier Biobuf *b;
1303ff48bf5SDavid du Colombier
1313ff48bf5SDavid du Colombier b = Bopen("/mnt/factotum/ctl", OREAD);
1323ff48bf5SDavid du Colombier if(b == nil){
133d854de59SDavid du Colombier fprint(2, "debug: cannot open /mnt/factotum/ctl\n");
1343ff48bf5SDavid du Colombier return;
1353ff48bf5SDavid du Colombier }
1363ff48bf5SDavid du Colombier found = 0;
1373ff48bf5SDavid du Colombier while((s = Brdstr(b, '\n', 1)) != nil){
1383ff48bf5SDavid du Colombier if(strncmp(s, "key ", 4) != 0){
1393ff48bf5SDavid du Colombier print("malformed ctl line: %s\n", s);
1403ff48bf5SDavid du Colombier free(s);
1413ff48bf5SDavid du Colombier continue;
1423ff48bf5SDavid du Colombier }
1433ff48bf5SDavid du Colombier a = _parseattr(s+4);
1443ff48bf5SDavid du Colombier free(s);
1452ebbfa15SDavid du Colombier proto = _strfindattr(a, "proto");
1463ff48bf5SDavid du Colombier if(proto==nil || strcmp(proto, "p9sk1")!=0)
1473ff48bf5SDavid du Colombier continue;
1482ebbfa15SDavid du Colombier dom = _strfindattr(a, "dom");
1493ff48bf5SDavid du Colombier if(dom == nil){
1503ff48bf5SDavid du Colombier print("p9sk1 key with no dom: %A\n", a);
1513ff48bf5SDavid du Colombier _freeattr(a);
1523ff48bf5SDavid du Colombier continue;
1533ff48bf5SDavid du Colombier }
1542ebbfa15SDavid du Colombier user = _strfindattr(a, "user");
1553ff48bf5SDavid du Colombier if(user == nil){
1563ff48bf5SDavid du Colombier print("p9sk1 key with no user: %A\n", a);
1573ff48bf5SDavid du Colombier _freeattr(a);
1583ff48bf5SDavid du Colombier continue;
1593ff48bf5SDavid du Colombier }
1603ff48bf5SDavid du Colombier print("p9sk1 key: %A\n", a);
1613ff48bf5SDavid du Colombier found = 1;
1623ff48bf5SDavid du Colombier authdialfutz(dom, user);
1633ff48bf5SDavid du Colombier _freeattr(a);
1643ff48bf5SDavid du Colombier }
1653ff48bf5SDavid du Colombier if(!found)
1663ff48bf5SDavid du Colombier print("no p9sk1 keys found in factotum\n");
1673ff48bf5SDavid du Colombier }
1683ff48bf5SDavid du Colombier
1693ff48bf5SDavid du Colombier void
authdialfutz(char * dom,char * user)1703ff48bf5SDavid du Colombier authdialfutz(char *dom, char *user)
1713ff48bf5SDavid du Colombier {
1723ff48bf5SDavid du Colombier int fd;
17357837e0bSDavid du Colombier char *server;
1743ff48bf5SDavid du Colombier char *addr;
1753ff48bf5SDavid du Colombier
1763ff48bf5SDavid du Colombier fd = authdial(nil, dom);
1773ff48bf5SDavid du Colombier if(fd >= 0){
1783ff48bf5SDavid du Colombier print("\tsuccessfully dialed auth server\n");
1793ff48bf5SDavid du Colombier close(fd);
1803ff48bf5SDavid du Colombier authfutz(dom, user);
1813ff48bf5SDavid du Colombier return;
1823ff48bf5SDavid du Colombier }
1833ff48bf5SDavid du Colombier print("\tcannot dial auth server: %r\n");
18457837e0bSDavid du Colombier server = csgetvalue(nil, "authdom", dom, "auth", nil);
18557837e0bSDavid du Colombier if(server){
1863ff48bf5SDavid du Colombier print("\tcsquery authdom=%q auth=%s\n", dom, server);
18757837e0bSDavid du Colombier free(server);
1883ff48bf5SDavid du Colombier return;
1893ff48bf5SDavid du Colombier }
1903ff48bf5SDavid du Colombier print("\tcsquery authdom=%q auth=* failed\n", dom);
19157837e0bSDavid du Colombier server = csgetvalue(nil, "dom", dom, "auth", nil);
19257837e0bSDavid du Colombier if(server){
1933ff48bf5SDavid du Colombier print("\tcsquery dom=%q auth=%q\n", dom, server);
19457837e0bSDavid du Colombier free(server);
1953ff48bf5SDavid du Colombier return;
1963ff48bf5SDavid du Colombier }
19757837e0bSDavid du Colombier print("\tcsquery dom=%q auth=*\n", dom);
1983ff48bf5SDavid du Colombier
19957837e0bSDavid du Colombier fd = dial(addr=netmkaddr("$auth", nil, "ticket"), 0, 0, 0);
2003ff48bf5SDavid du Colombier if(fd >= 0){
2013ff48bf5SDavid du Colombier print("\tdial %s succeeded\n", addr);
2023ff48bf5SDavid du Colombier close(fd);
2033ff48bf5SDavid du Colombier return;
2043ff48bf5SDavid du Colombier }
2053ff48bf5SDavid du Colombier print("\tdial %s failed: %r\n", addr);
2063ff48bf5SDavid du Colombier }
2073ff48bf5SDavid du Colombier
2083ff48bf5SDavid du Colombier void
authfutz(char * dom,char * user)2093ff48bf5SDavid du Colombier authfutz(char *dom, char *user)
2103ff48bf5SDavid du Colombier {
2113ff48bf5SDavid du Colombier int fd, nobootes;
2123ff48bf5SDavid du Colombier char pw[128], prompt[128], key[DESKEYLEN], booteskey[DESKEYLEN], tbuf[2*TICKETLEN],
2133ff48bf5SDavid du Colombier trbuf[TICKREQLEN];
2143ff48bf5SDavid du Colombier Ticket t;
2153ff48bf5SDavid du Colombier Ticketreq tr;
2163ff48bf5SDavid du Colombier
2173ff48bf5SDavid du Colombier snprint(prompt, sizeof prompt, "\tpassword for %s@%s [hit enter to skip test]", user, dom);
2183ff48bf5SDavid du Colombier readcons(prompt, nil, 1, pw, sizeof pw);
2193ff48bf5SDavid du Colombier if(pw[0] == '\0')
2203ff48bf5SDavid du Colombier return;
2213ff48bf5SDavid du Colombier passtokey(key, pw);
2223ff48bf5SDavid du Colombier
2233ff48bf5SDavid du Colombier fd = authdial(nil, dom);
2243ff48bf5SDavid du Colombier if(fd < 0){
2253ff48bf5SDavid du Colombier print("\tauthdial failed(!): %r\n");
2263ff48bf5SDavid du Colombier return;
2273ff48bf5SDavid du Colombier }
2283ff48bf5SDavid du Colombier
2293ff48bf5SDavid du Colombier /* try ticket request using just user key */
2303ff48bf5SDavid du Colombier tr.type = AuthTreq;
2313ff48bf5SDavid du Colombier strecpy(tr.authid, tr.authid+sizeof tr.authid, user);
2323ff48bf5SDavid du Colombier strecpy(tr.authdom, tr.authdom+sizeof tr.authdom, dom);
2333ff48bf5SDavid du Colombier strecpy(tr.hostid, tr.hostid+sizeof tr.hostid, user);
2343ff48bf5SDavid du Colombier strecpy(tr.uid, tr.uid+sizeof tr.uid, user);
2353ff48bf5SDavid du Colombier memset(tr.chal, 0xAA, sizeof tr.chal);
2363ff48bf5SDavid du Colombier convTR2M(&tr, trbuf);
2373ff48bf5SDavid du Colombier if(_asgetticket(fd, trbuf, tbuf) < 0){
2383ff48bf5SDavid du Colombier close(fd);
2393ff48bf5SDavid du Colombier print("\t_asgetticket failed: %r\n");
2403ff48bf5SDavid du Colombier return;
2413ff48bf5SDavid du Colombier }
2423ff48bf5SDavid du Colombier convM2T(tbuf, &t, key);
2433ff48bf5SDavid du Colombier if(t.num != AuthTc){
2443ff48bf5SDavid du Colombier print("\tcannot decrypt ticket1 from auth server (bad t.num=0x%.2ux)\n", t.num);
2453ff48bf5SDavid du Colombier print("\tauth server and you do not agree on key for %s@%s\n", user, dom);
2463ff48bf5SDavid du Colombier return;
2473ff48bf5SDavid du Colombier }
2483ff48bf5SDavid du Colombier if(memcmp(t.chal, tr.chal, sizeof tr.chal) != 0){
2493ff48bf5SDavid du Colombier print("\tbad challenge1 from auth server got %.*H wanted %.*H\n",
2503ff48bf5SDavid du Colombier sizeof t.chal, t.chal, sizeof tr.chal, tr.chal);
2513ff48bf5SDavid du Colombier print("\tauth server is rogue\n");
2523ff48bf5SDavid du Colombier return;
2533ff48bf5SDavid du Colombier }
2543ff48bf5SDavid du Colombier
2553ff48bf5SDavid du Colombier convM2T(tbuf+TICKETLEN, &t, key);
2563ff48bf5SDavid du Colombier if(t.num != AuthTs){
2573ff48bf5SDavid du Colombier print("\tcannot decrypt ticket2 from auth server (bad t.num=0x%.2ux)\n", t.num);
2583ff48bf5SDavid du Colombier print("\tauth server and you do not agree on key for %s@%s\n", user, dom);
2593ff48bf5SDavid du Colombier return;
2603ff48bf5SDavid du Colombier }
2613ff48bf5SDavid du Colombier if(memcmp(t.chal, tr.chal, sizeof tr.chal) != 0){
2623ff48bf5SDavid du Colombier print("\tbad challenge2 from auth server got %.*H wanted %.*H\n",
2633ff48bf5SDavid du Colombier sizeof t.chal, t.chal, sizeof tr.chal, tr.chal);
2643ff48bf5SDavid du Colombier print("\tauth server is rogue\n");
2653ff48bf5SDavid du Colombier return;
2663ff48bf5SDavid du Colombier }
2673ff48bf5SDavid du Colombier print("\tticket request using %s@%s key succeeded\n", user, dom);
2683ff48bf5SDavid du Colombier
2693ff48bf5SDavid du Colombier /* try ticket request using bootes key */
2703ff48bf5SDavid du Colombier snprint(prompt, sizeof prompt, "\tcpu server owner for domain %s ", dom);
2713ff48bf5SDavid du Colombier readcons(prompt, "bootes", 0, tr.authid, sizeof tr.authid);
2723ff48bf5SDavid du Colombier convTR2M(&tr, trbuf);
2733ff48bf5SDavid du Colombier if(_asgetticket(fd, trbuf, tbuf) < 0){
2743ff48bf5SDavid du Colombier close(fd);
2753ff48bf5SDavid du Colombier print("\t_asgetticket failed: %r\n");
2763ff48bf5SDavid du Colombier return;
2773ff48bf5SDavid du Colombier }
2783ff48bf5SDavid du Colombier convM2T(tbuf, &t, key);
2793ff48bf5SDavid du Colombier if(t.num != AuthTc){
2803ff48bf5SDavid du Colombier print("\tcannot decrypt ticket1 from auth server (bad t.num=0x%.2ux)\n", t.num);
2813ff48bf5SDavid du Colombier print("\tauth server and you do not agree on key for %s@%s\n", user, dom);
2823ff48bf5SDavid du Colombier return;
2833ff48bf5SDavid du Colombier }
2843ff48bf5SDavid du Colombier if(memcmp(t.chal, tr.chal, sizeof tr.chal) != 0){
2853ff48bf5SDavid du Colombier print("\tbad challenge1 from auth server got %.*H wanted %.*H\n",
2863ff48bf5SDavid du Colombier sizeof t.chal, t.chal, sizeof tr.chal, tr.chal);
2873ff48bf5SDavid du Colombier print("\tauth server is rogue\n");
2883ff48bf5SDavid du Colombier return;
2893ff48bf5SDavid du Colombier }
2903ff48bf5SDavid du Colombier
2913ff48bf5SDavid du Colombier snprint(prompt, sizeof prompt, "\tpassword for %s@%s [hit enter to skip test]", tr.authid, dom);
2923ff48bf5SDavid du Colombier readcons(prompt, nil, 1, pw, sizeof pw);
2933ff48bf5SDavid du Colombier if(pw[0] == '\0'){
2943ff48bf5SDavid du Colombier nobootes=1;
2953ff48bf5SDavid du Colombier goto Nobootes;
2963ff48bf5SDavid du Colombier }
2973ff48bf5SDavid du Colombier nobootes = 0;
2983ff48bf5SDavid du Colombier passtokey(booteskey, pw);
2993ff48bf5SDavid du Colombier
3003ff48bf5SDavid du Colombier convM2T(tbuf+TICKETLEN, &t, booteskey);
3013ff48bf5SDavid du Colombier if(t.num != AuthTs){
3023ff48bf5SDavid du Colombier print("\tcannot decrypt ticket2 from auth server (bad t.num=0x%.2ux)\n", t.num);
3033ff48bf5SDavid du Colombier print("\tauth server and you do not agree on key for %s@%s\n", tr.authid, dom);
3043ff48bf5SDavid du Colombier return;
3053ff48bf5SDavid du Colombier }
3063ff48bf5SDavid du Colombier if(memcmp(t.chal, tr.chal, sizeof tr.chal) != 0){
3073ff48bf5SDavid du Colombier print("\tbad challenge2 from auth server got %.*H wanted %.*H\n",
3083ff48bf5SDavid du Colombier sizeof t.chal, t.chal, sizeof tr.chal, tr.chal);
3093ff48bf5SDavid du Colombier print("\tauth server is rogue\n");
3103ff48bf5SDavid du Colombier return;
3113ff48bf5SDavid du Colombier }
3123ff48bf5SDavid du Colombier print("\tticket request using %s@%s key succeeded\n", tr.authid, dom);
3133ff48bf5SDavid du Colombier
3143ff48bf5SDavid du Colombier Nobootes:;
315453ee12cSDavid du Colombier USED(nobootes);
3163ff48bf5SDavid du Colombier
3173ff48bf5SDavid du Colombier /* try p9sk1 exchange with local factotum to test that key is right */
3183ff48bf5SDavid du Colombier
3193ff48bf5SDavid du Colombier
3203ff48bf5SDavid du Colombier /*
3213ff48bf5SDavid du Colombier * try p9sk1 exchange with factotum on
3223ff48bf5SDavid du Colombier * auth server (assumes running cpu service)
3233ff48bf5SDavid du Colombier * to test that bootes key is right over there
3243ff48bf5SDavid du Colombier */
3253ff48bf5SDavid du Colombier
3263ff48bf5SDavid du Colombier }
3273ff48bf5SDavid du Colombier
3283ff48bf5SDavid du Colombier void
main(int argc,char ** argv)3293ff48bf5SDavid du Colombier main(int argc, char **argv)
3303ff48bf5SDavid du Colombier {
3313ff48bf5SDavid du Colombier quotefmtinstall();
3323ff48bf5SDavid du Colombier fmtinstall('A', _attrfmt);
3333ff48bf5SDavid du Colombier fmtinstall('H', encodefmt);
3343ff48bf5SDavid du Colombier
3353ff48bf5SDavid du Colombier ARGBEGIN{
3363ff48bf5SDavid du Colombier default:
3373ff48bf5SDavid du Colombier usage();
3383ff48bf5SDavid du Colombier }ARGEND
3393ff48bf5SDavid du Colombier
3403ff48bf5SDavid du Colombier if(argc != 0)
3413ff48bf5SDavid du Colombier usage();
3423ff48bf5SDavid du Colombier
3433ff48bf5SDavid du Colombier debugfactotumkeys();
3443ff48bf5SDavid du Colombier }
345