From b4996c0e6de03056b76fe89cdf8f57b2a6b673be Mon Sep 17 00:00:00 2001 From: anonTree1417 Date: Tue, 31 Mar 2020 21:14:49 +0200 Subject: [PATCH] Even more reformatting. --- .../mian/gitnex/clients/IssuesService.java | 69 ++--- .../gitnex/clients/PullRequestsService.java | 69 ++--- .../mian/gitnex/clients/RetrofitClient.java | 84 +++-- .../gitnex/helpers/MemorizingActivity.java | 3 + .../helpers/MemorizingTrustManager.java | 286 +++++++++++------- 5 files changed, 290 insertions(+), 221 deletions(-) diff --git a/app/src/main/java/org/mian/gitnex/clients/IssuesService.java b/app/src/main/java/org/mian/gitnex/clients/IssuesService.java index 28d26ac7..999b9ad7 100644 --- a/app/src/main/java/org/mian/gitnex/clients/IssuesService.java +++ b/app/src/main/java/org/mian/gitnex/clients/IssuesService.java @@ -26,48 +26,49 @@ import retrofit2.converter.gson.GsonConverterFactory; public class IssuesService { - public static S createService(Class serviceClass, String instanceURL, Context ctx) { + public static S createService(Class serviceClass, String instanceURL, Context ctx) { - final boolean connToInternet = AppUtil.haveNetworkConnection(ctx); - File httpCacheDirectory = new File(ctx.getCacheDir(), "responses"); - int cacheSize = 50 * 1024 * 1024; // 50MB - Cache cache = new Cache(httpCacheDirectory, cacheSize); + final boolean connToInternet = AppUtil.haveNetworkConnection(ctx); + File httpCacheDirectory = new File(ctx.getCacheDir(), "responses"); + int cacheSize = 50 * 1024 * 1024; // 50MB + Cache cache = new Cache(httpCacheDirectory, cacheSize); - HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); - logging.setLevel(HttpLoggingInterceptor.Level.BODY); + HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); + logging.setLevel(HttpLoggingInterceptor.Level.BODY); - try { - SSLContext sslContext = SSLContext.getInstance("TLS"); + try { + SSLContext sslContext = SSLContext.getInstance("TLS"); - MemorizingTrustManager memorizingTrustManager = new MemorizingTrustManager(ctx); - sslContext.init(null, new X509TrustManager[]{memorizingTrustManager}, new SecureRandom()); + MemorizingTrustManager memorizingTrustManager = new MemorizingTrustManager(ctx); + sslContext.init(null, new X509TrustManager[]{memorizingTrustManager}, new SecureRandom()); - OkHttpClient okHttpClient = new OkHttpClient.Builder().cache(cache).sslSocketFactory(sslContext.getSocketFactory(), memorizingTrustManager).hostnameVerifier(memorizingTrustManager.wrapHostnameVerifier(HttpsURLConnection.getDefaultHostnameVerifier())).addInterceptor(new Interceptor() { + OkHttpClient okHttpClient = new OkHttpClient.Builder().cache(cache).sslSocketFactory(sslContext.getSocketFactory(), memorizingTrustManager).hostnameVerifier(memorizingTrustManager.wrapHostnameVerifier(HttpsURLConnection.getDefaultHostnameVerifier())).addInterceptor(new Interceptor() { - @NonNull - @Override - public Response intercept(@NonNull Chain chain) throws IOException { + @NonNull + @Override + public Response intercept(@NonNull Chain chain) throws IOException { - Request request = chain.request(); - if(connToInternet) { - request = request.newBuilder().header("Cache-Control", "public, max-age=" + 60).build(); - } - else { - request = request.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + 60 * 60 * 24 * 30).build(); - } - return chain.proceed(request); - } - }).build(); + Request request = chain.request(); + if(connToInternet) { + request = request.newBuilder().header("Cache-Control", "public, max-age=" + 60).build(); + } + else { + request = request.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + 60 * 60 * 24 * 30).build(); + } + return chain.proceed(request); + } + }).build(); - Retrofit.Builder builder = new Retrofit.Builder().baseUrl(instanceURL).client(okHttpClient).addConverterFactory(GsonConverterFactory.create()); + Retrofit.Builder builder = new Retrofit.Builder().baseUrl(instanceURL).client(okHttpClient).addConverterFactory(GsonConverterFactory.create()); - Retrofit retrofit = builder.build(); - return retrofit.create(serviceClass); - } - catch(Exception e) { - Log.e("onFailure", e.toString()); - } + Retrofit retrofit = builder.build(); + return retrofit.create(serviceClass); + } + catch(Exception e) { + Log.e("onFailure", e.toString()); + } + + return null; + } - return null; - } } diff --git a/app/src/main/java/org/mian/gitnex/clients/PullRequestsService.java b/app/src/main/java/org/mian/gitnex/clients/PullRequestsService.java index 50731225..bf2beb96 100644 --- a/app/src/main/java/org/mian/gitnex/clients/PullRequestsService.java +++ b/app/src/main/java/org/mian/gitnex/clients/PullRequestsService.java @@ -26,48 +26,49 @@ import retrofit2.converter.gson.GsonConverterFactory; public class PullRequestsService { - public static S createService(Class serviceClass, String instanceURL, Context ctx) { + public static S createService(Class serviceClass, String instanceURL, Context ctx) { - final boolean connToInternet = AppUtil.haveNetworkConnection(ctx); - File httpCacheDirectory = new File(ctx.getCacheDir(), "responses"); - int cacheSize = 50 * 1024 * 1024; // 50MB - Cache cache = new Cache(httpCacheDirectory, cacheSize); + final boolean connToInternet = AppUtil.haveNetworkConnection(ctx); + File httpCacheDirectory = new File(ctx.getCacheDir(), "responses"); + int cacheSize = 50 * 1024 * 1024; // 50MB + Cache cache = new Cache(httpCacheDirectory, cacheSize); - HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); - logging.setLevel(HttpLoggingInterceptor.Level.BODY); + HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); + logging.setLevel(HttpLoggingInterceptor.Level.BODY); - try { - SSLContext sslContext = SSLContext.getInstance("TLS"); + try { + SSLContext sslContext = SSLContext.getInstance("TLS"); - MemorizingTrustManager memorizingTrustManager = new MemorizingTrustManager(ctx); - sslContext.init(null, new X509TrustManager[]{memorizingTrustManager}, new SecureRandom()); + MemorizingTrustManager memorizingTrustManager = new MemorizingTrustManager(ctx); + sslContext.init(null, new X509TrustManager[]{memorizingTrustManager}, new SecureRandom()); - OkHttpClient okHttpClient = new OkHttpClient.Builder().cache(cache).sslSocketFactory(sslContext.getSocketFactory(), memorizingTrustManager).hostnameVerifier(memorizingTrustManager.wrapHostnameVerifier(HttpsURLConnection.getDefaultHostnameVerifier())).addInterceptor(new Interceptor() { + OkHttpClient okHttpClient = new OkHttpClient.Builder().cache(cache).sslSocketFactory(sslContext.getSocketFactory(), memorizingTrustManager).hostnameVerifier(memorizingTrustManager.wrapHostnameVerifier(HttpsURLConnection.getDefaultHostnameVerifier())).addInterceptor(new Interceptor() { - @NonNull - @Override - public Response intercept(@NonNull Chain chain) throws IOException { + @NonNull + @Override + public Response intercept(@NonNull Chain chain) throws IOException { - Request request = chain.request(); - if(connToInternet) { - request = request.newBuilder().header("Cache-Control", "public, max-age=" + 60).build(); - } - else { - request = request.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + 60 * 60 * 24 * 30).build(); - } - return chain.proceed(request); - } - }).build(); + Request request = chain.request(); + if(connToInternet) { + request = request.newBuilder().header("Cache-Control", "public, max-age=" + 60).build(); + } + else { + request = request.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + 60 * 60 * 24 * 30).build(); + } + return chain.proceed(request); + } + }).build(); - Retrofit.Builder builder = new Retrofit.Builder().baseUrl(instanceURL).client(okHttpClient).addConverterFactory(GsonConverterFactory.create()); + Retrofit.Builder builder = new Retrofit.Builder().baseUrl(instanceURL).client(okHttpClient).addConverterFactory(GsonConverterFactory.create()); - Retrofit retrofit = builder.build(); - return retrofit.create(serviceClass); - } - catch(Exception e) { - Log.e("onFailure", e.toString()); - } + Retrofit retrofit = builder.build(); + return retrofit.create(serviceClass); + } + catch(Exception e) { + Log.e("onFailure", e.toString()); + } + + return null; + } - return null; - } } diff --git a/app/src/main/java/org/mian/gitnex/clients/RetrofitClient.java b/app/src/main/java/org/mian/gitnex/clients/RetrofitClient.java index a2794ec7..9e677ff9 100644 --- a/app/src/main/java/org/mian/gitnex/clients/RetrofitClient.java +++ b/app/src/main/java/org/mian/gitnex/clients/RetrofitClient.java @@ -24,60 +24,56 @@ import retrofit2.converter.scalars.ScalarsConverterFactory; public class RetrofitClient { - private Retrofit retrofit; + private Retrofit retrofit; - private RetrofitClient(String instanceUrl, Context ctx) { - final boolean connToInternet = AppUtil.haveNetworkConnection(ctx); - int cacheSize = 50 * 1024 * 1024; // 50MB - File httpCacheDirectory = new File(ctx.getCacheDir(), "responses"); - Cache cache = new Cache(httpCacheDirectory, cacheSize); + private RetrofitClient(String instanceUrl, Context ctx) { - HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); - logging.setLevel(HttpLoggingInterceptor.Level.BODY); + final boolean connToInternet = AppUtil.haveNetworkConnection(ctx); + int cacheSize = 50 * 1024 * 1024; // 50MB + File httpCacheDirectory = new File(ctx.getCacheDir(), "responses"); + Cache cache = new Cache(httpCacheDirectory, cacheSize); - try { - SSLContext sslContext = SSLContext.getInstance("TLS"); + HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); + logging.setLevel(HttpLoggingInterceptor.Level.BODY); - MemorizingTrustManager memorizingTrustManager = new MemorizingTrustManager(ctx); - sslContext.init(null, new X509TrustManager[] { memorizingTrustManager }, new SecureRandom()); + try { + SSLContext sslContext = SSLContext.getInstance("TLS"); - OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder() - .cache(cache) - //.addInterceptor(logging) - .sslSocketFactory(sslContext.getSocketFactory(), memorizingTrustManager) - .hostnameVerifier(memorizingTrustManager.wrapHostnameVerifier(HttpsURLConnection.getDefaultHostnameVerifier())) - .addInterceptor(chain -> { + MemorizingTrustManager memorizingTrustManager = new MemorizingTrustManager(ctx); + sslContext.init(null, new X509TrustManager[]{memorizingTrustManager}, new SecureRandom()); - Request request = chain.request(); - if(connToInternet) { - request = request.newBuilder().header("Cache-Control", "public, max-age=" + 60).build(); - } - else { - request = request.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + 60 * 60 * 24 * 30).build(); - } - return chain.proceed(request); - }); + OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder().cache(cache) + //.addInterceptor(logging) + .sslSocketFactory(sslContext.getSocketFactory(), memorizingTrustManager).hostnameVerifier(memorizingTrustManager.wrapHostnameVerifier(HttpsURLConnection.getDefaultHostnameVerifier())).addInterceptor(chain -> { - Retrofit.Builder builder = new Retrofit.Builder() - .baseUrl(instanceUrl) - .client(okHttpClient.build()) - .addConverterFactory(ScalarsConverterFactory.create()) - .addConverterFactory(GsonConverterFactory.create()); + Request request = chain.request(); + if(connToInternet) { + request = request.newBuilder().header("Cache-Control", "public, max-age=" + 60).build(); + } + else { + request = request.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + 60 * 60 * 24 * 30).build(); + } + return chain.proceed(request); + }); - retrofit = builder.build(); + Retrofit.Builder builder = new Retrofit.Builder().baseUrl(instanceUrl).client(okHttpClient.build()).addConverterFactory(ScalarsConverterFactory.create()).addConverterFactory(GsonConverterFactory.create()); - } - catch(Exception e) { - Log.e("onFailure", e.toString()); - } - } + retrofit = builder.build(); - public static synchronized RetrofitClient getInstance(String instanceUrl, Context ctx) { - return new RetrofitClient(instanceUrl, ctx); - } + } + catch(Exception e) { + Log.e("onFailure", e.toString()); + } + } - public ApiInterface getApiInterface() { - return retrofit.create(ApiInterface.class); - } + public static synchronized RetrofitClient getInstance(String instanceUrl, Context ctx) { + + return new RetrofitClient(instanceUrl, ctx); + } + + public ApiInterface getApiInterface() { + + return retrofit.create(ApiInterface.class); + } } diff --git a/app/src/main/java/org/mian/gitnex/helpers/MemorizingActivity.java b/app/src/main/java/org/mian/gitnex/helpers/MemorizingActivity.java index 1de5c9fa..a787a007 100644 --- a/app/src/main/java/org/mian/gitnex/helpers/MemorizingActivity.java +++ b/app/src/main/java/org/mian/gitnex/helpers/MemorizingActivity.java @@ -14,6 +14,7 @@ public class MemorizingActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); Intent intent = getIntent(); @@ -34,7 +35,9 @@ public class MemorizingActivity extends Activity { } private void onSendResult(int decisionId, int decision) { + MemorizingTrustManager.interactResult(decisionId, decision); finish(); } + } \ No newline at end of file diff --git a/app/src/main/java/org/mian/gitnex/helpers/MemorizingTrustManager.java b/app/src/main/java/org/mian/gitnex/helpers/MemorizingTrustManager.java index 033cd9b7..bef13f21 100644 --- a/app/src/main/java/org/mian/gitnex/helpers/MemorizingTrustManager.java +++ b/app/src/main/java/org/mian/gitnex/helpers/MemorizingTrustManager.java @@ -46,9 +46,10 @@ import javax.net.ssl.X509TrustManager; */ public class MemorizingTrustManager implements X509TrustManager { + private final static String DECISION_INTENT = "de.duenndns.ssl.DECISION"; - final static String DECISION_INTENT_ID = DECISION_INTENT + ".decisionId"; - final static String DECISION_INTENT_CERT = DECISION_INTENT + ".cert"; + final static String DECISION_INTENT_ID = DECISION_INTENT + ".decisionId"; + final static String DECISION_INTENT_CERT = DECISION_INTENT + ".cert"; private final static Logger LOGGER = Logger.getLogger(MemorizingTrustManager.class.getName()); final static String DECISION_TITLE_ID = DECISION_INTENT + ".titleId"; @@ -69,44 +70,49 @@ public class MemorizingTrustManager implements X509TrustManager { private X509TrustManager defaultTrustManager; private X509TrustManager appTrustManager; - /** Creates an instance of the MemorizingTrustManager class that falls back to a custom TrustManager. - * + /** + * Creates an instance of the MemorizingTrustManager class that falls back to a custom TrustManager. + *

* You need to supply the application context. This has to be one of: - * - Application - * - Activity - * - Service - * + * - Application + * - Activity + * - Service + *

* The context is used for file management, to display the dialog / * notification and for obtaining translated strings. * - * @param m Context for the application. + * @param m Context for the application. * @param defaultTrustManager Delegate trust management to this TM. If null, the user must accept every certificate. */ public MemorizingTrustManager(Context m, X509TrustManager defaultTrustManager) { + init(m); this.appTrustManager = getTrustManager(appKeyStore); this.defaultTrustManager = defaultTrustManager; } - /** Creates an instance of the MemorizingTrustManager class using the system X509TrustManager. - * + /** + * Creates an instance of the MemorizingTrustManager class using the system X509TrustManager. + *

* You need to supply the application context. This has to be one of: - * - Application - * - Activity - * - Service - * + * - Application + * - Activity + * - Service + *

* The context is used for file management, to display the dialog / * notification and for obtaining translated strings. * * @param m Context for the application. */ public MemorizingTrustManager(Context m) { + init(m); this.appTrustManager = getTrustManager(appKeyStore); this.defaultTrustManager = getTrustManager(null); } private void init(Context m) { + context = m; masterHandler = new Handler(m.getMainLooper()); notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); @@ -115,11 +121,11 @@ public class MemorizingTrustManager implements X509TrustManager { appKeyStore = loadAppKeyStore(); } - + /** * Returns a X509TrustManager list containing a new instance of * TrustManagerFactory. - * + *

* This function is meant for convenience only. You can use it * as follows to integrate TrustManagerFactory for HTTPS sockets: * @@ -129,31 +135,34 @@ public class MemorizingTrustManager implements X509TrustManager { * new java.security.SecureRandom()); * HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); * + * * @param c Activity or Service to show the Dialog / Notification */ public static X509TrustManager[] getInstanceList(Context c) { - return new X509TrustManager[] { new MemorizingTrustManager(c) }; + + return new X509TrustManager[]{new MemorizingTrustManager(c)}; } /** * Binds an Activity to the MTM for displaying the query dialog. - * + *

* This is useful if your connection is run from a service that is * triggered by user interaction -- in such cases the activity is * visible and the user tends to ignore the service notification. - * + *

* You should never have a hidden activity bound to MTM! Use this * function in onResume() and @see unbindDisplayActivity in onPause(). * * @param act Activity to be bound */ private void bindDisplayActivity(Activity act) { + foregroundAct = act; } /** * Removes an Activity from the MTM display stack. - * + *

* Always call this function when the Activity added with * {@link #bindDisplayActivity(Activity)} is hidden. * @@ -161,8 +170,9 @@ public class MemorizingTrustManager implements X509TrustManager { */ public void unbindDisplayActivity(Activity act) { // do not remove if it was overridden by a different activity - if (foregroundAct == act) + if(foregroundAct == act) { foregroundAct = null; + } } /** @@ -171,9 +181,11 @@ public class MemorizingTrustManager implements X509TrustManager { * @return an {@link Enumeration} of all certificates */ private Enumeration getCertificates() { + try { return appKeyStore.aliases(); - } catch (KeyStoreException e) { + } + catch(KeyStoreException e) { // this should never happen, however... throw new RuntimeException(e); } @@ -183,13 +195,14 @@ public class MemorizingTrustManager implements X509TrustManager { * Get a certificate for a given alias. * * @param alias the certificate's alias as returned by {@link #getCertificates()}. - * * @return the certificate associated with the alias or null if none found. */ public Certificate getCertificate(String alias) { + try { return appKeyStore.getCertificate(alias); - } catch (KeyStoreException e) { + } + catch(KeyStoreException e) { // this should never happen, however... throw new RuntimeException(e); } @@ -204,11 +217,12 @@ public class MemorizingTrustManager implements X509TrustManager { * (b) new connections are created using TLS renegotiation, without a new cert * check. *

- * @param alias the certificate's alias as returned by {@link #getCertificates()}. * + * @param alias the certificate's alias as returned by {@link #getCertificates()}. * @throws KeyStoreException if the certificate could not be deleted. */ public void deleteCertificate(String alias) throws KeyStoreException { + appKeyStore.deleteEntry(alias); keyStoreUpdated(); } @@ -220,36 +234,39 @@ public class MemorizingTrustManager implements X509TrustManager { * the given instance of {@link MemorizingTrustManager}, and leverages an * existing {@link HostnameVerifier}. The returned verifier performs the * following steps, returning as soon as one of them succeeds: - *

- *
    - *
  1. Success, if the wrapped defaultVerifier accepts the certificate.
  2. - *
  3. Success, if the server certificate is stored in the keystore under the given hostname.
  4. - *
  5. Ask the user and return accordingly.
  6. - *
  7. Failure on exception.
  8. - *
+ * /p> + *
    + *
  1. Success, if the wrapped defaultVerifier accepts the certificate.
  2. + *
  3. Success, if the server certificate is stored in the keystore under the given hostname.
  4. + *
  5. Ask the user and return accordingly.
  6. + *
  7. Failure on exception.
  8. + *
* * @param defaultVerifier the {@link HostnameVerifier} that should perform the actual check * @return a new hostname verifier using the MTM's key store - * * @throws IllegalArgumentException if the defaultVerifier parameter is null */ public HostnameVerifier wrapHostnameVerifier(final HostnameVerifier defaultVerifier) { - if (defaultVerifier == null) + + if(defaultVerifier == null) { throw new IllegalArgumentException("The default verifier may not be null"); - + } + return new MemorizingHostnameVerifier(defaultVerifier); } - + private X509TrustManager getTrustManager(KeyStore ks) { + try { TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509"); tmf.init(ks); - for (TrustManager t : tmf.getTrustManagers()) { - if (t instanceof X509TrustManager) { - return (X509TrustManager)t; + for(TrustManager t : tmf.getTrustManagers()) { + if(t instanceof X509TrustManager) { + return (X509TrustManager) t; } } - } catch (Exception e) { + } + catch(Exception e) { e.printStackTrace(); } @@ -257,18 +274,21 @@ public class MemorizingTrustManager implements X509TrustManager { } private KeyStore loadAppKeyStore() { + KeyStore keyStore; try { keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); - } catch (KeyStoreException e) { + } + catch(KeyStoreException e) { e.printStackTrace(); return null; } try { keyStore.load(null, null); - } catch (NoSuchAlgorithmException | CertificateException | IOException e) { + } + catch(NoSuchAlgorithmException | CertificateException | IOException e) { e.printStackTrace(); } @@ -280,7 +300,8 @@ public class MemorizingTrustManager implements X509TrustManager { try { keyStore.load(inputStream, "MTM".toCharArray()); inputStream.close(); - } catch(Exception e) { + } + catch(Exception e) { e.printStackTrace(); } } @@ -289,17 +310,20 @@ public class MemorizingTrustManager implements X509TrustManager { } private void storeCert(String alias, Certificate cert) { + try { appKeyStore.setCertificateEntry(alias, cert); - } catch (KeyStoreException e) { + } + catch(KeyStoreException e) { e.printStackTrace(); return; } keyStoreUpdated(); } - + private void storeCert(X509Certificate cert) { + storeCert(cert.getSubjectDN().toString(), cert); } @@ -316,69 +340,83 @@ public class MemorizingTrustManager implements X509TrustManager { byteArrayOutputStream.close(); keyStoreStorage.edit().putString(KEYSTORE_KEY, Base64.encodeToString(byteArrayOutputStream.toByteArray(), Base64.DEFAULT)).apply(); - } catch (Exception e) { + } + catch(Exception e) { e.printStackTrace(); } } // if the certificate is stored in the app key store, it is considered "known" private boolean isCertKnown(X509Certificate cert) { + try { return appKeyStore.getCertificateAlias(cert) != null; - } catch (KeyStoreException e) { + } + catch(KeyStoreException e) { return false; } } private static boolean isExpiredException(Throwable e) { + do { - if (e instanceof CertificateExpiredException) + if(e instanceof CertificateExpiredException) { return true; + } e = e.getCause(); - } while (e != null); + } while(e != null); return false; } private static boolean isPathException(Throwable e) { + do { - if (e instanceof CertPathValidatorException) + if(e instanceof CertPathValidatorException) { return true; + } e = e.getCause(); - } while (e != null); + } while(e != null); return false; } private void checkCertTrusted(X509Certificate[] chain, String authType, boolean isServer) throws CertificateException { + LOGGER.log(Level.FINE, "checkCertTrusted(" + Arrays.toString(chain) + ", " + authType + ", " + isServer + ")"); try { LOGGER.log(Level.FINE, "checkCertTrusted: trying appTrustManager"); - if (isServer) + if(isServer) { appTrustManager.checkServerTrusted(chain, authType); - else + } + else { appTrustManager.checkClientTrusted(chain, authType); - } catch (CertificateException ae) { + } + } + catch(CertificateException ae) { LOGGER.log(Level.FINER, "checkCertTrusted: appTrustManager did not verify certificate. Will fall back to secondary verification mechanisms (if any).", ae); // if the cert is stored in our appTrustManager, we ignore expiredness - if (isExpiredException(ae)) { + if(isExpiredException(ae)) { LOGGER.log(Level.INFO, "checkCertTrusted: accepting expired certificate from keystore"); return; } - if (isCertKnown(chain[0])) { + if(isCertKnown(chain[0])) { LOGGER.log(Level.INFO, "checkCertTrusted: accepting cert already stored in keystore"); return; } try { - if (defaultTrustManager == null) { + if(defaultTrustManager == null) { LOGGER.fine("No defaultTrustManager set. Verification failed, throwing " + ae); throw ae; } LOGGER.log(Level.FINE, "checkCertTrusted: trying defaultTrustManager"); - if (isServer) + if(isServer) { defaultTrustManager.checkServerTrusted(chain, authType); - else + } + else { defaultTrustManager.checkClientTrusted(chain, authType); - } catch (CertificateException e) { + } + } + catch(CertificateException e) { LOGGER.log(Level.FINER, "checkCertTrusted: defaultTrustManager failed", e); interactCert(chain, authType, e); } @@ -386,18 +424,22 @@ public class MemorizingTrustManager implements X509TrustManager { } public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + checkCertTrusted(chain, authType, false); } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + checkCertTrusted(chain, authType, true); } public X509Certificate[] getAcceptedIssuers() { + return defaultTrustManager.getAcceptedIssuers(); } private static int createDecisionId(MTMDecision d) { + int myId; synchronized(openDecisions) { myId = decisionId; @@ -408,26 +450,31 @@ public class MemorizingTrustManager implements X509TrustManager { } private static String hexString(byte[] data) { + StringBuilder si = new StringBuilder(); - for (int i = 0; i < data.length; i++) { + for(int i = 0; i < data.length; i++) { si.append(String.format("%02x", data[i])); - if (i < data.length - 1) + if(i < data.length - 1) { si.append(":"); + } } return si.toString(); } private static String certHash(final X509Certificate cert, String digest) { + try { MessageDigest md = MessageDigest.getInstance(digest); md.update(cert.getEncoded()); return hexString(md.digest()); - } catch (CertificateEncodingException | NoSuchAlgorithmException e) { + } + catch(CertificateEncodingException | NoSuchAlgorithmException e) { return e.getMessage(); } } private static void certDetails(StringBuilder si, X509Certificate c) { + SimpleDateFormat validityDateFormater = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()); si.append("\n"); si.append(c.getSubjectDN().toString()); @@ -443,18 +490,22 @@ public class MemorizingTrustManager implements X509TrustManager { si.append(c.getIssuerDN().toString()); si.append("\n"); } - + private String certChainMessage(final X509Certificate[] chain, CertificateException cause) { + Throwable e = cause; StringBuilder si = new StringBuilder(); - if (isPathException(e)) { + if(isPathException(e)) { si.append(context.getString(R.string.mtm_trust_anchor)); - } else if (isExpiredException(e)) { + } + else if(isExpiredException(e)) { si.append(context.getString(R.string.mtm_cert_expired)); - } else { + } + else { // get to the cause - while (e.getCause() != null) e = e.getCause(); + while(e.getCause() != null) + e = e.getCause(); si.append(e.getLocalizedMessage()); } @@ -462,13 +513,14 @@ public class MemorizingTrustManager implements X509TrustManager { si.append(context.getString(R.string.mtm_connect_anyway)); si.append("\n\n"); si.append(context.getString(R.string.mtm_cert_details)); - for (X509Certificate c : chain) { + for(X509Certificate c : chain) { certDetails(si, c); } return si.toString(); } private String hostNameMessage(X509Certificate cert, String hostname) { + StringBuilder si = new StringBuilder(); si.append(context.getString(R.string.mtm_hostname_mismatch, hostname)); @@ -476,20 +528,24 @@ public class MemorizingTrustManager implements X509TrustManager { try { Collection> sans = cert.getSubjectAlternativeNames(); - if (sans == null) { + if(sans == null) { si.append(cert.getSubjectDN()); si.append("\n"); - } else for (List altName : sans) { - Object name = altName.get(1); - if (name instanceof String) { - si.append("["); - si.append(altName.get(0)); - si.append("] "); - si.append(name); - si.append("\n"); + } + else { + for(List altName : sans) { + Object name = altName.get(1); + if(name instanceof String) { + si.append("["); + si.append(altName.get(0)); + si.append("] "); + si.append(name); + si.append("\n"); + } } } - } catch (CertificateParsingException e) { + } + catch(CertificateParsingException e) { e.printStackTrace(); si.append("Notification.setLatestEventInfo(Context, CharSequence, CharSequence, PendingIntent) * since it was remove in Android API level 23. - * */ private static void setLatestEventInfoReflective(Notification notification, Context context, CharSequence mtmNotification, CharSequence certName, PendingIntent call) { + Method setLatestEventInfo; try { - setLatestEventInfo = notification.getClass().getMethod( - "setLatestEventInfo", Context.class, CharSequence.class, - CharSequence.class, PendingIntent.class); - } catch (NoSuchMethodException e) { + setLatestEventInfo = notification.getClass().getMethod("setLatestEventInfo", Context.class, CharSequence.class, CharSequence.class, PendingIntent.class); + } + catch(NoSuchMethodException e) { throw new IllegalStateException(e); } try { setLatestEventInfo.invoke(notification, context, mtmNotification, certName, call); - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + } + catch(IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { throw new IllegalStateException(e); } } @TargetApi(Build.VERSION_CODES.HONEYCOMB) private void startActivityNotification(Intent intent, int decisionId, String certName) { + final PendingIntent call = PendingIntent.getActivity(context, 0, intent, 0); final String mtmNotification = context.getString(R.string.mtm_notification); - NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "ssl") - .setSmallIcon(android.R.drawable.ic_lock_lock) - .setContentTitle(mtmNotification) - .setContentText(certName) - .setTicker(certName) - .setContentIntent(call) - .setAutoCancel(true) - .setPriority(NotificationCompat.PRIORITY_HIGH); + NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "ssl").setSmallIcon(android.R.drawable.ic_lock_lock).setContentTitle(mtmNotification).setContentText(certName).setTicker(certName).setContentIntent(call).setAutoCancel(true).setPriority(NotificationCompat.PRIORITY_HIGH); notificationManager.notify(NOTIFICATION_ID + decisionId, builder.build()); } @@ -551,6 +601,7 @@ public class MemorizingTrustManager implements X509TrustManager { * @return the Context of the currently bound UI or the master context if none is bound */ Context getUI() { + return (foregroundAct != null) ? foregroundAct : context; } @@ -560,7 +611,9 @@ public class MemorizingTrustManager implements X509TrustManager { final int myId = createDecisionId(choice); masterHandler.post(new Runnable() { + public void run() { + Intent intent = new Intent(context, MemorizingActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setData(Uri.parse(MemorizingTrustManager.class.getName() + "/" + myId)); @@ -575,7 +628,8 @@ public class MemorizingTrustManager implements X509TrustManager { // deployed. try { foregroundAct.startActivity(intent); - } catch (Exception e) { + } + catch(Exception e) { startActivityNotification(intent, myId, message); } } @@ -585,15 +639,17 @@ public class MemorizingTrustManager implements X509TrustManager { synchronized(choice) { choice.wait(); } - } catch (InterruptedException e) { + } + catch(InterruptedException e) { e.printStackTrace(); } return choice.state; } - + private void interactCert(final X509Certificate[] chain, String authType, CertificateException cause) throws CertificateException { - switch (interact(certChainMessage(chain, cause), R.string.mtm_accept_cert)) { + + 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 case MTMDecision.DECISION_ONCE: @@ -604,7 +660,8 @@ public class MemorizingTrustManager implements X509TrustManager { } private boolean interactHostname(X509Certificate cert, String hostname) { - switch (interact(hostNameMessage(cert, hostname), R.string.mtm_accept_servername)) { + + switch(interact(hostNameMessage(cert, hostname), R.string.mtm_accept_servername)) { case MTMDecision.DECISION_ALWAYS: storeCert(hostname, cert); case MTMDecision.DECISION_ONCE: @@ -615,46 +672,57 @@ public class MemorizingTrustManager implements X509TrustManager { } static void interactResult(int decisionId, int choice) { + MTMDecision d; synchronized(openDecisions) { - d = openDecisions.get(decisionId); - openDecisions.remove(decisionId); + d = openDecisions.get(decisionId); + openDecisions.remove(decisionId); } - if (d == null) return; + if(d == null) { + return; + } synchronized(d) { d.state = choice; d.notify(); } } - + class MemorizingHostnameVerifier implements HostnameVerifier { + private HostnameVerifier defaultVerifier; - + MemorizingHostnameVerifier(HostnameVerifier wrapped) { + defaultVerifier = wrapped; } @Override public boolean verify(String hostname, SSLSession session) { // if the default verifier accepts the hostname, we are done - if (defaultVerifier.verify(hostname, session)) return true; + if(defaultVerifier.verify(hostname, session)) { + return true; + } // 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]; - if (cert.equals(appKeyStore.getCertificate(hostname.toLowerCase(Locale.US)))) { + if(cert.equals(appKeyStore.getCertificate(hostname.toLowerCase(Locale.US)))) { return true; - } else { + } + else { return interactHostname(cert, hostname); } - } catch (Exception e) { + } + catch(Exception e) { e.printStackTrace(); return false; } } + } + }