xref: /plan9/sys/src/cmd/disk/kfs/auth.c (revision d9306527b4a7229dcf0cf3c58aed36bb9da82854)
159cc4ca5SDavid du Colombier /*
259cc4ca5SDavid du Colombier  * Network listening authentication.
359cc4ca5SDavid du Colombier  * This and all the other network-related
459cc4ca5SDavid du Colombier  * code is due to Richard Miller.
559cc4ca5SDavid du Colombier  */
659cc4ca5SDavid du Colombier #include	"all.h"
79a747e4fSDavid du Colombier #include	"9p1.h"
859cc4ca5SDavid du Colombier 
959cc4ca5SDavid du Colombier int allownone;
109a747e4fSDavid du Colombier Nvrsafe nvr;
119a747e4fSDavid du Colombier int didread;
1259cc4ca5SDavid du Colombier 
1359cc4ca5SDavid du Colombier /*
1459cc4ca5SDavid du Colombier  *  create a challenge for a fid space
1559cc4ca5SDavid du Colombier  */
1659cc4ca5SDavid du Colombier void
mkchallenge(Chan * cp)1759cc4ca5SDavid du Colombier mkchallenge(Chan *cp)
1859cc4ca5SDavid du Colombier {
1959cc4ca5SDavid du Colombier 	int i;
2059cc4ca5SDavid du Colombier 
219a747e4fSDavid du Colombier 	if(!didread && readnvram(&nvr, 0) >= 0)
229a747e4fSDavid du Colombier 		didread = 1;
239a747e4fSDavid du Colombier 
2459cc4ca5SDavid du Colombier 	srand(truerand());
2559cc4ca5SDavid du Colombier 	for(i = 0; i < CHALLEN; i++)
2659cc4ca5SDavid du Colombier 		cp->chal[i] = nrand(256);
2759cc4ca5SDavid du Colombier 
2859cc4ca5SDavid du Colombier 	cp->idoffset = 0;
2959cc4ca5SDavid du Colombier 	cp->idvec = 0;
3059cc4ca5SDavid du Colombier }
3159cc4ca5SDavid du Colombier 
3259cc4ca5SDavid du Colombier /*
3359cc4ca5SDavid du Colombier  *  match a challenge from an attach
3459cc4ca5SDavid du Colombier  */
359a747e4fSDavid du Colombier Nvrsafe nvr;
369a747e4fSDavid du Colombier 
3759cc4ca5SDavid du Colombier int
authorize(Chan * cp,Oldfcall * in,Oldfcall * ou)389a747e4fSDavid du Colombier authorize(Chan *cp, Oldfcall *in, Oldfcall *ou)
3959cc4ca5SDavid du Colombier {
4059cc4ca5SDavid du Colombier 	Ticket t;
4159cc4ca5SDavid du Colombier 	Authenticator a;
4259cc4ca5SDavid du Colombier 	int x;
4359cc4ca5SDavid du Colombier 	ulong bit;
4459cc4ca5SDavid du Colombier 
4559cc4ca5SDavid du Colombier 	if (cp == cons.srvchan)               /* local channel already safe */
4659cc4ca5SDavid du Colombier 		return 1;
4759cc4ca5SDavid du Colombier 
489a747e4fSDavid du Colombier 	if(wstatallow)		/* set to allow entry during boot */
4959cc4ca5SDavid du Colombier 		return 1;
5059cc4ca5SDavid du Colombier 
5159cc4ca5SDavid du Colombier 	if(strcmp(in->uname, "none") == 0)
529a747e4fSDavid du Colombier 		return allownone || cp->authed;
5359cc4ca5SDavid du Colombier 
549a747e4fSDavid du Colombier 	if(in->type == Toattach9p1)
559a747e4fSDavid du Colombier 		return 0;
569a747e4fSDavid du Colombier 
579a747e4fSDavid du Colombier 	if(!didread)
5859cc4ca5SDavid du Colombier 		return 0;
5959cc4ca5SDavid du Colombier 
6059cc4ca5SDavid du Colombier 	/* decrypt and unpack ticket */
61*d9306527SDavid du Colombier 	convM2T(in->ticket, &t, nvr.machkey);
6259cc4ca5SDavid du Colombier 	if(t.num != AuthTs){
6359cc4ca5SDavid du Colombier print("bad AuthTs num\n");
6459cc4ca5SDavid du Colombier 		return 0;
6559cc4ca5SDavid du Colombier 	}
6659cc4ca5SDavid du Colombier 
6759cc4ca5SDavid du Colombier 	/* decrypt and unpack authenticator */
6859cc4ca5SDavid du Colombier 	convM2A(in->auth, &a, t.key);
6959cc4ca5SDavid du Colombier 	if(a.num != AuthAc){
7059cc4ca5SDavid du Colombier print("bad AuthAc num\n");
7159cc4ca5SDavid du Colombier 		return 0;
7259cc4ca5SDavid du Colombier 	}
7359cc4ca5SDavid du Colombier 
7459cc4ca5SDavid du Colombier 	/* challenges must match */
7559cc4ca5SDavid du Colombier 	if(memcmp(a.chal, cp->chal, sizeof(a.chal)) != 0){
7659cc4ca5SDavid du Colombier print("bad challenge\n");
7759cc4ca5SDavid du Colombier 		return 0;
7859cc4ca5SDavid du Colombier 	}
7959cc4ca5SDavid du Colombier 
8059cc4ca5SDavid du Colombier 	/*
8159cc4ca5SDavid du Colombier 	 *  the id must be in a valid range.  the range is specified by a
8259cc4ca5SDavid du Colombier 	 *  lower bount (idoffset) and a bit vector (idvec) where a
8359cc4ca5SDavid du Colombier 	 *  bit set to 1 means unusable
8459cc4ca5SDavid du Colombier 	 */
8559cc4ca5SDavid du Colombier 	lock(&cp->idlock);
8659cc4ca5SDavid du Colombier 	x = a.id - cp->idoffset;
8759cc4ca5SDavid du Colombier 	bit = 1<<x;
8859cc4ca5SDavid du Colombier 	if(x < 0 || x > 31 || (bit&cp->idvec)){
8959cc4ca5SDavid du Colombier 		unlock(&cp->idlock);
9059cc4ca5SDavid du Colombier 		return 0;
9159cc4ca5SDavid du Colombier 	}
9259cc4ca5SDavid du Colombier 	cp->idvec |= bit;
9359cc4ca5SDavid du Colombier 
9459cc4ca5SDavid du Colombier 	/* normalize the vector */
9559cc4ca5SDavid du Colombier 	while(cp->idvec&0xffff0001){
9659cc4ca5SDavid du Colombier 		cp->idvec >>= 1;
9759cc4ca5SDavid du Colombier 		cp->idoffset++;
9859cc4ca5SDavid du Colombier 	}
9959cc4ca5SDavid du Colombier 	unlock(&cp->idlock);
10059cc4ca5SDavid du Colombier 
10159cc4ca5SDavid du Colombier 	/* ticket name and attach name must match */
10259cc4ca5SDavid du Colombier 	if(memcmp(in->uname, t.cuid, sizeof(in->uname)) != 0){
10359cc4ca5SDavid du Colombier print("names don't match\n");
10459cc4ca5SDavid du Colombier 		return 0;
10559cc4ca5SDavid du Colombier 	}
10659cc4ca5SDavid du Colombier 
10759cc4ca5SDavid du Colombier 	/* copy translated name into input record */
10859cc4ca5SDavid du Colombier 	memmove(in->uname, t.suid, sizeof(in->uname));
10959cc4ca5SDavid du Colombier 
11059cc4ca5SDavid du Colombier 	/* craft a reply */
11159cc4ca5SDavid du Colombier 	a.num = AuthAs;
11259cc4ca5SDavid du Colombier 	memmove(a.chal, cp->rchal, CHALLEN);
11359cc4ca5SDavid du Colombier 	convA2M(&a, ou->rauth, t.key);
11459cc4ca5SDavid du Colombier 
1159a747e4fSDavid du Colombier 	cp->authed = 1;
11659cc4ca5SDavid du Colombier 	return 1;
11759cc4ca5SDavid du Colombier }
118