shithub: riscv

Download patch

ref: 261e3190929acd3e8e00507894789a5575fb815f
parent: a75f4de5c9f1782b3a7e0a9648e24b360031a0d5
author: cinap_lenrek <[email protected]>
date: Sun Jul 31 16:16:25 EDT 2016

auth: various cleanups, use common readcons() from libauthsrv, zero keys after use

--- a/sys/src/cmd/auth/authcmdlib.h
+++ b/sys/src/cmd/auth/authcmdlib.h
@@ -1,7 +1,6 @@
 #pragma lib "./lib.$O.a"
 
 enum{
-	PASSLEN		= 10,
 	MAXNETCHAL	= 100000,		/* max securenet challenge */
 	Maxpath		= 256,
 };
@@ -36,6 +35,7 @@
 
 extern Fs fs[3];
 
+int	answer(char*);
 void	checksum(char*, char*);
 void	error(char*, ...);
 void	fail(char*);
@@ -46,7 +46,6 @@
 int	getauthkey(Authkey*);
 long	getexpiration(char *db, char *u);
 void	getpass(Authkey*, char*, int, int);
-int	getsecret(int, char*);
 int	deskeyfmt(Fmt*);
 void	logfail(char*);
 int	netcheck(void*, long, char*);
@@ -58,8 +57,6 @@
 void	rdbio(char*, char*, Acctbio*);
 int	readarg(int, char*, int);
 int	readfile(char*, char*, int);
-void	readln(char*, char*, int, int);
-long	readn(int, void*, long);
 char*	secureidcheck(char*, char*);
 int	setkey(char*, char*, Authkey*);
 char*	setdeskey(char*, char*, char*);
--- a/sys/src/cmd/auth/authsrv.c
+++ b/sys/src/cmd/auth/authsrv.c
@@ -3,7 +3,6 @@
 #include <bio.h>
 #include <ndb.h>
 #include <regexp.h>
-#include <mp.h>
 #include <libsec.h>
 #include <authsrv.h>
 #include "authcmdlib.h"
--- a/sys/src/cmd/auth/changeuser.c
+++ b/sys/src/cmd/auth/changeuser.c
@@ -1,13 +1,12 @@
 #include <u.h>
 #include <libc.h>
+#include <bio.h>
 #include <libsec.h>
 #include <authsrv.h>
-#include <ctype.h>
-#include <bio.h>
 #include "authcmdlib.h"
 
 void	install(char*, char*, Authkey*, long, int);
-int	exists (char*, char*);
+int	exists(char*, char*);
 
 void
 usage(void)
