]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/cwfs/auth.c
Import sources from 2011-03-30 iso image
[plan9front.git] / sys / src / cmd / cwfs / auth.c
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 }