diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/RepeaterFragment.kt b/mobile/src/main/java/be/mygod/vpnhotspot/RepeaterFragment.kt index 082d7473..60d66959 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/RepeaterFragment.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/RepeaterFragment.kt @@ -245,8 +245,8 @@ class RepeaterFragment : Fragment(), ServiceConnection, Toolbar.OnMenuItemClickL val conf = P2pSupplicantConfiguration() wifi.SSID = ssid wifi.preSharedKey = binder.password - if (wifi.preSharedKey == null || wifi.preSharedKey.length < 8) wifi.preSharedKey = conf.readPsk() - if (wifi.preSharedKey != null && wifi.preSharedKey.length >= 8) { + if (wifi.preSharedKey == null) wifi.preSharedKey = conf.readPsk() + if (wifi.preSharedKey != null) { var dialog: WifiP2pDialog? = null dialog = WifiP2pDialog(context, DialogInterface.OnClickListener { _, which -> when (which) { diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/RepeaterService.kt b/mobile/src/main/java/be/mygod/vpnhotspot/RepeaterService.kt index 5213b002..42707233 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/RepeaterService.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/RepeaterService.kt @@ -47,6 +47,8 @@ class RepeaterService : Service(), WifiP2pManager.ChannelListener, VpnMonitor.Ca val ssid get() = group?.networkName val password get() = group?.passphrase + private var groups: Collection = emptyList() + fun startWps(pin: String? = null) { if (!active) return val wps = WpsInfo() @@ -67,8 +69,8 @@ class RepeaterService : Service(), WifiP2pManager.ChannelListener, VpnMonitor.Ca if (active) removeGroup() } - fun resetCredentials() { - p2pManager.deletePersistentGroup(channel, (group ?: return).netId, object : WifiP2pManager.ActionListener { + fun resetCredentials() = (groups + group).filterNotNull().forEach { + p2pManager.deletePersistentGroup(channel, it.netId, object : WifiP2pManager.ActionListener { override fun onSuccess() = Toast.makeText(this@RepeaterService, R.string.repeater_reset_credentials_success, Toast.LENGTH_SHORT).show() override fun onFailure(reason: Int) = Toast.makeText(this@RepeaterService, @@ -80,11 +82,8 @@ class RepeaterService : Service(), WifiP2pManager.ChannelListener, VpnMonitor.Ca group = null try { p2pManager.requestPersistentGroupInfo(channel, { - when (it.size) { - 0 -> { } - 1 -> group = it.single() - else -> Log.w(TAG, "Unexpected groups: $it") - } + groups = it + if (it.size == 1) group = it.single() }) } catch (e: ReflectiveOperationException) { e.printStackTrace() diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/net/wifi/P2pSupplicantConfiguration.kt b/mobile/src/main/java/be/mygod/vpnhotspot/net/wifi/P2pSupplicantConfiguration.kt index a748cd22..74a45f24 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/net/wifi/P2pSupplicantConfiguration.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/net/wifi/P2pSupplicantConfiguration.kt @@ -12,16 +12,27 @@ import java.io.File class P2pSupplicantConfiguration { companion object { private const val TAG = "P2pSupplicationConf" - // format for ssid is much more complicated, therefore we are only trying to find the line + /** + * Format for ssid is much more complicated, therefore we are only trying to find the line and rely on + * Android's results instead. + * + * Source: https://android.googlesource.com/platform/external/wpa_supplicant_8/+/2933359/src/utils/common.c#631 + */ private val ssidMatcher = "^[\\r\\t ]*ssid=".toRegex() - private val pskParser = "^[\\r\\t ]*psk=\"(.*)\"\$".toRegex(RegexOption.MULTILINE) + /** + * PSK parser can be found here: https://android.googlesource.com/platform/external/wpa_supplicant_8/+/d2986c2/wpa_supplicant/config.c#448 + */ + private val pskParser = "^[\\r\\t ]*psk=(ext:|\"(.*)\"|\"(.*)|[0-9a-fA-F]{64})".toRegex(RegexOption.MULTILINE) } private val content by lazy { loggerSu("cat /data/misc/wifi/p2p_supplicant.conf") } fun readPsk(): String? { return try { - pskParser.findAll(content ?: return null).single().groupValues[1] + val match = pskParser.findAll(content ?: return null).single() + val result = match.groupValues[2] + match.groupValues[3] // only one will match and hold non-empty value + check(result.length in 8..63) + result } catch (e: RuntimeException) { Log.w(TAG, content) e.printStackTrace() @@ -34,26 +45,24 @@ class P2pSupplicantConfiguration { val content = content ?: return null val tempFile = File.createTempFile("vpnhotspot-", ".conf", app.cacheDir) try { - var ssidFound = false - var pskFound = false + var ssidFound = 0 + var pskFound = 0 tempFile.printWriter().use { for (line in content.lineSequence()) it.println(when { ssidMatcher.containsMatchIn(line) -> { - ssidFound = true + ssidFound += 1 "\tssid=" + config.SSID.toByteArray() .joinToString("") { it.toInt().toString(16).padStart(2, '0') } } pskParser.containsMatchIn(line) -> { - pskFound = true + pskFound += 1 "\tpsk=\"${config.preSharedKey}\"" // no control chars or weird stuff } else -> line // do nothing }) } - if (!ssidFound || !pskFound) { - Log.w(TAG, "Invalid conf ($ssidFound, $pskFound): $content") - return false - } + if (ssidFound != 1 || pskFound != 1) Log.w(TAG, "Invalid conf ($ssidFound, $pskFound): $content") + if (ssidFound == 0 || pskFound == 0) return false // pkill not available on Lollipop. Source: https://android.googlesource.com/platform/system/core/+/master/shell_and_utilities/README.md return noisySu("cat ${tempFile.absolutePath} > /data/misc/wifi/p2p_supplicant.conf", if (Build.VERSION.SDK_INT >= 23) "pkill wpa_supplicant"