/*
 * 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?",
};
