Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
static char*
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
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
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
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
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
}