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