Browse Source

Plan 9 from Bell Labs 2003-01-29

David du Colombier 21 years ago
parent
commit
e500f23300

+ 12 - 10
dist/replica/plan9.db

@@ -4757,7 +4757,7 @@ sys/man/4/snap - 664 sys sys 1017251244 1833
 sys/man/4/srv - 664 sys sys 1039069766 4650
 sys/man/4/tapefs - 664 sys sys 944959699 1731
 sys/man/4/telco - 664 sys sys 1015024814 4359
-sys/man/4/u9fs - 664 sys sys 1019858384 4725
+sys/man/4/u9fs - 664 sys sys 1043769139 4748
 sys/man/4/upasfs - 664 sys sys 1034348505 6212
 sys/man/4/usb - 664 sys sys 1019828742 3272
 sys/man/4/usbd - 664 sys sys 1018386778 731
@@ -10168,8 +10168,8 @@ sys/src/cmd/unix/spin/readme - 664 sys sys 956275829 271
 sys/src/cmd/unix/spin/spin334.tar.gz - 664 sys sys 956275830 264112
 sys/src/cmd/unix/tcs.shar.Z - 664 sys sys 944961315 312440
 sys/src/cmd/unix/u9fs - 20000000775 sys sys 1015092354 0
-sys/src/cmd/unix/u9fs/auth9p1.c - 664 sys sys 1015092350 24106
 sys/src/cmd/unix/u9fs/authnone.c - 664 sys sys 1015092351 321
+sys/src/cmd/unix/u9fs/authp9any.c - 664 sys sys 1043768484 28109
 sys/src/cmd/unix/u9fs/authrhosts.c - 664 sys sys 1015092351 747
 sys/src/cmd/unix/u9fs/convD2M.c - 664 sys sys 1015092351 1326
 sys/src/cmd/unix/u9fs/convM2D.c - 664 sys sys 1015092351 1361
@@ -10179,21 +10179,22 @@ sys/src/cmd/unix/u9fs/cygwin.c - 664 sys sys 1039101050 893
 sys/src/cmd/unix/u9fs/dirmodeconv.c - 664 sys sys 1015092351 549
 sys/src/cmd/unix/u9fs/doprint.c - 664 sys sys 1015092351 8640
 sys/src/cmd/unix/u9fs/fcall.h - 664 sys sys 1015092352 2732
-sys/src/cmd/unix/u9fs/fcallconv.c - 664 sys sys 1015092352 5437
-sys/src/cmd/unix/u9fs/makefile - 664 sys sys 1039110816 1029
+sys/src/cmd/unix/u9fs/fcallconv.c - 664 sys sys 1043768485 5467
+sys/src/cmd/unix/u9fs/makefile - 664 sys sys 1043768488 1055
 sys/src/cmd/unix/u9fs/oldfcall.c - 664 sys sys 1015092352 7595
 sys/src/cmd/unix/u9fs/oldfcall.h - 664 sys sys 1015092352 914
-sys/src/cmd/unix/u9fs/plan9.h - 664 sys sys 1039110851 5306
+sys/src/cmd/unix/u9fs/plan9.h - 664 sys sys 1043768487 5327
 sys/src/cmd/unix/u9fs/print.c - 664 sys sys 1015092352 1109
 sys/src/cmd/unix/u9fs/random.c - 664 sys sys 1015092352 812
 sys/src/cmd/unix/u9fs/readn.c - 664 sys sys 1015092353 220
 sys/src/cmd/unix/u9fs/remotehost.c - 664 sys sys 1015092353 719
 sys/src/cmd/unix/u9fs/rune.c - 664 sys sys 1015092353 2160
+sys/src/cmd/unix/u9fs/safecpy.c - 664 sys sys 1043768486 212
 sys/src/cmd/unix/u9fs/strecpy.c - 664 sys sys 1015092353 193
 sys/src/cmd/unix/u9fs/sun-inttypes.h - 664 sys sys 1039110816 441
 sys/src/cmd/unix/u9fs/tokenize.c - 664 sys sys 1015092353 602
-sys/src/cmd/unix/u9fs/u9fs.c - 664 sys sys 1041139559 29984
-sys/src/cmd/unix/u9fs/u9fs.h - 664 sys sys 1015092354 377
+sys/src/cmd/unix/u9fs/u9fs.c - 664 sys sys 1043769157 30784
+sys/src/cmd/unix/u9fs/u9fs.h - 664 sys sys 1043768488 649
 sys/src/cmd/unix/u9fs/u9fsauth.h - 664 sys sys 1015092354 126
 sys/src/cmd/unix/u9fs/utfrune.c - 664 sys sys 1015092354 387
 sys/src/cmd/unmount.c - 664 sys sys 1014926615 442
