debug.c 7.8 KB

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