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) { 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.M || NetworkSecurityPolicy.Instance.IsCleartextTrafficPermitted) { specs.Add(ConnectionSpec.Cleartext); } clientBuilder.ConnectionSpecs(specs); clientBuilder.Protocols(new[] { Protocol.Http11, Protocol.Http2 }); // 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 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(); }
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) { 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; } // 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 hostname = request.RequestUri.Host; 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.Contains(hostname)) { errors = SslPolicyErrors.RemoteCertificateNameMismatch; goto sslErrorVerify; } } if (this.CertificatePinner != null) { if (!this.CertificatePinner.HasPins(hostname)) { errors = SslPolicyErrors.RemoteCertificateNameMismatch; goto sslErrorVerify; } if (!this.CertificatePinner.Check(hostname, root.RawData)) { errors = SslPolicyErrors.RemoteCertificateNameMismatch; } } sslErrorVerify: return(errors == SslPolicyErrors.None); }; }