Wi-Fi na vifupisho vingine vingi. Jinsi ya kupata data kuhusu nodi za Wi-Fi kwenye programu ya Android bila kuvimba

Siku moja nilihitaji kuchanganua mitandao ya Wi-Fi kutoka kwa programu za Android na kupata data ya kina kuhusu sehemu za ufikiaji.

Hapa tulilazimika kukabiliana na shida kadhaa: off.Android nyaraka madarasa mengi yaliyoelezewa yaliacha kutumika (kiwango cha API> 26), ambayo haikuonyeshwa ndani yake; maelezo ya vitu vingine kwenye nyaraka ni ndogo (kwa mfano, uwanja wa uwezo wa darasa ScanResult wakati wa kuandika, karibu hakuna kinachoelezewa, ingawa ina data nyingi muhimu). Ugumu wa tatu unaweza kuwa katika ukweli kwamba unapofika karibu na Wi-Fi, isipokuwa kusoma nadharia na kuanzisha router kupitia localhost, unapaswa kukabiliana na idadi ya vifupisho vinavyoonekana kueleweka kibinafsi. Lakini inaweza isiwe dhahiri jinsi ya kuzihusisha na kuzipanga (hukumu ni ya kibinafsi na inategemea uzoefu wa hapo awali).

Makala haya yanajadili jinsi ya kupata data ya kina kuhusu mazingira ya Wi-Fi kutoka kwa msimbo wa Android bila NDK, udukuzi, lakini kwa kutumia API ya Android pekee na kuelewa jinsi ya kutafsiri.

Tusikawie tuanze kuandika msimbo.

1. Unda mradi

Dokezo hili linalenga wale ambao wameunda mradi wa Android zaidi ya mara moja, kwa hivyo tunaacha maelezo ya kipengee hiki. Msimbo ulio hapa chini utawasilishwa katika Kotlin, minSdkVersion=23.

2. Ruhusa za ufikiaji

Ili kufanya kazi na Wi-Fi kutoka kwa programu, utahitaji kupata ruhusa kadhaa kutoka kwa mtumiaji. Kulingana na nyaraka, ili kuchambua mtandao kwenye vifaa vilivyo na matoleo ya OS baada ya 8.0, pamoja na ufikiaji wa kutazama hali ya mtandao, unahitaji ufikiaji wa kubadilisha hali ya moduli ya Wi-Fi ya kifaa, au ufikiaji wa kuratibu (takriban au halisi). Kuanzia toleo la 9.0, lazima umwonyeshe mtumiaji kwa yote mawili, na pia umwombe mtumiaji kwa uwazi kuwasha huduma za eneo. Usisahau kuelezea mtumiaji kwa ujasiri kwamba hii ni matakwa ya Google, na sio hamu yetu ya kumpeleleza :)

Kwa hivyo, katika AndroidManifest.xml tutaongeza:

    <uses-permission android_name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android_name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android_name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android_name="android.permission.ACCESS_FINE_LOCATION"/>

Na katika nambari iliyo na kiunga cha Shughuli ya sasa:

import android.app.Activity
import android.content.Context
import android.location.LocationManager
import androidx.core.app.ActivityCompat

....

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            ActivityCompat.requestPermissions(
                activity,
                arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.CHANGE_WIFI_STATE),
                1
            )
            makeEnableLocationServices(activity.applicationContext)
        } else {
            ActivityCompat.requestPermissions(
                activity,
                arrayOf(Manifest.permission.CHANGE_WIFI_STATE),
                1
            )
        }

    /* Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ экран Π²ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ слуТбы ΠΏΠΎ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΡŽ мСстополоТСния */
    fun makeEnableLocationServices(context: Context) {
        // TODO: ΠΏΠ΅Ρ€Π΅Π΄ Π²Ρ‹Π·ΠΎΠ²ΠΎΠΌ этой Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π½Π°Π΄ΠΎ Ρ€Π°ΡΡΠΊΠ°Π·Π°Ρ‚ΡŒ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŽ, Π·Π°Ρ‡Π΅ΠΌ Π’Π°ΠΌ доступ ΠΊ ΠΌΠ΅ΡΡ‚ΠΎΠΏΠΎΠ»ΠΎΠΆΠ΅Π½ΠΈΡŽ
        val lm: LocationManager =
            context.applicationContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager

        val gpsEnabled: Boolean = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
        val networkEnabled: Boolean = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

        if (!gpsEnabled && !networkEnabled) {
            context.startActivity(Intent(ACTION_LOCATION_SOURCE_SETTINGS));
        }
    }

