diff options
| author | liuxueli <[email protected]> | 2022-07-25 10:16:46 +0800 |
|---|---|---|
| committer | liuxueli <[email protected]> | 2022-07-25 10:16:46 +0800 |
| commit | fa0ebd48e689499d495852915c16d15a206c134e (patch) | |
| tree | 7afa9cc4b0684bca7c67f7aa5f86356e7263b26f /src/dns.cpp | |
| parent | ac4dda42384a742d16bde2878c3c36401e01ee9d (diff) | |
OMPUB-563: 处理长度标识跨包的逻辑存在问题: 1)区分数据包方向导致偏移的长度出现负值导致访问越界,2)错误使用累计传输长度作为单包长度限制判断导致部分请求与应答未正常解析v2.1.4
Diffstat (limited to 'src/dns.cpp')
| -rw-r--r-- | src/dns.cpp | 133 |
1 files changed, 87 insertions, 46 deletions
diff --git a/src/dns.cpp b/src/dns.cpp index 0b958fc..1a143d2 100644 --- a/src/dns.cpp +++ b/src/dns.cpp @@ -107,6 +107,69 @@ const unsigned char PCAP_FILE_HEAD[24] = {0xD4, 0xC3, 0xB2, 0xA1, 0x02, 0x00, 0x 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00}; +int jump_message_length(struct dns_context *context, int payload_len, int lostlen, char dir) +{ + char *skiped_len=NULL; + + if(dir==DIR_C2S) + { + skiped_len=&(context->c2s_skiped_len); + } + else + { + skiped_len=&(context->s2c_skiped_len); + } + + if(lostlen>0) + { + switch(lostlen) + { + case 1: //drop 1 byte + if((*skiped_len)==1) + { + (*skiped_len)=0; + return 0; + } + else + { + (*skiped_len)=0; + return 1; + } + break; + case 2: //drop 2 byte + (*skiped_len)=0; + return 0; + default: + (*skiped_len)=0; + return 2; + } + } + + switch((*skiped_len)) + { + case 1: + (*skiped_len)=0; + return 1; + break; + case 2: + (*skiped_len)=0; + return 0; + break; + case 0: + if(payload_len<=2) + { + (*skiped_len)=(char)payload_len; + return payload_len; + } + return 2; + break; + default: + break; + } + + return -1; +} + static int str2hex(unsigned char *source, int s_len, char *dest, int d_len) { int i=0,used_len=0; @@ -1369,7 +1432,7 @@ int callback_dns_business_plug(struct streaminfo *a_stream, void **pme, void *in char state=PROT_STATE_GIVEME; char app_state=APP_STATE_GIVEME; stSessionInfo sessionInfo; - save_dns_business_info_t *apme = (save_dns_business_info_t *)*pme; + struct dns_context *apme = (struct dns_context *)*pme; memset(&sessionInfo, 0, sizeof(stSessionInfo)); @@ -1826,7 +1889,7 @@ int parse_dns_protocol(struct streaminfo *a_stream, unsigned char opstate, char char *cur_pos = NULL; dns_info_t dns_info; unsigned long long register_flag = dns_register_flag; - save_dns_business_info_t *context = (save_dns_business_info_t *)(*pme); + struct dns_context *context = (struct dns_context *)(*pme); if(payload_len<12 || payload==NULL) { @@ -1990,8 +2053,8 @@ char DNS_UDP_ENTRY(struct streaminfo *a_udp, void **pme, int thread_seq, void *a case OP_STATE_PENDING: if(*pme == NULL) { - *pme = dictator_malloc(thread_seq, sizeof(save_dns_business_info_t)); - memset(*pme, 0, sizeof(save_dns_business_info_t)); + *pme = dictator_malloc(thread_seq, sizeof(struct dns_context)); + memset(*pme, 0, sizeof(struct dns_context)); } /* no break here!!!! */ case OP_STATE_DATA: @@ -2014,13 +2077,12 @@ char DNS_UDP_ENTRY(struct streaminfo *a_udp, void **pme, int thread_seq, void *a state=parse_dns_protocol(a_udp, a_udp->opstate, payload, payload_len, pme, thread_seq, a_packet); break; case OP_STATE_CLOSE: - state=parse_dns_protocol(a_udp, a_udp->opstate, payload, payload_len, pme, thread_seq, a_packet); break; } if(state&APP_STATE_DROPME || a_udp->opstate==OP_STATE_CLOSE) { - save_dns_business_info_t *context=(save_dns_business_info_t *)(*pme); + struct dns_context *context=(struct dns_context *)(*pme); if((context->session_state&SESSION_STATE_CLOSE)!=SESSION_STATE_CLOSE) { callback_dns_business_plug(a_udp, pme, NULL, DNS_ALL, SESSION_STATE_CLOSE, thread_seq, a_packet); @@ -2036,40 +2098,38 @@ char DNS_UDP_ENTRY(struct streaminfo *a_udp, void **pme, int thread_seq, void *a char DNS_TCP_ENTRY(struct streaminfo *a_tcp, void **pme, int thread_seq, void *a_packet) { - int payload_len = 0; - char *payload = NULL; + int jump_len=0, payload_len=0; + char *payload=NULL; char state=APP_STATE_GIVEME; struct tcpdetail* tcp_detail = (struct tcpdetail*)a_tcp->pdetail; - save_dns_business_info_t *context=(save_dns_business_info_t*)(*pme); + struct dns_context *context=(struct dns_context*)(*pme); if(!check_port(a_tcp->addr, DNS_PORT)) { return APP_STATE_DROPME; } - tcp_detail = (struct tcpdetail *)a_tcp->ptcpdetail; - payload_len = tcp_detail->datalen; - payload = (char *)tcp_detail->pdata; - switch(a_tcp->opstate) { - case OP_STATE_PENDING: /* ��δ������������Ϣ */ - if((NULL == tcp_detail->pdata) || (0 == tcp_detail->datalen)) - { - return APP_STATE_GIVEME; - } - + case OP_STATE_PENDING: /* ��δ������������Ϣ */ if(*pme == NULL) { - *pme = dictator_malloc(thread_seq, sizeof(save_dns_business_info_t)); - memset(*pme, 0, sizeof(save_dns_business_info_t)); - context = (save_dns_business_info_t *)*pme; - context->skip_len=2; + *pme = dictator_malloc(thread_seq, sizeof(struct dns_context)); + memset(*pme, 0, sizeof(struct dns_context)); + context = (struct dns_context *)*pme; } /* no break here!!!! */ case OP_STATE_DATA: + tcp_detail = (struct tcpdetail *)a_tcp->ptcpdetail; + if((NULL==tcp_detail->pdata) || (0==tcp_detail->datalen)) + { + return APP_STATE_GIVEME; + } + payload_len = tcp_detail->datalen; + payload = (char *)tcp_detail->pdata; + switch(a_tcp->addr.addrtype) { case ADDR_TYPE_IPV4: @@ -2086,40 +2146,21 @@ char DNS_TCP_ENTRY(struct streaminfo *a_tcp, void **pme, int thread_seq, void *a break; } - if(tcp_detail->serverbytes <= 2) + jump_len=jump_message_length(context, payload_len, tcp_detail->lostlen, a_tcp->curdir); + if(jump_len<0 || payload_len-jump_len<12) { - context->skip_len -= payload_len; break; } - else - { - if(context->skip_len!=0) - { - payload_len -= context->skip_len; - payload += context->skip_len; - - context->skip_len=2; //https://datatracker.ietf.org/doc/html/rfc7766#section-8 - } - } - - if(tcp_detail->clientbytes >= 1500) - { - FS_operate(g_dns_proto_info.stat_handle, g_dns_proto_info.fild_id[ERR_PKT], 0, FS_OP_ADD, 1); - MESA_handle_runtime_log(g_dns_proto_info.logger, RLOG_LV_DEBUG, "TCP_ENTRY", - "tuple4: %s PKT size(S: %d/C: %d) is too bigger", printaddr(&a_tcp->addr, thread_seq), tcp_detail->serverbytes, tcp_detail->clientbytes); - return APP_STATE_GIVEME; - } - state=parse_dns_protocol(a_tcp, a_tcp->opstate, payload, payload_len, pme, thread_seq, a_packet); + state=parse_dns_protocol(a_tcp, a_tcp->opstate, payload+jump_len, payload_len-jump_len, pme, thread_seq, a_packet); break; case OP_STATE_CLOSE: - state=parse_dns_protocol(a_tcp, a_tcp->opstate, payload, payload_len, pme, thread_seq, a_packet); break; } if(state&APP_STATE_DROPME || a_tcp->opstate==OP_STATE_CLOSE) { - context=(save_dns_business_info_t *)(*pme); + context=(struct dns_context *)(*pme); if((context->session_state&SESSION_STATE_CLOSE)!=SESSION_STATE_CLOSE) { callback_dns_business_plug(a_tcp, pme, NULL, DNS_ALL, SESSION_STATE_CLOSE, thread_seq, a_packet); |
