Fossil SCM

When handling HTTPS urls, open a socket and then upgrade the socket to use TLS. See discussion starting with [forum:/forumpost/3726ae4219|forum post 3726ae4219].

andybradford 2025-12-20 23:46 trunk
Commit 61b3f488a6f045f2ff1ef19eae990280e43bd4f0ec8f656690154490fc1dbc43
2 files changed +8 +29 -99
--- src/http_socket.c
+++ src/http_socket.c
@@ -87,10 +87,18 @@
8787
char *socket_errmsg(void){
8888
char *zResult = socketErrMsg;
8989
socketErrMsg = 0;
9090
return zResult;
9191
}
92
+
93
+/*
94
+** Return the socket to the caller.
95
+** This can be used when setting up SSL on the socket.
96
+*/
97
+int get_socket(){
98
+ return iSocket;
99
+}
92100
93101
/*
94102
** Call this routine once before any other use of the socket interface.
95103
** This routine does initial configuration of the socket module.
96104
*/
97105
--- src/http_socket.c
+++ src/http_socket.c
@@ -87,10 +87,18 @@
87 char *socket_errmsg(void){
88 char *zResult = socketErrMsg;
89 socketErrMsg = 0;
90 return zResult;
91 }
 
 
 
 
 
 
 
 
92
93 /*
94 ** Call this routine once before any other use of the socket interface.
95 ** This routine does initial configuration of the socket module.
96 */
97
--- src/http_socket.c
+++ src/http_socket.c
@@ -87,10 +87,18 @@
87 char *socket_errmsg(void){
88 char *zResult = socketErrMsg;
89 socketErrMsg = 0;
90 return zResult;
91 }
92
93 /*
94 ** Return the socket to the caller.
95 ** This can be used when setting up SSL on the socket.
96 */
97 int get_socket(){
98 return iSocket;
99 }
100
101 /*
102 ** Call this routine once before any other use of the socket interface.
103 ** This routine does initial configuration of the socket module.
104 */
105
+29 -99
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -35,10 +35,19 @@
3535
3636
#include <openssl/bio.h>
3737
#include <openssl/ssl.h>
3838
#include <openssl/err.h>
3939
#include <openssl/x509.h>
40
+#if defined(_WIN32)
41
+# include <winsock2.h>
42
+# include <ws2tcpip.h>
43
+#else
44
+# include <netinet/in.h>
45
+# include <arpa/inet.h>
46
+# include <sys/socket.h>
47
+# include <netdb.h>
48
+#endif
4049
4150
#include <assert.h>
4251
#include <sys/types.h>
4352
4453
/*
@@ -363,10 +372,11 @@
363372
if( sslIsInit ){
364373
SSL_CTX_free(sslCtx);
365374
ssl_clear_errmsg();
366375
sslIsInit = 0;
367376
}
377
+ socket_global_shutdown();
368378
}
369379
370380
/*
371381
** Close the currently open client SSL connection. If no connection is open,
372382
** this routine is a no-op.
@@ -375,10 +385,11 @@
375385
if( iBio!=NULL ){
376386
(void)BIO_reset(iBio);
377387
BIO_free_all(iBio);
378388
iBio = NULL;
379389
}
390
+ socket_close();
380391
}
381392
382393
/* See RFC2817 for details */
383394
static int establish_proxy_tunnel(UrlData *pUrlData, BIO *bio){
384395
int rc, httpVerMin;
@@ -450,63 +461,35 @@
450461
** Return the number of errors.
451462
*/
452463
int ssl_open_client(UrlData *pUrlData){
453464
X509 *cert;
454465
const char *zRemoteHost;
466
+ BIO *sBio;
455467
456468
ssl_global_init_client();
469
+ if( socket_open(pUrlData) ){
470
+ ssl_set_errmsg("SSL: cannot open socket (%s)", socket_errmsg());
471
+ return 1;
472
+ }
473
+ sBio = BIO_new_socket(get_socket(), 0);
457474
if( pUrlData->useProxy ){
458
- int rc;
459
- char *connStr = mprintf("%s:%d", g.url.name, pUrlData->port);
460
- BIO *sBio = BIO_new_connect(connStr);
461
- switch( g.eIPvers ){
462
- default: /* Any available protocol */
463
- break;
464
- case 1: /* IPv4 only */
465
-#ifdef BIO_FAMILY_IPV4
466
- BIO_set_conn_ip_family(sBio, BIO_FAMILY_IPV4);
467
-#else
468
- fossil_warning("The --ipv4 option is not supported in this build\n");
469
-#endif
470
- break;
471
- case 2: /* IPv6 only */
472
-#ifdef BIO_FAMILY_IPV6
473
- BIO_set_conn_ip_family(sBio, BIO_FAMILY_IPV6);
474
-#else
475
- fossil_warning("The --ipv6 option is not supported in this build\n");
476
-#endif
477
- break;
478
- }
479
- fossil_free(connStr);
480
- if( BIO_do_connect(sBio)<=0 ){
481
- ssl_set_errmsg("SSL: cannot connect to proxy %s:%d (%s)",
482
- pUrlData->name, pUrlData->port,
483
- ERR_reason_error_string(ERR_get_error()));
484
- ssl_close_client();
485
- return 1;
486
- }
487
- rc = establish_proxy_tunnel(pUrlData, sBio);
475
+ int rc = establish_proxy_tunnel(pUrlData, sBio);
488476
if( rc<200||rc>299 ){
489477
ssl_set_errmsg("SSL: proxy connect failed with HTTP status code %d", rc);
478
+ ssl_close_client();
490479
return 1;
491480
}
492481
493482
pUrlData->path = pUrlData->proxyUrlPath;
494
-
495
- iBio = BIO_new_ssl(sslCtx, 1);
496
- BIO_push(iBio, sBio);
497
- zRemoteHost = pUrlData->hostname;
498
- }else{
499
- iBio = BIO_new_ssl_connect(sslCtx);
500
- zRemoteHost = pUrlData->name;
501
- }
502
- if( iBio==NULL ) {
503
- ssl_set_errmsg("SSL: cannot open SSL (%s)",
504
- ERR_reason_error_string(ERR_get_error()));
505
- return 1;
506
- }
483
+ }
484
+ iBio = BIO_new_ssl(sslCtx, 1);
485
+ BIO_push(iBio, sBio);
486
+ BIO_set_ssl(sBio, ssl, BIO_NOCLOSE);
487
+ BIO_set_ssl_mode(iBio, 1);
507488
BIO_get_ssl(iBio, &ssl);
489
+
490
+ zRemoteHost = pUrlData->useProxy ? pUrlData->hostname : pUrlData->name;
508491
509492
#if (SSLEAY_VERSION_NUMBER >= 0x00908070) && !defined(OPENSSL_NO_TLSEXT)
510493
if( !SSL_set_tlsext_host_name(ssl, zRemoteHost)){
511494
fossil_warning("WARNING: failed to set server name indication (SNI), "
512495
"continuing without it.\n");
@@ -523,45 +506,14 @@
523506
}
524507
/* SSL_set_verify(ssl, SSL_VERIFY_PEER, 0); */
525508
}
526509
#endif
527510
528
- if( !pUrlData->useProxy ){
529
- char *connStr = mprintf("%s:%d", pUrlData->name, pUrlData->port);
530
- BIO_set_conn_hostname(iBio, connStr);
531
- fossil_free(connStr);
532
- switch( g.eIPvers ){
533
- default: /* Any available protocol */
534
- break;
535
- case 1: /* IPv4 only */
536
-#ifdef BIO_FAMILY_IPV4
537
- BIO_set_conn_ip_family(iBio, BIO_FAMILY_IPV4);
538
-#else
539
- fossil_warning("The --ipv4 option is not supported in this build\n");
540
-#endif
541
- break;
542
- case 2: /* IPv6 only */
543
-#ifdef BIO_FAMILY_IPV6
544
- BIO_set_conn_ip_family(iBio, BIO_FAMILY_IPV6);
545
-#else
546
- fossil_warning("The --ipv6 option is not supported in this build\n");
547
-#endif
548
- break;
549
- }
550
- if( BIO_do_connect(iBio)<=0 ){
551
- ssl_set_errmsg("SSL: cannot connect to host %s:%d (%s)",
552
- pUrlData->name, pUrlData->port,
553
- ERR_reason_error_string(ERR_get_error()));
554
- ssl_close_client();
555
- return 1;
556
- }
557
- }
558
-
559
- if( BIO_do_handshake(iBio)<=0 ) {
511
+ if( BIO_do_handshake(iBio)<=0 ){
560512
ssl_set_errmsg("Error establishing SSL connection %s:%d (%s)",
561
- pUrlData->useProxy?pUrlData->hostname:pUrlData->name,
562
- pUrlData->useProxy?pUrlData->proxyOrigPort:pUrlData->port,
513
+ zRemoteHost,
514
+ pUrlData->useProxy ? pUrlData->proxyOrigPort : pUrlData->port,
563515
ERR_reason_error_string(ERR_get_error()));
564516
ssl_close_client();
565517
return 1;
566518
}
567519
/* Check if certificate is valid */
@@ -651,32 +603,10 @@
651603
}
652604
blob_reset(&ans);
653605
}
654606
}
655607
656
- /* Set the Global.zIpAddr variable to the server we are talking to.
657
- ** This is used to populate the ipaddr column of the rcvfrom table,
658
- ** if any files are received from the server.
659
- */
660
- {
661
- /* As soon as libressl implements
662
- ** BIO_ADDR_hostname_string/BIO_get_conn_address.
663
- ** check here for the correct LIBRESSL_VERSION_NUMBER too. For now: disable
664
- */
665
-#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L \
666
- && !defined(LIBRESSL_VERSION_NUMBER)
667
- char *ip = BIO_ADDR_hostname_string(BIO_get_conn_address(iBio),1);
668
- g.zIpAddr = fossil_strdup(ip);
669
- OPENSSL_free(ip);
670
-#else
671
- /* IPv4 only code */
672
- const unsigned char *ip;
673
- ip = (const unsigned char*)BIO_ptr_ctrl(iBio,BIO_C_GET_CONNECT,2);
674
- g.zIpAddr = mprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
675
-#endif
676
- }
677
-
678608
X509_free(cert);
679609
return 0;
680610
}
681611
682612
/*
683613
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -35,10 +35,19 @@
35
36 #include <openssl/bio.h>
37 #include <openssl/ssl.h>
38 #include <openssl/err.h>
39 #include <openssl/x509.h>
 
 
 
 
 
 
 
 
 
40
41 #include <assert.h>
42 #include <sys/types.h>
43
44 /*
@@ -363,10 +372,11 @@
363 if( sslIsInit ){
364 SSL_CTX_free(sslCtx);
365 ssl_clear_errmsg();
366 sslIsInit = 0;
367 }
 
368 }
369
370 /*
371 ** Close the currently open client SSL connection. If no connection is open,
372 ** this routine is a no-op.
@@ -375,10 +385,11 @@
375 if( iBio!=NULL ){
376 (void)BIO_reset(iBio);
377 BIO_free_all(iBio);
378 iBio = NULL;
379 }
 
380 }
381
382 /* See RFC2817 for details */
383 static int establish_proxy_tunnel(UrlData *pUrlData, BIO *bio){
384 int rc, httpVerMin;
@@ -450,63 +461,35 @@
450 ** Return the number of errors.
451 */
452 int ssl_open_client(UrlData *pUrlData){
453 X509 *cert;
454 const char *zRemoteHost;
 
455
456 ssl_global_init_client();
 
 
 
 
 
457 if( pUrlData->useProxy ){
458 int rc;
459 char *connStr = mprintf("%s:%d", g.url.name, pUrlData->port);
460 BIO *sBio = BIO_new_connect(connStr);
461 switch( g.eIPvers ){
462 default: /* Any available protocol */
463 break;
464 case 1: /* IPv4 only */
465 #ifdef BIO_FAMILY_IPV4
466 BIO_set_conn_ip_family(sBio, BIO_FAMILY_IPV4);
467 #else
468 fossil_warning("The --ipv4 option is not supported in this build\n");
469 #endif
470 break;
471 case 2: /* IPv6 only */
472 #ifdef BIO_FAMILY_IPV6
473 BIO_set_conn_ip_family(sBio, BIO_FAMILY_IPV6);
474 #else
475 fossil_warning("The --ipv6 option is not supported in this build\n");
476 #endif
477 break;
478 }
479 fossil_free(connStr);
480 if( BIO_do_connect(sBio)<=0 ){
481 ssl_set_errmsg("SSL: cannot connect to proxy %s:%d (%s)",
482 pUrlData->name, pUrlData->port,
483 ERR_reason_error_string(ERR_get_error()));
484 ssl_close_client();
485 return 1;
486 }
487 rc = establish_proxy_tunnel(pUrlData, sBio);
488 if( rc<200||rc>299 ){
489 ssl_set_errmsg("SSL: proxy connect failed with HTTP status code %d", rc);
 
490 return 1;
491 }
492
493 pUrlData->path = pUrlData->proxyUrlPath;
494
495 iBio = BIO_new_ssl(sslCtx, 1);
496 BIO_push(iBio, sBio);
497 zRemoteHost = pUrlData->hostname;
498 }else{
499 iBio = BIO_new_ssl_connect(sslCtx);
500 zRemoteHost = pUrlData->name;
501 }
502 if( iBio==NULL ) {
503 ssl_set_errmsg("SSL: cannot open SSL (%s)",
504 ERR_reason_error_string(ERR_get_error()));
505 return 1;
506 }
507 BIO_get_ssl(iBio, &ssl);
 
 
508
509 #if (SSLEAY_VERSION_NUMBER >= 0x00908070) && !defined(OPENSSL_NO_TLSEXT)
510 if( !SSL_set_tlsext_host_name(ssl, zRemoteHost)){
511 fossil_warning("WARNING: failed to set server name indication (SNI), "
512 "continuing without it.\n");
@@ -523,45 +506,14 @@
523 }
524 /* SSL_set_verify(ssl, SSL_VERIFY_PEER, 0); */
525 }
526 #endif
527
528 if( !pUrlData->useProxy ){
529 char *connStr = mprintf("%s:%d", pUrlData->name, pUrlData->port);
530 BIO_set_conn_hostname(iBio, connStr);
531 fossil_free(connStr);
532 switch( g.eIPvers ){
533 default: /* Any available protocol */
534 break;
535 case 1: /* IPv4 only */
536 #ifdef BIO_FAMILY_IPV4
537 BIO_set_conn_ip_family(iBio, BIO_FAMILY_IPV4);
538 #else
539 fossil_warning("The --ipv4 option is not supported in this build\n");
540 #endif
541 break;
542 case 2: /* IPv6 only */
543 #ifdef BIO_FAMILY_IPV6
544 BIO_set_conn_ip_family(iBio, BIO_FAMILY_IPV6);
545 #else
546 fossil_warning("The --ipv6 option is not supported in this build\n");
547 #endif
548 break;
549 }
550 if( BIO_do_connect(iBio)<=0 ){
551 ssl_set_errmsg("SSL: cannot connect to host %s:%d (%s)",
552 pUrlData->name, pUrlData->port,
553 ERR_reason_error_string(ERR_get_error()));
554 ssl_close_client();
555 return 1;
556 }
557 }
558
559 if( BIO_do_handshake(iBio)<=0 ) {
560 ssl_set_errmsg("Error establishing SSL connection %s:%d (%s)",
561 pUrlData->useProxy?pUrlData->hostname:pUrlData->name,
562 pUrlData->useProxy?pUrlData->proxyOrigPort:pUrlData->port,
563 ERR_reason_error_string(ERR_get_error()));
564 ssl_close_client();
565 return 1;
566 }
567 /* Check if certificate is valid */
@@ -651,32 +603,10 @@
651 }
652 blob_reset(&ans);
653 }
654 }
655
656 /* Set the Global.zIpAddr variable to the server we are talking to.
657 ** This is used to populate the ipaddr column of the rcvfrom table,
658 ** if any files are received from the server.
659 */
660 {
661 /* As soon as libressl implements
662 ** BIO_ADDR_hostname_string/BIO_get_conn_address.
663 ** check here for the correct LIBRESSL_VERSION_NUMBER too. For now: disable
664 */
665 #if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L \
666 && !defined(LIBRESSL_VERSION_NUMBER)
667 char *ip = BIO_ADDR_hostname_string(BIO_get_conn_address(iBio),1);
668 g.zIpAddr = fossil_strdup(ip);
669 OPENSSL_free(ip);
670 #else
671 /* IPv4 only code */
672 const unsigned char *ip;
673 ip = (const unsigned char*)BIO_ptr_ctrl(iBio,BIO_C_GET_CONNECT,2);
674 g.zIpAddr = mprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
675 #endif
676 }
677
678 X509_free(cert);
679 return 0;
680 }
681
682 /*
683
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -35,10 +35,19 @@
35
36 #include <openssl/bio.h>
37 #include <openssl/ssl.h>
38 #include <openssl/err.h>
39 #include <openssl/x509.h>
40 #if defined(_WIN32)
41 # include <winsock2.h>
42 # include <ws2tcpip.h>
43 #else
44 # include <netinet/in.h>
45 # include <arpa/inet.h>
46 # include <sys/socket.h>
47 # include <netdb.h>
48 #endif
49
50 #include <assert.h>
51 #include <sys/types.h>
52
53 /*
@@ -363,10 +372,11 @@
372 if( sslIsInit ){
373 SSL_CTX_free(sslCtx);
374 ssl_clear_errmsg();
375 sslIsInit = 0;
376 }
377 socket_global_shutdown();
378 }
379
380 /*
381 ** Close the currently open client SSL connection. If no connection is open,
382 ** this routine is a no-op.
@@ -375,10 +385,11 @@
385 if( iBio!=NULL ){
386 (void)BIO_reset(iBio);
387 BIO_free_all(iBio);
388 iBio = NULL;
389 }
390 socket_close();
391 }
392
393 /* See RFC2817 for details */
394 static int establish_proxy_tunnel(UrlData *pUrlData, BIO *bio){
395 int rc, httpVerMin;
@@ -450,63 +461,35 @@
461 ** Return the number of errors.
462 */
463 int ssl_open_client(UrlData *pUrlData){
464 X509 *cert;
465 const char *zRemoteHost;
466 BIO *sBio;
467
468 ssl_global_init_client();
469 if( socket_open(pUrlData) ){
470 ssl_set_errmsg("SSL: cannot open socket (%s)", socket_errmsg());
471 return 1;
472 }
473 sBio = BIO_new_socket(get_socket(), 0);
474 if( pUrlData->useProxy ){
475 int rc = establish_proxy_tunnel(pUrlData, sBio);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
476 if( rc<200||rc>299 ){
477 ssl_set_errmsg("SSL: proxy connect failed with HTTP status code %d", rc);
478 ssl_close_client();
479 return 1;
480 }
481
482 pUrlData->path = pUrlData->proxyUrlPath;
483 }
484 iBio = BIO_new_ssl(sslCtx, 1);
485 BIO_push(iBio, sBio);
486 BIO_set_ssl(sBio, ssl, BIO_NOCLOSE);
487 BIO_set_ssl_mode(iBio, 1);
 
 
 
 
 
 
 
 
488 BIO_get_ssl(iBio, &ssl);
489
490 zRemoteHost = pUrlData->useProxy ? pUrlData->hostname : pUrlData->name;
491
492 #if (SSLEAY_VERSION_NUMBER >= 0x00908070) && !defined(OPENSSL_NO_TLSEXT)
493 if( !SSL_set_tlsext_host_name(ssl, zRemoteHost)){
494 fossil_warning("WARNING: failed to set server name indication (SNI), "
495 "continuing without it.\n");
@@ -523,45 +506,14 @@
506 }
507 /* SSL_set_verify(ssl, SSL_VERIFY_PEER, 0); */
508 }
509 #endif
510
511 if( BIO_do_handshake(iBio)<=0 ){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
512 ssl_set_errmsg("Error establishing SSL connection %s:%d (%s)",
513 zRemoteHost,
514 pUrlData->useProxy ? pUrlData->proxyOrigPort : pUrlData->port,
515 ERR_reason_error_string(ERR_get_error()));
516 ssl_close_client();
517 return 1;
518 }
519 /* Check if certificate is valid */
@@ -651,32 +603,10 @@
603 }
604 blob_reset(&ans);
605 }
606 }
607
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
608 X509_free(cert);
609 return 0;
610 }
611
612 /*
613

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button