[System/TLS]: Switch to the new ChainValidationHelper.
authorMartin Baulig <martin.baulig@xamarin.com>
Wed, 14 Oct 2015 20:22:05 +0000 (16:22 -0400)
committerMartin Baulig <martin.baulig@xamarin.com>
Wed, 14 Oct 2015 23:26:06 +0000 (19:26 -0400)
* Removed Mono.Security.Protocol.Tls.ValidationResult, use
  Mono.Security.Interface instead.  This is an API breaking
  change, but you can fix your application by simply adding
  the new using directive.

  The rationale behind this is to avoid a dependency on the
  Mono.Security.Protocol.Tls namespace when building and
  related classes when building the new TLS stack.

* Enable ChainValidationHelper in WebConnection, LegacySslStream
  and SslStream.

  The custom conditionals that were previously required for the
  mobile profiles are now gone as ChainValidationHelper already
  handles that internally.

* This is an internal API, the public front-end is
  Mono.Security.Interface.CertificateValidationHelper.

  CertificateValidationHelper can be used to access the system
  certificate validator on OS X and iOS; we do not compute the
  X509Chain on these platforms as it's not supported by the OS.

(cherry picked from commit 9713f35878dd90fe87423b5052b4f82ddc0b87f0)

mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerCertificate.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/SslClientStream.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/SslServerStream.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/SslStreamBase.cs
mcs/class/System/Mono.Net.Security/LegacySslStream.cs
mcs/class/System/System.Net.Security/SslStream.cs
mcs/class/System/System.Net/ServicePointManager.cs
mcs/class/System/System.Net/WebConnection.cs

index dae12cc401347bd88c129e381b7f5202c8f33311..a96b415ef0c56c338ae57dedbe6b9e27f53d3645 100644 (file)
@@ -33,6 +33,8 @@ using X509Cert = System.Security.Cryptography.X509Certificates;
 using Mono.Security.X509;
 using Mono.Security.X509.Extensions;
 
