Esempio n. 1
0
        bool InvokeCallback(X509Certificate leaf, X509Chain chain, SslPolicyErrors errors)
        {
            object sender = null;

            if (request != null)
            {
                sender = request;
            }
            else if (owner != null && owner.TryGetTarget(out var sslStream))
            {
                sender = sslStream;
            }

            return(certValidationCallback.Invoke(sender, leaf, chain, errors));
        }
Esempio n. 2
0
        ValidationResult ValidateChain(string host, bool server, X509Certificate leaf,
                                       ref X509Chain chain, X509CertificateCollection certs,
                                       SslPolicyErrors errors)
        {
            // user_denied is true if the user callback is called and returns false
            bool user_denied = false;
            bool result      = false;

            var hasCallback = certValidationCallback != null || callbackWrapper != null;

            if (tlsStream != null)
            {
                request.ServicePoint.UpdateServerCertificate(leaf);
            }

            if (leaf == null)
            {
                errors |= SslPolicyErrors.RemoteCertificateNotAvailable;
                if (hasCallback)
                {
                    if (callbackWrapper != null)
                    {
                        result = callbackWrapper.Invoke(certValidationCallback, leaf, null, (MonoSslPolicyErrors)errors);
                    }
                    else
                    {
                        result = certValidationCallback.Invoke(sender, leaf, null, errors);
                    }
                    user_denied = !result;
                }
                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

            bool wantsChain = SystemCertificateValidator.NeedsChain(settings);

            if (!wantsChain && hasCallback)
            {
                if (settings == null || settings.CallbackNeedsCertificateChain)
                {
                    wantsChain = true;
                }
            }

            var xerrors = (MonoSslPolicyErrors)errors;

            result = provider.ValidateCertificate(this, host, server, certs, wantsChain, ref chain, ref xerrors, ref status11);
            errors = (SslPolicyErrors)xerrors;

            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;
                }

                // pre 2.0 callback
                result      = policy.CheckValidationResult(sp, leaf, request, status11);
                user_denied = !result && !(policy is DefaultCertificatePolicy);
            }
            // If there's a 2.0 callback, it takes precedence
            if (hasCallback)
            {
                if (callbackWrapper != null)
                {
                    result = callbackWrapper.Invoke(certValidationCallback, leaf, chain, (MonoSslPolicyErrors)errors);
                }
                else
                {
                    result = certValidationCallback.Invoke(sender, leaf, chain, errors);
                }
                user_denied = !result;
            }
            return(new ValidationResult(result, user_denied, status11, (MonoSslPolicyErrors)errors));
        }
Esempio n. 3
0
 internal static bool InvokeCallback(ServerCertValidationCallback callback, object sender, X509Certificate certificate, X509Chain chain, MonoSslPolicyErrors sslPolicyErrors)
 {
     return(callback.Invoke(sender, certificate, chain, (SslPolicyErrors)sslPolicyErrors));
 }
        ValidationResult ValidateChain(string host, bool server, XX509CertificateCollection certs, SslPolicyErrors errors)
        {
            // user_denied is true if the user callback is called and returns false
            bool user_denied = false;
            bool result      = false;

            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);
            }

            if (leaf == null)
            {
                errors |= SslPolicyErrors.RemoteCertificateNotAvailable;
                if (hasCallback)
                {
                    if (callbackWrapper != null)
                    {
                        result = callbackWrapper.Invoke(certValidationCallback, leaf, null, (MonoSslPolicyErrors)errors);
                    }
                    else
                    {
                        result = certValidationCallback.Invoke(sender, leaf, null, errors);
                    }
                    user_denied = !result;
                }
                return(new ValidationResult(result, user_denied, 0, (MonoSslPolicyErrors)errors));
            }

            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)
            {
                if (settings == null || settings.CallbackNeedsCertificateChain)
                {
                    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);
                errors            = (SslPolicyErrors)xerrors;
            }

            if (!providerValidated)
            {
                result = SystemCertificateValidator.Evaluate(settings, host, certs, chain, ref errors, ref status11);
            }

            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);
                user_denied = !result && !(policy is DefaultCertificatePolicy);
            }
            // If there's a 2.0 callback, it takes precedence
            if (hasCallback)
            {
                if (callbackWrapper != null)
                {
                    result = callbackWrapper.Invoke(certValidationCallback, leaf, chain, (MonoSslPolicyErrors)errors);
                }
                else
                {
                    result = certValidationCallback.Invoke(sender, leaf, chain, errors);
                }
                user_denied = !result;
            }
            return(new ValidationResult(result, user_denied, status11, (MonoSslPolicyErrors)errors));
        }
