diff options
Diffstat (limited to 'src/cmd/factotum/apop.c')
-rw-r--r-- | src/cmd/factotum/apop.c | 348 |
1 files changed, 0 insertions, 348 deletions
diff --git a/src/cmd/factotum/apop.c b/src/cmd/factotum/apop.c deleted file mode 100644 index f555c394..00000000 --- a/src/cmd/factotum/apop.c +++ /dev/null @@ -1,348 +0,0 @@ -/* - * APOP, CRAM - MD5 challenge/response authentication - * - * The client does not authenticate the server, hence no CAI. - * - * Protocol: - * - * S -> C: random@domain - * C -> S: hex-response - * S -> C: ok - * - * Note that this is the protocol between factotum and the local - * program, not between the two factotums. The information - * exchanged here is wrapped in the APOP protocol by the local - * programs. - * - * If S sends "bad [msg]" instead of "ok", that is a hint that the key is bad. - * The protocol goes back to "C -> S: user". - */ - -#include "std.h" -#include "dat.h" - -static int -apopcheck(Key *k) -{ - if(!strfindattr(k->attr, "user") || !strfindattr(k->privattr, "!password")){ - werrstr("need user and !password attributes"); - return -1; - } - return 0; -} - -static int -apopclient(Conv *c) -{ - char *chal, *pw, *res; - int astype, nchal, npw, ntry, ret; - uchar resp[MD5dlen]; - Attr *attr; - DigestState *ds; - Key *k; - - chal = nil; - k = nil; - res = nil; - ret = -1; - attr = c->attr; - - if(c->proto == &apop) - astype = AuthApop; - else if(c->proto == &cram) - astype = AuthCram; - else{ - werrstr("bad proto"); - goto out; - } - - c->state = "find key"; - k = keyfetch(c, "%A %s", attr, c->proto->keyprompt); - if(k == nil) - goto out; - - c->state = "read challenge"; - if((nchal = convreadm(c, &chal)) < 0) - goto out; - - for(ntry=1;; ntry++){ - if(c->attr != attr) - freeattr(c->attr); - c->attr = addattrs(copyattr(attr), k->attr); - if((pw = strfindattr(k->privattr, "!password")) == nil){ - werrstr("key has no password (cannot happen?)"); - goto out; - } - npw = strlen(pw); - - switch(astype){ - case AuthApop: - ds = md5((uchar*)chal, nchal, nil, nil); - md5((uchar*)pw, npw, resp, ds); - break; - case AuthCram: - hmac_md5((uchar*)chal, nchal, (uchar*)pw, npw, resp, nil); - break; - } - - /* C->S: APOP user hex-response\n */ - if(ntry == 1) - c->state = "write user"; - else{ - sprint(c->statebuf, "write user (auth attempt #%d)", ntry); - c->state = c->statebuf; - } - if(convprint(c, "%s", strfindattr(k->attr, "user")) < 0) - goto out; - - c->state = "write response"; - if(convprint(c, "%.*H", sizeof resp, resp) < 0) - goto out; - - c->state = "read result"; - if(convreadm(c, &res) < 0) - goto out; - - if(strcmp(res, "ok") == 0) - break; - - if(strncmp(res, "bad ", 4) != 0){ - werrstr("bad result: %s", res); - goto out; - } - - c->state = "replace key"; - if((k = keyreplace(c, k, "%s", res+4)) == nil){ - c->state = "auth failed"; - werrstr("%s", res+4); - goto out; - } - free(res); - res = nil; - } - - werrstr("succeeded"); - ret = 0; - -out: - keyclose(k); - free(chal); - if(c->attr != attr) - freeattr(attr); - return ret; -} - -/* shared with auth dialing routines */ -typedef struct ServerState ServerState; -struct ServerState -{ - int asfd; - Key *k; - Ticketreq tr; - Ticket t; - char *dom; - char *hostid; -}; - -enum -{ - APOPCHALLEN = 128, -}; - -static int apopchal(ServerState*, int, char[APOPCHALLEN]); -static int apopresp(ServerState*, char*, char*); - -static int -apopserver(Conv *c) -{ - char chal[APOPCHALLEN], *user, *resp; - ServerState s; - int astype, ret; - Attr *a; - - ret = -1; - user = nil; - resp = nil; - memset(&s, 0, sizeof s); - s.asfd = -1; - - if(c->proto == &apop) - astype = AuthApop; - else if(c->proto == &cram) - astype = AuthCram; - else{ - werrstr("bad proto"); - goto out; - } - - c->state = "find key"; - if((s.k = plan9authkey(c->attr)) == nil) - goto out; - - a = copyattr(s.k->attr); - a = delattr(a, "proto"); - c->attr = addattrs(c->attr, a); - freeattr(a); - - c->state = "authdial"; - s.hostid = strfindattr(s.k->attr, "user"); - s.dom = strfindattr(s.k->attr, "dom"); - if((s.asfd = xioauthdial(nil, s.dom)) < 0){ - werrstr("authdial %s: %r", s.dom); - goto out; - } - - c->state = "authchal"; - if(apopchal(&s, astype, chal) < 0) - goto out; - - c->state = "write challenge"; - if(convprint(c, "%s", chal) < 0) - goto out; - - for(;;){ - c->state = "read user"; - if(convreadm(c, &user) < 0) - goto out; - - c->state = "read response"; - if(convreadm(c, &resp) < 0) - goto out; - - c->state = "authwrite"; - switch(apopresp(&s, user, resp)){ - case -1: - goto out; - case 0: - c->state = "write status"; - if(convprint(c, "bad authentication failed") < 0) - goto out; - break; - case 1: - c->state = "write status"; - if(convprint(c, "ok") < 0) - goto out; - goto ok; - } - free(user); - free(resp); - user = nil; - resp = nil; - } - -ok: - ret = 0; - c->attr = addcap(c->attr, c->sysuser, &s.t); - -out: - keyclose(s.k); - free(user); - free(resp); -// xioclose(s.asfd); - return ret; -} - -static int -apopchal(ServerState *s, int astype, char chal[APOPCHALLEN]) -{ - char trbuf[TICKREQLEN]; - Ticketreq tr; - - memset(&tr, 0, sizeof tr); - - tr.type = astype; - - if(strlen(s->hostid) >= sizeof tr.hostid){ - werrstr("hostid too long"); - return -1; - } - strcpy(tr.hostid, s->hostid); - - if(strlen(s->dom) >= sizeof tr.authdom){ - werrstr("domain too long"); - return -1; - } - strcpy(tr.authdom, s->dom); - - convTR2M(&tr, trbuf); - if(xiowrite(s->asfd, trbuf, TICKREQLEN) != TICKREQLEN) - return -1; - - if(xioasrdresp(s->asfd, chal, APOPCHALLEN) <= 5) - return -1; - - s->tr = tr; - return 0; -} - -static int -apopresp(ServerState *s, char *user, char *resp) -{ - char tabuf[TICKETLEN+AUTHENTLEN]; - char trbuf[TICKREQLEN]; - int len; - Authenticator a; - Ticket t; - Ticketreq tr; - - tr = s->tr; - if(memrandom(tr.chal, CHALLEN) < 0) - return -1; - - if(strlen(user) >= sizeof tr.uid){ - werrstr("uid too long"); - return -1; - } - strcpy(tr.uid, user); - - convTR2M(&tr, trbuf); - if(xiowrite(s->asfd, trbuf, TICKREQLEN) != TICKREQLEN) - return -1; - - len = strlen(resp); - if(xiowrite(s->asfd, resp, len) != len) - return -1; - - if(xioasrdresp(s->asfd, tabuf, TICKETLEN+AUTHENTLEN) != TICKETLEN+AUTHENTLEN) - return 0; - - convM2T(tabuf, &t, s->k->priv); - if(t.num != AuthTs - || memcmp(t.chal, tr.chal, sizeof tr.chal) != 0){ - werrstr("key mismatch with auth server"); - return -1; - } - - convM2A(tabuf+TICKETLEN, &a, t.key); - if(a.num != AuthAc - || memcmp(a.chal, tr.chal, sizeof a.chal) != 0 - || a.id != 0){ - werrstr("key2 mismatch with auth server"); - return -1; - } - - s->t = t; - return 1; -} - -static Role -apoproles[] = -{ - "client", apopclient, - "server", apopserver, - 0 -}; - -Proto apop = { -.name= "apop", -.roles= apoproles, -.checkkey= apopcheck, -.keyprompt= "user? !password?", -}; - -Proto cram = { -.name= "cram", -.roles= apoproles, -.checkkey= apopcheck, -.keyprompt= "user? !password?", -}; |