3. Unda BroadcastReceiver na ujiandikishe kwa matukio ya kusasisha data kuhusu kuchanganua mazingira ya mtandao wa Wi-Fi

val wifiManager = context.getSystemService(Context.WIFI_SERVICE) as WifiManager

val wifiScanReceiver = object : BroadcastReceiver() {

  override fun onReceive(context: Context, intent: Intent) {
    val success = intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false)
    if (success) {
      scanSuccess()
    } 
  }
}

val intentFilter = IntentFilter()
/* подписываСмся Π½Π° сообщСния ΠΎ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠΈ Π½ΠΎΠ²Ρ‹Ρ… Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² сканирования */
intentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)
context.registerReceiver(wifiScanReceiver, intentFilter)

val success = wifiManager.startScan()
if (!success) {
  /* Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ Π½Π΅ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ»ΠΎΡΡŒ ΠΏΡ€ΠΈ запускС сканирования, ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡŒΡ‚Π΅ Π²Ρ‹Π΄Π°Π½Ρ‹Π΅ Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ */
}

....

private fun scanSuccess() {
 /* Π²ΠΎΡ‚ ΠΎΠ½ΠΈ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ сканирования */
  val results: List<ScanResult> = wifiManager.scanResults
}

Mbinu ya WiFiManager.startScan katika hati imetiwa alama kuwa haitumiki tangu toleo la 28 la API, lakini imezimwa. kuongoza inapendekeza kuitumia.

Kwa jumla, tulipokea orodha ya vitu ScanResult.

4. Angalia ScanResult na uelewe masharti

Hebu tuangalie baadhi ya nyanja za darasa hili na tueleze zinamaanisha nini:

SSID - Kitambulisho cha Seti ya Huduma ni jina la mtandao

BSSID Kitambulisho cha Seti ya Msingi - Anwani ya MAC ya adapta ya mtandao (pointi ya Wi-Fi)

ngazi ya β€” Kiashiria cha Nguvu ya Mawimbi [dBm (DBm ya Kirusi)) kilichopokelewa - Desibel, nguvu ya kumbukumbu 1 mW.] - Kiashiria cha nguvu ya mawimbi iliyopokelewa. Huchukua thamani kutoka 0 hadi -100, zaidi kutoka 0, ndivyo nguvu ya mawimbi inavyozidi kupotea njiani kutoka kwa kisambazaji Wi-Fi hadi kwenye kifaa chako. Maelezo zaidi yanaweza kupatikana, kwa mfano, saa Wikipedia. Hapa nitakuambia kuwa kwa kutumia darasa la Android WifiManeja unaweza kurekebisha kiwango cha ishara kwa kiwango kutoka bora hadi mbaya katika hatua unayochagua:

        val wifiManager = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
        val numberOfLevels = 5
        val level = WifiManager.calculateSignalLevel(level, numberOfLevels)

frequency β€” masafa ya kufanya kazi ya kisambazaji cha Wi-Fi [Hz]. Mbali na frequency yenyewe, unaweza kupendezwa na kinachojulikana kama chaneli. Kila hatua ina usafi wake wa uendeshaji. Wakati wa kuandika, aina mbalimbali maarufu zaidi za pointi za Wi-Fi ni 2.4 GHz. Lakini, ili kuwa sahihi zaidi, sehemu hiyo hutuma taarifa kwa simu yako kwa masafa ya nambari karibu na ile iliyotajwa. Idadi ya chaneli na masafa yanayolingana sanifu. Hii inafanywa ili pointi zilizo karibu zifanye kazi kwa masafa tofauti, na hivyo haziingiliani na sio kupunguza kasi na ubora wa maambukizi. Katika kesi hii, alama hazifanyi kazi kwa masafa moja, lakini juu ya anuwai ya masafa (parameter channelWidth), inayoitwa upana wa kituo. Hiyo ni, pointi zinazofanya kazi karibu (na si tu karibu, lakini hata 3 kutoka kwao wenyewe) njia zinaingilia kati. Unaweza kupata msimbo huu rahisi kuwa muhimu, ambayo hukuruhusu kuhesabu nambari ya kituo kutoka kwa thamani ya masafa ya alama na masafa ya 2.4 na 5 Ghz:


    /* ΠΏΠΎ частотС опрСдСляСм Π½ΠΎΠΌΠ΅Ρ€ ΠΊΠ°Π½Π°Π»Π° */
    val channel: Int
        get() {
            return if (frequency in 2412..2484) {
                (frequency - 2412) / 5 + 1
            } else if (frequency in 5170..5825) {
                (frequency - 5170) / 5 + 34
            } else {
                -1
            }
        }

