@@ 1,25 1,25 @@
/*
- * template for making a new device
+ * devssl - secure sockets layer emulation
*/
+#include "u.h"
+#include "../port/lib.h"
+#include "../port/error.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "../port/error.h"
-#include <libcrypt.h>
+#include <libcrypt.h>
typedef struct OneWay OneWay;
struct OneWay
{
- QLock;
+ QLock q;
- void *state; /* encryption state */
- int slen; /* hash data length */
- uchar *secret; /* secret */
- ulong mid; /* message id */
+ void *state; /* encryption state */
+ int slen; /* hash data length */
+ uchar *secret; /* secret */
+ ulong mid; /* message id */
};
enum
@@ 35,7 35,7 @@ enum
/* encryption algorithms */
Noencryption= 0,
DESCBC= 1,
- DESECB= 2,
+ DESECB= 2
};
typedef struct Dstate Dstate;
@@ 64,12 64,12 @@ struct Dstate
enum
{
- Maxdmsg= 1<<16,
+ Maxdmsg= 1<<16
};
enum{
Qdir,
- Qclone,
+ Qclone
};
Dirtab digesttab[]={
"ssl", {Qclone, 0}, 0, 0666,
@@ 98,21 98,20 @@ static void checkdigestb(Dstate*, Block*);
static Chan* buftochan(char*, long);
static void dighangup(Dstate*);
-
void
sslreset(void)
{
- randq.ep = randq.buf + sizeof(randq.buf);
- randq.rp = randq.wp = randq.buf;
}
void
sslinit(void)
{
+ randq.ep = randq.buf + sizeof(randq.buf);
+ randq.rp = randq.wp = randq.buf;
}
Chan *
-sslattach(char *spec)
+sslattach(void *spec)
{
return devattach('D', spec);
}
@@ 142,7 141,7 @@ sslopen(Chan *c, int omode)
switch(c->qid.path & ~CHDIR){
case Qclone:
- s = smalloc(sizeof(Dstate));
+ s = malloc(sizeof(Dstate));
memset(s, 0, sizeof(*s));
s->state = Algwait;
c->aux = s;
@@ 154,7 153,10 @@ sslopen(Chan *c, int omode)
void
sslcreate(Chan *c, char *name, int omode, ulong perm)
{
- USED(c, name, omode, perm);
+ USED(c);
+ USED(name);
+ USED(omode);
+ USED(perm);
error(Eperm);
}
@@ 168,7 170,8 @@ sslremove(Chan *c)
void
sslwstat(Chan *c, char *dp)
{
- USED(c, dp);
+ USED(c);
+ USED(dp);
error(Eperm);
}
@@ 181,7 184,7 @@ sslclose(Chan *c)
s = c->aux;
dighangup(s);
if(s->c)
- close(s->c);
+ cclose(s->c);
if(s->in.secret)
free(s->in.secret);
if(s->out.secret)
@@ 193,81 196,81 @@ sslclose(Chan *c)
Block*
sslbread(Chan *c, long n, ulong offset)
{
- Dstate *s;
+ volatile struct { Dstate *s; } s;
Block *b;
uchar count[2];
int i, len, pad;
USED(offset);
- s = c->aux;
- if(s == 0 || s->state != Established)
+ s.s = c->aux;
+ if(s.s == 0 || s.s->state != Established)
error(Ebadusefd);
if(waserror()){
- qunlock(&s->in);
- dighangup(s);
+ qunlock(&s.s->in.q);
+ dighangup(s.s);
nexterror();
}
- qlock(&s->in);
+ qlock(&s.s->in.q);
- b = s->processed;
+ b = s.s->processed;
if(b == 0){
/* read in the whole message */
- s->processed = s->unprocessed;
- s->unprocessed = 0;
- ensure(s, &s->processed, 2);
- consume(&s->processed, count, 2);
+ s.s->processed = s.s->unprocessed;
+ s.s->unprocessed = 0;
+ ensure(s.s, &s.s->processed, 2);
+ consume(&s.s->processed, count, 2);
if(count[0] & 0x80){
len = ((count[0] & 0x7f)<<8) | count[1];
- ensure(s, &s->processed, len);
+ ensure(s.s, &s.s->processed, len);
pad = 0;
} else {
len = ((count[0] & 0x3f)<<8) | count[1];
- ensure(s, &s->processed, len+1);
- consume(&s->processed, count, 1);
+ ensure(s.s, &s.s->processed, len+1);
+ consume(&s.s->processed, count, 1);
pad = count[0];
}
/* trade memory bandwidth for less processing complexity */
- b = s->processed = pullupblock(s->processed, len);
+ b = s.s->processed = pullupblock(s.s->processed, len);
/* put remainder on unprocessed queue */
i = BLEN(b);
if(i > len){
i -= len;
- s->unprocessed = allocb(i);
- memmove(s->unprocessed->wp, b->rp+len, i);
- s->unprocessed->wp += i;
+ s.s->unprocessed = allocb(i);
+ memmove(s.s->unprocessed->wp, b->rp+len, i);
+ s.s->unprocessed->wp += i;
b->wp -= i;
}
- if(s->encryptalg)
- b = decryptb(s, b);
+ if(s.s->encryptalg)
+ b = decryptb(s.s, b);
else {
- if(BLEN(b) < s->diglen)
+ if(BLEN(b) < s.s->diglen)
error("baddigest");
- checkdigestb(s, b);
- b->rp += s->diglen;
+ checkdigestb(s.s, b);
+ b->rp += s.s->diglen;
}
/* remove pad */
if(b->wp - b->rp < pad)
panic("sslbread");
b->wp -= pad;
- s->processed = b;
+ s.s->processed = b;
}
if(BLEN(b) > n){
b = allocb(n);
- memmove(b->wp, s->processed->rp, n);
+ memmove(b->wp, s.s->processed->rp, n);
b->wp += n;
- s->processed->rp += n;
+ s.s->processed->rp += n;
} else
- s->processed = b->next;
+ s.s->processed = b->next;
- qunlock(&s->in);
+ qunlock(&s.s->in.q);
poperror();
return b;
@@ 276,23 279,23 @@ sslbread(Chan *c, long n, ulong offset)
long
sslread(Chan *c, void *a, long n, ulong offset)
{
- Block *b;
+ volatile struct { Block *b; } b;
switch(c->qid.path & ~CHDIR){
case Qdir:
return devdirread(c, a, n, digesttab, Ndigesttab, devgen);
}
- b = sslbread(c, n, offset);
+ b.b = sslbread(c, n, offset);
if(waserror()){
- freeb(b);
+ freeb(b.b);
nexterror();
}
- n = BLEN(b);
- memmove(a, b->rp, n);
- freeb(b);
+ n = BLEN(b.b);
+ memmove(a, b.b->rp, n);
+ freeb(b.b);
poperror();
@@ 305,41 308,43 @@ sslread(Chan *c, void *a, long n, ulong offset)
long
sslbwrite(Chan *c, Block *b, ulong offset)
{
- Dstate *s;
+ volatile struct { Dstate *s; } s;
+ volatile struct { Block *b; } bb;
Block *nb;
int h, n, m, pad, rv;
uchar *p;
- s = c->aux;
- if(s == 0 || s->state != Established)
+ bb.b = b;
+ s.s = c->aux;
+ if(s.s == 0 || s.s->state != Established)
error(Ebadusefd);
if(waserror()){
- qunlock(&s->out);
- if(b)
- freeb(b);
- dighangup(s);
+ qunlock(&s.s->out.q);
+ if(bb.b)
+ freeb(bb.b);
+ dighangup(s.s);
nexterror();
}
- qlock(&s->out);
+ qlock(&s.s->out.q);
rv = 0;
- while(b){
- m = n = BLEN(b);
- h = s->diglen + 2;
+ while(bb.b){
+ m = n = BLEN(bb.b);
+ h = s.s->diglen + 2;
/* trim to maximum block size */
pad = 0;
- if(m > s->max){
- m = s->max;
- } else if(s->blocklen != 1){
- pad = m%s->blocklen;
+ if(m > s.s->max){
+ m = s.s->max;
+ } else if(s.s->blocklen != 1){
+ pad = m%s.s->blocklen;
if(pad){
- if(m > s->maxpad){
+ if(m > s.s->maxpad){
pad = 0;
- m = s->maxpad;
+ m = s.s->maxpad;
} else {
- pad = s->blocklen - pad;
+ pad = s.s->blocklen - pad;
h++;
}
}
@@ 348,16 353,15 @@ sslbwrite(Chan *c, Block *b, ulong offset)
rv += m;
if(m != n){
nb = allocb(m + h + pad);
- memmove(nb->wp + h, b->rp, m);
+ memmove(nb->wp + h, bb.b->rp, m);
nb->wp += m + h;
- b->rp += m;
+ bb.b->rp += m;
} else {
/* add header space */
- nb = padblock(b, h);
- nb->rp -= h;
- b = 0;
+ nb = padblock(bb.b, h);
+ bb.b = 0;
}
- m += s->diglen;
+ m += s.s->diglen;
/* SSL style count */
if(pad){
@@ 378,15 382,15 @@ sslbwrite(Chan *c, Block *b, ulong offset)
offset = 2;
}
- if(s->encryptalg)
- nb = encryptb(s, nb, offset);
+ if(s.s->encryptalg)
+ nb = encryptb(s.s, nb, offset);
else
- nb = digestb(s, nb, offset);
+ nb = digestb(s.s, nb, offset);
- (*devtab[s->c->type].bwrite)(s->c, nb, offset);
+ (*devtab[s.s->c->type].bwrite)(s.s->c, nb, offset);
}
- qunlock(&s->out);
+ qunlock(&s.s->out.q);
poperror();
return rv;
@@ 396,7 400,7 @@ long
sslwrite(Chan *c, void *a, long n, ulong offset)
{
Dstate *s;
- Block *b;
+ volatile struct { Block *b; } b;
int m;
char *p, *e, buf[32];
@@ 465,16 469,16 @@ sslwrite(Chan *c, void *a, long n, ulong offset)
if(m > s->max)
m = s->max;
- b = allocb(m);
+ b.b = allocb(m);
if(waserror()){
- freeb(b);
+ freeb(b.b);
nexterror();
}
- memmove(b->wp, p, m);
+ memmove(b.b->wp, p, m);
poperror();
- b->wp += m;
+ b.b->wp += m;
- sslbwrite(c, b, offset);
+ sslbwrite(c, b.b, offset);
}
break;
default:
@@ 544,7 548,7 @@ consume(Block **l, uchar *p, int n)
static void
setsecret(Dstate *s, OneWay *w, uchar *secret, int n)
{
- w->secret = smalloc(n);
+ w->secret = malloc(n);
memmove(w->secret, secret, n);
w->slen = n;
w->mid = 0;
@@ 553,13 557,13 @@ setsecret(Dstate *s, OneWay *w, uchar *secret, int n)
case DESECB:
if(n < 8)
error("secret too small");
- w->state = smalloc(sizeof(DESstate));
+ w->state = malloc(sizeof(DESstate));
setupDESstate(w->state, secret, 0);
break;
case DESCBC:
if(n < 16)
error("secret too small");
- w->state = smalloc(sizeof(DESstate));
+ w->state = malloc(sizeof(DESstate));
setupDESstate(w->state, secret, secret+8);
break;
}
@@ 714,7 718,7 @@ dighangup(Dstate *s)
{
Block *b;
- qlock(&s->in);
+ qlock(&s->in.q);
for(b = s->processed; b; b = s->processed){
s->processed = b->next;
freeb(b);
@@ 724,7 728,7 @@ dighangup(Dstate *s)
s->unprocessed = 0;
}
s->state = Closed;
- qunlock(&s->in);
+ qunlock(&s->in.q);
}
/*
@@ 735,9 739,9 @@ void
handle_exception(int type, char *exception)
{
if(type == CRITICAL)
- panic("kernel ssl: %s", exception);
+ panic("crypt library (devssl): %s", exception);
else
- print("kernel ssl: %s\n", exception);
+ print("crypt library (devssl): %s\n", exception);
}
void*
@@ 745,7 749,7 @@ crypt_malloc(int size)
{
void *x;
- x = smalloc(size);
+ x = malloc(size);
if(x == 0)
handle_exception(CRITICAL, "out of memory");
return x;
@@ 758,4 762,3 @@ crypt_free(void *x)
handle_exception(CRITICAL, "freeing null pointer");
free(x);
}
-
@@ 1,320 0,0 @@
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "../port/error.h"
-
-enum
-{
- Qlisten = 1,
- Qclone = 2,
- Q2nd = 3,
- Q3rd = 4,
- Qinf = 5,
-};
-
-/*
- * find protection structure
- */
-static Netprot*
-findprot(Network *np, int id)
-{
- Netprot *p;
-
- for(p = np->prot; p; p = p->next)
- if(p->id == id)
- break;
- return p;
-}
-
-/*
- * generate a 3 level directory
- */
-int
-netgen(Chan *c, void *vp, int, int i, Dir *dp)
-{
- Qid q;
- char buf[32];
- Network *np = vp;
- int t;
- Netprot *p;
- int perm;
- char *o;
-
- q.vers = 0;
-
- /* top level directory contains the name of the network */
- if(c->qid.path == CHDIR){
- switch(i){
- case 0:
- q.path = CHDIR | Q2nd;
- strcpy(buf, np->name);
- devdir(c, q, buf, 0, eve, 0555, dp);
- break;
- default:
- return -1;
- }
- return 1;
- }
-
- /* second level contains clone plus all the conversations */
- t = NETTYPE(c->qid.path);
- if(t == Q2nd || t == Qclone){
- if(i == 0){
- q.path = Qclone;
- devdir(c, q, "clone", 0, eve, 0666, dp);
- }else if(i <= np->nconv){
- if(findprot(np, i-1) == 0)
- return 0;
- q.path = CHDIR|NETQID(i-1, Q3rd);
- sprint(buf, "%d", i-1);
- devdir(c, q, buf, 0, eve, 0555, dp);
- }else
- return -1;
- return 1;
- }
-
- /* third level depends on the number of info files */
- p = findprot(np, NETID(c->qid.path));
- if(p == 0)
- return 0;
- if(*p->owner){
- o = p->owner;
- perm = p->mode;
- } else {
- o = eve;
- perm = 0666;
- }
- switch(i){
- case 0:
- q.path = NETQID(NETID(c->qid.path), Ndataqid);
- devdir(c, q, "data", 0, o, perm, dp);
- break;
- case 1:
- q.path = NETQID(NETID(c->qid.path), Nctlqid);
- devdir(c, q, "ctl", 0, o, perm, dp);
- break;
- case 2:
- if(np->listen == 0)
- return 0;
- q.path = NETQID(NETID(c->qid.path), Qlisten);
- devdir(c, q, "listen", 0, o, perm, dp);
- break;
- default:
- i -= 3;
- if(i >= np->ninfo)
- return -1;
- q.path = NETQID(NETID(c->qid.path), Qinf+i);
- devdir(c, q, np->info[i].name, 0, eve, 0444, dp);
- break;
- }
- return 1;
-}
-
-int
-netwalk(Chan *c, char *name, Network *np)
-{
- if(strcmp(name, "..") == 0) {
- switch(NETTYPE(c->qid.path)){
- case Q2nd:
- c->qid.path = CHDIR;
- break;
- case Q3rd:
- c->qid.path = CHDIR|Q2nd;
- break;
- default:
- panic("netwalk %lux", c->qid.path);
- }
- return 1;
- }
-
- return devwalk(c, name, (Dirtab*)np, 0, netgen);
-}
-
-void
-netstat(Chan *c, char *db, Network *np)
-{
- int i;
- Dir dir;
-
- for(i=0;; i++)
- switch(netgen(c, (Dirtab*)np, 0, i, &dir)){
- case -1:
- /*
- * devices with interesting directories usually don't get
- * here, which is good because we've lost the name by now.
- */
- if(c->qid.path & CHDIR){
- devdir(c, c->qid, c->path->elem, 0L, eve, CHDIR|0555, &dir);
- convD2M(&dir, db);
- return;
- }
- print("netstat %C %lux\n", devchar[c->type], c->qid.path);
- error(Enonexist);
- case 0:
- break;
- case 1:
- if(eqqid(c->qid, dir.qid)){
- if(c->flag&CMSG)
- dir.mode |= CHMOUNT;
- convD2M(&dir, db);
- return;
- }
- break;
- }
-}
-
-Chan *
-netopen(Chan *c, int omode, Network *np)
-{
- int id = 0;
- Netprot *p;
-
- if(c->qid.path & CHDIR){
- if(omode != OREAD)
- error(Eperm);
- } else {
- switch(NETTYPE(c->qid.path)){
- case Ndataqid:
- case Nctlqid:
- id = NETID(c->qid.path);
- id = (*np->open)(c, id);
- break;
- case Qlisten:
- id = (*np->listen)(c);
- c->qid.path = NETQID(id, Nctlqid);
- ptclone(c, 1, id);
- break;
- case Qclone:
- id = (*np->open)(c, -1);
- c->qid.path = NETQID(id, Nctlqid);
- ptclone(c, 0, id);
- break;
- default:
- if(omode != OREAD)
- error(Ebadarg);
- }
- switch(NETTYPE(c->qid.path)){
- case Ndataqid:
- case Nctlqid:
- p = findprot(np, id);
- if(netown(p, up->user, omode&7) < 0)
- error(Eperm);
- break;
- }
- }
- c->mode = openmode(omode);
- c->flag |= COPEN;
- c->offset = 0;
- return c;
-}
-
-long
-netread(Chan *c, void *a, long n, ulong offset, Network *np)
-{
- int t;
- char buf[256];
-
- if(c->qid.path&CHDIR)
- return devdirread(c, a, n, (Dirtab*)np, 0, netgen);
-
- t = NETTYPE(c->qid.path);
- if(t == Nctlqid)
- readnum(offset, a, n, NETID(c->qid.path), NUMSIZE);
-
- if(t < Qinf || t >= Qinf + np->ninfo)
- error(Ebadusefd);
-
- (*np->info[t-Qinf].fill)(c, buf, sizeof(buf));
- return readstr(offset, a, n, buf);
-}
-
-void
-netadd(Network *np, Netprot *p, int id)
-{
- Netprot **l, *pp;
-
- memset(p, 0, sizeof(Netprot));
- p->id = id;
- p->net = np;
-
- l = &np->prot;
- for(pp = np->prot; pp; pp = pp->next){
- if(pp->id == id)
- panic("netadd");
- l = &pp->next;
- }
- *l = p;
-}
-
-Lock netlock;
-
-int
-netown(Netprot *p, char *o, int omode)
-{
- static int access[] = { 0400, 0200, 0600, 0100 };
- int mode;
- int t;
-
- lock(&netlock);
- if(*p->owner){
- if(strncmp(o, p->owner, NAMELEN) == 0) /* User */
- mode = p->mode;
- else if(strncmp(o, eve, NAMELEN) == 0) /* Bootes is group */
- mode = p->mode<<3;
- else
- mode = p->mode<<6; /* Other */
-
- t = access[omode&3];
- if((t & mode) == t){
- unlock(&netlock);
- return 0;
- } else {
- unlock(&netlock);
- return -1;
- }
- }
- strncpy(p->owner, o, NAMELEN);
- p->mode = 0660;
- unlock(&netlock);
- return 0;
-}
-
-void
-netdisown(Netprot *p)
-{
- p->owner[0] = 0;
-}
-
-#undef CHDIR /* BUG */
-#include "/sys/src/libc/9syscall/sys.h"
-
-void
-netwstat(Chan *c, char *db, Network *np)
-{
- Dir dir;
- Netprot *p;
-
- p = findprot(np, NETID(c->qid.path));
- if(p == 0)
- error(Enonexist);
- lock(np);
-
- /*
- * A network channel's ownership/permissions can be changed only if the
- * wstat is by the owner or (HACK!) if it is performed using an fwstat.
- * The latter allows processes started by a network listener to gain
- * ownership of the connection. The open file descriptor is used as
- * a capability for the connection.
- */
- if(strncmp(p->owner, up->user, NAMELEN) != 0 && up->scallnr != FWSTAT){
- unlock(np);
- error(Eperm);
- }
- convM2D(db, &dir);
- strncpy(p->owner, dir.uid, NAMELEN);
- p->mode = dir.mode;
-
- unlock(np);
-}