📄 devsdp.c
字号:
b->wp[pad-1] = pad; b->wp += pad; } /* Make space to fit sdp header */ b = padblock(b, 4 + c->out.cipherivlen); b->rp[0] = (type << 4) | subtype; c->out.seq++; if(c->out.seq == (1<<24)) { c->out.seq = 0; c->out.seqwrap++; } b->rp[1] = c->out.seq>>16; b->rp[2] = c->out.seq>>8; b->rp[3] = c->out.seq; if(c->out.cipher) (*c->out.cipher)(&c->out, b->rp+4, BLEN(b)-4); // auth if(c->out.auth) { b->wp += c->out.authlen; (*c->out.auth)(&c->out, b->rp, BLEN(b)); } convwriteblock(c, b);}// assume hold conv lockstatic voidconvoconnect(Conv *c, int op, ulong dialid, ulong acceptid){ Block *b; c->lstats.outPackets++; assert(c->chan != nil); b = allocb(9); b->wp[0] = (TConnect << 4) | op; hnputl(b->wp+1, dialid); hnputl(b->wp+5, acceptid); b->wp += 9; if(!waserror()) { convwriteblock(c, b); poperror(); }}static Block *convreadblock(Conv *c, int n){ Block *b; Chan *ch; qlock(&c->readlk); if(waserror()) { c->readproc = nil; qunlock(&c->readlk); nexterror(); } qlock(c); if(c->state == CClosed) { qunlock(c); error("closed"); } c->readproc = up; ch = c->chan; assert(c->ref > 0); qunlock(c); b = devtab[ch->type]->bread(ch, n, 0); c->readproc = nil; poperror(); qunlock(&c->readlk); return b;}static intreadready(void *a){ Conv *c = a; return c->in.controlpkt != nil || (c->state == CClosed) || (c->state == CRemoteClose);}static Block *readcontrol(Conv *c, int n){ Block *b; USED(n); qlock(&c->in.controllk); if(waserror()) { qunlock(&c->in.controllk); nexterror(); } qlock(c); // this lock is not held during the sleep below for(;;) { if(c->chan == nil || c->state == CClosed) { qunlock(c);if(0)print("readcontrol: return error - state = %s\n", convstatename[c->state]); error("conversation closed"); } if(c->in.controlpkt != nil) break; if(c->state == CRemoteClose) { qunlock(c);if(0)print("readcontrol: return nil - state = %s\n", convstatename[c->state]); poperror(); return nil; } qunlock(c); sleep(&c->in.controlready, readready, c); qlock(c); } convack(c); b = c->in.controlpkt; c->in.controlpkt = nil; qunlock(c); poperror(); qunlock(&c->in.controllk); return b;}static intwriteready(void *a){ Conv *c = a; return c->out.controlpkt == nil || (c->state == CClosed) || (c->state == CRemoteClose);}// c is lockedstatic voidwritewait(Conv *c){ for(;;) { if(c->state == CInit || c->state == CClosed || c->state == CRemoteClose) error("conversation closed"); if(c->state == COpen && c->out.controlpkt == nil) break; qunlock(c); if(waserror()) { qlock(c); nexterror(); } sleep(&c->out.controlready, writeready, c); poperror(); qlock(c); }}static voidwritecontrol(Conv *c, void *p, int n, int wait){ Block *b; qlock(&c->out.controllk); qlock(c); if(waserror()) { qunlock(c); qunlock(&c->out.controllk); nexterror(); } writewait(c); b = allocb(4+n); c->out.controlseq++; hnputl(b->wp, c->out.controlseq); memmove(b->wp+4, p, n); b->wp += 4+n; c->out.controlpkt = b; convretryinit(c); convoput(c, TControl, ControlMesg, copyblock(b, blocklen(b))); if(wait) writewait(c); poperror(); qunlock(c); qunlock(&c->out.controllk);}static Block *readdata(Conv *c, int n){ Block *b; int nn; for(;;) { // some slack for tunneling overhead nn = n + 100; // make sure size is big enough for control messages if(nn < 1000) nn = 1000; b = convreadblock(c, nn); if(b == nil) return nil; qlock(c); if(waserror()) { qunlock(c); return nil; } b = conviput(c, b, 0); poperror(); qunlock(c); if(b != nil) { if(BLEN(b) > n) b->wp = b->rp + n; return b; } }}static longwritedata(Conv *c, Block *b){ int n; ulong seq; int subtype; qlock(c); if(waserror()) { qunlock(c); nexterror(); } if(c->state != COpen) { freeb(b); error("conversation not open"); } n = BLEN(b); c->lstats.outDataPackets++; c->lstats.outDataBytes += n; if(c->out.comp != nil) { // must generate same value as convoput seq = (c->out.seq + 1) & (SeqMax-1); subtype = (*c->out.comp)(c, 0, seq, &b); c->lstats.outCompDataBytes += BLEN(b); convoput(c, TCompData, subtype, b); } else convoput(c, TData, 0, b); poperror(); qunlock(c); return n;}static voidconvreader(void *a){ Conv *c = a; Block *b; qlock(c); assert(c->reader == 1); while(c->dataopen == 0 && c->state != CClosed) { qunlock(c); b = nil; if(!waserror()) { b = convreadblock(c, 2000); poperror(); } qlock(c); if(b == nil) { if(strcmp(up->error, Eintr) != 0) { convsetstate(c, CClosed); break; } } else if(!waserror()) { conviput(c, b, 1); poperror(); } } c->reader = 0; convderef(c); qunlock(c); pexit("hangup", 1);}/* ciphers, authenticators, and compressors */static voidsetalg(Conv *c, char *name, Algorithm *alg, Algorithm **p){ for(; alg->name; alg++) if(strcmp(name, alg->name) == 0) break; if(alg->name == nil) error("unknown algorithm"); *p = alg; alg->init(c);}static voidsetsecret(OneWay *ow, char *secret){ char *p; int i, c; i = 0; memset(ow->secret, 0, sizeof(ow->secret)); for(p=secret; *p; p++) { if(i >= sizeof(ow->secret)*2) break; c = *p; if(c >= '0' && c <= '9') c -= '0'; else if(c >= 'a' && c <= 'f') c -= 'a'-10; else if(c >= 'A' && c <= 'F') c -= 'A'-10; else error("bad character in secret"); if((i&1) == 0) c <<= 4; ow->secret[i>>1] |= c; i++; }}static voidsetkey(uchar *key, int n, OneWay *ow, char *prefix){ uchar ibuf[SHA1dlen], obuf[MD5dlen], salt[10]; int i, round = 0; while(n > 0){ for(i=0; i<round+1; i++) salt[i] = 'A'+round; sha1((uchar*)prefix, strlen(prefix), ibuf, sha1(salt, round+1, nil, nil)); md5(ibuf, SHA1dlen, obuf, md5(ow->secret, sizeof(ow->secret), nil, nil)); i = (n<MD5dlen) ? n : MD5dlen; memmove(key, obuf, i); key += i; n -= i; if(++round > sizeof salt) panic("setkey: you ask too much"); }}static voidcipherfree(Conv *c){ if(c->in.cipherstate) { free(c->in.cipherstate); c->in.cipherstate = nil; } if(c->out.cipherstate) { free(c->out.cipherstate); c->out.cipherstate = nil; } c->in.cipher = nil; c->in.cipherblklen = 0; c->out.cipherblklen = 0; c->in.cipherivlen = 0; c->out.cipherivlen = 0;}static voidauthfree(Conv *c){ if(c->in.authstate) { free(c->in.authstate); c->in.authstate = nil; } if(c->out.authstate) { free(c->out.authstate); c->out.authstate = nil; } c->in.auth = nil; c->in.authlen = 0; c->out.authlen = 0;}static voidcompfree(Conv *c){ if(c->in.compstate) { free(c->in.compstate); c->in.compstate = nil; } if(c->out.compstate) { free(c->out.compstate); c->out.compstate = nil; } c->in.comp = nil;}static voidnullcipherinit(Conv *c){ cipherfree(c);}static intdesencrypt(OneWay *ow, uchar *p, int n){ uchar *pp, *ip, *eip, *ep; DESstate *ds = ow->cipherstate; if(n < 8 || (n & 0x7 != 0)) return 0; ep = p + n; 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 intdesdecrypt(OneWay *ow, uchar *p, int n){ uchar tmp[8]; uchar *tp, *ip, *eip, *ep; DESstate *ds = ow->cipherstate; if(n < 8 || (n & 0x7 != 0)) return 0; ep = p + n; 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++; } } return 1;}static voiddescipherinit(Conv *c){ uchar key[8]; uchar ivec[8]; int i; int n = c->cipher->keylen; cipherfree(c); if(n > sizeof(key)) n = sizeof(key); /* in */ memset(key, 0, sizeof(key)); setkey(key, n, &c->in, "cipher"); memset(ivec, 0, sizeof(ivec)); c->in.cipherblklen = 8; c->in.cipherivlen = 8; c->in.cipher = desdecrypt; c->in.cipherstate = smalloc(sizeof(DESstate)); setupDESstate(c->in.cipherstate, key, ivec); /* out */ memset(key, 0, sizeof(key)); setkey(key, n, &c->out, "cipher"); for(i=0; i<8; i++) ivec[i] = nrand(256); c->out.cipherblklen = 8; c->out.cipherivlen = 8; c->out.cipher = desencrypt; c->out.cipherstate = smalloc(sizeof(DESstate)); setupDESstate(c->out.cipherstate, key, ivec);}static intrc4encrypt(OneWay *ow, uchar *p, int n){ CipherRc4 *cr = ow->cipherstate; if(n < 4) return 0; hnputl(p, cr->cseq); p += 4; n -= 4; rc4(&cr->current, p, n); cr->cseq += n; return 1;}static intrc4decrypt(OneWay *ow, uchar *p, int n){ CipherRc4 *cr = ow->cipherstate; RC4state tmpstate; ulong seq; long d, dd; if(n < 4) return 0; seq = nhgetl(p); p += 4; n -= 4; d = seq-cr->cseq; if(d == 0) { rc4(&cr->current, p, n); cr->cseq += n; if(cr->ovalid) { dd = cr->cseq - cr->lgseq; if(dd > RC4back) cr->ovalid = 0; } } else if(d > 0) {//print("missing packet: %uld %ld\n", seq, d); // this link is hosed if(d > RC4forward) return 0; cr->lgseq = seq; if(!cr->ovalid) { cr->ovalid = 1; cr->oseq = cr->cseq; memmove(&cr->old, &cr->current, sizeof(RC4state)); } rc4skip(&cr->current, d); rc4(&cr->current, p, n); cr->cseq = seq+n; } else {//print("reordered packet: %uld %ld\n", seq, d); dd = seq - cr->oseq; if(!cr->ovalid || -d > RC4back || dd < 0) return 0; memmove(&tmpstate, &cr->old, sizeof(RC4state)); rc4skip(&tmpstate, dd); rc4(&tmpstate, p, n); return 1; } // move old state up if(cr->ovalid) { dd = cr->cseq - RC4back - cr->oseq; if(dd > 0) { rc4skip(&cr->old, dd); cr->oseq += dd; } } return 1;}static voidrc4cipherinit(Conv *c){ uchar key[32]; CipherRc4 *cr; int n; cipherfree(c); n = c->cipher->keylen; if(n > sizeof(key)) n = sizeof(key); /* in */ memset(key, 0, sizeof(key)); setkey(key, n, &c->in, "cipher"); c->in.cipherblklen = 1; c->in.cipherivlen = 4; c->in.cipher = rc4decrypt; cr = smalloc(sizeof(CipherRc4)); memset(cr, 0, sizeof(*cr)); setupRC4state(&cr->current, key, n); c->in.cipherstate = cr; /* out */ memset(key, 0, sizeof(key)); setkey(key, n, &c->out, "cipher"); c->out.cipherblklen = 1; c->out.cipherivlen = 4; c->out.cipher = rc4encrypt; cr = smalloc(sizeof(CipherRc4)); memset(cr, 0, sizeof(*cr)); setupRC4state(&cr->current, key, n); c->out.cipherstate = cr;}static voidnullauthinit(Conv *c){ authfree(c);}static voidshaauthinit(Conv *c){ authfree(c);}static voidseanq_hmac_md5(uchar hash[MD5dlen], ulong wrap, uchar *t, long tlen, uchar *key, long klen){ uchar ipad[65], opad[65], wbuf[4]; 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]; } hnputl(wbuf, wrap); digest = md5(ipad, 64, nil, nil); digest = md5(wbuf, sizeof(wbuf), nil, digest); md5(t, tlen, innerhash, digest); digest = md5(opad, 64, nil, nil); md5(innerhash, MD5dlen, hash, digest);}static intmd5auth(OneWay *ow, uchar *t, int tlen){ uchar hash[MD5dlen]; int r; if(tlen < ow->authlen) return 0; tlen -= ow->authlen; memset(hash, 0, MD5dlen); seanq_hmac_md5(hash, ow->seqwrap, t, tlen, (uchar*)ow->authstate, 16); r = memcmp(t+tlen, hash, ow->authlen) == 0; memmove(t+tlen, hash, ow->authlen); return r;}static voidmd5authinit(Conv *c){ int keylen; authfree(c); keylen = c->auth->keylen; if(keylen > 16) keylen = 16; /* in */ c->in.authstate = smalloc(16); memset(c->in.authstate, 0, 16); setkey(c->in.authstate, keylen, &c->in, "auth"); c->in.authlen = 12; c->in.auth = md5auth; /* out */ c->out.authstate = smalloc(16); memset(c->out.authstate, 0, 16); setkey(c->out.authstate, keylen, &c->out, "auth"); c->out.authlen = 12; c->out.auth = md5auth;}static voidnullcompinit(Conv *c){ compfree(c);}static intthwackcomp(Conv *c, int, ulong seq, Block **bp){ Block *b, *bb; int nn; // add ack info b = padblock(*bp, 4); b->rp[0] = (c->in.window>>1) & 0xff; b->rp[1] = c->in.seq>>16; b->rp[2] = c->in.seq>>8; b->rp[3] = c->in.seq; bb = allocb(BLEN(b)); nn = thwack(c->out.compstate, bb->wp, b->rp, BLEN(b), seq, c->lstats.outCompStats); if(nn < 0) { freeb(bb); *bp = b; return ThwackU; } else { bb->wp += nn; freeb(b); *bp = bb; return ThwackC; }}static intthwackuncomp(Conv *c, int subtype, ulong seq, Block **bp){ Block *b, *bb; ulong mask; ulong mseq; int n; switch(subtype) { default: return 0; case ThwackU: b = *bp; mask = b->rp[0]; mseq = (b->rp[1]<<16) | (b->rp[2]<<8) | b->rp[3]; b->rp += 4; thwackack(c->out.compstate, mseq, mask); return 1; case ThwackC: bb = *bp; b = allocb(ThwMaxBlock); n = unthwack(c->in.compstate, b->wp, ThwMaxBlock, bb->rp, BLEN(bb), seq); freeb(bb); if(n < 0) {print("unthwack failed: %r!\n"); freeb(b); return 0; } b->wp += n; mask = b->rp[0]; mseq = (b->rp[1]<<16) | (b->rp[2]<<8) | b->rp[3]; thwackack(c->out.compstate, mseq, mask); b->rp += 4; *bp = b; return 1; }}static voidthwackcompinit(Conv *c){ compfree(c); c->in.compstate = malloc(sizeof(Unthwack)); if(c->in.compstate == nil) error(Enomem); unthwackinit(c->in.compstate); c->out.compstate = malloc(sizeof(Thwack)); if(c->out.compstate == nil) error(Enomem); thwackinit(c->out.compstate); c->in.comp = thwackuncomp; c->out.comp = thwackcomp;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -