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. }
  85. void authdialfutz(char*, char*);
  86. void authfutz(char*, char*);
  87. /* scan factotum for p9sk1 keys; check them */
  88. void
  89. debugfactotumkeys(void)
  90. {
  91. char *s, *dom, *proto, *user;
  92. int found;
  93. Attr *a;
  94. Biobuf *b;
  95. b = Bopen("/mnt/factotum/ctl", OREAD);
  96. if(b == nil){
  97. fprint(2, "debug: cannot open /mnt/factotum/ctl\n");
  98. return;
  99. }
  100. found = 0;
  101. while((s = Brdstr(b, '\n', 1)) != nil){
  102. if(strncmp(s, "key ", 4) != 0){
  103. print("malformed ctl line: %s\n", s);
  104. free(s);
  105. continue;
  106. }
  107. a = _parseattr(s+4);
  108. free(s);
  109. proto = _strfindattr(a, "proto");
  110. if(proto==nil || strcmp(proto, "p9sk1")!=0)
  111. continue;
  112. dom = _strfindattr(a, "dom");
  113. if(dom == nil){
  114. print("p9sk1 key with no dom: %A\n", a);
  115. _freeattr(a);
  116. continue;
  117. }
  118. user = _strfindattr(a, "user");
  119. if(user == nil){
  120. print("p9sk1 key with no user: %A\n", a);
  121. _freeattr(a);
  122. continue;
  123. }
  124. print("p9sk1 key: %A\n", a);
  125. found = 1;
  126. authdialfutz(dom, user);
  127. _freeattr(a);
  128. }
  129. if(!found)
  130. print("no p9sk1 keys found in factotum\n");
  131. }
  132. void
  133. authdialfutz(char *dom, char *user)
  134. {
  135. int fd;
  136. char *server;
  137. char *addr;
  138. fd = authdial(nil, dom);
  139. if(fd >= 0){
  140. print("\tsuccessfully dialed auth server\n");
  141. close(fd);
  142. authfutz(dom, user);
  143. return;
  144. }
  145. print("\tcannot dial auth server: %r\n");
  146. server = csgetvalue(nil, "authdom", dom, "auth", nil);
  147. if(server){
  148. print("\tcsquery authdom=%q auth=%s\n", dom, server);
  149. free(server);
  150. return;
  151. }
  152. print("\tcsquery authdom=%q auth=* failed\n", dom);
  153. server = csgetvalue(nil, "dom", dom, "auth", nil);
  154. if(server){
  155. print("\tcsquery dom=%q auth=%q\n", dom, server);
  156. free(server);
  157. return;
  158. }
  159. print("\tcsquery dom=%q auth=*\n", dom);
  160. fd = dial(addr=netmkaddr("$auth", nil, "ticket"), 0, 0, 0);
  161. if(fd >= 0){
  162. print("\tdial %s succeeded\n", addr);
  163. close(fd);
  164. return;
  165. }
  166. print("\tdial %s failed: %r\n", addr);
  167. }
  168. void
  169. authfutz(char *dom, char *user)
  170. {
  171. int fd, nobootes;
  172. char pw[128], prompt[128], key[DESKEYLEN], booteskey[DESKEYLEN], tbuf[2*TICKETLEN],
  173. trbuf[TICKREQLEN];
  174. Ticket t;
  175. Ticketreq tr;
  176. snprint(prompt, sizeof prompt, "\tpassword for %s@%s [hit enter to skip test]", user, dom);
  177. readcons(prompt, nil, 1, pw, sizeof pw);
  178. if(pw[0] == '\0')
  179. return;
  180. passtokey(key, pw);
  181. fd = authdial(nil, dom);
  182. if(fd < 0){
  183. print("\tauthdial failed(!): %r\n");
  184. return;
  185. }
  186. /* try ticket request using just user key */
  187. tr.type = AuthTreq;
  188. strecpy(tr.authid, tr.authid+sizeof tr.authid, user);
  189. strecpy(tr.authdom, tr.authdom+sizeof tr.authdom, dom);
  190. strecpy(tr.hostid, tr.hostid+sizeof tr.hostid, user);
  191. strecpy(tr.uid, tr.uid+sizeof tr.uid, user);
  192. memset(tr.chal, 0xAA, sizeof tr.chal);
  193. convTR2M(&tr, trbuf);
  194. if(_asgetticket(fd, trbuf, tbuf) < 0){
  195. close(fd);
  196. print("\t_asgetticket failed: %r\n");
  197. return;
  198. }
  199. convM2T(tbuf, &t, key);
  200. if(t.num != AuthTc){
  201. print("\tcannot decrypt ticket1 from auth server (bad t.num=0x%.2ux)\n", t.num);
  202. print("\tauth server and you do not agree on key for %s@%s\n", user, dom);
  203. return;
  204. }
  205. if(memcmp(t.chal, tr.chal, sizeof tr.chal) != 0){
  206. print("\tbad challenge1 from auth server got %.*H wanted %.*H\n",
  207. sizeof t.chal, t.chal, sizeof tr.chal, tr.chal);
  208. print("\tauth server is rogue\n");
  209. return;
  210. }
  211. convM2T(tbuf+TICKETLEN, &t, key);
  212. if(t.num != AuthTs){
  213. print("\tcannot decrypt ticket2 from auth server (bad t.num=0x%.2ux)\n", t.num);
  214. print("\tauth server and you do not agree on key for %s@%s\n", user, dom);
  215. return;
  216. }
  217. if(memcmp(t.chal, tr.chal, sizeof tr.chal) != 0){
  218. print("\tbad challenge2 from auth server got %.*H wanted %.*H\n",
  219. sizeof t.chal, t.chal, sizeof tr.chal, tr.chal);
  220. print("\tauth server is rogue\n");
  221. return;
  222. }
  223. print("\tticket request using %s@%s key succeeded\n", user, dom);
  224. /* try ticket request using bootes key */
  225. snprint(prompt, sizeof prompt, "\tcpu server owner for domain %s ", dom);
  226. readcons(prompt, "bootes", 0, tr.authid, sizeof tr.authid);
  227. convTR2M(&tr, trbuf);
  228. if(_asgetticket(fd, trbuf, tbuf) < 0){
  229. close(fd);
  230. print("\t_asgetticket failed: %r\n");
  231. return;
  232. }
  233. convM2T(tbuf, &t, key);
  234. if(t.num != AuthTc){
  235. print("\tcannot decrypt ticket1 from auth server (bad t.num=0x%.2ux)\n", t.num);
  236. print("\tauth server and you do not agree on key for %s@%s\n", user, dom);
  237. return;
  238. }
  239. if(memcmp(t.chal, tr.chal, sizeof tr.chal) != 0){
  240. print("\tbad challenge1 from auth server got %.*H wanted %.*H\n",
  241. sizeof t.chal, t.chal, sizeof tr.chal, tr.chal);
  242. print("\tauth server is rogue\n");
  243. return;
  244. }
  245. snprint(prompt, sizeof prompt, "\tpassword for %s@%s [hit enter to skip test]", tr.authid, dom);
  246. readcons(prompt, nil, 1, pw, sizeof pw);
  247. if(pw[0] == '\0'){
  248. nobootes=1;
  249. goto Nobootes;
  250. }
  251. nobootes = 0;
  252. passtokey(booteskey, pw);
  253. convM2T(tbuf+TICKETLEN, &t, booteskey);
  254. if(t.num != AuthTs){
  255. print("\tcannot decrypt ticket2 from auth server (bad t.num=0x%.2ux)\n", t.num);
  256. print("\tauth server and you do not agree on key for %s@%s\n", tr.authid, dom);
  257. return;
  258. }
  259. if(memcmp(t.chal, tr.chal, sizeof tr.chal) != 0){
  260. print("\tbad challenge2 from auth server got %.*H wanted %.*H\n",
  261. sizeof t.chal, t.chal, sizeof tr.chal, tr.chal);
  262. print("\tauth server is rogue\n");
  263. return;
  264. }
  265. print("\tticket request using %s@%s key succeeded\n", tr.authid, dom);
  266. Nobootes:;
  267. USED(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. }