aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/factotum/apop.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/factotum/apop.c')
-rw-r--r--src/cmd/factotum/apop.c348
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?",
-};