@@ -19,7 +18,7 @@
 void
 main(int argc, char *argv[])
 {
-	char *u, answer[32], p9pass[32];
+	char *u, pass[32];
 	int which, newkey, newbio, dosecret;
 	long t;
 	Authkey key;
@@ -50,26 +49,25 @@
 	if(!which)
 		which = Plan9;
 
+	private();
 	newbio = 0;
 	t = 0;
 	a.user = 0;
+	memset(&key, 0, sizeof(key));
 	if(which & Plan9){
 		f = &fs[Plan9];
-		newkey = 1;
-		if(exists(f->keys, u)){
-			readln("assign new password? [y/n]: ", answer, sizeof answer, 0);
-			if(answer[0] != 'y' && answer[0] != 'Y')
-				newkey = 0;
-		}
+		newkey = !exists(f->keys, u) || answer("assign new Plan 9 password?");
 		if(newkey)
-			getpass(&key, p9pass, 1, 1);
-		dosecret = getsecret(newkey, p9pass);
+			getpass(&key, pass, 1, 1);
+		dosecret = answer("assign new Inferno/POP secret?");
+		if(dosecret)
+			if(!newkey || !answer("make it the same as Plan 9 password?"))
+				getpass(nil, pass, 0, 1);
 		t = getexpiration(f->keys, u);
 		install(f->keys, u, &key, t, newkey);
-		if(dosecret && setsecret(KEYDB, u, p9pass) == 0)
-			error("error writing Inferno/pop secret");
-		newbio = querybio(f->who, u, &a);
-		if(newbio)
+		if(dosecret && setsecret(KEYDB, u, pass) == 0)
+			error("error writing Inferno/POP secret");
+		if(querybio(f->who, u, &a))
 			wrbio(f->who, &a);
 		print("user %s installed for Plan 9\n", u);
 		syslog(0, AUTHLOG, "user %s installed for plan 9", u);
@@ -76,16 +74,9 @@
 	}
 	if(which & Securenet){
 		f = &fs[Securenet];
-		newkey = 1;
-		if(exists(f->keys, u)){
-			readln("assign new key? [y/n]: ", answer, sizeof answer, 0);
-			if(answer[0] != 'y' && answer[0] != 'Y')
-				newkey = 0;
-		}
-		if(newkey){
-			memset(&key, 0, sizeof(key));
+		newkey = !exists(f->keys, u) || answer("assign new Securenet key?");
+		if(newkey)
 			genrandom((uchar*)key.des, DESKEYLEN);
-		}
 		if(a.user == 0){
 			t = getexpiration(f->keys, u);
 			newbio = querybio(f->who, u, &a);
@@ -93,10 +84,11 @@
 		install(f->keys, u, &key, t, newkey);
 		if(newbio)
 			wrbio(f->who, &a);
-		finddeskey(f->keys, u, key.des);
+		if(!finddeskey(f->keys, u, key.des))
+			error("error reading Securenet key");
 		print("user %s: SecureNet key: %K\n", u, key.des);
-		checksum(key.des, answer);
-		print("verify with checksum %s\n", answer);
+		checksum(key.des, pass);
+		print("verify with checksum %s\n", pass);
 		print("user %s installed for SecureNet\n", u);
 		syslog(0, AUTHLOG, "user %s installed for securenet", u);
 	}
@@ -110,7 +102,7 @@
 	int fd;
 
 	if(!exists(db, u)){
-		sprint(buf, "%s/%s", db, u);
+		snprint(buf, sizeof(buf), "%s/%s", db, u);
 		fd = create(buf, OREAD, 0777|DMDIR);
 		if(fd < 0)
 			error("can't create user %s: %r", u);
@@ -117,14 +109,12 @@
 		close(fd);
 	}
 
-	if(newkey){
-		if(!setkey(db, u, key))
-			error("can't set key: %r");
-	}
+	if(newkey && !setkey(db, u, key))
+		error("can't set key: %r");
 
 	if(t == -1)
 		return;
-	sprint(buf, "%s/%s/expire", db, u);
+	snprint(buf, sizeof(buf), "%s/%s/expire", db, u);
 	fd = open(buf, OWRITE);
 	if(fd < 0 || fprint(fd, "%ld", t) < 0)
 		error("can't write expiration time");
@@ -136,7 +126,7 @@
 {
 	char buf[KEYDBBUF+ANAMELEN+6];
 
-	sprint(buf, "%s/%s/expire", db, u);
+	snprint(buf, sizeof(buf), "%s/%s/expire", db, u);
 	if(access(buf, 0) < 0)
 		return 0;
 	return 1;
--- a/sys/src/cmd/auth/convbio.c
+++ b/sys/src/cmd/auth/convbio.c
@@ -2,6 +2,7 @@
 #include <libc.h>
 #include <bio.h>
 #include <ctype.h>
+#include <authsrv.h>
 #include "authcmdlib.h"
 
 void
--- a/sys/src/cmd/auth/convkeys.c
+++ b/sys/src/cmd/auth/convkeys.c
@@ -1,10 +1,8 @@
 #include <u.h>
 #include <libc.h>
-#include <ctype.h>
-#include <authsrv.h>
-#include <mp.h>
-#include <libsec.h>
 #include <bio.h>
+#include <libsec.h>
+#include <authsrv.h>
 #include "authcmdlib.h"
 
 Authkey	okey, nkey;
--- a/sys/src/cmd/auth/debug.c
+++ b/sys/src/cmd/auth/debug.c
@@ -44,78 +44,6 @@
 	exits("usage");
 }
 
-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];
-		}
-	}
-}
-
 void authdialfutz(char*, char*, char*);
 void authfutz(char*, char*, char*);
 
@@ -241,18 +169,22 @@
 void
 authfutz(char *dom, char *user, char *proto)
 {
-	int fd, nobootes, n, m;
-	char pw[128], prompt[128], tbuf[2*MAXTICKETLEN];
+	int fd, n, m;
+	char prompt[128], tbuf[2*MAXTICKETLEN], *pass;
 	Authkey key, booteskey;
 	Ticket t;
 	Ticketreq tr;
 
 	snprint(prompt, sizeof prompt, "\tpassword for %s@%s [hit enter to skip test]", user, dom);
-	readcons(prompt, nil, 1, pw, sizeof pw);
-	if(pw[0] == '\0')
+	pass = readcons(prompt, nil, 1);
+	if(pass == nil || *pass == 0){
+		free(pass);
 		return;
-	passtokey(&key, pw);
+	}
+	passtokey(&key, pass);
 	booteskey = key;
+	memset(pass, 0, strlen(pass));
+	free(pass);
 
 	fd = authdial(nil, dom);
 	if(fd < 0){
@@ -309,15 +241,22 @@
 
 	/* try ticket request using bootes key */
 	snprint(prompt, sizeof prompt, "\tcpu server owner for domain %s ", dom);
-	readcons(prompt, "glenda", 0, tr.authid, sizeof tr.authid);
+	user = readcons(prompt, "glenda", 0);
+	if(user == nil || *user == '\0'){
+		free(user);
+		goto Nobootes;
+	}
+	strecpy(tr.authid, tr.authid+sizeof tr.authid, user);
+	free(user);
 	snprint(prompt, sizeof prompt, "\tpassword for %s@%s [hit enter to skip test]", tr.authid, dom);
-	readcons(prompt, nil, 1, pw, sizeof pw);
-	if(pw[0] == '\0'){
-		nobootes=1;
+	pass = readcons(prompt, nil, 1);
+	if(pass == nil || *pass == '\0'){
+		free(pass);
 		goto Nobootes;
 	}
-	nobootes = 0;
-	passtokey(&booteskey, pw);
+	passtokey(&booteskey, pass);
+	memset(pass, 0, strlen(pass));
+	free(pass);
 
 	if(strcmp(proto, "dp9ik") == 0 && getpakkeys(fd, &tr, &booteskey, &key) < 0){
 		print("\tgetpakkeys failed: %r\n");
@@ -333,7 +272,7 @@
 	m = convM2T(tbuf, n, &t, &key);
 	if(t.num != AuthTc){
 		print("\tcannot decrypt ticket1 from auth server (bad t.num=0x%.2ux)\n", t.num);
-		print("\tauth server and you do not agree on key for %s@%s\n", user, dom);
+		print("\tauth server and you do not agree on key for %s@%s\n", tr.hostid, dom);
 		return;
 	}
 	if(memcmp(t.chal, tr.chal, sizeof tr.chal) != 0){
@@ -358,8 +297,6 @@
 	print("\tticket request using %s@%s key succeeded\n", tr.authid, dom);
 
 Nobootes:;
-	USED(nobootes);
-
 	/* try p9sk1 exchange with local factotum to test that key is right */
 
 
--- a/sys/src/cmd/auth/guard.srv.c
+++ b/sys/src/cmd/auth/guard.srv.c
@@ -89,7 +89,6 @@
 	alarm(0);
 
 	/* remove password login from guard.research.bell-labs.com, sucre, etc. */
-//	if(!findkey(KEYDB,    user, ukey) || !netcheck(ukey, chal, resp))
 	if(!finddeskey(NETKEYDB, user, ukey) || !netcheck(ukey, chal, resp))
 	if((err = secureidcheck(user, resp)) != nil){
 		print("NO %s", err);
--- a/sys/src/cmd/auth/keyfs.c
+++ b/sys/src/cmd/auth/keyfs.c
@@ -4,11 +4,10 @@
 #include <u.h>
 #include <libc.h>
 #include <ctype.h>
-#include <authsrv.h>
 #include <fcall.h>
 #include <bio.h>
-#include <mp.h>
 #include <libsec.h>
+#include <authsrv.h>
 #include "authcmdlib.h"
 
 #pragma	varargck	type	"W"	char*
--- /dev/null
+++ b/sys/src/cmd/auth/lib/answer.c
@@ -1,0 +1,18 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <authsrv.h>
+#include "authcmdlib.h"
+
+int
+answer(char *q)
+{
+	char pr[128];
+	int y;
+
+	snprint(pr, sizeof(pr), "%s [y/n]", q);
+	q = readcons(pr, nil, 0);
+	y = q != nil && (*q == 'y' || *q == 'Y');
+	free(q);
+	return y;
+}
--- a/sys/src/cmd/auth/lib/getauthkey.c
+++ b/sys/src/cmd/auth/lib/getauthkey.c
@@ -1,29 +1,22 @@
 #include <u.h>
 #include <libc.h>
-#include <authsrv.h>
 #include <bio.h>
+#include <authsrv.h>
 #include "authcmdlib.h"
 
-static int
-getkey(Authkey *authkey)
-{
-	Nvrsafe safe;
-
-	if(readnvram(&safe, 0) < 0)
-		return -1;
-	memmove(authkey->des, safe.machkey, DESKEYLEN);
-	memmove(authkey->aes, safe.aesmachkey, AESKEYLEN);
-	memset(&safe, 0, sizeof safe);
-	return 0;
-}
-
 int
 getauthkey(Authkey *authkey)
 {
+	Nvrsafe safe;
+
 	memset(authkey, 0, sizeof(Authkey));
-	if(getkey(authkey) == 0)
-		return 1;
-	print("can't read NVRAM, please enter machine key\n");
-	getpass(authkey, nil, 0, 1);
+	if(readnvram(&safe, 0) < 0){
+		print("can't read NVRAM, please enter machine key\n");
+		getpass(authkey, nil, 0, 1);
+	} else {
+		memmove(authkey->des, safe.machkey, DESKEYLEN);
+		memmove(authkey->aes, safe.aesmachkey, AESKEYLEN);
+		memset(&safe, 0, sizeof safe);
+	}
 	return 1;
 }
--- a/sys/src/cmd/auth/lib/getexpiration.c
+++ b/sys/src/cmd/auth/lib/getexpiration.c
@@ -31,8 +31,7 @@
 getexpiration(char *db, char *u)
 {
 	char buf[Maxpath];
-	char prompt[128];
-	char cdate[32];
+	char *cdate;
 	Tm date;
 	ulong secs, now;
 	int n, fd;
@@ -57,20 +56,24 @@
 			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;
+	for(;;free(cdate)){
+		cdate = readcons("Expiration date (YYYYMMDD or never)", buf, 0);
+		if(cdate == nil || *cdate == 0){
+			secs = -1;
+			break;
+		}
+		if(strcmp(cdate, "never") == 0){
+			secs = 0;
+			break;
+		}
 		date = getdate(cdate);
 		secs = tm2sec(&date);
+		now = time(0);
 		if(secs > now && secs < now + 2*365*24*60*60)
 			break;
 		print("expiration time must fall between now and 2 years from now\n");
 	}
+	free(cdate);
 	return secs;
 }
--- /dev/null
+++ b/sys/src/cmd/auth/lib/getpass.c
@@ -1,0 +1,48 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <authsrv.h>
+#include "authcmdlib.h"
+
+void
+getpass(Authkey *key, char *pass, int check, int confirm)
+{
+	char buf[PASSWDLEN], *s, *err;
+
+	for(;; memset(s, 0, strlen(s)), free(s)){
+		s = readcons("Password", nil, 1);
+		if(s == nil)
+			break;
+		if(check){
+			if(err = okpasswd(s)){
+				print("%s, try again\n", err);
+				continue;
+			}
+		}
+		if(strlen(s) >= sizeof(buf)){
+			print("password longer than %d characters\n", sizeof(buf)-1);
+			continue;
+		}
+		strcpy(buf, s);
+		memset(s, 0, strlen(s));
+		free(s);
+		if(confirm){
+			s = readcons("Confirm password", nil, 1);
+			if(s == nil)
+				break;
+			if(strcmp(s, buf) != 0){
+				print("mismatch, try again\n");
+				continue;
+			}
+			memset(s, 0, strlen(s));
+			free(s);
+		}
+		if(key)
+			passtokey(key, buf);
+		if(pass)
+			strcpy(pass, buf);
+		memset(buf, 0, sizeof(buf));
+		return;
+	}
+	error("no password");
+}
--- a/sys/src/cmd/auth/lib/mkfile
+++ b/sys/src/cmd/auth/lib/mkfile
@@ -3,6 +3,7 @@
 
 LIB=../lib.$O.a
 OFILES=\
+	answer.$O\
 	keyfmt.$O\
 	netcheck.$O\
 	okpasswd.$O\
@@ -9,7 +10,7 @@
 	private.$O\
 	readwrite.$O\
 	readarg.$O\
-	readln.$O\
+	getpass.$O\
 	getauthkey.$O\
 	log.$O\
 	error.$O\
--- a/sys/src/cmd/auth/lib/okpasswd.c
+++ b/sys/src/cmd/auth/lib/okpasswd.c
@@ -1,7 +1,7 @@
 #include <u.h>
 #include <libc.h>
-#include <authsrv.h>
 #include <bio.h>
+#include <authsrv.h>
 #include "authcmdlib.h"
 
 char *trivial[] = {
@@ -17,14 +17,14 @@
 char*
 okpasswd(char *p)
 {
-	char passwd[ANAMELEN];
-	char back[ANAMELEN];
+	char passwd[PASSWDLEN];
+	char back[PASSWDLEN];
 	int i, n;
 
 	strncpy(passwd, p, sizeof passwd - 1);
 	passwd[sizeof passwd - 1] = '\0';
 	n = strlen(passwd);
-	while(passwd[n - 1] == ' ')
+	while(n > 0 && passwd[n - 1] == ' ')
 		n--;
 	passwd[n] = '\0';
 	for(i = 0; i < n; i++)
--- a/sys/src/cmd/auth/lib/querybio.c
+++ b/sys/src/cmd/auth/lib/querybio.c
@@ -5,42 +5,31 @@
 #include <authsrv.h>
 #include "authcmdlib.h"
 
-
-#define TABLEN 8
-
-static char*
-defreadln(char *prompt, char *def, int must, int *changed)
+static void
+ask(char *prompt, char **sp, int must, int *changed)
 {
-	char pr[512];
-	char reply[256];
+	char pr[128], *def, *ans;
 
-	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);
+	def = *sp;
+	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);
+	ans = readcons(pr, nil, 0);
+	if(ans == nil || *ans == 0){
+		free(ans);
+		return;
 	}
-	return 0;
+	if(*ans == ' ' && !must){
+		free(ans);
+		ans = nil;
+	}
+	*sp = ans;
+	*changed = 1;
+	free(def);
 }
 
 /*
@@ -53,15 +42,15 @@
 	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);
+	ask("Post id", &a->postid, 0, &changed);
+	ask("User's full name", &a->name, 1, &changed);
+	ask("Department #", &a->dept, 1, &changed);
+	ask("User's email address", &a->email[0], 1, &changed);
+	ask("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);
+		ask("other email address", &a->email[i], 0, &changed);
 	}
 	return changed;
 }
--- a/sys/src/cmd/auth/lib/readln.c
+++ /dev/null
@@ -1,111 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <authsrv.h>
-#include <bio.h>
-#include "authcmdlib.h"
-
-void
-getpass(Authkey *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(check)
-			if(err = okpasswd(pass)){
-				print("%s, try again\n", err);
-				continue;
-			}
-		passtokey(key, pass);
-		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: ", 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;
-		}
-	}
-}
--- a/sys/src/cmd/auth/lib/readn.c
+++ /dev/null
@@ -1,20 +1,0 @@
-#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;
-}
--- a/sys/src/cmd/auth/lib/readwrite.c
+++ b/sys/src/cmd/auth/lib/readwrite.c
@@ -1,9 +1,12 @@
 #include <u.h>
 #include <libc.h>
-#include <authsrv.h>
 #include <bio.h>
+#include <libsec.h>
+#include <authsrv.h>
 #include "authcmdlib.h"
 
+static uchar zeros[16];
+
 int
 readfile(char *file, char *buf, int n)
 {
@@ -35,29 +38,23 @@
 char*
 finddeskey(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)
+	if(readfile(filename, key, DESKEYLEN) != DESKEYLEN)
 		return nil;
-	else
-		return key;
+	return key;
 }
 
 uchar*
 findaeskey(char *db, char *user, uchar *key)
 {
-	int n;
 	char filename[Maxpath];
 
 	snprint(filename, sizeof filename, "%s/%s/aeskey", db, user);
-	n = readfile(filename, (char*)key, AESKEYLEN);
-	if(n != AESKEYLEN)
+	if(readfile(filename, (char*)key, AESKEYLEN) != AESKEYLEN)
 		return nil;
-	else
-		return key;
+	return key;
 }
 
 int
@@ -67,8 +64,9 @@
 
 	memset(key, 0, sizeof(Authkey));
 	ret = findaeskey(db, user, key->aes) != nil;
-	if(ret){
+	if(ret && tsmemcmp(key->aes, zeros, AESKEYLEN) != 0){
 		char filename[Maxpath];
+
 		snprint(filename, sizeof filename, "%s/%s/pakhash", db, user);
 		if(readfile(filename, (char*)key->pakhash, PAKHASHLEN) != PAKHASHLEN)
 			authpak_hash(key, user);
@@ -84,40 +82,32 @@
 	char filename[Maxpath];
 
 	snprint(filename, sizeof filename, "%s/%s/secret", db, user);
-	n = readfile(filename, secret, SECRETLEN-1);
-	secret[n]=0;
-	if(n <= 0)
+	if((n = readfile(filename, secret, SECRETLEN-1)) <= 0)
 		return nil;
-	else
-		return secret;
+	secret[n]=0;
+	return secret;
 }
 
 char*
 setdeskey(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)
+	if(writefile(filename, key, DESKEYLEN) != DESKEYLEN)
 		return nil;
-	else
-		return key;
+	return key;
 }
 
 uchar*
 setaeskey(char *db, char *user, uchar *key)
 {
-	int n;
 	char filename[Maxpath];
 
 	snprint(filename, sizeof filename, "%s/%s/aeskey", db, user);
-	n = writefile(filename, (char*)key, AESKEYLEN);
-	if(n != AESKEYLEN)
+	if(writefile(filename, (char*)key, AESKEYLEN) != AESKEYLEN)
 		return nil;
-	else
-		return key;
+	return key;
 }
 
 int
@@ -126,7 +116,8 @@
 	int ret;
 
 	ret = setdeskey(db, user, key->des) != nil;
-	ret |= setaeskey(db, user, key->aes) != nil;
+	if(tsmemcmp(key->aes, zeros, AESKEYLEN) != 0)
+		ret |= setaeskey(db, user, key->aes) != nil;
 	return ret;
 }
 
@@ -133,13 +124,10 @@
 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))
+	if(writefile(filename, secret, strlen(secret)) != strlen(secret))
 		return nil;
-	else
-		return secret;
+	return secret;
 }
--- a/sys/src/cmd/auth/login.c
+++ b/sys/src/cmd/auth/login.c
@@ -8,65 +8,6 @@
 char *authdom;
 
 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){
-			fprint(2, "login: couldn't set raw mode");
-			exits("readln");
-		}
-		write(ctl, "rawon", 5);
-	} else
-		ctl = -1;
-	nr = 0;
-	p = line;
-	for(;;){
-		n = read(fdin, p, 1);
-		if(n < 0){
-			close(ctl);
-			close(fdin);
-			close(fdout);
-			fprint(2, "login: can't read cons");
-			exits("readln");
-		}
-		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);
-			close(fdin);
-			close(fdout);
-			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;
-		}
-	}
-}
-
-void
 setenv(char *var, char *val)
 {
 	int fd;
@@ -188,11 +129,10 @@
 void
 main(int argc, char *argv[])
 {
-	char pass[ANAMELEN];
 	char buf[2*ANAMELEN];
 	char home[2*ANAMELEN];
 	char srvname[2*ANAMELEN];
-	char *user, *sysname, *tz, *cputype, *service;
+	char *user, *pass, *sysname, *tz, *cputype, *service;
 	AuthInfo *ai;
 
 	ARGBEGIN{
@@ -217,8 +157,9 @@
 		exits("usage");
 	}
 	user = argv[0];
-	memset(pass, 0, sizeof(pass));
-	readln("Password: ", pass, sizeof(pass), 1);
+	pass = readcons("Password", nil, 1);
+	if(pass == nil)
+		exits("no password");
 
 	/* authenticate */
 	ai = auth_userpasswd(user, pass);
@@ -230,6 +171,9 @@
 
 	/* start a new factotum and hand it a new key */
 	startfactotum(user, pass, srvname);
+
+	memset(pass, 0, strlen(pass));
+	free(pass);
 
 	/* set up new namespace */
 	newns(ai->cuid, nil);
--- a/sys/src/cmd/auth/netkey.c
+++ b/sys/src/cmd/auth/netkey.c
@@ -4,7 +4,6 @@
 #include <bio.h>
 #include "authcmdlib.h"
 
-
 void
 usage(void)
 {
@@ -15,7 +14,7 @@
 void
 main(int argc, char *argv[])
 {
-	char buf[32], pass[32], key[DESKEYLEN];
+	char buf[32], key[DESKEYLEN], *pass;
 	char *s;
 	int n;
 
@@ -27,13 +26,18 @@
 		usage();
 
 	s = getenv("service");
-	if(s && strcmp(s, "cpu") == 0){
+	if(s != nil && strcmp(s, "cpu") == 0){
 		fprint(2, "netkey must not be run on the cpu server\n");
 		exits("boofhead");
 	}
+	private();
 
-	readln("Password: ", pass, sizeof pass, 1);
+	pass = readcons("Password", nil, 1);
+	if(pass == nil)
+		exits("no password");
 	passtodeskey(key, pass);
+	memset(pass, 0, strlen(pass));
+	free(pass);
 
 	for(;;){
 		print("challenge: ");
--- a/sys/src/cmd/auth/passwd.c
+++ b/sys/src/cmd/auth/passwd.c
@@ -15,11 +15,11 @@
 	char buf[512];
 	char *s, *user;
 
-	user = getuser();
-
 	ARGBEGIN{
 	}ARGEND
 
+	argv0 = "passwd";
+	user = getuser();
 	private();
 
 	s = nil;
@@ -46,8 +46,7 @@
 	 *  give up.
 	 */
 	memset(&pr, 0, sizeof(pr));
-	readln("Plan 9 Password: ", pr.old, sizeof pr.old, 1);
-	passtokey(&key, pr.old);
+	getpass(&key, pr.old, 0, 0);
 
 	/*
 	 *  negotiate PAK key. we need to retry in case the AS does
@@ -77,34 +76,18 @@
 
 	/* loop trying new passwords */
 	for(;;){
-		pr.changesecret = 0;
-		*pr.new = 0;
-		readln("change Plan 9 Password? (y/n) ", buf, sizeof buf, 0);
-		if(*buf == 'y' || *buf == 'Y'){
-			readln("Password: ", pr.new, sizeof pr.new, 1);
-			readln("Confirm: ", buf, sizeof buf, 1);
-			if(strcmp(pr.new, buf)){
-				print("!mismatch\n");
-				continue;
-			}
-		}
-		readln("change Inferno/POP password? (y/n) ", buf, sizeof buf, 0);
-		if(*buf == 'y' || *buf == 'Y'){
-			pr.changesecret = 1;
-			readln("make it the same as your plan 9 password? (y/n) ",
-				buf, sizeof buf, 0);
-			if(*buf == 'y' || *buf == 'Y'){
-				if(*pr.new == 0)
-					strcpy(pr.secret, pr.old);
-				else
+		memset(pr.new, 0, sizeof(pr.new));
+		if(answer("change Plan 9 Password?"))
+			getpass(nil, pr.new, 0, 1);
+		pr.changesecret = answer("change Inferno/POP secret?");
+		if(pr.changesecret){
+			if(answer("make it the same as your plan 9 password?")){
+				if(*pr.new)
 					strcpy(pr.secret, pr.new);
+				else
+					strcpy(pr.secret, pr.old);
 			} else {
-				readln("Secret: ", pr.secret, sizeof pr.secret, 1);
-				readln("Confirm: ", buf, sizeof buf, 1);
-				if(strcmp(pr.secret, buf)){
-					print("!mismatch\n");
-					continue;
-				}
+				getpass(nil, pr.secret, 0, 1);
 			}
 		}
 		pr.num = AuthPass;
--- a/sys/src/cmd/auth/pemdecode.c
+++ b/sys/src/cmd/auth/pemdecode.c
@@ -1,7 +1,5 @@
 #include <u.h>
 #include <libc.h>
-#include <bio.h>
-#include <mp.h>
 #include <libsec.h>
 
 void
--- a/sys/src/cmd/auth/pemencode.c
+++ b/sys/src/cmd/auth/pemencode.c
@@ -1,7 +1,5 @@
 #include <u.h>
 #include <libc.h>
-#include <bio.h>
-#include <mp.h>
 #include <libsec.h>
 
 void
--- a/sys/src/cmd/auth/secureidcheck.c
+++ b/sys/src/cmd/auth/secureidcheck.c
@@ -12,12 +12,11 @@
 /* RFC2138 */
 #include <u.h>
 #include <libc.h>
-#include <ip.h>
 #include <ctype.h>
-#include <mp.h>
-#include <libsec.h>
 #include <bio.h>
+#include <ip.h>
 #include <ndb.h>
+#include <libsec.h>
 
 #define AUTHLOG "auth"