tthese do work - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 4180d05ba41196e0633252de26750bb19f3a6da8
 (DIR) parent be8b315d1522fa1c109a49435c1638bafd838b91
 (HTM) Author: rsc <devnull@localhost>
       Date:   Thu, 17 Jun 2004 03:28:08 +0000
       
       tthese do work
       
       Diffstat:
         A src/libauthsrv/_asgetticket.c       |      16 ++++++++++++++++
         A src/libauthsrv/_asrdresp.c          |      56 +++++++++++++++++++++++++++++++
         A src/libauthsrv/authdial.c           |      31 +++++++++++++++++++++++++++++++
         A src/libauthsrv/convA2M.c            |      25 +++++++++++++++++++++++++
         A src/libauthsrv/convM2A.c            |      23 +++++++++++++++++++++++
         A src/libauthsrv/convM2PR.c           |      28 ++++++++++++++++++++++++++++
         A src/libauthsrv/convM2T.c            |      28 ++++++++++++++++++++++++++++
         A src/libauthsrv/convM2TR.c           |      28 ++++++++++++++++++++++++++++
         A src/libauthsrv/convPR2M.c           |      28 ++++++++++++++++++++++++++++
         A src/libauthsrv/convT2M.c            |      27 +++++++++++++++++++++++++++
         A src/libauthsrv/convTR2M.c           |      27 +++++++++++++++++++++++++++
         A src/libauthsrv/mkfile               |      25 +++++++++++++++++++++++++
         A src/libauthsrv/nvcsum.c             |      16 ++++++++++++++++
         A src/libauthsrv/opasstokey.c         |      29 +++++++++++++++++++++++++++++
         A src/libauthsrv/passtokey.c          |      33 +++++++++++++++++++++++++++++++
         A src/libauthsrv/readnvram.c          |     370 ++++++++++++++++++++++++++++++
       
       16 files changed, 790 insertions(+), 0 deletions(-)
       ---
 (DIR) diff --git a/src/libauthsrv/_asgetticket.c b/src/libauthsrv/_asgetticket.c
       t@@ -0,0 +1,16 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <authsrv.h>
       +
       +static char *pbmsg = "AS protocol botch";
       +
       +int
       +_asgetticket(int fd, char *trbuf, char *tbuf)
       +{
       +        if(write(fd, trbuf, TICKREQLEN) < 0){
       +                close(fd);
       +                werrstr(pbmsg);
       +                return -1;
       +        }
       +        return _asrdresp(fd, tbuf, 2*TICKETLEN);
       +}
 (DIR) diff --git a/src/libauthsrv/_asrdresp.c b/src/libauthsrv/_asrdresp.c
       t@@ -0,0 +1,56 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <authsrv.h>
       +
       +static char *pbmsg = "AS protocol botch";
       +
       +int
       +_asrdresp(int fd, char *buf, int len)
       +{
       +        int n;
       +        char error[64];
       +
       +        if(read(fd, buf, 1) != 1){
       +                werrstr(pbmsg);
       +                return -1;
       +        }
       +
       +        n = len;
       +        switch(buf[0]){
       +        case AuthOK:
       +                if(readn(fd, buf, len) != len){
       +                        werrstr(pbmsg);
       +                        return -1;
       +                }
       +                break;
       +        case AuthErr:
       +                if(readn(fd, error, sizeof error) != sizeof error){
       +                        werrstr(pbmsg);
       +                        return -1;
       +                }
       +                error[sizeof error-1] = '\0';
       +                werrstr("remote: %s", error);
       +                return -1;
       +        case AuthOKvar:
       +                if(readn(fd, error, 5) != 5){
       +                        werrstr(pbmsg);
       +                        return -1;
       +                }
       +                error[5] = 0;
       +                n = atoi(error);
       +                if(n <= 0 || n > len){
       +                        werrstr(pbmsg);
       +                        return -1;
       +                }
       +                memset(buf, 0, len);
       +                if(readn(fd, buf, n) != n){
       +                        werrstr(pbmsg);
       +                        return -1;
       +                }
       +                break;
       +        default:
       +                werrstr(pbmsg);
       +                return -1;
       +        }
       +        return n;
       +}
 (DIR) diff --git a/src/libauthsrv/authdial.c b/src/libauthsrv/authdial.c
       t@@ -0,0 +1,31 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <authsrv.h>
       +#include <bio.h>
       +#include <ndb.h>
       +
       +int
       +authdial(char *netroot, char *dom)
       +{
       +        char *p;
       +        int rv;
       +        
       +        if(dom != nil){
       +                /* look up an auth server in an authentication domain */
       +                p = csgetvalue(netroot, "authdom", dom, "auth", nil);
       +
       +                /* if that didn't work, just try the IP domain */
       +                if(p == nil)
       +                        p = csgetvalue(netroot, "dom", dom, "auth", nil);
       +                if(p == nil){
       +                        werrstr("no auth server found for %s", dom);
       +                        return -1;
       +                }
       +                rv = dial(netmkaddr(p, netroot, "ticket"), 0, 0, 0);
       +                free(p);
       +                return rv;
       +        } else {
       +                /* look for one relative to my machine */
       +                return dial(netmkaddr("$auth", netroot, "ticket"), 0, 0, 0);
       +        }
       +}
 (DIR) diff --git a/src/libauthsrv/convA2M.c b/src/libauthsrv/convA2M.c
       t@@ -0,0 +1,25 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <authsrv.h>
       +
       +#define        CHAR(x)                *p++ = f->x
       +#define        SHORT(x)        p[0] = f->x; p[1] = f->x>>8; p += 2
       +#define        VLONG(q)        p[0] = (q); p[1] = (q)>>8; p[2] = (q)>>16; p[3] = (q)>>24; p += 4
       +#define        LONG(x)                VLONG(f->x)
       +#define        STRING(x,n)        memmove(p, f->x, n); p += n
       +
       +int
       +convA2M(Authenticator *f, char *ap, char *key)
       +{
       +        int n;
       +        uchar *p;
       +
       +        p = (uchar*)ap;
       +        CHAR(num);
       +        STRING(chal, CHALLEN);
       +        LONG(id);
       +        n = p - (uchar*)ap;
       +        if(key)
       +                encrypt(key, ap, n);
       +        return n;
       +}
 (DIR) diff --git a/src/libauthsrv/convM2A.c b/src/libauthsrv/convM2A.c
       t@@ -0,0 +1,23 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <authsrv.h>
       +
       +#define        CHAR(x)                f->x = *p++
       +#define        SHORT(x)        f->x = (p[0] | (p[1]<<8)); p += 2
       +#define        VLONG(q)        q = (p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24)); p += 4
       +#define        LONG(x)                VLONG(f->x)
       +#define        STRING(x,n)        memmove(f->x, p, n); p += n
       +
       +void
       +convM2A(char *ap, Authenticator *f, char *key)
       +{
       +        uchar *p;
       +
       +        if(key)
       +                decrypt(key, ap, AUTHENTLEN);
       +        p = (uchar*)ap;
       +        CHAR(num);
       +        STRING(chal, CHALLEN);
       +        LONG(id);
       +        USED(p);
       +}
 (DIR) diff --git a/src/libauthsrv/convM2PR.c b/src/libauthsrv/convM2PR.c
       t@@ -0,0 +1,28 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <authsrv.h>
       +
       +#define        CHAR(x)                f->x = *p++
       +#define        SHORT(x)        f->x = (p[0] | (p[1]<<8)); p += 2
       +#define        VLONG(q)        q = (p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24)); p += 4
       +#define        LONG(x)                VLONG(f->x)
       +#define        STRING(x,n)        memmove(f->x, p, n); p += n
       +
       +void
       +convM2PR(char *ap, Passwordreq *f, char *key)
       +{
       +        uchar *p;
       +
       +        p = (uchar*)ap;
       +        if(key)
       +                decrypt(key, ap, PASSREQLEN);
       +        CHAR(num);
       +        STRING(old, ANAMELEN);
       +        f->old[ANAMELEN-1] = 0;
       +        STRING(new, ANAMELEN);
       +        f->new[ANAMELEN-1] = 0;
       +        CHAR(changesecret);
       +        STRING(secret, SECRETLEN);
       +        f->secret[SECRETLEN-1] = 0;
       +        USED(p);
       +}
 (DIR) diff --git a/src/libauthsrv/convM2T.c b/src/libauthsrv/convM2T.c
       t@@ -0,0 +1,28 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <authsrv.h>
       +
       +#define        CHAR(x)                f->x = *p++
       +#define        SHORT(x)        f->x = (p[0] | (p[1]<<8)); p += 2
       +#define        VLONG(q)        q = (p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24)); p += 4
       +#define        LONG(x)                VLONG(f->x)
       +#define        STRING(x,n)        memmove(f->x, p, n); p += n
       +
       +void
       +convM2T(char *ap, Ticket *f, char *key)
       +{
       +        uchar *p;
       +
       +        if(key)
       +                decrypt(key, ap, TICKETLEN);
       +        p = (uchar*)ap;
       +        CHAR(num);
       +        STRING(chal, CHALLEN);
       +        STRING(cuid, ANAMELEN);
       +        f->cuid[ANAMELEN-1] = 0;
       +        STRING(suid, ANAMELEN);
       +        f->suid[ANAMELEN-1] = 0;
       +        STRING(key, DESKEYLEN);
       +        USED(p);
       +}
       +
 (DIR) diff --git a/src/libauthsrv/convM2TR.c b/src/libauthsrv/convM2TR.c
       t@@ -0,0 +1,28 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <authsrv.h>
       +
       +#define        CHAR(x)                f->x = *p++
       +#define        SHORT(x)        f->x = (p[0] | (p[1]<<8)); p += 2
       +#define        VLONG(q)        q = (p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24)); p += 4
       +#define        LONG(x)                VLONG(f->x)
       +#define        STRING(x,n)        memmove(f->x, p, n); p += n
       +
       +void
       +convM2TR(char *ap, Ticketreq *f)
       +{
       +        uchar *p;
       +
       +        p = (uchar*)ap;
       +        CHAR(type);
       +        STRING(authid, ANAMELEN);
       +        f->authid[ANAMELEN-1] = 0;
       +        STRING(authdom, DOMLEN);
       +        f->authdom[DOMLEN-1] = 0;
       +        STRING(chal, CHALLEN);
       +        STRING(hostid, ANAMELEN);
       +        f->hostid[ANAMELEN-1] = 0;
       +        STRING(uid, ANAMELEN);
       +        f->uid[ANAMELEN-1] = 0;
       +        USED(p);
       +}
 (DIR) diff --git a/src/libauthsrv/convPR2M.c b/src/libauthsrv/convPR2M.c
       t@@ -0,0 +1,28 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <authsrv.h>
       +
       +#define        CHAR(x)                *p++ = f->x
       +#define        SHORT(x)        p[0] = f->x; p[1] = f->x>>8; p += 2
       +#define        VLONG(q)        p[0] = (q); p[1] = (q)>>8; p[2] = (q)>>16; p[3] = (q)>>24; p += 4
       +#define        LONG(x)                VLONG(f->x)
       +#define        STRING(x,n)        memmove(p, f->x, n); p += n
       +
       +int
       +convPR2M(Passwordreq *f, char *ap, char *key)
       +{
       +        int n;
       +        uchar *p;
       +
       +        p = (uchar*)ap;
       +        CHAR(num);
       +        STRING(old, ANAMELEN);
       +        STRING(new, ANAMELEN);
       +        CHAR(changesecret);
       +        STRING(secret, SECRETLEN);
       +        n = p - (uchar*)ap;
       +        if(key)
       +                encrypt(key, ap, n);
       +        return n;
       +}
       +
 (DIR) diff --git a/src/libauthsrv/convT2M.c b/src/libauthsrv/convT2M.c
       t@@ -0,0 +1,27 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <authsrv.h>
       +
       +#define        CHAR(x)                *p++ = f->x
       +#define        SHORT(x)        p[0] = f->x; p[1] = f->x>>8; p += 2
       +#define        VLONG(q)        p[0] = (q); p[1] = (q)>>8; p[2] = (q)>>16; p[3] = (q)>>24; p += 4
       +#define        LONG(x)                VLONG(f->x)
       +#define        STRING(x,n)        memmove(p, f->x, n); p += n
       +
       +int
       +convT2M(Ticket *f, char *ap, char *key)
       +{
       +        int n;
       +        uchar *p;
       +
       +        p = (uchar*)ap;
       +        CHAR(num);
       +        STRING(chal, CHALLEN);
       +        STRING(cuid, ANAMELEN);
       +        STRING(suid, ANAMELEN);
       +        STRING(key, DESKEYLEN);
       +        n = p - (uchar*)ap;
       +        if(key)
       +                encrypt(key, ap, n);
       +        return n;
       +}
 (DIR) diff --git a/src/libauthsrv/convTR2M.c b/src/libauthsrv/convTR2M.c
       t@@ -0,0 +1,27 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <authsrv.h>
       +
       +#define        CHAR(x)                *p++ = f->x
       +#define        SHORT(x)        p[0] = f->x; p[1] = f->x>>8; p += 2
       +#define        VLONG(q)        p[0] = (q); p[1] = (q)>>8; p[2] = (q)>>16; p[3] = (q)>>24; p += 4
       +#define        LONG(x)                VLONG(f->x)
       +#define        STRING(x,n)        memmove(p, f->x, n); p += n
       +
       +int
       +convTR2M(Ticketreq *f, char *ap)
       +{
       +        int n;
       +        uchar *p;
       +
       +        p = (uchar*)ap;
       +        CHAR(type);
       +        STRING(authid, 28);        /* BUG */
       +        STRING(authdom, DOMLEN);
       +        STRING(chal, CHALLEN);
       +        STRING(hostid, 28);        /* BUG */
       +        STRING(uid, 28);        /* BUG */
       +        n = p - (uchar*)ap;
       +        return n;
       +}
       +
 (DIR) diff --git a/src/libauthsrv/mkfile b/src/libauthsrv/mkfile
       t@@ -0,0 +1,25 @@
       +PLAN9=../..
       +<$PLAN9/src/mkhdr
       +
       +LIB=libauthsrv.a
       +OFILES=\
       +        _asgetticket.$O\
       +        _asrdresp.$O\
       +#        authdial.$O\
       +        convA2M.$O\
       +        convM2A.$O\
       +        convM2PR.$O\
       +        convM2T.$O\
       +        convM2TR.$O\
       +        convPR2M.$O\
       +        convT2M.$O\
       +        convTR2M.$O\
       +        nvcsum.$O\
       +        opasstokey.$O\
       +        passtokey.$O\
       +        readnvram.$O\
       +
       +HFILES=\
       +        $PLAN9/include/authsrv.h\
       +
       +<$PLAN9/src/mksyslib
 (DIR) diff --git a/src/libauthsrv/nvcsum.c b/src/libauthsrv/nvcsum.c
       t@@ -0,0 +1,16 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <auth.h>
       +
       +uchar
       +nvcsum(void *vmem, int n)
       +{
       +        uchar *mem, sum;
       +        int i;
       +
       +        sum = 9;
       +        mem = vmem;
       +        for(i = 0; i < n; i++)
       +                sum += mem[i];
       +        return sum;
       +}
 (DIR) diff --git a/src/libauthsrv/opasstokey.c b/src/libauthsrv/opasstokey.c
       t@@ -0,0 +1,29 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <authsrv.h>
       +
       +int
       +opasstokey(char *key, char *p)
       +{
       +        uchar t[10];
       +        int c, n;
       +
       +        n = strlen(p);
       +        memset(t, ' ', sizeof t);
       +        if(n < 5)
       +                return 0;
       +        if(n > 10)
       +                n = 10;
       +        strncpy((char*)t, p, n);
       +        if(n >= 9){
       +                c = p[8] & 0xf;
       +                if(n == 10)
       +                        c += p[9] << 4;
       +                for(n = 0; n < 8; n++)
       +                        if(c & (1 << n))
       +                                t[n] -= ' ';
       +        }
       +        for(n = 0; n < 7; n++)
       +                key[n] = (t[n] >> n) + (t[n+1] << (8 - (n+1)));
       +        return 1;
       +}
 (DIR) diff --git a/src/libauthsrv/passtokey.c b/src/libauthsrv/passtokey.c
       t@@ -0,0 +1,33 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <authsrv.h>
       +
       +int
       +passtokey(char *key, char *p)
       +{
       +        uchar buf[ANAMELEN], *t;
       +        int i, n;
       +
       +        n = strlen(p);
       +        if(n >= ANAMELEN)
       +                n = ANAMELEN-1;
       +        memset(buf, ' ', 8);
       +        t = buf;
       +        strncpy((char*)t, p, n);
       +        t[n] = 0;
       +        memset(key, 0, DESKEYLEN);
       +        for(;;){
       +                for(i = 0; i < DESKEYLEN; i++)
       +                        key[i] = (t[i] >> i) + (t[i+1] << (8 - (i+1)));
       +                if(n <= 8)
       +                        return 1;
       +                n -= 8;
       +                t += 8;
       +                if(n < 8){
       +                        t -= 8 - n;
       +                        n = 8;
       +                }
       +                encrypt(key, t, 8);
       +        }
       +        return 1;        /* not reached */
       +}
 (DIR) diff --git a/src/libauthsrv/readnvram.c b/src/libauthsrv/readnvram.c
       t@@ -0,0 +1,370 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <authsrv.h>
       +
       +static long        finddosfile(int, char*);
       +
       +static int
       +check(void *x, int len, uchar sum, char *msg)
       +{
       +        if(nvcsum(x, len) == sum)
       +                return 0;
       +        memset(x, 0, len);
       +        fprint(2, "%s\n", msg);
       +        return 1;
       +}
       +
       +/*
       + *  get key info out of nvram.  since there isn't room in the PC's nvram use
       + *  a disk partition there.
       + */
       +static struct {
       +        char *cputype;
       +        char *file;
       +        int off;
       +        int len;
       +} nvtab[] = {
       +        "sparc", "#r/nvram", 1024+850, sizeof(Nvrsafe),
       +        "pc", "#S/sdC0/nvram", 0, sizeof(Nvrsafe),
       +        "pc", "#S/sdC0/9fat", -1, sizeof(Nvrsafe),
       +        "pc", "#S/sdC1/nvram", 0, sizeof(Nvrsafe),
       +        "pc", "#S/sdC1/9fat", -1, sizeof(Nvrsafe),
       +        "pc", "#S/sd00/nvram", 0, sizeof(Nvrsafe),
       +        "pc", "#S/sd00/9fat", -1, sizeof(Nvrsafe),
       +        "pc", "#S/sd01/nvram", 0, sizeof(Nvrsafe),
       +        "pc", "#S/sd01/9fat", -1, sizeof(Nvrsafe),
       +        "pc", "#f/fd0disk", -1, 512,        /* 512: #f requires whole sector reads */
       +        "pc", "#f/fd1disk", -1, 512,
       +        "mips", "#r/nvram", 1024+900, sizeof(Nvrsafe),
       +        "power", "#F/flash/flash0", 0x440000, sizeof(Nvrsafe),
       +        "power", "#r/nvram", 4352, sizeof(Nvrsafe),        /* OK for MTX-604e */
       +        "debug", "/tmp/nvram", 0, sizeof(Nvrsafe),
       +};
       +
       +static char*
       +readcons(char *prompt, char *def, int raw, char *buf, int nbuf)
       +{
       +        int fdin, fdout, ctl, n, m;
       +        char line[10];
       +
       +        fdin = open("/dev/cons", OREAD);
       +        if(fdin < 0)
       +                fdin = 0;
       +        fdout = open("/dev/cons", OWRITE);
       +        if(fdout < 0)
       +                fdout = 1;
       +        if(def != nil)
       +                fprint(fdout, "%s[%s]: ", prompt, def);
       +        else
       +                fprint(fdout, "%s: ", prompt);
       +        if(raw){
       +                ctl = open("/dev/consctl", OWRITE);
       +                if(ctl >= 0)
       +                        write(ctl, "rawon", 5);
       +        } else
       +                ctl = -1;
       +
       +        m = 0;
       +        for(;;){
       +                n = read(fdin, line, 1);
       +                if(n == 0){
       +                        close(ctl);
       +                        werrstr("readcons: EOF");
       +                        return nil;
       +                }
       +                if(n < 0){
       +                        close(ctl);
       +                        werrstr("can't read cons");
       +                        return nil;
       +                }
       +                if(line[0] == 0x7f)
       +                        exits(0);
       +                if(n == 0 || line[0] == '\n' || line[0] == '\r'){
       +                        if(raw){
       +                                write(ctl, "rawoff", 6);
       +                                write(fdout, "\n", 1);
       +                                close(ctl);
       +                        }
       +                        buf[m] = '\0';
       +                        if(buf[0]=='\0' && def)
       +                                strcpy(buf, def);
       +                        return buf;
       +                }
       +                if(line[0] == '\b'){
       +                        if(m > 0)
       +                                m--;
       +                }else if(line[0] == 0x15){        /* ^U: line kill */
       +                        m = 0;
       +                        if(def != nil)
       +                                fprint(fdout, "%s[%s]: ", prompt, def);
       +                        else
       +                                fprint(fdout, "%s: ", prompt);
       +                }else{
       +                        if(m >= nbuf-1){
       +                                fprint(fdout, "line too long\n");
       +                                m = 0;
       +                                if(def != nil)
       +                                        fprint(fdout, "%s[%s]: ", prompt, def);
       +                                else
       +                                        fprint(fdout, "%s: ", prompt);
       +                        }else
       +                                buf[m++] = line[0];
       +                }
       +        }
       +        return buf;        /* how does this happen */
       +}
       +
       +
       +/*
       + *  get key info out of nvram.  since there isn't room in the PC's nvram use
       + *  a disk partition there.
       + */
       +int
       +readnvram(Nvrsafe *safep, int flag)
       +{
       +        char buf[1024], in[128], *cputype, *nvrfile, *nvrlen, *nvroff, *v[2];
       +        int fd, err, i, safeoff, safelen;
       +        Nvrsafe *safe;
       +
       +        err = 0;
       +        memset(safep, 0, sizeof(*safep));
       +
       +        nvrfile = getenv("nvram");
       +        cputype = getenv("cputype");
       +        if(cputype == nil)
       +                cputype = "mips";
       +        if(strcmp(cputype, "386")==0 || strcmp(cputype, "alpha")==0)
       +                cputype = "pc";
       +
       +        safe = (Nvrsafe*)buf;
       +
       +        fd = -1;
       +        safeoff = -1;
       +        safelen = -1;
       +        if(nvrfile != nil){
       +                /* accept device and device!file */
       +                i = gettokens(nvrfile, v, nelem(v), "!");
       +                fd = open(v[0], ORDWR);
       +                safelen = sizeof(Nvrsafe);
       +                if(strstr(v[0], "/9fat") == nil)
       +                        safeoff = 0;
       +                nvrlen = getenv("nvrlen");
       +                if(nvrlen != nil)
       +                        safelen = atoi(nvrlen);
       +                nvroff = getenv("nvroff");
       +                if(nvroff != nil){
       +                        if(strcmp(nvroff, "dos") == 0)
       +                                safeoff = -1;
       +                        else
       +                                safeoff = atoi(nvroff);
       +                }
       +                if(safeoff < 0 && fd >= 0){
       +                        safelen = 512;
       +                        safeoff = finddosfile(fd, i == 2 ? v[1] : "plan9.nvr");
       +                        if(safeoff < 0){
       +                                close(fd);
       +                                fd = -1;
       +                        }
       +                }
       +                free(nvrfile);
       +                if(nvrlen != nil)
       +                        free(nvrlen);
       +                if(nvroff != nil)
       +                        free(nvroff);
       +        }else{
       +                for(i=0; i<nelem(nvtab); i++){
       +                        if(strcmp(cputype, nvtab[i].cputype) != 0)
       +                                continue;
       +                        if((fd = open(nvtab[i].file, ORDWR)) < 0)
       +                                continue;
       +                        safeoff = nvtab[i].off;
       +                        safelen = nvtab[i].len;
       +                        if(safeoff == -1){
       +                                safeoff = finddosfile(fd, "plan9.nvr");
       +                                if(safeoff < 0){
       +                                        close(fd);
       +                                        fd = -1;
       +                                        continue;
       +                                }
       +                        }
       +                        break;
       +                }
       +        }
       +
       +        if(fd < 0
       +        || seek(fd, safeoff, 0) < 0
       +        || read(fd, buf, safelen) != safelen){
       +                err = 1;
       +                if(flag&(NVwrite|NVwriteonerr))
       +                        fprint(2, "can't read nvram: %r\n");
       +                memset(safep, 0, sizeof(*safep));
       +                safe = safep;
       +        }else{
       +                *safep = *safe;
       +                safe = safep;
       +
       +                err |= check(safe->machkey, DESKEYLEN, safe->machsum, "bad nvram key");
       +//                err |= check(safe->config, CONFIGLEN, safe->configsum, "bad secstore key");
       +                err |= check(safe->authid, ANAMELEN, safe->authidsum, "bad authentication id");
       +                err |= check(safe->authdom, DOMLEN, safe->authdomsum, "bad authentication domain");
       +        }
       +
       +        if((flag&NVwrite) || (err && (flag&NVwriteonerr))){
       +                readcons("authid", nil, 0, safe->authid, sizeof(safe->authid));
       +                readcons("authdom", nil, 0, safe->authdom, sizeof(safe->authdom));
       +                readcons("secstore key", nil, 1, safe->config, sizeof(safe->config));
       +                for(;;){
       +                        if(readcons("password", nil, 1, in, sizeof in) == nil)
       +                                goto Out;
       +                        if(passtokey(safe->machkey, in))
       +                                break;
       +                }
       +                safe->machsum = nvcsum(safe->machkey, DESKEYLEN);
       +                safe->configsum = nvcsum(safe->config, CONFIGLEN);
       +                safe->authidsum = nvcsum(safe->authid, sizeof(safe->authid));
       +                safe->authdomsum = nvcsum(safe->authdom, sizeof(safe->authdom));
       +                *(Nvrsafe*)buf = *safe;
       +                if(seek(fd, safeoff, 0) < 0
       +                || write(fd, buf, safelen) != safelen){
       +                        fprint(2, "can't write key to nvram: %r\n");
       +                        err = 1;
       +                }else
       +                        err = 0;
       +        }
       +Out:
       +        close(fd);
       +        return err ? -1 : 0;
       +}
       +
       +typedef struct Dosboot        Dosboot;
       +struct Dosboot{
       +        uchar        magic[3];        /* really an xx86 JMP instruction */
       +        uchar        version[8];
       +        uchar        sectsize[2];
       +        uchar        clustsize;
       +        uchar        nresrv[2];
       +        uchar        nfats;
       +        uchar        rootsize[2];
       +        uchar        volsize[2];
       +        uchar        mediadesc;
       +        uchar        fatsize[2];
       +        uchar        trksize[2];
       +        uchar        nheads[2];
       +        uchar        nhidden[4];
       +        uchar        bigvolsize[4];
       +        uchar        driveno;
       +        uchar        reserved0;
       +        uchar        bootsig;
       +        uchar        volid[4];
       +        uchar        label[11];
       +        uchar        type[8];
       +};
       +#define        GETSHORT(p) (((p)[1]<<8) | (p)[0])
       +#define        GETLONG(p) ((GETSHORT((p)+2) << 16) | GETSHORT((p)))
       +
       +typedef struct Dosdir        Dosdir;
       +struct Dosdir
       +{
       +        char        name[8];
       +        char        ext[3];
       +        uchar        attr;
       +        uchar        reserved[10];
       +        uchar        time[2];
       +        uchar        date[2];
       +        uchar        start[2];
       +        uchar        length[4];
       +};
       +
       +static char*
       +dosparse(char *from, char *to, int len)
       +{
       +        char c;
       +
       +        memset(to, ' ', len);
       +        if(from == 0)
       +                return 0;
       +        while(len-- > 0){
       +                c = *from++;
       +                if(c == '.')
       +                        return from;
       +                if(c == 0)
       +                        break;
       +                if(c >= 'a' && c <= 'z')
       +                        *to++ = c + 'A' - 'a';
       +                else
       +                        *to++ = c;
       +        }
       +        return 0;
       +}
       +
       +/*
       + *  return offset of first file block
       + *
       + *  This is a very simplistic dos file system.  It only
       + *  works on floppies, only looks in the root, and only
       + *  returns a pointer to the first block of a file.
       + *
       + *  This exists for cpu servers that have no hard disk
       + *  or nvram to store the key on.
       + *
       + *  Please don't make this any smarter: it stays resident
       + *  and I'ld prefer not to waste the space on something that
       + *  runs only at boottime -- presotto.
       + */
       +static long
       +finddosfile(int fd, char *file)
       +{
       +        uchar secbuf[512];
       +        char name[8];
       +        char ext[3];
       +        Dosboot        *b;
       +        Dosdir *root, *dp;
       +        int nroot, sectsize, rootoff, rootsects, n;
       +
       +        /* dos'ize file name */
       +        file = dosparse(file, name, 8);
       +        dosparse(file, ext, 3);
       +
       +        /* read boot block, check for sanity */
       +        b = (Dosboot*)secbuf;
       +        if(read(fd, secbuf, sizeof(secbuf)) != sizeof(secbuf))
       +                return -1;
       +        if(b->magic[0] != 0xEB || b->magic[1] != 0x3C || b->magic[2] != 0x90)
       +                return -1;
       +        sectsize = GETSHORT(b->sectsize);
       +        if(sectsize != 512)
       +                return -1;
       +        rootoff = (GETSHORT(b->nresrv) + b->nfats*GETSHORT(b->fatsize)) * sectsize;
       +        if(seek(fd, rootoff, 0) < 0)
       +                return -1;
       +        nroot = GETSHORT(b->rootsize);
       +        rootsects = (nroot*sizeof(Dosdir)+sectsize-1)/sectsize;
       +        if(rootsects <= 0 || rootsects > 64)
       +                return -1;
       +
       +        /* 
       +         *  read root. it is contiguous to make stuff like
       +         *  this easier
       +         */
       +        root = malloc(rootsects*sectsize);
       +        if(read(fd, root, rootsects*sectsize) != rootsects*sectsize)
       +                return -1;
       +        n = -1;
       +        for(dp = root; dp < &root[nroot]; dp++)
       +                if(memcmp(name, dp->name, 8) == 0 && memcmp(ext, dp->ext, 3) == 0){
       +                        n = GETSHORT(dp->start);
       +                        break;
       +                }
       +        free(root);
       +
       +        if(n < 0)
       +                return -1;
       +
       +        /*
       +         *  dp->start is in cluster units, not sectors.  The first
       +         *  cluster is cluster 2 which starts immediately after the
       +         *  root directory
       +         */
       +        return rootoff + rootsects*sectsize + (n-2)*sectsize*b->clustsize;
       +}
       +