Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <authsrv.h>
4
 
5
static long	finddosfile(int, char*);
6
 
7
static int nvramdebug;
8
 
9
static int
10
check(void *x, int len, uchar sum, char *msg)
11
{
12
	if(nvcsum(x, len) == sum)
13
		return 0;
14
	memset(x, 0, len);
15
	fprint(2, "%s\n", msg);
16
	return 1;
17
}
18
 
19
/*
20
 *  get key info out of nvram.  since there isn't room in the PC's nvram use
21
 *  a disk partition there.
22
 */
23
static struct {
24
	char *cputype;
25
	char *file;
26
	int off;
27
	int len;
28
} nvtab[] = {
29
	"sparc", "#r/nvram", 1024+850, sizeof(Nvrsafe),
30
	"pc", "#S/sdC0/nvram", 0, sizeof(Nvrsafe),
31
	"pc", "#S/sdC0/9fat", -1, sizeof(Nvrsafe),
32
	"pc", "#S/sdC1/nvram", 0, sizeof(Nvrsafe),
33
	"pc", "#S/sdC1/9fat", -1, sizeof(Nvrsafe),
34
	"pc", "#S/sdD0/nvram", 0, sizeof(Nvrsafe),
35
	"pc", "#S/sdD0/9fat", -1, sizeof(Nvrsafe),
36
	"pc", "#S/sdE0/nvram", 0, sizeof(Nvrsafe),
37
	"pc", "#S/sdE0/9fat", -1, sizeof(Nvrsafe),
38
	"pc", "#S/sdF0/nvram", 0, sizeof(Nvrsafe),
39
	"pc", "#S/sdF0/9fat", -1, sizeof(Nvrsafe),
40
	"pc", "#S/sd00/nvram", 0, sizeof(Nvrsafe),
41
	"pc", "#S/sd00/9fat", -1, sizeof(Nvrsafe),
42
	"pc", "#S/sd01/nvram", 0, sizeof(Nvrsafe),
43
	"pc", "#S/sd01/9fat", -1, sizeof(Nvrsafe),
44
	"pc", "#S/sd10/nvram", 0, sizeof(Nvrsafe),
45
	"pc", "#S/sd10/9fat", -1, sizeof(Nvrsafe),
46
	"pc", "#f/fd0disk", -1, 512,	/* 512: #f requires whole sector reads */
47
	"pc", "#f/fd1disk", -1, 512,
48
	"mips", "#r/nvram", 1024+900, sizeof(Nvrsafe),
49
	"power", "#F/flash/flash0", 0x440000, sizeof(Nvrsafe),
50
	"power", "#F/flash/flash", 0x440000, sizeof(Nvrsafe),
51
	"power", "#r/nvram", 4352, sizeof(Nvrsafe),	/* OK for MTX-604e */
52
	"power", "/nvram", 0, sizeof(Nvrsafe),	/* OK for Ucu */
53
	"arm", "#F/flash/flash0", 0x100000, sizeof(Nvrsafe),
54
	"arm", "#F/flash/flash", 0x100000, sizeof(Nvrsafe),
55
	"debug", "/tmp/nvram", 0, sizeof(Nvrsafe),
56
};
57
 
58
static char*
59
readcons(char *prompt, char *def, int raw, char *buf, int nbuf)
60
{
61
	int fdin, fdout, ctl, n, m;
62
	char line[10];
63
 
64
	fdin = open("/dev/cons", OREAD);
65
	if(fdin < 0)
66
		fdin = 0;
67
	fdout = open("/dev/cons", OWRITE);
68
	if(fdout < 0)
69
		fdout = 1;
70
	if(def != nil)
71
		fprint(fdout, "%s[%s]: ", prompt, def);
72
	else
73
		fprint(fdout, "%s: ", prompt);
74
	if(raw){
75
		ctl = open("/dev/consctl", OWRITE);
76
		if(ctl >= 0)
77
			write(ctl, "rawon", 5);
78
	} else
79
		ctl = -1;
80
 
81
	m = 0;
82
	for(;;){
83
		n = read(fdin, line, 1);
84
		if(n == 0){
85
			close(ctl);
86
			werrstr("readcons: EOF");
87
			return nil;
88
		}
89
		if(n < 0){
90
			close(ctl);
91
			werrstr("can't read cons");
92
			return nil;
93
		}
94
		if(line[0] == 0x7f)
95
			exits(0);
96
		if(n == 0 || line[0] == '\n' || line[0] == '\r'){
97
			if(raw){
98
				write(ctl, "rawoff", 6);
99
				write(fdout, "\n", 1);
100
				close(ctl);
101
			}
102
			buf[m] = '\0';
103
			if(buf[0]=='\0' && def)
104
				strcpy(buf, def);
105
			return buf;
106
		}
107
		if(line[0] == '\b'){
108
			if(m > 0)
109
				m--;
110
		}else if(line[0] == 0x15){	/* ^U: line kill */
111
			m = 0;
112
			if(def != nil)
113
				fprint(fdout, "%s[%s]: ", prompt, def);
114
			else
115
				fprint(fdout, "%s: ", prompt);
116
		}else{
117
			if(m >= nbuf-1){
118
				fprint(fdout, "line too long\n");
119
				m = 0;
120
				if(def != nil)
121
					fprint(fdout, "%s[%s]: ", prompt, def);
122
				else
123
					fprint(fdout, "%s: ", prompt);
124
			}else
125
				buf[m++] = line[0];
126
		}
127
	}
128
}
129
 
130
typedef struct {
131
	int	fd;
132
	int	safeoff;
133
	int	safelen;
134
} Nvrwhere;
135
 
136
static char *nvrfile = nil, *cputype = nil;
137
 
138
/* returns with *locp filled in and locp->fd open, if possible */
139
static void
140
findnvram(Nvrwhere *locp)
141
{
142
	char *nvrlen, *nvroff, *nvrcopy, *db, *v[2];
143
	int fd, i, safeoff, safelen;
144
 
145
	if (nvrfile == nil) {
146
		nvrfile = getenv("nvram");
147
		db = getenv("nvramdebug");
148
		nvramdebug = db != nil;
149
		free(db);
150
	}
151
	if (cputype == nil)
152
		cputype = getenv("cputype");
153
	if(cputype == nil)
154
		cputype = strdup("mips");
155
	if(strcmp(cputype, "386")==0 || strcmp(cputype, "alpha")==0) {
156
		free(cputype);
157
		cputype = strdup("pc");
158
	}
159
 
160
	fd = -1;
161
	safeoff = -1;
162
	safelen = -1;
163
	if(nvrfile != nil && *nvrfile != '\0'){
164
		/* accept device and device!file */
165
		nvrcopy = strdup(nvrfile);
166
		i = gettokens(nvrcopy, v, nelem(v), "!");
167
		if (i < 1) {
168
			i = 1;
169
			v[0] = "";
170
			v[1] = nil;
171
		}
172
		if(nvramdebug)
173
			fprint(2, "nvram at %s?...", v[0]);
174
		fd = open(v[0], ORDWR);
175
		if (fd < 0)
176
			fd = open(v[0], OREAD);
177
		safelen = sizeof(Nvrsafe);
178
		if(strstr(v[0], "/9fat") == nil)
179
			safeoff = 0;
180
		nvrlen = getenv("nvrlen");
181
		if(nvrlen != nil)
182
			safelen = atoi(nvrlen);
183
		nvroff = getenv("nvroff");
184
		if(nvroff != nil)
185
			if(strcmp(nvroff, "dos") == 0)
186
				safeoff = -1;
187
			else
188
				safeoff = atoi(nvroff);
189
		if(safeoff < 0 && fd >= 0){
190
			safelen = 512;
191
			safeoff = finddosfile(fd, i == 2? v[1]: "plan9.nvr");
192
			if(safeoff < 0){	/* didn't find plan9.nvr? */
193
				close(fd);
194
				fd = -1;
195
			}
196
		}
197
		free(nvrcopy);
198
		free(nvroff);
199
		free(nvrlen);
200
	}else{
201
		for(i=0; i<nelem(nvtab); i++){
202
			if(strcmp(cputype, nvtab[i].cputype) != 0)
203
				continue;
204
			if(nvramdebug)
205
				fprint(2, "nvram at %s?...", nvtab[i].file);
206
			if((fd = open(nvtab[i].file, ORDWR)) < 0 &&
207
			   (fd = open(nvtab[i].file, OREAD)) < 0)
208
				continue;
209
			safeoff = nvtab[i].off;
210
			safelen = nvtab[i].len;
211
			if(safeoff == -1){
212
				safeoff = finddosfile(fd, "plan9.nvr");
213
				if(safeoff < 0){  /* didn't find plan9.nvr? */
214
					close(fd);
215
					fd = -1;
216
					continue;
217
				}
218
			}
219
			nvrfile = strdup(nvtab[i].file);
220
			break;
221
		}
222
		if(i >= nelem(nvtab))		/* tried them all? */
223
			werrstr("");		/* ignore failed opens */
224
	}
225
	locp->fd = fd;
226
	locp->safelen = safelen;
227
	locp->safeoff = safeoff;
228
}
229
 
230
/*
231
 *  get key info out of nvram.  since there isn't room in the PC's nvram use
232
 *  a disk partition there.
233
 */
