Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/port/auth.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## diffname port/auth.c 1993/0330
## diff -e /dev/null /n/bootesdump/1993/0330/sys/src/9/port/auth.c
0a
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"
#include	"../port/error.h"

typedef struct Crypt	Crypt;
struct Crypt
{
	Crypt		*next;
	Ticket		t;
	Authenticator	a;
	char		tbuf[TICKETLEN];	/* remote ticket */
};

typedef struct Session	Session;
struct Session
{
	Lock;
	Crypt	*cache;			/* cache of tickets */
	char	cchal[CHALLEN];		/* client challenge */
	char	schal[CHALLEN];		/* server challenge */
	char	authid[NAMELEN];	/* server encryption uid */
	char	authdom[DOMLEN];	/* server encryption domain */
	ulong	cid;			/* challenge id */
};

struct
{
	Lock;
	Crypt		*free;
} cryptalloc;

char	eve[NAMELEN] = "bootes";
char	evekey[DESKEYLEN];
char	hostdomain[DOMLEN];

/*
 *  return true if current user is eve
 */
int
iseve(void)
{
	return strcmp(eve, u->p->user) == 0;
}

/*
 * crypt entries are allocated from a pool rather than allocated using malloc so
 * the memory can be protected from reading by devproc. The base and top of the
 * crypt arena is stored in palloc for devproc.
 */
Crypt*
newcrypt(void)
{
	Crypt *c;

	lock(&cryptalloc);
	if(cryptalloc.free) {
		c = cryptalloc.free;
		cryptalloc.free = c->next;
		unlock(&cryptalloc);
		memset(c, 0, sizeof(Crypt));
		return c;
	}

	cryptalloc.free = xalloc(sizeof(Crypt)*conf.nproc);
	if(cryptalloc.free == 0)
		panic("newcrypt");

	for(c = cryptalloc.free; c < cryptalloc.free+conf.nproc-1; c++)
		c->next = c+1;

	palloc.cmembase = (ulong)cryptalloc.free;
	palloc.cmemtop = palloc.cmembase+(sizeof(Crypt)*conf.nproc);
	unlock(&cryptalloc);
	return newcrypt();
}

void
freecrypt(Crypt *c)
{
	lock(&cryptalloc);
	c->next = cryptalloc.free;
	cryptalloc.free = c;
	unlock(&cryptalloc);
}

/*
 *  return the info received in the session message on this channel.
 *  if no session message has been exchanged, do it.
 */
long
sysfsession(ulong *arg)
{
	int i, n;
	Chan *c;
	Fcall *f;
	char *buf;
	Crypt *cp;
	Session *s;
	Ticketreq tr;

	validaddr(arg[1], TICKREQLEN, 1);
	f = malloc(sizeof(Fcall));
	if(f == 0)
		error(Enomem);
	buf = malloc(MAXMSG);
	if(buf == 0){
		free(f);
		error(Enomem);
	}
	c = fdtochan(arg[0], OWRITE, 0, 1);
	s = 0;
	if(waserror()) {
		if(s)
			free(s);
		close(c);
		free(buf);
		free(f);
		nexterror();
	}
	s = c->session;
	if(s == 0){
		/*  exchange a session message with the server */
		s = malloc(sizeof(Session));
		if(s == 0)
			error(Enomem);
		memset(s, 0, sizeof(Session));
		for(i = 0; i < CHALLEN; i++)
			s->cchal[i] = nrand(256);
		f->type = Tsession;
		memmove(f->chal, s->cchal, CHALLEN);
		n = convS2M(f, buf);
		if((*devtab[c->type].write)(c, buf, n, 0) != n)
			error(Emountrpc);
		n = (*devtab[c->type].read)(c, buf, MAXMSG, 0);
		if(convM2S(buf, f, n) == 0)
			error(Emountrpc);
		if(f->type == Rsession){
			memmove(s->schal, f->chal, CHALLEN);
			memmove(s->authid, f->authid, NAMELEN);
			memmove(s->authdom, f->authdom, DOMLEN);
		}
		s->cid = 0;
		c->session = s;
	}

	/* 
	 *  If server requires no ticket, or user is "none", or a ticket
	 *  is already cached, zero the request type
	 */
	tr.type = AuthTreq;
	if(strcmp(u->p->user, "none") == 0 || c->session->authid[0] == 0)
		tr.type = 0;
	else for(cp = s->cache; cp; cp = cp->next)
		if(strcmp(cp->t.cuid, u->p->user) == 0){
			tr.type = 0;
			break;
		}

	/*  create ticket request */
	memmove(tr.chal, c->session->schal, CHALLEN);
	memmove(tr.authid, c->session->authid, NAMELEN);
	memmove(tr.authdom, c->session->authdom, DOMLEN);
	memmove(tr.uid, u->p->user, NAMELEN);
	memmove(tr.hostid, eve, NAMELEN);
	convTR2M(&tr, (char*)arg[1]);

	poperror();
	close(c);
	free(buf);
	free(f);
	return 0;
}

/*
 *  attach tickets to a session
 */
long
sysfauth(ulong *arg)
{
	Chan *c;
	char *ta;
	Session *s;
	Crypt *cp, *ncp, **l;
	char tbuf[2*TICKETLEN];

	validaddr(arg[1], 2*TICKETLEN, 0);
	c = fdtochan(arg[0], OWRITE, 0, 1);
	s = c->session;
	if(s == 0)
		error("fauth must follow fsession");
	cp = newcrypt();
	if(waserror()){
		freecrypt(cp);
		nexterror();
	}

	/*  ticket supplied, use it */
	ta = (char*)arg[1];
	memmove(tbuf, ta, 2*TICKETLEN);
	convM2T(tbuf, &cp->t, evekey);
	if(cp->t.num != AuthTc)
		error("bad AuthTc in ticket");
	if(strncmp(u->p->user, cp->t.cuid, NAMELEN) != 0)
		error("bad uid in ticket");
	if(memcmp(cp->t.chal, s->schal, CHALLEN) != 0)
		error("bad chal in ticket");
	memmove(cp->tbuf, tbuf+TICKETLEN, TICKETLEN);

	/* string onto local list, replace old version */
	lock(s);
	l = &s->cache;
	for(ncp = s->cache; ncp; ncp = *l){
		if(strcmp(ncp->t.cuid, u->p->user) == 0){
			*l = ncp->next;
			freecrypt(ncp);
			break;
		}
		l = &ncp->next;
	}
	cp->next = s->cache;
	s->cache = cp;
	unlock(s);
	poperror();
	return 0;
}

