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