234
int
235
readnvram(Nvrsafe *safep, int flag)
236
{
237
	int err;
238
	char buf[512], in[128];		/* 512 for floppy i/o */
239
	Nvrsafe *safe;
240
	Nvrwhere loc;
241
 
242
	err = 0;
243
	safe = (Nvrsafe*)buf;
244
	memset(&loc, 0, sizeof loc);
245
	findnvram(&loc);
246
	if (loc.safelen < 0)
247
		loc.safelen = sizeof *safe;
248
	else if (loc.safelen > sizeof buf)
249
		loc.safelen = sizeof buf;
250
	if (loc.safeoff < 0) {
251
		fprint(2, "readnvram: can't find nvram\n");
252
		if(!(flag&NVwritemem))
253
			memset(safep, 0, sizeof(*safep));
254
		safe = safep;
255
		/*
256
		 * allow user to type the data for authentication,
257
		 * even if there's no nvram to store it in.
258
		 */
259
	}
260
 
261
	if(flag&NVwritemem)
262
		safe = safep;
263
	else {
264
		memset(safep, 0, sizeof(*safep));
265
		if(loc.fd >= 0)
266
			werrstr("");
267
		if(loc.fd < 0
268
		|| seek(loc.fd, loc.safeoff, 0) < 0
269
		|| read(loc.fd, buf, loc.safelen) != loc.safelen){
270
			err = 1;
271
			if(flag&(NVwrite|NVwriteonerr))
272
				if(loc.fd < 0 && nvrfile != nil)
273
					fprint(2, "can't open %s: %r\n", nvrfile);
274
				else if(loc.fd < 0){
275
					/* this will have been printed above */
276
					// fprint(2, "can't find nvram: %r\n");
277
				}else if (seek(loc.fd, loc.safeoff, 0) < 0)
278
					fprint(2, "can't seek %s to %d: %r\n",
279
						nvrfile, loc.safeoff);
280
				else
281
					fprint(2, "can't read %d bytes from %s: %r\n",
282
						loc.safelen, nvrfile);
283
			/* start from scratch */
284
			memset(safep, 0, sizeof(*safep));
285
			safe = safep;
286
		}else{
287
			*safep = *safe;	/* overwrite arg with data read */
288
			safe = safep;
289
 
290
			/* verify data read */
291
			err |= check(safe->machkey, DESKEYLEN, safe->machsum,
292
						"bad authentication password");
293
//			err |= check(safe->config, CONFIGLEN, safe->configsum,
294
//						"bad secstore password");
295
			err |= check(safe->authid, ANAMELEN, safe->authidsum,
296
						"bad authentication id");
297
			err |= check(safe->authdom, DOMLEN, safe->authdomsum,
298
						"bad authentication domain");
299
			if(err == 0)
300
				if(safe->authid[0]==0 || safe->authdom[0]==0){
301
					fprint(2, "empty nvram authid or authdom\n");
302
					err = 1;
303
				}
304
		}
305
	}
306
 
307
	if((flag&(NVwrite|NVwritemem)) || (err && (flag&NVwriteonerr))){
308
		if (!(flag&NVwritemem)) {
309
			readcons("authid", nil, 0, safe->authid,
310
					sizeof safe->authid);
311
			readcons("authdom", nil, 0, safe->authdom,
312
					sizeof safe->authdom);
313
			for(;;){
314
				if(readcons("auth password", nil, 1, in,
315
				    sizeof in) == nil)
316
					goto Out;
317
				if(passtokey(safe->machkey, in))
318
					break;
319
			}
320
			readcons("secstore password", nil, 1, safe->config,
321
					sizeof safe->config);
322
		}
323
 
324
		// safe->authsum = nvcsum(safe->authkey, DESKEYLEN);
325
		safe->machsum = nvcsum(safe->machkey, DESKEYLEN);
326
		safe->configsum = nvcsum(safe->config, CONFIGLEN);
327
		safe->authidsum = nvcsum(safe->authid, sizeof safe->authid);
328
		safe->authdomsum = nvcsum(safe->authdom, sizeof safe->authdom);
329
 
330
		*(Nvrsafe*)buf = *safe;
331
		if(loc.fd >= 0)
332
			werrstr("");
333
		if(loc.fd < 0
334
		|| seek(loc.fd, loc.safeoff, 0) < 0
335
		|| write(loc.fd, buf, loc.safelen) != loc.safelen){
336
			fprint(2, "can't write key to nvram: %r\n");
337
			err = 1;
338
		}else
339
			err = 0;
340
	}
341
Out:
342
	if (loc.fd >= 0)
343
		close(loc.fd);
344
	return err? -1: 0;
345
}
346
 
