2 2277c5d7 2004-03-21 devnull * p9sk1, p9sk2 - Plan 9 secret (private) key authentication.
3 2277c5d7 2004-03-21 devnull * p9sk2 is an incomplete flawed variant of p9sk1.
5 2277c5d7 2004-03-21 devnull * Client protocol:
6 2277c5d7 2004-03-21 devnull * write challenge[challen] (p9sk1 only)
7 2277c5d7 2004-03-21 devnull * read tickreq[tickreqlen]
8 2277c5d7 2004-03-21 devnull * write ticket[ticketlen]
9 2277c5d7 2004-03-21 devnull * read authenticator[authentlen]
11 2277c5d7 2004-03-21 devnull * Server protocol:
12 2277c5d7 2004-03-21 devnull * read challenge[challen] (p9sk1 only)
13 2277c5d7 2004-03-21 devnull * write tickreq[tickreqlen]
14 2277c5d7 2004-03-21 devnull * read ticket[ticketlen]
15 2277c5d7 2004-03-21 devnull * write authenticator[authentlen]
18 2277c5d7 2004-03-21 devnull #include "std.h"
19 2277c5d7 2004-03-21 devnull #include "dat.h"
21 2277c5d7 2004-03-21 devnull static int gettickets(Ticketreq*, char*, Key*);
23 2277c5d7 2004-03-21 devnull #define max(a, b) ((a) > (b) ? (a) : (b))
26 2277c5d7 2004-03-21 devnull MAXAUTH = max(TICKREQLEN, TICKETLEN+max(TICKETLEN, AUTHENTLEN))
29 2277c5d7 2004-03-21 devnull static int
30 2277c5d7 2004-03-21 devnull p9skclient(Conv *c)
32 2277c5d7 2004-03-21 devnull char *user;
33 2277c5d7 2004-03-21 devnull char cchal[CHALLEN];
34 2277c5d7 2004-03-21 devnull uchar secret[8];
35 2277c5d7 2004-03-21 devnull char buf[MAXAUTH];
36 2277c5d7 2004-03-21 devnull int speakfor, ret;
38 2277c5d7 2004-03-21 devnull Authenticator au;
40 2277c5d7 2004-03-21 devnull Ticket t;
41 2277c5d7 2004-03-21 devnull Ticketreq tr;
43 2277c5d7 2004-03-21 devnull ret = -1;
47 2277c5d7 2004-03-21 devnull /* p9sk1: send client challenge */
48 2277c5d7 2004-03-21 devnull if(c->proto == &p9sk1){
49 2277c5d7 2004-03-21 devnull c->state = "write challenge";
50 2277c5d7 2004-03-21 devnull memrandom(cchal, CHALLEN);
51 2277c5d7 2004-03-21 devnull if(convwrite(c, cchal, CHALLEN) < 0)
52 2277c5d7 2004-03-21 devnull goto out;
55 2277c5d7 2004-03-21 devnull /* read ticket request */
56 2277c5d7 2004-03-21 devnull c->state = "read tickreq";
57 2277c5d7 2004-03-21 devnull if(convread(c, buf, TICKREQLEN) < 0)
58 2277c5d7 2004-03-21 devnull goto out;
59 2277c5d7 2004-03-21 devnull convM2TR(buf, &tr);
61 2277c5d7 2004-03-21 devnull /* p9sk2: use server challenge as client challenge */
62 2277c5d7 2004-03-21 devnull if(c->proto == &p9sk2)
63 2277c5d7 2004-03-21 devnull memmove(cchal, tr.chal, CHALLEN);
66 2277c5d7 2004-03-21 devnull * find a key.
68 2277c5d7 2004-03-21 devnull * if the user is the factotum owner, any key will do.
69 2277c5d7 2004-03-21 devnull * if not, then if we have a speakfor key,
70 2277c5d7 2004-03-21 devnull * we will only vouch for the user's local identity.
72 2277c5d7 2004-03-21 devnull * this logic is duplicated in p9any.c
74 2277c5d7 2004-03-21 devnull user = strfindattr(c->attr, "user");
75 2277c5d7 2004-03-21 devnull a = delattr(copyattr(c->attr), "role");
76 2277c5d7 2004-03-21 devnull a = addattr(a, "proto=p9sk1");
78 2277c5d7 2004-03-21 devnull if(strcmp(c->sysuser, owner) == 0){
79 2277c5d7 2004-03-21 devnull speakfor = 0;
80 2277c5d7 2004-03-21 devnull a = addattr(a, "proto=p9sk1 user? dom=%q", tr.authdom);
81 2277c5d7 2004-03-21 devnull }else if(user==nil || strcmp(c->sysuser, user)==0){
82 2277c5d7 2004-03-21 devnull speakfor = 1;
83 2277c5d7 2004-03-21 devnull a = delattr(a, "user");
84 2277c5d7 2004-03-21 devnull a = addattr(a, "proto=p9sk1 user? dom=%q role=speakfor", tr.authdom);
86 2277c5d7 2004-03-21 devnull werrstr("will not authenticate for %q as %q", c->sysuser, user);
87 2277c5d7 2004-03-21 devnull goto out;
91 2277c5d7 2004-03-21 devnull c->state = "find key";
92 2277c5d7 2004-03-21 devnull k = keyfetch(c, "%A", a);
93 2277c5d7 2004-03-21 devnull if(k == nil)
94 2277c5d7 2004-03-21 devnull goto out;
96 2277c5d7 2004-03-21 devnull /* relay ticket request to auth server, get tickets */
97 2277c5d7 2004-03-21 devnull strcpy(tr.hostid, strfindattr(k->attr, "user"));
98 2277c5d7 2004-03-21 devnull if(speakfor)
99 2277c5d7 2004-03-21 devnull strcpy(tr.uid, c->sysuser);
101 2277c5d7 2004-03-21 devnull strcpy(tr.uid, tr.hostid);
103 2277c5d7 2004-03-21 devnull c->state = "get tickets";
104 2277c5d7 2004-03-21 devnull if(gettickets(&tr, buf, k) < 0)
105 2277c5d7 2004-03-21 devnull goto out;
107 2277c5d7 2004-03-21 devnull convM2T(buf, &t, k->priv);
108 2277c5d7 2004-03-21 devnull if(t.num == AuthTc)
111 2277c5d7 2004-03-21 devnull /* we don't agree with the auth server about the key; try again */
112 2277c5d7 2004-03-21 devnull c->state = "replace key";
113 2277c5d7 2004-03-21 devnull if((k = keyreplace(c, k, "key mismatch with auth server")) == nil){
114 2277c5d7 2004-03-21 devnull werrstr("key mismatch with auth server");
115 2277c5d7 2004-03-21 devnull goto out;
119 2277c5d7 2004-03-21 devnull /* send second ticket and authenticator to server */
120 2277c5d7 2004-03-21 devnull c->state = "write ticket+auth";
121 2277c5d7 2004-03-21 devnull memmove(buf, buf+TICKETLEN, TICKETLEN);
122 2277c5d7 2004-03-21 devnull au.num = AuthAc;
123 2277c5d7 2004-03-21 devnull memmove(au.chal, tr.chal, CHALLEN);
124 2277c5d7 2004-03-21 devnull au.id = 0;
125 2277c5d7 2004-03-21 devnull convA2M(&au, buf+TICKETLEN, t.key);
126 2277c5d7 2004-03-21 devnull if(convwrite(c, buf, TICKETLEN+AUTHENTLEN) < 0)
127 2277c5d7 2004-03-21 devnull goto out;
129 2277c5d7 2004-03-21 devnull /* read authenticator from server */
130 2277c5d7 2004-03-21 devnull c->state = "read auth";
131 2277c5d7 2004-03-21 devnull if(convread(c, buf, AUTHENTLEN) < 0)
132 2277c5d7 2004-03-21 devnull goto out;
133 2277c5d7 2004-03-21 devnull convM2A(buf, &au, t.key);
134 2277c5d7 2004-03-21 devnull if(au.num != AuthAs || memcmp(au.chal, cchal, CHALLEN) != 0 || au.id != 0){
135 2277c5d7 2004-03-21 devnull werrstr("server lies through his teeth");
136 2277c5d7 2004-03-21 devnull goto out;
139 2277c5d7 2004-03-21 devnull /* success */
140 2277c5d7 2004-03-21 devnull c->attr = addcap(c->attr, c->sysuser, &t);
141 2277c5d7 2004-03-21 devnull des56to64((uchar*)t.key, secret);
142 2277c5d7 2004-03-21 devnull c->attr = addattr(c->attr, "secret=%.8H", secret);
143 2277c5d7 2004-03-21 devnull ret = 0;
146 2277c5d7 2004-03-21 devnull freeattr(a);
147 2277c5d7 2004-03-21 devnull keyclose(k);
148 2277c5d7 2004-03-21 devnull return ret;
151 2277c5d7 2004-03-21 devnull static int
152 2277c5d7 2004-03-21 devnull p9skserver(Conv *c)
154 2277c5d7 2004-03-21 devnull char cchal[CHALLEN], buf[MAXAUTH];
155 2277c5d7 2004-03-21 devnull uchar secret[8];
156 2277c5d7 2004-03-21 devnull int ret;
157 2277c5d7 2004-03-21 devnull Attr *a;
158 2277c5d7 2004-03-21 devnull Authenticator au;
160 2277c5d7 2004-03-21 devnull Ticketreq tr;
161 2277c5d7 2004-03-21 devnull Ticket t;
163 2277c5d7 2004-03-21 devnull ret = -1;
165 2277c5d7 2004-03-21 devnull a = addattr(copyattr(c->attr), "user? dom?");
166 2277c5d7 2004-03-21 devnull a = addattr(a, "user? dom? proto=p9sk1");
167 2277c5d7 2004-03-21 devnull if((k = keyfetch(c, "%A", a)) == nil)
168 2277c5d7 2004-03-21 devnull goto out;
170 2277c5d7 2004-03-21 devnull /* p9sk1: read client challenge */
171 2277c5d7 2004-03-21 devnull if(c->proto == &p9sk1){
172 2277c5d7 2004-03-21 devnull if(convread(c, cchal, CHALLEN) < 0)
173 2277c5d7 2004-03-21 devnull goto out;
176 2277c5d7 2004-03-21 devnull /* send ticket request */
177 2277c5d7 2004-03-21 devnull memset(&tr, 0, sizeof tr);
178 2277c5d7 2004-03-21 devnull tr.type = AuthTreq;
179 2277c5d7 2004-03-21 devnull strcpy(tr.authid, strfindattr(k->attr, "user"));
180 2277c5d7 2004-03-21 devnull strcpy(tr.authdom, strfindattr(k->attr, "dom"));
181 2277c5d7 2004-03-21 devnull memrandom(tr.chal, sizeof tr.chal);
182 2277c5d7 2004-03-21 devnull convTR2M(&tr, buf);
183 2277c5d7 2004-03-21 devnull if(convwrite(c, buf, TICKREQLEN) < 0)
184 2277c5d7 2004-03-21 devnull goto out;
186 2277c5d7 2004-03-21 devnull /* p9sk2: use server challenge as client challenge */
187 2277c5d7 2004-03-21 devnull if(c->proto == &p9sk2)
188 2277c5d7 2004-03-21 devnull memmove(cchal, tr.chal, sizeof tr.chal);
190 2277c5d7 2004-03-21 devnull /* read ticket+authenticator */
191 2277c5d7 2004-03-21 devnull if(convread(c, buf, TICKETLEN+AUTHENTLEN) < 0)
192 2277c5d7 2004-03-21 devnull goto out;
194 2277c5d7 2004-03-21 devnull convM2T(buf, &t, k->priv);
195 2277c5d7 2004-03-21 devnull if(t.num != AuthTs || memcmp(t.chal, tr.chal, CHALLEN) != 0){
196 2277c5d7 2004-03-21 devnull /* BUG badkey */
197 2277c5d7 2004-03-21 devnull werrstr("key mismatch with auth server");
198 2277c5d7 2004-03-21 devnull goto out;
201 2277c5d7 2004-03-21 devnull convM2A(buf+TICKETLEN, &au, t.key);
202 2277c5d7 2004-03-21 devnull if(au.num != AuthAc || memcmp(au.chal, tr.chal, CHALLEN) != 0 || au.id != 0){
203 2277c5d7 2004-03-21 devnull werrstr("client lies through his teeth");
204 2277c5d7 2004-03-21 devnull goto out;
207 2277c5d7 2004-03-21 devnull /* send authenticator */
208 2277c5d7 2004-03-21 devnull au.num = AuthAs;
209 2277c5d7 2004-03-21 devnull memmove(au.chal, cchal, CHALLEN);
210 2277c5d7 2004-03-21 devnull convA2M(&au, buf, t.key);
211 2277c5d7 2004-03-21 devnull if(convwrite(c, buf, AUTHENTLEN) < 0)
212 2277c5d7 2004-03-21 devnull goto out;
214 2277c5d7 2004-03-21 devnull /* success */
215 2277c5d7 2004-03-21 devnull c->attr = addcap(c->attr, c->sysuser, &t);
216 2277c5d7 2004-03-21 devnull des56to64((uchar*)t.key, secret);
217 2277c5d7 2004-03-21 devnull c->attr = addattr(c->attr, "secret=%.8H", secret);
218 2277c5d7 2004-03-21 devnull ret = 0;
221 2277c5d7 2004-03-21 devnull freeattr(a);
222 2277c5d7 2004-03-21 devnull keyclose(k);
223 2277c5d7 2004-03-21 devnull return ret;
227 2277c5d7 2004-03-21 devnull _asgetticket(int fd, char *trbuf, char *tbuf)
229 2277c5d7 2004-03-21 devnull if(write(fd, trbuf, TICKREQLEN) < 0){
230 2277c5d7 2004-03-21 devnull close(fd);
231 2277c5d7 2004-03-21 devnull return -1;
233 2277c5d7 2004-03-21 devnull return _asrdresp(fd, tbuf, 2*TICKETLEN);
235 2277c5d7 2004-03-21 devnull static int
236 2277c5d7 2004-03-21 devnull getastickets(Ticketreq *tr, char *buf)
238 2277c5d7 2004-03-21 devnull int asfd;
239 2277c5d7 2004-03-21 devnull int ret;
241 2277c5d7 2004-03-21 devnull if((asfd = xioauthdial(nil, tr->authdom)) < 0)
242 2277c5d7 2004-03-21 devnull return -1;
243 2277c5d7 2004-03-21 devnull convTR2M(tr, buf);
244 2277c5d7 2004-03-21 devnull ret = xioasgetticket(asfd, buf, buf);
245 2277c5d7 2004-03-21 devnull xioclose(asfd);
246 2277c5d7 2004-03-21 devnull return ret;
249 2277c5d7 2004-03-21 devnull static int
250 2277c5d7 2004-03-21 devnull mktickets(Ticketreq *tr, char *buf, Key *k)
252 2277c5d7 2004-03-21 devnull Ticket t;
254 2277c5d7 2004-03-21 devnull if(strcmp(tr->authid, tr->hostid) != 0)
255 2277c5d7 2004-03-21 devnull return -1;
257 2277c5d7 2004-03-21 devnull memset(&t, 0, sizeof t);
258 2277c5d7 2004-03-21 devnull memmove(t.chal, tr->chal, CHALLEN);
259 2277c5d7 2004-03-21 devnull strcpy(t.cuid, tr->uid);
260 2277c5d7 2004-03-21 devnull strcpy(t.suid, tr->uid);
261 2277c5d7 2004-03-21 devnull memrandom(t.key, DESKEYLEN);
262 2277c5d7 2004-03-21 devnull t.num = AuthTc;
263 2277c5d7 2004-03-21 devnull convT2M(&t, buf, k->priv);
264 2277c5d7 2004-03-21 devnull t.num = AuthTs;
265 2277c5d7 2004-03-21 devnull convT2M(&t, buf+TICKETLEN, k->priv);
266 2277c5d7 2004-03-21 devnull return 0;
269 2277c5d7 2004-03-21 devnull static int
270 2277c5d7 2004-03-21 devnull gettickets(Ticketreq *tr, char *buf, Key *k)
272 2277c5d7 2004-03-21 devnull if(getastickets(tr, buf) == 0)
273 2277c5d7 2004-03-21 devnull return 0;
274 2277c5d7 2004-03-21 devnull if(mktickets(tr, buf, k) == 0)
275 2277c5d7 2004-03-21 devnull return 0;
276 2277c5d7 2004-03-21 devnull werrstr("gettickets: %r");
277 2277c5d7 2004-03-21 devnull return -1;
280 2277c5d7 2004-03-21 devnull static int
281 2277c5d7 2004-03-21 devnull p9sk1check(Key *k)
283 2277c5d7 2004-03-21 devnull char *user, *dom, *pass;
284 2277c5d7 2004-03-21 devnull Ticketreq tr;
286 2277c5d7 2004-03-21 devnull user = strfindattr(k->attr, "user");
287 2277c5d7 2004-03-21 devnull dom = strfindattr(k->attr, "dom");
288 2277c5d7 2004-03-21 devnull if(user==nil || dom==nil){
289 2277c5d7 2004-03-21 devnull werrstr("need user and dom attributes");
290 2277c5d7 2004-03-21 devnull return -1;
292 2277c5d7 2004-03-21 devnull if(strlen(user) >= sizeof tr.authid){
293 2277c5d7 2004-03-21 devnull werrstr("user name too long");
294 2277c5d7 2004-03-21 devnull return -1;
296 2277c5d7 2004-03-21 devnull if(strlen(dom) >= sizeof tr.authdom){
297 2277c5d7 2004-03-21 devnull werrstr("auth dom name too long");
298 2277c5d7 2004-03-21 devnull return -1;
301 2277c5d7 2004-03-21 devnull k->priv = emalloc(DESKEYLEN);
302 2277c5d7 2004-03-21 devnull if(pass = strfindattr(k->privattr, "!password"))
303 2277c5d7 2004-03-21 devnull passtokey(k->priv, pass);
304 2277c5d7 2004-03-21 devnull else if(pass = strfindattr(k->privattr, "!hex")){
305 2277c5d7 2004-03-21 devnull if(hexparse(pass, k->priv, 7) < 0){
306 2277c5d7 2004-03-21 devnull werrstr("malformed !hex key data");
307 2277c5d7 2004-03-21 devnull return -1;
310 2277c5d7 2004-03-21 devnull werrstr("need !password or !hex attribute");
311 2277c5d7 2004-03-21 devnull return -1;
314 2277c5d7 2004-03-21 devnull return 0;
317 2277c5d7 2004-03-21 devnull static void
318 2277c5d7 2004-03-21 devnull p9sk1close(Key *k)
320 2277c5d7 2004-03-21 devnull free(k->priv);
321 2277c5d7 2004-03-21 devnull k->priv = nil;
324 2277c5d7 2004-03-21 devnull static Role
325 2277c5d7 2004-03-21 devnull p9sk1roles[] =
327 2277c5d7 2004-03-21 devnull "client", p9skclient,
328 2277c5d7 2004-03-21 devnull "server", p9skserver,
332 2277c5d7 2004-03-21 devnull static Role
333 2277c5d7 2004-03-21 devnull p9sk2roles[] =
335 2277c5d7 2004-03-21 devnull "client", p9skclient,
336 2277c5d7 2004-03-21 devnull "server", p9skserver,
340 2277c5d7 2004-03-21 devnull Proto p9sk1 = {
341 2277c5d7 2004-03-21 devnull .name= "p9sk1",
342 2277c5d7 2004-03-21 devnull .roles= p9sk1roles,
343 2277c5d7 2004-03-21 devnull .checkkey= p9sk1check,
344 2277c5d7 2004-03-21 devnull .closekey= p9sk1close,
345 2277c5d7 2004-03-21 devnull .keyprompt= "user? dom? !password?",
348 2277c5d7 2004-03-21 devnull Proto p9sk2 = {
349 2277c5d7 2004-03-21 devnull .name= "p9sk2",
350 2277c5d7 2004-03-21 devnull .roles= p9sk2roles,