📄 mppc.c
字号:
s = mallocz(sizeof(Uncstate), 1); s->count = 0xfff; /* count of non existant last packet */ memmove(s->startkey, ppp->key, 16); memmove(s->key, ppp->key, 16); setkey(s->key, s->startkey); setupRC4state(&s->rc4key, s->key, 16); return s;}static Block*uncomp(PPP *ppp, Block *b, int *protop, Block **r){ Uncstate *s; ushort proto; ushort count; Lcpmsg *m; *r = nil; *protop = 0; s = ppp->uncstate; if(BLEN(b) < 2){ syslog(0, "ppp", ": mppc: short packet\n"); freeb(b); return nil; } count = nhgets(b->rptr); b->rptr += 2; b = uncomp2(s, b, count); if(b == nil) {//netlog("ppp: mppc: reset request\n"); /* return reset request packet */ *r = alloclcp(Lresetreq, s->resetid++, 4, &m); hnputs(m->len, 4); *protop = 0; return nil; } if(BLEN(b) < 2){ syslog(0, "ppp", ": mppc: short packet\n"); freeb(b); *protop = 0; return nil; } proto = nhgets(b->rptr); b->rptr += 2;/* if(proto == 0x21) if(!ipcheck(b->rptr, BLEN(b))) hischeck(s);*/ *protop = proto; return b;}#define NEXTBYTE sreg = (sreg<<8) | *p++; n--; bits += 8int maxoff; static Block*uncomp2(Uncstate *s, Block *b, ushort count){ int ecount, n, bits, off, len, ones; ulong sreg; int t; uchar *p, c, *hp, *hs, *he, *hq; if(count&Preset) {//netlog("mppc reset\n"); s->indx = 0; s->size = 0; setupRC4state(&s->rc4key, s->key, 16); } else { ecount = (s->count+1)&0xfff; if((count&0xfff) != ecount) {netlog("******* bad count - got %ux expected %ux\n", count&0xfff, ecount); freeb(b); return nil; } if(count&Pfront) { s->indx = 0;/* netlog("ppp: mppc: frount flag set\n"); */ } } /* update key */ n = (((count+1)>>8)&0xf) - (((s->count+1)>>8)&0xf); if(n < 0) n += 16;//netlog("mppc count = %ux oldcount %ux n = %d\n", count, s->count, n); if(n < 0 || n > 1) { syslog(0, "ppp", ": mppc bad count %ux, %ux", count, s->count); freeb(b); return nil; } if(n == 1) { setkey(s->key, s->startkey); setupRC4state(&s->rc4key, s->key, 16); rc4(&s->rc4key, s->key, 16); setupRC4state(&s->rc4key, s->key, 16); } s->count = count; n = BLEN(b); p = b->rptr; if(count & Pencrypt) {//netlog("mppc unencrypt count = %ux\n", count); rc4(&s->rc4key, p, n); } if(!(count & Pcompress)) {//netlog("uncompress blen = %d\n", BLEN(b)); return b; } bits = 0; sreg = 0; hs = s->his; /* history start */ hp = hs+s->indx; /* write pointer in history */ he = hs+sizeof(s->his); /* hsitory end */ for(;;) { if(bits<4) { if(n==0) goto Done; NEXTBYTE; } t = decode[(sreg>>(bits-4))&0xf]; switch(t) { default: sysfatal("mppc: bad decode!"); case Lit7: bits -= 1; if(bits<7) { if(n==0) goto Done; NEXTBYTE; } c = (sreg>>(bits-7))&0x7f; bits -= 7; if(hp >= he) goto His; *hp++ = c;/* netlog("\tlit7 %.2ux\n", c); */ continue; case Lit8: bits -= 2; if(bits<7) { if(n==0) goto Eof; NEXTBYTE; } c = 0x80 | ((sreg>>(bits-7))&0x7f); bits -= 7; if(hp >= he) goto His; *hp++ = c;/* netlog("\tlit8 %.2ux\n", c); */ continue; case Off6: bits -= 4; if(bits<6) { if(n==0) goto Eof; NEXTBYTE; } off = (sreg>>(bits-6))&0x3f; bits -= 6; break; case Off8: bits -= 4; if(bits<8) { if(n==0) goto Eof; NEXTBYTE; } off = ((sreg>>(bits-8))&0xff)+64; bits -= 8; break; case Off13: bits -= 3; while(bits<13) { if(n==0) goto Eof; NEXTBYTE; } off = ((sreg>>(bits-13))&0x1fff)+320; bits -= 13;/* netlog("\toff=%d bits = %d sreg = %ux t = %x\n", off, bits, sreg, t); */ break; } for(ones=0;;ones++) { if(bits == 0) { if(n==0) goto Eof; NEXTBYTE; } bits--; if(!(sreg&(1<<bits))) break; } if(ones>11) {netlog("ppp: mppc: bad length %d\n", ones); freeb(b); return nil; } if(ones == 0) { len = 3; } else { ones++; while(bits<ones) { if(n==0) goto Eof; NEXTBYTE; } len = (1<<ones) | ((sreg>>(bits-ones))&((1<<ones)-1)); bits -= ones; } hq = hp-off; if(hq < hs) { hq += sizeof(s->his); if(hq-hs+len > s->size) goto His; } if(hp+len > he) goto His; while(len) { *hp++ = *hq++; len--; } }Done: freeb(b); /* build up return block */ hq = hs+s->indx; len = hp-hq; b = allocb(len); memmove(b->wptr, hq, len); b->wptr += len;netlog("ppp: mppc: len %d bits = %d n=%d\n", len, bits, n); s->indx += len; if(s->indx > s->size) s->size = s->indx; return b;Eof:netlog("*****unexpected end of data\n"); freeb(b); return nil;His:netlog("*****bad history\n"); freeb(b); return nil;}static voiduncresetack(void*, Block*){}static voiduncfini(void *as){ Uncstate *s; s = as; free(s);}static voidsetkey(uchar *key, uchar *startkey){ uchar pad[40]; SHAstate *s; uchar digest[SHA1dlen]; s = sha1(startkey, 16, nil, nil); memset(pad, 0, 40); sha1(pad, 40, nil, s); sha1(key, 16, nil, s); memset(pad, 0xf2, 40); sha1(pad, 40, digest, s); memmove(key, digest, 16);}/* code to check if IP packet looks good */typedef struct Iphdr Iphdr;struct Iphdr{ uchar vihl; /* Version and header length */ uchar tos; /* Type of service */ uchar length[2]; /* packet length */ uchar id[2]; /* Identification */ uchar frag[2]; /* Fragment information */ uchar ttl; /* Time to live */ uchar proto; /* Protocol */ uchar cksum[2]; /* Header checksum */ uchar src[4]; /* Ip source */ uchar dst[4]; /* Ip destination */};enum{ QMAX = 64*1024-1, IP_TCPPROTO = 6, TCP_IPLEN = 8, TCP_PHDRSIZE = 12, TCP_HDRSIZE = 20, TCP_PKT = TCP_IPLEN+TCP_PHDRSIZE,};enum{ UDP_PHDRSIZE = 12, UDP_HDRSIZE = 20, UDP_IPHDR = 8, IP_UDPPROTO = 17, UDP_USEAD = 12, UDP_RELSIZE = 16, Udprxms = 200, Udptickms = 100, Udpmaxxmit = 10,};typedef struct UDPhdr UDPhdr;struct UDPhdr{ /* ip header */ uchar vihl; /* Version and header length */ uchar tos; /* Type of service */ uchar length[2]; /* packet length */ uchar id[2]; /* Identification */ uchar frag[2]; /* Fragment information */ uchar Unused; uchar udpproto; /* Protocol */ uchar udpplen[2]; /* Header plus data length */ uchar udpsrc[4]; /* Ip source */ uchar udpdst[4]; /* Ip destination */ /* udp header */ uchar udpsport[2]; /* Source port */ uchar udpdport[2]; /* Destination port */ uchar udplen[2]; /* data length */ uchar udpcksum[2]; /* Checksum */};typedef struct TCPhdr TCPhdr;struct TCPhdr{ uchar vihl; /* Version and header length */ uchar tos; /* Type of service */ uchar length[2]; /* packet length */ uchar id[2]; /* Identification */ uchar frag[2]; /* Fragment information */ uchar Unused; uchar proto; uchar tcplen[2]; uchar tcpsrc[4]; uchar tcpdst[4]; uchar tcpsport[2]; uchar tcpdport[2]; uchar tcpseq[4]; uchar tcpack[4]; uchar tcpflag[2]; uchar tcpwin[2]; uchar tcpcksum[2]; uchar tcpurg[2]; /* Options segment */ uchar tcpopt[2]; uchar tcpmss[2];};static voidhischeck(Uncstate *s){ uchar *p; Iphdr *iph; int len; p = s->his;netlog("***** history check\n"); while(p < s->his+s->size) { if(p[0] != 0 || p[1] != 0x21) {netlog("***** unknown protocol\n"); return; } p += 2;netlog("off = %ld ", p-s->his); iph = (Iphdr*)p; len = nhgets(iph->length); ipcheck(p, len); p += len; }}static intipcheck(uchar *p, int len){ Iphdr *iph; TCPhdr *tcph; ushort length; UDPhdr *uh; Block *bp; ushort cksum; int good; bp = allocb(len); memmove(bp->wptr, p, len); bp->wptr += len; good = 1; iph = (Iphdr *)(bp->rptr);/* netlog("ppp: mppc: ipcheck %I %I len %d proto %d\n", iph->src, iph->dst, BLEN(bp), iph->proto); */ if(len != nhgets(iph->length)) { netlog("***** bad length! %d %d\n", len, nhgets(iph->length)); good = 0; } cksum = ipcsum(&iph->vihl); if(cksum) { netlog("***** IP proto cksum!!! %I %ux\n", iph->src, cksum); good = 0; } switch(iph->proto) { default: break; case IP_TCPPROTO: tcph = (TCPhdr*)(bp->rptr); length = nhgets(tcph->length); tcph->Unused = 0; hnputs(tcph->tcplen, length-TCP_PKT); cksum = ptclcsum(bp, TCP_IPLEN, length-TCP_IPLEN); if(cksum) { netlog("***** bad tcp proto cksum %ux!!!\n", cksum); good = 0; } break; case IP_UDPPROTO: uh = (UDPhdr*)(bp->rptr); /* Put back pseudo header for checksum */ uh->Unused = 0; len = nhgets(uh->udplen); hnputs(uh->udpplen, len); if(nhgets(uh->udpcksum)) { cksum = ptclcsum(bp, UDP_IPHDR, len+UDP_PHDRSIZE); if(cksum) { netlog("***** udp: proto cksum!!! %I %ux\n", uh->udpsrc, cksum); good = 0; } } break; } freeb(bp); return good;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -