22 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
33 * SPDX-License-Identifier: Apache-2.0.
44 */
5+ #include <aws/common/byte_order.h>
56#include <aws/common/environment.h>
67#include <aws/http/private/no_proxy.h>
7-
8- #ifdef _WIN32
9- # include <ws2tcpip.h>
10- #else
11- # include <arpa/inet.h>
12- #endif
8+ #include <aws/io/socket.h>
139
1410enum hostname_type {
1511 HOSTNAME_TYPE_IPV4 ,
@@ -38,15 +34,15 @@ static bool s_cidr4_match(uint64_t bits, struct aws_string *network_part, uint32
3834 }
3935
4036 /* Convert network pattern to binary */
41- if (inet_pton ( AF_INET , aws_string_c_str ( network_part ) , & check ) != 1 ) {
37+ if (aws_parse_ipv4_address ( network_part , & check ) != AWS_OP_SUCCESS ) {
4238 return false;
4339 }
4440
4541 if (bits > 0 && bits < 32 ) {
4642 /* Apply the network mask for CIDR comparison */
4743 uint32_t mask = 0xffffffff << (32 - bits );
48- uint32_t host_network = ntohl (address );
49- uint32_t check_network = ntohl (check );
44+ uint32_t host_network = aws_ntoh32 (address );
45+ uint32_t check_network = aws_ntoh32 (check );
5046
5147 /* Compare the masked addresses */
5248 return (host_network & mask ) == (check_network & mask );
@@ -66,45 +62,62 @@ static bool s_cidr4_match(uint64_t bits, struct aws_string *network_part, uint32
6662 * @param host_addr Pre-parsed binary representation of the host IP, or NULL to parse from host
6763 * @return true if the IP address matches the CIDR pattern, false otherwise
6864 */
69- static bool s_cidr6_match (uint64_t bits , struct aws_string * network_part , uint8_t * address ) {
70- uint8_t check [16 ] = {0 };
71-
65+ static bool s_cidr6_match (
66+ struct aws_allocator * allocator ,
67+ uint64_t bits ,
68+ struct aws_string * network_part ,
69+ struct aws_byte_cursor address ) {
70+ bool result = false;
71+ struct aws_byte_buf check_buf ;
72+ aws_byte_buf_init (& check_buf , allocator , 16 );
7273 /* If no bits specified, use full 128 bits for IPv6 */
7374 if (!bits ) {
7475 bits = 128 ;
7576 }
7677
7778 /* Check for valid bits parameter */
7879 if (bits > 128 ) {
79- return false ;
80+ goto cleanup ;
8081 }
8182 /* Convert network pattern to binary */
82- if (inet_pton ( AF_INET6 , aws_string_c_str ( network_part ), check ) != 1 ) {
83- return false ;
83+ if (aws_parse_ipv6_address ( network_part , & check_buf ) != AWS_OP_SUCCESS ) {
84+ goto cleanup ;
8485 }
86+ struct aws_byte_cursor check = aws_byte_cursor_from_buf (& check_buf );
8587
8688 /* Calculate full bytes and remaining bits in the netmask */
8789 uint64_t bytes = bits / 8 ;
8890 uint64_t rest = bits % 8 ;
89-
90- /* Compare full bytes of the network part */
91- if (bytes > 0 && memcmp (address , check , (size_t )bytes ) != 0 ) {
92- return false;
91+ if (bytes > address .len || address .len != check_buf .len || check_buf .len != 16 ) {
92+ goto cleanup ;
93+ }
94+ if (bytes > 0 && !aws_array_eq (address .ptr , (size_t )bytes , check .ptr , (size_t )bytes )) {
95+ goto cleanup ;
9396 }
9497
9598 /* If we have remaining bits, compare the partial byte */
96- if (rest > 0 && bytes < 16 ) {
99+ if (rest > 0 ) {
97100 /* Create a mask for the remaining bits */
98101 unsigned char mask = (unsigned char )(0xff << (8 - rest ));
99-
102+ aws_byte_cursor_advance (& check , (size_t )bytes );
103+ aws_byte_cursor_advance (& address , (size_t )bytes );
104+ uint8_t address_byte = 0 ;
105+ uint8_t check_byte = 0 ;
106+ if (aws_byte_cursor_read_u8 (& address , & address_byte ) == false ||
107+ aws_byte_cursor_read_u8 (& check , & check_byte ) == false) {
108+ goto cleanup ;
109+ }
100110 /* Check if the masked bits match */
101- if ((address [ bytes ] & mask ) != (check [ bytes ] & mask )) {
102- return false ;
111+ if ((address_byte & mask ) != (check_byte & mask )) {
112+ goto cleanup ;
103113 }
104114 }
105115
106116 /* All checks passed, addresses match within the CIDR range */
107- return true;
117+ result = true;
118+ cleanup :
119+ aws_byte_buf_clean_up (& check_buf );
120+ return result ;
108121}
109122
110123static bool s_is_dot (uint8_t c ) {
@@ -128,6 +141,7 @@ bool aws_http_host_matches_no_proxy(
128141 struct aws_byte_cursor no_proxy_cur = aws_byte_cursor_from_string (no_proxy_str );
129142 struct aws_array_list no_proxy_list ;
130143 struct aws_string * host_str = aws_string_new_from_cursor (allocator , & host );
144+ struct aws_byte_buf ipv6_addr = {0 };
131145
132146 if (aws_array_list_init_dynamic (& no_proxy_list , allocator , 10 , sizeof (struct aws_byte_cursor ))) {
133147 goto cleanup ;
@@ -139,11 +153,10 @@ bool aws_http_host_matches_no_proxy(
139153
140154 /* Store parsed binary addresses for reuse */
141155 uint32_t ipv4_addr = 0 ;
142- uint8_t ipv6_addr [16 ] = {0 };
143156
144157 /* Determine host type and parse address if applicable */
145158 enum hostname_type type = HOSTNAME_TYPE_REGULAR ;
146- if (inet_pton ( AF_INET , aws_string_c_str ( host_str ) , & ipv4_addr ) == 1 ) {
159+ if (aws_parse_ipv4_address ( host_str , & ipv4_addr ) == AWS_OP_SUCCESS ) {
147160 type = HOSTNAME_TYPE_IPV4 ;
148161 } else {
149162 struct aws_string * host_str_copy = host_str ;
@@ -155,7 +168,8 @@ bool aws_http_host_matches_no_proxy(
155168 host_str_copy = aws_string_new_from_cursor (allocator , & host_copy );
156169 }
157170
158- if (inet_pton (AF_INET6 , aws_string_c_str (host_str_copy ), ipv6_addr ) == 1 ) {
171+ aws_byte_buf_init (& ipv6_addr , allocator , 16 );
172+ if (aws_parse_ipv6_address (host_str_copy , & ipv6_addr ) == AWS_OP_SUCCESS ) {
159173 /* Update the host str */
160174 if (host_str != host_str_copy ) {
161175 aws_string_destroy (host_str );
@@ -254,7 +268,8 @@ bool aws_http_host_matches_no_proxy(
254268 goto cleanup ;
255269 }
256270 } else {
257- if (s_cidr6_match (network_bits , network_part_str , ipv6_addr )) {
271+ if (s_cidr6_match (
272+ allocator , network_bits , network_part_str , aws_byte_cursor_from_buf (& ipv6_addr ))) {
258273 bypass = true;
259274 aws_string_destroy (network_part_str );
260275 goto cleanup ;
@@ -271,6 +286,7 @@ bool aws_http_host_matches_no_proxy(
271286 }
272287
273288cleanup :
289+ aws_byte_buf_clean_up (& ipv6_addr );
274290 aws_string_destroy (host_str );
275291 aws_array_list_clean_up (& no_proxy_list );
276292 return bypass ;
0 commit comments