1313#include <ggl/socket.h>
1414#include <netdb.h>
1515#include <openssl/bio.h>
16+ #include <openssl/crypto.h>
1617#include <openssl/err.h>
18+ #include <openssl/http.h>
1719#include <openssl/opensslv.h>
1820#include <openssl/prov_ssl.h>
1921#include <openssl/ssl.h>
@@ -222,6 +224,53 @@ static void cleanup_ssl(SSL **ssl) {
222224 }
223225}
224226
227+ static GglError parse_proxy_url (
228+ const char * proxy_url , char * * host , char * * port
229+ ) {
230+ int use_ssl = 0 ;
231+
232+ if (!OSSL_HTTP_parse_url (
233+ proxy_url , & use_ssl , NULL , host , port , NULL , NULL , NULL , NULL
234+ )) {
235+ GGL_LOGE ("Failed to parse proxy URL." );
236+ ERR_print_errors_cb (openssl_err_cb , NULL );
237+ return GGL_ERR_INVALID ;
238+ }
239+
240+ if (use_ssl ) {
241+ GGL_LOGE ("HTTPS proxies are not supported in this task." );
242+ return GGL_ERR_INVALID ;
243+ }
244+
245+ return GGL_ERR_OK ;
246+ }
247+
248+ static GglError http_proxy_connect (
249+ BIO * proxy_bio , const char * target_host , const char * target_port
250+ ) {
251+ GGL_LOGD ("Sending HTTP CONNECT %s:%s to proxy." , target_host , target_port );
252+
253+ int proxy_connect_ret = OSSL_HTTP_proxy_connect (
254+ proxy_bio ,
255+ target_host ,
256+ target_port ,
257+ NULL , // proxy_user
258+ NULL , // proxy_password
259+ 60 , // timeout
260+ NULL , // bio_err
261+ NULL // prog
262+ );
263+
264+ if (proxy_connect_ret != 1 ) {
265+ GGL_LOGE ("Failed HTTP proxy CONNECT." );
266+ ERR_print_errors_cb (openssl_err_cb , NULL );
267+ return GGL_ERR_FAILURE ;
268+ }
269+
270+ GGL_LOGD ("HTTP proxy CONNECT successful." );
271+ return GGL_ERR_OK ;
272+ }
273+
225274static GglError tls_handshake (const char * endpoint , BIO * bio , SSL * * ssl ) {
226275 SSL_CTX * ssl_ctx = SSL_CTX_new (TLS_client_method ());
227276 if (ssl_ctx == NULL ) {
@@ -381,8 +430,26 @@ int main(int argc, char *argv[]) {
381430 // NOLINTNEXTLINE(concurrency-mt-unsafe)
382431 argp_parse (& argp , argc , argv , 0 , 0 , NULL );
383432
433+ GglError ret ;
384434 int tcp_fd ;
385- GglError ret = create_tcp_connection (arg_endpoint , arg_port , & tcp_fd );
435+ bool using_proxy = false;
436+
437+ if (arg_proxy != NULL ) {
438+ char * parse_host ;
439+ char * parse_port ;
440+ ret = parse_proxy_url (arg_proxy , & parse_host , & parse_port );
441+ if (ret != GGL_ERR_OK ) {
442+ return 1 ;
443+ }
444+ using_proxy = true;
445+ const char * port = (parse_port != NULL ) ? parse_port : "80" ;
446+ ret = create_tcp_connection (parse_host , port , & tcp_fd );
447+
448+ OPENSSL_free (parse_host );
449+ OPENSSL_free (parse_port );
450+ } else {
451+ ret = create_tcp_connection (arg_endpoint , arg_port , & tcp_fd );
452+ }
386453 if (ret != GGL_ERR_OK ) {
387454 GGL_LOGE ("Failed to create TCP connection." );
388455 return 1 ;
@@ -395,6 +462,13 @@ int main(int argc, char *argv[]) {
395462 return 1 ;
396463 }
397464
465+ if (using_proxy ) {
466+ ret = http_proxy_connect (bio , arg_endpoint , arg_port );
467+ if (ret != GGL_ERR_OK ) {
468+ return 1 ;
469+ }
470+ }
471+
398472 SSL * ssl = NULL ;
399473 ret = tls_handshake (arg_endpoint , bio , & ssl );
400474 if (ret != GGL_ERR_OK ) {
@@ -430,14 +504,14 @@ int main(int argc, char *argv[]) {
430504 return 0 ;
431505 }
432506
433- GGL_LOGD ("Preparing to proxy socket traffic." );
507+ GGL_LOGD ("Preparing to relay socket traffic." );
434508
435509 // Close the parent's end of the socketpair
436510 (void ) close (parent_fds [0 ]);
437- int proxy_fd = parent_fds [1 ];
511+ int relay_fd = parent_fds [1 ];
438512
439- // Proxy data between socketpair and TLS connection
440- struct pollfd fds [2 ] = { { .fd = proxy_fd , .events = POLLIN },
513+ // Relay data between socketpair and TLS connection
514+ struct pollfd fds [2 ] = { { .fd = relay_fd , .events = POLLIN },
441515 { .fd = tcp_fd , .events = POLLIN } };
442516
443517 uint8_t buffer [4096 ];
@@ -449,15 +523,15 @@ int main(int argc, char *argv[]) {
449523 return 1 ;
450524 }
451525
452- // Data from proxy socket to TLS
526+ // Data from relay socket to TLS
453527 if (fds [0 ].revents & POLLIN ) {
454528 GglBuffer buf = GGL_BUF (buffer );
455529 do {
456- ret = ggl_file_read_partial (proxy_fd , & buf );
530+ ret = ggl_file_read_partial (relay_fd , & buf );
457531 } while (ret == GGL_ERR_RETRY );
458532
459533 if (ret == GGL_ERR_NODATA ) {
460- GGL_LOGD ("Proxy socket closed." );
534+ GGL_LOGD ("Relay socket closed." );
461535 int shutdown_ret = SSL_shutdown (ssl );
462536 if (shutdown_ret < 0 ) {
463537 GGL_LOGE ("Openssl shutdown on network socket failed." );
@@ -466,7 +540,7 @@ int main(int argc, char *argv[]) {
466540 (void ) shutdown (tcp_fd , SHUT_WR );
467541 fds [0 ].fd = -1 ;
468542 } else if (ret != GGL_ERR_OK ) {
469- GGL_LOGE ("Proxy socket read error." );
543+ GGL_LOGE ("Relay socket read error." );
470544 return 1 ;
471545 } else {
472546 size_t bytes_read = sizeof (buffer ) - buf .len ;
@@ -488,13 +562,13 @@ int main(int argc, char *argv[]) {
488562 }
489563 }
490564
491- // Handle proxy socket errors
565+ // Handle relay socket errors
492566 if (fds [0 ].revents & (POLLHUP | POLLERR )) {
493- GGL_LOGD ("Proxy socket closed uncleanly." );
567+ GGL_LOGD ("Relay socket closed uncleanly." );
494568 fds [0 ].fd = -1 ;
495569 }
496570
497- // Data from TLS to proxy socket
571+ // Data from TLS to relay socket
498572 if (fds [1 ].revents & POLLIN ) {
499573 int bytes = SSL_read (ssl , buffer , sizeof (buffer ));
500574 if (bytes <= 0 ) {
@@ -524,16 +598,16 @@ int main(int argc, char *argv[]) {
524598 return 1 ;
525599 }
526600
527- (void ) shutdown (proxy_fd , SHUT_WR );
601+ (void ) shutdown (relay_fd , SHUT_WR );
528602 fds [1 ].fd = -1 ;
529603 } else {
530604 GglBuffer buf = { .data = buffer , .len = (size_t ) bytes };
531- ret = ggl_socket_write (proxy_fd , buf );
605+ ret = ggl_socket_write (relay_fd , buf );
532606 if (ret == GGL_ERR_NOCONN ) {
533- GGL_LOGD ("Proxy socket closed by peer during write." );
607+ GGL_LOGD ("Relay socket closed by peer during write." );
534608 fds [1 ].fd = -1 ;
535609 } else if (ret != GGL_ERR_OK ) {
536- GGL_LOGE ("Proxy socket write error." );
610+ GGL_LOGE ("Relay socket write error." );
537611 return 1 ;
538612 }
539613 }
@@ -547,7 +621,7 @@ int main(int argc, char *argv[]) {
547621 }
548622
549623 close (tcp_fd );
550- close (proxy_fd );
624+ close (relay_fd );
551625
552626 GGL_LOGD ("TLS handling complete." );
553627}
0 commit comments