Towards WinDivert version 2.1 release.

- inbounds/outbound now work for SOCKET layer.
- passthru.exe now uses MTU_MAX to prevent 122
  errors.
- Further header parsing code hardening.
- Fix bug where Reserved2 was not zeroed.
This commit is contained in:
basil00
2019-08-04 08:11:43 +08:00
parent 69e4edade7
commit 194d9afa1e
9 changed files with 59 additions and 39 deletions
+39 -20
View File
@@ -2168,6 +2168,7 @@ static void windivert_read_service_request(context_t context, packet_t packet,
addr[i].TCPChecksum = packet->tcp_checksum;
addr[i].UDPChecksum = packet->udp_checksum;
addr[i].Reserved1 = 0;
addr[i].Reserved2 = 0;
layer_data = (PVOID)packet->data;
switch (packet->layer)
{
@@ -2371,6 +2372,7 @@ static void windivert_fast_read_service_request(PVOID packet, ULONG packet_len,
addr->TCPChecksum = (tcp_checksum? 1: 0);
addr->UDPChecksum = (udp_checksum? 1: 0);
addr->Reserved1 = 0;
addr->Reserved2 = 0;
switch (layer)
{
case WINDIVERT_LAYER_NETWORK:
@@ -4180,7 +4182,7 @@ static void windivert_resource_assignment_v4_classify(
windivert_socket_classify(context, &socket_data,
/*event=*/WINDIVERT_EVENT_SOCKET_BIND, /*ipv4=*/TRUE,
/*outbound=*/FALSE, loopback, result);
/*outbound=*/TRUE, loopback, result);
}
/*
@@ -4223,7 +4225,7 @@ static void windivert_resource_assignment_v6_classify(
windivert_socket_classify(context, &socket_data,
/*event=*/WINDIVERT_EVENT_SOCKET_BIND, /*ipv4=*/FALSE,
/*outbound=*/FALSE, loopback, result);
/*outbound=*/TRUE, loopback, result);
}
/*
@@ -4261,7 +4263,7 @@ static void windivert_resource_release_v4_classify(
windivert_socket_classify(context, &socket_data,
/*event=*/WINDIVERT_EVENT_SOCKET_CLOSE, /*ipv4=*/TRUE,
/*outbound=*/FALSE, loopback, result);
/*outbound=*/TRUE, loopback, result);
}
/*
@@ -4299,7 +4301,7 @@ static void windivert_resource_release_v6_classify(
windivert_socket_classify(context, &socket_data,
/*event=*/WINDIVERT_EVENT_SOCKET_CLOSE, /*ipv4=*/FALSE,
/*outbound=*/FALSE, loopback, result);
/*outbound=*/TRUE, loopback, result);
}
/*
@@ -4527,7 +4529,7 @@ static void windivert_auth_listen_v4_classify(
windivert_socket_classify(context, &socket_data,
/*event=*/WINDIVERT_EVENT_SOCKET_LISTEN, /*ipv4=*/TRUE,
/*outbound=*/FALSE, loopback, result);
/*outbound=*/TRUE, loopback, result);
}
/*
@@ -4569,7 +4571,7 @@ static void windivert_auth_listen_v6_classify(
windivert_socket_classify(context, &socket_data,
/*event=*/WINDIVERT_EVENT_SOCKET_LISTEN, /*ipv4=*/FALSE,
/*outbound=*/FALSE, loopback, result);
/*outbound=*/TRUE, loopback, result);
}
/*
@@ -5289,7 +5291,7 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
PWINDIVERT_UDPHDR *udp_header_ptr, UINT8 *proto_ptr, UINT *header_len_ptr,
UINT *payload_len_ptr)
{
UINT tot_len, ip_header_len;
UINT total_len, ip_header_len = 0;
PWINDIVERT_IPHDR ip_header = NULL;
PWINDIVERT_IPV6HDR ipv6_header = NULL;
PWINDIVERT_ICMPHDR icmp_header = NULL;
@@ -5306,8 +5308,8 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
DEBUG("FILTER: REJECT (packet is NULL)");
return FALSE;
}
tot_len = NET_BUFFER_DATA_LENGTH(buffer);
if (tot_len < sizeof(WINDIVERT_IPHDR))
total_len = NET_BUFFER_DATA_LENGTH(buffer);
if (total_len < sizeof(WINDIVERT_IPHDR))
{
DEBUG("FILTER: REJECT (packet length too small)");
return FALSE;
@@ -5317,7 +5319,7 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
if (ipv4)
{
// IPv4:
if (tot_len < sizeof(WINDIVERT_IPHDR))
if (total_len < sizeof(WINDIVERT_IPHDR))
{
DEBUG("FILTER: REJECT (packet length too small)");
return FALSE;
@@ -5331,14 +5333,14 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
}
ip_header_len = ip_header->HdrLength*sizeof(UINT32);
if (ip_header->Version != 4 ||
RtlUshortByteSwap(ip_header->Length) != tot_len ||
RtlUshortByteSwap(ip_header->Length) != total_len ||
ip_header->HdrLength < 5 ||
ip_header_len > tot_len)
ip_header_len > total_len)
{
DEBUG("FILTER: REJECT (bad IPv4 packet)");
return FALSE;
}
if (!frag_mode &&
if (!frag_mode &&
(WINDIVERT_IPHDR_GET_MF(ip_header) != 0 ||
WINDIVERT_IPHDR_GET_FRAGOFF(ip_header) != 0))
{
@@ -5351,7 +5353,7 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
else
{
// IPv6:
if (tot_len < sizeof(WINDIVERT_IPV6HDR))
if (total_len < sizeof(WINDIVERT_IPV6HDR))
{
DEBUG("FILTER: REJECT (packet length too small)");
return FALSE;
@@ -5365,9 +5367,9 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
}
ip_header_len = sizeof(WINDIVERT_IPV6HDR);
if (ipv6_header->Version != 6 ||
ip_header_len > tot_len ||
ip_header_len > total_len ||
RtlUshortByteSwap(ipv6_header->Length) +
sizeof(WINDIVERT_IPV6HDR) != tot_len)
sizeof(WINDIVERT_IPV6HDR) != total_len)
{
DEBUG("FILTER: REJECT (bad IPv6 packet)");
return FALSE;
@@ -5395,6 +5397,8 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
if (!frag_mode)
{
DEBUG("FILTER: REJECT (fragment)");
NdisRetreatNetBufferDataStart(buffer, ip_header_len,
0, NULL);
return FALSE;
}
ext_header_len = 8;
@@ -5420,6 +5424,13 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
}
proto = ext_header[0];
if (ip_header_len + ext_header_len > total_len)
{
DEBUG("FILTER: REJECT (bad IPv6 extension header)");
NdisRetreatNetBufferDataStart(buffer, ip_header_len,
0, NULL);
return FALSE;
}
ip_header_len += ext_header_len;
NdisAdvanceNetBufferDataStart(buffer, ext_header_len, FALSE,
NULL);
@@ -5443,8 +5454,17 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
case IPPROTO_TCP:
tcp_header = (PWINDIVERT_TCPHDR)NdisGetDataBuffer(buffer,
sizeof(WINDIVERT_TCPHDR), NULL, 1, 0);
header_len +=
(tcp_header == NULL? 0: tcp_header->HdrLength*sizeof(UINT32));
if (tcp_header != NULL)
{
UINT tcp_header_len = tcp_header->HdrLength * sizeof(UINT32);
if (header_len + tcp_header_len > total_len)
{
// Bad TCP options:
tcp_header = NULL;
break;
}
header_len += tcp_header_len;
}
break;
case IPPROTO_UDP:
udp_header = (PWINDIVERT_UDPHDR)NdisGetDataBuffer(buffer,
@@ -5454,7 +5474,6 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
default:
break;
}
status = NdisRetreatNetBufferDataStart(buffer, ip_header_len, 0, NULL);
if (!NT_SUCCESS(status))
{
@@ -5471,7 +5490,7 @@ static BOOL windivert_parse_headers(PNET_BUFFER buffer, BOOL ipv4,
*udp_header_ptr = udp_header;
*proto_ptr = proto;
*header_len_ptr = header_len;
*payload_len_ptr = (header_len > tot_len? 0: tot_len - header_len);
*payload_len_ptr = total_len - header_len;
return TRUE;
}