Use reflection instead of parcel magic to get around networkName check
This commit is contained in:
@@ -167,6 +167,7 @@ Greylisted/blacklisted APIs or internal constants: (some constants are hardcoded
|
||||
* (since API 26) `Landroid/net/wifi/WifiManager;->cancelLocalOnlyHotspotRequest()V,unsupported`
|
||||
* (prior to API 26) `Landroid/net/wifi/WifiManager;->setWifiApEnabled(Landroid/net/wifi/WifiConfiguration;Z)Z`
|
||||
* `Landroid/net/wifi/p2p/WifiP2pConfig$Builder;->MAC_ANY_ADDRESS:Landroid/net/MacAddress;,blocked`
|
||||
* (since API 29) `Landroid/net/wifi/p2p/WifiP2pConfig$Builder;->mNetworkName:Ljava/lang/String;,blocked`
|
||||
* `Landroid/net/wifi/p2p/WifiP2pManager;->startWps(Landroid/net/wifi/p2p/WifiP2pManager$Channel;Landroid/net/wifi/WpsInfo;Landroid/net/wifi/p2p/WifiP2pManager$ActionListener;)V,max-target-r`
|
||||
* (since API 28, prior to API 30) `Landroid/provider/Settings$Global;->SOFT_AP_TIMEOUT_ENABLED:Ljava/lang/String;,lo-prio,max-target-o`
|
||||
* (prior to API 30) `Lcom/android/internal/R$array;->config_tether_bluetooth_regexs:I,max-target-q`
|
||||
@@ -300,10 +301,7 @@ Nonexported system resources:
|
||||
* (since API 30) `@com.android.networkstack.tethering:array/config_tether_wigig_regexs`
|
||||
* (since API 30) `@com.android.wifi.resources:integer/config_wifiFrameworkSoftApShutDownTimeoutMilliseconds`
|
||||
|
||||
Other:
|
||||
|
||||
* (since API 29) `android.net.wifi.p2p.WifiP2pConfig` needs to be parcelized in a very specific order, except for possible extra fields at the end. (used only for safe mode)
|
||||
* Activity `com.android.settings/.Settings$TetherSettingsActivity` is assumed to be exported.
|
||||
Other: Activity `com.android.settings/.Settings$TetherSettingsActivity` is assumed to be exported.
|
||||
|
||||
For `ip rule` priorities, `RULE_PRIORITY_SECURE_VPN` and `RULE_PRIORITY_TETHERING` is assumed to be 12000 and 18000 respectively;
|
||||
(prior to API 24) `RULE_PRIORITY_DEFAULT_NETWORK` is assumed to be 22000 (or at least > 18000).
|
||||
|
||||
@@ -13,7 +13,6 @@ import android.os.Looper
|
||||
import android.provider.Settings
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.content.edit
|
||||
import be.mygod.librootkotlinx.useParcel
|
||||
import be.mygod.vpnhotspot.App.Companion.app
|
||||
import be.mygod.vpnhotspot.net.MacAddressCompat
|
||||
import be.mygod.vpnhotspot.net.monitor.TetherTimeoutMonitor
|
||||
@@ -48,10 +47,6 @@ class RepeaterService : Service(), CoroutineScope, WifiP2pManager.ChannelListene
|
||||
private const val KEY_AUTO_SHUTDOWN = "service.repeater.autoShutdown"
|
||||
private const val KEY_SHUTDOWN_TIMEOUT = "service.repeater.shutdownTimeout"
|
||||
private const val KEY_DEVICE_ADDRESS = "service.repeater.mac"
|
||||
/**
|
||||
* Placeholder for bypassing networkName check.
|
||||
*/
|
||||
private const val PLACEHOLDER_NETWORK_NAME = "DIRECT-00-VPNHotspot"
|
||||
|
||||
var persistentSupported = false
|
||||
|
||||
@@ -65,6 +60,7 @@ class RepeaterService : Service(), CoroutineScope, WifiP2pManager.ChannelListene
|
||||
val safeModeConfigurable get() = Build.VERSION.SDK_INT >= 29 && hasP2pValidateName
|
||||
val safeMode get() = Build.VERSION.SDK_INT >= 29 &&
|
||||
(!hasP2pValidateName || app.pref.getBoolean(KEY_SAFE_MODE, true))
|
||||
private val mNetworkName by lazy { UnblockCentral.WifiP2pConfig_Builder_mNetworkName }
|
||||
|
||||
var networkName: String?
|
||||
get() = app.pref.getString(KEY_NETWORK_NAME, null)
|
||||
@@ -372,7 +368,12 @@ class RepeaterService : Service(), CoroutineScope, WifiP2pManager.ChannelListene
|
||||
p2pManager.createGroup(channel, listener)
|
||||
} else @TargetApi(29) {
|
||||
p2pManager.createGroup(channel, WifiP2pConfig.Builder().apply {
|
||||
setNetworkName(PLACEHOLDER_NETWORK_NAME)
|
||||
try {
|
||||
mNetworkName.set(this, networkName) // bypass networkName check
|
||||
} catch (e: ReflectiveOperationException) {
|
||||
Timber.w(e)
|
||||
setNetworkName(networkName)
|
||||
}
|
||||
setPassphrase(passphrase)
|
||||
when (val oc = operatingChannel) {
|
||||
0 -> setGroupOperatingBand(when (val band = operatingBand) {
|
||||
@@ -386,37 +387,9 @@ class RepeaterService : Service(), CoroutineScope, WifiP2pManager.ChannelListene
|
||||
}
|
||||
}
|
||||
setDeviceAddress(deviceAddress?.toPlatform())
|
||||
}.build().run {
|
||||
useParcel { p ->
|
||||
p.writeParcelable(this, 0)
|
||||
val end = p.dataPosition()
|
||||
p.setDataPosition(0)
|
||||
val creator = p.readString()
|
||||
val deviceAddress = p.readString()
|
||||
val wps = p.readParcelable<WpsInfo>(javaClass.classLoader)
|
||||
val long = p.readLong()
|
||||
check(p.readString() == PLACEHOLDER_NETWORK_NAME)
|
||||
check(p.readString() == passphrase)
|
||||
val extrasLength = end - p.dataPosition()
|
||||
check(extrasLength and 3 == 0) // parcel should be padded
|
||||
if (extrasLength != 4) app.logEvent("p2p_config_extras_unexpected_length") {
|
||||
param("length", extrasLength.toLong())
|
||||
}.build(), listener)
|
||||
}
|
||||
val extras = (0 until extrasLength / 4).map { p.readInt() }
|
||||
p.setDataPosition(0)
|
||||
p.writeString(creator)
|
||||
p.writeString(deviceAddress)
|
||||
p.writeParcelable(wps, 0)
|
||||
p.writeLong(long)
|
||||
p.writeString(networkName)
|
||||
p.writeString(passphrase)
|
||||
extras.forEach(p::writeInt)
|
||||
p.setDataPosition(0)
|
||||
p.readParcelable(javaClass.classLoader)
|
||||
}
|
||||
}, listener)
|
||||
}
|
||||
} catch (e: SecurityException) {
|
||||
} catch (e: RuntimeException) {
|
||||
Timber.w(e)
|
||||
startFailure(e.readableMessage)
|
||||
}
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
package be.mygod.vpnhotspot.util
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.net.wifi.p2p.WifiP2pConfig
|
||||
import androidx.annotation.RequiresApi
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
* The central object for accessing all the useful blocked APIs. Thanks Google!
|
||||
*
|
||||
* Lazy cannot be used directly as it will create inner classes.
|
||||
*/
|
||||
@SuppressLint("DiscouragedPrivateApi")
|
||||
@SuppressLint("BlockedPrivateApi", "DiscouragedPrivateApi")
|
||||
@Suppress("FunctionName")
|
||||
object UnblockCentral {
|
||||
/**
|
||||
@@ -27,4 +30,9 @@ object UnblockCentral {
|
||||
|
||||
@RequiresApi(31)
|
||||
fun getApInstanceIdentifier(clazz: Class<*>) = init.let { clazz.getDeclaredMethod("getApInstanceIdentifier") }
|
||||
|
||||
@get:RequiresApi(29)
|
||||
val WifiP2pConfig_Builder_mNetworkName get() = init.let {
|
||||
WifiP2pConfig.Builder::class.java.getDeclaredField("mNetworkName").apply { isAccessible = true }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user