@@ -10418,6 +10419,7 @@ sys/src/cmd/venti/mkfile - 664 sys sys 1039749273 1112
 sys/src/cmd/venti/mkxml - 775 sys sys 1019678879 1078
 sys/src/cmd/venti/mkxml.elems - 775 sys sys 1019678880 786
 sys/src/cmd/venti/part.c - 664 sys sys 1036389637 2532
+sys/src/cmd/venti/printarena.c - 664 sys sys 1043805294 2557
 sys/src/cmd/venti/rdarena.c - 664 sys sys 1036389639 1622
 sys/src/cmd/venti/read.c - 664 sys sys 1039743542 1724
 sys/src/cmd/venti/score.c - 664 sys sys 1019678880 611
@@ -10496,7 +10498,7 @@ sys/src/cmd/vnc/rre.c - 664 sys sys 1014925999 11036
 sys/src/cmd/vnc/screen.c - 664 sys sys 1041115189 7434
 sys/src/cmd/vnc/screen.h - 664 sys sys 1014926000 880
 sys/src/cmd/vnc/vnc.h - 664 sys sys 1034430143 2616
-sys/src/cmd/vnc/vncs.c - 664 sys sys 1041115188 20831
+sys/src/cmd/vnc/vncs.c - 664 sys sys 1043764390 21001
 sys/src/cmd/vnc/vncs.h - 664 sys sys 1034430144 501
 sys/src/cmd/vnc/vncv.c - 664 sys sys 1034430145 5154
 sys/src/cmd/vnc/vncv.h - 664 sys sys 1014926000 643
@@ -11664,12 +11666,12 @@ sys/src/libthread/debug.c - 664 sys sys 1014928157 832
 sys/src/libthread/example.c - 664 sys sys 1041440306 1402
 sys/src/libthread/exec.c - 664 sys sys 1014928157 1844
 sys/src/libthread/exit.c - 664 sys sys 1015701273 1209
-sys/src/libthread/id.c - 664 sys sys 1014928157 1121
+sys/src/libthread/id.c - 664 sys sys 1043788754 1330
 sys/src/libthread/iocall.c - 664 sys sys 1030537962 364
 sys/src/libthread/ioclose.c - 664 sys sys 1030537962 242
 sys/src/libthread/iodial.c - 664 sys sys 1030537988 438
 sys/src/libthread/ioopen.c - 664 sys sys 1030537962 314
-sys/src/libthread/ioproc.c - 664 sys sys 1030537962 928
+sys/src/libthread/ioproc.c - 664 sys sys 1043788755 928
 sys/src/libthread/ioread.c - 664 sys sys 1030537963 338
 sys/src/libthread/ioreadn.c - 664 sys sys 1030537988 342
 sys/src/libthread/iowrite.c - 664 sys sys 1030537963 342

+ 14 - 0
dist/replica/plan9.log

@@ -17111,3 +17111,17 @@
 1043681548 0 c sys/man/4/mntgen - 664 sys sys 1043680799 473
 1043683350 0 c sys/src/ape/lib/ap/plan9/wait.c - 664 sys sys 1043681702 1133
 1043697767 0 c sys/games/lib/fortunes - 664 sys sys 1043697004 238254
+1043766108 0 c sys/src/cmd/vnc/vncs.c - 664 sys sys 1043764390 21001
+1043768569 0 a sys/src/cmd/unix/u9fs/authp9any.c - 664 sys sys 1043768484 28109
+1043768569 1 c sys/src/cmd/unix/u9fs/fcallconv.c - 664 sys sys 1043768485 5467
+1043768569 2 c sys/src/cmd/unix/u9fs/makefile - 664 sys sys 1043768488 1055
+1043768569 3 c sys/src/cmd/unix/u9fs/plan9.h - 664 sys sys 1043768487 5327
+1043768569 4 a sys/src/cmd/unix/u9fs/safecpy.c - 664 sys sys 1043768486 212
+1043768569 5 c sys/src/cmd/unix/u9fs/u9fs.c - 664 sys sys 1043768544 30795
+1043768569 6 c sys/src/cmd/unix/u9fs/u9fs.h - 664 sys sys 1043768488 649
+1043769710 0 c sys/man/4/u9fs - 664 sys sys 1043769139 4748
+1043769710 1 c sys/src/cmd/unix/u9fs/u9fs.c - 664 sys sys 1043769157 30784
+1043769710 2 d sys/src/cmd/unix/u9fs/auth9p1.c - 664 sys sys 1015092350 0
+1043789528 0 c sys/src/libthread/id.c - 664 sys sys 1043788754 1330
+1043789528 1 c sys/src/libthread/ioproc.c - 664 sys sys 1043788755 928
+1043805300 0 a sys/src/cmd/venti/printarena.c - 664 sys sys 1043805294 2557

