public static MatchHostnameToPattern ( string hostname, string pattern ) : bool | ||
hostname | string | |
pattern | string | |
리턴 | bool |
public bool Check(string hostname, List <X509Certificate2> peerCertificates) { if (!HasPins(hostname)) { Debug.WriteLine($"No certificate pin found for {hostname}"); return(false); } hostname = Pins.FirstOrDefault(p => Utility.MatchHostnameToPattern(hostname, p.Key)).Key; // Get pins string[] pins = Pins[hostname]; // Skip pinning with empty array if (pins == null || pins.Length == 0) { return(true); } foreach (var certificate in peerCertificates) { // Compute spki fingerprint var spkiFingerprint = SpkiFingerprint.Compute(certificate.RawData); // Check pin if (Array.IndexOf(pins, spkiFingerprint) > -1) { Debug.WriteLine($"Certificate pin {spkiFingerprint} is ok for {hostname}"); return(true); } } Debug.WriteLine($"Certificate pinning failure! Peer certificate chain for {hostname}: {string.Join("|", pins)}"); return(false); }
/// <summary> /// Verifies the server certificate by calling into ServicePointManager.ServerCertificateValidationCallback or, /// if the is no delegate attached to it by using the default hostname verifier. /// </summary> /// <returns><c>true</c>, if server certificate was verifyed, <c>false</c> otherwise.</returns> /// <param name="hostname"></param> /// <param name="session"></param> static bool verifyServerCertificate(string hostname, ISSLSession session) { var defaultVerifier = HttpsURLConnection.DefaultHostnameVerifier; if (ServicePointManager.ServerCertificateValidationCallback == null) { return(defaultVerifier.Verify(hostname, session)); } // Convert java certificates to .NET certificates and build cert chain from root certificate var certificates = session.GetPeerCertificateChain(); var chain = new X509Chain(); var errors = System.Net.Security.SslPolicyErrors.None; // Build certificate chain and check for errors if (certificates == null || certificates.Length == 0) { //no cert at all errors = System.Net.Security.SslPolicyErrors.RemoteCertificateNotAvailable; return(ServicePointManager.ServerCertificateValidationCallback(hostname, null, chain, errors)); } if (certificates.Length == 1) { //no root? errors = System.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors; return(ServicePointManager.ServerCertificateValidationCallback(hostname, null, chain, errors)); } var netCerts = certificates.Select(x => new X509Certificate2(x.GetEncoded())).ToArray(); for (int i = 1; i < netCerts.Length; i++) { chain.ChainPolicy.ExtraStore.Add(netCerts[i]); } var root = netCerts[0]; chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain; chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 1, 0); chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority; if (!chain.Build(root)) { errors = System.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors; return(ServicePointManager.ServerCertificateValidationCallback(hostname, root, chain, errors)); } var subject = root.Subject; var subjectCn = cnRegex.Match(subject).Groups[1].Value; if (String.IsNullOrWhiteSpace(subjectCn) || !Utility.MatchHostnameToPattern(hostname, subjectCn)) { errors = System.Net.Security.SslPolicyErrors.RemoteCertificateNameMismatch; } return(ServicePointManager.ServerCertificateValidationCallback(hostname, root, chain, errors)); }
public bool HasPins(string hostname) { foreach (var pin in Pins) { if (Utility.MatchHostnameToPattern(hostname, pin.Key)) { return(true); } } return(false); }
public bool Check(string hostname, byte[] certificate) { if (!HasPins(hostname)) { Debug.WriteLine($"No certificate pin found for {hostname}"); return(false); } hostname = Pins.FirstOrDefault(p => Utility.MatchHostnameToPattern(hostname, p.Key)).Key; // Get pins string[] pins = Pins[hostname]; // Skip pinning with empty array if (pins == null || pins.Length == 0) { return(true); } // Compute spki fingerprint var spkiFingerprint = SpkiFingerprint.Compute(certificate); // Check pin var match = Array.IndexOf(pins, spkiFingerprint) > -1; if (match) { Debug.WriteLine($"Certificate pin is ok for {hostname}"); } else { Debug.WriteLine($"Certificate pinning failure! Peer certificate chain: {spkiFingerprint}, Pinned certificates for {hostname}: {string.Join("|", pins)}"); } return(match); }
public NativeMessageHandler(bool throwOnCaptiveNetwork, TLSConfig tLSConfig, NativeCookieHandler cookieHandler = null, IWebProxy proxy = null) { this.throwOnCaptiveNetwork = throwOnCaptiveNetwork; this.TLSConfig = tLSConfig; // Enforce TLS1.2 SslProtocols = SslProtocols.Tls12; // Add Certificate Pins if (!TLSConfig.DangerousAcceptAnyServerCertificateValidator && TLSConfig.Pins != null && TLSConfig.Pins.Count > 0 && TLSConfig.Pins.FirstOrDefault(p => p.PublicKeys.Count() > 0) != null) { this.PinningMode = "PublicKeysOnly"; this.CertificatePinner = new CertificatePinner(); foreach (var pin in TLSConfig.Pins) { this.CertificatePinner.AddPins(pin.Hostname, pin.PublicKeys); } } // Set client credentials SetClientCertificate(TLSConfig.ClientCertificate); if (cookieHandler != null) { this.CookieContainer = cookieHandler; } // Adding proxy support if (proxy != null) { Proxy = proxy; UseProxy = true; } this.ServerCertificateCustomValidationCallback = (request, root, chain, e) => { var errors = SslPolicyErrors.None; if (TLSConfig.DangerousAcceptAnyServerCertificateValidator) { goto sslErrorVerify; } var hostname = request.RequestUri.Host; var netCerts = new List <X509Certificate2>(); foreach (var element in chain.ChainElements) { netCerts.Add(element.Certificate); } switch (this.PinningMode) { case "CertificateOnly": // Build certificate chain and check for errors if (chain == null || chain.ChainElements.Count == 0) { //no cert at all errors = SslPolicyErrors.RemoteCertificateNotAvailable; goto sslErrorVerify; } if (chain.ChainElements.Count == 1) { //no root? errors = SslPolicyErrors.RemoteCertificateChainErrors; goto sslErrorVerify; } if (!chain.Build(root)) { errors = SslPolicyErrors.RemoteCertificateChainErrors; goto sslErrorVerify; } var subject = root.Subject; var subjectCn = cnRegex.Match(subject).Groups[1].Value; if (string.IsNullOrWhiteSpace(subjectCn) || !Utility.MatchHostnameToPattern(hostname, subjectCn)) { var subjectAn = root.ParseSubjectAlternativeName(); if (subjectAn.FirstOrDefault(s => Utility.MatchHostnameToPattern(hostname, s)) == null) { errors = SslPolicyErrors.RemoteCertificateNameMismatch; goto sslErrorVerify; } } break; case "PublicKeysOnly": if (this.CertificatePinner != null) { if (!this.CertificatePinner.HasPins(hostname)) { errors = SslPolicyErrors.RemoteCertificateNameMismatch; goto sslErrorVerify; } if (!this.CertificatePinner.Check(hostname, netCerts)) { errors = SslPolicyErrors.RemoteCertificateNameMismatch; } } break; } sslErrorVerify: return(errors == SslPolicyErrors.None); }; }
public override void DidReceiveChallenge(NSUrlSession session, NSUrlSessionTask task, NSUrlAuthenticationChallenge challenge, Action <NSUrlSessionAuthChallengeDisposition, NSUrlCredential> completionHandler) { if (!This.customSSLVerification) { goto doDefault; } if (challenge.ProtectionSpace.AuthenticationMethod != "NSURLAuthenticationMethodServerTrust") { goto doDefault; } if (ServicePointManager.ServerCertificateValidationCallback == null) { goto doDefault; } // Convert Mono Certificates to .NET certificates and build cert // chain from root certificate var serverCertChain = challenge.ProtectionSpace.ServerSecTrust; var chain = new X509Chain(); X509Certificate2 root = null; var errors = SslPolicyErrors.None; if (serverCertChain == null || serverCertChain.Count == 0) { errors = SslPolicyErrors.RemoteCertificateNotAvailable; goto sslErrorVerify; } if (serverCertChain.Count == 1) { errors = SslPolicyErrors.RemoteCertificateChainErrors; goto sslErrorVerify; } var netCerts = Enumerable.Range(0, serverCertChain.Count) .Select(x => serverCertChain[x].ToX509Certificate2()) .ToArray(); for (int i = 1; i < netCerts.Length; i++) { chain.ChainPolicy.ExtraStore.Add(netCerts[i]); } root = netCerts[0]; chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain; chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 1, 0); chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority; try { if (!chain.Build(root)) { errors = SslPolicyErrors.RemoteCertificateChainErrors; goto sslErrorVerify; } } catch (System.Security.Cryptography.CryptographicException) { // As best we can tell, a XAMMIT (spurious). errors = SslPolicyErrors.RemoteCertificateChainErrors; goto sslErrorVerify; } var subject = root.Subject; var subjectCn = cnRegex.Match(subject).Groups[1].Value; if (String.IsNullOrWhiteSpace(subjectCn) || !Utility.MatchHostnameToPattern(task.CurrentRequest.Url.Host, subjectCn)) { errors = SslPolicyErrors.RemoteCertificateNameMismatch; goto sslErrorVerify; } sslErrorVerify: // NachoCove: Add this to make it look like other HTTP client var url = task.CurrentRequest.Url.ToString(); var request = new HttpWebRequest(new Uri(url)); // End of NachoCove bool result = ServicePointManager.ServerCertificateValidationCallback(request, root, chain, errors); if (result) { completionHandler( NSUrlSessionAuthChallengeDisposition.UseCredential, NSUrlCredential.FromTrust(challenge.ProtectionSpace.ServerSecTrust)); } else { completionHandler(NSUrlSessionAuthChallengeDisposition.CancelAuthenticationChallenge, null); } return; doDefault: if (null != This.Credentials) { var authenticationType = AuthenticationTypeFromAuthenticationMethod(challenge.ProtectionSpace.AuthenticationMethod); var uri = UriFromNSUrlProtectionSpace(challenge.ProtectionSpace); if (null != authenticationType && null != uri) { var specifedCredential = This.Credentials.GetCredential(uri, authenticationType); var state = getResponseForTask(task); if (null != specifedCredential && null != specifedCredential.UserName && null != specifedCredential.Password) { if (specifedCredential == state.PresentedCredential) { completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, null); } else { state.PresentedCredential = specifedCredential; var credential = new NSUrlCredential( specifedCredential.UserName, specifedCredential.Password, NSUrlCredentialPersistence.ForSession); completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, credential); } return; } } } completionHandler(NSUrlSessionAuthChallengeDisposition.PerformDefaultHandling, challenge.ProposedCredential); return; }
/// <summary> /// Verifies the server certificate by calling into ServicePointManager.ServerCertificateValidationCallback or, /// if the is no delegate attached to it by using the default hostname verifier. /// </summary> /// <returns><c>true</c>, if server certificate was verifyed, <c>false</c> otherwise.</returns> /// <param name="hostname"></param> /// <param name="session"></param> public bool Verify(string hostname, ISSLSession session) { var errors = SslPolicyErrors.None; if (nativeHandler.TLSConfig.DangerousAcceptAnyServerCertificateValidator) { goto sslErrorVerify; } // Convert java certificates to .NET certificates and build cert chain from root certificate var serverCertChain = session.GetPeerCertificateChain(); var netCerts = serverCertChain.Select(x => new X509Certificate2(x.GetEncoded())).ToList(); switch (nativeHandler.PinningMode) { case "CertificateOnly": var chain = new X509Chain(); X509Certificate2 root = null; // Build certificate chain and check for errors if (serverCertChain == null || serverCertChain.Length == 0) { //no cert at all errors = SslPolicyErrors.RemoteCertificateNotAvailable; PinningFailureMessage = FailureMessages.NoCertAtAll; goto sslErrorVerify; } if (serverCertChain.Length == 1) { //no root? errors = SslPolicyErrors.RemoteCertificateChainErrors; PinningFailureMessage = FailureMessages.NoRoot; goto sslErrorVerify; } for (int i = 1; i < netCerts.Count; i++) { chain.ChainPolicy.ExtraStore.Add(netCerts[i]); } chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain; chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 1, 0); chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority; root = netCerts[0]; if (!chain.Build(root)) { errors = SslPolicyErrors.RemoteCertificateChainErrors; PinningFailureMessage = FailureMessages.ChainError; goto sslErrorVerify; } var subject = root.Subject; var subjectCn = cnRegex.Match(subject).Groups[1].Value; if (string.IsNullOrWhiteSpace(subjectCn) || !Utility.MatchHostnameToPattern(hostname, subjectCn)) { var subjectAn = root.ParseSubjectAlternativeName(); if (subjectAn.FirstOrDefault(s => Utility.MatchHostnameToPattern(hostname, s)) == null) { errors = SslPolicyErrors.RemoteCertificateNameMismatch; PinningFailureMessage = FailureMessages.SubjectNameMismatch; goto sslErrorVerify; } } break; case "PublicKeysOnly": if (nativeHandler.CertificatePinner != null) { if (!nativeHandler.CertificatePinner.HasPins(hostname)) { errors = SslPolicyErrors.RemoteCertificateNameMismatch; PinningFailureMessage = FailureMessages.NoPinsProvided + " " + hostname; } // CertificatePinner.Check will be done by Square.OkHttp3.CertificatePinner } break; } sslErrorVerify: return(errors == SslPolicyErrors.None); }
public override void DidReceiveChallenge(NSUrlSession session, NSUrlSessionTask task, NSUrlAuthenticationChallenge challenge, Action <NSUrlSessionAuthChallengeDisposition, NSUrlCredential> completionHandler) { if (challenge.ProtectionSpace.AuthenticationMethod == NSUrlProtectionSpace.AuthenticationMethodNTLM) { NetworkCredential credentialsToUse; if (This.Credentials != null) { if (This.Credentials is NetworkCredential) { credentialsToUse = (NetworkCredential)This.Credentials; } else { var uri = this.getResponseForTask(task).Request.RequestUri; credentialsToUse = This.Credentials.GetCredential(uri, "NTLM"); } var credential = new NSUrlCredential(credentialsToUse.UserName, credentialsToUse.Password, NSUrlCredentialPersistence.ForSession); completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, credential); } return; } if (!This.customSSLVerification) { goto doDefault; } if (challenge.ProtectionSpace.AuthenticationMethod != "NSURLAuthenticationMethodServerTrust") { goto doDefault; } // Call custom ServicePointManager.ServerCertificateValidationCallback delegate // if customSSLVerification is true if (ServicePointManager.ServerCertificateValidationCallback == null) { goto doDefault; } // Convert Mono Certificates to .NET certificates and build cert // chain from root certificate var serverCertChain = challenge.ProtectionSpace.ServerSecTrust; var chain = new X509Chain(); X509Certificate2 root = null; var errors = SslPolicyErrors.None; if (serverCertChain == null || serverCertChain.Count == 0) { errors = SslPolicyErrors.RemoteCertificateNotAvailable; goto sslErrorVerify; } if (serverCertChain.Count == 1) { errors = SslPolicyErrors.RemoteCertificateChainErrors; goto sslErrorVerify; } var netCerts = Enumerable.Range(0, serverCertChain.Count) .Select(x => serverCertChain[x].ToX509Certificate2()) .ToArray(); for (int i = 1; i < netCerts.Length; i++) { chain.ChainPolicy.ExtraStore.Add(netCerts[i]); } root = netCerts[0]; chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain; chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 1, 0); chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority; if (!chain.Build(root)) { errors = SslPolicyErrors.RemoteCertificateChainErrors; goto sslErrorVerify; } var subject = root.Subject; var subjectCn = cnRegex.Match(subject).Groups[1].Value; if (String.IsNullOrWhiteSpace(subjectCn) || !Utility.MatchHostnameToPattern(task.CurrentRequest.Url.Host, subjectCn)) { errors = SslPolicyErrors.RemoteCertificateNameMismatch; goto sslErrorVerify; } sslErrorVerify: var hostname = task.CurrentRequest.Url.Host; bool result = ServicePointManager.ServerCertificateValidationCallback(hostname, root, chain, errors); if (result) { completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, NSUrlCredential.FromTrust(challenge.ProtectionSpace.ServerSecTrust)); } else { completionHandler(NSUrlSessionAuthChallengeDisposition.CancelAuthenticationChallenge, null); } return; doDefault: // Support self-signed certificates if (This.EnableUntrustedCertificates) { completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, NSUrlCredential.FromTrust(challenge.ProtectionSpace.ServerSecTrust)); } else { completionHandler(NSUrlSessionAuthChallengeDisposition.PerformDefaultHandling, challenge.ProposedCredential); } return; }
public override void DidReceiveChallenge(NSUrlSession session, NSUrlSessionTask task, NSUrlAuthenticationChallenge challenge, Action <NSUrlSessionAuthChallengeDisposition, NSUrlCredential> completionHandler) { if (!This.customSSLVerification) { goto doDefault; } if (challenge.ProtectionSpace.AuthenticationMethod != "NSURLAuthenticationMethodServerTrust") { goto doDefault; } if (ServicePointManager.ServerCertificateValidationCallback == null) { goto doDefault; } // Convert Mono Certificates to .NET certificates and build cert // chain from root certificate var serverCertChain = challenge.ProtectionSpace.ServerSecTrust; var chain = new X509Chain(); X509Certificate2 root = null; var errors = SslPolicyErrors.None; if (serverCertChain == null || serverCertChain.Count == 0) { errors = SslPolicyErrors.RemoteCertificateNotAvailable; goto sslErrorVerify; } if (serverCertChain.Count == 1) { errors = SslPolicyErrors.RemoteCertificateChainErrors; goto sslErrorVerify; } var netCerts = Enumerable.Range(0, serverCertChain.Count) .Select(x => serverCertChain[x].ToX509Certificate2()) .ToArray(); for (int i = 1; i < netCerts.Length; i++) { chain.ChainPolicy.ExtraStore.Add(netCerts[i]); } root = netCerts[0]; chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain; chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 1, 0); chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority; if (!chain.Build(root)) { errors = SslPolicyErrors.RemoteCertificateChainErrors; goto sslErrorVerify; } var subject = root.Subject; var subjectCn = cnRegex.Match(subject).Groups[1].Value; if (String.IsNullOrWhiteSpace(subjectCn) || !Utility.MatchHostnameToPattern(task.CurrentRequest.Url.Host, subjectCn)) { errors = SslPolicyErrors.RemoteCertificateNameMismatch; goto sslErrorVerify; } sslErrorVerify: bool result = ServicePointManager.ServerCertificateValidationCallback(this, root, chain, errors); if (result) { completionHandler( NSUrlSessionAuthChallengeDisposition.UseCredential, NSUrlCredential.FromTrust(challenge.ProtectionSpace.ServerSecTrust)); } else { completionHandler(NSUrlSessionAuthChallengeDisposition.RejectProtectionSpace, null); } return; doDefault: completionHandler(NSUrlSessionAuthChallengeDisposition.PerformDefaultHandling, challenge.ProposedCredential); return; }
public override void DidReceiveChallenge(NSUrlSession session, NSUrlSessionTask task, NSUrlAuthenticationChallenge challenge, Action <NSUrlSessionAuthChallengeDisposition, NSUrlCredential> completionHandler) { // TODO: add NSUrlProtectionSpace.HTTPSProxy case if (challenge.ProtectionSpace.AuthenticationMethod == NSUrlProtectionSpace.AuthenticationMethodNTLM) { NetworkCredential credentialsToUse; if (nativeHandler.Credentials != null) { if (nativeHandler.Credentials is NetworkCredential) { credentialsToUse = (NetworkCredential)nativeHandler.Credentials; } else { var uri = this.getResponseForTask(task).Request.RequestUri; credentialsToUse = nativeHandler.Credentials.GetCredential(uri, "NTLM"); } var credential = new NSUrlCredential(credentialsToUse.UserName, credentialsToUse.Password, NSUrlCredentialPersistence.ForSession); completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, credential); } return; } if (challenge.ProtectionSpace.AuthenticationMethod == NSUrlProtectionSpace.AuthenticationMethodServerTrust) { var errors = SslPolicyErrors.None; if (nativeHandler.TLSConfig.DangerousAcceptAnyServerCertificateValidator) { goto sslErrorVerify; } var hostname = task.CurrentRequest.Url.Host; // Convert java certificates to .NET certificates and build cert chain from root certificate var serverCertChain = challenge.ProtectionSpace.ServerSecTrust; var netCerts = Enumerable.Range(0, serverCertChain.Count) .Select(x => serverCertChain[x].ToX509Certificate2()) .ToList(); switch (nativeHandler.PinningMode) { case "CertificateOnly": //Security.addProvider(new BouncyCastleProvider()); //CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC"); var chain = new X509Chain(); X509Certificate2 root = null; // Build certificate chain and check for errors if (serverCertChain == null || serverCertChain.Count == 0) { //no cert at all errors = SslPolicyErrors.RemoteCertificateNotAvailable; PinningFailureMessage = FailureMessages.NoCertAtAll; goto sslErrorVerify; } if (serverCertChain.Count == 1) { //no root? errors = SslPolicyErrors.RemoteCertificateChainErrors; PinningFailureMessage = FailureMessages.NoRoot; goto sslErrorVerify; } for (int i = 1; i < netCerts.Count; i++) { chain.ChainPolicy.ExtraStore.Add(netCerts[i]); } //chain.ChainPolicy.CertificatePolicy.Add(new Oid("1.2.840.10045.2.1")); chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain; chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 1, 0); chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority; root = netCerts[0]; /*if (!chain.Build(root)) * { * errors = SslPolicyErrors.RemoteCertificateChainErrors; * PinningFailureMessage = FailureMessages.ChainError; * goto sslErrorVerify; * }*/ var subject = root.Subject; var subjectCn = cnRegex.Match(subject).Groups[1].Value; if (string.IsNullOrWhiteSpace(subjectCn) || !Utility.MatchHostnameToPattern(hostname, subjectCn)) { var subjectAn = root.ParseSubjectAlternativeName(); if (subjectAn.FirstOrDefault(s => Utility.MatchHostnameToPattern(hostname, s)) == null) { errors = SslPolicyErrors.RemoteCertificateNameMismatch; PinningFailureMessage = FailureMessages.SubjectNameMismatch; goto sslErrorVerify; } } break; case "PublicKeysOnly": if (nativeHandler.CertificatePinner != null) { if (!nativeHandler.CertificatePinner.HasPins(hostname)) { errors = SslPolicyErrors.RemoteCertificateNameMismatch; PinningFailureMessage = FailureMessages.NoPinsProvided + " " + hostname; goto sslErrorVerify; } if (!nativeHandler.CertificatePinner.Check(hostname, netCerts)) { errors = SslPolicyErrors.RemoteCertificateNameMismatch; PinningFailureMessage = FailureMessages.PinMismatch; } } break; } sslErrorVerify: if (errors == SslPolicyErrors.None) { completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, NSUrlCredential.FromTrust(challenge.ProtectionSpace.ServerSecTrust)); } else { completionHandler(NSUrlSessionAuthChallengeDisposition.CancelAuthenticationChallenge, null); } return; } if (challenge.ProtectionSpace.AuthenticationMethod == NSUrlProtectionSpace.AuthenticationMethodClientCertificate) { completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, nativeHandler.UrlCredential); return; } completionHandler(NSUrlSessionAuthChallengeDisposition.PerformDefaultHandling, challenge.ProposedCredential); }
public override void DidReceiveChallenge(NSUrlSession session, NSUrlSessionTask task, NSUrlAuthenticationChallenge challenge, Action <NSUrlSessionAuthChallengeDisposition, NSUrlCredential> completionHandler) { if (challenge.ProtectionSpace.AuthenticationMethod == NSUrlProtectionSpace.AuthenticationMethodNTLM) { NetworkCredential credentialsToUse; if (This.Credentials != null) { if (This.Credentials is NetworkCredential) { credentialsToUse = (NetworkCredential)This.Credentials; } else { var uri = this.getResponseForTask(task).Request.RequestUri; credentialsToUse = This.Credentials.GetCredential(uri, "NTLM"); } var credential = new NSUrlCredential(credentialsToUse.UserName, credentialsToUse.Password, NSUrlCredentialPersistence.ForSession); completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, credential); } return; } if (challenge.ProtectionSpace.AuthenticationMethod == NSUrlProtectionSpace.AuthenticationMethodClientCertificate) { Console.WriteLine("Client Cert!"); var password = "******"; var options = NSDictionary.FromObjectAndKey(NSObject.FromObject(password), SecImportExport.Passphrase); var path = Path.Combine(NSBundle.MainBundle.BundlePath, "Content", "client.p12"); var certData = File.ReadAllBytes(path); NSDictionary[] importResult; X509Certificate cert = new X509Certificate(certData, password); SecStatusCode statusCode = SecImportExport.ImportPkcs12(certData, options, out importResult); var identityHandle = importResult[0][SecImportExport.Identity]; var identity = new SecIdentity(identityHandle.Handle); var certificate = new SecCertificate(cert.GetRawCertData()); SecCertificate[] certificates = { certificate }; NSUrlCredential credential = NSUrlCredential.FromIdentityCertificatesPersistance(identity, certificates, NSUrlCredentialPersistence.ForSession); completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, credential); return; } if (!This.customSSLVerification) { goto doDefault; } if (challenge.ProtectionSpace.AuthenticationMethod != "NSURLAuthenticationMethodServerTrust") { goto doDefault; } if (ServicePointManager.ServerCertificateValidationCallback == null) { goto doDefault; } // Convert Mono Certificates to .NET certificates and build cert // chain from root certificate var serverCertChain = challenge.ProtectionSpace.ServerSecTrust; var chain = new X509Chain(); X509Certificate2 root = null; var errors = SslPolicyErrors.None; if (serverCertChain == null || serverCertChain.Count == 0) { errors = SslPolicyErrors.RemoteCertificateNotAvailable; goto sslErrorVerify; } if (serverCertChain.Count == 1) { errors = SslPolicyErrors.RemoteCertificateChainErrors; goto sslErrorVerify; } var netCerts = Enumerable.Range(0, serverCertChain.Count) .Select(x => serverCertChain[x].ToX509Certificate2()) .ToArray(); for (int i = 1; i < netCerts.Length; i++) { chain.ChainPolicy.ExtraStore.Add(netCerts[i]); } root = netCerts[0]; chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain; chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 1, 0); chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority; if (!chain.Build(root)) { errors = SslPolicyErrors.RemoteCertificateChainErrors; goto sslErrorVerify; } var subject = root.Subject; var subjectCn = cnRegex.Match(subject).Groups[1].Value; if (String.IsNullOrWhiteSpace(subjectCn) || !Utility.MatchHostnameToPattern(task.CurrentRequest.Url.Host, subjectCn)) { errors = SslPolicyErrors.RemoteCertificateNameMismatch; goto sslErrorVerify; } sslErrorVerify: var hostname = task.CurrentRequest.Url.Host; bool result = ServicePointManager.ServerCertificateValidationCallback(hostname, root, chain, errors); if (result) { completionHandler( NSUrlSessionAuthChallengeDisposition.UseCredential, NSUrlCredential.FromTrust(challenge.ProtectionSpace.ServerSecTrust)); } else { completionHandler(NSUrlSessionAuthChallengeDisposition.CancelAuthenticationChallenge, null); } return; doDefault: completionHandler(NSUrlSessionAuthChallengeDisposition.PerformDefaultHandling, challenge.ProposedCredential); return; }