aboutsummaryrefslogtreecommitdiff
path: root/src/libauthsrv
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2004-06-17 03:28:08 +0000
committerrsc <devnull@localhost>2004-06-17 03:28:08 +0000
commit4180d05ba41196e0633252de26750bb19f3a6da8 (patch)
treedb31b1dd561963f8e4b922d63573d971757ec122 /src/libauthsrv
parentbe8b315d1522fa1c109a49435c1638bafd838b91 (diff)
downloadplan9port-4180d05ba41196e0633252de26750bb19f3a6da8.tar.gz
plan9port-4180d05ba41196e0633252de26750bb19f3a6da8.tar.bz2
plan9port-4180d05ba41196e0633252de26750bb19f3a6da8.zip
these do work
Diffstat (limited to 'src/libauthsrv')
-rw-r--r--src/libauthsrv/_asgetticket.c16
-rw-r--r--src/libauthsrv/_asrdresp.c56
-rw-r--r--src/libauthsrv/authdial.c31
-rw-r--r--src/libauthsrv/convA2M.c25
-rw-r--r--src/libauthsrv/convM2A.c23
-rw-r--r--src/libauthsrv/convM2PR.c28
-rw-r--r--src/libauthsrv/convM2T.c28
-rw-r--r--src/libauthsrv/convM2TR.c28
-rw-r--r--src/libauthsrv/convPR2M.c28
-rw-r--r--src/libauthsrv/convT2M.c27
-rw-r--r--src/libauthsrv/convTR2M.c27
-rw-r--r--src/libauthsrv/mkfile25
-rw-r--r--src/libauthsrv/nvcsum.c16
-rw-r--r--src/libauthsrv/opasstokey.c29
-rw-r--r--src/libauthsrv/passtokey.c33
-rw-r--r--src/libauthsrv/readnvram.c370
16 files changed, 790 insertions, 0 deletions
diff --git a/src/libauthsrv/_asgetticket.c b/src/libauthsrv/_asgetticket.c
new file mode 100644
index 00000000..ea9e0c9e
--- /dev/null
+++ b/src/libauthsrv/_asgetticket.c
@@ -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);
+}
diff --git a/src/libauthsrv/_asrdresp.c b/src/libauthsrv/_asrdresp.c
new file mode 100644
index 00000000..8a7daf8c
--- /dev/null
+++ b/src/libauthsrv/_asrdresp.c
@@ -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;
+}
diff --git a/src/libauthsrv/authdial.c b/src/libauthsrv/authdial.c
new file mode 100644
index 00000000..5e608058
--- /dev/null
+++ b/src/libauthsrv/authdial.c
@@ -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);
+ }
+}
diff --git a/src/libauthsrv/convA2M.c b/src/libauthsrv/convA2M.c
new file mode 100644
index 00000000..2799cbf5
--- /dev/null
+++ b/src/libauthsrv/convA2M.c
@@ -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;
+}
diff --git a/src/libauthsrv/convM2A.c b/src/libauthsrv/convM2A.c
new file mode 100644
index 00000000..3d58f9b5
--- /dev/null
+++ b/src/libauthsrv/convM2A.c
@@ -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);
+}
diff --git a/src/libauthsrv/convM2PR.c b/src/libauthsrv/convM2PR.c
new file mode 100644
index 00000000..21df5b50
--- /dev/null
+++ b/src/libauthsrv/convM2PR.c
@@ -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);
+}
diff --git a/src/libauthsrv/convM2T.c b/src/libauthsrv/convM2T.c
new file mode 100644
index 00000000..372825a8
--- /dev/null
+++ b/src/libauthsrv/convM2T.c
@@ -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);
+}
+
diff --git a/src/libauthsrv/convM2TR.c b/src/libauthsrv/convM2TR.c
new file mode 100644
index 00000000..ffad75c7
--- /dev/null
+++ b/src/libauthsrv/convM2TR.c
@@ -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);
+}
diff --git a/src/libauthsrv/convPR2M.c b/src/libauthsrv/convPR2M.c
new file mode 100644
index 00000000..8b2422f1
--- /dev/null
+++ b/src/libauthsrv/convPR2M.c
@@ -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;
+}
+
diff --git a/src/libauthsrv/convT2M.c b/src/libauthsrv/convT2M.c
new file mode 100644
index 00000000..810ba5c6
--- /dev/null
+++ b/src/libauthsrv/convT2M.c
@@ -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;
+}
diff --git a/src/libauthsrv/convTR2M.c b/src/libauthsrv/convTR2M.c
new file mode 100644
index 00000000..3a7610a7
--- /dev/null
+++ b/src/libauthsrv/convTR2M.c
@@ -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;
+}
+
diff --git a/src/libauthsrv/mkfile b/src/libauthsrv/mkfile
new file mode 100644
index 00000000..a69cc942
--- /dev/null
+++ b/src/libauthsrv/mkfile
@@ -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
diff --git a/src/libauthsrv/nvcsum.c b/src/libauthsrv/nvcsum.c
new file mode 100644
index 00000000..306d7f7e
--- /dev/null
+++ b/src/libauthsrv/nvcsum.c
@@ -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;
+}
diff --git a/src/libauthsrv/opasstokey.c b/src/libauthsrv/opasstokey.c
new file mode 100644
index 00000000..d263d4b7
--- /dev/null
+++ b/src/libauthsrv/opasstokey.c
@@ -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;
+}
diff --git a/src/libauthsrv/passtokey.c b/src/libauthsrv/passtokey.c
new file mode 100644
index 00000000..8e267ce4
--- /dev/null
+++ b/src/libauthsrv/passtokey.c
@@ -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 */
+}
diff --git a/src/libauthsrv/readnvram.c b/src/libauthsrv/readnvram.c
new file mode 100644
index 00000000..e48a5761
--- /dev/null
+++ b/src/libauthsrv/readnvram.c
@@ -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;
+}
+