From e6d880ccd11b82d884f94e89e5187ddda922c41f Mon Sep 17 00:00:00 2001 From: Sudhir Emmadi Date: Fri, 1 Aug 2025 11:22:32 +0530 Subject: [PATCH 1/3] Http ssl options --- .../Apache/Hive2/HiveServer2TlsImpl.cs | 72 +++++++++++++------ 1 file changed, 49 insertions(+), 23 deletions(-) diff --git a/csharp/src/Drivers/Apache/Hive2/HiveServer2TlsImpl.cs b/csharp/src/Drivers/Apache/Hive2/HiveServer2TlsImpl.cs index 345974d77b..f1993c3d3a 100644 --- a/csharp/src/Drivers/Apache/Hive2/HiveServer2TlsImpl.cs +++ b/csharp/src/Drivers/Apache/Hive2/HiveServer2TlsImpl.cs @@ -65,11 +65,8 @@ static internal TlsProperties GetHttpTlsOptions(IReadOnlyDictionary { if (policyErrors == SslPolicyErrors.None || tlsProperties.DisableServerCertificateValidation) return true; + + if (certificate == null || !(certificate is X509Certificate2 cert2)) + return false; + + bool isNameMismatchError = policyErrors.HasFlag(SslPolicyErrors.RemoteCertificateNameMismatch) && !tlsProperties.AllowHostnameMismatch; + + if (isNameMismatchError) return false; + if (string.IsNullOrEmpty(tlsProperties.TrustedCertificatePath)) { - return - (!policyErrors.HasFlag(SslPolicyErrors.RemoteCertificateChainErrors) || tlsProperties.AllowSelfSigned) - && (!policyErrors.HasFlag(SslPolicyErrors.RemoteCertificateNameMismatch) || tlsProperties.AllowHostnameMismatch); + return !policyErrors.HasFlag(SslPolicyErrors.RemoteCertificateChainErrors)|| (tlsProperties.AllowSelfSigned && IsSelfSigned(cert2)); } - if (certificate == null) - return false; - X509Certificate2 customCertificate = new X509Certificate2(tlsProperties.TrustedCertificatePath); - X509Chain chain2 = new X509Chain(); - chain2.ChainPolicy.ExtraStore.Add(customCertificate); - - // "tell the X509Chain class that I do trust this root certs and it should check just the certs in the chain and nothing else" - chain2.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority; - // Build the chain and verify - return chain2.Build(certificate); + X509Certificate2 trustedRoot = new X509Certificate2(tlsProperties.TrustedCertificatePath); + X509Chain customChain = new X509Chain(); + customChain.ChainPolicy.ExtraStore.Add(trustedRoot); + // "tell the X509Chain class that I do trust this root certs and it should check just the certs in the chain and nothing else" + customChain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority; + customChain.ChainPolicy.RevocationMode = X509RevocationMode.Online; + + bool chainValid = customChain.Build(cert2); + + return chainValid || (tlsProperties.AllowSelfSigned && IsSelfSigned(cert2)); }; } proxyConfigurator.ConfigureProxy(httpClientHandler); @@ -105,6 +108,32 @@ static internal HttpClientHandler NewHttpClientHandler(TlsProperties tlsProperti return httpClientHandler; } + static private bool IsSelfSigned(X509Certificate2 cert) + { + return cert.Subject == cert.Issuer && IsSignedBy(cert, cert); + } + + static private bool IsSignedBy(X509Certificate2 cert, X509Certificate2 issuer) + { + try + { + using (var chain = new X509Chain()) + { + chain.ChainPolicy.ExtraStore.Add(issuer); + chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority; + chain.ChainPolicy.RevocationMode = X509RevocationMode.Online; + + return chain.Build(cert) + && chain.ChainElements.Count == 1 + && chain.ChainElements[0].Certificate.Thumbprint == issuer.Thumbprint; + } + } + catch + { + return false; + } + } + static internal TlsProperties GetStandardTlsOptions(IReadOnlyDictionary properties) { TlsProperties tlsProperties = new(); @@ -130,11 +159,8 @@ static internal TlsProperties GetStandardTlsOptions(IReadOnlyDictionary Date: Fri, 1 Aug 2025 15:41:55 +0530 Subject: [PATCH 2/3] Tls options --- .../Hive2/HiveServer2StandardConnection.cs | 3 +- .../Apache/Hive2/HiveServer2TlsImpl.cs | 68 ++++++++----------- .../Apache/Impala/ImpalaStandardConnection.cs | 6 +- .../Apache/Hive2/HiveServer2TlsImplTest.cs | 4 -- 4 files changed, 33 insertions(+), 48 deletions(-) diff --git a/csharp/src/Drivers/Apache/Hive2/HiveServer2StandardConnection.cs b/csharp/src/Drivers/Apache/Hive2/HiveServer2StandardConnection.cs index 66f175a147..4f89a39047 100644 --- a/csharp/src/Drivers/Apache/Hive2/HiveServer2StandardConnection.cs +++ b/csharp/src/Drivers/Apache/Hive2/HiveServer2StandardConnection.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; using System.Net; +using System.Net.Security; using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Tasks; @@ -115,7 +116,7 @@ protected override TTransport CreateTransport() ? new X509Certificate2(TlsOptions.TrustedCertificatePath!) : null; - var certValidator = HiveServer2TlsImpl.GetCertificateValidator(TlsOptions); + RemoteCertificateValidationCallback certValidator = (sender, cert, chain, errors) => HiveServer2TlsImpl.ValidateCertificate(cert, errors, TlsOptions); if (IPAddress.TryParse(hostName!, out var ipAddress)) { diff --git a/csharp/src/Drivers/Apache/Hive2/HiveServer2TlsImpl.cs b/csharp/src/Drivers/Apache/Hive2/HiveServer2TlsImpl.cs index f1993c3d3a..1abd9936c6 100644 --- a/csharp/src/Drivers/Apache/Hive2/HiveServer2TlsImpl.cs +++ b/csharp/src/Drivers/Apache/Hive2/HiveServer2TlsImpl.cs @@ -75,33 +75,7 @@ static internal HttpClientHandler NewHttpClientHandler(TlsProperties tlsProperti HttpClientHandler httpClientHandler = new(); if (tlsProperties.IsTlsEnabled) { - httpClientHandler.ServerCertificateCustomValidationCallback = (request, certificate, chain, policyErrors) => - { - if (policyErrors == SslPolicyErrors.None || tlsProperties.DisableServerCertificateValidation) return true; - - if (certificate == null || !(certificate is X509Certificate2 cert2)) - return false; - - bool isNameMismatchError = policyErrors.HasFlag(SslPolicyErrors.RemoteCertificateNameMismatch) && !tlsProperties.AllowHostnameMismatch; - - if (isNameMismatchError) return false; - - if (string.IsNullOrEmpty(tlsProperties.TrustedCertificatePath)) - { - return !policyErrors.HasFlag(SslPolicyErrors.RemoteCertificateChainErrors)|| (tlsProperties.AllowSelfSigned && IsSelfSigned(cert2)); - } - - X509Certificate2 trustedRoot = new X509Certificate2(tlsProperties.TrustedCertificatePath); - X509Chain customChain = new X509Chain(); - customChain.ChainPolicy.ExtraStore.Add(trustedRoot); - // "tell the X509Chain class that I do trust this root certs and it should check just the certs in the chain and nothing else" - customChain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority; - customChain.ChainPolicy.RevocationMode = X509RevocationMode.Online; - - bool chainValid = customChain.Build(cert2); - - return chainValid || (tlsProperties.AllowSelfSigned && IsSelfSigned(cert2)); - }; + httpClientHandler.ServerCertificateCustomValidationCallback = (request, cert, chain, errors) => ValidateCertificate(cert, errors, tlsProperties); } proxyConfigurator.ConfigureProxy(httpClientHandler); httpClientHandler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; @@ -164,20 +138,32 @@ static internal TlsProperties GetStandardTlsOptions(IReadOnlyDictionary - { - if (policyErrors == SslPolicyErrors.None || tlsProperties.DisableServerCertificateValidation) return true; - if (string.IsNullOrEmpty(tlsProperties.TrustedCertificatePath)) - { - return - (!policyErrors.HasFlag(SslPolicyErrors.RemoteCertificateChainErrors) || tlsProperties.AllowSelfSigned) - && (!policyErrors.HasFlag(SslPolicyErrors.RemoteCertificateNameMismatch) || tlsProperties.AllowHostnameMismatch); - } - - return false; - }; + static internal bool ValidateCertificate(X509Certificate? cert, SslPolicyErrors policyErrors, TlsProperties tlsProperties) + { + if (policyErrors == SslPolicyErrors.None || tlsProperties.DisableServerCertificateValidation) + return true; + + if (cert == null || !(cert is X509Certificate2 cert2)) + return false; + + bool isNameMismatchError = policyErrors.HasFlag(SslPolicyErrors.RemoteCertificateNameMismatch) && !tlsProperties.AllowHostnameMismatch; + + if (isNameMismatchError) return false; + + if (string.IsNullOrEmpty(tlsProperties.TrustedCertificatePath)) + { + return !policyErrors.HasFlag(SslPolicyErrors.RemoteCertificateChainErrors) || (tlsProperties.AllowSelfSigned && IsSelfSigned(cert2)); + } + + X509Certificate2 trustedRoot = new X509Certificate2(tlsProperties.TrustedCertificatePath); + X509Chain customChain = new(); + customChain.ChainPolicy.ExtraStore.Add(trustedRoot); + // "tell the X509Chain class that I do trust this root certs and it should check just the certs in the chain and nothing else" + customChain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority; + customChain.ChainPolicy.RevocationMode = X509RevocationMode.Online; + + bool chainValid = customChain.Build(cert2); + return chainValid || (tlsProperties.AllowSelfSigned && IsSelfSigned(cert2)); } } } diff --git a/csharp/src/Drivers/Apache/Impala/ImpalaStandardConnection.cs b/csharp/src/Drivers/Apache/Impala/ImpalaStandardConnection.cs index 6cbef924a8..a87a7973b3 100644 --- a/csharp/src/Drivers/Apache/Impala/ImpalaStandardConnection.cs +++ b/csharp/src/Drivers/Apache/Impala/ImpalaStandardConnection.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; using System.Net; +using System.Net.Security; using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Tasks; @@ -115,13 +116,14 @@ protected override TTransport CreateTransport() TTransport transport; if (TlsOptions.IsTlsEnabled) { + RemoteCertificateValidationCallback certValidator = (sender, cert, chain, errors) => HiveServer2TlsImpl.ValidateCertificate(cert, errors, TlsOptions); if (IPAddress.TryParse(hostName!, out var address)) { - transport = new TTlsSocketTransport(address!, int.Parse(port!), config: new(), 0, !string.IsNullOrEmpty(TlsOptions.TrustedCertificatePath) ? new X509Certificate2(TlsOptions.TrustedCertificatePath!) : null, certValidator: HiveServer2TlsImpl.GetCertificateValidator(TlsOptions)); + transport = new TTlsSocketTransport(address!, int.Parse(port!), config: new(), 0, null, certValidator: certValidator); } else { - transport = new TTlsSocketTransport(hostName!, int.Parse(port!), config: new(), 0, !string.IsNullOrEmpty(TlsOptions.TrustedCertificatePath) ? new X509Certificate2(TlsOptions.TrustedCertificatePath!) : null, certValidator: HiveServer2TlsImpl.GetCertificateValidator(TlsOptions)); + transport = new TTlsSocketTransport(hostName!, int.Parse(port!), config: new(), 0, null, certValidator: certValidator); } } else diff --git a/csharp/test/Drivers/Apache/Hive2/HiveServer2TlsImplTest.cs b/csharp/test/Drivers/Apache/Hive2/HiveServer2TlsImplTest.cs index f707b992f5..7ae6a207f3 100644 --- a/csharp/test/Drivers/Apache/Hive2/HiveServer2TlsImplTest.cs +++ b/csharp/test/Drivers/Apache/Hive2/HiveServer2TlsImplTest.cs @@ -64,8 +64,6 @@ internal void TestValidateStandardTlsOptions(Dictionary? dataTyp yield return new object?[] { new Dictionary { { HttpTlsOptions.IsTlsEnabled, "True" } }, new TlsProperties { IsTlsEnabled = true, DisableServerCertificateValidation = false, AllowSelfSigned = false, AllowHostnameMismatch = false } }; yield return new object?[] { new Dictionary { { HttpTlsOptions.IsTlsEnabled, "tRUe" }, { HttpTlsOptions.AllowSelfSigned, "true" } }, new TlsProperties { IsTlsEnabled = true, DisableServerCertificateValidation = false, AllowSelfSigned = true, AllowHostnameMismatch = false } }; yield return new object?[] { new Dictionary { { HttpTlsOptions.IsTlsEnabled, "TruE" }, { HttpTlsOptions.AllowSelfSigned, "True" }, { HttpTlsOptions.AllowHostnameMismatch, "True" } }, new TlsProperties { IsTlsEnabled = true, DisableServerCertificateValidation = false, AllowSelfSigned = true, AllowHostnameMismatch = true } }; - // certificate path is ignored if self signed is not allowed - yield return new object?[] { new Dictionary { { HttpTlsOptions.IsTlsEnabled, "True" }, { HttpTlsOptions.AllowSelfSigned, "False" }, { HttpTlsOptions.AllowHostnameMismatch, "True" }, { HttpTlsOptions.TrustedCertificatePath, "" } }, new TlsProperties { IsTlsEnabled = true, DisableServerCertificateValidation = false, AllowSelfSigned = false, AllowHostnameMismatch = true } }; // invalid certificate path yield return new object?[] { new Dictionary { { HttpTlsOptions.IsTlsEnabled, "True" }, { HttpTlsOptions.AllowSelfSigned, "True" }, { HttpTlsOptions.AllowHostnameMismatch, "True" }, { HttpTlsOptions.TrustedCertificatePath, "" } }, null, typeof(FileNotFoundException) }; } @@ -86,8 +84,6 @@ internal void TestValidateStandardTlsOptions(Dictionary? dataTyp yield return new object?[] { new Dictionary { { StandardTlsOptions.IsTlsEnabled, "True" } }, new TlsProperties { IsTlsEnabled = true, DisableServerCertificateValidation = false, AllowSelfSigned = false, AllowHostnameMismatch = false } }; yield return new object?[] { new Dictionary { { StandardTlsOptions.IsTlsEnabled, "tRUe" }, { StandardTlsOptions.AllowSelfSigned, "true" } }, new TlsProperties { IsTlsEnabled = true, DisableServerCertificateValidation = false, AllowSelfSigned = true, AllowHostnameMismatch = false } }; yield return new object?[] { new Dictionary { { StandardTlsOptions.IsTlsEnabled, "TruE" }, { StandardTlsOptions.AllowSelfSigned, "True" }, { StandardTlsOptions.AllowHostnameMismatch, "True" } }, new TlsProperties { IsTlsEnabled = true, DisableServerCertificateValidation = false, AllowSelfSigned = true, AllowHostnameMismatch = true } }; - // certificate path is ignored if self signed is not allowed - yield return new object?[] { new Dictionary { { StandardTlsOptions.IsTlsEnabled, "True" }, { StandardTlsOptions.AllowSelfSigned, "False" }, { StandardTlsOptions.AllowHostnameMismatch, "True" }, { StandardTlsOptions.TrustedCertificatePath, "" } }, new TlsProperties { IsTlsEnabled = true, DisableServerCertificateValidation = false, AllowSelfSigned = false, AllowHostnameMismatch = true } }; // invalid certificate path yield return new object?[] { new Dictionary { { StandardTlsOptions.IsTlsEnabled, "True" }, { StandardTlsOptions.AllowSelfSigned, "True" }, { StandardTlsOptions.AllowHostnameMismatch, "True" }, { StandardTlsOptions.TrustedCertificatePath, "" } }, null, typeof(FileNotFoundException) }; } From 0ad34419bedaaecc4ed85199224f2b31276bbcfa Mon Sep 17 00:00:00 2001 From: Sudhir Emmadi Date: Fri, 1 Aug 2025 15:59:28 +0530 Subject: [PATCH 3/3] Fix mixed line endings --- .../Apache/Hive2/HiveServer2TlsImpl.cs | 96 +++++++++---------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/csharp/src/Drivers/Apache/Hive2/HiveServer2TlsImpl.cs b/csharp/src/Drivers/Apache/Hive2/HiveServer2TlsImpl.cs index 1abd9936c6..9a9311d7af 100644 --- a/csharp/src/Drivers/Apache/Hive2/HiveServer2TlsImpl.cs +++ b/csharp/src/Drivers/Apache/Hive2/HiveServer2TlsImpl.cs @@ -82,30 +82,30 @@ static internal HttpClientHandler NewHttpClientHandler(TlsProperties tlsProperti return httpClientHandler; } - static private bool IsSelfSigned(X509Certificate2 cert) - { - return cert.Subject == cert.Issuer && IsSignedBy(cert, cert); + static private bool IsSelfSigned(X509Certificate2 cert) + { + return cert.Subject == cert.Issuer && IsSignedBy(cert, cert); } - static private bool IsSignedBy(X509Certificate2 cert, X509Certificate2 issuer) - { - try - { - using (var chain = new X509Chain()) - { - chain.ChainPolicy.ExtraStore.Add(issuer); - chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority; - chain.ChainPolicy.RevocationMode = X509RevocationMode.Online; - - return chain.Build(cert) - && chain.ChainElements.Count == 1 - && chain.ChainElements[0].Certificate.Thumbprint == issuer.Thumbprint; - } - } - catch - { - return false; - } + static private bool IsSignedBy(X509Certificate2 cert, X509Certificate2 issuer) + { + try + { + using (var chain = new X509Chain()) + { + chain.ChainPolicy.ExtraStore.Add(issuer); + chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority; + chain.ChainPolicy.RevocationMode = X509RevocationMode.Online; + + return chain.Build(cert) + && chain.ChainElements.Count == 1 + && chain.ChainElements[0].Certificate.Thumbprint == issuer.Thumbprint; + } + } + catch + { + return false; + } } static internal TlsProperties GetStandardTlsOptions(IReadOnlyDictionary properties) @@ -138,32 +138,32 @@ static internal TlsProperties GetStandardTlsOptions(IReadOnlyDictionary