port POSH code to OkHttp

This commit is contained in:
Daniel Gultsch 2021-03-22 14:32:31 +01:00
parent 70fc08314f
commit 8b90c1c498

View file

@ -31,6 +31,7 @@ import android.app.NotificationManager;
import android.app.Service; import android.app.Service;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri; import android.net.Uri;
import android.os.Handler; import android.os.Handler;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
@ -40,6 +41,9 @@ import android.util.SparseArray;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import com.google.common.base.Charsets;
import com.google.common.io.CharStreams;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
@ -52,7 +56,6 @@ import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.net.URL;
import java.security.KeyStore; import java.security.KeyStore;
import java.security.KeyStoreException; import java.security.KeyStoreException;
import java.security.MessageDigest; import java.security.MessageDigest;
@ -74,7 +77,6 @@ import java.util.logging.Logger;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.TrustManagerFactory;
@ -83,6 +85,7 @@ import javax.net.ssl.X509TrustManager;
import eu.siacs.conversations.R; import eu.siacs.conversations.R;
import eu.siacs.conversations.crypto.DomainHostnameVerifier; import eu.siacs.conversations.crypto.DomainHostnameVerifier;
import eu.siacs.conversations.entities.MTMDecision; import eu.siacs.conversations.entities.MTMDecision;
import eu.siacs.conversations.http.HttpConnectionManager;
import eu.siacs.conversations.persistance.FileBackend; import eu.siacs.conversations.persistance.FileBackend;
import eu.siacs.conversations.ui.MemorizingActivity; import eu.siacs.conversations.ui.MemorizingActivity;
@ -486,15 +489,18 @@ public class MemorizingTrustManager {
defaultTrustManager.checkServerTrusted(chain, authType); defaultTrustManager.checkServerTrusted(chain, authType);
else else
defaultTrustManager.checkClientTrusted(chain, authType); defaultTrustManager.checkClientTrusted(chain, authType);
} catch (CertificateException e) { } catch (final CertificateException e) {
boolean trustSystemCAs = !PreferenceManager.getDefaultSharedPreferences(master).getBoolean("dont_trust_system_cas", false); final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(master);
if (domain != null && isServer && trustSystemCAs && !isIp(domain)) { final boolean trustSystemCAs = !preferences.getBoolean("dont_trust_system_cas", false);
if (domain != null && isServer && trustSystemCAs && !isIp(domain) && !domain.endsWith(".onion")) {
final String hash = getBase64Hash(chain[0], "SHA-256"); final String hash = getBase64Hash(chain[0], "SHA-256");
final List<String> fingerprints = getPoshFingerprints(domain); final List<String> fingerprints = getPoshFingerprints(domain);
if (hash != null && fingerprints.size() > 0) { if (hash != null && fingerprints.size() > 0) {
if (fingerprints.contains(hash)) { if (fingerprints.contains(hash)) {
Log.d("mtm", "trusted cert fingerprint of " + domain + " via posh"); Log.d("mtm", "trusted cert fingerprint of " + domain + " via posh");
return; return;
} else {
Log.d("mtm", "fingerprint " + hash + " not found in " + fingerprints);
} }
if (getPoshCacheFile(domain).delete()) { if (getPoshCacheFile(domain).delete()) {
Log.d("mtm", "deleted posh file for " + domain + " after not being able to verify"); Log.d("mtm", "deleted posh file for " + domain + " after not being able to verify");
@ -511,7 +517,7 @@ public class MemorizingTrustManager {
} }
private List<String> getPoshFingerprints(String domain) { private List<String> getPoshFingerprints(String domain) {
List<String> cached = getPoshFingerprintsFromCache(domain); final List<String> cached = getPoshFingerprintsFromCache(domain);
if (cached == null) { if (cached == null) {
return getPoshFingerprintsFromServer(domain); return getPoshFingerprintsFromServer(domain);
} else { } else {
@ -525,19 +531,13 @@ public class MemorizingTrustManager {
private List<String> getPoshFingerprintsFromServer(String domain, String url, int maxTtl, boolean followUrl) { private List<String> getPoshFingerprintsFromServer(String domain, String url, int maxTtl, boolean followUrl) {
Log.d("mtm", "downloading json for " + domain + " from " + url); Log.d("mtm", "downloading json for " + domain + " from " + url);
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(master);
final boolean useTor = QuickConversationsService.isConversations() && preferences.getBoolean("use_tor", master.getResources().getBoolean(R.bool.use_tor));
try { try {
List<String> results = new ArrayList<>(); final List<String> results = new ArrayList<>();
HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection(); final InputStream inputStream = HttpConnectionManager.open(url, useTor);
connection.setConnectTimeout(5000); final String body = CharStreams.toString(new InputStreamReader(inputStream, Charsets.UTF_8));
connection.setReadTimeout(5000); final JSONObject jsonObject = new JSONObject(body);
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String inputLine;
StringBuilder builder = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
builder.append(inputLine);
}
JSONObject jsonObject = new JSONObject(builder.toString());
in.close();
int expires = jsonObject.getInt("expires"); int expires = jsonObject.getInt("expires");
if (expires <= 0) { if (expires <= 0) {
return new ArrayList<>(); return new ArrayList<>();
@ -554,17 +554,15 @@ public class MemorizingTrustManager {
if (followUrl && redirect != null && redirect.toLowerCase().startsWith("https")) { if (followUrl && redirect != null && redirect.toLowerCase().startsWith("https")) {
return getPoshFingerprintsFromServer(domain, redirect, expires, false); return getPoshFingerprintsFromServer(domain, redirect, expires, false);
} }
JSONArray fingerprints = jsonObject.getJSONArray("fingerprints"); final JSONArray fingerprints = jsonObject.getJSONArray("fingerprints");
for (int i = 0; i < fingerprints.length(); i++) { for (int i = 0; i < fingerprints.length(); i++) {
JSONObject fingerprint = fingerprints.getJSONObject(i); final JSONObject fingerprint = fingerprints.getJSONObject(i);
String sha256 = fingerprint.getString("sha-256"); final String sha256 = fingerprint.getString("sha-256");
if (sha256 != null) { results.add(sha256);
results.add(sha256);
}
} }
writeFingerprintsToCache(domain, results, 1000L * expires + System.currentTimeMillis()); writeFingerprintsToCache(domain, results, 1000L * expires + System.currentTimeMillis());
return results; return results;
} catch (Exception e) { } catch (final Exception e) {
Log.d("mtm", "error fetching posh " + e.getMessage()); Log.d("mtm", "error fetching posh " + e.getMessage());
return new ArrayList<>(); return new ArrayList<>();
} }
@ -575,7 +573,7 @@ public class MemorizingTrustManager {
} }
private void writeFingerprintsToCache(String domain, List<String> results, long expires) { private void writeFingerprintsToCache(String domain, List<String> results, long expires) {
File file = getPoshCacheFile(domain); final File file = getPoshCacheFile(domain);
file.getParentFile().mkdirs(); file.getParentFile().mkdirs();
try { try {
file.createNewFile(); file.createNewFile();