/*
 * p9cr - one-sided challenge/response authentication
 *
 * Protocol:
 *
 *	C -> S: user
 *	S -> C: challenge
 *	C -> S: response
 *	S -> C: ok or bad
 *
 * Note that this is the protocol between factotum and the local
 * program, not between the two factotums.  The information 
 * exchanged here is wrapped in other protocols by the local
 * programs.
 */

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

/* shared with auth dialing routines */
typedef struct ServerState ServerState;
struct ServerState
{
	int asfd;
	Key *k;
	Ticketreq tr;
	Ticket t;
	char *dom;
	char *hostid;
};

enum
{
	MAXCHAL = 64,
	MAXRESP = 64,
};

extern Proto p9cr, vnc;
static int p9response(char*, uchar*, uchar*);
// static int vncresponse(char*, uchar*, uchar*);
static int p9crchal(ServerState *s, int, char*, uchar*, int);
static int p9crresp(ServerState*, uchar*, int);

static int
p9crcheck(Key *k)
{
	if(!strfindattr(k->attr, "user") || !strfindattr(k->privattr, "!password")){
		werrstr("need user and !password attributes");
		return -1;
	}
	return 0;
}

static int
p9crclient(Conv *c)
{
	char *pw, *res, *user;
	int astype, challen, resplen, ntry, ret;
	Attr *attr;
	Key *k;
	uchar chal[MAXCHAL+1], resp[MAXRESP];
	int (*response)(char*, uchar*, uchar*);

	k = nil;
	res = nil;
	ret = -1;
	attr = c->attr;

	if(c->proto == &p9cr){
		astype = AuthChal;
		challen = NETCHLEN;
		response = p9response;
		attr = _mkattr(AttrNameval, "proto", "p9sk1", _delattr(_copyattr(attr), "proto"));
	}else if(c->proto == &vnc){
		astype = AuthVNC;
		challen = MAXCHAL;
	//	response = vncresponse;
		werrstr("no vnc");
		goto out;
	}else{
		werrstr("bad proto");
		goto out;
	}

	c->state = "find key";
	k = keyfetch(c, "%A %s", attr, c->proto->keyprompt);
	if(k == nil)
		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;
		}
		if((user = strfindattr(k->attr, "user")) == nil){
			werrstr("key has no user (cannot happen)");
			goto out;
		}

		if(convprint(c, "%s", user) < 0)
			goto out;

		if(convread(c, chal, challen) < 0)
			goto out;
		chal[challen] = 0;

		if((resplen = (*response)(pw, chal, resp)) < 0)
			goto out;

		if(convwrite(c, resp, resplen) < 0)
			goto out;

		if(convreadm(c, &res) < 0)
			goto out;

		if(strcmp(res, "ok") == 0)
			break;

		if((k = keyreplace(c, k, "%s", res)) == nil){
			c->state = "auth failed";
			werrstr("%s", res);
			goto out;
		}
	}

	werrstr("succeeded");
	ret = 0;

out:
	keyclose(k);
	if(c->attr != attr)
		freeattr(attr);
	return ret;
}

static int
p9crserver(Conv *c)
{
	uchar chal[MAXCHAL], *resp, *resp1;
	char *user;
	ServerState s;
	int astype, ret, challen, resplen;
	Attr *a;

	ret = -1;
	user = nil;
	resp = nil;
	memset(&s, 0, sizeof s);
	s.asfd = -1;

	if(c->proto == &p9cr){
		astype = AuthChal;
		challen = NETCHLEN;
	}else if(c->proto == &vnc){
		challen = MAXCHAL;
	}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;
	}

	for(;;){
		c->state = "read user";
		if(convreadm(c, &user) < 0)
			goto out;

		c->state = "authchal";
		if(p9crchal(&s, astype, user, chal, challen) < 0)
			goto out;

		c->state = "write challenge";
		if(convwrite(c, chal, challen) < 0)
			goto out;

		c->state = "read response";
		if((resplen = convreadm(c, (char**)(void*)&resp)) < 0)
			goto out;
		if(c->proto == &p9cr){
			if(resplen > NETCHLEN){
				convprint(c, "bad response too long");
				goto out;
			}
			resp1 = emalloc(NETCHLEN);
			memset(resp1, 0, NETCHLEN);
			memmove(resp1, resp, resplen);
			free(resp);
			resp = resp1;
			resplen = NETCHLEN;
		}

		c->state = "authwrite";
		switch(p9crresp(&s, resp, resplen)){
		case -1:
			fprint(2, "p9crresp: %r\n");
			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
p9crchal(ServerState *s, int astype, char *user, uchar *chal, int challen)
{
	char trbuf[TICKREQLEN];
	Ticketreq tr;
	int n;

	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);

	if(strlen(user) >= sizeof tr.uid){
		werrstr("user name too long");
		return -1;
	}
	strcpy(tr.uid, user);
	convTR2M(&tr, trbuf);

	if(xiowrite(s->asfd, trbuf, TICKREQLEN) != TICKREQLEN)
		return -1;

	if((n=xioasrdresp(s->asfd, chal, challen)) <= 0)
		return -1;
	return n;
}

static int
p9crresp(ServerState *s, uchar *resp, int resplen)
{
	char tabuf[TICKETLEN+AUTHENTLEN];
	Authenticator a;
	Ticket t;
	Ticketreq tr;

	if(xiowrite(s->asfd, resp, resplen) != resplen)
		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 int
p9response(char *pw, uchar *chal, uchar *resp)
{	
	char key[DESKEYLEN];
	uchar buf[8];
	ulong x;

	passtokey(key, pw);
	memset(buf, 0, 8);
	snprint((char*)buf, sizeof buf, "%d", atoi((char*)chal));
	if(encrypt(key, buf, 8) < 0){
		werrstr("can't encrypt response");
		return -1;
	}
	x = (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+buf[3];
	return snprint((char*)resp, MAXRESP, "%.8lux", x);
}

/*
static int
vncresponse(char *pw, uchar *chal, uchar *resp)
{
	DESstate des;
	
	memmove(resp, chal, MAXCHAL);
	setupDESstate(&des, 0, nil);  // XXX put key in for 0
	desECBencrypt(resp, MAXCHAL, &des);
	return MAXCHAL;
}
*/

static Role
p9crroles[] =
{
	"client", p9crclient,
	"server", p9crserver,
	0
};

Proto p9cr = {
	"p9cr",
	p9crroles,
	"user? !password?",
	p9crcheck,
	nil
};

/* still need to implement vnc key generator */
Proto vnc = {
	"vnc",
	p9crroles,
	"user? !password?",
	p9crcheck,
	nil
};
