diff --git a/app/src/main/java/com/nutomic/syncthingandroid/http/ApiRequest.java b/app/src/main/java/com/nutomic/syncthingandroid/http/ApiRequest.java index 9c54dcf5..23b67b54 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/http/ApiRequest.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/http/ApiRequest.java @@ -157,9 +157,12 @@ public abstract class ApiRequest { } @Override protected HttpURLConnection createConnection(URL url) throws IOException { - HttpsURLConnection connection = (HttpsURLConnection) super.createConnection(url); - connection.setHostnameVerifier((hostname, session) -> true); - return connection; + if (mUrl.toString().startsWith("https://")) { + HttpsURLConnection connection = (HttpsURLConnection) super.createConnection(url); + connection.setHostnameVerifier((hostname, session) -> true); + return connection; + } + return super.createConnection(url); } } diff --git a/app/src/main/java/com/nutomic/syncthingandroid/service/Constants.java b/app/src/main/java/com/nutomic/syncthingandroid/service/Constants.java index dfde0607..3e8a2d63 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/service/Constants.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/service/Constants.java @@ -1,6 +1,7 @@ package com.nutomic.syncthingandroid.service; import android.content.Context; +import android.os.Build; import android.os.Environment; import java.io.File; @@ -112,4 +113,28 @@ public class Constants { static File getLogFile(Context context) { return new File(context.getExternalFilesDir(null), "syncthing.log"); } + + /** + * Decide if we should enforce HTTPS when accessing the Web UI and REST API. + * Android 4.4 and earlier don't have support for TLS 1.2 requiring us to + * fall back to an unencrypted HTTP connection to localhost. This applies + * to syncthing core v0.14.53+. + */ + public static Boolean osSupportsTLS12() { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { + // Pre-Lollipop devices don't support TLS 1.2 + return false; + } + + if (Build.VERSION.SDK_INT == Build.VERSION_CODES.N) { + /** + * SSLProtocolException: SSL handshake failed on Android N/7.0, + * missing support for elliptic curves. + * See https://issuetracker.google.com/issues/37122132 + */ + return false; + } + + return true; + } } diff --git a/app/src/main/java/com/nutomic/syncthingandroid/util/ConfigXml.java b/app/src/main/java/com/nutomic/syncthingandroid/util/ConfigXml.java index b4259a27..0e2d245d 100644 --- a/app/src/main/java/com/nutomic/syncthingandroid/util/ConfigXml.java +++ b/app/src/main/java/com/nutomic/syncthingandroid/util/ConfigXml.java @@ -106,8 +106,9 @@ public class ConfigXml { } public URL getWebGuiUrl() { + String urlProtocol = Constants.osSupportsTLS12() ? "https" : "http"; try { - return new URL("https://" + getGuiElement().getElementsByTagName("address").item(0).getTextContent()); + return new URL(urlProtocol + "://" + getGuiElement().getElementsByTagName("address").item(0).getTextContent()); } catch (MalformedURLException e) { throw new RuntimeException("Failed to parse web interface URL", e); } @@ -154,9 +155,15 @@ public class ConfigXml { } /* Section - GUI */ - // Enforce TLS. Element gui = getGuiElement(); - changed = setConfigElement(gui, "tls", "true") || changed; + + // Platform-specific: Force REST API and Web UI access to use TLS 1.2 or not. + Boolean forceHttps = Constants.osSupportsTLS12(); + if (!gui.hasAttribute("tls") || + Boolean.parseBoolean(gui.getAttribute("tls")) != forceHttps) { + gui.setAttribute("tls", forceHttps ? "true" : "false"); + changed = true; + } // Set user to "syncthing" changed = setConfigElement(gui, "user", "syncthing") || changed;