+using Mono.Security.Interface;
+
 namespace Mono.Security.Protocol.Tls.Handshake.Client
 {
        internal class TlsServerCertificate : HandshakeMessage
index 2936122c4bd9d5826363fc35f453beab2145405b..39680547b0568d7a024a592e16d9c4ebf4f935de 100644 (file)
@@ -32,6 +32,7 @@ using System.Security.Cryptography.X509Certificates;
 using System.Threading;
 
 using Mono.Security.Protocol.Tls.Handshake;
+using Mono.Security.Interface;
 
 namespace Mono.Security.Protocol.Tls
 {
@@ -46,36 +47,6 @@ namespace Mono.Security.Protocol.Tls
                X509Certificate certificate, 
                int[]                   certificateErrors);
 
-#if INSIDE_SYSTEM
-       internal
-#else
-       public
-#endif
-       class ValidationResult {
-               bool trusted;
-               bool user_denied;
-               int error_code;
-
-               public ValidationResult (bool trusted, bool user_denied, int error_code)
-               {
-                       this.trusted = trusted;
-                       this.user_denied = user_denied;
-                       this.error_code = error_code;
-               }
-
-               public bool Trusted {
-                       get { return trusted; }
-               }
-
-               public bool UserDenied {
-                       get { return user_denied; }
-               }
-
-               public int ErrorCode {
-                       get { return error_code; }
-               }
-       }
-
 #if INSIDE_SYSTEM
        internal
 #else
index fb8ede4b90537578d7196e259638dc9185d9f9e1..f93ab4425e02609d16ed3a6aedb31a491b312679 100644 (file)
@@ -31,6 +31,7 @@ using System.Security.Cryptography;
 using System.Security.Cryptography.X509Certificates;
 
 using Mono.Security.Protocol.Tls.Handshake;
+using Mono.Security.Interface;
 
 namespace Mono.Security.Protocol.Tls
 {
index 41271cdb3267a0cca279e766a3167b6143da7c96..384fbaea0e8a50a4cc3439d603de04cc6e17af50 100644 (file)
@@ -31,6 +31,8 @@ using System.Security.Cryptography;
 using System.Security.Cryptography.X509Certificates;
 using System.Threading;
 
+using Mono.Security.Interface;
+
 namespace Mono.Security.Protocol.Tls
 {
 #if INSIDE_SYSTEM
index ae292c03479a3862d2dc2a6dd342b5ab0b2c41f8..c5eff6948511472d57fcc9bd43cec37dbeb9597f 100644 (file)
@@ -318,6 +318,7 @@ namespace Mono.Net.Security
                #endregion // Properties
 
                #region Methods
+
 /*
                AsymmetricAlgorithm GetPrivateKey (X509Certificate cert, string targetHost)
                {
index 02cdf8d24a091e30c0676c4d800b0f330078b34a..06d765fbddf273b00a05642198ae335c2c39f8b1 100644 (file)
@@ -47,12 +47,14 @@ using MonoHashAlgorithmType = MonoSecurity::Mono.Security.Protocol.Tls.HashAlgor
 using MonoExchangeAlgorithmType = MonoSecurity::Mono.Security.Protocol.Tls.ExchangeAlgorithmType;
 using MonoSecurityProtocolType = MonoSecurity::Mono.Security.Protocol.Tls.SecurityProtocolType;
 using MonoSecurity::Mono.Security.Protocol.Tls;
+using MonoSecurity::Mono.Security.Interface;
 #else
 using MonoCipherAlgorithmType = Mono.Security.Protocol.Tls.CipherAlgorithmType;
 using MonoHashAlgorithmType = Mono.Security.Protocol.Tls.HashAlgorithmType;
 using MonoExchangeAlgorithmType = Mono.Security.Protocol.Tls.ExchangeAlgorithmType;
 using MonoSecurityProtocolType = Mono.Security.Protocol.Tls.SecurityProtocolType;
 using Mono.Security.Protocol.Tls;
+using Mono.Security.Interface;
 #endif
 #if MONO_X509_ALIAS
 using X509CertificateCollection = PrebuiltSystem::System.Security.Cryptography.X509Certificates.X509CertificateCollection;
@@ -71,6 +73,7 @@ using System.Security.Principal;
 using System.Security.Cryptography;
 
 using System.Threading.Tasks;
+using MNS = Mono.Net.Security;
 
 namespace System.Net.Security 
 {
@@ -381,56 +384,13 @@ namespace System.Net.Security
                                return null;
                        };
 
-#if MONOTOUCH || MONODROID
                        // Even if validation_callback is null this allows us to verify requests where the user
                        // does not provide a verification callback but attempts to authenticate with the website
                        // as a client (see https://bugzilla.xamarin.com/show_bug.cgi?id=18962 for an example)
-                       var helper = new ServicePointManager.ChainValidationHelper (this, targetHost);
-                       helper.ServerCertificateValidationCallback = validation_callback;
-                       s.ServerCertValidation2 += new CertificateValidationCallback2 (helper.ValidateChain);
-#else
-                       if (validation_callback != null) {
-                               s.ServerCertValidationDelegate = delegate (X509Certificate cert, int [] certErrors) {
-                                       X509Chain chain = new X509Chain ();
-                                       X509Certificate2 x2 = (cert as X509Certificate2);
-                                       if (x2 == null)
-                                               x2 = new X509Certificate2 (cert);
-
-                                       if (!ServicePointManager.CheckCertificateRevocationList)
-                                               chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
-
-                                       // SSL specific checks (done by Mono.Security.dll SSL/TLS implementation) 
-                                       SslPolicyErrors errors = SslPolicyErrors.None;
-                                       foreach (int i in certErrors) {
-                                               switch (i) {
-                                               case -2146762490: // CERT_E_PURPOSE
-                                                       errors |= SslPolicyErrors.RemoteCertificateNotAvailable;
-                                                       break;
-                                               case -2146762481: // CERT_E_CN_NO_MATCH
-                                                       errors |= SslPolicyErrors.RemoteCertificateNameMismatch;
-                                                       break;
-                                               default:
-                                                       errors |= SslPolicyErrors.RemoteCertificateChainErrors;
-                                                       break;
-                                               }
-                                       }
-
-                                       chain.Build (x2);
-
-                                       // non-SSL specific X509 checks (i.e. RFC3280 related checks)
-                                       foreach (X509ChainStatus status in chain.ChainStatus) {
-                                               if (status.Status == X509ChainStatusFlags.NoError)
-                                                       continue;
-                                               if ((status.Status & X509ChainStatusFlags.PartialChain) != 0)
-                                                       errors |= SslPolicyErrors.RemoteCertificateNotAvailable;
-                                               else
-                                                       errors |= SslPolicyErrors.RemoteCertificateChainErrors;
-                                       }
-
-                                       return validation_callback (this, cert, chain, errors);
-                               };
-                       }
-#endif
+                       var settings = new MonoTlsSettings ();
+                       settings.ServerCertificateValidationCallback = MNS.Private.CallbackHelpers.PublicToMono (validation_callback);
+                       var helper = MNS.ChainValidationHelper.Create (ref settings, null);
+                       s.ServerCertValidation2 += (certs) => helper.ValidateChain (targetHost, certs);
                        if (selection_callback != null)
                                s.ClientCertSelectionDelegate = OnCertificateSelection;
 
index b0fdf1cbd5a0fae25386637e10a063a4dbcac851..1d6b80467278355f7759d901b3cc44fec869fbe1 100644 (file)
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-#if SECURITY_DEP
-
-#if MONOTOUCH || MONODROID
-using Mono.Security.Protocol.Tls;
-using MSX = Mono.Security.X509;
-using Mono.Security.X509.Extensions;
-#else
-extern alias MonoSecurity;
-using MonoSecurity::Mono.Security.X509.Extensions;
-using MonoSecurity::Mono.Security.Protocol.Tls;
-using MSX = MonoSecurity::Mono.Security.X509;
-#endif
-
-using System.Text.RegularExpressions;
-#endif
-
 using System;
 using System.Threading;
 using System.Collections;
@@ -390,382 +374,6 @@ namespace System.Net
                                }
                        }
                }
-               
-#if SECURITY_DEP
-               internal class ChainValidationHelper {
-                       object sender;
-                       string host;
-                       RemoteCertificateValidationCallback cb;
-
-#if !MONOTOUCH
-                       static bool is_macosx = System.IO.File.Exists (OSX509Certificates.SecurityLibrary);
-                       static X509RevocationMode revocation_mode;
-
-                       static ChainValidationHelper ()
-                       {
-                               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
-
-                       public ChainValidationHelper (object sender, string hostName)
-                       {
-                               this.sender = sender;
-                               host = hostName;
-                       }
-
-                       public RemoteCertificateValidationCallback ServerCertificateValidationCallback {
-                               get {
-                                       if (cb == null)
-                                               cb = ServicePointManager.ServerCertificateValidationCallback;
-                                       return cb;
-                               }
-                               set { cb = value; }
-                       }
-
-                       // Used when the obsolete ICertificatePolicy is set to DefaultCertificatePolicy
-                       // and the new ServerCertificateValidationCallback is not null
-                       internal ValidationResult ValidateChain (MSX.X509CertificateCollection certs)
-                       {
-                               // user_denied is true if the user callback is called and returns false
-                               bool user_denied = false;
-                               if (certs == null || certs.Count == 0)
-                                       return null;
-
-                               ICertificatePolicy policy = ServicePointManager.CertificatePolicy;
-
-                               X509Certificate2 leaf = new X509Certificate2 (certs [0].RawData);
-                               int status11 = 0; // Error code passed to the obsolete ICertificatePolicy callback
-                               SslPolicyErrors errors = 0;
-                               X509Chain chain = null;
-                               bool result = false;
-#if MONOTOUCH
-                               // The X509Chain is not really usable with MonoTouch (since the decision is not based on this data)
-                               // However if someone wants to override the results (good or bad) from iOS then they will want all
-                               // the certificates that the server provided (which generally does not include the root) so, only  
-                               // if there's a user callback, we'll create the X509Chain but won't build it
-                               // ref: https://bugzilla.xamarin.com/show_bug.cgi?id=7245
-                               if (ServerCertificateValidationCallback != null) {
-#endif
-                               chain = new X509Chain ();
-                               chain.ChainPolicy = new X509ChainPolicy ();
-#if !MONOTOUCH
-                               chain.ChainPolicy.RevocationMode = revocation_mode;
-#endif
-                               for (int i = 1; i < certs.Count; i++) {
-                                       X509Certificate2 c2 = new X509Certificate2 (certs [i].RawData);
-                                       chain.ChainPolicy.ExtraStore.Add (c2);
-                               }
-#if MONOTOUCH
-                               }
-#else
-                               try {
-                                       if (!chain.Build (leaf))
-                                               errors |= GetErrorsFromChain (chain);
-                               } catch (Exception e) {
-                                       Console.Error.WriteLine ("ERROR building certificate chain: {0}", e);
-                                       Console.Error.WriteLine ("Please, report this problem to the Mono team");
-                                       errors |= SslPolicyErrors.RemoteCertificateChainErrors;
-                               }
-
-                               // for OSX and iOS we're using the native API to check for the SSL server policy and host names
-                               if (!is_macosx) {
-                                       if (!CheckCertificateUsage (leaf)) {
-                                               errors |= SslPolicyErrors.RemoteCertificateChainErrors;
-                                               status11 = -2146762490; //CERT_E_PURPOSE 0x800B0106
-                                       }
-
-                                       if (!CheckServerIdentity (certs [0], host)) {
-                                               errors |= SslPolicyErrors.RemoteCertificateNameMismatch;
-                                               status11 = -2146762481; // CERT_E_CN_NO_MATCH 0x800B010F
-                                       }
-                               } else {
-#endif
-                                       // Attempt to use OSX certificates
-                                       // Ideally we should return the SecTrustResult
-                                       OSX509Certificates.SecTrustResult trustResult = OSX509Certificates.SecTrustResult.Deny;
-                                       try {
-                                               trustResult = OSX509Certificates.TrustEvaluateSsl (certs, host);
-                                               // We could use the other values of trustResult to pass this extra information
-                                               // to the .NET 2 callback for values like SecTrustResult.Confirm
-                                               result = (trustResult == OSX509Certificates.SecTrustResult.Proceed ||
-                                                                 trustResult == OSX509Certificates.SecTrustResult.Unspecified);
-                                       } catch {
-                                               // Ignore
-                                       }
-                                       
-                                       if (result) {
-                                               // TrustEvaluateSsl was successful so there's no trust error
-                                               // IOW we discard our own chain (since we trust OSX one instead)
-                                               errors = 0;
-                                       } else {
-                                               // callback and DefaultCertificatePolicy needs this since 'result' is not specified
-                                               status11 = (int) trustResult;
-                                               errors |= SslPolicyErrors.RemoteCertificateChainErrors;
-                                       }
-#if !MONOTOUCH
-                               }
-#endif
-
-#if MONODROID && SECURITY_DEP
-                               result = AndroidPlatform.TrustEvaluateSsl (certs, sender, leaf, chain, errors);
-                               if (result) {
-                                       // chain.Build() + GetErrorsFromChain() (above) will ALWAYS fail on
-                                       // Android (there are no mozroots or preinstalled root certificates),
-                                       // thus `errors` will ALWAYS have RemoteCertificateChainErrors.
-                                       // Android just verified the chain; clear RemoteCertificateChainErrors.
-                                       errors  &= ~SslPolicyErrors.RemoteCertificateChainErrors;
-                               }
-#endif
-
-                               if (policy != null && (!(policy is DefaultCertificatePolicy) || cb == null)) {
-                                       ServicePoint sp = null;
-                                       HttpWebRequest req = sender as HttpWebRequest;
-                                       if (req != null)
-                                               sp = req.ServicePointNoLock;
-                                       if (status11 == 0 && errors != 0)
-                                               status11 = GetStatusFromChain (chain);
-
-                                       // pre 2.0 callback
-                                       result = policy.CheckValidationResult (sp, leaf, req, status11);
-                                       user_denied = !result && !(policy is DefaultCertificatePolicy);
-                               }
-                               // If there's a 2.0 callback, it takes precedence
-                               if (ServerCertificateValidationCallback != null) {
-                                       result = ServerCertificateValidationCallback (sender, leaf, chain, errors);
-                                       user_denied = !result;
-                               }
-                               return new ValidationResult (result, user_denied, status11);
-                       }
-
-                       static int GetStatusFromChain (X509Chain chain)
-                       {
-                               long result = 0;
-                               foreach (var status in chain.ChainStatus) {
-                                       X509ChainStatusFlags flags = status.Status;
-                                       if (flags == X509ChainStatusFlags.NoError)
-                                               continue;
-
-                                       // CERT_E_EXPIRED
-                                       if ((flags & X509ChainStatusFlags.NotTimeValid) != 0) result = 0x800B0101;
-                                       // CERT_E_VALIDITYPERIODNESTING
-                                       else if ((flags & X509ChainStatusFlags.NotTimeNested) != 0) result = 0x800B0102;
-                                       // CERT_E_REVOKED
-                                       else if ((flags & X509ChainStatusFlags.Revoked) != 0) result = 0x800B010C;
-                                       // TRUST_E_CERT_SIGNATURE
-                                       else if ((flags & X509ChainStatusFlags.NotSignatureValid) != 0) result = 0x80096004;
-                                       // CERT_E_WRONG_USAGE
-                                       else if ((flags & X509ChainStatusFlags.NotValidForUsage) != 0) result = 0x800B0110;
-                                       // CERT_E_UNTRUSTEDROOT
-                                       else if ((flags & X509ChainStatusFlags.UntrustedRoot) != 0) result = 0x800B0109;
-                                       // CRYPT_E_NO_REVOCATION_CHECK
-                                       else if ((flags & X509ChainStatusFlags.RevocationStatusUnknown) != 0) result = 0x80092012;
-                                       // CERT_E_CHAINING
-                                       else if ((flags & X509ChainStatusFlags.Cyclic) != 0) result = 0x800B010A;
-                                       // TRUST_E_FAIL - generic
-                                       else if ((flags & X509ChainStatusFlags.InvalidExtension) != 0) result = 0x800B010B;
-                                       // CERT_E_UNTRUSTEDROOT
-                                       else if ((flags & X509ChainStatusFlags.InvalidPolicyConstraints) != 0) result = 0x800B010D;
-                                       // TRUST_E_BASIC_CONSTRAINTS
-                                       else if ((flags & X509ChainStatusFlags.InvalidBasicConstraints) != 0) result = 0x80096019;
-                                       // CERT_E_INVALID_NAME
-                                       else if ((flags & X509ChainStatusFlags.InvalidNameConstraints) != 0) result = 0x800B0114;
-                                       // CERT_E_INVALID_NAME
-                                       else if ((flags & X509ChainStatusFlags.HasNotSupportedNameConstraint) != 0) result = 0x800B0114;
-                                       // CERT_E_INVALID_NAME
-                                       else if ((flags & X509ChainStatusFlags.HasNotDefinedNameConstraint) != 0) result = 0x800B0114;
-                                       // CERT_E_INVALID_NAME
-                                       else if ((flags & X509ChainStatusFlags.HasNotPermittedNameConstraint) != 0) result = 0x800B0114;
-                                       // CERT_E_INVALID_NAME
-                                       else if ((flags & X509ChainStatusFlags.HasExcludedNameConstraint) != 0) result = 0x800B0114;
-                                       // CERT_E_CHAINING
-                                       else if ((flags & X509ChainStatusFlags.PartialChain) != 0) result = 0x800B010A;
-                                       // CERT_E_EXPIRED
-                                       else if ((flags & X509ChainStatusFlags.CtlNotTimeValid) != 0) result = 0x800B0101;
-                                       // TRUST_E_CERT_SIGNATURE
-                                       else if ((flags & X509ChainStatusFlags.CtlNotSignatureValid) != 0) result = 0x80096004;
-                                       // CERT_E_WRONG_USAGE
-                                       else if ((flags & X509ChainStatusFlags.CtlNotValidForUsage) != 0) result = 0x800B0110;
-                                       // CRYPT_E_NO_REVOCATION_CHECK
-                                       else if ((flags & X509ChainStatusFlags.OfflineRevocation) != 0) result = 0x80092012;
-                                       // CERT_E_ISSUERCHAINING
-                                       else if ((flags & X509ChainStatusFlags.NoIssuanceChainPolicy) != 0) result = 0x800B0107;
-                                       else result = 0x800B010B; // TRUST_E_FAIL - generic
-
-                                       break; // Exit the loop on the first error
-                               }
-                               return (int) result;
-                       }
-#if !MONOTOUCH
-                       static SslPolicyErrors GetErrorsFromChain (X509Chain chain)
-                       {
-                               SslPolicyErrors errors = SslPolicyErrors.None;
-                               foreach (var status in chain.ChainStatus) {
-                                       if (status.Status == X509ChainStatusFlags.NoError)
-                                               continue;
-                                       errors |= SslPolicyErrors.RemoteCertificateChainErrors;
-                                       break;
-                               }
-                               return errors;
-                       }
-
-                       static X509KeyUsageFlags s_flags = X509KeyUsageFlags.DigitalSignature  | 
-                                                       X509KeyUsageFlags.KeyAgreement |
-                                                       X509KeyUsageFlags.KeyEncipherment;
-                       // Adapted to System 2.0+ from TlsServerCertificate.cs
-                       //------------------------------
-                       // Note: this method only works for RSA certificates
-                       // DH certificates requires some changes - does anyone use one ?
-                       static bool CheckCertificateUsage (X509Certificate2 cert) 
-                       {
-                               try {
-                                       // certificate extensions are required for this
-                                       // we "must" accept older certificates without proofs
-                                       if (cert.Version < 3)
-                                               return true;
-
-                                       X509KeyUsageExtension kux = (cert.Extensions ["2.5.29.15"] as X509KeyUsageExtension);
-                                       X509EnhancedKeyUsageExtension eku = (cert.Extensions ["2.5.29.37"] as X509EnhancedKeyUsageExtension);
-                                       if (kux != null && eku != null) {
-                                               // RFC3280 states that when both KeyUsageExtension and 
-                                               // ExtendedKeyUsageExtension are present then BOTH should
-                                               // be valid
-                                               if ((kux.KeyUsages & s_flags) == 0)
-                                                       return false;
-                                               return eku.EnhancedKeyUsages ["1.3.6.1.5.5.7.3.1"] != null ||
-                                                       eku.EnhancedKeyUsages ["2.16.840.1.113730.4.1"] != null;
-                                       } else if (kux != null) {
-                                               return ((kux.KeyUsages & s_flags) != 0);
-                                       } else if (eku != null) {
-                                               // Server Authentication (1.3.6.1.5.5.7.3.1) or
-                                               // Netscape Server Gated Crypto (2.16.840.1.113730.4)
-                                               return eku.EnhancedKeyUsages ["1.3.6.1.5.5.7.3.1"] != null ||
-                                                       eku.EnhancedKeyUsages ["2.16.840.1.113730.4.1"] != null;
-                                       }
-
-                                       // last chance - try with older (deprecated) Netscape extensions
-                                       X509Extension ext = cert.Extensions ["2.16.840.1.113730.1.1"];
-                                       if (ext != null) {
-                                               string text = ext.NetscapeCertType (false);
-                                               return text.IndexOf ("SSL Server Authentication", StringComparison.Ordinal) != -1;
-                                       }
-                                       return true;
-                               } catch (Exception e) {
-                                       Console.Error.WriteLine ("ERROR processing certificate: {0}", e);
-                                       Console.Error.WriteLine ("Please, report this problem to the Mono team");
-                                       return false;
-                               }
-                       }
-
-                       // RFC2818 - HTTP Over TLS, Section 3.1
-                       // http://www.ietf.org/rfc/rfc2818.txt
-                       // 
-                       // 1.   if present MUST use subjectAltName dNSName as identity
-                       // 1.1.         if multiples entries a match of any one is acceptable
-                       // 1.2.         wildcard * is acceptable
-                       // 2.   URI may be an IP address -> subjectAltName.iPAddress
-                       // 2.1.         exact match is required
-                       // 3.   Use of the most specific Common Name (CN=) in the Subject
-                       // 3.1          Existing practice but DEPRECATED
-                       static bool CheckServerIdentity (MSX.X509Certificate cert, string targetHost) 
-                       {
-                               try {
-                                       MSX.X509Extension ext = cert.Extensions ["2.5.29.17"];
-                                       // 1. subjectAltName
-                                       if (ext != null) {
-                                               SubjectAltNameExtension subjectAltName = new SubjectAltNameExtension (ext);
-                                               // 1.1 - multiple dNSName
-                                               foreach (string dns in subjectAltName.DNSNames) {
-                                                       // 1.2 TODO - wildcard support
-                                                       if (Match (targetHost, dns))
-                                                               return true;
-                                               }
-                                               // 2. ipAddress
-                                               foreach (string ip in subjectAltName.IPAddresses) {
-                                                       // 2.1. Exact match required
-                                                       if (ip == targetHost)
-                                                               return true;
-                                               }
-                                       }
-                                       // 3. Common Name (CN=)
-                                       return CheckDomainName (cert.SubjectName, targetHost);
-                               } catch (Exception e) {
-                                       Console.Error.WriteLine ("ERROR processing certificate: {0}", e);
-                                       Console.Error.WriteLine ("Please, report this problem to the Mono team");
-                                       return false;
-                               }
-                       }
-
-                       static bool CheckDomainName (string subjectName, string targetHost)
-                       {
-                               string  domainName = String.Empty;
-                               Regex search = new Regex(@"CN\s*=\s*([^,]*)");
-                               MatchCollection elements = search.Matches(subjectName);
-                               if (elements.Count == 1) {
-                                       if (elements[0].Success)
-                                               domainName = elements[0].Groups[1].Value.ToString();
-                               }
-
-                               return Match (targetHost, domainName);
-                       }
-
-                       // ensure the pattern is valid wrt to RFC2595 and RFC2818
-                       // http://www.ietf.org/rfc/rfc2595.txt
-                       // http://www.ietf.org/rfc/rfc2818.txt
-                       static bool Match (string hostname, string pattern)
-                       {
-                               // check if this is a pattern
-                               int index = pattern.IndexOf ('*');
-                               if (index == -1) {
-                                       // not a pattern, do a direct case-insensitive comparison
-                                       return (String.Compare (hostname, pattern, true, CultureInfo.InvariantCulture) == 0);
-                               }
-
-                               // check pattern validity
-                               // A "*" wildcard character MAY be used as the left-most name component in the certificate.
-
-                               // unless this is the last char (valid)
-                               if (index != pattern.Length - 1) {
-                                       // then the next char must be a dot .'.
-                                       if (pattern [index + 1] != '.')
-                                               return false;
-                               }
-
-                               // only one (A) wildcard is supported
-                               int i2 = pattern.IndexOf ('*', index + 1);
-                               if (i2 != -1)
-                                       return false;
-
-                               // match the end of the pattern
-                               string end = pattern.Substring (index + 1);
-                               int length = hostname.Length - end.Length;
-                               // no point to check a pattern that is longer than the hostname
-                               if (length <= 0)
-                                       return false;
-
-                               if (String.Compare (hostname, length, end, 0, end.Length, true, CultureInfo.InvariantCulture) != 0)
-                                       return false;
-
-                               // special case, we start with the wildcard
-                               if (index == 0) {
-                                       // ensure we hostname non-matched part (start) doesn't contain a dot
-                                       int i3 = hostname.IndexOf ('.');
-                                       return ((i3 == -1) || (i3 >= (hostname.Length - end.Length)));
-                               }
-
-                               // match the start of the pattern
-                               string start = pattern.Substring (0, index);
-                               return (String.Compare (hostname, 0, start, 0, start.Length, true, CultureInfo.InvariantCulture) == 0);
-                       }
-#endif
-               }
-#endif
        }
 }
 
index 7ce79ab7ca3849f88a9effdd6e1d5ae4815bf738..5fb20ed5f0ae9a675b06bcb057e0147cac3231bf 100644 (file)
@@ -48,6 +48,8 @@ using System.Text;
 using System.Threading;
 using System.Diagnostics;
 
+using Mono.Net.Security;
+
 namespace System.Net
 {
        enum ReadState
@@ -458,8 +460,8 @@ namespace System.Net
                                                nstream = (Stream) Activator.CreateInstance (sslStream, args);
 #endif
                                                SslClientStream scs = (SslClientStream) nstream;
-                                               var helper = new ServicePointManager.ChainValidationHelper (request, request.Address.Host);
-                                               scs.ServerCertValidation2 += new CertificateValidationCallback2 (helper.ValidateChain);
+                                               var helper = new ChainValidationHelper (request);
+                                               scs.ServerCertValidation2 += (certs) => helper.ValidateChain (request.Address.Host, certs);
 #endif
                                                certsAvailable = false;
                                        }