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 NativeMessageHandler(bool throwOnCaptiveNetwork, TLSConfig tLSConfig, NativeCookieHandler cookieHandler = null, IWebProxy proxy = null) { this.throwOnCaptiveNetwork = throwOnCaptiveNetwork; var configuration = NSUrlSessionConfiguration.DefaultSessionConfiguration; this.TLSConfig = tLSConfig; // System.Net.ServicePointManager.SecurityProtocol provides a mechanism for specifying supported protocol types // for System.Net. Since iOS only provides an API for a minimum and maximum protocol we are not able to port // this configuration directly and instead use the specified minimum value when one is specified. configuration.TLSMinimumSupportedProtocol = SslProtocol.Tls_1_2; 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); } } SetClientCertificate(TLSConfig.ClientCertificate); // NSUrlSessionConfiguration.DefaultSessionConfiguration uses the default NSHttpCookieStorage.SharedStorage // PR: Proxy has been supported on iOS #19 if (proxy != null && proxy is WebProxy) { var webProxy = proxy as WebProxy; NSObject[] values = { NSObject.FromObject(webProxy.Address.Host), NSNumber.FromInt32(webProxy.Address.Port), NSNumber.FromInt32(1) }; NSObject[] keys = { NSObject.FromObject("HTTPSProxy"), NSObject.FromObject("HTTPSPort"), NSObject.FromObject("HTTPSEnable") }; var proxyDict = NSDictionary.FromObjectsAndKeys(values, keys); configuration.ConnectionProxyDictionary = proxyDict; if (webProxy.Credentials != null) { var credentials = (NetworkCredential)webProxy.Credentials; var authData = string.Format("{0}:{1}", credentials.UserName, credentials.Password); var authHeaderValue = Convert.ToBase64String(Encoding.UTF8.GetBytes(authData)); NSObject[] hValues = { NSObject.FromObject(authHeaderValue) }; NSObject[] hKeys = { NSObject.FromObject("Proxy-Authorization") }; var headers = NSDictionary.FromObjectsAndKeys(hValues, hKeys); configuration.HttpAdditionalHeaders = headers; } } var urlSessionDelegate = new DataTaskDelegate(this); session = NSUrlSession.FromConfiguration(configuration, (INSUrlSessionDelegate)urlSessionDelegate, null); }
public NativeMessageHandler(bool throwOnCaptiveNetwork, TLSConfig tLSConfig, NativeCookieHandler cookieHandler = null, IWebProxy proxy = null) { this.throwOnCaptiveNetwork = throwOnCaptiveNetwork; var clientBuilder = client.NewBuilder(); this.TLSConfig = tLSConfig; var tlsSpecBuilder = new ConnectionSpec.Builder(ConnectionSpec.ModernTls).TlsVersions(new[] { TlsVersion.Tls12, TlsVersion.Tls13 }); var tlsSpec = tlsSpecBuilder.Build(); var specs = new List <ConnectionSpec>() { tlsSpec }; if (Build.VERSION.SdkInt < BuildVersionCodes.Lollipop || NetworkSecurityPolicy.Instance.IsCleartextTrafficPermitted) { specs.Add(ConnectionSpec.Cleartext); } clientBuilder.ConnectionSpecs(specs); clientBuilder.Protocols(new[] { Protocol.Http11 }); // Required to avoid stream was reset: PROTOCOL_ERROR // 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); } clientBuilder.CertificatePinner(CertificatePinner.Build()); } // Set client credentials SetClientCertificate(TLSConfig.ClientCertificate); if (cookieHandler != null) { clientBuilder.CookieJar(cookieHandler); } // Adding proxy support if (proxy != null && proxy is WebProxy) { var webProxy = proxy as WebProxy; var type = Java.Net.Proxy.Type.Http; var address = new InetSocketAddress(webProxy.Address.Host, webProxy.Address.Port); var jProxy = new Proxy(type, address); clientBuilder.Proxy(jProxy); if (webProxy.Credentials != null) { var credentials = (NetworkCredential)webProxy.Credentials; clientBuilder.ProxyAuthenticator(new ProxyAuthenticator(credentials.UserName, credentials.Password)); } } var sslContext = SSLContext.GetInstance("TLS"); // Support self-signed certificates if (TLSConfig.DangerousAcceptAnyServerCertificateValidator) { // Install the all-trusting trust manager var trustManager = new CustomX509TrustManager(); sslContext.Init(KeyManagers, new ITrustManager[] { trustManager }, new SecureRandom()); // Create an ssl socket factory with our all-trusting manager var sslSocketFactory = sslContext.SocketFactory; clientBuilder.SslSocketFactory(sslSocketFactory, trustManager); } else { // Set SslSocketFactory if (Build.VERSION.SdkInt < BuildVersionCodes.Lollipop) { // Support TLS1.2 on Android versions before Lollipop ProviderInstaller.InstallIfNeeded(Application.Context); // To enable TLS clientBuilder.SslSocketFactory(new TlsSslSocketFactory(), TlsSslSocketFactory.GetSystemDefaultTrustManager()); } else { sslContext.Init(KeyManagers, null, null); clientBuilder.SslSocketFactory(sslContext.SocketFactory, TlsSslSocketFactory.GetSystemDefaultTrustManager()); } } clientBuilder.HostnameVerifier(new HostnameVerifier(this)); client = clientBuilder.Build(); }
/// <summary> /// Initializes a new instance of the <see /// cref="ModernHttpClient.NativeMessageHandler"/> class. /// </summary> /// <param name="throwOnCaptiveNetwork">If set to <c>true</c> throw on /// captive network (ie: a captive network is usually a wifi network /// where an authentication html form is shown instead of the real /// content).</param> /// <param name="sSLConfig">To enable TLS Mutual Authentication</param> /// <param name="cookieHandler">Enable native cookie handling. /// </param> public NativeMessageHandler(bool throwOnCaptiveNetwork, TLSConfig tLSConfig, NativeCookieHandler cookieHandler = null, IWebProxy proxy = null) : base() { }