Subversion Repositories planix.SVN

Rev

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

Rev Author Line No. Line
2 - 1
#include "all.h"
2
#include "io.h"
3
#include <authsrv.h>
4
 
5
Nvrsafe	nvr;
6
 
7
static int gotnvr;	/* flag: nvr contains nvram; it could be bad */
8
 
9
char*
10
nvrgetconfig(void)
11
{
12
	return conf.confdev;
13
}
14
 
15
/*
16
 * we shouldn't be writing nvram any more.
17
 * the secstore/config field is now just secstore key.
18
 * we still use authid, authdom and machkey for authentication.
19
 */
20
 
21
int
22
nvrcheck(void)
23
{
24
	uchar csum;
25
 
26
	if (readnvram(&nvr, NVread) < 0) {
27
		print("nvrcheck: can't read nvram\n");
28
		return 1;
29
	} else
30
		gotnvr = 1;
31
	print("nvr read\n");
32
 
33
	csum = nvcsum(nvr.machkey, sizeof nvr.machkey);
34
	if(csum != nvr.machsum) {
35
		print("\n\n ** NVR key checksum is incorrect  **\n");
36
		print(" ** set password to allow attaches **\n\n");
37
		memset(nvr.machkey, 0, sizeof nvr.machkey);
38
		return 1;
39
	}
40
 
41
	return 0;
42
}
43
 
44
int
45
nvrsetconfig(char* word)
46
{
47
	/* config block is on device `word' */
48
	USED(word);
49
	return 0;
50
}
51
 
52
int
53
conslock(void)
54
{
55
	char *ln;
56
	char nkey1[DESKEYLEN];
57
	static char zeroes[DESKEYLEN];
58
 
59
	if(memcmp(nvr.machkey, zeroes, DESKEYLEN) == 0) {
60
		print("no password set\n");
61
		return 0;
62
	}
63
 
64
	for(;;) {
65
		print("%s password:", service);
66
		/* could turn off echo here */
67
 
68
		if ((ln = Brdline(&bin, '\n')) == nil)
69
			return 0;
70
		ln[Blinelen(&bin)-1] = '\0';
71
 
72
		/* could turn on echo here */
73
		memset(nkey1, 0, DESKEYLEN);
74
		passtokey(nkey1, ln);
75
		if(memcmp(nkey1, nvr.machkey, DESKEYLEN) == 0) {
76
			prdate();
77
			break;
78
		}
79
 
80
		print("Bad password\n");
81
		delay(1000);
82
	}
83
	return 1;
84
}
85
 
86
/*
87
 *  authentication specific to 9P2000
88
 */
89
 
90
/* authentication states */
91
enum
92
{
93
	HaveProtos=1,
94
	NeedProto,
95
	HaveOK,
96
	NeedCchal,
97
	HaveSinfo,
98
	NeedTicket,
99
	HaveSauthenticator,
100
	SSuccess,
101
};
102
 
103
char *phasename[] =
104
{
105
[HaveProtos]	"HaveProtos",
106
[NeedProto]	"NeedProto",
107
[HaveOK]	"HaveOK",
108
[NeedCchal]	"NeedCchal",
109
[HaveSinfo]	"HaveSinfo",
110
[NeedTicket]	"NeedTicket",
111
[HaveSauthenticator]	"HaveSauthenticator",
112
[SSuccess]	"SSuccess",
113
};
114
 
115
/* authentication structure */
116
struct	Auth
117
{
118
	int	inuse;
119
	char	uname[NAMELEN];	/* requestor's remote user name */
120
	char	aname[NAMELEN];	/* requested aname */
121
	Userid	uid;		/* uid decided on */
122
	int	phase;
123
	char	cchal[CHALLEN];
124
	char	tbuf[TICKETLEN+AUTHENTLEN];	/* server ticket */
125
	Ticket	t;
126
	Ticketreq tr;
127
};
128
 
129
Auth*	auths;
130
Lock	authlock;
131
 
132
void
133
authinit(void)
134
{
135
	auths = malloc(conf.nauth * sizeof(*auths));
136
}
137
 
138
static int
139
failure(Auth *s, char *why)
140
{
141
	int i;
142
 
143
if(*why)print("authentication failed: %s: %s\n", phasename[s->phase], why);
144
	srand((uintptr)s + time(nil));
145
	for(i = 0; i < CHALLEN; i++)
146
		s->tr.chal[i] = nrand(256);
147
	s->uid = -1;
148
	strncpy(s->tr.authid, nvr.authid, NAMELEN);
149
	strncpy(s->tr.authdom, nvr.authdom, DOMLEN);
150
	memmove(s->cchal, s->tr.chal, sizeof(s->cchal));
151
	s->phase = HaveProtos;
152
	return -1;
153
}
154
 
