Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AndroidClientHandler TLS 1.1 and 1.2 support on Android 4.1 to 4.4 #1615

Closed
leonluc-dev opened this issue Apr 30, 2018 · 2 comments
Closed
Assignees

Comments

@leonluc-dev
Copy link
Contributor

leonluc-dev commented Apr 30, 2018

Currently the AndroidClientHandler only supports TLS 1.1 and TLS 1.2 on API Level 20 or up.

However, the SslSocket instances that Java.Net.HttpURLConnection (and by extension AndroidClientHandler) utilizes do have support for TLS 1.1 and 1.2, but they are disabled by default on API Level 16 to 19 (Android 4.1 to 4.4).

This is shown in the following screenshot when such a socket is examined during runtime on Android 4.1 to 4.4 (screenshot is API Level 17/Android 4.2):
afbeelding

Currently I solved this by subclassing AndroidClientHandler and implementing a custom SSLSocketFactory that builts upon the default implementation.

using Javax.Net.Ssl;
using Xamarin.Android.Net;

namespace MyAndroidApp.HelperClasses
{
    public class MyAndroidClientHandler : AndroidClientHandler
    {
        TlsSSLSocketFactory _customTlsSSLSocketFactory = new TlsSSLSocketFactory();
        protected override System.Threading.Tasks.Task SetupRequest(System.Net.Http.HttpRequestMessage request, Java.Net.HttpURLConnection conn)
        {
            if (conn is HttpsURLConnection sslConn)
            {
                if (Android.OS.Build.VERSION.SdkInt < Android.OS.BuildVersionCodes.Lollipop)
                    //Enable support for TLS v1.2 through custom TLS socketfactory
                    sslConn.SSLSocketFactory = _customTlsSSLSocketFactory;
            }
            return base.SetupRequest(request, conn);
        }


        private class TlsSSLSocketFactory : SSLSocketFactory
        {
            readonly SSLSocketFactory factory = (SSLSocketFactory)Default;

            public override string[] GetDefaultCipherSuites()
            {
                return factory.GetDefaultCipherSuites();
            }

            public override string[] GetSupportedCipherSuites()
            {
                return factory.GetSupportedCipherSuites();
            }
            public override Java.Net.Socket CreateSocket(Java.Net.InetAddress address, int port, Java.Net.InetAddress localAddress, int localPort)
            {
                return EnableTlsOnSocket(factory.CreateSocket(address, port, localAddress, localPort));
            }

            public override Java.Net.Socket CreateSocket(Java.Net.InetAddress host, int port)
            {
                return EnableTlsOnSocket(factory.CreateSocket(host, port));
            }

            public override Java.Net.Socket CreateSocket(string host, int port, Java.Net.InetAddress localHost, int localPort)
            {
                return EnableTlsOnSocket(factory.CreateSocket(host, port, localHost, localPort));
            }

            public override Java.Net.Socket CreateSocket(string host, int port)
            {
                return EnableTlsOnSocket(factory.CreateSocket(host, port));
            }

            public override Java.Net.Socket CreateSocket(Java.Net.Socket s, string host, int port, bool autoClose)
            {
                return EnableTlsOnSocket(factory.CreateSocket(s, host, port, autoClose));
            }

            public override Java.Net.Socket CreateSocket()
            {
                return EnableTlsOnSocket(factory.CreateSocket());
            }

            private Java.Net.Socket EnableTlsOnSocket(Java.Net.Socket socket)
            {
                if(socket != null && (socket is SSLSocket sslSocket))
                {
                    sslSocket.SetEnabledProtocols(sslSocket.GetSupportedProtocols());
                }
                return socket;
            }

           protected override void Dispose(bool disposing)
           {
                factory.Dispose();
                base.Dispose(disposing);
           }
        }
    }

}

It's based on a solution originally provided for ModernHttpClient
This allows the AndroidClientHandler to support TLS 1.1 and TLS 1.2 on pre-API 20 Android versions.

Does this solution have any major caveats to it, or could this possibly be implemented in AndroidClientHandler itself?

grendello added a commit to grendello/xamarin-android that referenced this issue Sep 14, 2018
Context: xamarin#1615

It turns out that the older platforms do support TLS 1.1 and 1.2 protocols but
that they don't enable it by default. Thanks to code provided by
https://github.com/gameleon-dev in the issue linked to above we now support it
too.

Updated the TLS 1.2 tests to enable them on platforms >= 16
@grendello
Copy link
Member

PR incorporating the code from OP is up, thanks @gameleon-dev!

grendello added a commit to grendello/xamarin-android that referenced this issue Sep 14, 2018
Context: xamarin#1615

It turns out that the older platforms do support TLS 1.1 and 1.2 protocols but
that they don't enable it by default. Thanks to code provided by
https://github.com/gameleon-dev in the issue linked to above we now support it
too.

Updated the TLS 1.2 tests to enable them on platforms >= 16
grendello added a commit to grendello/xamarin-android that referenced this issue Sep 14, 2018
Context: xamarin#1615

It turns out that the older platforms do support TLS 1.1 and 1.2 protocols but
that they don't enable it by default. Thanks to code provided by
https://github.com/gameleon-dev in the issue linked to above we now support it
too.

Updated the TLS 1.2 tests to enable them on platforms >= 16
@grendello
Copy link
Member

Fixed in: d8f1783

@xamarin xamarin locked as resolved and limited conversation to collaborators Jun 8, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants