diff --git a/src/libraries/Common/src/System/Net/Security/CertificateValidation.OSX.cs b/src/libraries/Common/src/System/Net/Security/CertificateValidation.OSX.cs index b269a0fb70fa5b..f0ce7002b3d4e8 100644 --- a/src/libraries/Common/src/System/Net/Security/CertificateValidation.OSX.cs +++ b/src/libraries/Common/src/System/Net/Security/CertificateValidation.OSX.cs @@ -13,8 +13,9 @@ internal static class CertificateValidation { private static readonly IdnMapping s_idnMapping = new IdnMapping(); - // WARNING: This function will do the verification using OpenSSL. If the intention is to use OS function, caller should use CertificatePal interface. - internal static SslPolicyErrors BuildChainAndVerifyProperties(X509Chain chain, X509Certificate2 remoteCertificate, bool checkCertName, bool _ /*isServer*/, string? hostName, Span certificateBuffer) +#pragma warning disable IDE0060 + internal static SslPolicyErrors BuildChainAndVerifyProperties(X509Chain chain, X509Certificate2 remoteCertificate, bool checkCertName, bool isServer, string? hostName, Span certificateBuffer) +#pragma warning restore IDE0060 { SslPolicyErrors errors = chain.Build(remoteCertificate) ? SslPolicyErrors.None : @@ -30,53 +31,19 @@ internal static SslPolicyErrors BuildChainAndVerifyProperties(X509Chain chain, X return errors | SslPolicyErrors.RemoteCertificateNameMismatch; } - SafeX509Handle certHandle; - unsafe + bool match; + + if (IPAddress.TryParse(hostName, out _)) { - if (certificateBuffer.Length > 0) - { - fixed (byte* pCert = certificateBuffer) - { - certHandle = Interop.Crypto.DecodeX509((IntPtr)pCert, certificateBuffer.Length); - } - } - else - { - // We dont't have DER encoded buffer. - byte[] der = remoteCertificate.Export(X509ContentType.Cert); - fixed (byte* pDer = der) - { - certHandle = Interop.Crypto.DecodeX509((IntPtr)pDer, der.Length); - } - } + match = remoteCertificate.MatchesHostname(hostName); } - - int hostNameMatch; - using (certHandle) + else { - IPAddress? hostnameAsIp; - if (IPAddress.TryParse(hostName, out hostnameAsIp)) - { - byte[] addressBytes = hostnameAsIp.GetAddressBytes(); - hostNameMatch = Interop.Crypto.CheckX509IpAddress(certHandle, addressBytes, addressBytes.Length, hostName, hostName.Length); - } - else - { - // The IdnMapping converts Unicode input into the IDNA punycode sequence. - // It also does host case normalization. The bypass logic would be something - // like "all characters being within [a-z0-9.-]+" - string matchName = s_idnMapping.GetAscii(hostName); - hostNameMatch = Interop.Crypto.CheckX509Hostname(certHandle, matchName, matchName.Length); - - if (hostNameMatch < 0) - { - throw Interop.Crypto.CreateOpenSslCryptographicException(); - } - } + string matchName = s_idnMapping.GetAscii(hostName); + match = remoteCertificate.MatchesHostname(matchName); } - Debug.Assert(hostNameMatch == 0 || hostNameMatch == 1, $"Expected 0 or 1 from CheckX509Hostname, got {hostNameMatch}"); - return hostNameMatch == 1 ? + return match ? errors : errors | SslPolicyErrors.RemoteCertificateNameMismatch; } diff --git a/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj b/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj index 546996f4b97c33..8cacb09b8d3c41 100644 --- a/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj +++ b/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj @@ -77,12 +77,9 @@ - - - - + + - @@ -99,6 +96,12 @@ + + + + + + diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs index 827841626541ab..49464fe44514e7 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs @@ -1426,7 +1426,7 @@ private async Task SniTestCore(string hostname, bool shouldSendSni) [InlineData("a")] [InlineData("test")] [InlineData("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")] // max allowed hostname length is 63 - [InlineData("\u017C\u00F3\u0142\u0107 g\u0119\u015Bl\u0105 ja\u017A\u0144. \u7EA2\u70E7. \u7167\u308A\u713C\u304D")] + [InlineData("\u017C\u00F3\u0142\u0107g\u0119\u015Bl\u0105ja\u017A\u0144.\u7EA2\u70E7.\u7167\u308A\u713C\u304D")] public Task ClientSendsSniServerReceives_Ok(string hostname) => SniTestCore(hostname, true); [Theory]