/*
 * 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;
	astype = -1;

	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:
	USED(astype);
	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
};
