Merge pull request #2802 from BrzVlad/feature-evacuation-opt2
[mono.git] / mcs / class / Mono.Security / Mono.Security.Interface / CertificateValidationHelper.cs
index 6d8d1bbff662f0cfaefa94eda375e7c197ccabe1..fd392b409e5a4bef6de68f174911b79f638997be 100644 (file)
@@ -29,25 +29,21 @@ using System.IO;
 using System.Net;
 using System.Net.Security;
 using System.Threading;
-using System.Reflection;
 using System.Security.Cryptography.X509Certificates;
 using Mono.Security.Protocol.Tls;
 using MX = Mono.Security.X509;
-#if MOBILE
 using Mono.Net.Security;
-#endif
 
 namespace Mono.Security.Interface
 {
-       #if (!MONOTOUCH && !MONODROID) || INSIDE_SYSTEM
        public class ValidationResult
        {
                bool trusted;
                bool user_denied;
                int error_code;
-               MonoSslPolicyErrors policy_errors;
+               MonoSslPolicyErrors? policy_errors;
 
-               public ValidationResult (bool trusted, bool user_denied, int error_code, MonoSslPolicyErrors policy_errors)
+               public ValidationResult (bool trusted, bool user_denied, int error_code, MonoSslPolicyErrors? policy_errors)
                {
                        this.trusted = trusted;
                        this.user_denied = user_denied;
@@ -55,6 +51,13 @@ namespace Mono.Security.Interface
                        this.policy_errors = policy_errors;
                }
 
+               internal 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; }
                }
@@ -67,7 +70,7 @@ namespace Mono.Security.Interface
                        get { return error_code; }
                }
 
-               public MonoSslPolicyErrors PolicyErrors {
+               public MonoSslPolicyErrors? PolicyErrors {
                        get { return policy_errors; }
                }
        }
@@ -81,53 +84,56 @@ namespace Mono.Security.Interface
                        get;
                }
 
-               X509Certificate SelectClientCertificate (
+               /*
+                * Returns `true` if a client certificate has been selected (which could be `null`).
+                */
+               bool SelectClientCertificate (
                        string targetHost, X509CertificateCollection localCertificates, X509Certificate remoteCertificate,
-                       string[] acceptableIssuers);
+                       string[] acceptableIssuers, out X509Certificate clientCertificate);
 
-               ValidationResult ValidateChain (string targetHost, X509CertificateCollection certificates);
+               /*
+                * If @serverMode is true, then we're a server and want to validate a certificate that we received from a client.
+                */
+               ValidationResult ValidateCertificate (string targetHost, bool serverMode, X509CertificateCollection certificates);
+       }
 
-               ValidationResult ValidateClientCertificate (X509CertificateCollection certificates);
+       internal interface ICertificateValidator2 : ICertificateValidator
+       {
+               /*
+                * Internal use only.
+                */
+               ValidationResult ValidateCertificate (string targetHost, bool serverMode, X509Certificate leaf, X509Chain chain);
+
+               /*
+                * On OS X and Mobile, the @chain will be initialized with the @certificates, but not actually built.
+                */
+               bool InvokeSystemValidator (
+                       string targetHost, bool serverMode, X509CertificateCollection certificates,
+                       X509Chain chain, ref MonoSslPolicyErrors errors, ref int status11);
        }
-       #endif
 
-       #if !INSIDE_SYSTEM
-       public
-       #endif
-       static class CertificateValidationHelper
+       public static class CertificateValidationHelper
        {
                const string SecurityLibrary = "/System/Library/Frameworks/Security.framework/Security";
                static readonly bool noX509Chain;
-
-               #if !INSIDE_SYSTEM
-               const string InternalHelperTypeName = "Mono.Net.Security.ChainValidationHelper";
-               static readonly Type internalHelperType;
-               static readonly MethodInfo createMethod;
-               static readonly MethodInfo validateClientCertificateMethod;
-               static readonly MethodInfo validateChainMethod;
-               #endif
+               static readonly bool supportsTrustAnchors;
 
                static CertificateValidationHelper ()
                {
-                       #if !INSIDE_SYSTEM
-                       internalHelperType = Type.GetType (InternalHelperTypeName + ", " + Consts.AssemblySystem, true);
-                       if (internalHelperType == null)
-                               throw new NotSupportedException ();
-                       createMethod = internalHelperType.GetMethod ("GetDefaultValidator", BindingFlags.Static | BindingFlags.NonPublic);
-                       if (createMethod == null)
-                               throw new NotSupportedException ();
-                       validateClientCertificateMethod = internalHelperType.GetMethod ("ValidateClientCertificate", BindingFlags.Instance | BindingFlags.Public);
-                       if (validateClientCertificateMethod == null)
-                               throw new NotSupportedException ();
-                       validateChainMethod = internalHelperType.GetMethod ("ValidateChain", BindingFlags.Instance | BindingFlags.Public);
-                       if (validateChainMethod == null)
-                               throw new NotSupportedException ();
-                       #endif
-
                        #if MONOTOUCH || XAMMAC
                        noX509Chain = true;
+                       supportsTrustAnchors = true;
+                       #elif MONODROID
+                       noX509Chain = true;
+                       supportsTrustAnchors = false;
                        #else
-                       noX509Chain = File.Exists (SecurityLibrary);
+                       if (File.Exists (SecurityLibrary)) {
+                               noX509Chain = true;
+                               supportsTrustAnchors = true;
+                       } else {
+                               noX509Chain = false;
+                               supportsTrustAnchors = false;
+                       }
                        #endif
                }
 
@@ -135,24 +141,24 @@ namespace Mono.Security.Interface
                        get { return !noX509Chain; }
                }
 
-               internal static ICertificateValidator GetDefaultValidator (MonoTlsSettings settings)
+               public static bool SupportsTrustAnchors {
+                       get { return supportsTrustAnchors; }
+               }
+
+               /*
+                * Internal API, intended to be used by MonoTlsProvider implementations.
+                */
+               internal static ICertificateValidator2 GetDefaultValidator (MonoTlsSettings settings, MonoTlsProvider provider)
                {
-                       #if INSIDE_SYSTEM
-                       #if MARTIN_FIXME
-                       return ChainValidationHelper.GetDefaultValidator (settings);
-                       #else
-                       throw new NotImplementedException ();
-                       #endif
-                       #else
-                       return (ICertificateValidator)createMethod.Invoke (null, new object[] { settings });
-                       #endif
+                       return (ICertificateValidator2)NoReflectionHelper.GetDefaultCertificateValidator (provider, settings);
                }
 
-               #if !INSIDE_SYSTEM
-               public static ICertificateValidator GetValidator (MonoTlsSettings settings)
+               /*
+                * Use this overloaded version in user code.
+                */
+               public static ICertificateValidator GetValidator (MonoTlsSettings settings, MonoTlsProvider provider = null)
                {
-                       return GetDefaultValidator (settings);
+                       return GetDefaultValidator (settings, provider);
                }
-               #endif
        }
 }