use bundled letsencrypt for uri link header checker

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/http/HttpConnectionManager.java       | 55 
src/main/java/eu/siacs/conversations/services/ChannelDiscoveryService.java | 32 
src/main/java/eu/siacs/conversations/ui/UriHandlerActivity.java            | 20 
src/main/res/layout/activity_uri_handler.xml                               |  6 
4 files changed, 58 insertions(+), 55 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/http/HttpConnectionManager.java 🔗

@@ -2,9 +2,24 @@ package eu.siacs.conversations.http;
 
 import static eu.siacs.conversations.utils.Random.SECURE_RANDOM;
 
+import android.content.Context;
 import android.os.Build;
 import android.util.Log;
 
+import eu.siacs.conversations.BuildConfig;
+import eu.siacs.conversations.Config;
+import eu.siacs.conversations.crypto.TrustManagers;
+import eu.siacs.conversations.entities.Account;
+import eu.siacs.conversations.entities.Message;
+import eu.siacs.conversations.services.AbstractConnectionManager;
+import eu.siacs.conversations.services.XmppConnectionService;
+import eu.siacs.conversations.utils.TLSSocketFactory;
+
+import okhttp3.HttpUrl;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.ResponseBody;
+
 import org.apache.http.conn.ssl.StrictHostnameVerifier;
 
 import java.io.IOException;
@@ -14,7 +29,9 @@ import java.net.InetSocketAddress;
 import java.net.Proxy;
 import java.net.UnknownHostException;
 import java.security.KeyManagementException;
+import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.Executor;
@@ -24,18 +41,6 @@ import java.util.concurrent.TimeUnit;
 import javax.net.ssl.SSLSocketFactory;
 import javax.net.ssl.X509TrustManager;
 
-import eu.siacs.conversations.BuildConfig;
-import eu.siacs.conversations.Config;
-import eu.siacs.conversations.entities.Account;
-import eu.siacs.conversations.entities.Message;
-import eu.siacs.conversations.services.AbstractConnectionManager;
-import eu.siacs.conversations.services.XmppConnectionService;
-import eu.siacs.conversations.utils.TLSSocketFactory;
-import okhttp3.HttpUrl;
-import okhttp3.OkHttpClient;
-import okhttp3.Request;
-import okhttp3.ResponseBody;
-
 public class HttpConnectionManager extends AbstractConnectionManager {
 
     private final List<HttpDownloadConnection> downloadConnections = new ArrayList<>();
@@ -43,7 +48,7 @@ public class HttpConnectionManager extends AbstractConnectionManager {
 
     public static final Executor EXECUTOR = Executors.newFixedThreadPool(4);
 
-    public static final OkHttpClient OK_HTTP_CLIENT;
+    private static final OkHttpClient OK_HTTP_CLIENT;
 
     static {
         OK_HTTP_CLIENT = new OkHttpClient.Builder()
@@ -173,4 +178,28 @@ public class HttpConnectionManager extends AbstractConnectionManager {
         }
         return body.byteStream();
     }
+
+
+    public static OkHttpClient okHttpClient(final Context context) {
+        final OkHttpClient.Builder builder = HttpConnectionManager.OK_HTTP_CLIENT.newBuilder();
+        try {
+            final X509TrustManager trustManager;
+            if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N) {
+                trustManager = TrustManagers.defaultWithBundledLetsEncrypt(context);
+            } else {
+                trustManager = TrustManagers.createDefaultTrustManager();
+            }
+            final SSLSocketFactory socketFactory =
+                    new TLSSocketFactory(new X509TrustManager[] {trustManager}, SECURE_RANDOM);
+            builder.sslSocketFactory(socketFactory, trustManager);
+        } catch (final IOException
+                       | KeyManagementException
+                       | NoSuchAlgorithmException
+                       | KeyStoreException
+                       | CertificateException e) {
+            Log.d(Config.LOGTAG, "not reconfiguring service to work with bundled LetsEncrypt");
+            throw new RuntimeException(e);
+        }
+        return builder.build();
+    }
 }

src/main/java/eu/siacs/conversations/services/ChannelDiscoveryService.java 🔗

@@ -1,8 +1,6 @@
 package eu.siacs.conversations.services;
 
-import static eu.siacs.conversations.utils.Random.SECURE_RANDOM;
 
-import android.os.Build;
 import android.util.Log;
 
 import androidx.annotation.NonNull;
@@ -12,17 +10,16 @@ import com.google.common.cache.Cache;
 import com.google.common.cache.CacheBuilder;
 
 import eu.siacs.conversations.Config;
-import eu.siacs.conversations.crypto.TrustManagers;
 import eu.siacs.conversations.entities.Account;
 import eu.siacs.conversations.entities.Room;
 import eu.siacs.conversations.http.HttpConnectionManager;
 import eu.siacs.conversations.http.services.MuclumbusService;
 import eu.siacs.conversations.parser.IqParser;
-import eu.siacs.conversations.utils.TLSSocketFactory;
 import eu.siacs.conversations.xmpp.Jid;
 import eu.siacs.conversations.xmpp.XmppConnection;
 
 import im.conversations.android.xmpp.model.stanza.Iq;
+
 import okhttp3.OkHttpClient;
 import okhttp3.ResponseBody;
 
@@ -33,10 +30,6 @@ import retrofit2.Retrofit;
 import retrofit2.converter.gson.GsonConverterFactory;
 
 import java.io.IOException;
