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

