+ status11 = -2146762481; // CERT_E_CN_NO_MATCH 0x800B010F
+ }
+
+ bool result = false;
+ // No certificate root found means no mozroots or monotouch
+#if !MONOTOUCH
+ if (is_macosx) {
+#endif
+ // Attempt to use OSX certificates
+ // Ideally we should return the SecTrustResult
+ MSX.OSX509Certificates.SecTrustResult trustResult = MSX.OSX509Certificates.SecTrustResult.Deny;
+ try {
+ trustResult = MSX.OSX509Certificates.TrustEvaluateSsl (certs);
+ // 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 == MSX.OSX509Certificates.SecTrustResult.Proceed ||
+ trustResult == MSX.OSX509Certificates.SecTrustResult.Unspecified);
+
+ } catch {
+ // Ignore
+ }
+ // Clear error status if the OS told us to trust the certificate
+ if (result) {
+ status11 = 0;
+ errors = 0;
+ } else {
+ // callback and DefaultCertificatePolicy needs this since 'result' is not specified
+ status11 = (int) trustResult;
+ errors |= SslPolicyErrors.RemoteCertificateChainErrors;
+ }
+#if !MONOTOUCH
+ }
+#endif
+
+#if MONODROID
+ result = monodroidCallback (certs);
+ if (result) {
+ status11 = 0;
+ errors = 0;
+ }
+#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);
+ }
+
+ 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;