-import java.security.KeyManagementException;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.CertificateException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -46,9 +39,6 @@ import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import javax.net.ssl.SSLSocketFactory;
-import javax.net.ssl.X509TrustManager;
-
 public class ChannelDiscoveryService {
 
     private final XmppConnectionService service;
@@ -67,25 +57,7 @@ public class ChannelDiscoveryService {
             this.muclumbusService = null;
             return;
         }
-        final OkHttpClient.Builder builder = HttpConnectionManager.OK_HTTP_CLIENT.newBuilder();
-        try {
-            final X509TrustManager trustManager;
-            if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N) {
-                trustManager = TrustManagers.defaultWithBundledLetsEncrypt(service);
-            } else {
-                trustManager = TrustManagers.createDefaultTrustManager();
-            }
-            final SSLSocketFactory socketFactory =
-                    new TLSSocketFactory(new X509TrustManager[] {trustManager}, SECURE_RANDOM);
-            builder.sslSocketFactory(socketFactory, trustManager);
-        } catch (final IOException
-                | KeyManagementException
-                | NoSuchAlgorithmException
-                | KeyStoreException
-                | CertificateException e) {
-            Log.d(Config.LOGTAG, "not reconfiguring service to work with bundled LetsEncrypt");
-            throw new RuntimeException(e);
-        }
+        final OkHttpClient.Builder builder = HttpConnectionManager.okHttpClient(service).newBuilder();
         if (service.useTorToConnect()) {
             builder.proxy(HttpConnectionManager.getProxy());
         }

src/main/java/eu/siacs/conversations/ui/UriHandlerActivity.java 🔗

@@ -5,7 +5,6 @@ import android.app.Activity;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.net.Uri;
-import android.os.Build;
 import android.os.Bundle;
 import android.util.Log;
 import android.view.View;
@@ -57,9 +56,7 @@ public class UriHandlerActivity extends BaseActivity {
     }
 
     public static void scan(final Activity activity, final boolean provisioning) {
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M
-                || ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA)
-                        == PackageManager.PERMISSION_GRANTED) {
+        if (ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
             final Intent intent = new Intent(activity, UriHandlerActivity.class);
             intent.setAction(UriHandlerActivity.ACTION_SCAN_QR_CODE);
             if (provisioning) {
@@ -103,6 +100,7 @@ public class UriHandlerActivity extends BaseActivity {
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         this.binding = DataBindingUtil.setContentView(this, R.layout.activity_uri_handler);
+        Activities.setStatusAndNavigationBarColors(this, binding.getRoot());
     }
 
     @Override
@@ -138,7 +136,7 @@ public class UriHandlerActivity extends BaseActivity {
                 startActivity(intent);
                 return true;
             }
-            if (accounts.size() == 0
+            if (accounts.isEmpty()
                     && xmppUri.isAction(XmppUri.ACTION_ROSTER)
                     && "y"
                             .equalsIgnoreCase(
@@ -154,7 +152,7 @@ public class UriHandlerActivity extends BaseActivity {
             return false;
         }
 
-        if (accounts.size() == 0) {
+        if (accounts.isEmpty()) {
             if (xmppUri.isValidJid()) {
                 intent = SignupUtils.getSignUpIntent(this);
                 intent.putExtra(StartConversationActivity.EXTRA_INVITE_URI, xmppUri.toString());
@@ -211,14 +209,14 @@ public class UriHandlerActivity extends BaseActivity {
     private void checkForLinkHeader(final HttpUrl url) {
         Log.d(Config.LOGTAG, "checking for link header on " + url);
         this.call =
-                HttpConnectionManager.OK_HTTP_CLIENT.newCall(
+                HttpConnectionManager.okHttpClient(this).newCall(
                         new Request.Builder().url(url).head().build());
         this.call.enqueue(
                 new Callback() {
                     @Override
                     public void onFailure(@NonNull Call call, @NonNull IOException e) {
                         Log.d(Config.LOGTAG, "unable to check HTTP url", e);
-                        showError(R.string.no_xmpp_adddress_found);
+                        showErrorOnUiThread(R.string.no_xmpp_adddress_found);
                     }
 
                     @Override
@@ -229,7 +227,7 @@ public class UriHandlerActivity extends BaseActivity {
                                 return;
                             }
                         }
-                        showError(R.string.no_xmpp_adddress_found);
+                        showErrorOnUiThread(R.string.no_xmpp_adddress_found);
                     }
                 });
     }
@@ -253,6 +251,10 @@ public class UriHandlerActivity extends BaseActivity {
         this.binding.error.setVisibility(View.VISIBLE);
     }
 
+    private void showErrorOnUiThread(@StringRes int error) {
+        runOnUiThread(()-> showError(error));
+    }
+
     private static Class<?> findShareViaAccountClass() {
         try {
             return Class.forName("eu.siacs.conversations.ui.ShareViaAccountActivity");

src/main/res/layout/activity_uri_handler.xml 🔗

@@ -4,7 +4,7 @@
     <RelativeLayout
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:background="?colorPrimaryContainer"
+        android:background="?colorSurface"
         android:padding="24dp">
 
         <ProgressBar
@@ -13,7 +13,7 @@
             android:layout_height="wrap_content"
             android:layout_centerInParent="true"
             android:indeterminate="true"
-            android:indeterminateTint="?colorOnPrimaryContainer" />
+            android:indeterminateTint="?colorPrimary" />
 
         <TextView
             android:id="@+id/error"
@@ -24,7 +24,7 @@
             android:layout_marginTop="16dp"
             android:gravity="center_horizontal"
             android:textAppearance="?textAppearanceBodyMedium"
-            android:textColor="?colorOnPrimaryContainer"
+            android:textColor="?colorError"
             android:visibility="invisible" />
 
     </RelativeLayout>