debug.c 7.2 KB

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