Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * 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;
}