Esempio n. 5
0
        ValidationResult ValidateChain(string host, X509Certificate2Collection certs, SslPolicyErrors errors)
        {
            // user_denied is true if the user callback is called and returns false
            bool user_denied = false;
            bool result      = false;

            var hasCallback = certValidationCallback != null || callbackWrapper != null;

            X509Certificate2 leaf;

            if (certs == null || certs.Count == 0)
            {
                leaf = null;
            }
            else
            {
                leaf = certs [0];
            }

            if (tlsStream != null)
            {
                request.ServicePoint.SetServerCertificate(leaf);
            }

            if (leaf == null)
            {
                errors |= SslPolicyErrors.RemoteCertificateNotAvailable;
                if (hasCallback)
                {
                    if (callbackWrapper != null)
                    {
                        result = callbackWrapper.Invoke(certValidationCallback, leaf, null, (MonoSslPolicyErrors)errors);
                    }
                    else
                    {
                        result = certValidationCallback.Invoke(sender, leaf, null, errors);
                    }
                    user_denied = !result;
                }
                return(new ValidationResult(result, user_denied, 0, (MonoSslPolicyErrors)errors));
            }

            bool needsChain;
            bool skipSystemValidators = false;

            if (!CertificateValidationHelper.SupportsX509Chain || is_mobile || is_macosx)
            {
                needsChain = false;
            }
            else if (settings != null)
            {
                skipSystemValidators = settings.SkipSystemValidators;
                needsChain           = !settings.SkipSystemValidators || settings.CallbackNeedsCertificateChain;
            }
            else
            {
                needsChain = true;
            }

            ICertificatePolicy policy = ServicePointManager.GetLegacyCertificatePolicy();

            int       status11 = 0;       // Error code passed to the obsolete ICertificatePolicy callback
            X509Chain chain    = null;

            if (needsChain)
            {
                chain             = new X509Chain();
                chain.ChainPolicy = new X509ChainPolicy();


#if !MONOTOUCH
                chain.ChainPolicy.RevocationMode = revocation_mode;
#endif
                for (int i = 1; i < certs.Count; i++)
                {
                    chain.ChainPolicy.ExtraStore.Add(certs [i]);
                }
            }

#if !MONOTOUCH
            if (needsChain)
            {
                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 (host != null && !CheckServerIdentity(leaf, host))
                {
                    errors  |= SslPolicyErrors.RemoteCertificateNameMismatch;
                    status11 = -2146762481;                     // CERT_E_CN_NO_MATCH 0x800B010F
                }
            }
#endif

            if (is_macosx && !skipSystemValidators)
            {
                // 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 MONODROID && SECURITY_DEP
            if (!skipSystemValidators)
            {
                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) || certValidationCallback == null))
            {
                ServicePoint sp = null;
                if (request != null)
                {
                    sp = request.ServicePointNoLock;
                }
                if (status11 == 0 && errors != 0)
                {
                    status11 = GetStatusFromChain(chain);
                }

                // pre 2.0 callback
                result      = policy.CheckValidationResult(sp, leaf, request, status11);
                user_denied = !result && !(policy is DefaultCertificatePolicy);
            }
            // If there's a 2.0 callback, it takes precedence
            if (hasCallback)
            {
                if (callbackWrapper != null)
                {
                    result = callbackWrapper.Invoke(certValidationCallback, leaf, chain, (MonoSslPolicyErrors)errors);
                }
                else
                {
                    result = certValidationCallback.Invoke(sender, leaf, chain, errors);
                }
                user_denied = !result;
            }
            return(new ValidationResult(result, user_denied, status11, (MonoSslPolicyErrors)errors));
        }
Esempio n. 6
0
        ValidationResult ValidateChain(string host, XX509CertificateCollection certs, SslPolicyErrors errors)
        {
            // user_denied is true if the user callback is called and returns false
            bool user_denied = false;
            bool result      = false;

            var hasCallback = certValidationCallback != null || callbackWrapper != null;
            var anchors     = settings != null ? settings.TrustAnchors : null;

            var systemValidator = GetSystemCertificateValidator();

            X509Certificate leaf;

            if (certs == null || certs.Count == 0)
            {
                leaf = null;
            }
            else
            {
                leaf = certs [0];
            }

            if (tlsStream != null)
            {
                request.ServicePoint.SetServerCertificate(leaf);
            }

            if (leaf == null)
            {
                errors |= SslPolicyErrors.RemoteCertificateNotAvailable;
                if (hasCallback)
                {
                    if (callbackWrapper != null)
                    {
                        result = callbackWrapper.Invoke(certValidationCallback, leaf, null, (MonoSslPolicyErrors)errors);
                    }
                    else
                    {
                        result = certValidationCallback.Invoke(sender, leaf, null, errors);
                    }
                    user_denied = !result;
                }
                return(new ValidationResult(result, user_denied, 0, (MonoSslPolicyErrors)errors));
            }

            bool needsChain;
            bool skipSystemValidators = false;

            if (!CertificateValidationHelper.SupportsX509Chain || is_mobile || is_macosx)
            {
                needsChain = false;
            }
            else if (settings != null)
            {
                skipSystemValidators = settings.SkipSystemValidators;
                needsChain           = !settings.SkipSystemValidators || settings.CallbackNeedsCertificateChain;
            }
            else
            {
                needsChain = true;
            }

            ICertificatePolicy policy = ServicePointManager.GetLegacyCertificatePolicy();

            int       status11 = 0;       // Error code passed to the obsolete ICertificatePolicy callback
            X509Chain chain    = null;

#if !MOBILE
            if (needsChain)
            {
                chain = systemValidator.ComputeX509Chain(certs, ref errors, ref status11);
            }
#endif

            systemValidator.CheckUsage(certs, host, ref errors, ref status11);

            if (!skipSystemValidators)
            {
                result = systemValidator.EvaluateSystem(certs, anchors, host, chain, ref errors, ref status11);
            }

            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);
                user_denied = !result && !(policy is DefaultCertificatePolicy);
            }
            // If there's a 2.0 callback, it takes precedence
            if (hasCallback)
            {
                if (callbackWrapper != null)
                {
                    result = callbackWrapper.Invoke(certValidationCallback, leaf, chain, (MonoSslPolicyErrors)errors);
                }
                else
                {
                    result = certValidationCallback.Invoke(sender, leaf, chain, errors);
                }
                user_denied = !result;
            }
            return(new ValidationResult(result, user_denied, status11, (MonoSslPolicyErrors)errors));
        }