summaryrefslogtreecommitdiff
path: root/sys/src/cmd/auth/lib
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/auth/lib
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/auth/lib')
-rwxr-xr-xsys/src/cmd/auth/lib/error.c20
-rwxr-xr-xsys/src/cmd/auth/lib/fs.c10
-rwxr-xr-xsys/src/cmd/auth/lib/getauthkey.c27
-rwxr-xr-xsys/src/cmd/auth/lib/getexpiration.c77
-rwxr-xr-xsys/src/cmd/auth/lib/keyfmt.c29
-rwxr-xr-xsys/src/cmd/auth/lib/log.c45
-rwxr-xr-xsys/src/cmd/auth/lib/mkfile30
-rwxr-xr-xsys/src/cmd/auth/lib/netcheck.c111
-rwxr-xr-xsys/src/cmd/auth/lib/okpasswd.c42
-rwxr-xr-xsys/src/cmd/auth/lib/querybio.c66
-rwxr-xr-xsys/src/cmd/auth/lib/rdbio.c58
-rwxr-xr-xsys/src/cmd/auth/lib/readarg.c23
-rwxr-xr-xsys/src/cmd/auth/lib/readln.c115
-rwxr-xr-xsys/src/cmd/auth/lib/readn.c20
-rwxr-xr-xsys/src/cmd/auth/lib/readwrite.c90
-rwxr-xr-xsys/src/cmd/auth/lib/wrbio.c40
16 files changed, 803 insertions, 0 deletions
diff --git a/sys/src/cmd/auth/lib/error.c b/sys/src/cmd/auth/lib/error.c
new file mode 100755
index 000000000..71bf63df1
--- /dev/null
+++ b/sys/src/cmd/auth/lib/error.c
@@ -0,0 +1,20 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "authcmdlib.h"
+
+void
+error(char *fmt, ...)
+{
+ char buf[8192], *s;
+ va_list arg;
+
+ s = buf;
+ s += sprint(s, "%s: ", argv0);
+ va_start(arg, fmt);
+ s = vseprint(s, buf + sizeof(buf), fmt, arg);
+ va_end(arg);
+ *s++ = '\n';
+ write(2, buf, s - buf);
+ exits(buf);
+}
diff --git a/sys/src/cmd/auth/lib/fs.c b/sys/src/cmd/auth/lib/fs.c
new file mode 100755
index 000000000..43f7db845
--- /dev/null
+++ b/sys/src/cmd/auth/lib/fs.c
@@ -0,0 +1,10 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "authcmdlib.h"
+
+Fs fs[3] =
+{
+[Plan9] { "/mnt/keys", "plan 9 key", "/adm/keys.who", 0 },
+[Securenet] { "/mnt/netkeys", "network access key", "/adm/netkeys.who", 0 },
+};
diff --git a/sys/src/cmd/auth/lib/getauthkey.c b/sys/src/cmd/auth/lib/getauthkey.c
new file mode 100755
index 000000000..1ae8d4e87
--- /dev/null
+++ b/sys/src/cmd/auth/lib/getauthkey.c
@@ -0,0 +1,27 @@
+#include <u.h>
+#include <libc.h>
+#include <authsrv.h>
+#include <bio.h>
+#include "authcmdlib.h"
+
+static int
+getkey(char *authkey)
+{
+ Nvrsafe safe;
+
+ if(readnvram(&safe, 0) < 0)
+ return -1;
+ memmove(authkey, safe.machkey, DESKEYLEN);
+ memset(&safe, 0, sizeof safe);
+ return 0;
+}
+
+int
+getauthkey(char *authkey)
+{
+ if(getkey(authkey) == 0)
+ return 1;
+ print("can't read NVRAM, please enter machine key\n");
+ getpass(authkey, nil, 0, 1);
+ return 1;
+}
diff --git a/sys/src/cmd/auth/lib/getexpiration.c b/sys/src/cmd/auth/lib/getexpiration.c
new file mode 100755
index 000000000..fb07d261e
--- /dev/null
+++ b/sys/src/cmd/auth/lib/getexpiration.c
@@ -0,0 +1,77 @@
+#include <u.h>
+#include <libc.h>
+#include <ctype.h>
+#include <bio.h>
+#include "authcmdlib.h"
+
+/*
+ * get the date in the format yyyymmdd
+ */
+Tm
+getdate(char *d)
+{
+ Tm date;
+ int i;
+
+ date.year = date.mon = date.mday = 0;
+ date.hour = date.min = date.sec = 0;
+ for(i = 0; i < 8; i++)
+ if(!isdigit(d[i]))
+ return date;
+ date.year = (d[0]-'0')*1000 + (d[1]-'0')*100 + (d[2]-'0')*10 + d[3]-'0';
+ date.year -= 1900;
+ d += 4;
+ date.mon = (d[0]-'0')*10 + d[1]-'0' - 1;
+ d += 2;
+ date.mday = (d[0]-'0')*10 + d[1]-'0';
+ date.yday = 0;
+ return date;
+}
+
+long
+getexpiration(char *db, char *u)
+{
+ char buf[Maxpath];
+ char prompt[128];
+ char cdate[32];
+ Tm date;
+ ulong secs, now;
+ int n, fd;
+
+ /* read current expiration (if any) */
+ snprint(buf, sizeof buf, "%s/%s/expire", db, u);
+ fd = open(buf, OREAD);
+ buf[0] = 0;
+ if(fd >= 0){
+ n = read(fd, buf, sizeof(buf)-1);
+ if(n > 0)
+ buf[n-1] = 0;
+ close(fd);
+ }
+
+ if(buf[0]){
+ if(strncmp(buf, "never", 5)){
+ secs = atoi(buf);
+ memmove(&date, localtime(secs), sizeof(date));
+ sprint(buf, "%4.4d%2.2d%2.2d", date.year+1900, date.mon+1, date.mday);
+ } else
+ buf[5] = 0;
+ } else
+ strcpy(buf, "never");
+ sprint(prompt, "Expiration date (YYYYMMDD or never)[return = %s]: ", buf);
+
+ now = time(0);
+ for(;;){
+ readln(prompt, cdate, sizeof cdate, 0);
+ if(*cdate == 0)
+ return -1;
+ if(strcmp(cdate, "never") == 0)
+ return 0;
+ date = getdate(cdate);
+ secs = tm2sec(&date);
+ if(secs > now && secs < now + 2*365*24*60*60)
+ break;
+ print("expiration time must fall between now and 2 years from now\n");
+ }
+ return secs;
+}
diff --git a/sys/src/cmd/auth/lib/keyfmt.c b/sys/src/cmd/auth/lib/keyfmt.c
new file mode 100755
index 000000000..86c2378a3
--- /dev/null
+++ b/sys/src/cmd/auth/lib/keyfmt.c
@@ -0,0 +1,29 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "authcmdlib.h"
+
+/*
+ * print a key in des standard form
+ */
+int
+keyfmt(Fmt *f)
+{
+ uchar key[8];
+ char buf[32];
+ uchar *k;
+ int i;
+
+ k = va_arg(f->args, uchar*);
+ key[0] = 0;
+ for(i = 0; i < 7; i++){
+ key[i] |= k[i] >> i;
+ key[i] &= ~1;
+ key[i+1] = k[i] << (7 - i);
+ }
+ key[7] &= ~1;
+ sprint(buf, "%.3uo %.3uo %.3uo %.3uo %.3uo %.3uo %.3uo %.3uo",
+ key[0], key[1], key[2], key[3], key[4], key[5], key[6], key[7]);
+ fmtstrcpy(f, buf);
+ return 0;
+}
diff --git a/sys/src/cmd/auth/lib/log.c b/sys/src/cmd/auth/lib/log.c
new file mode 100755
index 000000000..bd4eaf1a3
--- /dev/null
+++ b/sys/src/cmd/auth/lib/log.c
@@ -0,0 +1,45 @@
+#include <u.h>
+#include <libc.h>
+#include <authsrv.h>
+#include <bio.h>
+#include "authcmdlib.h"
+
+static void
+record(char *db, char *user, char *msg)
+{
+ char buf[Maxpath];
+ int fd;
+
+ snprint(buf, sizeof buf, "%s/%s/log", db, user);
+ fd = open(buf, OWRITE);
+ if(fd < 0)
+ return;
+ write(fd, msg, strlen(msg));
+ close(fd);
+ return;
+}
+
+void
+logfail(char *user)
+{
+ if(!user)
+ return;
+ record(KEYDB, user, "bad");
+ record(NETKEYDB, user, "bad");
+}
+
+void
+succeed(char *user)
+{
+ if(!user)
+ return;
+ record(KEYDB, user, "good");
+ record(NETKEYDB, user, "good");
+}
+
+void
+fail(char *user)
+{
+ logfail(user);
+ exits("failure");
+}
diff --git a/sys/src/cmd/auth/lib/mkfile b/sys/src/cmd/auth/lib/mkfile
new file mode 100755
index 000000000..9e54d35fc
--- /dev/null
+++ b/sys/src/cmd/auth/lib/mkfile
@@ -0,0 +1,30 @@
+</$objtype/mkfile
+
+
+LIB=../lib.$O.a
+OFILES=\
+ keyfmt.$O\
+ netcheck.$O\
+ okpasswd.$O\
+ readwrite.$O\
+ readarg.$O\
+ readln.$O\
+ getauthkey.$O\
+ log.$O\
+ error.$O\
+ fs.$O\
+ rdbio.$O\
+ querybio.$O\
+ wrbio.$O\
+ getexpiration.$O\
+
+
+HFILES=/sys/include/auth.h /sys/include/authsrv.h ../authcmdlib.h
+
+UPDATE=\
+ mkfile\
+ $HFILES\
+ ${OFILES:%.$O=%.c}\
+
+</sys/src/cmd/mksyslib
+CFLAGS=$CFLAGS -I..
diff --git a/sys/src/cmd/auth/lib/netcheck.c b/sys/src/cmd/auth/lib/netcheck.c
new file mode 100755
index 000000000..5e4220c25
--- /dev/null
+++ b/sys/src/cmd/auth/lib/netcheck.c
@@ -0,0 +1,111 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "authcmdlib.h"
+
+/*
+ * compute the key verification checksum
+ */
+void
+checksum(char key[], char csum[]) {
+ uchar buf[8];
+
+ memset(buf, 0, 8);
+ encrypt(key, buf, 8);
+ sprint(csum, "C %.2ux%.2ux%.2ux%.2ux", buf[0], buf[1], buf[2], buf[3]);
+}
+
+/*
+ * compute the proper response. We encrypt the ascii of
+ * challenge number, with trailing binary zero fill.
+ * This process was derived empirically.
+ * this was copied from inet's guard.
+ */
+char *
+netresp(char *key, long chal, char *answer)
+{
+ uchar buf[8];
+
+ memset(buf, 0, 8);
+ sprint((char *)buf, "%lud", chal);
+ if(encrypt(key, buf, 8) < 0)
+ error("can't encrypt response");
+ chal = (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+buf[3];
+ sprint(answer, "%.8lux", chal);
+
+ return answer;
+}
+
+char *
+netdecimal(char *answer)
+{
+ int i;
+
+ for(i = 0; answer[i]; i++)
+ switch(answer[i]){
+ case 'a': case 'b': case 'c':
+ answer[i] = '2';
+ break;
+ case 'd': case 'e': case 'f':
+ answer[i] = '3';
+ break;
+ }
+ return answer;
+}
+
+int
+netcheck(void *key, long chal, char *response)
+{
+ char answer[32], *p;
+ int i;
+
+ if(smartcheck(key, chal, response))
+ return 1;
+
+ if(p = strchr(response, '\n'))
+ *p = '\0';
+ netresp(key, chal, answer);
+
+ /*
+ * check for hex response -- securenet mode 1 or 5
+ */
+ for(i = 0; response[i]; i++)
+ if(response[i] >= 'A' && response[i] <= 'Z')
+ response[i] -= 'A' - 'a';
+ if(strcmp(answer, response) == 0)
+ return 1;
+
+ /*
+ * check for decimal response -- securenet mode 0 or 4
+ */
+ return strcmp(netdecimal(answer), response) == 0;
+}
+
+int
+smartcheck(void *key, long chal, char *response)
+{
+ uchar buf[2*8];
+ int i, c, cslo, cshi;
+
+ sprint((char*)buf, "%lud ", chal);
+ cslo = 0x52;
+ cshi = cslo;
+ for(i = 0; i < 8; i++){
+ c = buf[i];
+ if(c >= '0' && c <= '9')
+ c -= '0';
+ cslo += c;
+ if(cslo > 0xff)
+ cslo -= 0xff;
+ cshi += cslo;
+ if(cshi > 0xff)
+ cshi -= 0xff;
+ buf[i] = c | (cshi & 0xf0);
+ }
+
+ encrypt(key, buf, 8);
+ for(i = 0; i < 8; i++)
+ if(response[i] != buf[i] % 10 + '0')
+ return 0;
+ return 1;
+}
diff --git a/sys/src/cmd/auth/lib/okpasswd.c b/sys/src/cmd/auth/lib/okpasswd.c
new file mode 100755
index 000000000..b904db5aa
--- /dev/null
+++ b/sys/src/cmd/auth/lib/okpasswd.c
@@ -0,0 +1,42 @@
+#include <u.h>
+#include <libc.h>
+#include <authsrv.h>
+#include <bio.h>
+#include "authcmdlib.h"
+
+char *trivial[] = {
+ "login",
+ "guest",
+ "change me",
+ "passwd",
+ "no passwd",
+ "anonymous",
+ 0
+};
+
+char*
+okpasswd(char *p)
+{
+ char passwd[ANAMELEN];
+ char back[ANAMELEN];
+ int i, n;
+
+ strncpy(passwd, p, sizeof passwd - 1);
+ passwd[sizeof passwd - 1] = '\0';
+ n = strlen(passwd);
+ while(passwd[n - 1] == ' ')
+ n--;
+ passwd[n] = '\0';
+ for(i = 0; i < n; i++)
+ back[i] = passwd[n - 1 - i];
+ back[n] = '\0';
+ if(n < 8)
+ return "password must be at least 8 chars";
+
+ for(i = 0; trivial[i]; i++)
+ if(strcmp(passwd, trivial[i]) == 0
+ || strcmp(back, trivial[i]) == 0)
+ return "trivial password";
+
+ return 0;
+}
diff --git a/sys/src/cmd/auth/lib/querybio.c b/sys/src/cmd/auth/lib/querybio.c
new file mode 100755
index 000000000..97218a6dc
--- /dev/null
+++ b/sys/src/cmd/auth/lib/querybio.c
@@ -0,0 +1,66 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <ctype.h>
+#include "authcmdlib.h"
+
+
+#define TABLEN 8
+
+static char*
+defreadln(char *prompt, char *def, int must, int *changed)
+{
+ char pr[512];
+ char reply[256];
+
+ do {
+ if(def && *def){
+ if(must)
+ snprint(pr, sizeof pr, "%s[return = %s]: ", prompt, def);
+ else
+ snprint(pr, sizeof pr, "%s[return = %s, space = none]: ", prompt, def);
+ } else
+ snprint(pr, sizeof pr, "%s: ", prompt);
+ readln(pr, reply, sizeof(reply), 0);
+ switch(*reply){
+ case ' ':
+ break;
+ case 0:
+ return def;
+ default:
+ *changed = 1;
+ if(def)
+ free(def);
+ return strdup(reply);
+ }
+ } while(must);
+
+ if(def){
+ *changed = 1;
+ free(def);
+ }
+ return 0;
+}
+
+/*
+ * get bio from stdin
+ */
+int
+querybio(char *file, char *user, Acctbio *a)
+{
+ int i;
+ int changed;
+
+ rdbio(file, user, a);
+ a->postid = defreadln("Post id", a->postid, 0, &changed);
+ a->name = defreadln("User's full name", a->name, 1, &changed);
+ a->dept = defreadln("Department #", a->dept, 1, &changed);
+ a->email[0] = defreadln("User's email address", a->email[0], 1, &changed);
+ a->email[1] = defreadln("Sponsor's email address", a->email[1], 0, &changed);
+ for(i = 2; i < Nemail; i++){
+ if(a->email[i-1] == 0)
+ break;
+ a->email[i] = defreadln("other email address", a->email[i], 0, &changed);
+ }
+ return changed;
+}
diff --git a/sys/src/cmd/auth/lib/rdbio.c b/sys/src/cmd/auth/lib/rdbio.c
new file mode 100755
index 000000000..7363e4284
--- /dev/null
+++ b/sys/src/cmd/auth/lib/rdbio.c
@@ -0,0 +1,58 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <ctype.h>
+#include "authcmdlib.h"
+
+void
+clrbio(Acctbio *a)
+{
+ int i;
+
+ if(a->user)
+ free(a->user);
+ if(a->postid)
+ free(a->postid);
+ if(a->name)
+ free(a->name);
+ if(a->dept)
+ free(a->dept);
+ for(i = 0; i < Nemail; i++)
+ if(a->email[i])
+ free(a->email[i]);
+ memset(a, 0, sizeof(Acctbio));
+}
+
+void
+rdbio(char *file, char *user, Acctbio *a)
+{
+ int i,n;
+ Biobuf *b;
+ char *p;
+ char *field[20];
+
+ memset(a, 0, sizeof(Acctbio));
+ b = Bopen(file, OREAD);
+ if(b == 0)
+ return;
+ while(p = Brdline(b, '\n')){
+ p[Blinelen(b)-1] = 0;
+ n = getfields(p, field, nelem(field), 0, "|");
+ if(n < 4)
+ continue;
+ if(strcmp(field[0], user) != 0)
+ continue;
+
+ clrbio(a);
+
+ a->postid = strdup(field[1]);
+ a->name = strdup(field[2]);
+ a->dept = strdup(field[3]);
+ if(n-4 >= Nemail)
+ n = Nemail-4;
+ for(i = 4; i < n; i++)
+ a->email[i-4] = strdup(field[i]);
+ }
+ a->user = strdup(user);
+ Bterm(b);
+}
diff --git a/sys/src/cmd/auth/lib/readarg.c b/sys/src/cmd/auth/lib/readarg.c
new file mode 100755
index 000000000..cce957db9
--- /dev/null
+++ b/sys/src/cmd/auth/lib/readarg.c
@@ -0,0 +1,23 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "authcmdlib.h"
+
+int
+readarg(int fd, char *arg, int len)
+{
+ char buf[1];
+ int i;
+
+ i = 0;
+ memset(arg, 0, len);
+ while(read(fd, buf, 1) == 1){
+ if(i < len - 1)
+ arg[i++] = *buf;
+ if(*buf == '\0'){
+ arg[i] = '\0';
+ return 0;
+ }
+ }
+ return -1;
+}
diff --git a/sys/src/cmd/auth/lib/readln.c b/sys/src/cmd/auth/lib/readln.c
new file mode 100755
index 000000000..ee470a52c
--- /dev/null
+++ b/sys/src/cmd/auth/lib/readln.c
@@ -0,0 +1,115 @@
+#include <u.h>
+#include <libc.h>
+#include <authsrv.h>
+#include <bio.h>
+#include "authcmdlib.h"
+
+void
+getpass(char *key, char *pass, int check, int confirm)
+{
+ char rpass[32], npass[32];
+ char *err;
+
+ if(pass == nil)
+ pass = npass;
+
+ for(;;){
+ readln("Password: ", pass, sizeof npass, 1);
+ if(confirm){
+ readln("Confirm password: ", rpass, sizeof rpass, 1);
+ if(strcmp(pass, rpass) != 0){
+ print("mismatch, try again\n");
+ continue;
+ }
+ }
+ if(!passtokey(key, pass)){
+ print("bad password, try again\n");
+ continue;
+ }
+ if(check)
+ if(err = okpasswd(pass)){
+ print("%s, try again\n", err);
+ continue;
+ }
+ break;
+ }
+}
+
+int
+getsecret(int passvalid, char *p9pass)
+{
+ char answer[32];
+
+ readln("assign Inferno/POP secret? (y/n) ", answer, sizeof answer, 0);
+ if(*answer != 'y' && *answer != 'Y')
+ return 0;
+
+ if(passvalid){
+ readln("make it the same as the plan 9 password? (y/n) ",
+ answer, sizeof answer, 0);
+ if(*answer == 'y' || *answer == 'Y')
+ return 1;
+ }
+
+ for(;;){
+ readln("Secret(0 to 256 characters): ", p9pass,
+ sizeof answer, 1);
+ readln("Confirm: ", answer, sizeof answer, 1);
+ if(strcmp(p9pass, answer) == 0)
+ break;
+ print("mismatch, try again\n");
+ }
+ return 1;
+}
+
+void
+readln(char *prompt, char *line, int len, int raw)
+{
+ char *p;
+ int fdin, fdout, ctl, n, nr;
+
+ fdin = open("/dev/cons", OREAD);
+ fdout = open("/dev/cons", OWRITE);
+ fprint(fdout, "%s", prompt);
+ if(raw){
+ ctl = open("/dev/consctl", OWRITE);
+ if(ctl < 0)
+ error("couldn't set raw mode");
+ write(ctl, "rawon", 5);
+ } else
+ ctl = -1;
+ nr = 0;
+ p = line;
+ for(;;){
+ n = read(fdin, p, 1);
+ if(n < 0){
+ close(ctl);
+ error("can't read cons\n");
+ }
+ if(*p == 0x7f)
+ exits(0);
+ if(n == 0 || *p == '\n' || *p == '\r'){
+ *p = '\0';
+ if(raw){
+ write(ctl, "rawoff", 6);
+ write(fdout, "\n", 1);
+ }
+ close(ctl);
+ return;
+ }
+ if(*p == '\b'){
+ if(nr > 0){
+ nr--;
+ p--;
+ }
+ }else{
+ nr++;
+ p++;
+ }
+ if(nr == len){
+ fprint(fdout, "line too long; try again\n");
+ nr = 0;
+ p = line;
+ }
+ }
+}
diff --git a/sys/src/cmd/auth/lib/readn.c b/sys/src/cmd/auth/lib/readn.c
new file mode 100755
index 000000000..6f9324958
--- /dev/null
+++ b/sys/src/cmd/auth/lib/readn.c
@@ -0,0 +1,20 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "authcmdlib.h"
+
+/*
+ * read exactly len bytes
+ */
+int
+readn(int fd, char *buf, int len)
+{
+ int m, n;
+
+ for(n = 0; n < len; n += m){
+ m = read(fd, buf+n, len-n);
+ if(m <= 0)
+ return -1;
+ }
+ return n;
+}
diff --git a/sys/src/cmd/auth/lib/readwrite.c b/sys/src/cmd/auth/lib/readwrite.c
new file mode 100755
index 000000000..54f494eb4
--- /dev/null
+++ b/sys/src/cmd/auth/lib/readwrite.c
@@ -0,0 +1,90 @@
+#include <u.h>
+#include <libc.h>
+#include <authsrv.h>
+#include <bio.h>
+#include "authcmdlib.h"
+
+int
+readfile(char *file, char *buf, int n)
+{
+ int fd;
+
+ fd = open(file, OREAD);
+ if(fd < 0){
+ werrstr("%s: %r", file);
+ return -1;
+ }
+ n = read(fd, buf, n);
+ close(fd);
+ return n;
+}
+
+int
+writefile(char *file, char *buf, int n)
+{
+ int fd;
+
+ fd = open(file, OWRITE);
+ if(fd < 0)
+ return -1;
+ n = write(fd, buf, n);
+ close(fd);
+ return n;
+}
+
+char*
+findkey(char *db, char *user, char *key)
+{
+ int n;
+ char filename[Maxpath];
+
+ snprint(filename, sizeof filename, "%s/%s/key", db, user);
+ n = readfile(filename, key, DESKEYLEN);
+ if(n != DESKEYLEN)
+ return 0;
+ else
+ return key;
+}
+
+char*
+findsecret(char *db, char *user, char *secret)
+{
+ int n;
+ char filename[Maxpath];
+
+ snprint(filename, sizeof filename, "%s/%s/secret", db, user);
+ n = readfile(filename, secret, SECRETLEN-1);
+ secret[n]=0;
+ if(n <= 0)
+ return 0;
+ else
+ return secret;
+}
+
+char*
+setkey(char *db, char *user, char *key)
+{
+ int n;
+ char filename[Maxpath];
+
+ snprint(filename, sizeof filename, "%s/%s/key", db, user);
+ n = writefile(filename, key, DESKEYLEN);
+ if(n != DESKEYLEN)
+ return 0;
+ else
+ return key;
+}
+
+char*
+setsecret(char *db, char *user, char *secret)
+{
+ int n;
+ char filename[Maxpath];
+
+ snprint(filename, sizeof filename, "%s/%s/secret", db, user);
+ n = writefile(filename, secret, strlen(secret));
+ if(n != strlen(secret))
+ return 0;
+ else
+ return secret;
+}
diff --git a/sys/src/cmd/auth/lib/wrbio.c b/sys/src/cmd/auth/lib/wrbio.c
new file mode 100755
index 000000000..e50ca500b
--- /dev/null
+++ b/sys/src/cmd/auth/lib/wrbio.c
@@ -0,0 +1,40 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <ctype.h>
+#include "authcmdlib.h"
+
+void
+wrbio(char *file, Acctbio *a)
+{
+ char buf[1024];
+ int i, fd, n;
+
+ fd = open(file, OWRITE);
+ if(fd < 0)
+ error("can't open %s", file);
+ if(seek(fd, 0, 2) < 0)
+ error("can't seek %s", file);
+
+ if(a->postid == 0)
+ a->postid = "";
+ if(a->name == 0)
+ a->name = "";
+ if(a->dept == 0)
+ a->dept = "";
+ if(a->email[0] == 0)
+ a->email[0] = strdup(a->user);
+
+ n = 0;
+ n += snprint(buf+n, sizeof(buf)-n, "%s|%s|%s|%s",
+ a->user, a->postid, a->name, a->dept);
+ for(i = 0; i < Nemail; i++){
+ if(a->email[i] == 0)
+ break;
+ n += snprint(buf+n, sizeof(buf)-n, "|%s", a->email[i]);
+ }
+ n += snprint(buf+n, sizeof(buf)-n, "\n");
+
+ write(fd, buf, n);
+ close(fd);
+}