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
authdial(char * netroot,char * dom)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
usage(void)41 usage(void)
42 {
43 fprint(2, "usage: auth/debug\n");
44 exits("usage");
45 }
46
47 static char*
readcons(char * prompt,char * def,int raw,char * buf,int nbuf)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
debugfactotumkeys(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
authdialfutz(char * dom,char * user)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
authfutz(char * dom,char * user)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
main(int argc,char ** argv)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