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)); }
public static SecTrustResult TrustEvaluateSsl(MSX.X509CertificateCollection certificates, string host) { if (certificates == null) { return(SecTrustResult.Deny); } try { return(_TrustEvaluateSsl(certificates, host)); } catch { return(SecTrustResult.Deny); } }
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); }
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; } }
// 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)); }
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); } } }