diff options
author | Christian Schneppe <christian.schneppe@pix-art.de> | 2019-12-08 15:40:58 +0100 |
---|---|---|
committer | Christian Schneppe <christian.schneppe@pix-art.de> | 2019-12-08 15:40:58 +0100 |
commit | 31c16b0f8fb54c26e45cdee9a4b47cfe4e5994fa (patch) | |
tree | 95a704f39d8adda949531263c51cf2ab73b3f31c /src/main/java | |
parent | 32b1ab2b3b54c53e61c61bc779ae01bc9b62c776 (diff) |
delete cached posh file after not being able to verify
Diffstat (limited to 'src/main/java')
-rw-r--r-- | src/main/java/de/pixart/messenger/services/MemorizingTrustManager.java | 93 |
1 files changed, 49 insertions, 44 deletions
diff --git a/src/main/java/de/pixart/messenger/services/MemorizingTrustManager.java b/src/main/java/de/pixart/messenger/services/MemorizingTrustManager.java index 899a12d5b..f321332d7 100644 --- a/src/main/java/de/pixart/messenger/services/MemorizingTrustManager.java +++ b/src/main/java/de/pixart/messenger/services/MemorizingTrustManager.java @@ -34,11 +34,12 @@ import android.content.Intent; import android.net.Uri; import android.os.Handler; import android.preference.PreferenceManager; -import androidx.appcompat.app.AppCompatActivity; import android.util.Base64; import android.util.Log; import android.util.SparseArray; +import androidx.appcompat.app.AppCompatActivity; + import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -104,12 +105,12 @@ public class MemorizingTrustManager { private static final Pattern PATTERN_IPV6 = Pattern.compile("\\A(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\\z"); final static String DECISION_INTENT = "de.duenndns.ssl.DECISION"; - public final static String DECISION_INTENT_ID = DECISION_INTENT + ".decisionId"; - public final static String DECISION_INTENT_CERT = DECISION_INTENT + ".cert"; + public final static String DECISION_INTENT_ID = DECISION_INTENT + ".decisionId"; + public final static String DECISION_INTENT_CERT = DECISION_INTENT + ".cert"; final static String DECISION_INTENT_CHOICE = DECISION_INTENT + ".decisionChoice"; private final static Logger LOGGER = Logger.getLogger(MemorizingTrustManager.class.getName()); - public final static String DECISION_TITLE_ID = DECISION_INTENT + ".titleId"; + public final static String DECISION_TITLE_ID = DECISION_INTENT + ".titleId"; private final static int NOTIFICATION_ID = 100509; final static String NO_TRUST_ANCHOR = "Trust anchor for certification path not found."; @@ -170,21 +171,22 @@ public class MemorizingTrustManager { void init(Context m) { master = m; masterHandler = new Handler(m.getMainLooper()); - notificationManager = (NotificationManager)master.getSystemService(Context.NOTIFICATION_SERVICE); + notificationManager = (NotificationManager) master.getSystemService(Context.NOTIFICATION_SERVICE); Application app; if (m instanceof Application) { - app = (Application)m; + app = (Application) m; } else if (m instanceof Service) { - app = ((Service)m).getApplication(); + app = ((Service) m).getApplication(); } else if (m instanceof AppCompatActivity) { - app = ((AppCompatActivity)m).getApplication(); - } else throw new ClassCastException("MemorizingTrustManager context must be either Activity or Service!"); + app = ((AppCompatActivity) m).getApplication(); + } else + throw new ClassCastException("MemorizingTrustManager context must be either Activity or Service!"); File dir = app.getDir(KEYSTORE_DIR, Context.MODE_PRIVATE); keyStoreFile = new File(dir + File.separator + KEYSTORE_FILE); - poshCacheDir = app.getFilesDir().getAbsolutePath()+"/posh_cache/"; + poshCacheDir = app.getCacheDir().getAbsolutePath() + "/posh_cache/"; appKeyStore = loadAppKeyStore(); } @@ -315,7 +317,7 @@ public class MemorizingTrustManager { tmf.init(ks); for (TrustManager t : tmf.getTrustManagers()) { if (t instanceof X509TrustManager) { - return (X509TrustManager)t; + return (X509TrustManager) t; } } } catch (Exception e) { @@ -401,8 +403,7 @@ public class MemorizingTrustManager { } public void checkCertTrusted(X509Certificate[] chain, String authType, String domain, boolean isServer, boolean interactive) - throws CertificateException - { + throws CertificateException { LOGGER.log(Level.FINE, "checkCertTrusted(" + chain + ", " + authType + ", " + isServer + ")"); try { LOGGER.log(Level.FINE, "checkCertTrusted: trying appTrustManager"); @@ -432,14 +433,18 @@ public class MemorizingTrustManager { } catch (CertificateException e) { boolean trustSystemCAs = !PreferenceManager.getDefaultSharedPreferences(master).getBoolean("dont_trust_system_cas", false); if (domain != null && isServer && trustSystemCAs && !isIp(domain)) { - String hash = getBase64Hash(chain[0],"SHA-256"); - List<String> fingerprints = getPoshFingerprints(domain); - if (hash != null && fingerprints.contains(hash)) { - Log.d("mtm","trusted cert fingerprint of "+domain+" via posh"); - return; + final String hash = getBase64Hash(chain[0], "SHA-256"); + final List<String> fingerprints = getPoshFingerprints(domain); + if (hash != null && fingerprints.size() > 0) { + if (fingerprints.contains(hash)) { + Log.d("mtm", "trusted cert fingerprint of " + domain + " via posh"); + return; + } + if (getPoshCacheFile(domain).delete()) { + Log.d("mtm", "deleted posh file for " + domain + " after not being able to verify"); + } } } - e.printStackTrace(); if (interactive) { interactCert(chain, authType, e); } else { @@ -459,11 +464,11 @@ public class MemorizingTrustManager { } private List<String> getPoshFingerprintsFromServer(String domain) { - return getPoshFingerprintsFromServer(domain, "https://"+domain+"/.well-known/posh/xmpp-client.json",-1,true); + return getPoshFingerprintsFromServer(domain, "https://" + domain + "/.well-known/posh/xmpp-client.json", -1, true); } 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); try { List<String> results = new ArrayList<>(); HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection(); @@ -482,7 +487,7 @@ public class MemorizingTrustManager { return new ArrayList<>(); } if (maxTtl >= 0) { - expires = Math.min(maxTtl,expires); + expires = Math.min(maxTtl, expires); } String redirect; try { @@ -494,23 +499,23 @@ public class MemorizingTrustManager { return getPoshFingerprintsFromServer(domain, redirect, expires, false); } 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); String sha256 = fingerprint.getString("sha-256"); if (sha256 != null) { results.add(sha256); } } - writeFingerprintsToCache(domain, results,1000L * expires+System.currentTimeMillis()); + writeFingerprintsToCache(domain, results, 1000L * expires + System.currentTimeMillis()); return results; } catch (Exception e) { - Log.d("mtm","error fetching posh "+e.getMessage()); + Log.d("mtm", "error fetching posh " + e.getMessage()); return new ArrayList<>(); } } private File getPoshCacheFile(String domain) { - return new File(poshCacheDir+domain+".json"); + return new File(poshCacheDir + domain + ".json"); } private void writeFingerprintsToCache(String domain, List<String> results, long expires) { @@ -519,8 +524,8 @@ public class MemorizingTrustManager { try { file.createNewFile(); JSONObject jsonObject = new JSONObject(); - jsonObject.put("expires",expires); - jsonObject.put("fingerprints",new JSONArray(results)); + jsonObject.put("expires", expires); + jsonObject.put("fingerprints", new JSONArray(results)); FileOutputStream outputStream = new FileOutputStream(file); outputStream.write(jsonObject.toString().getBytes()); outputStream.flush(); @@ -539,7 +544,7 @@ public class MemorizingTrustManager { String line = buf.readLine(); StringBuilder sb = new StringBuilder(); - while(line != null){ + while (line != null) { sb.append(line).append("\n"); line = buf.readLine(); } @@ -551,11 +556,11 @@ public class MemorizingTrustManager { file.delete(); return null; } else { - Log.d("mtm","posh fingerprints expire in "+(expiresIn/1000)+"s"); + Log.d("mtm", "posh fingerprints expire in " + (expiresIn / 1000) + "s"); } List<String> result = new ArrayList<>(); JSONArray jsonArray = jsonObject.getJSONArray("fingerprints"); - for(int i = 0; i < jsonArray.length(); ++i) { + for (int i = 0; i < jsonArray.length(); ++i) { result.add(jsonArray.getString(i)); } return result; @@ -586,7 +591,7 @@ public class MemorizingTrustManager { return null; } md.update(certificate.getEncoded()); - return Base64.encodeToString(md.digest(),Base64.NO_WRAP); + return Base64.encodeToString(md.digest(), Base64.NO_WRAP); } private X509Certificate[] getAcceptedIssuers() { @@ -596,7 +601,7 @@ public class MemorizingTrustManager { private int createDecisionId(MTMDecision d) { int myId; - synchronized(openDecisions) { + synchronized (openDecisions) { myId = decisionId; openDecisions.put(myId, d); decisionId += 1; @@ -681,7 +686,7 @@ public class MemorizingTrustManager { Object name = altName.get(1); if (name instanceof String) { si.append("["); - si.append((Integer)altName.get(0)); + si.append((Integer) altName.get(0)); si.append("] "); si.append(name); si.append("\n"); @@ -735,7 +740,9 @@ public class MemorizingTrustManager { LOGGER.log(Level.FINE, "openDecisions: " + openDecisions + ", waiting on " + myId); try { - synchronized(choice) { choice.wait(); } + synchronized (choice) { + choice.wait(); + } } catch (InterruptedException e) { LOGGER.log(Level.FINER, "InterruptedException", e); } @@ -744,8 +751,7 @@ public class MemorizingTrustManager { } void interactCert(final X509Certificate[] chain, String authType, CertificateException cause) - throws CertificateException - { + throws CertificateException { switch (interact(certChainMessage(chain, cause), R.string.mtm_accept_cert)) { case MTMDecision.DECISION_ALWAYS: storeCert(chain[0]); // only store the server cert, not the whole chain @@ -756,8 +762,7 @@ public class MemorizingTrustManager { } } - boolean interactHostname(X509Certificate cert, String hostname) - { + boolean interactHostname(X509Certificate cert, String hostname) { switch (interact(hostNameMessage(cert, hostname), R.string.mtm_accept_servername)) { case MTMDecision.DECISION_ALWAYS: storeCert(hostname, cert); @@ -770,7 +775,7 @@ public class MemorizingTrustManager { public static void interactResult(int decisionId, int choice) { MTMDecision d; - synchronized(openDecisions) { + synchronized (openDecisions) { d = openDecisions.get(decisionId); openDecisions.remove(decisionId); } @@ -778,7 +783,7 @@ public class MemorizingTrustManager { LOGGER.log(Level.SEVERE, "interactResult: aborting due to stale decision reference!"); return; } - synchronized(d) { + synchronized (d) { d.state = choice; d.notify(); } @@ -798,7 +803,7 @@ public class MemorizingTrustManager { LOGGER.log(Level.FINE, "hostname verifier for " + domain + ", trying default verifier first"); // if the default verifier accepts the hostname, we are done if (defaultVerifier instanceof DomainHostnameVerifier) { - if (((DomainHostnameVerifier) defaultVerifier).verify(domain,hostname, session)) { + if (((DomainHostnameVerifier) defaultVerifier).verify(domain, hostname, session)) { return true; } } else { @@ -810,7 +815,7 @@ public class MemorizingTrustManager { // otherwise, we check if the hostname is an alias for this cert in our keystore try { - X509Certificate cert = (X509Certificate)session.getPeerCertificates()[0]; + X509Certificate cert = (X509Certificate) session.getPeerCertificates()[0]; //Log.d(TAG, "cert: " + cert); if (cert.equals(appKeyStore.getCertificate(domain.toLowerCase(Locale.US)))) { LOGGER.log(Level.FINE, "certificate for " + domain + " is in our keystore. accepting."); @@ -831,7 +836,7 @@ public class MemorizingTrustManager { @Override public boolean verify(String domain, SSLSession sslSession) { - return verify(domain,null,sslSession); + return verify(domain, null, sslSession); } } |