+ 6 - 4
sys/man/4/u9fs

@@ -81,7 +81,7 @@ should be
 .BR rhosts ,
 .BR none ,
 or
-.BR 9p1 .
+.BR p9any .
 The default is
 .BR rhosts ,
 which uses the
@@ -98,10 +98,12 @@ This is useful when
 .I u9fs
 is not invoked from
 .I inetd
-(see examples below).
+(see examples below, or
+.I srvssh
+in .IR srv (4)).
 Specifying
-.B 9p1
-uses the second and third edition Plan 9 authentication mechanisms.
+.B p9any
+uses the fourth edition Plan 9 authentication mechanisms.
 The file 
 .BR /etc/u9fs.key ,
 or

+ 246 - 54
sys/src/cmd/unix/u9fs/auth9p1.c → sys/src/cmd/unix/u9fs/authp9any.c

@@ -1,3 +1,8 @@
+/*
+ * 4th Edition p9any/p9sk1 authentication based on auth9p1.c
+ * Nigel Roles (nigel@9fs.org) 2003
+ */
+
 #include <plan9.h>
 #include <fcall.h>
 #include <u9fs.h>
@@ -14,6 +19,16 @@ enum
 	CHALLEN=	8		/* length of a challenge */
 };
 
+enum {
+	HaveProtos,
+	NeedProto,
+	NeedChal,
+	HaveTreq,
+	NeedTicket,
+	HaveAuth,
+	Established,
+};
+
 /* encryption numberings (anti-replay) */
 enum
 {
@@ -91,6 +106,8 @@ static	void	fp(long, long, char[8]);
 static	void	key_setup(char[DESKEYLEN], char[128]);
 static	void	block_cipher(char[128], char[8], int);
 
+extern int chatty9p;
+
 /*
  * destructively encrypt the buffer, which
  * must be at least 8 characters long.
@@ -491,6 +508,23 @@ key_setup(char key[DESKEYLEN], char *ek)
 #define	LONG(x)		VLONG(f->x)
 #define	STRING(x,n)	memmove(p, f->x, n); p += n
 
+static int
+convTR2M(Ticketreq *f, char *ap)
+{
+	int n;
+	uchar *p;
+
+	p = (uchar*)ap;
+	CHAR(type);
+	STRING(authid, NAMELEN);
+	STRING(authdom, DOMLEN);
+	STRING(chal, CHALLEN);
+	STRING(hostid, NAMELEN);
+	STRING(uid, NAMELEN);
+	n = p - (uchar*)ap;
+	return n;
+}
+
 static int
 convT2M(Ticket *f, char *ap, char *key)
 {
@@ -608,14 +642,14 @@ passtokey(char *key, char *p)
 static char authkey[DESKEYLEN];
 static char *authid;
 static char *authdom;
-static char cchal[CHALLEN];
-static char schal[CHALLEN];
+static char *haveprotosmsg;
+static char *needprotomsg;
 
 static void
-a9p1init(void)
+p9anyinit(void)
 {
 	int n, fd;
-	static char abuf[200];
+	char abuf[200];
 	char *af, *f[4];
 
 	af = autharg;
@@ -627,77 +661,235 @@ a9p1init(void)
 
 	if((n = readn(fd, abuf, sizeof(abuf)-1)) < 0)
 		sysfatal("can't read key file '%s'", af);
+	if (n > 0 && abuf[n - 1] == '\n')
+		n--;
 	abuf[n] = '\0';
 
 	if(getfields(abuf, f, nelem(f), 0, "\n") != 3)
 		sysfatal("key file '%s' not exactly 3 lines", af);
 
 	passtokey(authkey, f[0]);
-	authid = f[1];
-	authdom = f[2];
+	authid = strdup(f[1]);
+	authdom = strdup(f[2]);
+	haveprotosmsg = malloc(strlen("p9sk1") + 1 + strlen(authdom) + 1);
+	sprint(haveprotosmsg, "p9sk1@%s", authdom);
+	needprotomsg = malloc(strlen("p9sk1") + 1 + strlen(authdom) + 1);
+	sprint(needprotomsg, "p9sk1 %s", authdom);
 }
 
-static int
-a9p1session(Fcall *rx, Fcall *tx)
+typedef struct AuthSession {
+	int state;
+	char *uname;
+	char *aname;
+	char cchal[CHALLEN];
+	Ticketreq tr;
+	Ticket t;
+} AuthSession;
+
+static char*
+p9anyauth(Fcall *rx, Fcall *tx)
+{
+	AuthSession *sp;
+	int result;
+	Fid *f;
+	char *ep;
+
+	sp = malloc(sizeof(AuthSession));
+	f = newauthfid(rx->afid, sp, &ep);
+	if (f == nil) {
+		free(sp);
+		return ep;
+	}
+	if (chatty9p)
+		fprint(2, "p9anyauth: afid %d\n", rx->afid);
+	sp->state = HaveProtos;
+	sp->uname = strdup(rx->uname);
+	sp->aname = strdup(rx->aname);
+	tx->aqid.type = QTAUTH;
+	tx->aqid.path = 1;
+	tx->aqid.vers = 0;
+	return nil;
+}
+
+static char *
+p9anyattach(Fcall *rx, Fcall *tx)
 {
-	if(rx->nchal != CHALLEN)
-		return -1;
-
-	memmove(cchal, rx->chal, CHALLEN);
-	randombytes((uchar*)schal, CHALLEN);
-	memset(tx->chal, 0, CHALLEN+NAMELEN+DOMLEN);
-	memmove(tx->chal, schal, CHALLEN);
-	tx->nchal = CHALLEN;
-	tx->authid = authid;
-	tx->authdom = authdom;
-	return 0;
+	AuthSession *sp;
+	Fid *f;
+	char *ep;
+
+	f = oldauthfid(rx->afid, (void **)&sp, &ep);
+	if (f == nil)
+		return ep;
+	if (chatty9p)
+		fprint(2, "p9anyattach: afid %d state %d\n", rx->afid, sp->state);
+	if (sp->state == Established && strcmp(rx->uname, sp->uname) == 0
+		&& strcmp(rx->aname, sp->aname) == 0)
+		return nil;
+	return "authentication failed";
 }
 
 static int
-a9p1attach(Fcall *rx, Fcall *tx)
+readstr(Fcall *rx, Fcall *tx, char *s, int len)
 {
-	static Ticket t;
-	Authenticator a;
+	if (rx->offset >= len)
+		return 0;
+	tx->count = len - rx->offset;
+	if (tx->count > rx->count)
+		tx->count = rx->count;
+	memcpy(tx->data, s + rx->offset, tx->count);
+	return tx->count;
+}
 
-	if(rx->nauth != TICKETLEN+AUTHENTLEN){
-		fprint(2, "bad length in attach\n");
-		return -1;
+static char *
+p9anyread(Fcall *rx, Fcall *tx)
+{
+	AuthSession *sp;
+	char *ep;
+	char buf[100];
+
+	Fid *f;
+	f = oldauthfid(rx->afid, (void **)&sp, &ep);
+	if (f == nil)
+		return ep;
+	if (chatty9p)
+		fprint(2, "p9anyread: afid %d state %d\n", rx->fid, sp->state);
+	switch (sp->state) {
+	case HaveProtos:
+		readstr(rx, tx, haveprotosmsg, strlen(haveprotosmsg) + 1);
+		if (rx->offset + tx->count == strlen(haveprotosmsg) + 1)
+			sp->state = NeedProto;
+		return nil;
+	case HaveTreq:
+		if (rx->count != TICKREQLEN)
+			goto botch;
+		convTR2M(&sp->tr, tx->data);
+		tx->count = TICKREQLEN;
+		sp->state = NeedTicket;
+		return nil;
+	case HaveAuth: {
+		Authenticator a;
+		if (rx->count != AUTHENTLEN)
+			goto botch;
+		a.num = AuthAs;
+		memmove(a.chal, sp->cchal, CHALLEN);
+		a.id = 0;
+		convA2M(&a, (char*)tx->data, sp->t.key);
+		memset(sp->t.key, 0, sizeof(sp->t.key));
+		tx->count = rx->count;
+		sp->state = Established;
+		return nil;
 	}
+	default:
+	botch:
+		return "protocol botch";
+	}
+}
 
-	convM2T((char*)rx->auth, &t, authkey);
-	if(t.num != AuthTs){
-		fprint(2, "bad AuthTs in attach\n");
-		return -1;
+static char *
+p9anywrite(Fcall *rx, Fcall *tx)
+{
+	AuthSession *sp;
+	char *ep;
+
+	Fid *f;
+
+	f = oldauthfid(rx->afid, (void **)&sp, &ep);
+	if (f == nil)
+		return ep;
+	if (chatty9p)
+		fprint(2, "p9anywrite: afid %d state %d\n", rx->fid, sp->state);
+	switch (sp->state) {
+	case NeedProto:
+		if (rx->count != strlen(needprotomsg) + 1)
+			return "protocol response wrong length";
+		if (memcmp(rx->data, needprotomsg, rx->count) != 0)
+			return "unacceptable protocol";
+		sp->state = NeedChal;
+		tx->count = rx->count;
+		return nil;
+	case NeedChal:
+		if (rx->count != CHALLEN)
+			goto botch;
+		memmove(sp->cchal, rx->data, CHALLEN);
+		sp->tr.type = AuthTreq;
+		safecpy(sp->tr.authid, authid, sizeof(sp->tr.authid));
+		safecpy(sp->tr.authdom, authdom, sizeof(sp->tr.authdom));
+		randombytes((uchar *)sp->tr.chal, CHALLEN);
+		safecpy(sp->tr.hostid, "", sizeof(sp->tr.hostid));
+		safecpy(sp->tr.uid, "", sizeof(sp->tr.uid));
+		tx->count = rx->count;
+		sp->state = HaveTreq;
+		return nil;
+	case NeedTicket: {
+		Authenticator a;
+
+		if (rx->count != TICKETLEN + AUTHENTLEN) {
+			fprint(2, "bad length in attach");
+			goto botch;
+		}
+		convM2T((char*)rx->data, &sp->t, authkey);
+		if (sp->t.num != AuthTs) {
+			fprint(2, "bad AuthTs in attach\n");
+			goto botch;
+		}
+		if (memcmp(sp->t.chal, sp->tr.chal, CHALLEN) != 0) {
+			fprint(2, "bad challenge in attach\n");
+			goto botch;
+		}
+		convM2A((char*)rx->data + TICKETLEN, &a, sp->t.key);
+		if (a.num != AuthAc) {
+			fprint(2, "bad AuthAs in attach\n");
+			goto botch;
+		}
+		if(memcmp(a.chal, sp->tr.chal, CHALLEN) != 0) {
+			fprint(2, "bad challenge in attach 2\n");
+			goto botch;
+		}
+		sp->state = HaveAuth;
+		tx->count = rx->count;
+		return nil;
 	}
-	if(memcmp(t.chal, schal, CHALLEN) != 0){
-		fprint(2, "bad challenge in attach\n");
-		return -1;
+	default:
+	botch:
+		return "protocol botch";
 	}
+}
 
-	if(strcmp(t.cuid, rx->uname) != 0){
-		fprint(2, "bad uid %s %s\n", t.cuid, rx->uname);
-		return -1;
+static void
+safefree(char *p)
+{
+	if (p) {
+		memset(p, 0, strlen(p));
+		free(p);
 	}
+}
 
-	rx->uname = t.suid;
-
-	convM2A((char*)rx->auth+TICKETLEN, &a, t.key);
-	if(a.num != AuthAc)
-		return -1;
-	if(memcmp(a.chal, schal, CHALLEN) != 0)
-		return -1;
-
-	a.num = AuthAs;
-	memmove(a.chal, cchal, CHALLEN);
-	convA2M(&a, (char*)tx->rauth, t.key);
-	memset(t.key, 0, sizeof t.key);
-	tx->nrauth = AUTHENTLEN;
-	return 0;
+static char *
+p9anyclunk(Fcall *rx, Fcall *tx)
+{
+	Fid *f;
+	AuthSession *sp;
+	char *ep;
+
+	f = oldauthfid(rx->afid, (void **)&sp, &ep);
+	if (f == nil)
+		return ep;
+	if (chatty9p)
+		fprint(2, "p9anyclunk: afid %d\n", rx->fid);
+	safefree(sp->uname);
+	safefree(sp->aname);
+	memset(sp, 0, sizeof(sp));
+	free(sp);
+	return nil;
 }
 
-Auth auth9p1 = {
-	"9p1",
-	a9p1session,
-	a9p1attach,
-	a9p1init,
+Auth authp9any = {
+	"p9any",
+	p9anyauth,
+	p9anyattach,
+	p9anyinit,
+	p9anyread,
+	p9anywrite,
+	p9anyclunk,
 };

+ 2 - 0
sys/src/cmd/unix/u9fs/fcallconv.c

@@ -159,6 +159,8 @@ qidtype(char *s, uchar t)
 		*p++ = 'l';
 	if(t & QTMOUNT)
 		*p++ = 'm';
+	if(t & QTAUTH)
+		*p++ = 'A';
 	*p = '\0';
 	return s;
 }

+ 2 - 0
sys/src/cmd/unix/u9fs/makefile

@@ -23,6 +23,7 @@ LDTAIL=
 OFILES=\
 	authnone.o\
 	authrhosts.o\
+	authp9any.o\
 	convD2M.o\
 	convM2D.o\
 	convM2S.o\
@@ -36,6 +37,7 @@ OFILES=\
 	readn.o\
 	remotehost.o\
 	rune.o\
+	safecpy.o\
 	strecpy.o\
 	tokenize.o\
 	u9fs.o\

+ 1 - 0
sys/src/cmd/unix/u9fs/plan9.h

@@ -136,6 +136,7 @@ extern	int	fltconv(va_list*, Fconv*);
 #define QTAPPEND	0x40		/* type bit for append only files */
 #define QTEXCL		0x20		/* type bit for exclusive use files */
 #define QTMOUNT		0x10		/* type bit for mounted channel */
+#define QTAUTH		0x08
 #define QTFILE		0x00		/* plain file */
 
 /* bits in Dir.mode */

+ 12 - 0
sys/src/cmd/unix/u9fs/safecpy.c

@@ -0,0 +1,12 @@
+#include <stdio.h>
+
+void
+safecpy(char *to, char *from, int tolen)
+{
+	int fromlen;
+	memset(to, 0, tolen);
+	fromlen = from ? strlen(from) : 0;
+	if (fromlen > tolen)
+		fromlen = tolen;
+	memcpy(to, from, fromlen);
+}

+ 71 - 12
sys/src/cmd/unix/u9fs/u9fs.c

@@ -49,7 +49,6 @@ struct User {
 	User *next;
 };
 
-typedef struct Fid Fid;
 struct Fid {
 	int fid;
 	char *path;
@@ -62,6 +61,8 @@ struct Fid {
 	struct dirent *dirent;
 	Fid *next;
 	Fid *prev;
+	int auth;
+	void *authmagic;
 };
 
 void*	emalloc(size_t);
@@ -93,6 +94,7 @@ User*	uid2user(int);
 User*	gid2user(int);
 
 Fid*	newfid(int, char**);
+Fid*	oldfidex(int, int, char**);
 Fid*	oldfid(int, char**);
 int	fidstat(Fid*, char**);
 void	freefid(Fid*);
@@ -147,6 +149,7 @@ User*	none;
 
 Auth *authmethods[] = {	/* first is default */
 	&authrhosts,
+	&authp9any,
 	&authnone,
 };
 
@@ -656,11 +659,19 @@ rread(Fcall *rx, Fcall *tx)
 		return;
 	}
 
-	if((fid = oldfid(rx->fid, &e)) == nil){
+	if((fid = oldfidex(rx->fid, -1, &e)) == nil){
 		seterror(tx, e);
 		return;
 	}
 
+	if (fid->auth) {
+		char *e;
+		e = auth->read(rx, tx);
+		if (e)
+			seterror(tx, e);
+		return;
+	}
+
 	if(fid->omode == -1 || (fid->omode&3) == OWRITE){
 		seterror(tx, Ebadusefid);
 		return;
@@ -727,11 +738,19 @@ rwrite(Fcall *rx, Fcall *tx)
 		return;
 	}
 
-	if((fid = oldfid(rx->fid, &e)) == nil){
+	if((fid = oldfidex(rx->fid, -1, &e)) == nil){
 		seterror(tx, e);
 		return;
 	}
 
+	if (fid->auth) {
+		char *e;
+		e = auth->write(rx, tx);
+		if (e)
+			seterror(tx, e);
+		return;
+	}
+
 	if(fid->omode == -1 || (fid->omode&3) == OREAD || (fid->omode&3) == OEXEC){
 		seterror(tx, Ebadusefid);
 		return;
@@ -750,11 +769,20 @@ rclunk(Fcall *rx, Fcall *tx)
 	char *e;
 	Fid *fid;
 
-	if((fid = oldfid(rx->fid, &e)) == nil){
+	if((fid = oldfidex(rx->fid, -1, &e)) == nil){
 		seterror(tx, e);
 		return;
 	}
-	if(fid->omode != -1 && fid->omode&ORCLOSE)
+	if (fid->auth) {
+		if (auth->clunk) {
+			e = (*auth->clunk)(rx, tx);
+			if (e) {
+				seterror(tx, e);
+				return;
+			}
+		}
+	}
+	else if(fid->omode != -1 && fid->omode&ORCLOSE)
 		remove(fid->path);
 	freefid(fid);
 }
@@ -1127,11 +1155,6 @@ estrpath(char *p, char *q)
 	return r;
 }
 
-Fid *newfid(int, char**);
-Fid *oldfid(int, char**);
-int fidstat(Fid*, char**);
-void freefid(Fid*);
-
 Fid *fidtab[1];
 
 Fid*
@@ -1167,7 +1190,19 @@ newfid(int fid, char **ep)
 }
 
 Fid*
-oldfid(int fid, char **ep)
+newauthfid(int fid, void *magic, char **ep)
+{
+	Fid *af;
+	af = newfid(fid, ep);
+	if (af == nil)
+		return nil;
+	af->auth = 1;
+	af->authmagic = magic;
+	return af;
+}
+
+Fid*
+oldfidex(int fid, int auth, char **ep)
 {
 	Fid *f;
 
@@ -1176,12 +1211,36 @@ oldfid(int fid, char **ep)
 		return nil;
 	}
 
-	if(userchange(f->u, ep) < 0)
+	if (auth != -1 && f->auth != auth) {
+		*ep = Ebadfid;
 		return nil;
+	}
+
+	if (!f->auth) {
+		if(userchange(f->u, ep) < 0)
+			return nil;
+	}
 
 	return f;
 }
 
+Fid*
+oldfid(int fid, char **ep)
+{
+	return oldfidex(fid, 0, ep);
+}
+
+Fid*
+oldauthfid(int fid, void **magic, char **ep)
+{
+	Fid *af;
+	af = oldfidex(fid, 1, ep);
+	if (af == nil)
+		return nil;
+	*magic = af->authmagic;
+	return af;
+}
+
 void
 freefid(Fid *f)
 {

+ 10 - 1
sys/src/cmd/unix/u9fs/u9fs.h

@@ -5,17 +5,26 @@ struct Auth {
 	char* (*auth)(Fcall*, Fcall*);
 	char* (*attach)(Fcall*, Fcall*);
 	void (*init)(void);
+	char* (*read)(Fcall*, Fcall*);
+	char* (*write)(Fcall*, Fcall*);
+	char* (*clunk)(Fcall*, Fcall*);
 };
 
 extern char remotehostname[];
 extern char Eauth[];
 extern char *autharg;
 
+extern Auth authp9any;
 extern Auth authrhosts;
-extern Auth auth9p1;
 extern Auth authnone;
 
 extern ulong truerand(void);
 extern void randombytes(uchar*, uint);
 
 extern ulong  msize;
+
+typedef struct Fid Fid;
+Fid *newauthfid(int fid, void *magic, char **ep);
+Fid *oldauthfid(int fid, void **magic, char **ep);
+
+void safecpy(char *to, char *from, int len);

+ 132 - 0
sys/src/cmd/venti/printarena.c

@@ -0,0 +1,132 @@
+#include "stdinc.h"
+#include "dat.h"
+#include "fns.h"
+
+int readonly = 1;	/* for part.c */
+
+void
+usage(void)
+{
+	fprint(2, "usage: printarena arenafile [offset]\n");
+	exits("usage");
+}
+
+static void
+rdArena(Arena *arena, u64int offset)
+{
+	u64int a, aa, e;
+	u32int magic;
+	Clump cl;
+	uchar score[VtScoreSize];
+	ZBlock *lump;
+
+	printArena(2, arena);
+
+	a = arena->base;
+	e = arena->base + arena->size;
+	if(offset != ~(u64int)0) {
+		if(offset >= e-a)
+			vtFatal("bad offset %llud >= %llud\n",
+				offset, e-a);
+		aa = offset;
+	} else
+		aa = 0;
+
+	for(; aa < e; aa += ClumpSize+cl.info.size) {
+		magic = clumpMagic(arena, aa);
+		if(magic == ClumpFreeMagic)
+			break;
+		if(magic != ClumpMagic) {
+			fprint(2, "illegal clump magic number %#8.8ux offset %llud\n",
+				magic, aa);
+			break;
+		}
+		lump = loadClump(arena, aa, 0, &cl, score, 0);
+		if(lump == nil) {
+			fprint(2, "clump %llud failed to read: %R\n", aa);
+			break;
+		}
+		if(cl.info.type != VtTypeCorrupt) {
+			scoreMem(score, lump->data, cl.info.uncsize);
+			if(!scoreEq(cl.info.score, score)) {
+				fprint(2, "clump %llud has mismatched score\n", aa);
+				break;
+			}
+			if(!vtTypeValid(cl.info.type)) {
+				fprint(2, "clump %llud has bad type %d\n", aa, cl.info.type);
+				break;
+			}
+		}
+		print("%V %d\n", score, cl.info.type);
+		freeZBlock(lump);
+	}
+	print("end offset %llud\n", aa);
+}
+
+int
+main(int argc, char *argv[])
+{
+	char *file;
+	Arena *arena;
+	u64int offset, aoffset;
+	Part *part;
+	Dir *d;
+	uchar buf[8192];
+	ArenaHead head;
+
+	aoffset = 0;
+	ARGBEGIN{
+	case 'o':
+		aoffset = strtoull(EARGF(usage()), 0, 0);
+		break;
+	default:
+		usage();
+		break;
+	}ARGEND
+
+	offset = ~(u64int)0;
+	switch(argc) {
+	default:
+		usage();
+	case 2:
+		offset = strtoull(argv[1], 0, 0);
+		/* fall through */
+	case 1:
+		file = argv[0];
+	}
+
+	vtAttach();
+
+	fmtinstall('V', vtScoreFmt);
+	fmtinstall('R', vtErrFmt);
+
+	statsInit();
+
+	if((d = dirstat(file)) == nil)
+		vtFatal("can't stat file %s: %r", file);
+
+	part = initPart(file, 0);
+	if(part == nil)
+		vtFatal("can't open file %s: %R", file);
+	if(!readPart(part, aoffset, buf, sizeof buf))
+		vtFatal("can't read file %s: %R", file);
+
+	if(!unpackArenaHead(&head, buf))
+		vtFatal("corrupted arena header: %R");
+
+	if(aoffset+head.size > d->length)
+		vtFatal("arena is truncated: want %llud bytes have %llud\n",
+			head.size, d->length);
+
+	partBlockSize(part, head.blockSize);
+	initDCache(8 * MaxDiskBlock);
+
+	arena = initArena(part, aoffset, head.size, head.blockSize);
+	if(arena == nil)
+		vtFatal("initArena: %R");
+
+	rdArena(arena, offset);
+	vtDetach();
+	exits(0);
+	return 0;
+}

+ 16 - 1
sys/src/cmd/vnc/vncs.c

@@ -541,6 +541,20 @@ vncnegotiate_srv(Vnc *v)
 	return 0;
 }
 
+static int
+encoding_ok(int x)
+{
+	switch(x) {
+	default:
+		return 0;
+	case EncRaw:
+	case EncRre:
+	case EncCorre:
+	case EncHextile:
+		return 1;
+	}
+}
+
 static void
 vnc_srv(Vncs *v, int dfd, int cfd)
 {
@@ -640,7 +654,8 @@ vnc_srv(Vncs *v, int dfd, int cfd)
 					v->usecopyrect = 1;
 				else if (x == EncMouseWarp)
 					v->canwarp = 1;
-				else if(v->preferredencoding == -1)
+				else if(v->preferredencoding == -1 &&
+					encoding_ok(x))
 					v->preferredencoding = x;
 			}
 			if(v->preferredencoding == -1)

+ 12 - 1
sys/src/libthread/id.c

@@ -57,12 +57,23 @@ threadgetgrp(void)
 void
 threadsetname(char *name)
 {
+	int fd;
+	char buf[40];
+	Proc *p;
 	Thread *t;
 
-	t = _threadgetproc()->thread;
+	p = _threadgetproc();
+	t = p->thread;
 	if (t->cmdname)
 		free(t->cmdname);
 	t->cmdname = strdup(name);
+	if(p->nthreads == 1){
+		snprint(buf, sizeof buf, "#p/%d/args", getpid());
+		if((fd = open(buf, OWRITE)) >= 0){
+			write(fd, name, strlen(name));
+			close(fd);
+		}
+	}
 }
 
 char*

+ 1 - 1
sys/src/libthread/ioproc.c

@@ -15,7 +15,7 @@ iointerrupt(Ioproc *io)
 {
 	if(!io->inuse)
 		return;
-	postnote(PNPROC, io->pid, "interrupt");
+	postnote(PNPROC, io->pid, "threadint");
 }
 
 static void