/*
 *  free a session created by fsession
 */
void
freesession(Session *s)
{
	Crypt *cp;

	for(cp = s->cache; cp; cp = cp->next)
		freecrypt(cp);
	free(s);
}

/*
 *  called by mattach() to fill in the Tattach message
 */
ulong
authrequest(Session *s, Fcall *f)
{
	Crypt *cp;
	ulong id, dofree;

	/* no authentication if user is "none" or if no ticket required by remote */
	if(s == 0 || s->authid[0] == 0 || strcmp(u->p->user, "none") == 0){
		memset(f->ticket, 0, TICKETLEN);
		memset(f->auth, 0, AUTHENTLEN);
		return 0;
	}

	/* look for ticket in cache */
	dofree = 0;
	for(cp = s->cache; cp; cp = cp->next)
		if(strcmp(cp->t.cuid, u->p->user) == 0)
			break;
	if(cp == 0){
		/*
		 *  create a ticket using hostkey, this solves the
		 *  chicken and egg problem
		 */
		cp = newcrypt();
		cp->t.num = AuthTs;
		memmove(cp->t.chal, s->schal, CHALLEN);
		memmove(cp->t.cuid, u->p->user, NAMELEN);
		memmove(cp->t.suid, u->p->user, NAMELEN);
		memmove(cp->t.key, evekey, DESKEYLEN);
		convT2M(&cp->t, f->ticket, evekey);
		dofree = 1;
	} else
		memmove(f->ticket, cp->tbuf, TICKETLEN);
	lock(s);
	id = s->cid++;
	unlock(s);

	/* create an authenticator */
	memmove(cp->a.chal, s->schal, CHALLEN);
	cp->a.num = AuthAc;
	cp->a.id = id;
	convA2M(&cp->a, f->auth, cp->t.key);
	if(dofree)
		freecrypt(cp);
	return id;
}

/*
 *  called by mattach() to check the Rattach message
 */
void
authreply(Session *s, ulong id, Fcall *f)
{
	Crypt *cp;

	if(s == 0)
		return;

	for(cp = s->cache; cp; cp = cp->next)
		if(strcmp(cp->t.cuid, u->p->user) == 0)
			break;

	/* we're getting around authentication */
	if(s == 0 || cp == 0 || s->authid[0] == 0 || strcmp(u->p->user, "none") == 0)
		return;

	convM2A(f->rauth, &cp->a, cp->t.key);
	if(cp->a.num != AuthAs){
		print("bad encryption type\n");
		error("server lies");
	}
	if(memcmp(cp->a.chal, s->cchal, sizeof(cp->a.chal))){
		print("bad returned challenge\n");
		error("server lies");
	}	
	if(cp->a.id != id){
		print("bad returned id\n");
		error("server lies");
	}
}

/*
 *  called by devcons() for #c/authenticate
 *
 *  The protocol is
 *	1) read ticket request from #c/authenticate
 *	2) write ticket to #c/authenticate. if it matchs the challenge the
 *	  user is changed to the suid field of the ticket
 *	3) read authenticator (to confirm this is the server advertised)
 */
long
authread(Chan *c, char *a, int n)
{
	Crypt *cp;
	int i;
	Ticketreq tr;

	if(c->aux == 0){
		/*
		 *  first read returns a ticket request
		 */
		if(n != TICKREQLEN)
			error(Ebadarg);
		c->aux = newcrypt();
		cp = c->aux;
		memset(&tr, 0, sizeof(tr));
		tr.type = AuthTreq;
		strcpy(tr.hostid, eve);
		strcpy(tr.authid, eve);
		strcpy(tr.authdom, hostdomain);
		strcpy(tr.uid, u->p->user);
		for(i = 0; i < CHALLEN; i++)
			tr.chal[i] = nrand(256);
		memmove(cp->a.chal, tr.chal, CHALLEN);
		convTR2M(&tr, a);
	} else {
		/*
		 *  subsequent read returns an authenticator
		 */
		if(n != AUTHENTLEN)
			error(Ebadarg);
		cp = c->aux;
		cp->a.num = AuthAs;
		memmove(cp->a.chal, cp->t.chal, CHALLEN);
		cp->a.id = 0;
		convA2M(&cp->a, a, cp->t.key);
		freecrypt(cp);
		c->aux = 0;
	}
	return n;
}

long
authwrite(Chan *c, char *a, int n)
{
	Crypt *cp;

	if(n != TICKETLEN)
		error(Ebadarg);
	if(c->aux == 0)
		error(Ebadarg);
	cp = c->aux;
	convM2T(a, &cp->t, evekey);
	if(cp->t.num != AuthTs || memcmp(cp->a.chal, cp->t.chal, CHALLEN))
		error(Eperm);
	memmove(u->p->user, cp->t.suid, NAMELEN);
	return n;
}

/*
 *  called by devcons() for #c/authcheck
 *
 *  a write of a ticket+authenticator succeeds if they match
 */
long
authcheck(Chan *c, char *a, int n)
{
	Crypt *cp;

	if(n != TICKETLEN+AUTHENTLEN)
		error(Ebadarg);
	if(c->aux == 0)
		c->aux = newcrypt();
	cp = c->aux;
	convM2T(a, &cp->t, evekey);
	if(cp->t.num != AuthTc || strcmp(u->p->user, cp->t.cuid))
		error(Ebadarg);
	convM2A(a+TICKETLEN, &cp->a, cp->t.key);
	if(cp->a.num != AuthAs || memcmp(cp->t.chal, cp->a.chal, CHALLEN))
		error(Eperm);
	return n;
}

