]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/auth/debug.c
merge
[plan9front.git] / sys / src / cmd / auth / debug.c
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 void authdialfutz(char*, char*, char*);
48 void authfutz(char*, char*, char*);
49
50 /* scan factotum for p9sk1 keys; check them */
51 void
52 debugfactotumkeys(void)
53 {
54         char *s, *dom, *proto, *user;
55         int found;
56         Attr *a;
57         Biobuf *b;
58
59         b = Bopen("/mnt/factotum/ctl", OREAD);
60         if(b == nil){
61                 fprint(2, "debug: cannot open /mnt/factotum/ctl\n");
62                 return;
63         }
64         found = 0;
65         while((s = Brdstr(b, '\n', 1)) != nil){
66                 if(strncmp(s, "key ", 4) != 0){
67                         print("malformed ctl line: %s\n", s);
68                         free(s);
69                         continue;
70                 }
71                 a = _parseattr(s+4);
72                 free(s);
73                 proto = _strfindattr(a, "proto");
74                 if(proto==nil || (strcmp(proto, "p9sk1")!=0 && strcmp(proto, "dp9ik")!=0))
75                         continue;
76                 dom = _strfindattr(a, "dom");
77                 if(dom == nil){
78                         print("p9sk1 key with no dom: %A\n", a);
79                         _freeattr(a);
80                         continue;
81                 }
82                 user = _strfindattr(a, "user");
83                 if(user == nil){
84                         print("p9sk1 key with no user: %A\n", a);
85                         _freeattr(a);
86                         continue;
87                 }
88                 print("key: %A\n", a);
89                 found = 1;
90                 authdialfutz(dom, user, proto);
91                 _freeattr(a);
92         }
93         if(!found)
94                 print("no p9sk1/dp9ik keys found in factotum\n");
95 }
96
97 void
98 authdialfutz(char *dom, char *user, char *proto)
99 {
100         int fd;
101         char *server;
102         char *addr;
103
104         fd = authdial(nil, dom);
105         if(fd >= 0){
106                 print("\tsuccessfully dialed auth server\n");
107                 close(fd);
108                 authfutz(dom, user, proto);
109                 return;
110         }
111         print("\tcannot dial auth server: %r\n");
112         server = csgetvalue(nil, "authdom", dom, "auth", nil);
113         if(server){
114                 print("\tcsquery authdom=%q auth=%s\n", dom, server);
115                 free(server);
116                 return;
117         }
118         print("\tcsquery authdom=%q auth=* failed\n", dom);
119         server = csgetvalue(nil, "dom", dom, "auth", nil);
120         if(server){
121                 print("\tcsquery dom=%q auth=%q\n", dom, server);
122                 free(server);
123                 return;
124         }
125         print("\tcsquery dom=%q auth=*\n", dom);
126
127         fd = dial(addr=netmkaddr("$auth", nil, "ticket"), 0, 0, 0);
128         if(fd >= 0){
129                 print("\tdial %s succeeded\n", addr);
130                 close(fd);
131                 return;
132         }
133         print("\tdial %s failed: %r\n", addr);
134 }
135
136 int
137 getpakkeys(int fd, Ticketreq *tr, Authkey *akey, Authkey *hkey)
138 {
139         uchar y[PAKYLEN];
140         PAKpriv p;
141         int ret, type;
142
143         ret = -1;
144         type = tr->type;
145         tr->type = AuthPAK;
146         if(_asrequest(fd, tr) < 0 || _asrdresp(fd, (char*)y, 0) < 0)
147                 goto out;
148
149         authpak_hash(akey, tr->authid);
150         authpak_new(&p, akey, y, 1);
151         if(write(fd, y, PAKYLEN) != PAKYLEN
152         || readn(fd, y, PAKYLEN) != PAKYLEN
153         || authpak_finish(&p, akey, y))
154                 goto out;
155
156         authpak_hash(hkey, tr->hostid);
157         authpak_new(&p, hkey, y, 1);
158         if(write(fd, y, PAKYLEN) != PAKYLEN
159         || readn(fd, y, PAKYLEN) != PAKYLEN
160         || authpak_finish(&p, hkey, y))
161                 goto out;
162
163         ret = 0;
164 out:
165         tr->type = type;
166         return ret;
167 }
168
169 void
170 authfutz(char *dom, char *user, char *proto)
171 {
172         int fd, n, m;
173         char prompt[128], tbuf[2*MAXTICKETLEN], *pass;
174         Authkey key, booteskey;
175         Ticket t;
176         Ticketreq tr;
177
178         snprint(prompt, sizeof prompt, "\tpassword for %s@%s [hit enter to skip test]", user, dom);
179         pass = readcons(prompt, nil, 1);
180         if(pass == nil || *pass == 0){
181                 free(pass);
182                 return;
183         }
184         passtokey(&key, pass);
185         booteskey = key;
186         memset(pass, 0, strlen(pass));
187         free(pass);
188
189         fd = authdial(nil, dom);
190         if(fd < 0){
191                 print("\tauthdial failed(!): %r\n");
192                 return;
193         }
194
195         /* try ticket request using just user key */
196         memset(&tr, 0, sizeof(tr));
197         tr.type = AuthTreq;
198         strecpy(tr.authid, tr.authid+sizeof tr.authid, user);
199         strecpy(tr.authdom, tr.authdom+sizeof tr.authdom, dom);
200         strecpy(tr.hostid, tr.hostid+sizeof tr.hostid, user);
201         strecpy(tr.uid, tr.uid+sizeof tr.uid, user);
202         memset(tr.chal, 0xAA, sizeof tr.chal);
203
204         if(strcmp(proto, "dp9ik") == 0 && getpakkeys(fd, &tr, &booteskey, &key) < 0){
205                 print("\tgetpakkeys failed: %r\n");
206                 close(fd);
207                 return;
208         }
209
210         if((n = _asgetticket(fd, &tr, tbuf, sizeof(tbuf))) < 0){
211                 print("\t_asgetticket failed: %r\n");
212                 close(fd);
213                 return;
214         }
215         m = convM2T(tbuf, n, &t, &key);
216         if(t.num != AuthTc){
217                 print("\tcannot decrypt ticket1 from auth server (bad t.num=0x%.2ux)\n", t.num);
218                 print("\tauth server and you do not agree on key for %s@%s\n", user, dom);
219                 return;
220         }
221         if(memcmp(t.chal, tr.chal, sizeof tr.chal) != 0){
222                 print("\tbad challenge1 from auth server got %.*H wanted %.*H\n",
223                         sizeof t.chal, t.chal, sizeof tr.chal, tr.chal);
224                 print("\tauth server is rogue\n");
225                 return;
226         }
227
228         convM2T(tbuf+m, n-m, &t, &booteskey);
229         if(t.num != AuthTs){
230                 print("\tcannot decrypt ticket2 from auth server (bad t.num=0x%.2ux)\n", t.num);
231                 print("\tauth server and you do not agree on key for %s@%s\n", user, dom);
232                 return;
233         }
234         if(memcmp(t.chal, tr.chal, sizeof tr.chal) != 0){
235                 print("\tbad challenge2 from auth server got %.*H wanted %.*H\n",
236                         sizeof t.chal, t.chal, sizeof tr.chal, tr.chal);
237                 print("\tauth server is rogue\n");
238                 return;
239         }
240         print("\tticket request using %s@%s key succeeded\n", user, dom);
241
242         /* try ticket request using bootes key */
243         snprint(prompt, sizeof prompt, "\tcpu server owner for domain %s ", dom);
244         user = readcons(prompt, "glenda", 0);
245         if(user == nil || *user == '\0'){
246                 free(user);
247                 goto Nobootes;
248         }
249         strecpy(tr.authid, tr.authid+sizeof tr.authid, user);
250         free(user);
251         snprint(prompt, sizeof prompt, "\tpassword for %s@%s [hit enter to skip test]", tr.authid, dom);
252         pass = readcons(prompt, nil, 1);
253         if(pass == nil || *pass == '\0'){
254                 free(pass);
255                 goto Nobootes;
256         }
257         passtokey(&booteskey, pass);
258         memset(pass, 0, strlen(pass));
259         free(pass);
260
261         if(strcmp(proto, "dp9ik") == 0 && getpakkeys(fd, &tr, &booteskey, &key) < 0){
262                 print("\tgetpakkeys failed: %r\n");
263                 close(fd);
264                 return;
265         }
266
267         if((n = _asgetticket(fd, &tr, tbuf, sizeof(tbuf))) < 0){
268                 print("\t_asgetticket failed: %r\n");
269                 close(fd);
270                 return;
271         }
272         m = convM2T(tbuf, n, &t, &key);
273         if(t.num != AuthTc){
274                 print("\tcannot decrypt ticket1 from auth server (bad t.num=0x%.2ux)\n", t.num);
275                 print("\tauth server and you do not agree on key for %s@%s\n", tr.hostid, dom);
276                 return;
277         }
278         if(memcmp(t.chal, tr.chal, sizeof tr.chal) != 0){
279                 print("\tbad challenge1 from auth server got %.*H wanted %.*H\n",
280                         sizeof t.chal, t.chal, sizeof tr.chal, tr.chal);
281                 print("\tauth server is rogue\n");
282                 return;
283         }
284         
285         convM2T(tbuf+m, n-m, &t, &booteskey);
286         if(t.num != AuthTs){
287                 print("\tcannot decrypt ticket2 from auth server (bad t.num=0x%.2ux)\n", t.num);
288                 print("\tauth server and you do not agree on key for %s@%s\n", tr.authid, dom);
289                 return;
290         }
291         if(memcmp(t.chal, tr.chal, sizeof tr.chal) != 0){
292                 print("\tbad challenge2 from auth server got %.*H wanted %.*H\n",
293                         sizeof t.chal, t.chal, sizeof tr.chal, tr.chal);
294                 print("\tauth server is rogue\n");
295                 return;
296         }
297         print("\tticket request using %s@%s key succeeded\n", tr.authid, dom);
298
299 Nobootes:;
300         /* try p9sk1 exchange with local factotum to test that key is right */
301
302
303         /*
304          * try p9sk1 exchange with factotum on
305          * auth server (assumes running cpu service)
306          * to test that bootes key is right over there
307          */
308 }
309
310 void
311 main(int argc, char **argv)
312 {
313         quotefmtinstall();
314         fmtinstall('A', _attrfmt);
315         fmtinstall('H', encodefmt);
316
317         ARGBEGIN{
318         default:
319                 usage();
320         }ARGEND
321
322         if(argc != 0)
323                 usage();
324
325         debugfactotumkeys();
326 }