예제 #1
0
 internal static bool TrustEvaluateSsl(MSX.X509CertificateCollection collection, object sender, X509Certificate2 certificate, X509Chain chain, SslPolicyErrors errors)
 {
     if (trustEvaluateSsl2 != null)
     {
         return(trustEvaluateSsl2(collection, sender, certificate, chain, errors));
     }
     return(trustEvaluateSsl(collection));
 }
예제 #2
0
        public static SecTrustResult TrustEvaluateSsl(MSX.X509CertificateCollection certificates, string host)
        {
            if (certificates == null)
            {
                return(SecTrustResult.Deny);
            }

            try {
                return(_TrustEvaluateSsl(certificates, host));
            } catch {
                return(SecTrustResult.Deny);
            }
        }
예제 #3
0
        static X509Certificate2Collection Convert(MSX.X509CertificateCollection certificates)
        {
            if (certificates == null)
            {
                return(null);
            }

            var certs2 = new X509Certificate2Collection();

            for (int i = 0; i < certificates.Count; i++)
            {
                certs2.Add(new X509Certificate2(certificates [i].RawData));
            }
            return(certs2);
        }
예제 #4
0
 internal ValidationResult ValidateChain(string host, MSX.X509CertificateCollection certs)
 {
     try {
         var certs2 = Convert(certs);
         var result = ValidateChain(host, certs2, 0);
         if (tlsStream != null)
         {
             tlsStream.CertificateValidationFailed = result == null || !result.Trusted || result.UserDenied;
         }
         return(result);
     } catch {
         if (tlsStream != null)
         {
             tlsStream.CertificateValidationFailed = true;
         }
         throw;
     }
 }
예제 #5
0
            // 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;
                RemoteCertificateValidationCallback cb = ServicePointManager.ServerCertificateValidationCallback;

                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 (cb != 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 (cb != null)
            {
                result      = cb(sender, leaf, chain, errors);
                user_denied = !result;
            }
            return(new ValidationResult(result, user_denied, status11));
        }
예제 #6
0
        static SecTrustResult _TrustEvaluateSsl(MSX.X509CertificateCollection certificates, string hostName)
        {
            int certCount = certificates.Count;

            IntPtr []      cfDataPtrs   = new IntPtr [certCount];
            IntPtr []      secCerts     = new IntPtr [certCount];
            IntPtr         certArray    = IntPtr.Zero;
            IntPtr         sslsecpolicy = IntPtr.Zero;
            IntPtr         host         = IntPtr.Zero;
            IntPtr         sectrust     = IntPtr.Zero;
            SecTrustResult result       = SecTrustResult.Deny;

            try {
                for (int i = 0; i < certCount; i++)
                {
                    cfDataPtrs [i] = MakeCFData(certificates [i].RawData);
                }

                for (int i = 0; i < certCount; i++)
                {
                    secCerts [i] = SecCertificateCreateWithData(IntPtr.Zero, cfDataPtrs [i]);
                    if (secCerts [i] == IntPtr.Zero)
                    {
                        return(SecTrustResult.Deny);
                    }
                }
                certArray    = FromIntPtrs(secCerts);
                host         = CFStringCreateWithCharacters(IntPtr.Zero, hostName, hostName.Length);
                sslsecpolicy = SecPolicyCreateSSL(true, host);

                int code = SecTrustCreateWithCertificates(certArray, sslsecpolicy, out sectrust);
                if (code == 0)
                {
                    code = SecTrustEvaluate(sectrust, out result);
                }
                return(result);
            } finally {
                for (int i = 0; i < certCount; i++)
                {
                    if (cfDataPtrs [i] != IntPtr.Zero)
                    {
                        CFRelease(cfDataPtrs [i]);
                    }
                }

                if (certArray != IntPtr.Zero)
                {
                    CFRelease(certArray);
                }

                for (int i = 0; i < certCount; i++)
                {
                    if (secCerts [i] != IntPtr.Zero)
                    {
                        CFRelease(secCerts [i]);
                    }
                }

                if (sslsecpolicy != IntPtr.Zero)
                {
                    CFRelease(sslsecpolicy);
                }
                if (host != IntPtr.Zero)
                {
                    CFRelease(host);
                }
                if (sectrust != IntPtr.Zero)
                {
                    CFRelease(sectrust);
                }
            }
        }