/*
 * p9sk1, p9sk2 - Plan 9 secret (private) key authentication.
 * p9sk2 is an incomplete flawed variant of p9sk1.
 *
 * Client protocol:
 *	write challenge[challen]	(p9sk1 only)
 *	read tickreq[tickreqlen]
 *	write ticket[ticketlen]
 *	read authenticator[authentlen]
 *
 * Server protocol:
 * 	read challenge[challen]	(p9sk1 only)
 *	write tickreq[tickreqlen]
 *	read ticket[ticketlen]
 *	write authenticator[authentlen]
 */

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

extern Proto p9sk1, p9sk2;
static int gettickets(Ticketreq*, char*, Key*);

#define max(a, b) ((a) > (b) ? (a) : (b))
enum
{
	MAXAUTH = max(TICKREQLEN, TICKETLEN+max(TICKETLEN, AUTHENTLEN))
};

static int
p9skclient(Conv *c)
{
	char *user;
	char cchal[CHALLEN];
	uchar secret[8];
	char buf[MAXAUTH];
	int speakfor, ret;
	Attr *a;
	Authenticator au;
	Key *k;
	Ticket t;
	Ticketreq tr;

	ret = -1;
	a = nil;
	k = nil;

	/* p9sk1: send client challenge */
	if(c->proto == &p9sk1){
		c->state = "write challenge";
		memrandom(cchal, CHALLEN);
		if(convwrite(c, cchal, CHALLEN) < 0)
			goto out;
	}

	/* read ticket request */
	c->state = "read tickreq";
	if(convread(c, buf, TICKREQLEN) < 0)
		goto out;
	convM2TR(buf, &tr);

	/* p9sk2: use server challenge as client challenge */
	if(c->proto == &p9sk2)
		memmove(cchal, tr.chal, CHALLEN);

	/*
	 * find a key.
	 *
	 * if the user is the factotum owner, any key will do.
	 * if not, then if we have a speakfor key,
	 * we will only vouch for the user's local identity.
	 *
	 * this logic is duplicated in p9any.c
	 */
	user = strfindattr(c->attr, "user");
	a = delattr(copyattr(c->attr), "role");
	a = addattr(a, "proto=p9sk1");

	if(strcmp(c->sysuser, owner) == 0){
		speakfor = 0;
		a = addattr(a, "proto=p9sk1 user? dom=%q", tr.authdom);
	}else if(user==nil || strcmp(c->sysuser, user)==0){
		speakfor = 1;
		a = delattr(a, "user");
		a = addattr(a, "proto=p9sk1 user? dom=%q role=speakfor", tr.authdom);
	}else{
		werrstr("will not authenticate for %q as %q", c->sysuser, user);
		goto out;
	}

	for(;;){
		c->state = "find key";
		k = keyfetch(c, "%A", a);
		if(k == nil)
			goto out;
		
		/* relay ticket request to auth server, get tickets */
		strcpy(tr.hostid, strfindattr(k->attr, "user"));
		if(speakfor)
			strcpy(tr.uid, c->sysuser);
		else
			strcpy(tr.uid, tr.hostid);

		c->state = "get tickets";
		if(gettickets(&tr, buf, k) < 0)
			goto out;

		convM2T(buf, &t, k->priv);
		if(t.num == AuthTc)
			break;

		/* we don't agree with the auth server about the key; try again */
		c->state = "replace key";
		if((k = keyreplace(c, k, "key mismatch with auth server")) == nil){
			werrstr("key mismatch with auth server");
			goto out;
		}
	}

	/* send second ticket and authenticator to server */
	c->state = "write ticket+auth";
	memmove(buf, buf+TICKETLEN, TICKETLEN);
	au.num = AuthAc;
	memmove(au.chal, tr.chal, CHALLEN);
	au.id = 0;
	convA2M(&au, buf+TICKETLEN, t.key);
	if(convwrite(c, buf, TICKETLEN+AUTHENTLEN) < 0)
		goto out;

	/* read authenticator from server */
	c->state = "read auth";
	if(convread(c, buf, AUTHENTLEN) < 0)
		goto out;
	convM2A(buf, &au, t.key);
	if(au.num != AuthAs || memcmp(au.chal, cchal, CHALLEN) != 0 || au.id != 0){
		werrstr("server lies through his teeth");
		goto out;
	}

	/* success */
	c->attr = addcap(c->attr, c->sysuser, &t);
	flog("p9skclient success %A", c->attr);	/* before adding secret! */
	des56to64((uchar*)t.key, secret);
	c->attr = addattr(c->attr, "secret=%.8H", secret);
	ret = 0;

out:
	if(ret < 0)
		flog("p9skclient: %r");
	freeattr(a);
	keyclose(k);
	return ret;
}

static int
p9skserver(Conv *c)
{
	char cchal[CHALLEN], buf[MAXAUTH];
	uchar secret[8];
	int ret;
	Attr *a;
	Authenticator au;
	Key *k;
	Ticketreq tr;
	Ticket t;

	ret = -1;

	a = addattr(copyattr(c->attr), "user? dom?");
	a = addattr(a, "user? dom? proto=p9sk1");
	if((k = keyfetch(c, "%A", a)) == nil)
		goto out;

	/* p9sk1: read client challenge */
	if(c->proto == &p9sk1){
		if(convread(c, cchal, CHALLEN) < 0)
			goto out;
	}

	/* send ticket request */
	memset(&tr, 0, sizeof tr);
	tr.type = AuthTreq;
	strcpy(tr.authid, strfindattr(k->attr, "user"));
	strcpy(tr.authdom, strfindattr(k->attr, "dom"));
	memrandom(tr.chal, sizeof tr.chal);
	convTR2M(&tr, buf);
	if(convwrite(c, buf, TICKREQLEN) < 0)
		goto out;

	/* p9sk2: use server challenge as client challenge */
	if(c->proto == &p9sk2)
		memmove(cchal, tr.chal, sizeof tr.chal);

	/* read ticket+authenticator */
	if(convread(c, buf, TICKETLEN+AUTHENTLEN) < 0)
		goto out;

	convM2T(buf, &t, k->priv);
	if(t.num != AuthTs || memcmp(t.chal, tr.chal, CHALLEN) != 0){
		/* BUG badkey */
		werrstr("key mismatch with auth server");
		goto out;
	}

	convM2A(buf+TICKETLEN, &au, t.key);
	if(au.num != AuthAc || memcmp(au.chal, tr.chal, CHALLEN) != 0 || au.id != 0){
		werrstr("client lies through his teeth");
		goto out;
	}

	/* send authenticator */
	au.num = AuthAs;
	memmove(au.chal, cchal, CHALLEN);
	convA2M(&au, buf, t.key);
	if(convwrite(c, buf, AUTHENTLEN) < 0)
		goto out;

	/* success */
	c->attr = addcap(c->attr, c->sysuser, &t);
	flog("p9skserver success %A", c->attr);	/* before adding secret! */
	des56to64((uchar*)t.key, secret);
	c->attr = addattr(c->attr, "secret=%.8H", secret);
	ret = 0;

out:
	if(ret < 0)
		flog("p9skserver: %r");
	freeattr(a);
	keyclose(k);
	return ret;
}

int
_asgetticket(int fd, char *trbuf, char *tbuf)
{
	if(write(fd, trbuf, TICKREQLEN) < 0){
		close(fd);
		return -1;
	}
	return _asrdresp(fd, tbuf, 2*TICKETLEN);
}
static int
getastickets(Ticketreq *tr, char *buf)
{
	int asfd;
	int ret;

	if((asfd = xioauthdial(nil, tr->authdom)) < 0)
		return -1;
	convTR2M(tr, buf);
	ret = xioasgetticket(asfd, buf, buf);
	xioclose(asfd);
	return ret;
}

static int
mktickets(Ticketreq *tr, char *buf, Key *k)
{
	Ticket t;

	if(strcmp(tr->authid, tr->hostid) != 0)
		return -1;

	memset(&t, 0, sizeof t);
	memmove(t.chal, tr->chal, CHALLEN);
	strcpy(t.cuid, tr->uid);
	strcpy(t.suid, tr->uid);
	memrandom(t.key, DESKEYLEN);
	t.num = AuthTc;
	convT2M(&t, buf, k->priv);
	t.num = AuthTs;
	convT2M(&t, buf+TICKETLEN, k->priv);
	return 0;
}

static int
gettickets(Ticketreq *tr, char *buf, Key *k)
{
	if(getastickets(tr, buf) == 0)
		return 0;
	if(mktickets(tr, buf, k) == 0)
		return 0;
	werrstr("gettickets: %r");
	return -1;
}

static int
p9sk1check(Key *k)
{
	char *user, *dom, *pass;
	Ticketreq tr;

	user = strfindattr(k->attr, "user");
	dom = strfindattr(k->attr, "dom");
	if(user==nil || dom==nil){
		werrstr("need user and dom attributes");
		return -1;
	}
	if(strlen(user) >= sizeof tr.authid){
		werrstr("user name too long");
		return -1;
	}
	if(strlen(dom) >= sizeof tr.authdom){
		werrstr("auth dom name too long");
		return -1;
	}

	k->priv = emalloc(DESKEYLEN);
	if(pass = strfindattr(k->privattr, "!password"))
		passtokey(k->priv, pass);
	else if(pass = strfindattr(k->privattr, "!hex")){
		if(hexparse(pass, k->priv, 7) < 0){
			werrstr("malformed !hex key data");
			return -1;
		}
	}else{
		werrstr("need !password or !hex attribute");
		return -1;
	}

	return 0;
}

static void
p9sk1close(Key *k)
{
	free(k->priv);
	k->priv = nil;
}

static Role
p9sk1roles[] = 
{
	"client",	p9skclient,
	"server",	p9skserver,
	0
};

static Role
p9sk2roles[] = 
{
	"client",	p9skclient,
	"server",	p9skserver,
	0
};

Proto p9sk1 = {
	"p9sk1",
	p9sk1roles,
	"user? dom? !password?",
	p9sk1check,
	p9sk1close
};

Proto p9sk2 = {
	"p9sk2",
	p9sk2roles
};

