HttpDownloader bypasses proxy when accessing a swap repo

Proxying are basically always for internet access, and swap repos are by
definition only on the local network.  This adds a pretty strict check for
whether a given download URL is for a swap repo, and if so, the proxy
settings are ignored.

fixes https://dev.guardianproject.info/issues/3421
This commit is contained in:
Hans-Christoph Steiner 2015-09-10 17:54:49 +02:00
parent 1654443b00
commit a69488b32f
4 changed files with 37 additions and 7 deletions

View File

@ -27,6 +27,7 @@ if (!hasProperty('sourceDeps')) {
compile 'com.madgag.spongycastle:pkix:1.51.0.0' compile 'com.madgag.spongycastle:pkix:1.51.0.0'
compile 'com.madgag.spongycastle:prov:1.51.0.0' compile 'com.madgag.spongycastle:prov:1.51.0.0'
compile 'com.madgag.spongycastle:core:1.51.0.0' compile 'com.madgag.spongycastle:core:1.51.0.0'
compile 'commons-net:commons-net:3.3'
// Upstream doesn't have a binary on mavenCentral/jcenter yet: // Upstream doesn't have a binary on mavenCentral/jcenter yet:
// https://github.com/kolavar/android-support-v4-preferencefragment/issues/13 // https://github.com/kolavar/android-support-v4-preferencefragment/issues/13
@ -70,6 +71,7 @@ if (!hasProperty('sourceDeps')) {
compile 'eu.chainfire:libsuperuser:1.0.0.201504231659' compile 'eu.chainfire:libsuperuser:1.0.0.201504231659'
compile 'cc.mvdan.accesspoint:library:0.1.1' compile 'cc.mvdan.accesspoint:library:0.1.1'
compile 'info.guardianproject.netcipher:netcipher:1.2' compile 'info.guardianproject.netcipher:netcipher:1.2'
compile 'commons-net:commons-net:3.3'
compile(project(':extern:support-v4-preferencefragment')) { compile(project(':extern:support-v4-preferencefragment')) {
exclude module: 'support-v4' exclude module: 'support-v4'

View File

@ -44,6 +44,7 @@ import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.utils.StorageUtils; import com.nostra13.universalimageloader.utils.StorageUtils;
import org.apache.commons.net.util.SubnetUtils;
import org.fdroid.fdroid.Preferences.ChangeListener; import org.fdroid.fdroid.Preferences.ChangeListener;
import org.fdroid.fdroid.compat.PRNGFixes; import org.fdroid.fdroid.compat.PRNGFixes;
import org.fdroid.fdroid.data.AppProvider; import org.fdroid.fdroid.data.AppProvider;
@ -68,6 +69,7 @@ public class FDroidApp extends Application {
// for the local repo on this device, all static since there is only one // for the local repo on this device, all static since there is only one
public static int port; public static int port;
public static String ipAddressString; public static String ipAddressString;
public static SubnetUtils.SubnetInfo subnetInfo;
public static String ssid; public static String ssid;
public static String bssid; public static String bssid;
public static final Repo repo = new Repo(); public static final Repo repo = new Repo();
@ -135,6 +137,7 @@ public class FDroidApp extends Application {
public static void initWifiSettings() { public static void initWifiSettings() {
port = 8888; port = 8888;
ipAddressString = null; ipAddressString = null;
subnetInfo = (new SubnetUtils("0.0.0.0/32").getInfo());
ssid = ""; ssid = "";
bssid = ""; bssid = "";
} }

View File

@ -5,6 +5,7 @@ import android.util.Log;
import com.nostra13.universalimageloader.core.download.BaseImageDownloader; import com.nostra13.universalimageloader.core.download.BaseImageDownloader;
import org.fdroid.fdroid.FDroidApp;
import org.fdroid.fdroid.Preferences; import org.fdroid.fdroid.Preferences;
import org.fdroid.fdroid.Utils; import org.fdroid.fdroid.Utils;
@ -84,11 +85,18 @@ public class HttpDownloader extends Downloader {
} }
} }
boolean isSwapUrl() {
String host = sourceUrl.getHost();
return sourceUrl.getPort() > 1023 // only root can use <= 1023, so never a swap repo
&& host.matches("[0-9.]+") // host must be an IP address
&& FDroidApp.subnetInfo.isInRange(host); // on the same subnet as we are
}
protected void setupConnection() throws IOException { protected void setupConnection() throws IOException {
if (connection != null) if (connection != null)
return; return;
Preferences prefs = Preferences.get(); Preferences prefs = Preferences.get();
if (prefs.isProxyEnabled()) { if (prefs.isProxyEnabled() && ! isSwapUrl()) {
SocketAddress sa = new InetSocketAddress(prefs.getProxyHost(), prefs.getProxyPort()); SocketAddress sa = new InetSocketAddress(prefs.getProxyHost(), prefs.getProxyPort());
Proxy proxy = new Proxy(Proxy.Type.HTTP, sa); Proxy proxy = new Proxy(Proxy.Type.HTTP, sa);
NetCipher.setProxy(proxy); NetCipher.setProxy(proxy);

View File

@ -1,5 +1,6 @@
package org.fdroid.fdroid.net; package org.fdroid.fdroid.net;
import android.annotation.TargetApi;
import android.app.Service; import android.app.Service;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
@ -9,10 +10,13 @@ import android.net.NetworkInfo;
import android.net.wifi.WifiInfo; import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager; import android.net.wifi.WifiManager;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Build;
import android.os.IBinder; import android.os.IBinder;
import android.support.v4.content.LocalBroadcastManager; import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import org.apache.commons.net.util.SubnetUtils;
import org.fdroid.fdroid.BuildConfig; import org.fdroid.fdroid.BuildConfig;
import org.fdroid.fdroid.FDroidApp; import org.fdroid.fdroid.FDroidApp;
import org.fdroid.fdroid.Preferences; import org.fdroid.fdroid.Preferences;
@ -23,6 +27,7 @@ import org.fdroid.fdroid.localrepo.SwapService;
import java.net.Inet6Address; import java.net.Inet6Address;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface; import java.net.NetworkInterface;
import java.net.SocketException; import java.net.SocketException;
import java.security.cert.Certificate; import java.security.cert.Certificate;
@ -80,14 +85,17 @@ public class WifiStateChangeService extends Service {
if (wifiState == WifiManager.WIFI_STATE_ENABLED) { if (wifiState == WifiManager.WIFI_STATE_ENABLED) {
wifiInfo = wifiManager.getConnectionInfo(); wifiInfo = wifiManager.getConnectionInfo();
FDroidApp.ipAddressString = formatIpAddress(wifiInfo.getIpAddress()); FDroidApp.ipAddressString = formatIpAddress(wifiInfo.getIpAddress());
String netmask = formatIpAddress(wifiManager.getDhcpInfo().netmask);
if (!TextUtils.isEmpty(FDroidApp.ipAddressString))
FDroidApp.subnetInfo = new SubnetUtils(FDroidApp.ipAddressString, netmask).getInfo();
} else if (wifiState == WifiManager.WIFI_STATE_DISABLED } else if (wifiState == WifiManager.WIFI_STATE_DISABLED
|| wifiState == WifiManager.WIFI_STATE_DISABLING) { || wifiState == WifiManager.WIFI_STATE_DISABLING) {
// try once to see if its a hotspot // try once to see if its a hotspot
FDroidApp.ipAddressString = getIpAddressFromNetworkInterface(); setIpInfoFromNetworkInterface();
if (FDroidApp.ipAddressString == null) if (FDroidApp.ipAddressString == null)
return null; return null;
} else { // a hotspot can be active during WIFI_STATE_UNKNOWN } else { // a hotspot can be active during WIFI_STATE_UNKNOWN
FDroidApp.ipAddressString = getIpAddressFromNetworkInterface(); setIpInfoFromNetworkInterface();
} }
if (FDroidApp.ipAddressString == null) { if (FDroidApp.ipAddressString == null) {
@ -179,7 +187,8 @@ public class WifiStateChangeService extends Service {
return null; return null;
} }
public String getIpAddressFromNetworkInterface() { @TargetApi(9)
public void setIpInfoFromNetworkInterface() {
try { try {
for (Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces(); networkInterfaces.hasMoreElements(); ) { for (Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces(); networkInterfaces.hasMoreElements(); ) {
NetworkInterface netIf = networkInterfaces.nextElement(); NetworkInterface netIf = networkInterfaces.nextElement();
@ -191,15 +200,23 @@ public class WifiStateChangeService extends Service {
} else if (netIf.getDisplayName().contains("wlan0") } else if (netIf.getDisplayName().contains("wlan0")
|| netIf.getDisplayName().contains("eth0") || netIf.getDisplayName().contains("eth0")
|| netIf.getDisplayName().contains("ap0")) { || netIf.getDisplayName().contains("ap0")) {
return inetAddress.getHostAddress(); FDroidApp.ipAddressString = inetAddress.getHostAddress();
if (Build.VERSION.SDK_INT < 9)
return;
// the following methods were not added until android-9/Gingerbread
for (InterfaceAddress address : netIf.getInterfaceAddresses()) {
if (inetAddress.equals(address.getAddress()) && ! TextUtils.isEmpty(FDroidApp.ipAddressString)) {
String cidr = String.format("%s/%i", FDroidApp.ipAddressString, address.getNetworkPrefixLength());
FDroidApp.subnetInfo = (new SubnetUtils(cidr)).getInfo();
break;
}
}
} }
} }
} }
} catch (SocketException e) { } catch (SocketException e) {
Log.e(TAG, "Could not get ip address", e); Log.e(TAG, "Could not get ip address", e);
} }
return null;
} }
private String formatIpAddress(int ipAddress) { private String formatIpAddress(int ipAddress) {