1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 
12 /**************************************************************************/
13 /**************************************************************************/
14 /**                                                                       */
15 /** NetX Component                                                        */
16 /**                                                                       */
17 /**   HTTP Proxy Protocol                                                 */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 #define NX_SOURCE_CODE
22 
23 
24 #include "nx_ip.h"
25 #include "nx_ipv6.h"
26 #include "nx_packet.h"
27 #include "nx_tcp.h"
28 #include "nx_http_proxy_client.h"
29 
30 #ifdef NX_ENABLE_HTTP_PROXY
31 #define NX_HTTP_CRLF       "\r\n"
32 #define NX_HTTP_CRLF_SIZE  2
33 
34 /**************************************************************************/
35 /*                                                                        */
36 /*  FUNCTION                                               RELEASE        */
37 /*                                                                        */
38 /*    _nxe_http_proxy_client_enable                       PORTABLE C      */
39 /*                                                           6.2.0        */
40 /*  AUTHOR                                                                */
41 /*                                                                        */
42 /*    Wenhui Xie, Microsoft Corporation                                   */
43 /*                                                                        */
44 /*  DESCRIPTION                                                           */
45 /*                                                                        */
46 /*    This function checks for errors in the HTTP Proxy enable call.      */
47 /*                                                                        */
48 /*                                                                        */
49 /*  INPUT                                                                 */
50 /*                                                                        */
51 /*    ip_ptr                                Pointer to IP instance        */
52 /*    proxy_server_ip                       IP address of proxy server    */
53 /*    proxy_server_port                     Port of proxy server          */
54 /*    username                              Pointer to username           */
55 /*    username_length                       Length of username            */
56 /*    password                              Pointer to password           */
57 /*    password_length                       Length of password            */
58 /*                                                                        */
59 /*  OUTPUT                                                                */
60 /*                                                                        */
61 /*    status                                Completion status             */
62 /*                                                                        */
63 /*  CALLS                                                                 */
64 /*                                                                        */
65 /*    _nx_http_proxy_client_enable          Actual HTTP Proxy enable call */
66 /*                                                                        */
67 /*  CALLED BY                                                             */
68 /*                                                                        */
69 /*    Application Code                                                    */
70 /*                                                                        */
71 /*  RELEASE HISTORY                                                       */
72 /*                                                                        */
73 /*    DATE              NAME                      DESCRIPTION             */
74 /*                                                                        */
75 /*  10-31-2022     Wenhui Xie               Initial Version 6.2.0         */
76 /*                                                                        */
77 /**************************************************************************/
_nxe_http_proxy_client_enable(NX_IP * ip_ptr,NXD_ADDRESS * proxy_server_ip,UINT proxy_server_port,UCHAR * username,UINT username_length,UCHAR * password,UINT password_length)78 UINT _nxe_http_proxy_client_enable(NX_IP *ip_ptr, NXD_ADDRESS *proxy_server_ip, UINT proxy_server_port,
79                                    UCHAR *username, UINT username_length, UCHAR *password, UINT password_length)
80 {
81 UINT        status;
82 
83     /* Check for invalid input pointers.  */
84     if ((ip_ptr == NX_NULL) || (ip_ptr -> nx_ip_id != NX_IP_ID) ||
85         (proxy_server_ip == NX_NULL) || (proxy_server_port == 0) ||
86         ((username == NX_NULL) && (username_length != 0)) ||
87         ((password == NX_NULL) && (password_length != 0)))
88     {
89         return(NX_PTR_ERROR);
90     }
91 
92     /* Check the length of username and password.  */
93     if ((username_length > NX_HTTP_PROXY_MAX_USERNAME) ||
94         (password_length > NX_HTTP_PROXY_MAX_PASSWORD))
95     {
96         return(NX_SIZE_ERROR);
97     }
98 
99     /* Check that the server IP address version is either IPv4 or IPv6. */
100     if ((proxy_server_ip -> nxd_ip_version != NX_IP_VERSION_V4) &&
101         (proxy_server_ip -> nxd_ip_version != NX_IP_VERSION_V6))
102     {
103 
104         return(NX_IP_ADDRESS_ERROR);
105     }
106 
107 #ifndef NX_DISABLE_IPV4
108     /* Check for a valid server IP address if the server_ip is version IPv4.  */
109     if (proxy_server_ip -> nxd_ip_version == NX_IP_VERSION_V4)
110     {
111         if (((proxy_server_ip -> nxd_ip_address.v4 & NX_IP_CLASS_A_MASK) != NX_IP_CLASS_A_TYPE) &&
112             ((proxy_server_ip -> nxd_ip_address.v4 & NX_IP_CLASS_B_MASK) != NX_IP_CLASS_B_TYPE) &&
113             ((proxy_server_ip -> nxd_ip_address.v4 & NX_IP_CLASS_C_MASK) != NX_IP_CLASS_C_TYPE))
114         {
115             return(NX_IP_ADDRESS_ERROR);
116         }
117     }
118 #endif /* !NX_DISABLE_IPV4  */
119 
120     /* Check for an invalid port.  */
121     if (((ULONG)proxy_server_port) > (ULONG)NX_MAX_PORT)
122     {
123         return(NX_INVALID_PORT);
124     }
125 
126     /* Call actual HTTP proxy enable function.  */
127     status = _nx_http_proxy_client_enable(ip_ptr, proxy_server_ip, proxy_server_port, username,
128                                           username_length, password, password_length);
129 
130     /* Return completion status.  */
131     return(status);
132 }
133 
134 /**************************************************************************/
135 /*                                                                        */
136 /*  FUNCTION                                               RELEASE        */
137 /*                                                                        */
138 /*    _nx_http_proxy_client_enable                        PORTABLE C      */
139 /*                                                           6.2.0        */
140 /*  AUTHOR                                                                */
141 /*                                                                        */
142 /*    Wenhui Xie, Microsoft Corporation                                   */
143 /*                                                                        */
144 /*  DESCRIPTION                                                           */
145 /*                                                                        */
146 /*    This function enables the HTTP Proxy and sets the information of    */
147 /*    the HTTP Proxy server.                                              */
148 /*                                                                        */
149 /*                                                                        */
150 /*  INPUT                                                                 */
151 /*                                                                        */
152 /*    ip_ptr                                Pointer to IP instance        */
153 /*    proxy_server_ip                       IP address of proxy server    */
154 /*    proxy_server_port                     Port of proxy server          */
155 /*    username                              Pointer to username           */
156 /*    username_length                       Length of username            */
157 /*    password                              Pointer to password           */
158 /*    password_length                       Length of password            */
159 /*                                                                        */
160 /*  OUTPUT                                                                */
161 /*                                                                        */
162 /*    status                                Completion status             */
163 /*                                                                        */
164 /*  CALLS                                                                 */
165 /*                                                                        */
166 /*    COPY_IPV6_ADDRESS                     Copy IPv6 address             */
167 /*                                                                        */
168 /*  CALLED BY                                                             */
169 /*                                                                        */
170 /*    Application Code                                                    */
171 /*                                                                        */
172 /*  RELEASE HISTORY                                                       */
173 /*                                                                        */
174 /*    DATE              NAME                      DESCRIPTION             */
175 /*                                                                        */
176 /*  10-31-2022     Wenhui Xie               Initial Version 6.2.0         */
177 /*                                                                        */
178 /**************************************************************************/
_nx_http_proxy_client_enable(NX_IP * ip_ptr,NXD_ADDRESS * proxy_server_ip,UINT proxy_server_port,UCHAR * username,UINT username_length,UCHAR * password,UINT password_length)179 UINT _nx_http_proxy_client_enable(NX_IP *ip_ptr, NXD_ADDRESS *proxy_server_ip, UINT proxy_server_port,
180                                   UCHAR *username, UINT username_length, UCHAR *password, UINT password_length)
181 {
182 
183 UINT status;
184 UCHAR string[NX_HTTP_PROXY_MAX_USERNAME + NX_HTTP_PROXY_MAX_PASSWORD + 2];
185 
186     /* Set the IP address of HTTP proxy.  */
187     ip_ptr -> nx_ip_http_proxy_ip_address.nxd_ip_version = proxy_server_ip -> nxd_ip_version;
188 
189 #ifndef NX_DISABLE_IPV4
190     if (proxy_server_ip -> nxd_ip_version == NX_IP_VERSION_V4)
191     {
192 
193         /* Copy the IPv4 address */
194         ip_ptr -> nx_ip_http_proxy_ip_address.nxd_ip_address.v4 = proxy_server_ip -> nxd_ip_address.v4;
195     }
196 #endif /* !NX_DISABLE_IPV4  */
197 
198 #ifdef FEATURE_NX_IPV6
199     if (proxy_server_ip -> nxd_ip_version == NX_IP_VERSION_V6)
200     {
201 
202         /* Copy the IPv6 address */
203         COPY_IPV6_ADDRESS(proxy_server_ip -> nxd_ip_address.v6,
204                           ip_ptr -> nx_ip_http_proxy_ip_address.nxd_ip_address.v6);
205     }
206 #endif /* FEATURE_NX_IPV6 */
207 
208     /* Set the port of HTTP proxy.  */
209     ip_ptr -> nx_ip_http_proxy_port = (USHORT)proxy_server_port;
210 
211     /* Determine if basic authentication is required.  */
212     if ((username_length) && (password_length))
213     {
214 
215         /* Encode the "name:password" into authentication buffer.  */
216 
217         /* Place the name and password in a single string.  */
218 
219         /* Copy the name into the merged string.  */
220         memcpy(string, username, username_length); /* Use case of memcpy is verified. */
221 
222         /* Insert the colon.  */
223         string[username_length] =  ':';
224 
225         /* Copy the password into the merged string.  */
226         memcpy(&string[username_length + 1], password, password_length); /* Use case of memcpy is verified. */
227 
228         /* Make combined string NULL terminated.  */
229         string[username_length + password_length + 1] =  NX_NULL;
230 
231         /* Now encode the username:password string.  */
232         status = _nx_utility_base64_encode((UCHAR *)string, username_length + password_length + 1,
233                                            (UCHAR *)ip_ptr -> nx_ip_http_proxy_authentication,
234                                            sizeof(ip_ptr -> nx_ip_http_proxy_authentication),
235                                            &(ip_ptr -> nx_ip_http_proxy_authentication_length));
236 
237         /* Check status.  */
238         if (status)
239         {
240             return(status);
241         }
242     }
243     else
244     {
245         ip_ptr -> nx_ip_http_proxy_authentication_length = 0;
246     }
247 
248     /* Set HTTP proxy as enabled.  */
249     ip_ptr -> nx_ip_http_proxy_enable = NX_TRUE;
250 
251     return(NX_SUCCESS);
252 }
253 
254 /**************************************************************************/
255 /*                                                                        */
256 /*  FUNCTION                                               RELEASE        */
257 /*                                                                        */
258 /*    _nx_http_proxy_client_initialize                    PORTABLE C      */
259 /*                                                           6.2.0        */
260 /*  AUTHOR                                                                */
261 /*                                                                        */
262 /*    Wenhui Xie, Microsoft Corporation                                   */
263 /*                                                                        */
264 /*  DESCRIPTION                                                           */
265 /*                                                                        */
266 /*    This function initializes the state of HTTP Proxy and stores the    */
267 /*    the information of remote server.                                   */
268 /*                                                                        */
269 /*                                                                        */
270 /*  INPUT                                                                 */
271 /*                                                                        */
272 /*    socket_ptr                            Pointer to TCP client socket  */
273 /*    server_ip                             IP address of remote server   */
274 /*    server_port                           Port of remote server         */
275 /*                                                                        */
276 /*  OUTPUT                                                                */
277 /*                                                                        */
278 /*    NONE                                                                */
279 /*                                                                        */
280 /*  CALLS                                                                 */
281 /*                                                                        */
282 /*    COPY_IPV6_ADDRESS                     Copy IPv6 address             */
283 /*                                                                        */
284 /*  CALLED BY                                                             */
285 /*                                                                        */
286 /*    _nxd_tcp_client_socket_connect        Connect TCP client socket     */
287 /*                                                                        */
288 /*  RELEASE HISTORY                                                       */
289 /*                                                                        */
290 /*    DATE              NAME                      DESCRIPTION             */
291 /*                                                                        */
292 /*  10-31-2022     Wenhui Xie               Initial Version 6.2.0         */
293 /*                                                                        */
294 /**************************************************************************/
_nx_http_proxy_client_initialize(NX_TCP_SOCKET * socket_ptr,NXD_ADDRESS ** server_ip,UINT * server_port)295 VOID _nx_http_proxy_client_initialize(NX_TCP_SOCKET *socket_ptr, NXD_ADDRESS **server_ip, UINT *server_port)
296 {
297 
298 NX_IP *ip_ptr = socket_ptr -> nx_tcp_socket_ip_ptr;
299 
300     /* Store the server's IP and port for sending CONNECT request later.  */
301     socket_ptr -> nx_tcp_socket_original_server_ip.nxd_ip_version = (*server_ip) -> nxd_ip_version;
302 
303 #ifndef NX_DISABLE_IPV4
304     if ((*server_ip) -> nxd_ip_version == NX_IP_VERSION_V4)
305     {
306 
307         /* Copy the IPv4 address */
308         socket_ptr -> nx_tcp_socket_original_server_ip.nxd_ip_address.v4 = (*server_ip) -> nxd_ip_address.v4;
309     }
310 #endif /* !NX_DISABLE_IPV4  */
311 
312 #ifdef FEATURE_NX_IPV6
313     if ((*server_ip) -> nxd_ip_version == NX_IP_VERSION_V6)
314     {
315 
316         /* Copy the IPv6 address */
317         COPY_IPV6_ADDRESS((*server_ip) -> nxd_ip_address.v6,
318                           socket_ptr -> nx_tcp_socket_original_server_ip.nxd_ip_address.v6);
319     }
320 #endif /* FEATURE_NX_IPV6 */
321 
322     socket_ptr -> nx_tcp_socket_original_server_port = *server_port;
323 
324     /* Replace the peer info with HTTP proxy's IP and port.  */
325     *server_ip = &(ip_ptr -> nx_ip_http_proxy_ip_address);
326     *server_port = ip_ptr -> nx_ip_http_proxy_port;
327 
328     /* Initialize the state.  */
329     socket_ptr -> nx_tcp_socket_http_proxy_state = NX_HTTP_PROXY_STATE_INIT;
330     socket_ptr -> nx_tcp_socket_http_proxy_header_packet = NX_NULL;
331 }
332 
333 /**************************************************************************/
334 /*                                                                        */
335 /*  FUNCTION                                               RELEASE        */
336 /*                                                                        */
337 /*    _nx_http_proxy_client_connect                       PORTABLE C      */
338 /*                                                           6.2.0        */
339 /*  AUTHOR                                                                */
340 /*                                                                        */
341 /*    Wenhui Xie, Microsoft Corporation                                   */
342 /*                                                                        */
343 /*  DESCRIPTION                                                           */
344 /*                                                                        */
345 /*    This function sends HTTP request to connect with HTTP Proxy server. */
346 /*                                                                        */
347 /*                                                                        */
348 /*  INPUT                                                                 */
349 /*                                                                        */
350 /*    socket_ptr                            Pointer to TCP client socket  */
351 /*                                                                        */
352 /*  OUTPUT                                                                */
353 /*                                                                        */
354 /*    status                                Completion status             */
355 /*                                                                        */
356 /*  CALLS                                                                 */
357 /*                                                                        */
358 /*    _nx_tcp_socket_disconnect             Disconnect TCP socket         */
359 /*    _nx_utility_uint_to_string            Convert integer to string     */
360 /*    _nx_utility_base64_encode             Base64 encode                 */
361 /*    _nx_packet_allocate                   Allocate packet               */
362 /*    _nx_packet_data_append                Append packet data            */
363 /*    _nx_packet_release                    Release packet                */
364 /*                                                                        */
365 /*  CALLED BY                                                             */
366 /*                                                                        */
367 /*    _nx_tcp_socket_state_syn_received     Process SYN RECEIVED state    */
368 /*    _nx_tcp_socket_state_syn_sent         Process SYN SENT state        */
369 /*                                                                        */
370 /*  RELEASE HISTORY                                                       */
371 /*                                                                        */
372 /*    DATE              NAME                      DESCRIPTION             */
373 /*                                                                        */
374 /*  10-31-2022     Wenhui Xie               Initial Version 6.2.0         */
375 /*                                                                        */
376 /**************************************************************************/
_nx_http_proxy_client_connect(NX_TCP_SOCKET * socket_ptr)377 UINT _nx_http_proxy_client_connect(NX_TCP_SOCKET *socket_ptr)
378 {
379 
380 UINT status;
381 NX_PACKET *packet_ptr;
382 NX_IP *ip_ptr = socket_ptr -> nx_tcp_socket_ip_ptr;
383 NX_PACKET_POOL *pool_ptr = ip_ptr -> nx_ip_default_packet_pool;
384 CHAR *ip_string_ptr;
385 UINT ip_string_len = 0;
386 CHAR *port_string_ptr;
387 UINT port_string_len = 0;
388 UINT temp_length = 0;
389 NXD_ADDRESS *server_ip = &(socket_ptr -> nx_tcp_socket_original_server_ip);
390 UINT port = socket_ptr -> nx_tcp_socket_original_server_port;
391 
392 
393     /* Check the IP version of the server.  */
394     if (server_ip -> nxd_ip_version != NX_IP_VERSION_V4)
395     {
396 
397         /* Only IPv4 is supported.  */
398         _nx_tcp_socket_disconnect(socket_ptr, NX_NO_WAIT);
399         return(NX_NOT_SUPPORTED);
400     }
401 
402     /* Allocate packet.  */
403     if (socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V4)
404     {
405         status =  _nx_packet_allocate(pool_ptr, &packet_ptr, NX_IPv4_TCP_PACKET, NX_NO_WAIT);
406     }
407     else
408     {
409         status =  _nx_packet_allocate(pool_ptr, &packet_ptr, NX_IPv6_TCP_PACKET, NX_NO_WAIT);
410     }
411 
412     /* Check status.  */
413     if (status)
414     {
415         _nx_tcp_socket_disconnect(socket_ptr, NX_NO_WAIT);
416         return(status);
417     }
418 
419     /* Convert IP address and port to string.  */
420     /* Use the buffer before prepend pointer to store the IP and port string.  */
421     ip_string_ptr = (CHAR *)packet_ptr -> nx_packet_data_start;
422     temp_length = (UINT)(packet_ptr -> nx_packet_prepend_ptr - packet_ptr -> nx_packet_data_start);
423 
424     /* Convert IP address to string.  */
425     ip_string_len = _nx_utility_uint_to_string((UCHAR)(server_ip -> nxd_ip_address.v4 >> 24), 10, ip_string_ptr, temp_length);
426     ip_string_ptr[ip_string_len++] = '.';
427     ip_string_len += _nx_utility_uint_to_string((UCHAR)(server_ip -> nxd_ip_address.v4 >> 16), 10, ip_string_ptr + ip_string_len, temp_length - ip_string_len);
428     ip_string_ptr[ip_string_len++] = '.';
429     ip_string_len += _nx_utility_uint_to_string((UCHAR)(server_ip -> nxd_ip_address.v4 >> 8), 10, ip_string_ptr + ip_string_len, temp_length - ip_string_len);
430     ip_string_ptr[ip_string_len++] = '.';
431     ip_string_len += _nx_utility_uint_to_string((UCHAR)(server_ip -> nxd_ip_address.v4), 10, ip_string_ptr + ip_string_len, temp_length - ip_string_len);
432 
433     /* Convert port to string.  */
434     port_string_ptr = ip_string_ptr + ip_string_len;
435     port_string_len = _nx_utility_uint_to_string(port, 10, ip_string_ptr + ip_string_len, temp_length - ip_string_len);
436 
437     /* HTTP proxy opening handshake message format:
438        CONNECT IP address:port HTTP/1.1
439        Host: IP address
440     */
441 
442     /* Build the CONNECT request: CONNECT + Request URI(IP address:port) + HTTP version.  */
443     status = _nx_packet_data_append(packet_ptr, "CONNECT ", sizeof("CONNECT ") - 1, pool_ptr, NX_NO_WAIT);
444     status += _nx_packet_data_append(packet_ptr, ip_string_ptr, ip_string_len, pool_ptr, NX_NO_WAIT);
445     status += _nx_packet_data_append(packet_ptr, ":", sizeof(":") - 1, pool_ptr, NX_NO_WAIT);
446     status += _nx_packet_data_append(packet_ptr, port_string_ptr, port_string_len, pool_ptr, NX_NO_WAIT);
447     status += _nx_packet_data_append(packet_ptr, " HTTP/1.1", sizeof(" HTTP/1.1") - 1, pool_ptr, NX_NO_WAIT);
448     status += _nx_packet_data_append(packet_ptr, NX_HTTP_CRLF, NX_HTTP_CRLF_SIZE, pool_ptr, NX_NO_WAIT);
449 
450     /* Place the Host in the header.  */
451     status += _nx_packet_data_append(packet_ptr, "Host: ", sizeof("Host: ") - 1, pool_ptr, NX_NO_WAIT);
452     status += _nx_packet_data_append(packet_ptr, ip_string_ptr, ip_string_len, pool_ptr, NX_NO_WAIT);
453     status += _nx_packet_data_append(packet_ptr, NX_HTTP_CRLF, NX_HTTP_CRLF_SIZE, pool_ptr, NX_NO_WAIT);
454 
455     /* Check status.  */
456     if (status)
457     {
458         _nx_packet_release(packet_ptr);
459         _nx_tcp_socket_disconnect(socket_ptr, NX_NO_WAIT);
460         return(NX_NOT_SUCCESSFUL);
461     }
462 
463     /* Determine if basic authentication is required.  */
464     if (ip_ptr -> nx_ip_http_proxy_authentication_length)
465     {
466 
467         /* Yes, attempt to build basic authentication.  */
468         status = _nx_packet_data_append(packet_ptr, "Proxy-authorization: Basic ", 27, pool_ptr, NX_NO_WAIT);
469 
470         /* Check status.  */
471         if (status)
472         {
473             _nx_packet_release(packet_ptr);
474             _nx_tcp_socket_disconnect(socket_ptr, NX_NO_WAIT);
475             return(status);
476         }
477 
478         /* Append authentication string.  */
479         status = _nx_packet_data_append(packet_ptr, ip_ptr -> nx_ip_http_proxy_authentication,
480                                         ip_ptr -> nx_ip_http_proxy_authentication_length, pool_ptr, NX_NO_WAIT);
481         status += _nx_packet_data_append(packet_ptr, NX_HTTP_CRLF, NX_HTTP_CRLF_SIZE, pool_ptr, NX_NO_WAIT);
482 
483         /* Check status.  */
484         if (status)
485         {
486             _nx_packet_release(packet_ptr);
487             _nx_tcp_socket_disconnect(socket_ptr, NX_NO_WAIT);
488             return(NX_NOT_SUCCESSFUL);
489         }
490     }
491 
492     /* Append CRLF.  */
493     status = _nx_packet_data_append(packet_ptr, NX_HTTP_CRLF, NX_HTTP_CRLF_SIZE, pool_ptr, NX_NO_WAIT);
494 
495     /* Check status.  */
496     if (status)
497     {
498         _nx_packet_release(packet_ptr);
499         _nx_tcp_socket_disconnect(socket_ptr, NX_NO_WAIT);
500         return(status);
501     }
502 
503     /* Send out the packet.  */
504     status = _nx_tcp_socket_send(socket_ptr, packet_ptr, NX_NO_WAIT);
505 
506     /* Check status.  */
507     if (status)
508     {
509         _nx_packet_release(packet_ptr);
510         _nx_tcp_socket_disconnect(socket_ptr, NX_NO_WAIT);
511         return(status);
512     }
513 
514     /* Update HTTP Proxy state.  */
515     socket_ptr -> nx_tcp_socket_http_proxy_state = NX_HTTP_PROXY_STATE_CONNECTING;
516 
517     /* Return successful completion.  */
518     return(NX_SUCCESS);
519 }
520 
521 /**************************************************************************/
522 /*                                                                        */
523 /*  FUNCTION                                               RELEASE        */
524 /*                                                                        */
525 /*    _nx_http_proxy_client_connect_response_process      PORTABLE C      */
526 /*                                                           6.2.0        */
527 /*  AUTHOR                                                                */
528 /*                                                                        */
529 /*    Wenhui Xie, Microsoft Corporation                                   */
530 /*                                                                        */
531 /*  DESCRIPTION                                                           */
532 /*                                                                        */
533 /*    This function processes the CONNECT response from HTTP Proxy server.*/
534 /*                                                                        */
535 /*                                                                        */
536 /*  INPUT                                                                 */
537 /*                                                                        */
538 /*    socket_ptr                            Pointer to TCP client socket  */
539 /*                                                                        */
540 /*  OUTPUT                                                                */
541 /*                                                                        */
542 /*    status                                Completion status             */
543 /*                                                                        */
544 /*  CALLS                                                                 */
545 /*                                                                        */
546 /*    _nx_tcp_socket_receive                Receive TCP socket            */
547 /*    _nx_tcp_socket_disconnect             Disconnect TCP socket         */
548 /*    _nx_tcp_socket_thread_resume          Resume the suspended thread   */
549 /*    _nx_packet_data_append                Append packet data            */
550 /*    _nx_packet_release                    Release packet                */
551 /*                                                                        */
552 /*  CALLED BY                                                             */
553 /*                                                                        */
554 /*    _nx_tcp_socket_packet_process         Process socket packet         */
555 /*                                                                        */
556 /*  RELEASE HISTORY                                                       */
557 /*                                                                        */
558 /*    DATE              NAME                      DESCRIPTION             */
559 /*                                                                        */
560 /*  10-31-2022     Wenhui Xie               Initial Version 6.2.0         */
561 /*                                                                        */
562 /**************************************************************************/
_nx_http_proxy_client_connect_response_process(NX_TCP_SOCKET * socket_ptr)563 UINT _nx_http_proxy_client_connect_response_process(NX_TCP_SOCKET *socket_ptr)
564 {
565 NX_PACKET *head_packet_ptr = socket_ptr -> nx_tcp_socket_http_proxy_header_packet;
566 NX_PACKET *new_packet_ptr;
567 CHAR *buffer_ptr;
568 UINT status = NX_SUCCESS;
569 NX_PACKET *work_ptr;
570 UINT crlf_found = 0;
571 NX_PACKET *tmp_ptr;
572 NX_IP *ip_ptr = socket_ptr -> nx_tcp_socket_ip_ptr;
573 NX_PACKET_POOL *pool_ptr = ip_ptr -> nx_ip_default_packet_pool;
574 
575 
576     if (head_packet_ptr == NX_NULL)
577     {
578 
579         /* Wait for a response from HTTP proxy.  */
580         status = _nx_tcp_socket_receive(socket_ptr, &head_packet_ptr, NX_NO_WAIT);
581 
582         /* Check the return status.  */
583         if (status == NX_NO_PACKET)
584         {
585             return(NX_IN_PROGRESS);
586         }
587         else if (status != NX_SUCCESS)
588         {
589 
590             /* Return an error condition.  */
591             _nx_tcp_socket_disconnect(socket_ptr, NX_NO_WAIT);
592             return(status);
593         }
594 
595         socket_ptr -> nx_tcp_socket_http_proxy_header_packet = head_packet_ptr;
596     }
597 
598     crlf_found = 0;
599     work_ptr = head_packet_ptr;
600 
601     /* Build a pointer to the buffer area.  */
602     buffer_ptr =  (CHAR *) work_ptr -> nx_packet_prepend_ptr;
603 
604     do
605     {
606 
607         /* See if there is a blank line present in the buffer.  */
608         /* Search the buffer for a cr/lf pair.  */
609         while ((buffer_ptr < (CHAR *) work_ptr -> nx_packet_append_ptr) &&
610                (crlf_found < 4))
611         {
612             if (!(crlf_found & 1) && (*buffer_ptr == (CHAR)13))
613             {
614 
615                 /* Found CR.  */
616                 crlf_found++;
617             }
618             else if((crlf_found & 1) && (*buffer_ptr == (CHAR)10))
619             {
620 
621                 /* Found LF.  */
622                 crlf_found++;
623             }
624             else
625             {
626 
627                 /* Reset the CRLF marker.  */
628                 crlf_found = 0;
629             }
630 
631             /* Move the buffer pointer up.  */
632             buffer_ptr++;
633         }
634 
635         if (crlf_found == 4)
636         {
637 
638             /* Yes, we have found the end of the HTTP response header.  */
639             break;
640         }
641 
642         /* Determine if the packet has already overflowed into another packet.  */
643 
644 #ifndef NX_DISABLE_PACKET_CHAIN
645 
646         if (work_ptr -> nx_packet_next != NX_NULL)
647         {
648 
649             /* Get the next packet in the chain.  */
650             work_ptr  = work_ptr -> nx_packet_next;
651             buffer_ptr =  (CHAR *) work_ptr -> nx_packet_prepend_ptr;
652         }
653         else
654 #endif
655         {
656             /* Receive another packet from the HTTP proxy.  */
657             status = _nx_tcp_socket_receive(socket_ptr, &new_packet_ptr, NX_NO_WAIT);
658 
659             /* Check the return status.  */
660             if (status == NX_NO_PACKET)
661             {
662                 return(NX_IN_PROGRESS);
663             }
664             else if (status != NX_SUCCESS)
665             {
666                 break;
667             }
668 
669             /* Successfully received another packet. Its contents now need to be placed in the head packet.  */
670             tmp_ptr = new_packet_ptr;
671 
672 #ifndef NX_DISABLE_PACKET_CHAIN
673             while (tmp_ptr)
674 #endif /* NX_DISABLE_PACKET_CHAIN */
675             {
676 
677                 /* Copy the contents of the current packet into the head packet.  */
678                 status =  _nx_packet_data_append(head_packet_ptr, (VOID *) tmp_ptr -> nx_packet_prepend_ptr,
679                                                 (ULONG)(tmp_ptr -> nx_packet_append_ptr - tmp_ptr -> nx_packet_prepend_ptr),
680                                                 pool_ptr, NX_NO_WAIT);
681 
682 #ifndef NX_DISABLE_PACKET_CHAIN
683 
684                 /* Determine if an error occurred.  */
685                 if (status != NX_SUCCESS)
686                 {
687                     break;
688                 }
689                 else
690                 {
691                     tmp_ptr = tmp_ptr -> nx_packet_next;
692                 }
693 #endif /* NX_DISABLE_PACKET_CHAIN */
694             }
695 
696             /* Release the new packet.  */
697             _nx_packet_release(new_packet_ptr);
698         }
699 
700     } while (status == NX_SUCCESS);
701 
702     if (status)
703     {
704 
705         /* Return an error condition.  */
706         _nx_tcp_socket_disconnect(socket_ptr, NX_NO_WAIT);
707         return(status);
708     }
709 
710     /* Check the packet length and response code.  */
711     if ((head_packet_ptr -> nx_packet_append_ptr - head_packet_ptr -> nx_packet_prepend_ptr < 12) ||
712         (*(head_packet_ptr -> nx_packet_prepend_ptr + 9) != '2'))
713     {
714 
715         /* If error occurs, disconnect the TCP connection.  */
716         _nx_tcp_socket_disconnect(socket_ptr, NX_NO_WAIT);
717         return(NX_NOT_SUCCESSFUL);
718     }
719 
720     /* Update the HTTP Proxy state.  */
721     socket_ptr -> nx_tcp_socket_http_proxy_state = NX_HTTP_PROXY_STATE_CONNECTED;
722 
723     /* Release the packet.  */
724     _nx_packet_release(head_packet_ptr);
725     socket_ptr -> nx_tcp_socket_http_proxy_header_packet = NX_NULL;
726 
727 #ifndef NX_DISABLE_EXTENDED_NOTIFY_SUPPORT
728 
729     /* Is a connection completion callback registered with the TCP socket?  */
730     if (socket_ptr -> nx_tcp_establish_notify)
731     {
732 
733         /* Call the application's establish callback function.  */
734         (socket_ptr -> nx_tcp_establish_notify)(socket_ptr);
735     }
736 #endif /* NX_DISABLE_EXTENDED_NOTIFY_SUPPORT */
737 
738     /* Determine if we need to wake a thread suspended on the connection.  */
739     if (socket_ptr -> nx_tcp_socket_connect_suspended_thread)
740     {
741 
742         /* Resume the suspended thread.  */
743         _nx_tcp_socket_thread_resume(&(socket_ptr -> nx_tcp_socket_connect_suspended_thread), NX_SUCCESS);
744     }
745 
746     /* Return status.  */
747     return(NX_SUCCESS);
748 }
749 
750 /**************************************************************************/
751 /*                                                                        */
752 /*  FUNCTION                                               RELEASE        */
753 /*                                                                        */
754 /*    _nx_http_proxy_client_cleanup                       PORTABLE C      */
755 /*                                                           6.2.0        */
756 /*  AUTHOR                                                                */
757 /*                                                                        */
758 /*    Wenhui Xie, Microsoft Corporation                                   */
759 /*                                                                        */
760 /*  DESCRIPTION                                                           */
761 /*                                                                        */
762 /*    This function cleans up the HTTP Proxy by resetting the state and   */
763 /*    release the processing packet.                                      */
764 /*                                                                        */
765 /*                                                                        */
766 /*  INPUT                                                                 */
767 /*                                                                        */
768 /*    socket_ptr                            Pointer to TCP client socket  */
769 /*                                                                        */
770 /*  OUTPUT                                                                */
771 /*                                                                        */
772 /*    status                                Completion status             */
773 /*                                                                        */
774 /*  CALLS                                                                 */
775 /*                                                                        */
776 /*    _nx_packet_release                    Release packet                */
777 /*                                                                        */
778 /*  CALLED BY                                                             */
779 /*                                                                        */
780 /*    _nx_tcp_socket_block_cleanup          Clean up the socket block     */
781 /*                                                                        */
782 /*  RELEASE HISTORY                                                       */
783 /*                                                                        */
784 /*    DATE              NAME                      DESCRIPTION             */
785 /*                                                                        */
786 /*  10-31-2022     Wenhui Xie               Initial Version 6.2.0         */
787 /*                                                                        */
788 /**************************************************************************/
_nx_http_proxy_client_cleanup(NX_TCP_SOCKET * socket_ptr)789 VOID _nx_http_proxy_client_cleanup(NX_TCP_SOCKET *socket_ptr)
790 {
791 
792     /* Clear the HTTP Proxy connection state.  */
793     socket_ptr -> nx_tcp_socket_http_proxy_state = NX_HTTP_PROXY_STATE_INIT;
794 
795     /* Release HTTP Proxy header packet.  */
796     if (socket_ptr -> nx_tcp_socket_http_proxy_header_packet)
797     {
798         _nx_packet_release(socket_ptr -> nx_tcp_socket_http_proxy_header_packet);
799         socket_ptr -> nx_tcp_socket_http_proxy_header_packet = NX_NULL;
800     }
801 }
802 #endif /* NX_ENABLE_HTTP_PROXY */