void
authclose(Chan *c)
{
	if(c->aux)
		freecrypt(c->aux);
	c->aux = 0;
}

/*
 *  called by devcons() for key device
 */
long
keyread(char *a, int n, long offset)
{
	if(n<DESKEYLEN || offset != 0)
		error(Ebadarg);
	if(!iseve())
		error(Eperm);
	memmove(a, evekey, DESKEYLEN);
	return DESKEYLEN;
}

long
keywrite(char *a, int n)
{
	if(n != DESKEYLEN)
		error(Ebadarg);
	if(!iseve())
		error(Eperm);
	memmove(evekey, a, DESKEYLEN);
	return DESKEYLEN;
}

/*
 *  called by devcons() for user device
 *
 *  anyone can become none
 */
long
userwrite(char *a, int n)
{
	if(n >= NAMELEN)
		error(Ebadarg);
	if(strcmp(a, "none") != 0)
		error(Eperm);
	memset(u->p->user, 0, NAMELEN);
	strcpy(u->p->user, "none");
	return n;
}

/*
 *  called by devcons() for host owner/domain
 *
 *  writing hostowner also sets user
 */
long
hostownerwrite(char *a, int n)
{
	char buf[NAMELEN];

	if(!iseve())
		error(Eperm);
	if(n >= NAMELEN)
		error(Ebadarg);
	memset(buf, 0, NAMELEN);
	strncpy(buf, a, n);
	if(buf[0] == 0)
		error(Ebadarg);
	memmove(eve, buf, NAMELEN);
	memmove(u->p->user, buf, NAMELEN);
	return n;
}

long
hostdomainwrite(char *a, int n)
{
	char buf[DOMLEN];

	if(!iseve())
		error(Eperm);
	if(n >= DOMLEN)
		error(Ebadarg);
	memset(buf, 0, DOMLEN);
	strncpy(buf, a, n);
	if(buf[0] == 0)
		error(Ebadarg);
	memmove(hostdomain, buf, DOMLEN);
	return n;
}
.
## diffname port/auth.c 1993/0402
## diff -e /n/bootesdump/1993/0330/sys/src/9/port/auth.c /n/bootesdump/1993/0402/sys/src/9/port/auth.c
413a
	if(strcmp(u->p->user, cp->t.cuid))
		error(cp->t.cuid);
.
412c
	if(cp->t.num != AuthTc)
.
138a
		if(n == 2 && buf[0] == 'O' && buf[1] == 'K')
			goto dkhack;
.
137a
	dkhack:
.
## diffname port/auth.c 1993/0403
## diff -e /n/bootesdump/1993/0402/sys/src/9/port/auth.c /n/bootesdump/1993/0403/sys/src/9/port/auth.c
310a
	unlock(s);
.
307a
	lock(s);
.
283,285d
267a

	id = s->cid++;
	unlock(s);

.
264a
	lock(s);
.
243a
	}