uwezo - uwanja wa kuvutia zaidi kwa uchambuzi, kazi ambayo ilihitaji muda mwingi. Hapa "uwezo" wa uhakika umeandikwa kwenye mstari. Katika kesi hii, sio lazima utafute maelezo ya tafsiri ya kamba kwenye hati. Hapa kuna mifano ya kile kinachoweza kuwa katika mstari huu:

[WPA-PSK-TKIP+CCMP][WPA2-PSK-TKIP+CCMP][WPS][ESS]
[WPA2-PSK-CCMP][ESS]
[WPA2-PSK-CCMP+TKIP][ESS]
[WPA-PSK-CCMP+TKIP][WPA2-PSK-CCMP+TKIP][ESS]
[ESS][WPS]

5. Kuelewa vifupisho na uwezo wa kuchanganua

Inafaa kutaja kwamba madarasa ya kifurushi cha android.net.wifi.* hutumiwa chini ya kifuniko na shirika la Linux. wpa_uhusika na matokeo ya pato katika uga wa uwezo ni nakala ya uga wa bendera wakati wa kuchanganua.

Tutachukua hatua mfululizo. Hebu kwanza tuchunguze matokeo ya umbizo ambalo vipengele ndani ya mabano vinatenganishwa na ishara β€œ-β€œ:

[WPA-PSK-TKIP+CCMP]
[WPA2-PSK-CCMP]

Maana ya kwanza inaelezea kinachojulikana. njia ya uthibitishaji. Hiyo ni, ni mlolongo gani wa vitendo lazima kifaa na sehemu ya ufikiaji ifanye ili mahali pa ufikiaji ijiruhusu kutumika na jinsi ya kusimba mzigo wa malipo. Wakati wa kuandika chapisho hili, chaguo za kawaida ni WPA na WPA2, ambayo ama kila kifaa kilichounganishwa moja kwa moja au kwa njia ya kinachojulikana. Seva ya RADIUS (WPA-Enterprice) hutoa nenosiri kwenye chaneli iliyosimbwa. Uwezekano mkubwa zaidi, hatua ya kufikia nyumbani kwako hutoa uunganisho kulingana na mpango huu. Tofauti kati ya toleo la pili na la kwanza ni kwamba ina cipher yenye nguvu zaidi: AES dhidi ya TKIP isiyo salama. WPA3, ambayo ni ngumu zaidi na ya juu, pia inaletwa hatua kwa hatua. Kinadharia, kunaweza kuwa na chaguo na suluhisho la biashara CCKM (Usimamizi wa Ufunguo wa Cisco Centralized), lakini sijawahi kukutana nayo.

Sehemu ya ufikiaji inaweza kuwa imesanidiwa ili kuthibitishwa na anwani ya MAC. Au, ikiwa eneo la ufikiaji hutoa data kwa kutumia algoriti ya WEP iliyopitwa na wakati, basi kwa kweli hakuna uthibitishaji (ufunguo wa siri hapa ni ufunguo wa usimbaji fiche). Tunaainisha chaguo kama NYINGINE.
Pia kuna njia ambayo ni maarufu katika wi-fi ya umma iliyo na Utambuzi wa Tovuti ya Wafungwa - ombi la uthibitishaji kupitia kivinjari. Sehemu kama hizo za ufikiaji zinaonekana kwa skana kama wazi (ambayo ni kutoka kwa mtazamo wa unganisho la mwili). Kwa hivyo, tunaziainisha kama FUNGUA.

Thamani ya pili inaweza kuonyeshwa kama algorithm muhimu ya usimamizi. Hii ni parameter ya njia ya uthibitishaji iliyoelezwa hapo juu. Inazungumza kuhusu jinsi funguo za usimbaji fiche zinabadilishwa. Hebu fikiria chaguzi zinazowezekana. EAP - inayotumika katika WPA-Enterprice iliyotajwa, hutumia hifadhidata ili kuthibitisha data iliyoingizwa ya uthibitishaji. SAE - kutumika katika WPA3 ya juu, sugu zaidi kwa nguvu ya kikatili. PSK - chaguo la kawaida, linahusisha kuingia nenosiri na kusambaza kwa fomu iliyofichwa. IEEE8021X - kulingana na kiwango cha kimataifa (tofauti na kinachoungwa mkono na familia ya WPA). OWE (Usimbaji Fiche wa Fursa wa Waya) ni kiendelezi cha kiwango cha IEEE 802.11 kwa pointi ambazo tuliainisha kuwa OPEN. OWE inahakikisha usalama wa data inayotumwa kwenye mtandao usiolindwa kwa kuisimba kwa njia fiche. Chaguo pia linawezekana wakati hakuna funguo za ufikiaji, wacha tuite chaguo hili HAKUNA.

