From 05490cdb1d38889d0d0e0fed6e5e48ee209cd86f Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 7 Apr 2001 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2001-04-07 --- port/devtls.c | 170 ++++++++++++++++++++++++++++---------------------- 1 file changed, 95 insertions(+), 75 deletions(-) diff --git a/port/devtls.c b/port/devtls.c index 8c8943dd56334c28f15010434ae0718eee694d41..13f42e305eaa874e5d66c785296c19710d25fc91 100644 --- a/port/devtls.c +++ b/port/devtls.c @@ -14,11 +14,12 @@ typedef struct OneWay OneWay; typedef struct Secret Secret; enum { + /* buffer limits */ MaxRecLen = 1<<14, /* max payload length of a record layer message */ MaxCipherRecLen = MaxRecLen + 2048, - -//ZZZ RecHdrLen = 5, + + /* protocol versions we can accept */ TLSVersion = 0x0301, SSL3Version = 0x0300, ProtocolVersion = 0x0301, /* maximum version we speak */ @@ -26,13 +27,13 @@ enum { MaxProtoVersion = 0x03ff, /* connection states */ - SHandshake = 1 << 0, // doing handshake - SOpen = 1 << 1, // application data can be sent - SRClose = 1 << 2, // remote side has closed down - SLClose = 1 << 3, // sent a close notify alert - SAlert = 1 << 5, // sending or sent a fatal alert - SError = 1 << 6, // some sort of error has occured - SClosed = 1 << 7, // it is all over + SHandshake = 1 << 0, /* doing handshake */ + SOpen = 1 << 1, /* application data can be sent */ + SRClose = 1 << 2, /* remote side has closed down */ + SLClose = 1 << 3, /* sent a close notify alert */ + SAlert = 1 << 5, /* sending or sent a fatal alert */ + SError = 1 << 6, /* some sort of error has occured */ + SClosed = 1 << 7, /* it is all over */ /* record types */ RChangeCipherSpec = 20, @@ -89,12 +90,12 @@ struct OneWay typedef struct TlsRec TlsRec; struct TlsRec { - Chan *c; /* io channel */ - int ref; /* serialized by dslock for atomic destroy */ - int version; /* version of the protocol we are speaking */ - char verset; /* version has been set */ - char opened; /* opened command every issued? */ - char err[ERRLEN]; /* error message to return to handshake requests */ + Chan *c; /* io channel */ + int ref; /* serialized by tdlock for atomic destroy */ + int version; /* version of the protocol we are speaking */ + char verset; /* version has been set */ + char opened; /* opened command every issued? */ + char err[ERRLEN]; /* error message to return to handshake requests */ Lock statelk; int state; @@ -104,13 +105,15 @@ struct TlsRec /* input side -- protected by in.io */ OneWay in; - Block *processed; /* next bunch of application data */ - Block *unprocessed; /* data read from c but not parsed into records */ + Block *processed; /* next bunch of application data */ + Block *unprocessed; /* data read from c but not parsed into records */ /* handshake queue */ - Lock hqlock; + Lock hqlock; /* protects hqref, alloc & free of handq, hprocessed */ int hqref; - Queue *handq; /* queue of handshake messages */ + Queue *handq; /* queue of handshake messages */ + Block *hprocessed; /* remainder of last block read from handq */ + QLock hqread; /* protects reads for hprocessed, handq */ /* output side */ OneWay out; @@ -178,18 +181,18 @@ static TlsErrs tlserrs[] = { 0, "handshake canceled by user"}, {ENoRenegotiation, EUnexpectedMessage, ENoRenegotiation, 0, "no renegotiation"}, - {-1}, }; enum { - Maxdstate = 64, + /* max. open tls connections */ + MaxTlsDevs = 1024 }; -static Lock dslock; -static int dshiwat; -static int maxdstate = 128; -static TlsRec** dstate; +static Lock tdlock; +static int tdhiwat; +static int maxtlsdevs = 128; +static TlsRec **tlsdevs; static char *encalgs; static char *hashalgs; @@ -206,7 +209,7 @@ enum{ }; #define TYPE(x) ((x).path & 0xf) -#define CONV(x) (((x).path >> 5)&(Maxdstate-1)) +#define CONV(x) (((x).path >> 5)&(MaxTlsDevs-1)) #define QID(c, y) (((c)<<5) | (y)) static void checkstate(TlsRec *, int, int); @@ -270,10 +273,10 @@ tlsgen(Chan *c, Dirtab *d, int nd, int s, Dir *dp) devdir(c, q, ".", 0, eve, CHDIR|0555, dp); return 1; } - if(s < dshiwat) { + if(s < tdhiwat) { sprint(name, "%d", s); q.path = QID(s, Qconvdir)|CHDIR; - ds = dstate[s]; + ds = tlsdevs[s]; if(ds != 0) nm = ds->user; else @@ -281,7 +284,7 @@ tlsgen(Chan *c, Dirtab *d, int nd, int s, Dir *dp) devdir(c, q, name, 0, nm, CHDIR|0555, dp); return 1; } - if(s > dshiwat) + if(s > tdhiwat) return -1; q.path = QID(0, Qclonus); devdir(c, q, "clone", 0, eve, 0555, dp); @@ -292,7 +295,7 @@ tlsgen(Chan *c, Dirtab *d, int nd, int s, Dir *dp) devdir(c, q, "tls", 0, eve, CHDIR|0555, dp); return 1; } - ds = dstate[CONV(c->qid)]; + ds = tlsdevs[CONV(c->qid)]; if(ds != 0) nm = ds->user; else @@ -327,7 +330,7 @@ tlsgen(Chan *c, Dirtab *d, int nd, int s, Dir *dp) devdir(c, c->qid, tlsnames[TYPE(c->qid)], 0, eve, 0555, dp); return 1; default: - ds = dstate[CONV(c->qid)]; + ds = tlsdevs[CONV(c->qid)]; devdir(c, c->qid, tlsnames[TYPE(c->qid)], 0, ds->user, 0660, dp); return 1; } @@ -396,11 +399,11 @@ tlsopen(Chan *c, int omode) case Qdata: case Qhand: if(waserror()) { - unlock(&dslock); + unlock(&tdlock); nexterror(); } - lock(&dslock); - pp = &dstate[CONV(c->qid)]; + lock(&tdlock); + pp = &tlsdevs[CONV(c->qid)]; tr = *pp; if(tr == nil) error("must open connection using clone"); @@ -425,7 +428,7 @@ tlsopen(Chan *c, int omode) poperror(); } tr->ref++; - unlock(&dslock); + unlock(&tdlock); poperror(); break; case Qencalgs: @@ -448,7 +451,7 @@ tlswstat(Chan *c, char *dp) convM2D(dp, &d); - tr = dstate[CONV(c->qid)]; + tr = tlsdevs[CONV(c->qid)]; if(tr == nil) error(Ebadusefd); if(strcmp(tr->user, up->user) != 0) @@ -463,9 +466,15 @@ static void dechandq(TlsRec *tr) { lock(&tr->hqlock); - if(--tr->hqref == 0 && tr->handq != nil){ - qfree(tr->handq); - tr->handq = nil; + if(--tr->hqref == 0){ + if(tr->handq != nil){ + qfree(tr->handq); + tr->handq = nil; + } + if(tr->hprocessed != nil){ + freeb(tr->hprocessed); + tr->hprocessed = nil; + } } unlock(&tr->hqlock); } @@ -484,20 +493,20 @@ tlsclose(Chan *c) if((c->flag & COPEN) == 0) break; - tr = dstate[CONV(c->qid)]; + tr = tlsdevs[CONV(c->qid)]; if(tr == nil) break; if(t == Qhand) dechandq(tr); - lock(&dslock); + lock(&tdlock); if(--tr->ref > 0) { - unlock(&dslock); + unlock(&tdlock); return; } - dstate[CONV(c->qid)] = nil; - unlock(&dslock); + tlsdevs[CONV(c->qid)] = nil; + unlock(&tdlock); if(tr->c != nil && !waserror()){ checkstate(tr, 0, SOpen|SHandshake|SRClose); @@ -943,7 +952,7 @@ tlsbread(Chan *c, long n, ulong offset) break; } - tr = dstate[CONV(c->qid)]; + tr = tlsdevs[CONV(c->qid)]; if(tr == nil) panic("tlsbread"); @@ -969,17 +978,30 @@ tlsbread(Chan *c, long n, ulong offset) * since it only protects reading records, * and we have that tr->in.io held. */ - while(!tr->opened && !qcanread(tr->handq)) + while(!tr->opened && tr->hprocessed == nil && !qcanread(tr->handq)) tlsrecread(tr); qunlock(&tr->in.io); poperror(); - b = qbread(tr->handq, n); - if(*b->rp++ == RAlert){ - strncpy(up->error, (char*)b->rp, ERRLEN - 1); - up->error[ERRLEN - 1] = '\0'; - error(up->error); + + if(waserror()){ + qunlock(&tr->hqread); + nexterror(); + } + qlock(&tr->hqread); + if(tr->hprocessed == nil){ + b = qbread(tr->handq, MaxRecLen + 1); + if(*b->rp++ == RAlert){ + strncpy(up->error, (char*)b->rp, ERRLEN - 1); + up->error[ERRLEN - 1] = '\0'; + freeb(b); + error(up->error); + } + tr->hprocessed = b; } + b = qremove(&tr->hprocessed, n, 0); + poperror(); + qunlock(&tr->hqread); } return b; @@ -1156,7 +1178,7 @@ tlsbwrite(Chan *c, Block *b, ulong offset) n = BLEN(b); - tr = dstate[CONV(c->qid)]; + tr = tlsdevs[CONV(c->qid)]; if(tr == nil) panic("tlsbread"); @@ -1261,7 +1283,7 @@ tlswrite(Chan *c, void *a, long n, vlong off) uchar *volatile x; ulong offset = off; - tr = dstate[CONV(c->qid)]; + tr = tlsdevs[CONV(c->qid)]; if(tr == nil) panic("tlswrite"); @@ -1305,7 +1327,6 @@ tlswrite(Chan *c, void *a, long n, vlong off) error("short control request"); /* mutex with operations using what we're about to change */ -//ZZZ check this locking if(waserror()){ qunlock(&tr->in.seclock); qunlock(&tr->out.seclock); @@ -1418,8 +1439,7 @@ tlswrite(Chan *c, void *a, long n, vlong off) lock(&tr->statelk); if(tr->state != SHandshake && tr->state != SOpen){ unlock(&tr->statelk); -//ZZZ bad error message - error("can't set open state"); + error("can't enable data messages"); } tr->state = SOpen; unlock(&tr->statelk); @@ -1463,7 +1483,7 @@ tlsinit(void) int n; char *cp; - if((dstate = smalloc(sizeof(TlsRec*) * maxdstate)) == 0) + if((tlsdevs = smalloc(sizeof(TlsRec*) * maxtlsdevs)) == 0) panic("tlsinit"); n = 1; @@ -1618,39 +1638,39 @@ newtls(Chan *ch) int t, newmax; if(waserror()) { - unlock(&dslock); + unlock(&tdlock); nexterror(); } - lock(&dslock); - ep = &dstate[maxdstate]; - for(pp = dstate; pp < ep; pp++) + lock(&tdlock); + ep = &tlsdevs[maxtlsdevs]; + for(pp = tlsdevs; pp < ep; pp++) if(*pp == nil) break; if(pp >= ep) { - if(maxdstate >= Maxdstate) { - unlock(&dslock); + if(maxtlsdevs >= MaxTlsDevs) { + unlock(&tdlock); poperror(); return nil; } - newmax = 2 * maxdstate; - if(newmax > Maxdstate) - newmax = Maxdstate; + newmax = 2 * maxtlsdevs; + if(newmax > MaxTlsDevs) + newmax = MaxTlsDevs; np = smalloc(sizeof(TlsRec*) * newmax); - memmove(np, dstate, sizeof(TlsRec*) * maxdstate); - dstate = np; - pp = &dstate[maxdstate]; - memset(pp, 0, sizeof(TlsRec*)*(newmax - maxdstate)); - maxdstate = newmax; + memmove(np, tlsdevs, sizeof(TlsRec*) * maxtlsdevs); + tlsdevs = np; + pp = &tlsdevs[maxtlsdevs]; + memset(pp, 0, sizeof(TlsRec*)*(newmax - maxtlsdevs)); + maxtlsdevs = newmax; } *pp = mktlsrec(); - if(pp - dstate >= dshiwat) - dshiwat++; + if(pp - tlsdevs >= tdhiwat) + tdhiwat++; t = TYPE(ch->qid); if(t == Qclonus) t = Qctl; - ch->qid.path = QID(pp - dstate, t); + ch->qid.path = QID(pp - tlsdevs, t); ch->qid.vers = 0; - unlock(&dslock); + unlock(&tdlock); poperror(); return *pp; }