.
242c
	for(cp = s->cache; cp; cp = next) {
		next = cp->next;
.
240c
	Crypt *cp, *next;
.
132a
		f->tag = NOTAG;
.
## diffname port/auth.c 1993/0407
## diff -e /n/bootesdump/1993/0403/sys/src/9/port/auth.c /n/bootesdump/1993/0407/sys/src/9/port/auth.c
177,178c
	poperror();
.
175d
150d
131,148c

		/*
		 *  Exchange a session message with the server.
		 *  If an error occurs reading or writing,
		 *  assume this is a mount of a mount and turn off
		 *  authentication.
		 */
		if(!waserror()){
			for(i = 0; i < CHALLEN; i++)
				s->cchal[i] = nrand(256);
			f.tag = NOTAG;
			f.type = Tsession;
			memmove(f.chal, s->cchal, CHALLEN);
			n = convS2M(&f, buf);
			if((*devtab[c->type].write)(c, buf, n, 0) != n)
				error(Emountrpc);
			n = (*devtab[c->type].read)(c, buf, sizeof buf, 0);
			if(n == 2 && buf[0] == 'O' && buf[1] == 'K')
				n = (*devtab[c->type].read)(c, buf, sizeof buf, 0);
			poperror();
			if(convM2S(buf, &f, n) == 0){
				free(s);
				error(Emountrpc);
			}
			switch(f.type){
			case Rsession:
				memmove(s->schal, f.chal, CHALLEN);
				memmove(s->authid, f.authid, NAMELEN);
				memmove(s->authdom, f.authdom, DOMLEN);
				break;
			case Rerror:
				free(s);
				error(f.ename);
			default:
				free(s);
				error(Emountrpc);
			}
.
126c
		/*
		 *  no session exchanged yet
		 */
.
123a

	/*
	 *  if two processes get here at the same
	 *  time with no session exchanged, we have
	 *  a race.
	 */
.
120,121d
115,118c
	if(waserror()){
.
106,113d
103a
	Fcall f;
	char buf[MAXMSG];
.
99,100d
## diffname port/auth.c 1993/0408
## diff -e /n/bootesdump/1993/0407/sys/src/9/port/auth.c /n/bootesdump/1993/0408/sys/src/9/port/auth.c
181,183c
	memmove(tr.chal, s->schal, CHALLEN);
	memmove(tr.authid, s->authid, NAMELEN);
	memmove(tr.authdom, s->authdom, DOMLEN);
.
174,178c
	else{
		lock(s);
		for(cp = s->cache; cp; cp = cp->next)
			if(strcmp(cp->t.cuid, u->p->user) == 0){
				tr.type = 0;
				break;
			}
		unlock(s);
	}
.
172c
	if(strcmp(u->p->user, "none") == 0 || s->authid[0] == 0)
.
165a
	unlock(&s->send);
.
164c
		s->valid = 1;
.
160c
				unlock(s);
.
157c
				unlock(s);
.
147c
				unlock(s);
.
126a
	/* back off if someone else is doing an fsession */
	while(!canlock(&s->send))
		sched();

	if(s->valid == 0){
.
125c
		}
		c->session = s;
	}
	unlock(c);
.
123c
		if(s == 0){
			unlock(c);
.
119,121d
112,116c
	/* add a session structure to the channel if it has none */
	lock(c);
.
27a
	int	valid;
.
21a
	Lock	send;
.
## diffname port/auth.c 1993/0411
## diff -e /n/bootesdump/1993/0408/sys/src/9/port/auth.c /n/bootesdump/1993/0411/sys/src/9/port/auth.c
165c
				unlock(&s->send);
.
162c
				unlock(&s->send);
.
152c
				unlock(&s->send);
.
## diffname port/auth.c 1993/0427
## diff -e /n/bootesdump/1993/0411/sys/src/9/port/auth.c /n/bootesdump/1993/0427/sys/src/9/port/auth.c
165a
print("error using %d bytes %ux %ux %ux\n", n, buf[0], buf[1], buf[2]);
.
152a
print("error converting %d bytes %ux %ux %ux\n", n, buf[0], buf[1], buf[2]);
.
## diffname port/auth.c 1993/0428
## diff -e /n/bootesdump/1993/0427/sys/src/9/port/auth.c /n/bootesdump/1993/0428/sys/src/9/port/auth.c
451a

	return n;
}

/*
 *  called by devcons() for #c/authenticator
 *
 *  a read after a write of a ticket returns an authenticator
 *  for that ticket.
 */
long
authentwrite(Chan *c, char *a, int n)
{
	Crypt *cp;

	if(n != TICKETLEN)
		error(Ebadarg);
	if(c->aux == 0)
		c->aux = newcrypt();
	cp = c->aux;

	memmove(cp->tbuf, a, TICKETLEN);
	convM2T(cp->tbuf, &cp->t, evekey);
	if(cp->t.num != AuthTc || strcmp(cp->t.cuid, u->p->user)){
		freecrypt(cp);
		c->aux = 0;
		error(Ebadarg);
	}

	return n;
}
long
authentread(Chan *c, char *a, int n)
{
	Crypt *cp;

	cp = c->aux;
	if(cp == 0)
		error("authenticator read must follow a write");

	cp->a.num = AuthAc;
	memmove(cp->a.chal, cp->t.chal, CHALLEN);
	cp->a.id = 0;
	convA2M(&cp->a, cp->tbuf, cp->t.key);
	memmove(a, cp->tbuf, AUTHENTLEN);

.
449c

	memmove(cp->tbuf, a+TICKETLEN, AUTHENTLEN);
	convM2A(cp->tbuf, &cp->a, cp->t.key);
.
444c

	memmove(cp->tbuf, a, TICKETLEN);
	convM2T(cp->tbuf, &cp->t, evekey);
.
424a

	memmove(cp->tbuf, a+TICKETLEN, AUTHENTLEN);
	convM2A(cp->tbuf, &cp->a, cp->t.key);
	if(cp->a.num != AuthAc || memcmp(cp->a.chal, cp->t.chal, CHALLEN))
		error(Eperm);

.
422c

	memmove(cp->tbuf, a, TICKETLEN);
	convM2T(cp->tbuf, &cp->t, evekey);
.
417c
	if(n != TICKETLEN+AUTHENTLEN)
.
405c
		convA2M(&cp->a, cp->tbuf, cp->t.key);
		memmove(a, cp->tbuf, AUTHENTLEN);

.
401a

.
384a

.
366,367c
 *	2) write ticket+authenticator to #c/authenticate. if it matches
 *	  the challenge the user is changed to the suid field of the ticket
.
167d
153d
## diffname port/auth.c 1993/0501
## diff -e /n/bootesdump/1993/0428/sys/src/9/port/auth.c /n/fornaxdump/1993/0501/sys/src/brazil/port/auth.c
584c
	memmove(up->user, buf, NAMELEN);
.
560,561c
	memset(up->user, 0, NAMELEN);
	strcpy(up->user, "none");
.
470,514d
466d
461,463c
	convM2A(a+TICKETLEN, &cp->a, cp->t.key);
.
459c
	if(strcmp(up->user, cp->t.cuid))
.
454,456c
	convM2T(a, &cp->t, evekey);
.
429,435c
	memmove(up->user, cp->t.suid, NAMELEN);
.
424,426c
	convM2T(a, &cp->t, evekey);
.
419c
	if(n != TICKETLEN)
.
405,407c
		convA2M(&cp->a, a, cp->t.key);
.
401d
389c
		strcpy(tr.uid, up->user);
.
383d
364,365c
 *	2) write ticket to #c/authenticate. if it matchs the challenge the
 *	  user is changed to the suid field of the ticket
.
341c
	if(s == 0 || cp == 0 || s->authid[0] == 0 || strcmp(up->user, "none") == 0)
.
336c
		if(strcmp(cp->t.cuid, up->user) == 0)
.
305,306c
		memmove(cp->t.cuid, up->user, NAMELEN);
		memmove(cp->t.suid, up->user, NAMELEN);
.
291c
		if(strcmp(cp->t.cuid, up->user) == 0)
.
281c
	if(s == 0 || s->authid[0] == 0 || strcmp(up->user, "none") == 0){
.
242c
		if(strcmp(ncp->t.cuid, up->user) == 0){
.
232c
	if(strncmp(up->user, cp->t.cuid, NAMELEN) != 0)
.
191,194c
	memmove(tr.chal, c->session->schal, CHALLEN);
	memmove(tr.authid, c->session->authid, NAMELEN);
	memmove(tr.authdom, c->session->authdom, DOMLEN);
	memmove(tr.uid, up->user, NAMELEN);
.
180,188c
	else for(cp = s->cache; cp; cp = cp->next)
		if(strcmp(cp->t.cuid, up->user) == 0){
			tr.type = 0;
			break;
		}
.
178c
	if(strcmp(up->user, "none") == 0 || c->session->authid[0] == 0)
.
171d
169c
		c->session = s;
.
165c
				free(s);
.
162c
				free(s);
.
152c
				free(s);
.
149c
				goto dkhack;
.
146a
		dkhack:
.
127,131d
122,125c
		memset(s, 0, sizeof(Session));
.
119,120c
		if(s == 0)
.
117a
		/*
		 *  no session exchanged yet
		 */
.
114,115c
	/*
	 *  if two processes get here at the same
	 *  time with no session exchanged, we have
	 *  a race.
	 */
.
48c
	return strcmp(eve, up->user) == 0;
.
29d
22d
18d
## diffname port/auth.c 1993/0731
## diff -e /n/fornaxdump/1993/0501/sys/src/brazil/port/auth.c /n/fornaxdump/1993/0731/sys/src/brazil/port/auth.c
439a

	return n;
}

/*
 *  called by devcons() for #c/authenticator
 *
 *  a read after a write of a ticket (or ticket+id) returns an authenticator
 *  for that ticket.
 */
long
authentwrite(Chan *c, char *a, int n)
{
	Crypt *cp;

	if(n != TICKETLEN && n != TICKETLEN+4)
		error(Ebadarg);
	if(c->aux == 0)
		c->aux = newcrypt();
	cp = c->aux;

	memmove(cp->tbuf, a, TICKETLEN);
	convM2T(cp->tbuf, &cp->t, evekey);
	if(cp->t.num != AuthTc || strcmp(cp->t.cuid, up->user)){
		freecrypt(cp);
		c->aux = 0;
		error(Ebadarg);
	}
	if(n == TICKETLEN+4){
		uchar *p = (uchar *)&a[TICKETLEN];
		cp->a.id = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
	}else
		cp->a.id = 0;

	return n;
}

long
authentread(Chan *c, char *a, int n)
{
	Crypt *cp;

	cp = c->aux;
	if(cp == 0)
		error("authenticator read must follow a write");

	cp->a.num = AuthAc;
	memmove(cp->a.chal, cp->t.chal, CHALLEN);
	convA2M(&cp->a, cp->tbuf, cp->t.key);
	memmove(a, cp->tbuf, AUTHENTLEN);

.
437,438c

	memmove(cp->tbuf, a+TICKETLEN, AUTHENTLEN);
	convM2A(cp->tbuf, &cp->a, cp->t.key);
	if(n == TICKETLEN+AUTHENTLEN+CHALLEN+4){
		uchar *p = (uchar *)&a[TICKETLEN+AUTHENTLEN+CHALLEN];
		id = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
		chal = &a[TICKETLEN+AUTHENTLEN];
	}else{
		id = 0;
		chal = cp->t.chal;
	}
	if(cp->a.num != AuthAs || memcmp(chal, cp->a.chal, CHALLEN) || cp->a.id != id)
.
432c

	memmove(cp->tbuf, a, TICKETLEN);
	convM2T(cp->tbuf, &cp->t, evekey);
.
427c
	if(n != TICKETLEN+AUTHENTLEN && n != TICKETLEN+AUTHENTLEN+CHALLEN+4)
.
425a
	char *chal;
	ulong id;
.
420c
 *  a write of a ticket+authenticator [+challenge+id] succeeds if they match
.
412a

	memmove(cp->tbuf, a+TICKETLEN, AUTHENTLEN);
	convM2A(cp->tbuf, &cp->a, cp->t.key);
	if(cp->a.num != AuthAc || memcmp(cp->a.chal, cp->t.chal, CHALLEN))
		error(Eperm);

.
410c

	memmove(cp->tbuf, a, TICKETLEN);
	convM2T(cp->tbuf, &cp->t, evekey);
.
405c
	if(n != TICKETLEN+AUTHENTLEN)
.
393c
		convA2M(&cp->a, cp->tbuf, cp->t.key);
		memmove(a, cp->tbuf, AUTHENTLEN);

.
389a

.
372a

.
354,355c
 *	2) write ticket+authenticator to #c/authenticate. if it matches
 *	  the challenge the user is changed to the suid field of the ticket
.
181,183c
	memmove(tr.chal, s->schal, CHALLEN);
	memmove(tr.authid, s->authid, NAMELEN);
	memmove(tr.authdom, s->authdom, DOMLEN);
.
174,178c
	else{
		lock(s);
		for(cp = s->cache; cp; cp = cp->next)
			if(strcmp(cp->t.cuid, up->user) == 0){
				tr.type = 0;
				break;
			}
		unlock(s);
	}
.
172c
	if(strcmp(up->user, "none") == 0 || s->authid[0] == 0)
.
165a
	unlock(&s->send);
.
164c
		s->valid = 1;
.
160c
				unlock(&s->send);
.
157c
				unlock(&s->send);
.
147c
				unlock(&s->send);
.
144c
				n = (*devtab[c->type].read)(c, buf, sizeof buf, 0);
.
141d
125a
	/* back off if someone else is doing an fsession */
	while(!canlock(&s->send))
		sched();

	if(s->valid == 0){
.
124c
		}
		c->session = s;
	}
	unlock(c);
.
122c
		if(s == 0){
			unlock(c);
.
118,120d
111,115c
	/* add a session structure to the channel if it has none */
	lock(c);
.
26a
	int	valid;
.
20a
	Lock	send;
.
17a
typedef struct Session	Session;
.
## diffname port/auth.c 1994/0624
## diff -e /n/fornaxdump/1993/0731/sys/src/brazil/port/auth.c /n/fornaxdump/1994/0624/sys/src/brazil/port/auth.c
6d
## diffname port/auth.c 1994/0915
## diff -e /n/fornaxdump/1994/0624/sys/src/brazil/port/auth.c /n/fornaxdump/1994/0915/sys/src/brazil/port/auth.c
598a
	up->basepri = PriNormal;
.
575a
	up->basepri = PriNormal;
.
## diffname port/auth.c 1994/1027
## diff -e /n/fornaxdump/1994/0915/sys/src/brazil/port/auth.c /n/fornaxdump/1994/1027/sys/src/brazil/port/auth.c
597a
	renameuser(eve, buf);
.
37c
char	eve[NAMELEN];
.
## diffname port/auth.c 1995/0102
## diff -e /n/fornaxdump/1994/1027/sys/src/brazil/port/auth.c /n/fornaxdump/1995/0102/sys/src/brazil/port/auth.c
601c
	up->nice = NiceNormal;
.
576c
	up->nice = NiceNormal;
.
## diffname port/auth.c 1995/0106
## diff -e /n/fornaxdump/1995/0102/sys/src/brazil/port/auth.c /n/fornaxdump/1995/0106/sys/src/brazil/port/auth.c
128a
	}
.
127c
	while(!canlock(&s->send)) {
		up->yield = 1;
.
## diffname port/auth.c 1995/0110
## diff -e /n/fornaxdump/1995/0106/sys/src/brazil/port/auth.c /n/fornaxdump/1995/0110/sys/src/brazil/port/auth.c
603c
	up->basepri = PriNormal;
.
578c
	up->basepri = PriNormal;
.
130d
127,128c
	while(!canlock(&s->send))
.
## diffname port/auth.c 1995/0113
## diff -e /n/fornaxdump/1995/0110/sys/src/brazil/port/auth.c /n/fornaxdump/1995/0113/sys/src/brazil/port/auth.c
545c
	if(!cpuserver || !iseve())
.
## diffname port/auth.c 1995/0414
## diff -e /n/fornaxdump/1995/0113/sys/src/brazil/port/auth.c /n/fornaxdump/1995/0414/sys/src/brazil/port/auth.c
130c
	if(s->valid == 0 && (c->flag & CMSG) == 0){

.
## diffname port/auth.c 1997/0327
## diff -e /n/fornaxdump/1995/0414/sys/src/brazil/port/auth.c /n/emeliedump/1997/0327/sys/src/brazil/port/auth.c
198c
	cclose(c);
.
149c
				n = devtab[c->type]->read(c, buf, sizeof buf, 0);
.
147c
			n = devtab[c->type]->read(c, buf, sizeof buf, 0);
.
145c
			if(devtab[c->type]->write(c, buf, n, 0) != n)
.
109c
		cclose(c);
.
## diffname port/auth.c 1998/0404
## diff -e /n/emeliedump/1997/0327/sys/src/brazil/port/auth.c /n/emeliedump/1998/0404/sys/src/brazil/port/auth.c
525c

	if(n >= AUTHENTLEN)
		memmove(a, cp->tbuf, AUTHENTLEN);
	if(n >= AUTHENTLEN + TICKETLEN)
		convT2M(&cp->t, a+AUTHENTLEN, nil);
.
480a
 *  reading authcheck after writing into it yields the
 *  nonce key
 */
long
authcheckread(Chan *c, char *a, int n)
{
	Crypt *cp;

	cp = c->aux;
	if(cp == nil)
		error(Ebadarg);
	if(n < TICKETLEN))
		error(Ebadarg);
	convT2M(&cp->t, a, nil);
	return sizeof(cp->t);
}

/*
.
## diffname port/auth.c 1998/0406
## diff -e /n/emeliedump/1998/0404/sys/src/brazil/port/auth.c /n/emeliedump/1998/0406/sys/src/brazil/port/auth.c
492c
	if(n < TICKETLEN)
.
## diffname port/auth.c 1998/0407
## diff -e /n/emeliedump/1998/0406/sys/src/brazil/port/auth.c /n/emeliedump/1998/0407/sys/src/brazil/port/auth.c
530a
/*
 *  create an authenticator and return it and optionally the
 *  unencripted ticket
 */
.
482c
 *  unencrypted ticket
.
## diffname port/auth.c 1998/0422
## diff -e /n/emeliedump/1998/0407/sys/src/brazil/port/auth.c /n/emeliedump/1998/0422/sys/src/brazil/port/auth.c
550,552d
407a
		if(n >= AUTHENTLEN + TICKETLEN)
			convT2M(&cp->t, a+AUTHENTLEN, nil);

.
398c
		if(n < AUTHENTLEN)
.
## diffname port/auth.c 1998/0512
## diff -e /n/emeliedump/1998/0422/sys/src/brazil/port/auth.c /n/emeliedump/1998/0512/sys/src/brazil/port/auth.c
352c
	}
.
173c
	/*
.
## diffname port/auth.c 1999/0331
## diff -e /n/emeliedump/1998/0512/sys/src/brazil/port/auth.c /n/emeliedump/1999/0331/sys/src/brazil/port/auth.c
251a
	cclose(c);
.
221a
		cclose(c);
.
219a
	}
.
218c
	if(s == 0){
		cclose(c);
.
## diffname port/auth.c 1999/1224
## diff -e /n/emeliedump/1999/0331/sys/src/brazil/port/auth.c /n/emeliedump/1999/1224/sys/src/9/port/auth.c
540c
 *  unencrypted ticket
.
## diffname port/auth.c 2000/0710
## diff -e /n/emeliedump/1999/1224/sys/src/9/port/auth.c /n/emeliedump/2000/0710/sys/src/9/port/auth.c
603c
	if(!iseve() || strcmp(a, "none") != 0)
.
## diffname port/auth.c 2001/0503
## diff -e /n/emeliedump/2000/0710/sys/src/9/port/auth.c /n/emeliedump/2001/0503/sys/src/9/port/auth.c
357c
	if(a.id != id){
.
353c
	if(memcmp(a.chal, s->cchal, sizeof(a.chal))){
.
348,349c
	convM2A(f->rauth, &a, cp->t.key);
	if(a.num != AuthAs){
.
332a
	Authenticator a;
.
318,321c
	memmove(a.chal, s->schal, CHALLEN);
	a.num = AuthAc;
	a.id = id;
	convA2M(&a, f->auth, cp->t.key);
.
280a
	Authenticator a;
.
## diffname port/auth.c 2001/0527
## diff -e /n/emeliedump/2001/0503/sys/src/9/port/auth.c /n/emeliedump/2001/0527/sys/src/9/port/auth.c
632,633c
	kstrdup(&eve, buf);
	kstrdup(&up->user, buf);
.
630a

.
627,629c
	strncpy(buf, a, n+1);
	if(buf[0] == '\0')
.
625c
	if(n >= sizeof buf)
.
621c
	char buf[128];
.
607,608c
	kstrdup(&up->user, "none");
.
603,604d
490,570d
456,486c
	error("sysfauth unimplemented");
	return -1;
.
454c
sysfauth(ulong *)
.
448,452d
439,445c
	free(msg);
	poperror();
	poperror();
	cclose(c);
	return m;
.
434,437c
	n = convM2S(msg, m, &f);
	if(n != m)
		error("bad fsession conversion on reply");
	if(f.type != Rsession)
		error("unexpected reply type in fsession");
	m = f.nchal;
	if(m > authlen)
		error(Eshort);
//BUG print("auth stuff ignored; noauth by default\n");
	((uchar*)arg[1])[0] = 0;
.
428,432c
	lock(c);
	c->offset += m;
	unlock(c);
.
423,426c
	/* message sent; receive and decode reply */
	m = devtab[c->type]->read(c, msg, MAXMSG, c->offset);
	if(m <= 0)
		error("EOF receiving fsession reply");
.
420,421d
390,418c
	if(m < n){
		lock(c);
		c->offset -= n - m;
		unlock(c);
		error("short write in fsession");
.
381,388c
	m = devtab[c->type]->write(c, msg, n, oo);
.
365,379c
	lock(c);
	oo = c->offset;
	c->offset += n;
	unlock(c);
.
355,363c
	n = convS2M(&f, msg, MAXMSG);
	if(n == 0)
		error("bad fsession conversion on send");
.
292,353c
	f.type = Tsession;
	f.tag = NOTAG;
	f.nchal = 0;
	f.chal = (uchar*)"";
	msg = smalloc(MAXMSG);
	if(waserror()){
		free(msg);
		nexterror();
.
229,288c
	if(c->flag & CMSG){
//BUG what to do?
		((uchar*)arg[1])[0] = 0;
		poperror();
		cclose(c);
.
225d
215,222c
//BUG print("warning: stub fsession being used\n");
	authlen = arg[2];
	validaddr(arg[1], authlen, 1);
	c = fdtochan(arg[0], ORDWR, 0, 1);
.
210,213c
	uvlong oo;
.
208a
	Fcall f;
	uchar *msg;
	uint authlen, n, m;
.
207c
sysfsession(ulong *arg)
.
203,205d
200c
	return m;
.
197a
	n = convM2S(msg, m, &f);
	if(n != m)
		error("bad fversion conversion on reply");
	if(f.type != Rversion)
		error("unexpected reply type in fversion");
	if(f.msize > msize)
		error("server tries to increase msize in fversion");
	if(f.msize<256 || f.msize>1024*1024)
		error("nonsense value of msize in fversion");
	kstrdup(&c->version, f.version);
	c->iounit = f.msize;
	free(msg);
	poperror();

Return:
	m = strlen(c->version);
	if(m > arglen)
		m = arglen;
	memmove((char*)arg[2], c->version, m);

.
190,196c
	lock(c);
	c->offset += m;
	unlock(c);
.
173,188c
	/* message sent; receive and decode reply */
	m = devtab[c->type]->read(c, msg, MAXMSG, c->offset);
	if(m <= 0)
		error("EOF receiving fversion reply");
.
171d
130,169c
	if(m < n){
		lock(c);
		c->offset -= n - m;
		unlock(c);
		error("short write in fversion");
.
126,128c
	m = devtab[c->type]->write(c, msg, n, oo);
.
123a
	n = convS2M(&f, msg, MAXMSG);
	if(n == 0)
		error("bad fversion conversion on send");

	lock(c);
	oo = c->offset;
	c->offset += n;
.
113,122c
	if((c->flag&CMSG) && c->version!=nil) /* BUG: insufficient; should check compatibility */
		goto Return;

	f.type = Tversion;
	f.tag = NOTAG;
	if(msize == 0)
		msize = IOHDRSZ+8192;	/* reasonable default */
	f.msize = msize;
	if(vers[0] == '\0')
		vers = VERSION9P;
	f.version = vers;
	msg = smalloc(MAXMSG);
	if(waserror()){
		free(msg);
		nexterror();
.
106,107c
	msize = arg[1];
	vers = (char*)arg[2];
	arglen = arg[3];
	validaddr(arg[2], arglen, 1);
	/* check there's a NUL in the version string */
	if(memchr(vers, 0, arglen) == 0)
		error(Ebadarg);
	c = fdtochan(arg[0], ORDWR, 0, 1);
.
100,104c
	uvlong oo;
.
98c
	Fcall f;	/* two Fcalls should be big enough for reply */
	uchar *msg;
	char *vers;
	uint arglen, n, m, msize;
.
96c
sysfversion(ulong *arg)
.
50,94d
17,37c
char	*eve;
.
8,15c
#include	<auth.h>
.
## diffname port/auth.c 2001/0529
## diff -e /n/emeliedump/2001/0527/sys/src/9/port/auth.c /n/emeliedump/2001/0529/sys/src/9/port/auth.c
168c
	m = devtab[c->type]->read(c, msg, 8192+IOHDRSZ, c->offset);
.
149c
	n = convS2M(&f, msg, 8192+IOHDRSZ);
.
144c
	msg = smalloc(8192+IOHDRSZ);
.
81c
	m = devtab[c->type]->read(c, msg, 8192+IOHDRSZ, c->offset);
.
62c
	n = convS2M(&f, msg, 8192+IOHDRSZ);
.
57c
	msg = smalloc(8192+IOHDRSZ);
.
## diffname port/auth.c 2001/0807
## diff -e /n/emeliedump/2001/0529/sys/src/9/port/auth.c /n/emeliedump/2001/0807/sys/src/9/port/auth.c
197,198c
	Chan *c;
	uint authlen, rauthlen;
	int n;

	authlen = arg[2];
	validaddr(arg[1], authlen, 1);
	rauthlen = arg[4];
	validaddr(arg[3], rauthlen, 1);
	c = fdtochan(arg[0], ORDWR, 0, 1);
	if(waserror()){
		cclose(c);
		nexterror();
	}

	n = mntauth(c, (uchar*)arg[1], authlen, (uchar*)arg[3], rauthlen);

	poperror();
	cclose(c);
	return n;

.
195c
sysfauth(ulong *arg)
.
191c
	return n;

.
188a
}

long
sysfsession(ulong *arg)
{
	Chan *c;
	uint authlen, n;

	authlen = arg[2];
	validaddr(arg[1], authlen, 1);
	c = fdtochan(arg[0], ORDWR, 0, 1);
	if(waserror()){
		cclose(c);
		nexterror();
	}

	if(c->session == nil){
		if(c->flag&CMSG)
			error("session on mounted channel");
		sendsession(c);
	}

	n = strlen(c->session->authlist)+1;
	if(n > authlen)
		error(Eshort);
	memmove((uchar*)arg[1], c->session->authlist, n);

.
181,185c
	c->session = allocsession(f.authlist);
.
176a
print("rsession conv returns %d\n", n);
.
170a
print("rsession rcvd\n");
.
158a
print("session sent\n");
.
142,143d
123,139d
119,120c
	uint n, m;
.
114,115c
void
sendsession(Chan *c)
.
13a
struct Session
{
	char *authlist;
};

Session*
allocsession(char *authlist)
{
	Session *s;

	s = smalloc(sizeof(*s));
	s->authlist = nil;
	kstrdup(&s->authlist, authlist);
	return s;
}

void
freesession(Session *s)
{
	if(s == nil)
		return;
	free(s->authlist);
	free(s);
}

.
## diffname port/auth.c 2001/0808
## diff -e /n/emeliedump/2001/0807/sys/src/9/port/auth.c /n/emeliedump/2001/0808/sys/src/9/port/auth.c
229,248c
	error("sysfauth unimplemented");
	return -1;
.
227c
sysfauth(ulong *)
.
222,223c
	return m;
.
193,219d
189c
	m = f.nchal;
	if(m > authlen)
		error(Eshort);
//BUG print("auth stuff ignored; noauth by default\n");
	((uchar*)arg[1])[0] = 0;
.
184d
177d
164d
148a
	f.nchal = 0;
	f.chal = (uchar*)"";
.
146a
//BUG print("warning: stub fsession being used\n");
	authlen = arg[2];
	validaddr(arg[1], authlen, 1);
	c = fdtochan(arg[0], ORDWR, 0, 1);
	if(waserror()){
		cclose(c);
		nexterror();
	}

	if(c->flag & CMSG){
//BUG what to do?
		((uchar*)arg[1])[0] = 0;
		poperror();
		cclose(c);
		return 0;
	}

.
144c
	uint authlen, n, m;
	Chan *c;
.
139,140c
long
sysfsession(ulong *arg)
.
14,38d
## diffname port/auth.c 2001/0819
## diff -e /n/emeliedump/2001/0808/sys/src/9/port/auth.c /n/emeliedump/2001/0819/sys/src/9/port/auth.c
160,198c
	return fd;
.
158c
	/* always mark it close on exec */
	ac->flag |= CCEXEC;
.
153,156c
	fd = newfd(ac);
	if(fd < 0)
		error(Enofd);
	poperror();	/* ac */
	poperror();	/* c */
.
149,151d
146c
		cclose(ac);
.
132,144c
	ac = mntauth(c, aname);
.
123,125c
	if(arg[2] == 0)
		error(Ebadarg);
	validaddr(arg[1], arg[2], 1);
	((uchar*)arg[1])[0] = '\0';
	return 0;
}

long
sysfauth(ulong *arg)
{
	Chan *c, *ac;
	char *aname;
	int fd;

	validaddr(arg[1], 1, 0);
	aname = (char*)arg[1];
	validname(aname, 0);
.
117,121c
	/* deprecated; backwards compatibility only */
.
115c
sys_fsession(ulong *arg)
.
49,108d
46,47c
	m = mntversion(c, vers, msize, arglen);
.
38c
	if(arglen==0 || memchr(vers, 0, arglen)==0)
.
31d
29c
	uint arglen, m, msize;
.
26,27d
## diffname port/auth.c 2001/0925
## diff -e /n/emeliedump/2001/0819/sys/src/9/port/auth.c /n/emeliedump/2001/0925/sys/src/9/port/auth.c
8c
#include	<authsrv.h>
.
## diffname port/auth.c 2001/0929
## diff -e /n/emeliedump/2001/0925/sys/src/9/port/auth.c /n/emeliedump/2001/0929/sys/src/9/port/auth.c
97,121d
## diffname port/auth.c 2001/0930
## diff -e /n/emeliedump/2001/0929/sys/src/9/port/auth.c /n/emeliedump/2001/0930/sys/src/9/port/auth.c
104c
	if(strcmp(a, "none") != 0)
.
## diffname port/auth.c 2002/0115
## diff -e /n/emeliedump/2001/0930/sys/src/9/port/auth.c /n/emeliedump/2002/0115/sys/src/9/port/auth.c
11d
## diffname port/auth.c 2002/0221
## diff -e /n/emeliedump/2002/0115/sys/src/9/port/auth.c /n/emeliedump/2002/0221/sys/src/9/port/auth.c
124,126c
	memmove(buf, a, n);
	buf[n] = 0;
.
122c
	if(n <= 0 || n >= sizeof buf)
.
## diffname port/auth.c 2002/0410
## diff -e /n/emeliedump/2002/0221/sys/src/9/port/auth.c /n/emeliedump/2002/0410/sys/src/9/port/auth.c
103c
	if(n!=4 || strncmp(a, "none", 4)!=0)
.
## diffname port/auth.c 2002/0517
## diff -e /n/emeliedump/2002/0410/sys/src/9/port/auth.c /n/emeliedump/2002/0517/sys/src/9/port/auth.c
87d
77a

	/* at this point ac is responsible for keeping c alive */
	cclose(c);
	poperror();	/* c */

.
## diffname port/auth.c 2002/0831
## diff -e /n/emeliedump/2002/0517/sys/src/9/port/auth.c /n/emeliedump/2002/0831/sys/src/9/port/auth.c
70c
	validname(aname, 1);
.

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].