From 26f562a7e0710c1b4e26596766b3b5f7529f593d Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 31 Jul 1993 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1993-07-31 --- port/auth.c | 157 ++++++++++++++++++++++++++++++++++++++----------- port/devcons.c | 9 +++ port/portdat.h | 1 - port/portfns.h | 2 + port/proc.c | 1 - 5 files changed, 133 insertions(+), 37 deletions(-) diff --git a/port/auth.c b/port/auth.c index bcd1fa474984799b6a93128e9f318a78d159a13e..9ccc1d85fd7a8f40a6ab412d929c06a728fe938a 100644 --- a/port/auth.c +++ b/port/auth.c @@ -15,15 +15,18 @@ struct Crypt char tbuf[TICKETLEN]; /* remote ticket */ }; +typedef struct Session Session; struct Session { Lock; + Lock send; 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 */ + int valid; }; struct @@ -108,21 +111,24 @@ sysfsession(ulong *arg) nexterror(); } - /* - * if two processes get here at the same - * time with no session exchanged, we have - * a race. - */ + /* add a session structure to the channel if it has none */ + lock(c); s = c->session; if(s == 0){ - /* - * no session exchanged yet - */ s = malloc(sizeof(Session)); - if(s == 0) + if(s == 0){ + unlock(c); error(Enomem); - memset(s, 0, sizeof(Session)); + } + c->session = s; + } + unlock(c); + /* back off if someone else is doing an fsession */ + while(!canlock(&s->send)) + sched(); + + if(s->valid == 0){ /* * Exchange a session message with the server. * If an error occurs reading or writing, @@ -138,13 +144,12 @@ sysfsession(ulong *arg) n = convS2M(&f, buf); if((*devtab[c->type].write)(c, buf, n, 0) != n) error(Emountrpc); - dkhack: n = (*devtab[c->type].read)(c, buf, sizeof buf, 0); if(n == 2 && buf[0] == 'O' && buf[1] == 'K') - goto dkhack; + n = (*devtab[c->type].read)(c, buf, sizeof buf, 0); poperror(); if(convM2S(buf, &f, n) == 0){ - free(s); + unlock(&s->send); error(Emountrpc); } switch(f.type){ @@ -154,33 +159,38 @@ sysfsession(ulong *arg) memmove(s->authdom, f.authdom, DOMLEN); break; case Rerror: - free(s); + unlock(&s->send); error(f.ename); default: - free(s); + unlock(&s->send); error(Emountrpc); } } - c->session = s; + s->valid = 1; } + unlock(&s->send); /* * If server requires no ticket, or user is "none", or a ticket * is already cached, zero the request type */ tr.type = AuthTreq; - if(strcmp(up->user, "none") == 0 || c->session->authid[0] == 0) + if(strcmp(up->user, "none") == 0 || s->authid[0] == 0) tr.type = 0; - else for(cp = s->cache; cp; cp = cp->next) - if(strcmp(cp->t.cuid, up->user) == 0){ - tr.type = 0; - break; - } + 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); + } /* 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.chal, s->schal, CHALLEN); + memmove(tr.authid, s->authid, NAMELEN); + memmove(tr.authdom, s->authdom, DOMLEN); memmove(tr.uid, up->user, NAMELEN); memmove(tr.hostid, eve, NAMELEN); convTR2M(&tr, (char*)arg[1]); @@ -351,8 +361,8 @@ authreply(Session *s, ulong id, Fcall *f) * * 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 + * 2) write ticket+authenticator to #c/authenticate. if it matches + * the challenge the user is changed to the suid field of the ticket * 3) read authenticator (to confirm this is the server advertised) */ long @@ -370,6 +380,7 @@ authread(Chan *c, char *a, int n) error(Ebadarg); c->aux = newcrypt(); cp = c->aux; + memset(&tr, 0, sizeof(tr)); tr.type = AuthTreq; strcpy(tr.hostid, eve); @@ -387,10 +398,13 @@ authread(Chan *c, char *a, int n) 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); + convA2M(&cp->a, cp->tbuf, cp->t.key); + memmove(a, cp->tbuf, AUTHENTLEN); + freecrypt(cp); c->aux = 0; } @@ -402,14 +416,22 @@ authwrite(Chan *c, char *a, int n) { Crypt *cp; - if(n != TICKETLEN) + if(n != TICKETLEN+AUTHENTLEN) error(Ebadarg); if(c->aux == 0) error(Ebadarg); cp = c->aux; - convM2T(a, &cp->t, evekey); + + memmove(cp->tbuf, a, TICKETLEN); + convM2T(cp->tbuf, &cp->t, evekey); if(cp->t.num != AuthTs || memcmp(cp->a.chal, cp->t.chal, CHALLEN)) error(Eperm); + + 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); + memmove(up->user, cp->t.suid, NAMELEN); return n; } @@ -417,26 +439,91 @@ authwrite(Chan *c, char *a, int n) /* * called by devcons() for #c/authcheck * - * a write of a ticket+authenticator succeeds if they match + * a write of a ticket+authenticator [+challenge+id] succeeds if they match */ long authcheck(Chan *c, char *a, int n) { Crypt *cp; + char *chal; + ulong id; - if(n != TICKETLEN+AUTHENTLEN) + if(n != TICKETLEN+AUTHENTLEN && n != TICKETLEN+AUTHENTLEN+CHALLEN+4) error(Ebadarg); if(c->aux == 0) c->aux = newcrypt(); cp = c->aux; - convM2T(a, &cp->t, evekey); + + memmove(cp->tbuf, a, TICKETLEN); + convM2T(cp->tbuf, &cp->t, evekey); if(cp->t.num != AuthTc) error(Ebadarg); if(strcmp(up->user, cp->t.cuid)) error(cp->t.cuid); - convM2A(a+TICKETLEN, &cp->a, cp->t.key); - if(cp->a.num != AuthAs || memcmp(cp->t.chal, cp->a.chal, CHALLEN)) + + 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) error(Eperm); + + 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); + return n; } diff --git a/port/devcons.c b/port/devcons.c index 691f621ab61825fca047d30cd689daaa865df74c..9eadbb5652bba244195b85b07114aec08235e1b6 100644 --- a/port/devcons.c +++ b/port/devcons.c @@ -277,6 +277,7 @@ enum{ Qdir, Qauth, Qauthcheck, + Qauthent, Qclock, Qcons, Qconsctl, @@ -304,6 +305,7 @@ enum{ Dirtab consdir[]={ "authenticate", {Qauth}, 0, 0666, "authcheck", {Qauthcheck}, 0, 0666, + "authenticator", {Qauthent}, 0, 0666, "clock", {Qclock}, 2*NUMSIZE, 0444, "cons", {Qcons}, 0, 0660, "consctl", {Qconsctl}, 0, 0220, @@ -439,6 +441,7 @@ consclose(Chan *c) } case Qauth: case Qauthcheck: + case Qauthent: authclose(c); } } @@ -551,6 +554,9 @@ consread(Chan *c, void *buf, long n, ulong offset) case Qauth: return authread(c, cbuf, n); + case Qauthent: + return authentread(c, cbuf, n); + case Qhostowner: return readstr(offset, buf, n, eve); @@ -738,6 +744,9 @@ conswrite(Chan *c, void *va, long n, ulong offset) case Qauthcheck: return authcheck(c, a, n); + case Qauthent: + return authentwrite(c, a, n); + case Qnull: break; diff --git a/port/portdat.h b/port/portdat.h index ebd998d7f63ef666f089e78720182fd42f58ea73..9529d72a54b4a53b250a789a6be2ee98401ae8a6 100644 --- a/port/portdat.h +++ b/port/portdat.h @@ -305,7 +305,6 @@ struct Page ulong va; /* Virtual address for user */ ulong daddr; /* Disc address on swap */ ushort ref; /* Reference count */ - char lock; /* Software lock */ char modref; /* Simulated modify/reference bits */ char cachectl[MAXMACH]; /* Cache flushing control for putmmu */ Image *image; /* Associated text or swap image */ diff --git a/port/portfns.h b/port/portfns.h index c57071bc885513a7769b73d60a1d0c361b45b395..c8ab4a3f75cb6eb4428466d52b10a5ff89cb9f97 100644 --- a/port/portfns.h +++ b/port/portfns.h @@ -2,6 +2,8 @@ void addrootfile(char*, uchar*, ulong); void alarmkproc(void*); int anyready(void); Image* attachimage(int, Chan*, ulong, ulong); +long authentwrite(Chan*, char*, int); +long authentread(Chan*, char*, int); long authread(Chan*, char*, int); long authwrite(Chan*, char*, int); long authcheck(Chan*, char*, int); diff --git a/port/proc.c b/port/proc.c index 7ef8120af3906674f38d04c67ccd5dc8c34bc705..bf47bf007ac69477f0e8d8c7a72bf9515f965333 100644 --- a/port/proc.c +++ b/port/proc.c @@ -84,7 +84,6 @@ schedinit(void) /* never returns */ void sched(void) { - kmapinval(); if(up) { splhi(); m->cs++;