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*
nvrgetconfig(void)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
nvrcheck(void)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
nvrsetconfig(char * word)45 nvrsetconfig(char* word)
46 {
47 /* config block is on device `word' */
48 USED(word);
49 return 0;
50 }
51
52 int
conslock(void)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
authinit(void)133 authinit(void)
134 {
135 auths = malloc(conf.nauth * sizeof(*auths));
136 }
137
138 static int
failure(Auth * s,char * why)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*
authnew(char * uname,char * aname)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
authfree(Auth * s)189 authfree(Auth *s)
190 {
191 if(s != nil)
192 s->inuse = 0;
193 }
194
195 int
authread(File * file,uchar * data,int n)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
authwrite(File * file,uchar * data,int n)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
authuid(Auth * s)311 authuid(Auth* s)
312 {
313 return s->uid;
314 }
315
316 char*
authaname(Auth * s)317 authaname(Auth* s)
318 {
319 return s->aname;
320 }
321
322 char*
authuname(Auth * s)323 authuname(Auth* s)
324 {
325 return s->uname;
326 }
327