Remove obsolete Mono.Security.Providers.* assemblies (#3595)
[mono.git] / mcs / class / System / Mono.Net.Security / ChainValidationHelper.cs
index 1f37bc47589c7cebf77d7b621cd499d095f0c3db..5d2812d2738e4c51c72af55564a3e3c95356e0c4 100644 (file)
@@ -34,9 +34,6 @@
 #if MONO_SECURITY_ALIAS
 extern alias MonoSecurity;
 #endif
-#if MONO_X509_ALIAS
-extern alias PrebuiltSystem;
-#endif
 
 #if MONO_SECURITY_ALIAS
 using MonoSecurity::Mono.Security.Interface;
@@ -47,13 +44,8 @@ using Mono.Security.Interface;
 using MSX = Mono.Security.X509;
 using Mono.Security.X509.Extensions;
 #endif
-#if MONO_X509_ALIAS
-using XX509CertificateCollection = PrebuiltSystem::System.Security.Cryptography.X509Certificates.X509CertificateCollection;
-using XX509Chain = PrebuiltSystem::System.Security.Cryptography.X509Certificates.X509Chain;
-#else
 using XX509CertificateCollection = System.Security.Cryptography.X509Certificates.X509CertificateCollection;
 using XX509Chain = System.Security.Cryptography.X509Certificates.X509Chain;
-#endif
 
 using System;
 using System.Net;
@@ -74,7 +66,7 @@ namespace Mono.Net.Security
 {
        internal delegate bool ServerCertValidationCallbackWrapper (ServerCertValidationCallback callback, X509Certificate certificate, X509Chain chain, MonoSslPolicyErrors sslPolicyErrors);
 
-       internal class ChainValidationHelper : ICertificateValidator
+       internal class ChainValidationHelper : ICertificateValidator2
        {
                readonly object sender;
                readonly MonoTlsSettings settings;
@@ -85,37 +77,6 @@ namespace Mono.Net.Security
                readonly MonoTlsStream tlsStream;
                readonly HttpWebRequest request;
 
-               static bool is_macosx;
-               static bool is_mobile;
-#if !MOBILE
-               static X509RevocationMode revocation_mode;
-#endif
-
-               static ChainValidationHelper ()
-               {
-#if MONOTOUCH
-                       is_macosx = true;
-                       is_mobile = true;
-#elif MONODROID
-                       is_macosx = false;
-                       is_mobile = true;
-#else
-                       is_macosx = System.IO.File.Exists (OSX509Certificates.SecurityLibrary);
-                       is_mobile = false;
-#endif
-
-#if !MOBILE
-                       revocation_mode = X509RevocationMode.NoCheck;
-                       try {
-                               string str = Environment.GetEnvironmentVariable ("MONO_X509_REVOCATION_MODE");
-                               if (String.IsNullOrEmpty (str))
-                                       return;
-                               revocation_mode = (X509RevocationMode)Enum.Parse (typeof(X509RevocationMode), str, true);
-                       } catch {
-                       }
-#endif
-               }
-
                internal static ICertificateValidator GetDefaultValidator (MonoTlsProvider provider, MonoTlsSettings settings)
                {
                        if (settings == null)
@@ -191,7 +152,7 @@ namespace Mono.Net.Security
                                        certValidationCallback = new ServerCertValidationCallback (callback);
                                }
                                certSelectionCallback = Private.CallbackHelpers.MonoToInternal (settings.ClientCertificateSelectionCallback);
-                               fallbackToSPM = settings.UseServicePointManagerCallback;
+                               fallbackToSPM = settings.UseServicePointManagerCallback ?? stream != null;
                        }
 
                        if (stream != null) {
@@ -259,7 +220,7 @@ namespace Mono.Net.Security
                        var certs = new XX509CertificateCollection ();
                        certs.Add (new X509Certificate2 (certificate.GetRawCertData ()));
 
-                       var result = ValidateChain (string.Empty, true, certs, (SslPolicyErrors)errors);
+                       var result = ValidateChain (string.Empty, true, certificate, null, certs, (SslPolicyErrors)errors);
                        if (result == null)
                                return false;
 
@@ -269,7 +230,12 @@ namespace Mono.Net.Security
                public ValidationResult ValidateCertificate (string host, bool serverMode, XX509CertificateCollection certs)
                {
                        try {
-                               var result = ValidateChain (host, serverMode, certs, 0);
+                               X509Certificate leaf;
+                               if (certs != null && certs.Count != 0)
+                                       leaf = certs [0];
+                               else
+                                       leaf = null;
+                               var result = ValidateChain (host, serverMode, leaf, null, certs, 0);
                                if (tlsStream != null)
                                        tlsStream.CertificateValidationFailed = result == null || !result.Trusted || result.UserDenied;
                                return result;
@@ -280,7 +246,43 @@ namespace Mono.Net.Security
                        }
                }
 
-               ValidationResult ValidateChain (string host, bool server, XX509CertificateCollection certs, SslPolicyErrors errors)
+               public ValidationResult ValidateCertificate (string host, bool serverMode, X509Certificate leaf, XX509Chain xchain)
+               {
+                       try {
+                               var chain = xchain;
+                               var result = ValidateChain (host, serverMode, leaf, chain, null, 0);
+                               if (tlsStream != null)
+                                       tlsStream.CertificateValidationFailed = result == null || !result.Trusted || result.UserDenied;
+                               return result;
+                       } catch {
+                               if (tlsStream != null)
+                                       tlsStream.CertificateValidationFailed = true;
+                               throw;
+                       }
+               }
+
+               ValidationResult ValidateChain (string host, bool server, X509Certificate leaf,
+                                               X509Chain chain, XX509CertificateCollection certs,
+                                               SslPolicyErrors errors)
+               {
+                       var oldChain = chain;
+                       var ownsChain = chain == null;
+                       try {
+                               var result = ValidateChain (host, server, leaf, ref chain, certs, errors);
+                               if (chain != oldChain)
+                                       ownsChain = true;
+
+                               return result;
+                       } finally {
+                               // If ValidateChain() changed the chain, then we need to free it.
+                               if (ownsChain && chain != null)
+                                       chain.Dispose ();
+                       }
+               }
+
+               ValidationResult ValidateChain (string host, bool server, X509Certificate leaf,
+                                               ref X509Chain chain, XX509CertificateCollection certs,
+                                               SslPolicyErrors errors)
                {
                        // user_denied is true if the user callback is called and returns false
                        bool user_denied = false;
@@ -288,14 +290,8 @@ namespace Mono.Net.Security
 
                        var hasCallback = certValidationCallback != null || callbackWrapper != null;
 
-                       X509Certificate leaf;
-                       if (certs == null || certs.Count == 0)
-                               leaf = null;
-                       else
-                               leaf = certs [0];
-
                        if (tlsStream != null)
-                               request.ServicePoint.SetServerCertificate (leaf);
+                               request.ServicePoint.UpdateServerCertificate (leaf);
 
                        if (leaf == null) {
                                errors |= SslPolicyErrors.RemoteCertificateNotAvailable;
@@ -312,7 +308,6 @@ namespace Mono.Net.Security
                        ICertificatePolicy policy = ServicePointManager.GetLegacyCertificatePolicy ();
 
                        int status11 = 0; // Error code passed to the obsolete ICertificatePolicy callback
-                       X509Chain chain = null;
 
                        bool wantsChain = SystemCertificateValidator.NeedsChain (settings);
                        if (!wantsChain && hasCallback) {
@@ -320,18 +315,15 @@ namespace Mono.Net.Security
                                        wantsChain = true;
                        }
 
-                       if (wantsChain)
-                               chain = SystemCertificateValidator.CreateX509Chain (certs);
-
-                       if (wantsChain || SystemCertificateValidator.NeedsChain (settings))
-                               SystemCertificateValidator.BuildX509Chain (certs, chain, ref errors, ref status11);
-
                        bool providerValidated = false;
                        if (provider != null && provider.HasCustomSystemCertificateValidator) {
                                var xerrors = (MonoSslPolicyErrors)errors;
-                               var xchain = (XX509Chain)(object)chain;
-                               providerValidated = provider.InvokeSystemCertificateValidator (this, host, server, certs, xchain, out result, ref xerrors, ref status11);
+                               var xchain = chain;
+                               providerValidated = provider.InvokeSystemCertificateValidator (this, host, server, certs, wantsChain, ref xchain, out result, ref xerrors, ref status11);
+                               chain = xchain;
                                errors = (SslPolicyErrors)xerrors;
+                       } else if (wantsChain) {
+                               chain = SystemCertificateValidator.CreateX509Chain (certs);
                        }
 
                        if (!providerValidated)
@@ -363,7 +355,7 @@ namespace Mono.Net.Security
 
                public bool InvokeSystemValidator (string targetHost, bool serverMode, XX509CertificateCollection certificates, XX509Chain xchain, ref MonoSslPolicyErrors xerrors, ref int status11)
                {
-                       X509Chain chain = (X509Chain)(object)xchain;
+                       X509Chain chain = xchain;
                        var errors = (SslPolicyErrors)xerrors;
                        var result = SystemCertificateValidator.Evaluate (settings, targetHost, certificates, chain, ref errors, ref status11);
                        xerrors = (MonoSslPolicyErrors)errors;