Kigezo cha tatu ni kinachojulikana. mipango ya usimbaji fiche β€” jinsi hasa misimbo inatumiwa kulinda data inayotumwa. Wacha tuorodheshe chaguzi. WEP - hutumia cipher ya mkondo wa RC4, ufunguo wa siri ni ufunguo wa usimbuaji, ambao unachukuliwa kuwa haukubaliki katika ulimwengu wa cryptography ya kisasa. TKIP - kutumika katika WPA, CKIP - katika WPA2. TKIP+CKIP - inaweza kubainishwa katika pointi zinazoweza WPA na WPA2 kwa utangamano wa nyuma.

Badala ya vitu vitatu, unaweza kupata alama ya WEP ya upweke:

[WEP]

Kama tulivyojadili hapo juu, hii inatosha kutotaja algorithm ya kutumia funguo, ambayo haipo, na njia ya usimbuaji, ambayo ni sawa na chaguo-msingi.

Sasa fikiria mabano haya:

[ESS]

Ni Njia ya uendeshaji ya Wi-Fi au Topolojia ya mtandao wa Wi-Fi. Unaweza kukutana na hali ya BSS (Basic Service Set) - wakati kuna sehemu moja ya kufikia ambayo vifaa vilivyounganishwa vinawasiliana. Inaweza kupatikana kwenye mitandao ya ndani. Kama sheria, sehemu za ufikiaji zinahitajika ili kuunganisha vifaa kutoka kwa mitandao tofauti ya ndani, kwa hivyo ni sehemu ya Seti za Huduma Zilizopanuliwa - ESS. Aina ya IBSSs (Seti Huru za Huduma za Msingi) inaonyesha kuwa kifaa ni sehemu ya mtandao wa Peer-to-Rika.

Unaweza pia kuona bendera ya WPS:

[WPS]

WPS (Wi-Fi Protected Setup) ni itifaki ya uanzishaji wa nusu-otomatiki wa mtandao wa Wi-Fi. Ili kuanzisha, mtumiaji aidha huingiza nenosiri la herufi 8 au bonyeza kitufe kwenye kipanga njia. Ikiwa eneo lako la ufikiaji ni la aina ya kwanza na kisanduku cha kuteua hiki kinaonekana karibu na jina la eneo lako la ufikiaji, unapendekezwa sana kwenda kwenye paneli ya msimamizi na kuzima ufikiaji wa WPS. Ukweli ni kwamba mara nyingi PIN ya tarakimu 8 inaweza kupatikana kwa anwani ya MAC, au inaweza kutatuliwa kwa wakati unaoonekana, ambao mtu anaweza kuchukua faida kwa njia isiyo ya uaminifu.

6. Unda mfano na kazi ya kuchanganua

Kulingana na kile tulichogundua hapo juu, tutaelezea kile kilichotokea kwa kutumia madarasa ya data:

/* схСма Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠΈ */
enum class AuthMethod {
    WPA3,
    WPA2,
    WPA, // Wi-Fi Protected Access
    OTHER, // Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ Π² сСбя Shared Key Authentication ΠΈ Π΄Ρ€. ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‰ΠΈΠ΅ mac-address-based ΠΈ WEP
    CCKM, // Cisco
    OPEN // Open Authentication. ΠœΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ со скрытым Captive Portal Detection - запрос Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠΈ Ρ‡Π΅Ρ€Π΅Π· Π±Ρ€Π°ΡƒΠ·Π΅Ρ€
}

/* Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌ Π²Π²ΠΎΠ΄Π° ΠΊΠ»ΡŽΡ‡Π΅ΠΉ */
enum class KeyManagementAlgorithm {
    IEEE8021X, // ΠΏΠΎ стандарту
    EAP, // Extensible Authentication Protocol, Ρ€Π°ΡΡˆΠΈΡ€ΡΠ΅ΠΌΡ‹ΠΉ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠΈ
    PSK, // Pre-Shared Key β€” ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΡƒΠ·Π΅Π» Π²Π²ΠΎΠ΄ΠΈΡ‚ ΠΏΠ°Ρ€ΠΎΠ»ΡŒ для доступа ΠΊ сСти
    WEP, // Π² WEP ΠΏΠ°Ρ€ΠΎΠ»ΡŒ являСтся ΠΊΠ»ΡŽΡ‡ΠΎΠΌ ΡˆΠΈΡ„Ρ€ΠΎΠ²Π°Π½ΠΈΡ (No auth key)
    SAE, // Simultaneous Authentication of Equals - ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Π² WPA3
    OWE, // Opportunistic Wireless Encryption - Π² Ρ€ΠΎΡƒΡ‚Π΅Ρ€Π°Ρ… Π½ΠΎΠ²Ρ‹Ρ… ΠΏΠΎΠΊΠΎΠ»Π΅Π½ΠΈΠΉ, ΠΏΡƒΠ±Π»ΠΈΡ‡Π½Ρ‹Ρ… сСтях Ρ‚ΠΈΠΏΠ° OPEN
    NONE // ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Π±Π΅Π· ΡˆΠΈΡ„Ρ€ΠΎΠ²Π°Π½ΠΈΡ Π² OPEN, OTHER
}

/* ΠΌΠ΅Ρ‚ΠΎΠ΄ ΡˆΠΈΡ„Ρ€ΠΎΠ²Π°Π½ΠΈΡ */
enum class CipherMethod {
    WEP, // Wired Equivalent Privacy, Аналог ΡˆΠΈΡ„Ρ€ΠΎΠ²Π°Π½ΠΈΡ Ρ‚Ρ€Π°Ρ„ΠΈΠΊΠ° Π² ΠΏΡ€ΠΎΠ²ΠΎΠ΄Π½Ρ‹Ρ… сСтях
    TKIP, // Temporal Key Integrity Protocol
    CCMP, // Counter Mode with Cipher Block Chaining Message Authentication Code Protocol,
    // ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» Π±Π»ΠΎΡ‡Π½ΠΎΠ³ΠΎ ΡˆΠΈΡ„Ρ€ΠΎΠ²Π°Π½ΠΈΡ с ΠΊΠΎΠ΄ΠΎΠΌ аутСнтичности сообщСния ΠΈ Ρ€Π΅ΠΆΠΈΠΌΠΎΠΌ сцСплСния Π±Π»ΠΎΠΊΠΎΠ² ΠΈ счСтчика
    // на основС AES
    NONE // ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Π±Π΅Π· ΡˆΠΈΡ„Ρ€ΠΎΠ²Π°Π½ΠΈΡ Π² OPEN, OTHER
}

/* Π½Π°Π±ΠΎΡ€ ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ² ΡˆΠΈΡ„Ρ€ΠΎΠ²Π°Π½ΠΈΡ ΠΈ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»ΠΎΠ², ΠΏΠΎ ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌ ΠΌΠΎΠΆΠ΅Ρ‚ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Ρ‚ΠΎΡ‡ΠΊΠ° */
data class Capability(
    var authScheme: AuthMethod? = null,
    var keyManagementAlgorithm: KeyManagementAlgorithm? = null,
    var cipherMethod: CipherMethod? = null
)

/* Π Π΅ΠΆΠΈΠΌ Ρ€Π°Π±ΠΎΡ‚Ρ‹ WiFi (ΠΈΠ»ΠΈ топология сСтСй WiFi) */
enum class TopologyMode {
    IBSS, // ЭпизодичСская ΡΠ΅Ρ‚ΡŒ (Ad-Hoc ΠΈΠ»ΠΈ IBSS – Independent Basic Service Set).
    BSS, // Основная Π·ΠΎΠ½Π° обслуТивания Basic Service Set (BSS) ΠΈΠ»ΠΈ Infrastructure Mode.
    ESS // Π Π°ΡΡˆΠΈΡ€Π΅Π½Π½Π°Ρ Π·ΠΎΠ½Π° обслуТивания ESS – Extended Service Set.
}

Sasa wacha tuandike kazi ambayo itachanganua uwanja wa uwezo:


