📄 devtls.c
字号:
static longtlswrite(Chan *c, void *a, long n, vlong off){ Encalg *ea; Hashalg *ha; TlsRec *volatile tr; Secret *volatile tos, *volatile toc; Block *volatile b; Cmdbuf *volatile cb; int m, ty; char *p, *e; uchar *volatile x; ulong offset = off; tr = tlsdevs[CONV(c->qid)]; if(tr == nil) panic("tlswrite"); ty = TYPE(c->qid); switch(ty){ case Qdata: case Qhand: p = a; e = p + n; do{ m = e - p; if(m > MaxRecLen) m = MaxRecLen; b = allocb(m); if(waserror()){ freeb(b); nexterror(); } memmove(b->wp, p, m); poperror(); b->wp += m; tlsbwrite(c, b, offset); p += m; }while(p < e); return n; case Qctl: break; default: error(Ebadusefd); return -1; } cb = parsecmd(a, n); if(waserror()){ free(cb); nexterror(); } if(cb->nf < 1) error("short control request"); /* mutex with operations using what we're about to change */ if(waserror()){ qunlock(&tr->in.seclock); qunlock(&tr->out.seclock); nexterror(); } qlock(&tr->in.seclock); qlock(&tr->out.seclock); if(strcmp(cb->f[0], "fd") == 0){ if(cb->nf != 3) error("usage: fd open-fd version"); if(tr->c != nil) error(Einuse); m = strtol(cb->f[2], nil, 0); if(m < MinProtoVersion || m > MaxProtoVersion) error("unsupported version"); tr->c = buftochan(cb->f[1]); tr->version = m; tlsSetState(tr, SHandshake, SClosed); }else if(strcmp(cb->f[0], "version") == 0){ if(cb->nf != 2) error("usage: version vers"); if(tr->c == nil) error("must set fd before version"); if(tr->verset) error("version already set"); m = strtol(cb->f[1], nil, 0); if(m == SSL3Version) tr->packMac = sslPackMac; else if(m == TLSVersion) tr->packMac = tlsPackMac; else error("unsupported version"); tr->verset = 1; tr->version = m; }else if(strcmp(cb->f[0], "secret") == 0){ if(cb->nf != 5) error("usage: secret hashalg encalg isclient secretdata"); if(tr->c == nil || !tr->verset) error("must set fd and version before secrets"); if(tr->in.new != nil){ freeSec(tr->in.new); tr->in.new = nil; } if(tr->out.new != nil){ freeSec(tr->out.new); tr->out.new = nil; } ha = parsehashalg(cb->f[1]); ea = parseencalg(cb->f[2]); p = cb->f[4]; m = (strlen(p)*3)/2; x = smalloc(m); tos = nil; toc = nil; if(waserror()){ freeSec(tos); freeSec(toc); free(x); nexterror(); } m = dec64(x, m, p, strlen(p)); if(m < 2 * ha->maclen + 2 * ea->keylen + 2 * ea->ivlen) error("not enough secret data provided"); tos = smalloc(sizeof(Secret)); toc = smalloc(sizeof(Secret)); if(!ha->initkey || !ea->initkey) error("misimplemented secret algorithm"); (*ha->initkey)(ha, tr->version, tos, &x[0]); (*ha->initkey)(ha, tr->version, toc, &x[ha->maclen]); (*ea->initkey)(ea, tos, &x[2 * ha->maclen], &x[2 * ha->maclen + 2 * ea->keylen]); (*ea->initkey)(ea, toc, &x[2 * ha->maclen + ea->keylen], &x[2 * ha->maclen + 2 * ea->keylen + ea->ivlen]); if(!tos->mac || !tos->enc || !tos->dec || !toc->mac || !toc->enc || !toc->dec) error("missing algorithm implementations"); if(strtol(cb->f[3], nil, 0) == 0){ tr->in.new = tos; tr->out.new = toc; }else{ tr->in.new = toc; tr->out.new = tos; } if(tr->version == SSL3Version){ toc->unpad = sslunpad; tos->unpad = sslunpad; }else{ toc->unpad = tlsunpad; tos->unpad = tlsunpad; } toc->encalg = ea->name; toc->hashalg = ha->name; tos->encalg = ea->name; tos->hashalg = ha->name; free(x); poperror(); }else if(strcmp(cb->f[0], "changecipher") == 0){ if(cb->nf != 1) error("usage: changecipher"); if(tr->out.new == nil) error("cannot change cipher spec without setting secret"); qunlock(&tr->in.seclock); qunlock(&tr->out.seclock); poperror(); free(cb); poperror(); /* * the real work is done as the message is written * so the stream is encrypted in sync. */ b = allocb(1); *b->wp++ = 1; tlsrecwrite(tr, RChangeCipherSpec, b); return n; }else if(strcmp(cb->f[0], "opened") == 0){ if(cb->nf != 1) error("usage: opened"); if(tr->in.sec == nil || tr->out.sec == nil) error("cipher must be configured before enabling data messages"); lock(&tr->statelk); if(tr->state != SHandshake && tr->state != SOpen){ unlock(&tr->statelk); error("cannot enable data messages"); } tr->state = SOpen; unlock(&tr->statelk); tr->opened = 1; }else if(strcmp(cb->f[0], "alert") == 0){ if(cb->nf != 2) error("usage: alert n"); if(tr->c == nil) error("must set fd before sending alerts"); m = strtol(cb->f[1], nil, 0); qunlock(&tr->in.seclock); qunlock(&tr->out.seclock); poperror(); free(cb); poperror(); sendAlert(tr, m); if(m == ECloseNotify) tlsclosed(tr, SLClose); return n; } else if(strcmp(cb->f[0], "debug") == 0){ if(cb->nf == 2){ if(strcmp(cb->f[1], "on") == 0) tr->debug = 1; else tr->debug = 0; } else tr->debug = 1; } else error(Ebadarg); qunlock(&tr->in.seclock); qunlock(&tr->out.seclock); poperror(); free(cb); poperror(); return n;}static voidtlsinit(void){ struct Encalg *e; struct Hashalg *h; int n; char *cp; static int already; if(!already){ fmtinstall('H', encodefmt); already = 1; } tlsdevs = smalloc(sizeof(TlsRec*) * maxtlsdevs); trnames = smalloc((sizeof *trnames) * maxtlsdevs); n = 1; for(e = encrypttab; e->name != nil; e++) n += strlen(e->name) + 1; cp = encalgs = smalloc(n); for(e = encrypttab;;){ strcpy(cp, e->name); cp += strlen(e->name); e++; if(e->name == nil) break; *cp++ = ' '; } *cp = 0; n = 1; for(h = hashtab; h->name != nil; h++) n += strlen(h->name) + 1; cp = hashalgs = smalloc(n); for(h = hashtab;;){ strcpy(cp, h->name); cp += strlen(h->name); h++; if(h->name == nil) break; *cp++ = ' '; } *cp = 0;}Dev tlsdevtab = { 'a', "tls", devreset, tlsinit, devshutdown, tlsattach, tlswalk, tlsstat, tlsopen, devcreate, tlsclose, tlsread, tlsbread, tlswrite, tlsbwrite, devremove, tlswstat,};/* get channel associated with an fd */static Chan*buftochan(char *p){ Chan *c; int fd; if(p == 0) error(Ebadarg); fd = strtoul(p, 0, 0); if(fd < 0) error(Ebadarg); c = fdtochan(fd, -1, 0, 1); /* error check and inc ref */ return c;}static voidsendAlert(TlsRec *tr, int err){ Block *b; int i, fatal; char *msg;if(tr->debug)pprint("sendAlert %d\n", err); fatal = 1; msg = "tls unknown alert"; for(i=0; i < nelem(tlserrs); i++) { if(tlserrs[i].err == err) { msg = tlserrs[i].msg; if(tr->version == SSL3Version) err = tlserrs[i].sslerr; else err = tlserrs[i].tlserr; fatal = tlserrs[i].fatal; break; } } if(!waserror()){ b = allocb(2); *b->wp++ = fatal + 1; *b->wp++ = err; if(fatal) tlsSetState(tr, SAlert, SOpen|SHandshake|SRClose); tlsrecwrite(tr, RAlert, b); poperror(); } if(fatal) tlsError(tr, msg);}static voidtlsError(TlsRec *tr, char *msg){ int s;if(tr->debug)pprint("tleError %s\n", msg); lock(&tr->statelk); s = tr->state; tr->state = SError; if(s != SError){ strncpy(tr->err, msg, ERRMAX - 1); tr->err[ERRMAX - 1] = '\0'; } unlock(&tr->statelk); if(s != SError) alertHand(tr, msg);}static voidtlsSetState(TlsRec *tr, int new, int old){ lock(&tr->statelk); if(tr->state & old) tr->state = new; unlock(&tr->statelk);}/* hand up a digest connection */static voidtlshangup(TlsRec *tr){ Block *b; qlock(&tr->in.io); for(b = tr->processed; b; b = tr->processed){ tr->processed = b->next; freeb(b); } if(tr->unprocessed != nil){ freeb(tr->unprocessed); tr->unprocessed = nil; } qunlock(&tr->in.io); tlsSetState(tr, SClosed, ~0);}static TlsRec*newtls(Chan *ch){ TlsRec **pp, **ep, **np; char **nmp; int t, newmax; if(waserror()) { unlock(&tdlock); nexterror(); } lock(&tdlock); ep = &tlsdevs[maxtlsdevs]; for(pp = tlsdevs; pp < ep; pp++) if(*pp == nil) break; if(pp >= ep) { if(maxtlsdevs >= MaxTlsDevs) { unlock(&tdlock); poperror(); return nil; } newmax = 2 * maxtlsdevs; if(newmax > MaxTlsDevs) newmax = MaxTlsDevs; np = smalloc(sizeof(TlsRec*) * newmax); memmove(np, tlsdevs, sizeof(TlsRec*) * maxtlsdevs); tlsdevs = np; pp = &tlsdevs[maxtlsdevs]; memset(pp, 0, sizeof(TlsRec*)*(newmax - maxtlsdevs)); nmp = smalloc(sizeof *nmp * newmax); memmove(nmp, trnames, sizeof *nmp * maxtlsdevs); trnames = nmp; maxtlsdevs = newmax; } *pp = mktlsrec(); if(pp - tlsdevs >= tdhiwat) tdhiwat++; t = TYPE(ch->qid); if(t == Qclonus) t = Qctl; ch->qid.path = QID(pp - tlsdevs, t); ch->qid.vers = 0; unlock(&tdlock); poperror(); return *pp;}static TlsRec *mktlsrec(void){ TlsRec *tr; tr = mallocz(sizeof(*tr), 1); if(tr == nil) error(Enomem); tr->state = SClosed; tr->ref = 1; kstrdup(&tr->user, up->user); tr->perm = 0660; return tr;}static char*tlsstate(int s){ switch(s){ case SHandshake: return "Handshaking"; case SOpen: return "Established"; case SRClose: return "RemoteClosed"; case SLClose: return "LocalClosed"; case SAlert: return "Alerting"; case SError: return "Errored"; case SClosed: return "Closed"; } return "Unknown";}static voidfreeSec(Secret *s){ if(s != nil){ free(s->enckey); free(s); }}static intnoenc(Secret *s, uchar *u, int n){ return n;}static intrc4enc(Secret *sec, uchar *buf, int n){ rc4(sec->enckey, buf, n); return n;}static inttlsunpad(uchar *buf, int n, int block){ int pad, nn; pad = buf[n - 1]; nn = n - 1 - pad; if(nn <= 0 || n % block) return -1; while(--n > nn) if(pad != buf[n - 1]) return -1; return nn;}static intsslunpad(uchar *buf, int n, int block){ int pad, nn; pad = buf[n - 1]; nn = n - 1 - pad; if(nn <= 0 || n % block) return -1; return nn;}static intblockpad(uchar *buf, int n, int block){ int pad, nn; nn = n + block; nn -= nn % block; pad = nn - (n + 1); while(n < nn) buf[n++] = pad; return nn;} static intdes3enc(Secret *sec, uchar *buf, int n){ n = blockpad(buf, n, 8); des3CBCencrypt(buf, n, sec->enckey); return n;}static intdes3dec(Secret *sec, uchar *buf, int n){ des3CBCdecrypt(buf, n, sec->enckey); return (*sec->unpad)(buf, n, 8);}static DigestState*nomac(uchar *a, ulong b, uchar *c, ulong d, uchar *e, DigestState *f){ return nil;}/* * sslmac: mac calculations for ssl 3.0 only; tls 1.0 uses the standard hmac. */static DigestState*sslmac_x(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s, DigestState*(*x)(uchar*, ulong, uchar*, DigestState*), int xlen, int padlen){ int i; uchar pad[48], innerdigest[20]; if(xlen > sizeof(innerdigest) || padlen > sizeof(pad)) return nil; if(klen>64) return nil; /* first time through */ if(s == nil){ for(i=0; i<padlen; i++) pad[i] = 0x36; s = (*x)(key, klen, nil, nil); s = (*x)(pad, padlen, nil, s); if(s == nil) return nil; } s = (*x)(p, len, nil, s); if(digest == nil) return s; /* last time through */ for(i=0; i<padlen; i++) pad[i] = 0x5c; (*x)(nil, 0, innerdigest, s); s = (*x)(key, klen, nil, nil); s = (*x)(pad, padlen, nil, s); (*x)(innerdigest, xlen, digest, s); return nil;}static DigestState*sslmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s){ return sslmac_x(p, len, key, klen, digest, s, sha1, SHA1dlen, 40);}static DigestState*sslmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s){ return sslmac_x(p, len, key, klen, digest, s, md5, MD5dlen, 48);}static voidsslPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac){ DigestState *s; uchar buf[11]; memmove(buf, seq, 8); buf[8] = header[0]; buf[9] = header[3]; buf[10] = header[4]; s = (*sec->mac)(buf, 11, mackey, sec->maclen, 0, 0); (*sec->mac)(body, len, mackey, sec->maclen, mac, s);}static voidtlsPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac){ DigestState *s; uchar buf[13]; memmove(buf, seq, 8); memmove(&buf[8], header, 5); s = (*sec->mac)(buf, 13, mackey, sec->maclen, 0, 0); (*sec->mac)(body, len, mackey, sec->maclen, mac, s);}static voidput32(uchar *p, u32int x){ p[0] = x>>24; p[1] = x>>16; p[2] = x>>8; p[3] = x;}static voidput64(uchar *p, vlong x){ put32(p, (u32int)(x >> 32)); put32(p+4, (u32int)x);}static voidput24(uchar *p, int x){ p[0] = x>>16; p[1] = x>>8; p[2] = x;}static voidput16(uchar *p, int x){ p[0] = x>>8; p[1] = x;}#if 0static u32intget32(uchar *p){ return (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];}#endifstatic intget16(uchar *p){ return (p[0]<<8)|p[1];}static char *charmap = "0123456789abcdef";static voidpdump(int len, void *a, char *tag){ uchar *p; int i; char buf[65+32]; char *q; p = a; strcpy(buf, tag); while(len > 0){ q = buf + strlen(tag); for(i = 0; len > 0 && i < 32; i++){ if(*p >= ' ' && *p < 0x7f){ *q++ = ' '; *q++ = *p; } else { *q++ = charmap[*p>>4]; *q++ = charmap[*p & 0xf]; } len--; p++; } *q = 0; if(len > 0) pprint("%s...\n", buf); else pprint("%s\n", buf); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -