📄 esp.c
字号:
ecb->header = 1; else if(strcmp(f[0], "noheader") == 0) ecb->header = 0; else e = "unknown control request"; return e;}voidespadvise(Proto *esp, Block *bp, char *msg){ Esphdr *h; Conv *c; ulong spi; h = (Esphdr*)(bp->rp); spi = nhgets(h->espspi); qlock(esp); c = convlookup(esp, spi); if(c != nil) { qhangup(c->rq, msg); qhangup(c->wq, msg); } qunlock(esp); freeblist(bp);}intespstats(Proto *esp, char *buf, int len){ Esppriv *upriv; upriv = esp->priv; return snprint(buf, len, "%lud %lud\n", upriv->in, upriv->inerrors);}static intesplocal(Conv *c, char *buf, int len){ Espcb *ecb = c->ptcl; int n; qlock(c); if(ecb->incoming) n = snprint(buf, len, "%I!%uld\n", c->laddr, ecb->spi); else n = snprint(buf, len, "%I\n", c->laddr); qunlock(c); return n;}static intespremote(Conv *c, char *buf, int len){ Espcb *ecb = c->ptcl; int n; qlock(c); if(ecb->incoming) n = snprint(buf, len, "%I\n", c->raddr); else n = snprint(buf, len, "%I!%uld\n", c->raddr, ecb->spi); qunlock(c); return n;}static Conv*convlookup(Proto *esp, ulong spi){ Conv *c, **p; Espcb *ecb; for(p=esp->conv; *p; p++){ c = *p; ecb = c->ptcl; if(ecb->incoming && ecb->spi == spi) return c; } return nil;}static char *setalg(Espcb *ecb, char **f, int n, Algorithm *alg){ uchar *key; int i, nbyte, nchar; int c; if(n < 2) return "bad format"; for(; alg->name; alg++) if(strcmp(f[1], alg->name) == 0) break; if(alg->name == nil) return "unknown algorithm"; if(n != 3) return "bad format"; nbyte = (alg->keylen + 7) >> 3; nchar = strlen(f[2]); for(i=0; i<nchar; i++) { c = f[2][i]; if(c >= '0' && c <= '9') f[2][i] -= '0'; else if(c >= 'a' && c <= 'f') f[2][i] -= 'a'-10; else if(c >= 'A' && c <= 'F') f[2][i] -= 'A'-10; else return "bad character in key"; } key = smalloc(nbyte); for(i=0; i<nchar && i*2<nbyte; i++) { c = f[2][nchar-i-1]; if(i&1) c <<= 4; key[i>>1] |= c; } alg->init(ecb, alg->name, key, alg->keylen); free(key); return nil;}static intnullcipher(Espcb*, uchar*, int){ return 1;}static voidnullespinit(Espcb *ecb, char *name, uchar*, int){ ecb->espalg = name; ecb->espblklen = 1; ecb->espivlen = 0; ecb->cipher = nullcipher;}static intnullauth(Espcb*, uchar*, int, uchar*){ return 1;}static voidnullahinit(Espcb *ecb, char *name, uchar*, int){ ecb->ahalg = name; ecb->ahblklen = 1; ecb->ahlen = 0; ecb->auth = nullauth;}voidseanq_hmac_sha1(uchar hash[SHA1dlen], uchar *t, long tlen, uchar *key, long klen){ uchar ipad[65], opad[65]; int i; DigestState *digest; uchar innerhash[SHA1dlen]; for(i=0; i<64; i++){ ipad[i] = 0x36; opad[i] = 0x5c; } ipad[64] = opad[64] = 0; for(i=0; i<klen; i++){ ipad[i] ^= key[i]; opad[i] ^= key[i]; } digest = sha1(ipad, 64, nil, nil); sha1(t, tlen, innerhash, digest); digest = sha1(opad, 64, nil, nil); sha1(innerhash, SHA1dlen, hash, digest);}static intshaauth(Espcb *ecb, uchar *t, int tlen, uchar *auth){ uchar hash[SHA1dlen]; int r; memset(hash, 0, SHA1dlen); seanq_hmac_sha1(hash, t, tlen, (uchar*)ecb->ahstate, 16); r = memcmp(auth, hash, ecb->ahlen) == 0; memmove(auth, hash, ecb->ahlen); return r;}static voidshaahinit(Espcb *ecb, char *name, uchar *key, int klen){ if(klen != 128) panic("shaahinit: bad keylen"); klen >>= 8; // convert to bytes ecb->ahalg = name; ecb->ahblklen = 1; ecb->ahlen = 12; ecb->auth = shaauth; ecb->ahstate = smalloc(klen); memmove(ecb->ahstate, key, klen);}voidseanq_hmac_md5(uchar hash[MD5dlen], uchar *t, long tlen, uchar *key, long klen){ uchar ipad[65], opad[65]; int i; DigestState *digest; uchar innerhash[MD5dlen]; for(i=0; i<64; i++){ ipad[i] = 0x36; opad[i] = 0x5c; } ipad[64] = opad[64] = 0; for(i=0; i<klen; i++){ ipad[i] ^= key[i]; opad[i] ^= key[i]; } digest = md5(ipad, 64, nil, nil); md5(t, tlen, innerhash, digest); digest = md5(opad, 64, nil, nil); md5(innerhash, MD5dlen, hash, digest);}static intmd5auth(Espcb *ecb, uchar *t, int tlen, uchar *auth){ uchar hash[MD5dlen]; int r; memset(hash, 0, MD5dlen); seanq_hmac_md5(hash, t, tlen, (uchar*)ecb->ahstate, 16); r = memcmp(auth, hash, ecb->ahlen) == 0; memmove(auth, hash, ecb->ahlen); return r;}static voidmd5ahinit(Espcb *ecb, char *name, uchar *key, int klen){ if(klen != 128) panic("md5ahinit: bad keylen"); klen >>= 3; // convert to bytes ecb->ahalg = name; ecb->ahblklen = 1; ecb->ahlen = 12; ecb->auth = md5auth; ecb->ahstate = smalloc(klen); memmove(ecb->ahstate, key, klen);}static intdescipher(Espcb *ecb, uchar *p, int n){ uchar tmp[8]; uchar *pp, *tp, *ip, *eip, *ep; DESstate *ds = ecb->espstate; ep = p + n; if(ecb->incoming) { memmove(ds->ivec, p, 8); p += 8; while(p < ep){ memmove(tmp, p, 8); block_cipher(ds->expanded, p, 1); tp = tmp; ip = ds->ivec; for(eip = ip+8; ip < eip; ){ *p++ ^= *ip; *ip++ = *tp++; } } } else { memmove(p, ds->ivec, 8); for(p += 8; p < ep; p += 8){ pp = p; ip = ds->ivec; for(eip = ip+8; ip < eip; ) *pp++ ^= *ip++; block_cipher(ds->expanded, p, 0); memmove(ds->ivec, p, 8); } } return 1;} static voiddesespinit(Espcb *ecb, char *name, uchar *k, int n){ uchar key[8]; uchar ivec[8]; int i; // bits to bytes n = (n+7)>>3; if(n > 8) n = 8; memset(key, 0, sizeof(key)); memmove(key, k, n); for(i=0; i<8; i++) ivec[i] = nrand(256); ecb->espalg = name; ecb->espblklen = 8; ecb->espivlen = 8; ecb->cipher = descipher; ecb->espstate = smalloc(sizeof(DESstate)); setupDESstate(ecb->espstate, key, ivec);}static intrc4cipher(Espcb *ecb, uchar *p, int n){ Esprc4 *esprc4; RC4state tmpstate; ulong seq; long d, dd; if(n < 4) return 0; esprc4 = ecb->espstate; if(ecb->incoming) { seq = nhgetl(p); p += 4; n -= 4; d = seq-esprc4->cseq; if(d == 0) { rc4(&esprc4->current, p, n); esprc4->cseq += n; if(esprc4->ovalid) { dd = esprc4->cseq - esprc4->lgseq; if(dd > RC4back) esprc4->ovalid = 0; } } else if(d > 0) {print("missing packet: %uld %ld\n", seq, d); // this link is hosed if(d > RC4forward) { strcpy(up->errstr, "rc4cipher: skipped too much"); return 0; } esprc4->lgseq = seq; if(!esprc4->ovalid) { esprc4->ovalid = 1; esprc4->oseq = esprc4->cseq; memmove(&esprc4->old, &esprc4->current, sizeof(RC4state)); } rc4skip(&esprc4->current, d); rc4(&esprc4->current, p, n); esprc4->cseq = seq+n; } else {print("reordered packet: %uld %ld\n", seq, d); dd = seq - esprc4->oseq; if(!esprc4->ovalid || -d > RC4back || dd < 0) { strcpy(up->errstr, "rc4cipher: too far back"); return 0; } memmove(&tmpstate, &esprc4->old, sizeof(RC4state)); rc4skip(&tmpstate, dd); rc4(&tmpstate, p, n); return 1; } // move old state up if(esprc4->ovalid) { dd = esprc4->cseq - RC4back - esprc4->oseq; if(dd > 0) { rc4skip(&esprc4->old, dd); esprc4->oseq += dd; } } } else { hnputl(p, esprc4->cseq); p += 4; n -= 4; rc4(&esprc4->current, p, n); esprc4->cseq += n; } return 1;}static voidrc4espinit(Espcb *ecb, char *name, uchar *k, int n){ Esprc4 *esprc4; // bits to bytes n = (n+7)>>3; esprc4 = smalloc(sizeof(Esprc4)); memset(esprc4, 0, sizeof(Esprc4)); setupRC4state(&esprc4->current, k, n); ecb->espalg = name; ecb->espblklen = 4; ecb->espivlen = 4; ecb->cipher = rc4cipher; ecb->espstate = esprc4;} voidespinit(Fs *fs){ Proto *esp; esp = smalloc(sizeof(Proto)); esp->priv = smalloc(sizeof(Esppriv)); esp->name = "esp"; esp->connect = espconnect; esp->announce = nil; esp->ctl = espctl; esp->state = espstate; esp->create = espcreate; esp->close = espclose; esp->rcv = espiput; esp->advise = espadvise; esp->stats = espstats; esp->local = esplocal; esp->remote = espremote; esp->ipproto = IP_ESPPROTO; esp->nc = Nchans; esp->ptclsize = sizeof(Espcb); Fsproto(fs, esp);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -