From 1325e7a3fca062dcdff092ce804837217e0aad36 Mon Sep 17 00:00:00 2001 From: Morten Nielsen Date: Thu, 11 Apr 2024 13:34:02 -0700 Subject: [PATCH 01/17] Adds support for X509 client certificates --- src/Foundation/NSUrlSessionHandler.cs | 36 ++++++++++++++++++++------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/src/Foundation/NSUrlSessionHandler.cs b/src/Foundation/NSUrlSessionHandler.cs index a2029e14a34d..cb9c03359046 100644 --- a/src/Foundation/NSUrlSessionHandler.cs +++ b/src/Foundation/NSUrlSessionHandler.cs @@ -567,15 +567,21 @@ public DecompressionMethods AutomaticDecompression { [EditorBrowsable (EditorBrowsableState.Never)] public bool CheckCertificateRevocationList { get; set; } = false; - // We're ignoring this property, just like Xamarin.Android does: - // https://github.com/xamarin/xamarin-android/blob/09e8cb5c07ea6c39383185a3f90e53186749b802/src/Mono.Android/Xamarin.Android.Net/AndroidMessageHandler.cs#L150 - // Note: we can't return null (like Xamarin.Android does), because the return type isn't nullable. - [UnsupportedOSPlatform ("ios")] - [UnsupportedOSPlatform ("maccatalyst")] - [UnsupportedOSPlatform ("tvos")] - [UnsupportedOSPlatform ("macos")] - [EditorBrowsable (EditorBrowsableState.Never)] - public X509CertificateCollection ClientCertificates { get { return new X509CertificateCollection (); } } + + private X509CertificateCollection? _clientCertificates; + + public X509CertificateCollection ClientCertificates + { + get + { + if (ClientCertificateOptions != ClientCertificateOption.Manual) + { + throw new InvalidOperationException($"Enable manual options first on {nameof(ClientCertificateOptions)}"); + } + + return _clientCertificates ?? (_clientCertificates = new X509CertificateCollection()); + } + } // We're ignoring this property, just like Xamarin.Android does: // https://github.com/xamarin/xamarin-android/blob/09e8cb5c07ea6c39383185a3f90e53186749b802/src/Mono.Android/Xamarin.Android.Net/AndroidMessageHandler.cs#L148 @@ -1088,6 +1094,18 @@ void DidReceiveChallengeImpl (NSUrlSession session, NSUrlSessionTask task, NSUrl } return; } + if (sessionHandler.ClientCertificateOptions == ClientCertificateOption.Manual && challenge.ProtectionSpace.AuthenticationMethod == NSUrlProtectionSpace.AuthenticationMethodClientCertificate) + { + var certificate = System.Net.Security.CertificateHelper.GetEligibleClientCertificate(sessionHandler.ClientCertificates); + if (certificate != null) + { + var cert = new SecCertificate(certificate); + var identity = SecIdentity.Import(certificate); + var credential = new NSUrlCredential(identity, new SecCertificate[] { cert }, NSUrlCredentialPersistence.ForSession); + completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, credential); + return; + } + } // case for the basic auth failing up front. As per apple documentation: // The URL Loading System is designed to handle various aspects of the HTTP protocol for you. As a result, you should not modify the following headers using // the addValue(_:forHTTPHeaderField:) or setValue(_:forHTTPHeaderField:) methods: From f4432517f1e1b2d61916252d7e1ea96eefa94666 Mon Sep 17 00:00:00 2001 From: dotMorten Date: Fri, 12 Apr 2024 12:00:22 -0700 Subject: [PATCH 02/17] Add certicate helper from .NET Runtime repro --- src/Foundation/CertificateHelper.cs | 77 +++++++++++++++++++++++++++ src/Foundation/NSUrlSessionHandler.cs | 18 +++---- 2 files changed, 85 insertions(+), 10 deletions(-) create mode 100644 src/Foundation/CertificateHelper.cs diff --git a/src/Foundation/CertificateHelper.cs b/src/Foundation/CertificateHelper.cs new file mode 100644 index 000000000000..28209680bf57 --- /dev/null +++ b/src/Foundation/CertificateHelper.cs @@ -0,0 +1,77 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Based on https://github.com/dotnet/runtime/blob/c2848c582f5d6ae42c89f5bfe0818687ab3345f0/src/libraries/Common/src/System/Net/Security/CertificateHelper.cs +// with the NetEventSource code removed and namespace changed. + +using System.Diagnostics; +using System.Globalization; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using Microsoft.Win32.SafeHandles; + +namespace Foundation { + internal static partial class CertificateHelper { + private const string ClientAuthenticationOID = "1.3.6.1.5.5.7.3.2"; + + internal static X509Certificate2? GetEligibleClientCertificate (X509CertificateCollection? candidateCerts) + { + if (candidateCerts is null || candidateCerts.Count == 0) { + return null; + } + + var certs = new X509Certificate2Collection (); + certs.AddRange (candidateCerts); + + return GetEligibleClientCertificate (certs); + } + + internal static X509Certificate2? GetEligibleClientCertificate (X509Certificate2Collection? candidateCerts) + { + if (candidateCerts is null || candidateCerts.Count == 0) { + return null; + } + + foreach (X509Certificate2 cert in candidateCerts) { + if (!cert.HasPrivateKey) { + continue; + } + + if (IsValidClientCertificate (cert)) { + return cert; + } + } + return null; + } + + private static bool IsValidClientCertificate (X509Certificate2 cert) + { + foreach (X509Extension extension in cert.Extensions) { + if ((extension is X509EnhancedKeyUsageExtension eku) && !IsValidForClientAuthenticationEKU (eku)) { + return false; + } else if ((extension is X509KeyUsageExtension ku) && !IsValidForDigitalSignatureUsage (ku)) { + return false; + } + } + + return true; + } + + private static bool IsValidForClientAuthenticationEKU (X509EnhancedKeyUsageExtension eku) + { + foreach (Oid oid in eku.EnhancedKeyUsages) { + if (oid.Value == ClientAuthenticationOID) { + return true; + } + } + + return false; + } + + private static bool IsValidForDigitalSignatureUsage (X509KeyUsageExtension ku) + { + const X509KeyUsageFlags RequiredUsages = X509KeyUsageFlags.DigitalSignature; + return (ku.KeyUsages & RequiredUsages) == RequiredUsages; + } + } +} diff --git a/src/Foundation/NSUrlSessionHandler.cs b/src/Foundation/NSUrlSessionHandler.cs index cb9c03359046..033d546d1c8e 100644 --- a/src/Foundation/NSUrlSessionHandler.cs +++ b/src/Foundation/NSUrlSessionHandler.cs @@ -1094,18 +1094,16 @@ void DidReceiveChallengeImpl (NSUrlSession session, NSUrlSessionTask task, NSUrl } return; } - if (sessionHandler.ClientCertificateOptions == ClientCertificateOption.Manual && challenge.ProtectionSpace.AuthenticationMethod == NSUrlProtectionSpace.AuthenticationMethodClientCertificate) - { - var certificate = System.Net.Security.CertificateHelper.GetEligibleClientCertificate(sessionHandler.ClientCertificates); - if (certificate != null) - { - var cert = new SecCertificate(certificate); - var identity = SecIdentity.Import(certificate); - var credential = new NSUrlCredential(identity, new SecCertificate[] { cert }, NSUrlCredentialPersistence.ForSession); - completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, credential); + if (sessionHandler.ClientCertificateOptions == ClientCertificateOption.Manual && challenge.ProtectionSpace.AuthenticationMethod == NSUrlProtectionSpace.AuthenticationMethodClientCertificate) { + var certificate = CertificateHelper.GetEligibleClientCertificate (sessionHandler.ClientCertificates); + if (certificate is not null) { + var cert = new SecCertificate (certificate); + var identity = SecIdentity.Import (certificate); + var credential = new NSUrlCredential (identity, new SecCertificate [] { cert }, NSUrlCredentialPersistence.ForSession); + completionHandler (NSUrlSessionAuthChallengeDisposition.UseCredential, credential); return; } - } + } // case for the basic auth failing up front. As per apple documentation: // The URL Loading System is designed to handle various aspects of the HTTP protocol for you. As a result, you should not modify the following headers using // the addValue(_:forHTTPHeaderField:) or setValue(_:forHTTPHeaderField:) methods: From 257dfdbe32b87e7c3845abab7e16ef19a2429d7d Mon Sep 17 00:00:00 2001 From: dotMorten Date: Mon, 15 Apr 2024 08:57:45 -0700 Subject: [PATCH 03/17] Move certificate helper in as a private local class --- src/Foundation/CertificateHelper.cs | 77 --------------------------- src/Foundation/NSUrlSessionHandler.cs | 66 +++++++++++++++++++++++ 2 files changed, 66 insertions(+), 77 deletions(-) delete mode 100644 src/Foundation/CertificateHelper.cs diff --git a/src/Foundation/CertificateHelper.cs b/src/Foundation/CertificateHelper.cs deleted file mode 100644 index 28209680bf57..000000000000 --- a/src/Foundation/CertificateHelper.cs +++ /dev/null @@ -1,77 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -// Based on https://github.com/dotnet/runtime/blob/c2848c582f5d6ae42c89f5bfe0818687ab3345f0/src/libraries/Common/src/System/Net/Security/CertificateHelper.cs -// with the NetEventSource code removed and namespace changed. - -using System.Diagnostics; -using System.Globalization; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; -using Microsoft.Win32.SafeHandles; - -namespace Foundation { - internal static partial class CertificateHelper { - private const string ClientAuthenticationOID = "1.3.6.1.5.5.7.3.2"; - - internal static X509Certificate2? GetEligibleClientCertificate (X509CertificateCollection? candidateCerts) - { - if (candidateCerts is null || candidateCerts.Count == 0) { - return null; - } - - var certs = new X509Certificate2Collection (); - certs.AddRange (candidateCerts); - - return GetEligibleClientCertificate (certs); - } - - internal static X509Certificate2? GetEligibleClientCertificate (X509Certificate2Collection? candidateCerts) - { - if (candidateCerts is null || candidateCerts.Count == 0) { - return null; - } - - foreach (X509Certificate2 cert in candidateCerts) { - if (!cert.HasPrivateKey) { - continue; - } - - if (IsValidClientCertificate (cert)) { - return cert; - } - } - return null; - } - - private static bool IsValidClientCertificate (X509Certificate2 cert) - { - foreach (X509Extension extension in cert.Extensions) { - if ((extension is X509EnhancedKeyUsageExtension eku) && !IsValidForClientAuthenticationEKU (eku)) { - return false; - } else if ((extension is X509KeyUsageExtension ku) && !IsValidForDigitalSignatureUsage (ku)) { - return false; - } - } - - return true; - } - - private static bool IsValidForClientAuthenticationEKU (X509EnhancedKeyUsageExtension eku) - { - foreach (Oid oid in eku.EnhancedKeyUsages) { - if (oid.Value == ClientAuthenticationOID) { - return true; - } - } - - return false; - } - - private static bool IsValidForDigitalSignatureUsage (X509KeyUsageExtension ku) - { - const X509KeyUsageFlags RequiredUsages = X509KeyUsageFlags.DigitalSignature; - return (ku.KeyUsages & RequiredUsages) == RequiredUsages; - } - } -} diff --git a/src/Foundation/NSUrlSessionHandler.cs b/src/Foundation/NSUrlSessionHandler.cs index 033d546d1c8e..1106c9b117a1 100644 --- a/src/Foundation/NSUrlSessionHandler.cs +++ b/src/Foundation/NSUrlSessionHandler.cs @@ -1608,5 +1608,71 @@ protected override void Dispose (bool disposing) stream?.Dispose (); } } + + private static class CertificateHelper { + // Based on https://github.com/dotnet/runtime/blob/c2848c582f5d6ae42c89f5bfe0818687ab3345f0/src/libraries/Common/src/System/Net/Security/CertificateHelper.cs + // with the NetEventSource code removed and namespace changed. + private const string ClientAuthenticationOID = "1.3.6.1.5.5.7.3.2"; + + internal static X509Certificate2? GetEligibleClientCertificate (X509CertificateCollection? candidateCerts) + { + if (candidateCerts is null || candidateCerts.Count == 0) { + return null; + } + + var certs = new X509Certificate2Collection (); + certs.AddRange (candidateCerts); + + return GetEligibleClientCertificate (certs); + } + + internal static X509Certificate2? GetEligibleClientCertificate (X509Certificate2Collection? candidateCerts) + { + if (candidateCerts is null || candidateCerts.Count == 0) { + return null; + } + + foreach (X509Certificate2 cert in candidateCerts) { + if (!cert.HasPrivateKey) { + continue; + } + + if (IsValidClientCertificate (cert)) { + return cert; + } + } + return null; + } + + private static bool IsValidClientCertificate (X509Certificate2 cert) + { + foreach (X509Extension extension in cert.Extensions) { + if ((extension is X509EnhancedKeyUsageExtension eku) && !IsValidForClientAuthenticationEKU (eku)) { + return false; + } else if ((extension is X509KeyUsageExtension ku) && !IsValidForDigitalSignatureUsage (ku)) { + return false; + } + } + + return true; + } + + private static bool IsValidForClientAuthenticationEKU (X509EnhancedKeyUsageExtension eku) + { + foreach (Oid oid in eku.EnhancedKeyUsages) { + if (oid.Value == ClientAuthenticationOID) { + return true; + } + } + + return false; + } + + private static bool IsValidForDigitalSignatureUsage (X509KeyUsageExtension ku) + { + const X509KeyUsageFlags RequiredUsages = X509KeyUsageFlags.DigitalSignature; + return (ku.KeyUsages & RequiredUsages) == RequiredUsages; + } + } } } From 636031e5b9ac07e37c8de3fbfec13ac7b3b2f5e3 Mon Sep 17 00:00:00 2001 From: dotMorten Date: Mon, 15 Apr 2024 11:28:27 -0700 Subject: [PATCH 04/17] Fully qualify type --- src/Foundation/NSUrlSessionHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Foundation/NSUrlSessionHandler.cs b/src/Foundation/NSUrlSessionHandler.cs index 1106c9b117a1..b18909b8c8a3 100644 --- a/src/Foundation/NSUrlSessionHandler.cs +++ b/src/Foundation/NSUrlSessionHandler.cs @@ -1659,7 +1659,7 @@ private static bool IsValidClientCertificate (X509Certificate2 cert) private static bool IsValidForClientAuthenticationEKU (X509EnhancedKeyUsageExtension eku) { - foreach (Oid oid in eku.EnhancedKeyUsages) { + foreach (System.Security.Cryptography.Oid oid in eku.EnhancedKeyUsages) { if (oid.Value == ClientAuthenticationOID) { return true; } From f34ded9d83ea3d0fc424c94372d51f95eac37281 Mon Sep 17 00:00:00 2001 From: dotMorten Date: Mon, 15 Apr 2024 12:56:18 -0700 Subject: [PATCH 05/17] Only include new functionality for NET builds --- src/Foundation/NSUrlSessionHandler.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Foundation/NSUrlSessionHandler.cs b/src/Foundation/NSUrlSessionHandler.cs index b18909b8c8a3..f26abb8a5f18 100644 --- a/src/Foundation/NSUrlSessionHandler.cs +++ b/src/Foundation/NSUrlSessionHandler.cs @@ -1094,6 +1094,7 @@ void DidReceiveChallengeImpl (NSUrlSession session, NSUrlSessionTask task, NSUrl } return; } +#if NET if (sessionHandler.ClientCertificateOptions == ClientCertificateOption.Manual && challenge.ProtectionSpace.AuthenticationMethod == NSUrlProtectionSpace.AuthenticationMethodClientCertificate) { var certificate = CertificateHelper.GetEligibleClientCertificate (sessionHandler.ClientCertificates); if (certificate is not null) { @@ -1104,6 +1105,8 @@ void DidReceiveChallengeImpl (NSUrlSession session, NSUrlSessionTask task, NSUrl return; } } +#endif + // case for the basic auth failing up front. As per apple documentation: // The URL Loading System is designed to handle various aspects of the HTTP protocol for you. As a result, you should not modify the following headers using // the addValue(_:forHTTPHeaderField:) or setValue(_:forHTTPHeaderField:) methods: @@ -1609,6 +1612,7 @@ protected override void Dispose (bool disposing) } } +#if NET private static class CertificateHelper { // Based on https://github.com/dotnet/runtime/blob/c2848c582f5d6ae42c89f5bfe0818687ab3345f0/src/libraries/Common/src/System/Net/Security/CertificateHelper.cs // with the NetEventSource code removed and namespace changed. @@ -1674,5 +1678,6 @@ private static bool IsValidForDigitalSignatureUsage (X509KeyUsageExtension ku) return (ku.KeyUsages & RequiredUsages) == RequiredUsages; } } +#endif } } From c7b65b436dd2d1a7c175054edd9e737b06bcb1c9 Mon Sep 17 00:00:00 2001 From: Morten Nielsen Date: Tue, 16 Apr 2024 10:27:41 -0700 Subject: [PATCH 06/17] Fix code formatting --- src/Foundation/NSUrlSessionHandler.cs | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/Foundation/NSUrlSessionHandler.cs b/src/Foundation/NSUrlSessionHandler.cs index f26abb8a5f18..d5b1752538c5 100644 --- a/src/Foundation/NSUrlSessionHandler.cs +++ b/src/Foundation/NSUrlSessionHandler.cs @@ -568,18 +568,15 @@ public DecompressionMethods AutomaticDecompression { public bool CheckCertificateRevocationList { get; set; } = false; - private X509CertificateCollection? _clientCertificates; + X509CertificateCollection? _clientCertificates; - public X509CertificateCollection ClientCertificates - { - get - { - if (ClientCertificateOptions != ClientCertificateOption.Manual) - { - throw new InvalidOperationException($"Enable manual options first on {nameof(ClientCertificateOptions)}"); + public X509CertificateCollection ClientCertificates { + get { + if (ClientCertificateOptions != ClientCertificateOption.Manual) { + throw new InvalidOperationException ($"Enable manual options first on {nameof (ClientCertificateOptions)}"); } - return _clientCertificates ?? (_clientCertificates = new X509CertificateCollection()); + return _clientCertificates ?? (_clientCertificates = new X509CertificateCollection ()); } } @@ -1613,10 +1610,10 @@ protected override void Dispose (bool disposing) } #if NET - private static class CertificateHelper { + static class CertificateHelper { // Based on https://github.com/dotnet/runtime/blob/c2848c582f5d6ae42c89f5bfe0818687ab3345f0/src/libraries/Common/src/System/Net/Security/CertificateHelper.cs // with the NetEventSource code removed and namespace changed. - private const string ClientAuthenticationOID = "1.3.6.1.5.5.7.3.2"; + const string ClientAuthenticationOID = "1.3.6.1.5.5.7.3.2"; internal static X509Certificate2? GetEligibleClientCertificate (X509CertificateCollection? candidateCerts) { @@ -1648,7 +1645,7 @@ private static class CertificateHelper { return null; } - private static bool IsValidClientCertificate (X509Certificate2 cert) + static bool IsValidClientCertificate (X509Certificate2 cert) { foreach (X509Extension extension in cert.Extensions) { if ((extension is X509EnhancedKeyUsageExtension eku) && !IsValidForClientAuthenticationEKU (eku)) { @@ -1661,7 +1658,7 @@ private static bool IsValidClientCertificate (X509Certificate2 cert) return true; } - private static bool IsValidForClientAuthenticationEKU (X509EnhancedKeyUsageExtension eku) + static bool IsValidForClientAuthenticationEKU (X509EnhancedKeyUsageExtension eku) { foreach (System.Security.Cryptography.Oid oid in eku.EnhancedKeyUsages) { if (oid.Value == ClientAuthenticationOID) { @@ -1672,7 +1669,7 @@ private static bool IsValidForClientAuthenticationEKU (X509EnhancedKeyUsageExten return false; } - private static bool IsValidForDigitalSignatureUsage (X509KeyUsageExtension ku) + static bool IsValidForDigitalSignatureUsage (X509KeyUsageExtension ku) { const X509KeyUsageFlags RequiredUsages = X509KeyUsageFlags.DigitalSignature; return (ku.KeyUsages & RequiredUsages) == RequiredUsages; From a8886c08425441f02971d5aab5567376c9094889 Mon Sep 17 00:00:00 2001 From: dotMorten Date: Fri, 19 Apr 2024 13:42:40 -0700 Subject: [PATCH 07/17] Add unit test --- .../System.Net.Http/MessageHandlers.cs | 23 +++++++++++++++++++ .../System.Net.Http/NetworkResources.cs | 1 + 2 files changed, 24 insertions(+) diff --git a/tests/monotouch-test/System.Net.Http/MessageHandlers.cs b/tests/monotouch-test/System.Net.Http/MessageHandlers.cs index d08d7185c80e..d2f7fa8eb115 100644 --- a/tests/monotouch-test/System.Net.Http/MessageHandlers.cs +++ b/tests/monotouch-test/System.Net.Http/MessageHandlers.cs @@ -664,6 +664,29 @@ public void RejectSslCertificatesWithCustomValidationCallbackNSUrlSessionHandler Assert.IsNull (ex2, "Callback asserts"); } } + + [Test] + public void TestNSUrlSessionHandlerSendClientCertificate () + { + string certificate_base64 = "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"; + X509Certificate2 certificate = new X509Certificate2 (global::System.Convert.FromBase64String (certificate_base64), "test"); + string content = ""; + var done = TestRuntime.TryRunAsync (TimeSpan.FromSeconds (30), async () => { + using var handler = new NSUrlSessionHandler (); + handler.ClientCertificates.Add (certificate); + using var client = new HttpClient (handler); + var response = await client.GetAsync (NetworkResources.EchoClientCertificateUrl); + content = await response.EnsureSuccessStatusCode ().Content.ReadAsStringAsync (); + }, out var ex); + if (!done) { // timeouts happen in the bots due to dns issues, connection issues etc.. we do not want to fail + Assert.Inconclusive ("Request timedout."); + } else { + Assert.IsNull (ex, "Exception wasn't expected."); + X509Certificate2 certificate2 = new X509Certificate2 (global::System.Convert.FromBase64String (content)); + Assert.AreEqual (certificate.Thumbprint, certificate2.Thumbprint); + } + } + #endif [Test] diff --git a/tests/monotouch-test/System.Net.Http/NetworkResources.cs b/tests/monotouch-test/System.Net.Http/NetworkResources.cs index b4a53e376182..e0483022c32f 100644 --- a/tests/monotouch-test/System.Net.Http/NetworkResources.cs +++ b/tests/monotouch-test/System.Net.Http/NetworkResources.cs @@ -19,6 +19,7 @@ public static class NetworkResources { public static string XamarinHttpUrl => AssertNetworkConnection ("http://dotnet.microsoft.com/apps/xamarin"); public static Uri XamarinUri => new Uri (XamarinUrl); public static string StatsUrl => AssertNetworkConnection ("https://api.imgur.com/2/stats"); + public static string EchoClientCertificateUrl = "https://corefx-net-tls.azurewebsites.net/EchoClientCertificate.ashx"; public static string [] HttpsUrls => new [] { MicrosoftUrl, From ee2d96e14dd0271aaf10d27e25efb48593e6dc0c Mon Sep 17 00:00:00 2001 From: Manuel de la Pena Date: Mon, 6 May 2024 12:50:15 -0400 Subject: [PATCH 08/17] Fix tests on macOS by not using the default keyset of the system by an in memory one (EphemeralKeySet). --- tests/monotouch-test/System.Net.Http/MessageHandlers.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/monotouch-test/System.Net.Http/MessageHandlers.cs b/tests/monotouch-test/System.Net.Http/MessageHandlers.cs index d2f7fa8eb115..eaf38965a332 100644 --- a/tests/monotouch-test/System.Net.Http/MessageHandlers.cs +++ b/tests/monotouch-test/System.Net.Http/MessageHandlers.cs @@ -669,7 +669,10 @@ public void RejectSslCertificatesWithCustomValidationCallbackNSUrlSessionHandler public void TestNSUrlSessionHandlerSendClientCertificate () { string certificate_base64 = "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"; - X509Certificate2 certificate = new X509Certificate2 (global::System.Convert.FromBase64String (certificate_base64), "test"); + // Use the ephemeral keystore so that the test do pass on macOS, otherwise we will get an exception from dotnet because it does not have the rights + // to access the defualt key storage. + // ref: https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.x509certificates.x509keystorageflags?view=net-8.0 + X509Certificate2 certificate = new X509Certificate2 (global::System.Convert.FromBase64String (certificate_base64), "test", X509KeyStorageFlags.EphemeralKeySet); string content = ""; var done = TestRuntime.TryRunAsync (TimeSpan.FromSeconds (30), async () => { using var handler = new NSUrlSessionHandler (); From 2bef14f74b65b5b40432ee5664c5817a2e2b1715 Mon Sep 17 00:00:00 2001 From: Manuel de la Pena Date: Mon, 6 May 2024 17:29:32 -0400 Subject: [PATCH 09/17] Move to exportable to fix the tests. --- tests/monotouch-test/System.Net.Http/MessageHandlers.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/monotouch-test/System.Net.Http/MessageHandlers.cs b/tests/monotouch-test/System.Net.Http/MessageHandlers.cs index eaf38965a332..12f3e312ffba 100644 --- a/tests/monotouch-test/System.Net.Http/MessageHandlers.cs +++ b/tests/monotouch-test/System.Net.Http/MessageHandlers.cs @@ -669,10 +669,8 @@ public void RejectSslCertificatesWithCustomValidationCallbackNSUrlSessionHandler public void TestNSUrlSessionHandlerSendClientCertificate () { string certificate_base64 = "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"; - // Use the ephemeral keystore so that the test do pass on macOS, otherwise we will get an exception from dotnet because it does not have the rights - // to access the defualt key storage. - // ref: https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.x509certificates.x509keystorageflags?view=net-8.0 - X509Certificate2 certificate = new X509Certificate2 (global::System.Convert.FromBase64String (certificate_base64), "test", X509KeyStorageFlags.EphemeralKeySet); + // make the cert exportable so that the tests pass: ref: https://github.com/dotnet/runtime/issues/21581 + X509Certificate2 certificate = new X509Certificate2 (global::System.Convert.FromBase64String (certificate_base64), "test", X509KeyStorageFlags.Exportable); string content = ""; var done = TestRuntime.TryRunAsync (TimeSpan.FromSeconds (30), async () => { using var handler = new NSUrlSessionHandler (); From 56a0758ae76ac009912efb23c190182c527c3a5a Mon Sep 17 00:00:00 2001 From: Manuel de la Pena Date: Tue, 7 May 2024 15:50:11 -0400 Subject: [PATCH 10/17] Add the persistent storage. --- tests/monotouch-test/System.Net.Http/MessageHandlers.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/monotouch-test/System.Net.Http/MessageHandlers.cs b/tests/monotouch-test/System.Net.Http/MessageHandlers.cs index 12f3e312ffba..f78a390d0001 100644 --- a/tests/monotouch-test/System.Net.Http/MessageHandlers.cs +++ b/tests/monotouch-test/System.Net.Http/MessageHandlers.cs @@ -670,7 +670,7 @@ public void TestNSUrlSessionHandlerSendClientCertificate () { string certificate_base64 = "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"; // make the cert exportable so that the tests pass: ref: https://github.com/dotnet/runtime/issues/21581 - X509Certificate2 certificate = new X509Certificate2 (global::System.Convert.FromBase64String (certificate_base64), "test", X509KeyStorageFlags.Exportable); + X509Certificate2 certificate = new X509Certificate2 (global::System.Convert.FromBase64String (certificate_base64), "test", X509KeyStorageFlags.PersistKeySet); string content = ""; var done = TestRuntime.TryRunAsync (TimeSpan.FromSeconds (30), async () => { using var handler = new NSUrlSessionHandler (); From 2583158783b2bcffb9831705e703f112a433cf3b Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Wed, 8 May 2024 10:09:40 +0200 Subject: [PATCH 11/17] Add documentation. --- src/Foundation/NSUrlSessionHandler.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Foundation/NSUrlSessionHandler.cs b/src/Foundation/NSUrlSessionHandler.cs index d5b1752538c5..fb76ba63ef4e 100644 --- a/src/Foundation/NSUrlSessionHandler.cs +++ b/src/Foundation/NSUrlSessionHandler.cs @@ -570,6 +570,8 @@ public DecompressionMethods AutomaticDecompression { X509CertificateCollection? _clientCertificates; + /// Gets the collection of security certificates that are associated with requests to the server. + /// Client certificates are only supported when ClientCertificateOptions is set to ClientCertificateOptions.Manual. public X509CertificateCollection ClientCertificates { get { if (ClientCertificateOptions != ClientCertificateOption.Manual) { From 30d46f95f0c12d0b4668979508146151edf05d88 Mon Sep 17 00:00:00 2001 From: Manuel de la Pena Date: Fri, 10 May 2024 16:27:34 -0400 Subject: [PATCH 12/17] Seems to be that just adding exportable is enough. --- tests/monotouch-test/System.Net.Http/MessageHandlers.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/monotouch-test/System.Net.Http/MessageHandlers.cs b/tests/monotouch-test/System.Net.Http/MessageHandlers.cs index f78a390d0001..12f3e312ffba 100644 --- a/tests/monotouch-test/System.Net.Http/MessageHandlers.cs +++ b/tests/monotouch-test/System.Net.Http/MessageHandlers.cs @@ -670,7 +670,7 @@ public void TestNSUrlSessionHandlerSendClientCertificate () { string certificate_base64 = "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"; // make the cert exportable so that the tests pass: ref: https://github.com/dotnet/runtime/issues/21581 - X509Certificate2 certificate = new X509Certificate2 (global::System.Convert.FromBase64String (certificate_base64), "test", X509KeyStorageFlags.PersistKeySet); + X509Certificate2 certificate = new X509Certificate2 (global::System.Convert.FromBase64String (certificate_base64), "test", X509KeyStorageFlags.Exportable); string content = ""; var done = TestRuntime.TryRunAsync (TimeSpan.FromSeconds (30), async () => { using var handler = new NSUrlSessionHandler (); From 9d0e5c558493ffabaef68f389e62afdb14e123ee Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Tue, 21 May 2024 09:50:43 +0200 Subject: [PATCH 13/17] Use platform-specific x509 flags, macOS isn't like other platforms. --- tests/monotouch-test/System.Net.Http/MessageHandlers.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/monotouch-test/System.Net.Http/MessageHandlers.cs b/tests/monotouch-test/System.Net.Http/MessageHandlers.cs index 12f3e312ffba..9dbb664f3b97 100644 --- a/tests/monotouch-test/System.Net.Http/MessageHandlers.cs +++ b/tests/monotouch-test/System.Net.Http/MessageHandlers.cs @@ -670,7 +670,14 @@ public void TestNSUrlSessionHandlerSendClientCertificate () { string certificate_base64 = "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"; // make the cert exportable so that the tests pass: ref: https://github.com/dotnet/runtime/issues/21581 - X509Certificate2 certificate = new X509Certificate2 (global::System.Convert.FromBase64String (certificate_base64), "test", X509KeyStorageFlags.Exportable); + +#if __MACOS__ + var storageFlags = X509KeyStorageFlags.Exportable; +#else + var storageFlags = X509KeyStorageFlags.DefaultKeySet; +#endif + + X509Certificate2 certificate = new X509Certificate2 (global::System.Convert.FromBase64String (certificate_base64), "test", storageFlags); string content = ""; var done = TestRuntime.TryRunAsync (TimeSpan.FromSeconds (30), async () => { using var handler = new NSUrlSessionHandler (); From 2d43afdae548d1fa551321240f1be1942415fcb2 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Mon, 23 Sep 2024 11:23:47 +0200 Subject: [PATCH 14/17] Use temporary keychain when importing PKCS#12 data into a SecIdentity on macOS 15+. --- src/Security/Certificate.cs | 83 ++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/src/Security/Certificate.cs b/src/Security/Certificate.cs index deb4053f1c89..796f67ce5709 100644 --- a/src/Security/Certificate.cs +++ b/src/Security/Certificate.cs @@ -583,6 +583,13 @@ public SecCertificate Certificate { } } + /// Create a from PKCS #12 data. + /// The PKCS #12 blob data as a byte array. + /// The password for the private key in the PKCS #12 data. An empty password is not supported. + /// + /// On macOS 14 or earlier this method requires access to the default keychain,where the private key + certificate will be stored. + /// On macOS 15 or later, as well as all other platforms (iOS, tvOS, Mac Catalyst), calling this method will not affect any keychains (a temporary, in-memory keychain is created for the duration of the import). + /// public static SecIdentity Import (byte [] data, string password) { if (data is null) @@ -590,8 +597,82 @@ public static SecIdentity Import (byte [] data, string password) if (string.IsNullOrEmpty (password)) // SecPKCS12Import() doesn't allow empty passwords. throw new ArgumentException (nameof (password)); using (var pwstring = new NSString (password)) - using (var options = NSDictionary.FromObjectAndKey (pwstring, SecImportExport.Passphrase)) { + using (var options = NSMutableDictionary.FromObjectAndKey (pwstring, SecImportExport.Passphrase)) { NSDictionary [] array; +#if __MACOS__ + /* There are unfortunate platform differences for SecPKCS12Import: + * + * `SecPKCS12Import` will, _on macOS only, not other platforms_, add the imported certificate + private key into the default keychain. + * + * Apple's documentation for [`SecPKCS12Import`](https://developer.apple.com/documentation/security/1396915-secpkcs12import?language=objc) + * implies importing into the keychain is optional ("[...] You can then use the Keychain Services API + * (see [Keychain services](https://developer.apple.com/documentation/security/keychain_services?language=objc)) + * to put the identities and associated certificates in the keychain."), but that doesn't match the behavior we're seeing, + * either on the bots nor locally (if I lock the keychain before running the unit test on macOS, I get a dialog asking for + * my password to unlock the keychain when this method is called). Other people on StackOverflow has run into the same issue + * (https://stackoverflow.com/q/33181127), where one of the answers points to the source code (https://stackoverflow.com/a/66846609), + * confirming this behavior. + * + * StackOverflow also suggests using [`SecItemImport`](https://developer.apple.com/documentation/security/1395728-secitemimport) + * instead, which works, with a few caveats: + * + * 1. Importing a PKCS#12 blob only returns the certificate, not the private key. This is a bug, as [confirmed](https://forums.developer.apple.com/forums/thread/31711) by Quinn "The Eskimo!": + * + * > `SecItemImport` really does support importing private keys without putting them in the keychain, + * > and that code all runs and works in the PKCS#12 case; internally I see both the certificate and + * > the private key extracted from the PKCS#12. The problem arises when the code tries to match up + * > the certificate and private key to form an identity. That code is failing in the no-keychain case, + * > so you end up getting back just the certificate. Notably, in the PEM case no matching occurs and + * > thus you get back both the certificate and the private key. + * > + * > This is clearly a bug and I’ve filed it as such (r. 25,140,029). + * + * That was 8 years ago, and 6 years later it still hasn't been fixed (as confirmed by Quinn in the same thread), so it's unlikely it'll ever be fixed. + * + * 2. So I tried exporting the X509Certificate into a PEM string instead, and that works, I successfully + * get back a `SecKey` instance and a `SecCertificate` instance! Success? + * + * 3. Nope, because there's no way to create a `SecIdentity` from `SecKey`+`SecCertificate`. You have to put + * the `SecKey` into a keychain, and then pass the `SecCertificate` to [`SecIdentityCreateWithCertificate`](https://developer.apple.com/documentation/security/1401160-secidentitycreatewithcertificate?language=objc), + * and we're back to where we started. + * + * 4. OK, what about creating a temporary `SecKeychain`, add the `SecKey` there, create the `SecIdentity`, then delete the `SecKeychain`? + * + * * [`SecKeyChain`](https://developer.apple.com/documentation/security/1401214-seckeychaincreate) was deprecated in macOS 10.10 :/ + * * curl had the same problem: + * * https://github.com/curl/curl/issues/10038 + * * https://github.com/curl/curl/issues/5403) + * + * There was PR to use a temporary keychain (https://github.com/curl/curl/pull/10059), with a number of good reasons why it was a bad idea, so it was eventually rejected: + * + * * The temporary keychain is stored on disk, which isn't particularly fast. + * * The ownership/rights of the file must be considered to ensure there are no security issues. + * * Concurrency would have to be considered with regards to cleanup - what if there are multiple threads trying to use the same location on disk. + * + * + * In [this Apple forum thread](https://forums.developer.apple.com/forums/thread/31711) a user gripes about this exact problem: + * + * > I've resorted to using a private API to created a SecIdentity from a SecCertificate and a SecKey that I already have in memory. + * + * Quinn answers: + * + * > On the macOS front, there’s nothing stopping a command-line tool running on a CI machine using the keychain. + * There are some pain points but no showstoppers. + * + * FWIW Quinn “The Eskimo!” wrote a document explaining how to find and fix problems with regards to the keychain on CI machines + * (https://developer.apple.com/forums/thread/712005). The last sentence is a gem: "Resetting trust settings is more of a challenge. + * It’s probably possible to do this with the security tool but, honestly, if you think that your CI system has messed up trust settings + * it’s easiest to throw it away and start again from scratch." - in other words if something goes wrong, the easiest is to wipe the + * machine and start over again. + * + * "some pain points" is somewhat of an understatement... + * + * The good news is that on macOS 15+, Apple added an option to use a temporary, in-memory only keychain, avoiding the whole problem, + * so let's use that! + */ + if (OperatingSystem.IsMacOSVersionAtLeast (15, 0)) + options.Add (SecImportExport.ToMemoryOnly, NSNumber.FromBoolean (true)); +#endif SecStatusCode result = SecImportExport.ImportPkcs12 (data, options, out array); if (result != SecStatusCode.Success) throw new InvalidOperationException (result.ToString ()); From 70e4b1677ff300b0350b2b036f8e689f283f1138 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Mon, 23 Sep 2024 11:28:06 +0200 Subject: [PATCH 15/17] Don't run new test on macOS 14 or earlier. --- tests/monotouch-test/System.Net.Http/MessageHandlers.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/monotouch-test/System.Net.Http/MessageHandlers.cs b/tests/monotouch-test/System.Net.Http/MessageHandlers.cs index 9dbb664f3b97..14074f71c64d 100644 --- a/tests/monotouch-test/System.Net.Http/MessageHandlers.cs +++ b/tests/monotouch-test/System.Net.Http/MessageHandlers.cs @@ -672,6 +672,10 @@ public void TestNSUrlSessionHandlerSendClientCertificate () // make the cert exportable so that the tests pass: ref: https://github.com/dotnet/runtime/issues/21581 #if __MACOS__ + // The test requires access to the default system keychain on macOS 14 or earlier, which is really + // annoying on bots (a password dialog will pop up, blocking the tests). So just not run this test + // on anything earlier than macOS 15.0, + TestRuntime.CheckXcodeVersion (16, 0); var storageFlags = X509KeyStorageFlags.Exportable; #else var storageFlags = X509KeyStorageFlags.DefaultKeySet; From 878218fc8ead60d09a221cc19d18d4e7d1e0a3cc Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Mon, 23 Sep 2024 11:32:01 +0200 Subject: [PATCH 16/17] Update cecil tests. --- tests/cecil-tests/Documentation.KnownFailures.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/cecil-tests/Documentation.KnownFailures.txt b/tests/cecil-tests/Documentation.KnownFailures.txt index 9ad4d29db89a..56aca8bf163d 100644 --- a/tests/cecil-tests/Documentation.KnownFailures.txt +++ b/tests/cecil-tests/Documentation.KnownFailures.txt @@ -47220,7 +47220,6 @@ M:Security.SecCertificate.ToX509Certificate M:Security.SecCertificate.ToX509Certificate2 M:Security.SecCertificate2.#ctor(Security.SecCertificate) M:Security.SecIdentity.GetTypeID -M:Security.SecIdentity.Import(System.Byte[],System.String) M:Security.SecIdentity.Import(System.Security.Cryptography.X509Certificates.X509Certificate2) M:Security.SecIdentity2.#ctor(Security.SecIdentity,Security.SecCertificate[]) M:Security.SecIdentity2.#ctor(Security.SecIdentity) From 76336c5e402efac939e5f3ddb22697eb87f55ed4 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Tue, 24 Sep 2024 16:27:29 +0200 Subject: [PATCH 17/17] Fix Xcode version check. --- tests/monotouch-test/System.Net.Http/MessageHandlers.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/monotouch-test/System.Net.Http/MessageHandlers.cs b/tests/monotouch-test/System.Net.Http/MessageHandlers.cs index 14074f71c64d..4e23e7e149fe 100644 --- a/tests/monotouch-test/System.Net.Http/MessageHandlers.cs +++ b/tests/monotouch-test/System.Net.Http/MessageHandlers.cs @@ -675,7 +675,7 @@ public void TestNSUrlSessionHandlerSendClientCertificate () // The test requires access to the default system keychain on macOS 14 or earlier, which is really // annoying on bots (a password dialog will pop up, blocking the tests). So just not run this test // on anything earlier than macOS 15.0, - TestRuntime.CheckXcodeVersion (16, 0); + TestRuntime.AssertXcodeVersion (16, 0); var storageFlags = X509KeyStorageFlags.Exportable; #else var storageFlags = X509KeyStorageFlags.DefaultKeySet;