347
typedef struct Dosboot	Dosboot;
348
struct Dosboot{
349
	uchar	magic[3];	/* really an xx86 JMP instruction */
350
	uchar	version[8];
351
	uchar	sectsize[2];
352
	uchar	clustsize;
353
	uchar	nresrv[2];
354
	uchar	nfats;
355
	uchar	rootsize[2];
356
	uchar	volsize[2];
357
	uchar	mediadesc;
358
	uchar	fatsize[2];
359
	uchar	trksize[2];
360
	uchar	nheads[2];
361
	uchar	nhidden[4];
362
	uchar	bigvolsize[4];
363
	uchar	driveno;
364
	uchar	reserved0;
365
	uchar	bootsig;
366
	uchar	volid[4];
367
	uchar	label[11];
368
	uchar	type[8];
369
};
370
#define	GETSHORT(p) (((p)[1]<<8) | (p)[0])
371
#define	GETLONG(p) ((GETSHORT((p)+2) << 16) | GETSHORT((p)))
372
 
373
typedef struct Dosdir	Dosdir;
374
struct Dosdir
375
{
376
	char	name[8];
377
	char	ext[3];
378
	uchar	attr;
379
	uchar	reserved[10];
380
	uchar	time[2];
381
	uchar	date[2];
382
	uchar	start[2];
383
	uchar	length[4];
384
};
385
 
386
static char*
387
dosparse(char *from, char *to, int len)
388
{
389
	char c;
390
 
391
	memset(to, ' ', len);
392
	if(from == 0)
393
		return 0;
394
	while(len-- > 0){
395
		c = *from++;
396
		if(c == '.')
397
			return from;
398
		if(c == 0)
399
			break;
400
		if(c >= 'a' && c <= 'z')
401
			*to++ = c + 'A' - 'a';
402
		else
403
			*to++ = c;
404
	}
405
	return 0;
406
}
407
 
408
/*
409
 *  return offset of first file block
410
 *
411
 *  This is a very simplistic dos file system.  It only
412
 *  works on floppies, only looks in the root, and only
413
 *  returns a pointer to the first block of a file.
414
 *
415
 *  This exists for cpu servers that have no hard disk
416
 *  or nvram to store the key on.
417
 *
418
 *  Please don't make this any smarter: it stays resident
419
 *  and I'ld prefer not to waste the space on something that
420
 *  runs only at boottime -- presotto.
421
 */
422
static long
423
finddosfile(int fd, char *file)
424
{
425
	uchar secbuf[512];
426
	char name[8];
427
	char ext[3];
428
	Dosboot	*b;
429
	Dosdir *root, *dp;
430
	int nroot, sectsize, rootoff, rootsects, n;
431
 
432
	/* dos'ize file name */
433
	file = dosparse(file, name, 8);
434
	dosparse(file, ext, 3);
435
 
436
	/* read boot block, check for sanity */
437
	b = (Dosboot*)secbuf;
438
	if(read(fd, secbuf, sizeof(secbuf)) != sizeof(secbuf))
439
		return -1;
440
	if(b->magic[0] != 0xEB || b->magic[1] != 0x3C || b->magic[2] != 0x90)
441
		return -1;
442
	sectsize = GETSHORT(b->sectsize);
443
	if(sectsize != 512)
444
		return -1;
445
	rootoff = (GETSHORT(b->nresrv) + b->nfats*GETSHORT(b->fatsize)) * sectsize;
446
	if(seek(fd, rootoff, 0) < 0)
447
		return -1;
448
	nroot = GETSHORT(b->rootsize);
449
	rootsects = (nroot*sizeof(Dosdir)+sectsize-1)/sectsize;
450
	if(rootsects <= 0 || rootsects > 64)
451
		return -1;
452
 
453
	/*
454
	 *  read root. it is contiguous to make stuff like
455
	 *  this easier
456
	 */
457
	root = malloc(rootsects*sectsize);
458
	if(read(fd, root, rootsects*sectsize) != rootsects*sectsize)
459
		return -1;
460
	n = -1;
461
	for(dp = root; dp < &root[nroot]; dp++)
462
		if(memcmp(name, dp->name, 8) == 0 && memcmp(ext, dp->ext, 3) == 0){
463
			n = GETSHORT(dp->start);
464
			break;
465
		}
466
	free(root);
467
 
468
	if(n < 0)
469
		return -1;
470
 
471
	/*
472
	 *  dp->start is in cluster units, not sectors.  The first
473
	 *  cluster is cluster 2 which starts immediately after the
474
	 *  root directory
475
	 */
476
	return rootoff + rootsects*sectsize + (n-2)*sectsize*b->clustsize;
477
}
478