Merge pull request #3769 from evincarofautumn/fix-verify-before-allocs
[mono.git] / mcs / class / System / Mono.Net.Security / ChainValidationHelper.cs
index 3f14f95bea696faa323bd543c567215a6ba27832..324192d6af182a898272432a394351099def6971 100644 (file)
@@ -44,8 +44,6 @@ using Mono.Security.Interface;
 using MSX = Mono.Security.X509;
 using Mono.Security.X509.Extensions;
 #endif
-using XX509CertificateCollection = System.Security.Cryptography.X509Certificates.X509CertificateCollection;
-using XX509Chain = System.Security.Cryptography.X509Certificates.X509Chain;
 
 using System;
 using System.Net;
@@ -77,6 +75,8 @@ namespace Mono.Net.Security
                readonly MonoTlsStream tlsStream;
                readonly HttpWebRequest request;
 
+#pragma warning disable 618
+
                internal static ICertificateValidator GetInternalValidator (MonoTlsProvider provider, MonoTlsSettings settings)
                {
                        if (settings == null)
@@ -184,7 +184,9 @@ namespace Mono.Net.Security
                                certValidationCallback = ServicePointManager.ServerCertValidationCallback;
                }
 
-               static X509Certificate DefaultSelectionCallback (string targetHost, XX509CertificateCollection localCertificates, X509Certificate remoteCertificate, string[] acceptableIssuers)
+#pragma warning restore 618
+
+               static X509Certificate DefaultSelectionCallback (string targetHost, X509CertificateCollection localCertificates, X509Certificate remoteCertificate, string[] acceptableIssuers)
                {
                        X509Certificate clientCertificate;
                        if (localCertificates == null || localCertificates.Count == 0)
@@ -207,7 +209,7 @@ namespace Mono.Net.Security
                }
 
                public bool SelectClientCertificate (
-                       string targetHost, XX509CertificateCollection localCertificates, X509Certificate remoteCertificate,
+                       string targetHost, X509CertificateCollection localCertificates, X509Certificate remoteCertificate,
                        string[] acceptableIssuers, out X509Certificate clientCertificate)
                {
                        if (certSelectionCallback == null) {
@@ -219,7 +221,7 @@ namespace Mono.Net.Security
                }
 
                internal X509Certificate SelectClientCertificate (
-                       string targetHost, XX509CertificateCollection localCertificates, X509Certificate remoteCertificate,
+                       string targetHost, X509CertificateCollection localCertificates, X509Certificate remoteCertificate,
                        string[] acceptableIssuers)
                {
                        if (certSelectionCallback == null)
@@ -229,7 +231,7 @@ namespace Mono.Net.Security
 
                internal bool ValidateClientCertificate (X509Certificate certificate, MonoSslPolicyErrors errors)
                {
-                       var certs = new XX509CertificateCollection ();
+                       var certs = new X509CertificateCollection ();
                        certs.Add (new X509Certificate2 (certificate.GetRawCertData ()));
 
                        var result = ValidateChain (string.Empty, true, certificate, null, certs, (SslPolicyErrors)errors);
@@ -239,7 +241,7 @@ namespace Mono.Net.Security
                        return result.Trusted && !result.UserDenied;
                }
 
-               public ValidationResult ValidateCertificate (string host, bool serverMode, XX509CertificateCollection certs)
+               public ValidationResult ValidateCertificate (string host, bool serverMode, X509CertificateCollection certs)
                {
                        try {
                                X509Certificate leaf;
@@ -258,10 +260,9 @@ namespace Mono.Net.Security
                        }
                }
 
-               public ValidationResult ValidateCertificate (string host, bool serverMode, X509Certificate leaf, XX509Chain xchain)
+               public ValidationResult ValidateCertificate (string host, bool serverMode, X509Certificate leaf, X509Chain chain)
                {
                        try {
-                               var chain = xchain;
                                var result = ValidateChain (host, serverMode, leaf, chain, null, 0);
                                if (tlsStream != null)
                                        tlsStream.CertificateValidationFailed = result == null || !result.Trusted || result.UserDenied;
@@ -274,7 +275,7 @@ namespace Mono.Net.Security
                }
 
                ValidationResult ValidateChain (string host, bool server, X509Certificate leaf,
-                                               X509Chain chain, XX509CertificateCollection certs,
+                                               X509Chain chain, X509CertificateCollection certs,
                                                SslPolicyErrors errors)
                {
                        var oldChain = chain;
@@ -293,7 +294,7 @@ namespace Mono.Net.Security
                }
 
                ValidationResult ValidateChain (string host, bool server, X509Certificate leaf,
-                                               ref X509Chain chain, XX509CertificateCollection certs,
+                                               ref X509Chain chain, X509CertificateCollection certs,
                                                SslPolicyErrors errors)
                {
                        // user_denied is true if the user callback is called and returns false
@@ -317,6 +318,13 @@ namespace Mono.Net.Security
                                return new ValidationResult (result, user_denied, 0, (MonoSslPolicyErrors)errors);
                        }
 
+                       // Ignore port number when validating certificates.
+                       if (!string.IsNullOrEmpty (host)) {
+                               var pos = host.IndexOf (':');
+                               if (pos > 0)
+                                       host = host.Substring (0, pos);
+                       }
+
                        ICertificatePolicy policy = ServicePointManager.GetLegacyCertificatePolicy ();
 
                        int status11 = 0; // Error code passed to the obsolete ICertificatePolicy callback
@@ -327,28 +335,19 @@ namespace Mono.Net.Security
                                        wantsChain = true;
                        }
 
-                       bool providerValidated = false;
-                       if (provider != null && provider.HasCustomSystemCertificateValidator) {
-                               var xerrors = (MonoSslPolicyErrors)errors;
-                               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);
-                       }
+                       var xerrors = (MonoSslPolicyErrors)errors;
+                       result = provider.ValidateCertificate (this, host, server, certs, wantsChain, ref chain, ref xerrors, ref status11);
+                       errors = (SslPolicyErrors)xerrors;
 
-                       if (!providerValidated)
-                               result = SystemCertificateValidator.Evaluate (settings, host, certs, chain, ref errors, ref status11);
+                       if (status11 == 0 && errors != 0) {
+                               // TRUST_E_FAIL
+                               status11 = unchecked ((int)0x800B010B);
+                       }
 
                        if (policy != null && (!(policy is DefaultCertificatePolicy) || certValidationCallback == null)) {
                                ServicePoint sp = null;
                                if (request != null)
                                        sp = request.ServicePointNoLock;
-                               if (status11 == 0 && errors != 0) {
-                                       // TRUST_E_FAIL
-                                       status11 = unchecked ((int)0x800B010B);
-                               }
 
                                // pre 2.0 callback
                                result = policy.CheckValidationResult (sp, leaf, request, status11);
@@ -365,9 +364,8 @@ namespace Mono.Net.Security
                        return new ValidationResult (result, user_denied, status11, (MonoSslPolicyErrors)errors);
                }
 
-               public bool InvokeSystemValidator (string targetHost, bool serverMode, XX509CertificateCollection certificates, XX509Chain xchain, ref MonoSslPolicyErrors xerrors, ref int status11)
+               bool InvokeSystemValidator (string targetHost, bool serverMode, X509CertificateCollection certificates, X509Chain chain, ref MonoSslPolicyErrors xerrors, ref int status11)
                {
-                       X509Chain chain = xchain;
                        var errors = (SslPolicyErrors)xerrors;
                        var result = SystemCertificateValidator.Evaluate (settings, targetHost, certificates, chain, ref errors, ref status11);
                        xerrors = (MonoSslPolicyErrors)errors;