/*
* Network listening authentication.
* This and all the other network-related
* code is due to Richard Miller.
*/
#include "all.h"
#include "9p1.h"
int allownone;
Nvrsafe nvr;
int didread;
/*
* create a challenge for a fid space
*/
void
mkchallenge(Chan *cp)
{
int i;
if(!didread && readnvram(&nvr, 0) >= 0)
didread = 1;
srand(truerand());
for(i = 0; i < CHALLEN; i++)
cp->chal[i] = nrand(256);
cp->idoffset = 0;
cp->idvec = 0;
}
/*
* match a challenge from an attach
*/
Nvrsafe nvr;
int
authorize(Chan *cp, Oldfcall *in, Oldfcall *ou)
{
Ticket t;
Authenticator a;
int x;
ulong bit;
if (cp == cons.srvchan) /* local channel already safe */
return 1;
if(wstatallow) /* set to allow entry during boot */
return 1;
if(strcmp(in->uname, "none") == 0)
return allownone || cp->authed;
if(in->type == Toattach9p1)
return 0;
if(!didread)
return 0;
/* decrypt and unpack ticket */
convM2T(in->ticket, &t, nvr.machkey);
if(t.num != AuthTs){
print("bad AuthTs num\n");
return 0;
}
/* decrypt and unpack authenticator */
convM2A(in->auth, &a, t.key);
if(a.num != AuthAc){
print("bad AuthAc num\n");
return 0;
}
/* challenges must match */
if(memcmp(a.chal, cp->chal, sizeof(a.chal)) != 0){
print("bad challenge\n");
return 0;
}
/*
* the id must be in a valid range. the range is specified by a
* lower bount (idoffset) and a bit vector (idvec) where a
* bit set to 1 means unusable
*/
lock(&cp->idlock);
x = a.id - cp->idoffset;
bit = 1<<x;
if(x < 0 || x > 31 || (bit&cp->idvec)){
unlock(&cp->idlock);
return 0;
}
cp->idvec |= bit;
/* normalize the vector */
while(cp->idvec&0xffff0001){
cp->idvec >>= 1;
cp->idoffset++;
}
unlock(&cp->idlock);
/* ticket name and attach name must match */
if(memcmp(in->uname, t.cuid, sizeof(in->uname)) != 0){
print("names don't match\n");
return 0;
}
/* copy translated name into input record */
memmove(in->uname, t.suid, sizeof(in->uname));
/* craft a reply */
a.num = AuthAs;
memmove(a.chal, cp->rchal, CHALLEN);
convA2M(&a, ou->rauth, t.key);
cp->authed = 1;
return 1;
}
|