use bundled letsencrypt for quicksy registration

Daniel Gultsch created

Change summary

src/quicksy/java/eu/siacs/conversations/services/QuickConversationsService.java | 45 
1 file changed, 43 insertions(+), 2 deletions(-)

Detailed changes

src/quicksy/java/eu/siacs/conversations/services/QuickConversationsService.java 🔗

@@ -1,9 +1,13 @@
 package eu.siacs.conversations.services;
 
 
+import static eu.siacs.conversations.utils.Random.SECURE_RANDOM;
+
+import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.SystemClock;
 import android.preference.PreferenceManager;
@@ -21,6 +25,9 @@ import java.net.SocketTimeoutException;
 import java.net.URL;
 import java.net.UnknownHostException;
 import java.security.GeneralSecurityException;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
 import java.security.cert.CertificateException;
 import java.util.ArrayList;
@@ -38,12 +45,16 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import javax.net.ssl.HttpsURLConnection;
 import javax.net.ssl.SSLException;
 import javax.net.ssl.SSLHandshakeException;
 import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.X509TrustManager;
 
 import eu.siacs.conversations.Config;
 import eu.siacs.conversations.android.PhoneNumberContact;
+import eu.siacs.conversations.crypto.TrustManagers;
 import eu.siacs.conversations.crypto.sasl.Plain;
 import eu.siacs.conversations.entities.Account;
 import eu.siacs.conversations.entities.Contact;
@@ -54,6 +65,7 @@ import eu.siacs.conversations.utils.CryptoHelper;
 import eu.siacs.conversations.utils.PhoneNumberUtilWrapper;
 import eu.siacs.conversations.utils.SerialSingleThreadExecutor;
 import eu.siacs.conversations.utils.SmsRetrieverWrapper;
+import eu.siacs.conversations.utils.TLSSocketFactory;
 import eu.siacs.conversations.xml.Element;
 import eu.siacs.conversations.xml.Namespace;
 import eu.siacs.conversations.xmpp.Jid;
@@ -133,7 +145,8 @@ public class QuickConversationsService extends AbstractQuickConversationsService
             new Thread(() -> {
                 try {
                     final URL url = new URL(BASE_URL + "/authentication/" + e164);
-                    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+                    final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+                    setBundledLetsEncrypt(service, connection);
                     connection.setConnectTimeout(Config.SOCKET_TIMEOUT * 1000);
                     connection.setReadTimeout(Config.SOCKET_TIMEOUT * 1000);
                     setHeader(connection);
@@ -161,8 +174,35 @@ public class QuickConversationsService extends AbstractQuickConversationsService
                 }
             }).start();
         }
+    }
 
-
+    private static void setBundledLetsEncrypt(
+            final Context context, final HttpURLConnection connection) {
+        if (connection instanceof HttpsURLConnection httpsURLConnection) {
+            final X509TrustManager trustManager;
+            if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N) {
+                try {
+                    trustManager = TrustManagers.defaultWithBundledLetsEncrypt(context);
+                } catch (final NoSuchAlgorithmException
+                        | KeyStoreException
+                        | CertificateException
+                        | IOException e) {
+                    Log.e(Config.LOGTAG, "could not configured bundled LetsEncrypt", e);
+                    return;
+                }
+            } else {
+                return;
+            }
+            final SSLSocketFactory socketFactory;
+            try {
+                socketFactory =
+                        new TLSSocketFactory(new X509TrustManager[] {trustManager}, SECURE_RANDOM);
+            } catch (final KeyManagementException | NoSuchAlgorithmException e) {
+                Log.e(Config.LOGTAG, "could not configured bundled LetsEncrypt", e);
+                return;
+            }
+            httpsURLConnection.setSSLSocketFactory(socketFactory);
+        }
     }
 
     public void signalAccountStateChange() {
@@ -204,6 +244,7 @@ public class QuickConversationsService extends AbstractQuickConversationsService
                 try {
                     final URL url = new URL(BASE_URL + "/password");
                     final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+                    setBundledLetsEncrypt(service, connection);
                     connection.setConnectTimeout(Config.SOCKET_TIMEOUT * 1000);
                     connection.setReadTimeout(Config.SOCKET_TIMEOUT * 1000);
                     connection.setRequestMethod("POST");