Fossil SCM

Strip trailing dots on hostnames, which are valid hostnames but not accepted as TLS or certificate hostnames. from libfossil.

danshearer 2026-10-12 06:53 UTC trunk
Commit 6362cc0666eaa536b0233be3c23990268eac9fe092e5502bc28f0dafa3dbd2ec
1 file changed +20 -6
+20 -6
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -495,10 +495,12 @@
495495
** Return the number of errors.
496496
*/
497497
int ssl_open_client(UrlData *pUrlData){
498498
X509 *cert;
499499
const char *zRemoteHost;
500
+ const char *zTlsName; /* zRemoteHost needed by the TLS layer */
501
+ char zDotless[256]; /* zRemoteHost without a trailing dot */
500502
int isIpAddr; /* True if zRemoteHost is an IP address */
501503
BIO *sBio;
502504
503505
ssl_global_init_client();
504506
if( socket_open(pUrlData) ){
@@ -521,15 +523,27 @@
521523
BIO_set_ssl(sBio, ssl, BIO_NOCLOSE);
522524
BIO_set_ssl_mode(iBio, 1);
523525
BIO_get_ssl(iBio, &ssl);
524526
525527
zRemoteHost = ssl_server_name(pUrlData);
526
- isIpAddr = ssl_host_is_ip_address(zRemoteHost);
528
+ /* A fully qualified name may end with a dot, as in "example.com.".
529
+ ** The RFC 6066 TLS server name and all certificate names are
530
+ ** dotless */
531
+ zTlsName = zRemoteHost;
532
+ {
533
+ size_t n = strlen(zRemoteHost);
534
+ if( n>1 && zRemoteHost[n-1]=='.' && n<sizeof(zDotless) ){
535
+ memcpy(zDotless, zRemoteHost, n-1);
536
+ zDotless[n-1] = 0;
537
+ zTlsName = zDotless;
538
+ }
539
+ }
540
+ isIpAddr = ssl_host_is_ip_address(zTlsName);
527541
528542
#if (SSLEAY_VERSION_NUMBER >= 0x00908070) && !defined(OPENSSL_NO_TLSEXT)
529
- if( !isIpAddr && !ssl_host_is_non_ascii(zRemoteHost)
530
- && !SSL_set_tlsext_host_name(ssl, zRemoteHost)
543
+ if( !isIpAddr && !ssl_host_is_non_ascii(zTlsName)
544
+ && !SSL_set_tlsext_host_name(ssl, zTlsName)
531545
){
532546
fossil_warning("WARNING: failed to set server name indication (SNI), "
533547
"continuing without it.\n");
534548
}
535549
#endif
@@ -538,15 +552,15 @@
538552
#if OPENSSL_VERSION_NUMBER >= 0x010002000
539553
if( !sslNoCertVerify ){
540554
X509_VERIFY_PARAM *param = 0;
541555
param = SSL_get0_param(ssl);
542556
if( isIpAddr ){
543
- if( !X509_VERIFY_PARAM_set1_ip_asc(param, zRemoteHost) ){
557
+ if( !X509_VERIFY_PARAM_set1_ip_asc(param, zTlsName) ){
544558
fossil_fatal("failed to set IP address.");
545559
}
546
- }else if( !X509_VERIFY_PARAM_set1_host(param, zRemoteHost,
547
- strlen(zRemoteHost)) ){
560
+ }else if( !X509_VERIFY_PARAM_set1_host(param, zTlsName,
561
+ strlen(zTlsName)) ){
548562
fossil_fatal("failed to set hostname.");
549563
}
550564
/* SSL_set_verify(ssl, SSL_VERIFY_PEER, 0); */
551565
}
552566
#endif
553567
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -495,10 +495,12 @@
495 ** Return the number of errors.
496 */
497 int ssl_open_client(UrlData *pUrlData){
498 X509 *cert;
499 const char *zRemoteHost;
 
 
500 int isIpAddr; /* True if zRemoteHost is an IP address */
501 BIO *sBio;
502
503 ssl_global_init_client();
504 if( socket_open(pUrlData) ){
@@ -521,15 +523,27 @@
521 BIO_set_ssl(sBio, ssl, BIO_NOCLOSE);
522 BIO_set_ssl_mode(iBio, 1);
523 BIO_get_ssl(iBio, &ssl);
524
525 zRemoteHost = ssl_server_name(pUrlData);
526 isIpAddr = ssl_host_is_ip_address(zRemoteHost);
 
 
 
 
 
 
 
 
 
 
 
 
527
528 #if (SSLEAY_VERSION_NUMBER >= 0x00908070) && !defined(OPENSSL_NO_TLSEXT)
529 if( !isIpAddr && !ssl_host_is_non_ascii(zRemoteHost)
530 && !SSL_set_tlsext_host_name(ssl, zRemoteHost)
531 ){
532 fossil_warning("WARNING: failed to set server name indication (SNI), "
533 "continuing without it.\n");
534 }
535 #endif
@@ -538,15 +552,15 @@
538 #if OPENSSL_VERSION_NUMBER >= 0x010002000
539 if( !sslNoCertVerify ){
540 X509_VERIFY_PARAM *param = 0;
541 param = SSL_get0_param(ssl);
542 if( isIpAddr ){
543 if( !X509_VERIFY_PARAM_set1_ip_asc(param, zRemoteHost) ){
544 fossil_fatal("failed to set IP address.");
545 }
546 }else if( !X509_VERIFY_PARAM_set1_host(param, zRemoteHost,
547 strlen(zRemoteHost)) ){
548 fossil_fatal("failed to set hostname.");
549 }
550 /* SSL_set_verify(ssl, SSL_VERIFY_PEER, 0); */
551 }
552 #endif
553
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -495,10 +495,12 @@
495 ** Return the number of errors.
496 */
497 int ssl_open_client(UrlData *pUrlData){
498 X509 *cert;
499 const char *zRemoteHost;
500 const char *zTlsName; /* zRemoteHost needed by the TLS layer */
501 char zDotless[256]; /* zRemoteHost without a trailing dot */
502 int isIpAddr; /* True if zRemoteHost is an IP address */
503 BIO *sBio;
504
505 ssl_global_init_client();
506 if( socket_open(pUrlData) ){
@@ -521,15 +523,27 @@
523 BIO_set_ssl(sBio, ssl, BIO_NOCLOSE);
524 BIO_set_ssl_mode(iBio, 1);
525 BIO_get_ssl(iBio, &ssl);
526
527 zRemoteHost = ssl_server_name(pUrlData);
528 /* A fully qualified name may end with a dot, as in "example.com.".
529 ** The RFC 6066 TLS server name and all certificate names are
530 ** dotless */
531 zTlsName = zRemoteHost;
532 {
533 size_t n = strlen(zRemoteHost);
534 if( n>1 && zRemoteHost[n-1]=='.' && n<sizeof(zDotless) ){
535 memcpy(zDotless, zRemoteHost, n-1);
536 zDotless[n-1] = 0;
537 zTlsName = zDotless;
538 }
539 }
540 isIpAddr = ssl_host_is_ip_address(zTlsName);
541
542 #if (SSLEAY_VERSION_NUMBER >= 0x00908070) && !defined(OPENSSL_NO_TLSEXT)
543 if( !isIpAddr && !ssl_host_is_non_ascii(zTlsName)
544 && !SSL_set_tlsext_host_name(ssl, zTlsName)
545 ){
546 fossil_warning("WARNING: failed to set server name indication (SNI), "
547 "continuing without it.\n");
548 }
549 #endif
@@ -538,15 +552,15 @@
552 #if OPENSSL_VERSION_NUMBER >= 0x010002000
553 if( !sslNoCertVerify ){
554 X509_VERIFY_PARAM *param = 0;
555 param = SSL_get0_param(ssl);
556 if( isIpAddr ){
557 if( !X509_VERIFY_PARAM_set1_ip_asc(param, zTlsName) ){
558 fossil_fatal("failed to set IP address.");
559 }
560 }else if( !X509_VERIFY_PARAM_set1_host(param, zTlsName,
561 strlen(zTlsName)) ){
562 fossil_fatal("failed to set hostname.");
563 }
564 /* SSL_set_verify(ssl, SSL_VERIFY_PEER, 0); */
565 }
566 #endif
567

Keyboard Shortcuts

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