/*
 * APOP, CRAM - MD5 challenge/response authentication
 *
 * The client does not authenticate the server, hence no CAI.
 *
 * Protocol:
 *
 *	S -> C:	random@domain
 *	C -> S:	user 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 hex-response".
 */

#include "std.h"
#include "dat.h"

extern Proto apop, cram;

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 = {
	"apop",
	apoproles,
	"user? !password?",
	apopcheck,
	nil
};

Proto cram = {
	"cram",
	apoproles,
	"user? !password?",
	apopcheck,
	nil
};