private fun parseCapabilities(capabilitiesString: String): List < Capability > {
    val capabilities: List < Capability > = capabilitiesString
        .splitByBrackets()
        .filter {
            !it.isTopology() && !it.isWps()
        }
        .flatMap {
            parseCapability(it)
        }
    return
        if (!capabilities.isEmpty()) {
            capabilities
        } else {
            listOf(Capability(AuthMethod.OPEN, KeyManagementAlgorithm.NONE, CipherMethod.NONE))
        }
}

private fun parseCapability(part: String): List < Capability > {
    if (part.contains("WEP")) {
        return listOf(Capability(
            AuthMethod.OTHER,
            KeyManagementAlgorithm.WEP,
            CipherMethod.WEP
        ))
    }

    val authScheme = when {
        part.contains("WPA3") - > AuthMethod.WPA3
        part.contains("WPA2") - > AuthMethod.WPA2
        part.contains("WPA") - > AuthMethod.WPA
        else - > null
    }

    val keyManagementAlgorithm = when {
        part.contains("OWE") - > KeyManagementAlgorithm.OWE
        part.contains("SAE") - > KeyManagementAlgorithm.SAE
        part.contains("IEEE802.1X") - > KeyManagementAlgorithm.IEEE8021X
        part.contains("EAP") - > KeyManagementAlgorithm.EAP
        part.contains("PSK") - > KeyManagementAlgorithm.PSK
        else - > null
    }

    val capabilities = ArrayList < Capability > ()
    if (part.contains("TKIP") || part.contains("CCMP")) {
        if (part.contains("TKIP")) {
            capabilities.add(Capability(
                authScheme ? : AuthMethod.OPEN,
                keyManagementAlgorithm ? : KeyManagementAlgorithm.NONE,
                CipherMethod.TKIP
            ))
        }
        if (part.contains("CCMP")) {
            capabilities.add(Capability(
                authScheme ? : AuthMethod.OPEN,
                keyManagementAlgorithm ? : KeyManagementAlgorithm.NONE,
                CipherMethod.CCMP
            ))
        }
    } else if (authScheme != null || keyManagementAlgorithm != null) {
        capabilities.add(Capability(
            authScheme ? : AuthMethod.OPEN,
            keyManagementAlgorithm ? : KeyManagementAlgorithm.NONE,
            CipherMethod.NONE
        ))
    }

    return capabilities
}

private fun parseTopologyMode(capabilitiesString: String): TopologyMode ? {
    return capabilitiesString
        .splitByBrackets()
        .mapNotNull {
            when {
                it.contains("ESS") - > TopologyMode.ESS
                it.contains("BSS") - > TopologyMode.BSS
                it.contains("IBSS") - > TopologyMode.IBSS
                else - > null
            }
        }
        .firstOrNull()
}

private fun parseWPSAvailable(capabilitiesString: String): Boolean {
    return capabilitiesString
        .splitByBrackets()
        .any {
            it.isWps()
        }
}

private fun String.splitByBrackets(): List < String > {
    val m = Pattern.compile("[(.*?)]").matcher(this)
    val parts = ArrayList < String > ()
    while (m.find()) {
        parts.add(m.group().replace("[", "").replace("]", ""))
    }
    return parts
}

private fun String.isTopology(): Boolean {
    return TopologyMode.values().any {
        this == it.name
    }
}

private fun String.isWps(): Boolean {
    return this == "WPS"
}

8. Tazama matokeo

Nitachanganua mtandao na kukuonyesha nilichopata. Imeonyeshwa matokeo ya pato rahisi kupitia Log.d:

Capability of Home-Home [WPA2-PSK-CCMP][ESS][WPS]
...
capabilities=[Capability(authScheme=WPA2, keyManagementAlgorithm=PSK, cipherMethod=CCMP)], topologyMode=ESS, availableWps=true

Suala la kuunganisha kwenye mtandao kutoka kwa msimbo wa maombi lilibakia bila kuchunguzwa. Nitasema tu kwamba ili kusoma nywila zilizohifadhiwa za OS ya kifaa cha rununu, unahitaji haki za mizizi na nia ya kuvinjari kupitia mfumo wa faili kusoma wpa_supplicant.conf. Ikiwa mantiki ya programu inahitaji kuingiza nenosiri kutoka nje, uunganisho unaweza kufanywa kupitia darasa android.net.wifi.WifiManager.

Shukrani Egor Ponomarev kwa nyongeza za thamani.

Ikiwa unafikiri kitu kinahitaji kuongezwa au kusahihishwa, andika kwenye maoni :)

Chanzo: mapenzi.com

Kuongeza maoni