diff --git a/app/src/full/java/org/fdroid/fdroid/FDroidApp.java b/app/src/full/java/org/fdroid/fdroid/FDroidApp.java index 70b5ce6aa..1eef90c4a 100644 --- a/app/src/full/java/org/fdroid/fdroid/FDroidApp.java +++ b/app/src/full/java/org/fdroid/fdroid/FDroidApp.java @@ -3,6 +3,7 @@ package org.fdroid.fdroid; import android.content.Context; import org.apache.commons.net.util.SubnetUtils; +import org.apache.commons.net.util.SubnetUtils6; import org.fdroid.database.Repository; import org.fdroid.index.IndexFormatVersion; @@ -23,6 +24,8 @@ public class FDroidApp { @Nullable public static volatile SubnetUtils.SubnetInfo subnetInfo; @Nullable + public static volatile SubnetUtils6.SubnetInfo subnet6Info; + @Nullable public static volatile String ssid; @Nullable public static volatile String bssid; @@ -32,14 +35,12 @@ public class FDroidApp { @SuppressWarnings("unused") public static volatile String queryString; - public static final SubnetUtils.SubnetInfo UNSET_SUBNET_INFO = - new SubnetUtils("0.0.0.0/32").getInfo(); - public static void initWifiSettings() { port = generateNewPort ? (int) (Math.random() * 10000 + 8080) : port == 0 ? 8888 : port; generateNewPort = false; ipAddressString = null; - subnetInfo = UNSET_SUBNET_INFO; + subnetInfo = null; + subnet6Info = null; ssid = null; bssid = null; } diff --git a/app/src/full/java/org/fdroid/fdroid/nearby/SwapWorkflowActivity.java b/app/src/full/java/org/fdroid/fdroid/nearby/SwapWorkflowActivity.java index 73a336243..090a80843 100644 --- a/app/src/full/java/org/fdroid/fdroid/nearby/SwapWorkflowActivity.java +++ b/app/src/full/java/org/fdroid/fdroid/nearby/SwapWorkflowActivity.java @@ -71,6 +71,10 @@ import org.fdroid.fdroid.qr.CameraCharacteristicsChecker; import org.fdroid.settings.SettingsManager; import org.fdroid.ui.nearby.SwapSuccessViewModel; +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.UnknownHostException; import java.util.Date; import java.util.HashMap; import java.util.Locale; @@ -478,13 +482,27 @@ public class SwapWorkflowActivity extends AppCompatActivity { } private static boolean isSwapUrl(Uri uri) { - return isSwapUrl(uri.getHost(), uri.getPort()); + return isSwapUrl(uri.getHost()); } - private static boolean isSwapUrl(String host, int port) { - return port > 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 + private static boolean isSwapUrl(String host) { + try { + InetAddress hostIp = InetAddress.getByName(host); + if (hostIp instanceof Inet4Address && FDroidApp.subnetInfo != null) { + return FDroidApp.subnetInfo.isInRange(host); + } else if (hostIp instanceof Inet6Address && FDroidApp.subnet6Info != null) { + return FDroidApp.subnet6Info.isInRange(host); + } else { + // unable to verify subnet range + return false; + } + } catch (UnknownHostException e) { + // if the host can't be parsed, it isn't a valid ip address + return false; + } catch (NullPointerException e) { + // FDroidApp.subnetInfo/subnet6Info may not have been setup + return false; + } } private void promptToSelectWifiNetwork() { @@ -835,27 +853,26 @@ public class SwapWorkflowActivity extends AppCompatActivity { private boolean checkIfNewRepoOnSameWifi(NewRepoConfig newRepo) { // if this is a local repo, check we're on the same wifi - if (!TextUtils.isEmpty(newRepo.getBssid())) { - WifiManager wifiManager = ContextCompat.getSystemService(getApplicationContext(), - WifiManager.class); - WifiInfo wifiInfo = wifiManager.getConnectionInfo(); - String bssid = wifiInfo.getBSSID(); - if (TextUtils.isEmpty(bssid)) { - // device may not have wifi - return false; - } - bssid = bssid.toLowerCase(Locale.ENGLISH); - String newRepoBssid = Uri.decode(newRepo.getBssid()).toLowerCase(Locale.ENGLISH); - if (!bssid.equals(newRepoBssid)) { - // repo config bssid doesn't match device bssid - return false; - } - // repo config appears to be on same wifi as device - return true; - } else { - // repo config has empty bssid + if (TextUtils.isEmpty(newRepo.getBssid())) { + // repo may not be connected to an access point return false; } + WifiManager wifiManager = ContextCompat.getSystemService(getApplicationContext(), + WifiManager.class); + WifiInfo wifiInfo = wifiManager.getConnectionInfo(); + String bssid = wifiInfo.getBSSID(); + if (TextUtils.isEmpty(bssid)) { + // device may not be connected to an access point + return false; + } + bssid = bssid.toLowerCase(Locale.ENGLISH); + String newRepoBssid = Uri.decode(newRepo.getBssid()).toLowerCase(Locale.ENGLISH); + if (!bssid.equals(newRepoBssid)) { + // repo config bssid doesn't match device bssid, check subnet + return isSwapUrl(newRepo.getRepoUri()); + } + // repo config appears to be on same wifi as device + return true; } /** diff --git a/app/src/full/java/org/fdroid/fdroid/nearby/WifiStateChangeService.java b/app/src/full/java/org/fdroid/fdroid/nearby/WifiStateChangeService.java index fbc169285..e565a8e5b 100644 --- a/app/src/full/java/org/fdroid/fdroid/nearby/WifiStateChangeService.java +++ b/app/src/full/java/org/fdroid/fdroid/nearby/WifiStateChangeService.java @@ -25,6 +25,7 @@ import androidx.work.Worker; import androidx.work.WorkerParameters; import org.apache.commons.net.util.SubnetUtils; +import org.apache.commons.net.util.SubnetUtils6; import org.fdroid.database.Repository; import org.fdroid.BuildConfig; import org.fdroid.fdroid.FDroidApp; @@ -33,6 +34,7 @@ import org.fdroid.fdroid.Preferences; import org.fdroid.R; import org.fdroid.fdroid.Utils; +import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.net.InterfaceAddress; @@ -166,24 +168,9 @@ public class WifiStateChangeService extends Worker { } if (wifiState == WifiManager.WIFI_STATE_ENABLED) { wifiInfo = wifiManager.getConnectionInfo(); - FDroidApp.ipAddressString = formatIpAddress(wifiInfo.getIpAddress()); setSsid(wifiInfo); - DhcpInfo dhcpInfo = wifiManager.getDhcpInfo(); - if (dhcpInfo != null) { - String netmask = formatIpAddress(dhcpInfo.netmask); - if (!TextUtils.isEmpty(FDroidApp.ipAddressString) && netmask != null) { - try { - FDroidApp.subnetInfo = new SubnetUtils(FDroidApp.ipAddressString, netmask).getInfo(); - } catch (IllegalArgumentException e) { - // catch mystery: "java.lang.IllegalArgumentException: Could not parse [null/24]" - e.printStackTrace(); - } - } - } - if (FDroidApp.ipAddressString == null - || FDroidApp.subnetInfo == FDroidApp.UNSET_SUBNET_INFO) { - setIpInfoFromNetworkInterface(); - } + // WifiInfo only supports ipv4 so use network interface instead + setIpInfoFromNetworkInterface(); } else if (wifiState == WifiManager.WIFI_STATE_DISABLED || wifiState == WifiManager.WIFI_STATE_DISABLING || wifiState == WifiManager.WIFI_STATE_UNKNOWN) { @@ -323,7 +310,7 @@ public class WifiStateChangeService extends Worker { for (Enumeration inetAddresses = netIf.getInetAddresses(); inetAddresses.hasMoreElements(); ) { InetAddress inetAddress = inetAddresses.nextElement(); - if (inetAddress.isLoopbackAddress() || inetAddress instanceof Inet6Address) { + if (inetAddress.isLoopbackAddress()) { continue; } if (netIf.getDisplayName().contains("wlan0") @@ -332,16 +319,26 @@ public class WifiStateChangeService extends Worker { FDroidApp.ipAddressString = inetAddress.getHostAddress(); for (InterfaceAddress address : netIf.getInterfaceAddresses()) { short networkPrefixLength = address.getNetworkPrefixLength(); - if (networkPrefixLength > 32) { - // something is giving a "/64" netmask, IPv6? - // java.lang.IllegalArgumentException: Value [64] not in range [0,32] + // assume that ipv6 prefix length > 32 + if ((inetAddress instanceof Inet4Address && networkPrefixLength > 32) + || (inetAddress instanceof Inet6Address && networkPrefixLength <= 32)) { continue; } + // include support for both ipv4 and ipv6 try { - String cidr = String.format(Locale.ENGLISH, "%s/%d", - FDroidApp.ipAddressString, networkPrefixLength); - FDroidApp.subnetInfo = new SubnetUtils(cidr).getInfo(); - break; + if (inetAddress instanceof Inet4Address) { + String cidr = String.format(Locale.ENGLISH, "%s/%d", + FDroidApp.ipAddressString, networkPrefixLength); + FDroidApp.subnetInfo = new SubnetUtils(cidr).getInfo(); + break; + } else if (inetAddress instanceof Inet6Address) { + String cidr = String.format(Locale.ENGLISH, "%s/%d", + FDroidApp.ipAddressString, networkPrefixLength); + FDroidApp.subnet6Info = new SubnetUtils6(cidr).getInfo(); + break; + } else { + Log.i(TAG, "Unexpected address type: " + inetAddress.getHostAddress()); + } } catch (IllegalArgumentException e) { if (BuildConfig.DEBUG) { e.printStackTrace();