2 d96dce4d 2007-09-14 rsc * p9cr - one-sided challenge/response authentication
4 6e527fbc 2005-02-13 devnull * Protocol:
6 6e527fbc 2005-02-13 devnull * C -> S: user
7 6e527fbc 2005-02-13 devnull * S -> C: challenge
8 6e527fbc 2005-02-13 devnull * C -> S: response
9 6e527fbc 2005-02-13 devnull * S -> C: ok or bad
11 6e527fbc 2005-02-13 devnull * Note that this is the protocol between factotum and the local
12 6e527fbc 2005-02-13 devnull * program, not between the two factotums. The information
13 6e527fbc 2005-02-13 devnull * exchanged here is wrapped in other protocols by the local
14 6e527fbc 2005-02-13 devnull * programs.
17 6e527fbc 2005-02-13 devnull #include "std.h"
18 6e527fbc 2005-02-13 devnull #include "dat.h"
20 d96dce4d 2007-09-14 rsc /* shared with auth dialing routines */
21 d96dce4d 2007-09-14 rsc typedef struct ServerState ServerState;
22 d96dce4d 2007-09-14 rsc struct ServerState
26 d96dce4d 2007-09-14 rsc Ticketreq tr;
29 d96dce4d 2007-09-14 rsc char *hostid;
34 d96dce4d 2007-09-14 rsc MAXCHAL = 64,
35 d96dce4d 2007-09-14 rsc MAXRESP = 64,
38 d96dce4d 2007-09-14 rsc extern Proto p9cr, vnc;
39 d96dce4d 2007-09-14 rsc static int p9response(char*, uchar*, uchar*);
40 d96dce4d 2007-09-14 rsc // static int vncresponse(char*, uchar*, uchar*);
41 d96dce4d 2007-09-14 rsc static int p9crchal(ServerState *s, int, char*, uchar*, int);
42 d96dce4d 2007-09-14 rsc static int p9crresp(ServerState*, uchar*, int);
44 6e527fbc 2005-02-13 devnull static int
45 d96dce4d 2007-09-14 rsc p9crcheck(Key *k)
47 d96dce4d 2007-09-14 rsc if(!strfindattr(k->attr, "user") || !strfindattr(k->privattr, "!password")){
48 d96dce4d 2007-09-14 rsc werrstr("need user and !password attributes");
55 6e527fbc 2005-02-13 devnull p9crclient(Conv *c)
57 d96dce4d 2007-09-14 rsc char *pw, *res, *user;
58 d96dce4d 2007-09-14 rsc int astype, challen, resplen, ntry, ret;
59 6e527fbc 2005-02-13 devnull Attr *attr;
61 d96dce4d 2007-09-14 rsc uchar chal[MAXCHAL+1], resp[MAXRESP];
62 d96dce4d 2007-09-14 rsc int (*response)(char*, uchar*, uchar*);
65 6e527fbc 2005-02-13 devnull res = nil;
66 6e527fbc 2005-02-13 devnull ret = -1;
67 6e527fbc 2005-02-13 devnull attr = c->attr;
69 6e527fbc 2005-02-13 devnull if(c->proto == &p9cr){
70 6e527fbc 2005-02-13 devnull astype = AuthChal;
71 6e527fbc 2005-02-13 devnull challen = NETCHLEN;
72 d96dce4d 2007-09-14 rsc response = p9response;
73 d96dce4d 2007-09-14 rsc attr = _mkattr(AttrNameval, "proto", "p9sk1", _delattr(_copyattr(attr), "proto"));
74 6e527fbc 2005-02-13 devnull }else if(c->proto == &vnc){
75 d96dce4d 2007-09-14 rsc astype = AuthVNC;
76 6e527fbc 2005-02-13 devnull challen = MAXCHAL;
77 d96dce4d 2007-09-14 rsc // response = vncresponse;
78 523f3148 2007-11-05 rsc werrstr("no vnc");
81 6e527fbc 2005-02-13 devnull werrstr("bad proto");
82 6e527fbc 2005-02-13 devnull goto out;
85 6e527fbc 2005-02-13 devnull c->state = "find key";
86 6e527fbc 2005-02-13 devnull k = keyfetch(c, "%A %s", attr, c->proto->keyprompt);
87 6e527fbc 2005-02-13 devnull if(k == nil)
88 6e527fbc 2005-02-13 devnull goto out;
90 6e527fbc 2005-02-13 devnull for(ntry=1;; ntry++){
91 6e527fbc 2005-02-13 devnull if(c->attr != attr)
92 6e527fbc 2005-02-13 devnull freeattr(c->attr);
93 6e527fbc 2005-02-13 devnull c->attr = addattrs(copyattr(attr), k->attr);
95 6e527fbc 2005-02-13 devnull if((pw = strfindattr(k->privattr, "!password")) == nil){
96 6e527fbc 2005-02-13 devnull werrstr("key has no !password (cannot happen)");
97 6e527fbc 2005-02-13 devnull goto out;
99 6e527fbc 2005-02-13 devnull if((user = strfindattr(k->attr, "user")) == nil){
100 6e527fbc 2005-02-13 devnull werrstr("key has no user (cannot happen)");
101 6e527fbc 2005-02-13 devnull goto out;
104 6e527fbc 2005-02-13 devnull if(convprint(c, "%s", user) < 0)
105 6e527fbc 2005-02-13 devnull goto out;
107 d96dce4d 2007-09-14 rsc if(convread(c, chal, challen) < 0)
108 6e527fbc 2005-02-13 devnull goto out;
109 d96dce4d 2007-09-14 rsc chal[challen] = 0;
111 d96dce4d 2007-09-14 rsc if((resplen = (*response)(pw, chal, resp)) < 0)
112 6e527fbc 2005-02-13 devnull goto out;
114 d96dce4d 2007-09-14 rsc if(convwrite(c, resp, resplen) < 0)
115 6e527fbc 2005-02-13 devnull goto out;
117 6e527fbc 2005-02-13 devnull if(convreadm(c, &res) < 0)
118 6e527fbc 2005-02-13 devnull goto out;
120 6e527fbc 2005-02-13 devnull if(strcmp(res, "ok") == 0)
123 6e527fbc 2005-02-13 devnull if((k = keyreplace(c, k, "%s", res)) == nil){
124 6e527fbc 2005-02-13 devnull c->state = "auth failed";
125 6e527fbc 2005-02-13 devnull werrstr("%s", res);
126 6e527fbc 2005-02-13 devnull goto out;
130 6e527fbc 2005-02-13 devnull werrstr("succeeded");
131 6e527fbc 2005-02-13 devnull ret = 0;
134 6e527fbc 2005-02-13 devnull keyclose(k);
135 6e527fbc 2005-02-13 devnull if(c->attr != attr)
136 6e527fbc 2005-02-13 devnull freeattr(attr);
137 6e527fbc 2005-02-13 devnull return ret;
140 6e527fbc 2005-02-13 devnull static int
141 6e527fbc 2005-02-13 devnull p9crserver(Conv *c)
143 d96dce4d 2007-09-14 rsc uchar chal[MAXCHAL], *resp, *resp1;
145 d96dce4d 2007-09-14 rsc ServerState s;
146 d96dce4d 2007-09-14 rsc int astype, ret, challen, resplen;
147 6e527fbc 2005-02-13 devnull Attr *a;
149 6e527fbc 2005-02-13 devnull ret = -1;
150 6e527fbc 2005-02-13 devnull user = nil;
151 6e527fbc 2005-02-13 devnull resp = nil;
152 6e527fbc 2005-02-13 devnull memset(&s, 0, sizeof s);
153 6e527fbc 2005-02-13 devnull s.asfd = -1;
155 1757e76a 2005-02-13 devnull if(c->proto == &p9cr){
156 1757e76a 2005-02-13 devnull astype = AuthChal;
157 1757e76a 2005-02-13 devnull challen = NETCHLEN;
158 1757e76a 2005-02-13 devnull }else if(c->proto == &vnc){
159 d96dce4d 2007-09-14 rsc astype = AuthVNC;
160 1757e76a 2005-02-13 devnull challen = MAXCHAL;
162 6e527fbc 2005-02-13 devnull werrstr("bad proto");
163 6e527fbc 2005-02-13 devnull goto out;
166 6e527fbc 2005-02-13 devnull c->state = "find key";
167 d96dce4d 2007-09-14 rsc if((s.k = plan9authkey(c->attr)) == nil)
168 6e527fbc 2005-02-13 devnull goto out;
170 d96dce4d 2007-09-14 rsc a = copyattr(s.k->attr);
171 6e527fbc 2005-02-13 devnull a = delattr(a, "proto");
172 6e527fbc 2005-02-13 devnull c->attr = addattrs(c->attr, a);
173 6e527fbc 2005-02-13 devnull freeattr(a);
175 6e527fbc 2005-02-13 devnull c->state = "authdial";
176 d96dce4d 2007-09-14 rsc s.hostid = strfindattr(s.k->attr, "user");
177 d96dce4d 2007-09-14 rsc s.dom = strfindattr(s.k->attr, "dom");
178 d96dce4d 2007-09-14 rsc if((s.asfd = xioauthdial(nil, s.dom)) < 0){
179 6e527fbc 2005-02-13 devnull werrstr("authdial %s: %r", s.dom);
180 6e527fbc 2005-02-13 devnull goto out;
183 6e527fbc 2005-02-13 devnull for(;;){
184 6e527fbc 2005-02-13 devnull c->state = "read user";
185 6e527fbc 2005-02-13 devnull if(convreadm(c, &user) < 0)
186 6e527fbc 2005-02-13 devnull goto out;
188 d96dce4d 2007-09-14 rsc c->state = "authchal";
189 d96dce4d 2007-09-14 rsc if(p9crchal(&s, astype, user, chal, challen) < 0)
192 d96dce4d 2007-09-14 rsc c->state = "write challenge";
193 d96dce4d 2007-09-14 rsc if(convwrite(c, chal, challen) < 0)
196 6e527fbc 2005-02-13 devnull c->state = "read response";
197 d96dce4d 2007-09-14 rsc if((resplen = convreadm(c, (char**)(void*)&resp)) < 0)
198 6e527fbc 2005-02-13 devnull goto out;
199 d96dce4d 2007-09-14 rsc if(c->proto == &p9cr){
200 d96dce4d 2007-09-14 rsc if(resplen > NETCHLEN){
201 d96dce4d 2007-09-14 rsc convprint(c, "bad response too long");
204 d96dce4d 2007-09-14 rsc resp1 = emalloc(NETCHLEN);
205 d96dce4d 2007-09-14 rsc memset(resp1, 0, NETCHLEN);
206 d96dce4d 2007-09-14 rsc memmove(resp1, resp, resplen);
208 d96dce4d 2007-09-14 rsc resp = resp1;
209 d96dce4d 2007-09-14 rsc resplen = NETCHLEN;
212 6e527fbc 2005-02-13 devnull c->state = "authwrite";
213 d96dce4d 2007-09-14 rsc switch(p9crresp(&s, resp, resplen)){
214 6e527fbc 2005-02-13 devnull case -1:
215 d96dce4d 2007-09-14 rsc fprint(2, "p9crresp: %r\n");
216 6e527fbc 2005-02-13 devnull goto out;
218 6e527fbc 2005-02-13 devnull c->state = "write status";
219 6e527fbc 2005-02-13 devnull if(convprint(c, "bad authentication failed") < 0)
220 6e527fbc 2005-02-13 devnull goto out;
223 6e527fbc 2005-02-13 devnull c->state = "write status";
224 6e527fbc 2005-02-13 devnull if(convprint(c, "ok") < 0)
225 6e527fbc 2005-02-13 devnull goto out;
226 6e527fbc 2005-02-13 devnull goto ok;
228 6e527fbc 2005-02-13 devnull free(user);
229 6e527fbc 2005-02-13 devnull free(resp);
230 6e527fbc 2005-02-13 devnull user = nil;
231 6e527fbc 2005-02-13 devnull resp = nil;
235 6e527fbc 2005-02-13 devnull ret = 0;
236 6e527fbc 2005-02-13 devnull c->attr = addcap(c->attr, c->sysuser, &s.t);
239 6e527fbc 2005-02-13 devnull keyclose(s.k);
240 6e527fbc 2005-02-13 devnull free(user);
241 6e527fbc 2005-02-13 devnull free(resp);
242 1757e76a 2005-02-13 devnull xioclose(s.asfd);
243 6e527fbc 2005-02-13 devnull return ret;
247 d96dce4d 2007-09-14 rsc p9crchal(ServerState *s, int astype, char *user, uchar *chal, int challen)
249 d96dce4d 2007-09-14 rsc char trbuf[TICKREQLEN];
250 6e527fbc 2005-02-13 devnull Ticketreq tr;
253 d96dce4d 2007-09-14 rsc memset(&tr, 0, sizeof tr);
255 d96dce4d 2007-09-14 rsc tr.type = astype;
257 d96dce4d 2007-09-14 rsc if(strlen(s->hostid) >= sizeof tr.hostid){
258 d96dce4d 2007-09-14 rsc werrstr("hostid too long");
261 d96dce4d 2007-09-14 rsc strcpy(tr.hostid, s->hostid);
263 d96dce4d 2007-09-14 rsc if(strlen(s->dom) >= sizeof tr.authdom){
264 d96dce4d 2007-09-14 rsc werrstr("domain too long");
267 d96dce4d 2007-09-14 rsc strcpy(tr.authdom, s->dom);
269 d96dce4d 2007-09-14 rsc if(strlen(user) >= sizeof tr.uid){
270 d96dce4d 2007-09-14 rsc werrstr("user name too long");
273 d96dce4d 2007-09-14 rsc strcpy(tr.uid, user);
274 d96dce4d 2007-09-14 rsc convTR2M(&tr, trbuf);
276 d96dce4d 2007-09-14 rsc if(xiowrite(s->asfd, trbuf, TICKREQLEN) != TICKREQLEN)
279 d96dce4d 2007-09-14 rsc if((n=xioasrdresp(s->asfd, chal, challen)) <= 0)
284 6e527fbc 2005-02-13 devnull static int
285 d96dce4d 2007-09-14 rsc p9crresp(ServerState *s, uchar *resp, int resplen)
287 d96dce4d 2007-09-14 rsc char tabuf[TICKETLEN+AUTHENTLEN];
288 d96dce4d 2007-09-14 rsc Authenticator a;
290 d96dce4d 2007-09-14 rsc Ticketreq tr;
292 d96dce4d 2007-09-14 rsc if(xiowrite(s->asfd, resp, resplen) != resplen)
295 d96dce4d 2007-09-14 rsc if(xioasrdresp(s->asfd, tabuf, TICKETLEN+AUTHENTLEN) != TICKETLEN+AUTHENTLEN)
298 d96dce4d 2007-09-14 rsc convM2T(tabuf, &t, s->k->priv);
299 d96dce4d 2007-09-14 rsc if(t.num != AuthTs
300 d96dce4d 2007-09-14 rsc || memcmp(t.chal, tr.chal, sizeof tr.chal) != 0){
301 d96dce4d 2007-09-14 rsc werrstr("key mismatch with auth server");
305 d96dce4d 2007-09-14 rsc convM2A(tabuf+TICKETLEN, &a, t.key);
306 d96dce4d 2007-09-14 rsc if(a.num != AuthAc
307 d96dce4d 2007-09-14 rsc || memcmp(a.chal, tr.chal, sizeof a.chal) != 0
308 d96dce4d 2007-09-14 rsc || a.id != 0){
309 d96dce4d 2007-09-14 rsc werrstr("key2 mismatch with auth server");
317 6e527fbc 2005-02-13 devnull static int
318 d96dce4d 2007-09-14 rsc p9response(char *pw, uchar *chal, uchar *resp)
320 6e527fbc 2005-02-13 devnull char key[DESKEYLEN];
321 6e527fbc 2005-02-13 devnull uchar buf[8];
324 6e527fbc 2005-02-13 devnull passtokey(key, pw);
325 6e527fbc 2005-02-13 devnull memset(buf, 0, 8);
326 d96dce4d 2007-09-14 rsc snprint((char*)buf, sizeof buf, "%d", atoi((char*)chal));
327 d96dce4d 2007-09-14 rsc if(encrypt(key, buf, 8) < 0){
328 d96dce4d 2007-09-14 rsc werrstr("can't encrypt response");
329 6e527fbc 2005-02-13 devnull return -1;
331 d96dce4d 2007-09-14 rsc x = (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+buf[3];
332 d96dce4d 2007-09-14 rsc return snprint((char*)resp, MAXRESP, "%.8lux", x);
336 6e527fbc 2005-02-13 devnull static int
337 d96dce4d 2007-09-14 rsc vncresponse(char *pw, uchar *chal, uchar *resp)
339 6e527fbc 2005-02-13 devnull DESstate des;
341 d96dce4d 2007-09-14 rsc memmove(resp, chal, MAXCHAL);
342 d96dce4d 2007-09-14 rsc setupDESstate(&des, 0, nil); // XXX put key in for 0
343 d96dce4d 2007-09-14 rsc desECBencrypt(resp, MAXCHAL, &des);
344 d96dce4d 2007-09-14 rsc return MAXCHAL;
349 d96dce4d 2007-09-14 rsc p9crroles[] =
351 d96dce4d 2007-09-14 rsc "client", p9crclient,
352 d96dce4d 2007-09-14 rsc "server", p9crserver,
356 d96dce4d 2007-09-14 rsc Proto p9cr = {
359 d96dce4d 2007-09-14 rsc "user? !password?",
364 50f5d1a7 2007-09-16 rsc /* still need to implement vnc key generator */
365 d96dce4d 2007-09-14 rsc Proto vnc = {
368 d96dce4d 2007-09-14 rsc "user? !password?",