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