155
Auth*
156
authnew(char *uname, char *aname)
157
{
158
	static int si = 0;
159
	int i, nwrap;
160
	Auth *s;
161
 
162
	i = si;
163
	nwrap = 0;
164
	for(;;){
165
		if(i < 0 || i >= conf.nauth){
166
			if(++nwrap > 1)
167
				return nil;
168
			i = 0;
169
		}
170
		s = &auths[i++];
171
		if(s->inuse)
172
			continue;
173
		lock(&authlock);
174
		if(s->inuse == 0){
175
			s->inuse = 1;
176
			strncpy(s->uname, uname, NAMELEN-1);
177
			strncpy(s->aname, aname, NAMELEN-1);
178
			failure(s, "");
179
			si = i;
180
			unlock(&authlock);
181
			break;
182
		}
183
		unlock(&authlock);
184
	}
185
	return s;
186
}
187
 
188
void
189
authfree(Auth *s)
190
{
191
	if(s != nil)
192
		s->inuse = 0;
193
}
194
 
195
int
196
authread(File* file, uchar* data, int n)
197
{
198
	Auth *s;
199
	int m;
200
 
201
	s = file->auth;
202
	if(s == nil)
203
		return -1;
204
 
205
	switch(s->phase){
206
	default:
207
		return failure(s, "unexpected phase");
208
	case HaveProtos:
209
		m = snprint((char*)data, n, "v.2 p9sk1@%s", nvr.authdom) + 1;
210
		s->phase = NeedProto;
211
		break;
212
	case HaveOK:
213
		m = 3;
214
		if(n < m)
215
			return failure(s, "read too short");
216
		strcpy((char*)data, "OK");
217
		s->phase = NeedCchal;
218
		break;
219
	case HaveSinfo:
220
		m = TICKREQLEN;
221
		if(n < m)
222
			return failure(s, "read too short");
223
		convTR2M(&s->tr, (char*)data);
224
		s->phase = NeedTicket;
225
		break;
226
	case HaveSauthenticator:
227
		m = AUTHENTLEN;
228
		if(n < m)
229
			return failure(s, "read too short");
230
		memmove(data, s->tbuf+TICKETLEN, m);
231
		s->phase = SSuccess;
232
		break;
233
	}
234
	return m;
235
}
236
 
237
int
238
authwrite(File* file, uchar *data, int n)
239
{
240
	Auth *s;
241
	int m;
242
	char *p, *d;
243
	Authenticator a;
244
 
245
	s = file->auth;
246
	if(s == nil)
247
		return -1;
248
 
249
	switch(s->phase){
250
	default:
251
		return failure(s, "unknown phase");
252
	case NeedProto:
253
		p = (char*)data;
254
		if(p[n-1] != 0)
255
			return failure(s, "proto missing terminator");
256
		d = strchr(p, ' ');
257
		if(d == nil)
258
			return failure(s, "proto missing separator");
259
		*d++ = 0;
260
		if(strcmp(p, "p9sk1") != 0)
261
			return failure(s, "unknown proto");
262
		if(strcmp(d, nvr.authdom) != 0)
263
			return failure(s, "unknown domain");
264
		s->phase = HaveOK;
265
		m = n;
266
		break;
267
	case NeedCchal:
268
		m = CHALLEN;
269
		if(n < m)
270
			return failure(s, "client challenge too short");
271
		memmove(s->cchal, data, sizeof(s->cchal));
272
		s->phase = HaveSinfo;
273
		break;
274
	case NeedTicket:
275
		m = TICKETLEN+AUTHENTLEN;
276
		if(n < m)
277
			return failure(s, "ticket+auth too short");
278
 
279
		convM2T((char*)data, &s->t, nvr.machkey);
280
		if(s->t.num != AuthTs
281
		|| memcmp(s->t.chal, s->tr.chal, sizeof(s->t.chal)) != 0)
282
			return failure(s, "bad ticket");
283
 
284
		convM2A((char*)data+TICKETLEN, &a, s->t.key);
285
		if(a.num != AuthAc
286
		|| memcmp(a.chal, s->tr.chal, sizeof(a.chal)) != 0
287
		|| a.id != 0)
288
			return failure(s, "bad authenticator");
289
 
290
		/* at this point, we're convinced */
291
		s->uid = strtouid(s->t.suid);
292
		if(s->uid < 0)
293
			return failure(s, "unknown user");
294
		if(cons.flags & authdebugflag)
295
			print("user %s = %d authenticated\n",
296
				s->t.suid, s->uid);
297
 
298
		/* create an authenticator to send back */
299
		a.num = AuthAs;
300
		memmove(a.chal, s->cchal, sizeof(a.chal));
301
		a.id = 0;
302
		convA2M(&a, s->tbuf+TICKETLEN, s->t.key);
303
 
304
		s->phase = HaveSauthenticator;
305
		break;
306
	}
307
	return m;
308
}
309
 
310
int
311
authuid(Auth* s)
312
{
313
	return s->uid;
314
}
315
 
316
char*
317
authaname(Auth* s)
318
{
319
	return s->aname;
320
}
321
 
322
char*
323
authuname(Auth* s)
324
{
325
	return s->uname;
326
}