diff --git a/lua/zapret-tests.lua b/lua/zapret-tests.lua index 0ff0e7c..9940eb6 100644 --- a/lua/zapret-tests.lua +++ b/lua/zapret-tests.lua @@ -594,18 +594,17 @@ function test_csum() print( dis1.tcp.th_sum==dis2.tcp.th_sum and "TCP+IP6 CSUM OK" or "TCP+IP6 CSUM FAILED" ) test_assert(dis1.tcp.th_sum==dis2.tcp.th_sum) - - ip.ip_p = IPPROTO_UDP - ip4b = reconstruct_iphdr(ip) - ip6.ip6_plen = packet_len({ip6=ip6,udp=udp,payload=payload}) - IP6_BASE_LEN - ip6b = reconstruct_ip6hdr(ip6, {ip6_last_proto=IPPROTO_UDP}) - local udp = { uh_sport = math.random(0,0xFFFF), uh_dport = math.random(0,0xFFFF), uh_ulen = UDP_BASE_LEN + #payload } + ip.ip_p = IPPROTO_UDP + ip4b = reconstruct_iphdr(ip) + ip6.ip6_plen = packet_len({ip6=ip6,udp=udp,payload=payload}) - IP6_BASE_LEN + ip6b = reconstruct_ip6hdr(ip6, {ip6_last_proto=IPPROTO_UDP}) + udpb = reconstruct_udphdr(udp) raw = bu16(udp.uh_sport) .. bu16(udp.uh_dport) .. diff --git a/nfq2/darkmagic.c b/nfq2/darkmagic.c index c5f7945..fa3d56e 100644 --- a/nfq2/darkmagic.c +++ b/nfq2/darkmagic.c @@ -329,12 +329,16 @@ void proto_skip_tcp(const uint8_t **data, size_t *len) } bool proto_check_udp(const uint8_t *data, size_t len) { - return len >= sizeof(struct udphdr) && len>=(data[4]<<8 | data[5]); + return len >= sizeof(struct udphdr); +} +bool proto_check_udp_payload(const uint8_t *data, size_t len) +{ + return len >= ntohs(((struct udphdr*)data)->uh_ulen); } void proto_skip_udp(const uint8_t **data, size_t *len) { - *data += 8; - *len -= 8; + *data += sizeof(struct udphdr); + *len -= sizeof(struct udphdr); } bool proto_check_ipv6(const uint8_t *data, size_t len) @@ -487,7 +491,7 @@ void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis) dis->len_payload = len; } - else if (dis->proto==IPPROTO_UDP && proto_check_udp(data, len)) + else if (dis->proto==IPPROTO_UDP && proto_check_udp(data, len) && proto_check_udp_payload(data, len)) { dis->udp = (const struct udphdr *) data; dis->transport_len = len; diff --git a/nfq2/darkmagic.h b/nfq2/darkmagic.h index e1363b6..5a12b42 100644 --- a/nfq2/darkmagic.h +++ b/nfq2/darkmagic.h @@ -141,6 +141,7 @@ uint8_t *proto_find_ip6_exthdr(struct ip6_hdr *ip6, size_t len, uint8_t proto); bool proto_check_tcp(const uint8_t *data, size_t len); void proto_skip_tcp(const uint8_t **data, size_t *len); bool proto_check_udp(const uint8_t *data, size_t len); +bool proto_check_udp_payload(const uint8_t *data, size_t len); void proto_skip_udp(const uint8_t **data, size_t *len); struct dissect { diff --git a/nfq2/helpers.c b/nfq2/helpers.c index a249874..7878f51 100644 --- a/nfq2/helpers.c +++ b/nfq2/helpers.c @@ -127,28 +127,6 @@ bool load_file(const char *filename, off_t offset, void *buffer, size_t *buffer_ return true; } -bool load_file_nonempty(const char *filename, off_t offset, void *buffer, size_t *buffer_size) -{ - bool b = load_file(filename, offset, buffer, buffer_size); - return b && *buffer_size; -} -bool save_file(const char *filename, const void *buffer, size_t buffer_size) -{ - FILE *F; - - F = fopen(filename, "wb"); - if (!F) return false; - - fwrite(buffer, 1, buffer_size, F); - if (ferror(F)) - { - fclose(F); - return false; - } - - fclose(F); - return true; -} bool append_to_list_file(const char *filename, const char *s) { FILE *F = fopen(filename,"at"); @@ -262,50 +240,6 @@ void print_sockaddr(const struct sockaddr *sa) printf("%s", ip_port); } -bool pton4_port(const char *s, struct sockaddr_in *sa) -{ - char ip[16],*p; - size_t l; - unsigned int u; - - p = strchr(s,':'); - if (!p) return false; - l = p-s; - if (l<7 || l>15) return false; - memcpy(ip,s,l); - ip[l]=0; - p++; - - sa->sin_family = AF_INET; - if (inet_pton(AF_INET,ip,&sa->sin_addr)!=1 || sscanf(p,"%u",&u)!=1 || !u || u>0xFFFF) return false; - sa->sin_port = htons((uint16_t)u); - - return true; -} -bool pton6_port(const char *s, struct sockaddr_in6 *sa) -{ - char ip[40],*p; - size_t l; - unsigned int u; - - if (*s++!='[') return false; - p = strchr(s,']'); - if (!p || p[1]!=':') return false; - l = p-s; - if (l<2 || l>39) return false; - p+=2; - memcpy(ip,s,l); - ip[l]=0; - - sa->sin6_family = AF_INET6; - if (inet_pton(AF_INET6,ip,&sa->sin6_addr)!=1 || sscanf(p,"%u",&u)!=1 || !u || u>0xFFFF) return false; - sa->sin6_port = htons((uint16_t)u); - sa->sin6_flowinfo = 0; - sa->sin6_scope_id = 0; - - return true; -} - uint16_t saport(const struct sockaddr *sa) { return ntohs(sa->sa_family==AF_INET ? ((struct sockaddr_in*)sa)->sin_port : diff --git a/nfq2/helpers.h b/nfq2/helpers.h index 1a96a5b..93963d9 100644 --- a/nfq2/helpers.h +++ b/nfq2/helpers.h @@ -33,8 +33,6 @@ char *strncasestr(const char *s,const char *find, size_t slen); bool is_identifier(const char *p); bool load_file(const char *filename, off_t offset, void *buffer, size_t *buffer_size); -bool load_file_nonempty(const char *filename, off_t offset, void *buffer, size_t *buffer_size); -bool save_file(const char *filename, const void *buffer, size_t buffer_size); bool append_to_list_file(const char *filename, const char *s); void expand_bits(void *target, const void *source, unsigned int source_bitlen, unsigned int target_bytelen); @@ -45,8 +43,6 @@ void print_sockaddr(const struct sockaddr *sa); void ntopa46(const struct in_addr *ip, const struct in6_addr *ip6,char *str, size_t len); void ntop46(const struct sockaddr *sa, char *str, size_t len); void ntop46_port(const struct sockaddr *sa, char *str, size_t len); -bool pton4_port(const char *s, struct sockaddr_in *sa); -bool pton6_port(const char *s, struct sockaddr_in6 *sa); uint16_t saport(const struct sockaddr *sa); bool sa_has_addr(const struct sockaddr *sa); diff --git a/nfq2/lua.c b/nfq2/lua.c index 797f9a2..50aae14 100644 --- a/nfq2/lua.c +++ b/nfq2/lua.c @@ -2053,7 +2053,7 @@ uint8_t lua_ip6_l4proto_from_dissect(lua_State *L, int idx) bool lua_reconstruct_dissect(lua_State *L, int idx, uint8_t *buf, size_t *len, bool badsum, bool ip6_preserve_next) { uint8_t *data = buf; - size_t l,lpayload,l3,left = *len; + size_t sz,l,lpayload,l3,left = *len; struct ip *ip=NULL; struct ip6_hdr *ip6=NULL; struct tcphdr *tcp=NULL; @@ -2123,6 +2123,11 @@ bool lua_reconstruct_dissect(lua_State *L, int idx, uint8_t *buf, size_t *len, b p = lua_tolstring(L,-1,&lpayload); if (p) { + if (lpayload>0xFFFF) + { + DLOG_ERR("reconstruct_dissect: invalid payload length\n"); + goto err; + } if (leftuh_ulen = htons((uint16_t)(lpayload+sizeof(struct udphdr))); + sz = (uint16_t)(lpayload+sizeof(struct udphdr)); + if (sz>0xFFFF) + { + DLOG_ERR("reconstruct_dissect: invalid payload length\n"); + goto err; + } + udp->uh_ulen = htons((uint16_t)sz); udp_fix_checksum(udp,l-l3,ip,ip6); if (badsum) udp->uh_sum ^= 1 + (random() % 0xFFFF); } @@ -2290,6 +2301,8 @@ static int luacall_csum_tcp_fix(lua_State *L) size_t l_pl; const uint8_t *b_pl = (const uint8_t*)luaL_checklstring(L, 3, &l_pl); + if (l_pl>0xFFFF) + luaL_error(L, "invalid payload length"); size_t l_tpl = l_tcp + l_pl; uint8_t *tpl = malloc(l_tpl); @@ -2326,11 +2339,13 @@ static int luacall_csum_udp_fix(lua_State *L) size_t l_udp; const uint8_t *b_udp = (const uint8_t*)luaL_checklstring(L, 2, &l_udp); - if (!proto_check_udp(b_udp, ntohs(((struct udphdr*)b_udp)->uh_ulen))) + if (!proto_check_udp(b_udp, l_udp)) luaL_error(L, "invalid udp header"); size_t l_pl; const uint8_t *b_pl = (const uint8_t*)luaL_checklstring(L, 3, &l_pl); + if (l_pl>0xFFFF) + luaL_error(L, "invalid payload length"); size_t l_tpl = l_udp + l_pl; uint8_t *tpl = malloc(l_tpl);