From 80bf751141c85316c22a0d16c1e4d6fa0f473f44 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Sat, 2 Oct 2021 13:31:36 +0200 Subject: * refactor startTorProxy() * fix setting http proxy port correctly * snowflake+tor does currently only work when being connected to a wifi, not a cellular network. For now, we check if the device is connected to a wifi, before attempting to start tor --- .../java/de/blinkt/openvpn/core/NetworkUtils.java | 30 ++++++++++++++ .../bitmaskclient/providersetup/ProviderAPI.java | 34 ++++++++------- .../providersetup/ProviderApiManagerBase.java | 41 +++++++++++------- .../providersetup/ProviderApiManager.java | 48 +++++++++++++--------- 4 files changed, 105 insertions(+), 48 deletions(-) (limited to 'app') diff --git a/app/src/main/java/de/blinkt/openvpn/core/NetworkUtils.java b/app/src/main/java/de/blinkt/openvpn/core/NetworkUtils.java index 78799a3a..cbb58f0f 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/NetworkUtils.java +++ b/app/src/main/java/de/blinkt/openvpn/core/NetworkUtils.java @@ -9,6 +9,9 @@ import android.content.Context; import android.net.*; import android.os.Build; import android.text.TextUtils; +import android.util.Log; + +import androidx.core.net.ConnectivityManagerCompat; import java.net.Inet4Address; import java.net.Inet6Address; @@ -16,6 +19,8 @@ import java.util.Vector; public class NetworkUtils { + private static final String TAG = NetworkUtils.class.getSimpleName(); + public static Vector getLocalNetworks(Context c, boolean ipv6) { Vector nets = new Vector<>(); ConnectivityManager conn = (ConnectivityManager) c.getSystemService(Context.CONNECTIVITY_SERVICE); @@ -76,4 +81,29 @@ public class NetworkUtils { return nets; } + public static boolean isConnectedToWifi(Context context) { + ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP_MR1) { + NetworkInfo wifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); + Log.d(TAG, "isConnectedToWifi (<=LOLLIPOP_MR1): " + wifi.isConnected()); + return wifi.isConnected(); + } else if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.O_MR1) { + NetworkInfo[] netInfos = connManager.getAllNetworkInfo(); + for (NetworkInfo netInfo : netInfos) { + if (netInfo != null && netInfo.getType() == ConnectivityManager.TYPE_WIFI) { + Log.d(TAG, "isConnectedToWifi (<= Build.VERSION_CODES.O_MR1): " + netInfo.isConnected()); + return netInfo.isConnected(); + } + } + } else { + NetworkInfo netInfo = connManager.getActiveNetworkInfo(); + if(netInfo != null) { + NetworkCapabilities networkCapabilities = connManager.getNetworkCapabilities(connManager.getActiveNetwork()); + Log.d(TAG, "isConnectedToWifi (> Build.VERSION_CODES.O_MR1): " + networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)); + return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI); + } + } + + return false; + } } \ No newline at end of file diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderAPI.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderAPI.java index 42ded09f..e818f587 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderAPI.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderAPI.java @@ -37,17 +37,15 @@ import java.io.Closeable; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; +import de.blinkt.openvpn.core.NetworkUtils; import se.leap.bitmaskclient.base.utils.PreferenceHelper; import se.leap.bitmaskclient.providersetup.connectivity.OkHttpClientGenerator; import se.leap.bitmaskclient.tor.ClientTransportPlugin; import se.leap.bitmaskclient.tor.TorNotificationManager; -import se.leap.bitmaskclient.tor.TorStatusObservable; import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; import static se.leap.bitmaskclient.base.utils.ConfigHelper.ensureNotOnMainThread; import static se.leap.bitmaskclient.tor.TorNotificationManager.TOR_SERVICE_NOTIFICATION_ID; -import static se.leap.bitmaskclient.tor.TorStatusObservable.TorStatus.OFF; -import static se.leap.bitmaskclient.tor.TorStatusObservable.TorStatus.STOPPING; /** * Implements HTTP api methods (encapsulated in {{@link ProviderApiManager}}) @@ -151,23 +149,31 @@ public class ProviderAPI extends JobIntentService implements ProviderApiManagerB LocalBroadcastManager.getInstance(this).sendBroadcast(intent); } + @Override + public boolean isConnectedToWifi() { + return NetworkUtils.isConnectedToWifi(getApplicationContext()); + } + + @Override + public void startTorService() { + initTorServiceConnection(this); + Intent torServiceIntent = new Intent(this, TorService.class); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + Notification notification = TorNotificationManager.buildTorForegroundNotification(getApplicationContext()); + //noinspection NewApi + getApplicationContext().startForegroundService(torServiceIntent); + torServiceConnection.torService.startForeground(TOR_SERVICE_NOTIFICATION_ID, notification); + } else { + getApplicationContext().startService(torServiceIntent); + } + } @Override public int getTorHttpTunnelPort() { initTorServiceConnection(this); if (torServiceConnection != null) { - Intent torServiceIntent = new Intent(this, TorService.class); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - Notification notification = TorNotificationManager.buildTorForegroundNotification(getApplicationContext()); - //noinspection NewApi - getApplicationContext().startForegroundService(torServiceIntent); - torServiceConnection.torService.startForeground(TOR_SERVICE_NOTIFICATION_ID, notification); - } else { - getApplicationContext().startService(torServiceIntent); - } - int tunnelPort = torServiceConnection.torService.getHttpTunnelPort(); torServiceConnection.close(); torServiceConnection = null; diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java index 9ca4c746..780ecaed 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java @@ -51,6 +51,8 @@ import java.util.NoSuchElementException; import java.util.Observer; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.SSLPeerUnverifiedException; @@ -149,7 +151,9 @@ public abstract class ProviderApiManagerBase { public interface ProviderApiServiceCallback { void broadcastEvent(Intent intent); + void startTorService(); int getTorHttpTunnelPort(); + boolean isConnectedToWifi(); } private final ProviderApiServiceCallback serviceCallback; @@ -188,7 +192,11 @@ public abstract class ProviderApiManagerBase { } // uncomment for testing --v - TorStatusObservable.setProxyPort(startTorProxy()); + /* try { + startTorProxy(); + } catch (InterruptedException | TimeoutException e) { + e.printStackTrace(); + } */ Bundle result = new Bundle(); switch (action) { @@ -287,35 +295,38 @@ public abstract class ProviderApiManagerBase { } } - protected int startTorProxy() { - int port = -1; - if (PreferenceHelper.useTor(preferences) && EipStatus.getInstance().isDisconnected() ) { - port = serviceCallback.getTorHttpTunnelPort(); - if (port != -1) { - try { - waitForTorCircuits(); - } catch (InterruptedException e) { - e.printStackTrace(); - port = -1; - } - } + protected boolean startTorProxy() throws InterruptedException, TimeoutException { + if (PreferenceHelper.useTor(preferences) && + EipStatus.getInstance().isDisconnected() && + serviceCallback.isConnectedToWifi() + ) { + serviceCallback.startTorService(); + waitForTorCircuits(); + int port = serviceCallback.getTorHttpTunnelPort(); + TorStatusObservable.setProxyPort(port); + return port != -1; } - return port; + return false; } - private void waitForTorCircuits() throws InterruptedException { + private void waitForTorCircuits() throws InterruptedException, TimeoutException { if (TorStatusObservable.getStatus() == ON) { return; } CountDownLatch countDownLatch = new CountDownLatch(1); + AtomicBoolean successfulSetup = new AtomicBoolean(false); Observer observer = (o, arg) -> { if (TorStatusObservable.getStatus() == ON) { + successfulSetup.set(true); countDownLatch.countDown(); } }; TorStatusObservable.getInstance().addObserver(observer); countDownLatch.await(180, TimeUnit.SECONDS); TorStatusObservable.getInstance().deleteObserver(observer); + if (!successfulSetup.get()) { + throw new TimeoutException("Timeout reached"); + } } void resetProviderDetails(Provider provider) { diff --git a/app/src/production/java/se/leap/bitmaskclient/providersetup/ProviderApiManager.java b/app/src/production/java/se/leap/bitmaskclient/providersetup/ProviderApiManager.java index fc1f0f59..3067c1bf 100644 --- a/app/src/production/java/se/leap/bitmaskclient/providersetup/ProviderApiManager.java +++ b/app/src/production/java/se/leap/bitmaskclient/providersetup/ProviderApiManager.java @@ -28,6 +28,7 @@ import org.json.JSONObject; import java.io.IOException; import java.net.URL; import java.util.List; +import java.util.concurrent.TimeoutException; import de.blinkt.openvpn.core.VpnStatus; import okhttp3.OkHttpClient; @@ -325,17 +326,21 @@ public class ProviderApiManager extends ProviderApiManagerBase { } } - if (tries == 0 && - responseString != null && - responseString.contains(ERRORS) && - PreferenceHelper.useTor(preferences) && - EipStatus.getInstance().isDisconnected() && - (TorStatusObservable.getStatus() == OFF || - TorStatusObservable.getStatus() == UNKOWN)) { - TorStatusObservable.setProxyPort(startTorProxy()); - return downloadWithCommercialCA(stringUrl, provider, 1); + try { + if (tries == 0 && + responseString != null && + responseString.contains(ERRORS) && + PreferenceHelper.useTor(preferences) && + EipStatus.getInstance().isDisconnected() && + (TorStatusObservable.getStatus() == OFF || + TorStatusObservable.getStatus() == UNKOWN) && + startTorProxy() + ) { + return downloadWithCommercialCA(stringUrl, provider, 1); + } + } catch (InterruptedException | TimeoutException e) { + e.printStackTrace(); } - return responseString; } @@ -366,15 +371,20 @@ public class ProviderApiManager extends ProviderApiManagerBase { List> headerArgs = getAuthorizationHeader(); responseString = sendGetStringToServer(urlString, headerArgs, okHttpClient); - if (tries == 0 && - responseString != null && - responseString.contains(ERRORS) && - PreferenceHelper.useTor(preferences) && - EipStatus.getInstance().isDisconnected() && - (TorStatusObservable.getStatus() == OFF || - TorStatusObservable.getStatus() == UNKOWN)) { - TorStatusObservable.setProxyPort(startTorProxy()); - return downloadFromUrlWithProviderCA(urlString, provider, 1); + try { + if (tries == 0 && + responseString != null && + responseString.contains(ERRORS) && + PreferenceHelper.useTor(preferences) && + EipStatus.getInstance().isDisconnected() && + (TorStatusObservable.getStatus() == OFF || + TorStatusObservable.getStatus() == UNKOWN) && + startTorProxy() + ) { + return downloadFromUrlWithProviderCA(urlString, provider, 1); + } + } catch (InterruptedException | TimeoutException e) { + e.printStackTrace(); } return responseString; -- cgit v1.2.3