From 6924cce826dff07a260b4338eba4f57584d38793 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E6=81=92aead?= Date: Mon, 2 Sep 2024 18:35:22 +0800 Subject: [PATCH 1/3] =?UTF-8?q?[=E4=BC=98=E5=8C=96]=20=E5=8F=AF=E6=AD=A3?= =?UTF-8?q?=E5=B8=B8=20=E6=98=BE=E7=A4=BA=20UTF-8=E7=BC=96=E7=A0=81?= =?UTF-8?q?=E7=9A=84=E4=B8=AD=E6=96=87=E5=AD=97=E7=AC=A6=20=E4=BB=A5?= =?UTF-8?q?=E5=8F=8A=20=E8=BF=9E=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pywifi/_wifiutil_win.py | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/pywifi/_wifiutil_win.py b/pywifi/_wifiutil_win.py index d0adb11..d4a54d1 100755 --- a/pywifi/_wifiutil_win.py +++ b/pywifi/_wifiutil_win.py @@ -277,7 +277,30 @@ def scan_results(self, obj): if networks[i].dot11Ssid.ucSSID != b'': ssid += "%c" % networks[i].dot11Ssid.ucSSID[j] - + + # * 该部分用于将SSID转换为UTF-8编码,可正常显示中文字符 p.s.由 PR #31 提供 + temp_cnt = 0 + temp_hex_res = 0 + bytes_list = [] + converted_name = "" + for bin_encode_char in ssid: + if (32 <= ord(bin_encode_char) <= 126): + converted_name = converted_name + bin_encode_char + else: + temp_cnt = temp_cnt + 1 + temp_now = int(str(bin(ord(bin_encode_char)))[2:6], 2) + temp_now1 = int(str(bin(ord(bin_encode_char)))[6:10], 2) + temp_hex_res = temp_hex_res + temp_now * 16 + temp_now1 + bytes_list.append(temp_hex_res) + temp_hex_res = 0 + if temp_cnt == 3: + converted_name = converted_name + bytes(bytes_list).decode('utf-8', 'ignore') + bytes_list = [] + temp_hex_res = 0 + temp_cnt = 0 + ssid = converted_name + # * 转换结束 + bss_list = pointer(WLAN_BSS_LIST()) self._wlan_get_network_bss_list(self._handle, byref(obj['guid']), byref(bss_list), networks[i].dot11Ssid, networks[i].bSecurityEnabled) @@ -333,6 +356,8 @@ def add_network_profile(self, obj, params): params.process_akm() profile_data = {} + # * 使用hex编码,优化对使用了utf-8编码的中文WiFi SSID的连接的适配性 + profile_data['hex'] = ''.join(['%02X' % byte for byte in params.ssid.encode('utf-8')]) profile_data['ssid'] = params.ssid if AKM_TYPE_NONE in params.akm: @@ -352,6 +377,7 @@ def add_network_profile(self, obj, params): {profile_name} + {hex} {ssid} From 6d0b89af51f57643d7e4a2fedc115f164ae22ad1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E6=81=92aead?= Date: Wed, 4 Sep 2024 17:43:56 +0800 Subject: [PATCH 2/3] =?UTF-8?q?[=E6=96=B0=E5=A2=9E]=20win=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=AE=89=E5=85=A8=E7=B1=BB=E5=9E=8BWPA3=E3=80=82=20[?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D]=20wifi=E6=89=AB=E6=8F=8F=E7=BB=93=E6=9E=9C?= =?UTF-8?q?=E4=B8=AD=E5=AE=89=E5=85=A8=E7=B1=BB=E5=9E=8B=E4=B8=8D=E6=AD=A3?= =?UTF-8?q?=E7=A1=AE=E7=9A=84=E9=97=AE=E9=A2=98=E3=80=82=20[=E4=BC=98?= =?UTF-8?q?=E5=8C=96]=20=E9=83=A8=E5=88=86=E5=8A=9F=E8=83=BD=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pywifi/_wifiutil_win.py | 154 +++++++++++++++++++++++++--------------- pywifi/const.py | 24 ++++--- pywifi/profile.py | 14 ++-- setup.py | 2 +- 4 files changed, 121 insertions(+), 73 deletions(-) diff --git a/pywifi/_wifiutil_win.py b/pywifi/_wifiutil_win.py index d4a54d1..7778ab2 100755 --- a/pywifi/_wifiutil_win.py +++ b/pywifi/_wifiutil_win.py @@ -7,8 +7,8 @@ import platform import time import logging -from ctypes import * -from ctypes.wintypes import * +from ctypes import * # type: ignore +from ctypes.wintypes import * # type: ignore from comtypes import GUID from .const import * @@ -61,20 +61,28 @@ akm_str_to_value_dict = { 'NONE': AKM_TYPE_NONE, + 'open': AKM_TYPE_OPEN, + 'shared': AKM_TYPE_SHARED, 'WPA': AKM_TYPE_WPA, 'WPAPSK': AKM_TYPE_WPAPSK, 'WPA2': AKM_TYPE_WPA2, 'WPA2PSK': AKM_TYPE_WPA2PSK, - 'OTHER': AKM_TYPE_UNKNOWN + 'WPA3': AKM_TYPE_WPA3, + 'WPA3SAE': AKM_TYPE_WPA3SAE, + 'OTHER': AKM_TYPE_OWE } akm_value_to_str_dict = { AKM_TYPE_NONE: 'NONE', + AKM_TYPE_OPEN: 'open', + AKM_TYPE_SHARED: 'shared', AKM_TYPE_WPA: 'WPA', AKM_TYPE_WPAPSK: 'WPAPSK', AKM_TYPE_WPA2: 'WPA2', AKM_TYPE_WPA2PSK: 'WPA2PSK', - AKM_TYPE_UNKNOWN: 'OTHER' + AKM_TYPE_WPA3: 'WPA3', + AKM_TYPE_WPA3SAE: 'WPA3SAE', + AKM_TYPE_OWE: 'OTHER' } cipher_str_to_value_dict = { @@ -284,20 +292,47 @@ def scan_results(self, obj): bytes_list = [] converted_name = "" for bin_encode_char in ssid: + # if (32 <= ord(bin_encode_char) <= 126): + # converted_name = converted_name + bin_encode_char + # else: + # temp_cnt = temp_cnt + 1 + # temp_now = int(str(bin(ord(bin_encode_char)))[2:6], 2) + # temp_now1 = int(str(bin(ord(bin_encode_char)))[6:10], 2) + # temp_hex_res = temp_hex_res + temp_now * 16 + temp_now1 + # bytes_list.append(temp_hex_res) + # temp_hex_res = 0 + # if temp_cnt == 4: + # converted_name = converted_name + bytes(bytes_list).decode('utf-8', 'ignore') + # bytes_list = [] + # temp_hex_res = 0 + # temp_cnt = 0 if (32 <= ord(bin_encode_char) <= 126): - converted_name = converted_name + bin_encode_char + converted_name += bin_encode_char else: - temp_cnt = temp_cnt + 1 + temp_cnt += 1 temp_now = int(str(bin(ord(bin_encode_char)))[2:6], 2) temp_now1 = int(str(bin(ord(bin_encode_char)))[6:10], 2) temp_hex_res = temp_hex_res + temp_now * 16 + temp_now1 bytes_list.append(temp_hex_res) temp_hex_res = 0 - if temp_cnt == 3: - converted_name = converted_name + bytes(bytes_list).decode('utf-8', 'ignore') - bytes_list = [] - temp_hex_res = 0 - temp_cnt = 0 + # 收集到完整的UTF-8字符时(最多四个字节) + if temp_cnt >= 1 and temp_cnt <= 4: + try: + converted_name = converted_name + bytes(bytes_list).decode('utf-8') + bytes_list = [] + temp_hex_res = 0 + temp_cnt = 0 + except UnicodeDecodeError: + # 如果解码失败,忽略错误并继续处理下一个字符 + pass + # 处理末尾可能剩下的未完成的字节序列 + if bytes_list: + try: + decoded_chars = bytes(bytes_list).decode('utf-8', 'ignore') + converted_name += decoded_chars + except UnicodeDecodeError: + pass + ssid = converted_name # * 转换结束 @@ -307,26 +342,33 @@ def scan_results(self, obj): bsses = cast(bss_list.contents.wlanBssEntries, POINTER(WLAN_BSS_ENTRY)) + # if ssid == 'testtest': + # print(f'auth:{networks[i].dot11DefaultAuthAlgorithm}') + # print(f'cipher:{networks[i].dot11DefaultCipherAlgorithm}') + if networks[i].bSecurityEnabled: - akm = self._get_akm(networks[i].dot11DefaultCipherAlgorithm) + akm = networks[i].dot11DefaultAuthAlgorithm auth_alg = self._get_auth_alg(networks[i].dot11DefaultAuthAlgorithm) + cipher = networks[i].dot11DefaultCipherAlgorithm else: - akm = [AKM_TYPE_NONE] - auth_alg = [AUTH_ALG_OPEN] + akm = AKM_TYPE_OPEN + auth_alg = AUTH_ALG_OPEN + cipher = CIPHER_TYPE_NONE for j in range(bss_list.contents.dwNumberOfItems): network = Profile() - network.ssid = ssid + network.ssid = ssid # type: ignore - network.bssid = '' + network.bssid = '' # type: ignore for k in range(6): network.bssid += "%02x:" % bsses[j].dot11Bssid[k] - network.signal = bsses[j].lRssi - network.freq = bsses[j].ulChCenterFrequency + network.signal = bsses[j].lRssi # type: ignore + network.freq = bsses[j].ulChCenterFrequency # type: ignore network.auth = auth_alg network.akm = akm + network.cipher = cipher network_list.append(network) return network_list @@ -354,22 +396,21 @@ def add_network_profile(self, obj, params): reason_code = DWORD() - params.process_akm() profile_data = {} # * 使用hex编码,优化对使用了utf-8编码的中文WiFi SSID的连接的适配性 profile_data['hex'] = ''.join(['%02X' % byte for byte in params.ssid.encode('utf-8')]) profile_data['ssid'] = params.ssid - if AKM_TYPE_NONE in params.akm: - profile_data['auth'] = auth_value_to_str_dict[params.auth] + if params.akm in (AKM_TYPE_NONE,AKM_TYPE_OPEN): + profile_data['auth'] = 'open' profile_data['encrypt'] = "none" else: - profile_data['auth'] = akm_value_to_str_dict[params.akm[-1]] + profile_data['auth'] = akm_value_to_str_dict[params.akm] profile_data['encrypt'] = cipher_value_to_str_dict[params.cipher] profile_data['key'] = params.key - profile_data['protected'] = 'false' + profile_data['protected'] = "false" profile_data['profile_name'] = params.ssid xml = """ @@ -392,7 +433,7 @@ def add_network_profile(self, obj, params): """ - if AKM_TYPE_NONE not in params.akm: + if params.akm not in (AKM_TYPE_NONE,AKM_TYPE_OPEN): xml += """ passPhrase {protected} @@ -410,6 +451,8 @@ def add_network_profile(self, obj, params): """ xml = xml.format(**profile_data) + + # print(xml) status = self._wlan_set_profile(self._handle, obj['guid'], xml, True, byref(reason_code)) @@ -456,20 +499,17 @@ def network_profiles(self, obj): profile_name, byref(xml), byref(flags), byref(access)) # fill profile info - profile.ssid = re.search(r'(.*)', xml.value).group(1) + profile.ssid = re.search(r'(.*)', xml.value).group(1) # type: ignore auth = re.search(r'(.*)', - xml.value).group(1).upper() + xml.value).group(1).upper() # type: ignore - profile.akm = [] + profile.akm = AKM_TYPE_NONE if auth not in akm_str_to_value_dict: - if auth not in auth_str_to_value_dict: - profile.auth = AUTH_ALG_OPEN - else: - profile.auth = auth_str_to_value_dict[auth] - profile.akm.append(AKM_TYPE_NONE) + profile.auth = auth_str_to_value_dict[auth] + profile.akm = AKM_TYPE_NONE else: - profile.auth = AUTH_ALG_OPEN - profile.akm.append(akm_str_to_value_dict[auth]) + profile.auth = AUTH_ALG_OPEN + profile.akm = akm_str_to_value_dict[auth] profile_list.append(profile) @@ -535,14 +575,14 @@ def _wlan_open_handle(self, client_version, _nego_version, handle): func = native_wifi.WlanOpenHandle func.argtypes = [DWORD, c_void_p, POINTER(DWORD), POINTER(HANDLE)] - func.restypes = [DWORD] + func.restypes = [DWORD] # type: ignore return func(client_version, None, _nego_version, handle) def _wlan_close_handle(self, handle): func = native_wifi.WlanCloseHandle func.argtypes = [HANDLE, c_void_p] - func.restypes = [DWORD] + func.restypes = [DWORD] # type: ignore return func(handle, None) def _wlan_enum_interfaces(self, handle, ifaces): @@ -550,7 +590,7 @@ def _wlan_enum_interfaces(self, handle, ifaces): func = native_wifi.WlanEnumInterfaces func.argtypes = [HANDLE, c_void_p, POINTER( POINTER(WLAN_INTERFACE_INFO_LIST))] - func.restypes = [DWORD] + func.restypes = [DWORD] # type: ignore return func(handle, None, ifaces) def _wlan_get_available_network_list(self, handle, @@ -560,7 +600,7 @@ def _wlan_get_available_network_list(self, handle, func = native_wifi.WlanGetAvailableNetworkList func.argtypes = [HANDLE, POINTER(GUID), DWORD, c_void_p, POINTER( POINTER(WLAN_AVAILABLE_NETWORK_LIST))] - func.restypes = [DWORD] + func.restypes = [DWORD] # type: ignore return func(handle, iface_guid, 2, None, network_list) def _wlan_get_network_bss_list(self, handle, iface_guid, bss_list, ssid = None, security = False): @@ -568,7 +608,7 @@ def _wlan_get_network_bss_list(self, handle, iface_guid, bss_list, ssid = None, func = native_wifi.WlanGetNetworkBssList func.argtypes = [HANDLE, POINTER(GUID), POINTER( DOT11_SSID), c_uint, c_bool, c_void_p, POINTER(POINTER(WLAN_BSS_LIST))] - func.restypes = [DWORD] + func.restypes = [DWORD] # type: ignore return func(handle, iface_guid, ssid, 1, security, None, bss_list) def _wlan_scan(self, handle, iface_guid): @@ -576,7 +616,7 @@ def _wlan_scan(self, handle, iface_guid): func = native_wifi.WlanScan func.argtypes = [HANDLE, POINTER(GUID), POINTER( DOT11_SSID), POINTER(WLAN_RAW_DATA), c_void_p] - func.restypes = [DWORD] + func.restypes = [DWORD] # type: ignore return func(handle, iface_guid, None, None, None) def _wlan_connect(self, handle, iface_guid, params): @@ -584,7 +624,7 @@ def _wlan_connect(self, handle, iface_guid, params): func = native_wifi.WlanConnect func.argtypes = [HANDLE, POINTER(GUID), POINTER( WLAN_CONNECTION_PARAMETERS), c_void_p] - func.restypes = [DWORD] + func.restypes = [DWORD] # type: ignore return func(handle, iface_guid, params, None) def _wlan_set_profile(self, handle, iface_guid, xml, overwrite, reason_code): @@ -592,14 +632,14 @@ def _wlan_set_profile(self, handle, iface_guid, xml, overwrite, reason_code): func = native_wifi.WlanSetProfile func.argtypes = [HANDLE, POINTER( GUID), DWORD, c_wchar_p, c_wchar_p, c_bool, c_void_p, POINTER(DWORD)] - func.restypes = [DWORD] + func.restypes = [DWORD] # type: ignore return func(handle, iface_guid, 2, xml, None, overwrite, None, reason_code) def _wlan_reason_code_to_str(self, reason_code, buf_size, buf): func = native_wifi.WlanReasonCodeToString func.argtypes = [DWORD, DWORD, PWCHAR, c_void_p] - func.restypes = [DWORD] + func.restypes = [DWORD] # type: ignore return func(reason_code, buf_size, buf, None) def _wlan_get_profile_list(self, handle, iface_guid, profile_list): @@ -607,7 +647,7 @@ def _wlan_get_profile_list(self, handle, iface_guid, profile_list): func = native_wifi.WlanGetProfileList func.argtypes = [HANDLE, POINTER(GUID), c_void_p, POINTER( POINTER(WLAN_PROFILE_INFO_LIST))] - func.restypes = [DWORD] + func.restypes = [DWORD] # type: ignore return func(handle, iface_guid, None, profile_list) def _wlan_get_profile(self, handle, iface_guid, profile_name, xml, flags, access): @@ -615,14 +655,14 @@ def _wlan_get_profile(self, handle, iface_guid, profile_name, xml, flags, access func = native_wifi.WlanGetProfile func.argtypes = [HANDLE, POINTER(GUID), c_wchar_p, c_void_p, POINTER( c_wchar_p), POINTER(DWORD), POINTER(DWORD)] - func.restypes = [DWORD] + func.restypes = [DWORD] # type: ignore return func(handle, iface_guid, profile_name, None, xml, flags, access) def _wlan_delete_profile(self, handle, iface_guid, profile_name): func = native_wifi.WlanDeleteProfile func.argtypes = [HANDLE, POINTER(GUID), c_wchar_p, c_void_p] - func.restypes = [DWORD] + func.restypes = [DWORD] # type: ignore return func(handle, iface_guid, profile_name, None) def _wlan_query_interface(self, handle, iface_guid, opcode, data_size, data, opcode_value_type): @@ -630,32 +670,30 @@ def _wlan_query_interface(self, handle, iface_guid, opcode, data_size, data, opc func = native_wifi.WlanQueryInterface func.argtypes = [HANDLE, POINTER(GUID), DWORD, c_void_p, POINTER( DWORD), POINTER(POINTER(DWORD)), POINTER(DWORD)] - func.restypes = [DWORD] + func.restypes = [DWORD] # type: ignore return func(handle, iface_guid, opcode, None, data_size, data, opcode_value_type) def _wlan_disconnect(self, handle, iface_guid): func = native_wifi.WlanDisconnect func.argtypes = [HANDLE, POINTER(GUID), c_void_p] - func.restypes = [DWORD] + func.restypes = [DWORD] # type: ignore return func(handle, iface_guid, None) def _get_auth_alg(self, auth_val): - - auth_alg = [] + + auth_alg = AUTH_ALG_OPEN if auth_val in [1, 3, 4, 6, 7]: - auth_alg.append(AUTH_ALG_OPEN) + auth_alg = AUTH_ALG_OPEN elif auth_val == 2: - auth_alg.append(AUTH_ALG_SHARED) + auth_alg = AUTH_ALG_SHARED return auth_alg def _get_akm(self, akm_val): - akm = [] - if akm_val == 2: - akm.append(AKM_TYPE_WPAPSK) - elif akm_val == 4: - akm.append(AKM_TYPE_WPA2PSK) - + akm = AKM_TYPE_OPEN + if akm_val in akm_value_to_str_dict: + akm = akm_value_to_str_dict[akm_val] + return akm diff --git a/pywifi/const.py b/pywifi/const.py index 66b73dc..e2ac564 100755 --- a/pywifi/const.py +++ b/pywifi/const.py @@ -11,23 +11,29 @@ IFACE_CONNECTED = 4 # Define auth algorithms. -AUTH_ALG_OPEN = 0 -AUTH_ALG_SHARED = 1 +AUTH_ALG_OPEN = 1 +AUTH_ALG_SHARED = 2 # Define auth key mgmt types. AKM_TYPE_NONE = 0 -AKM_TYPE_WPA = 1 -AKM_TYPE_WPAPSK = 2 -AKM_TYPE_WPA2 = 3 -AKM_TYPE_WPA2PSK = 4 -AKM_TYPE_UNKNOWN = 5 +AKM_TYPE_OPEN = 1 +AKM_TYPE_SHARED = 2 +AKM_TYPE_WPA = 3 +AKM_TYPE_WPAPSK = 4 +AKM_TYPE_WPANONE = 5 +AKM_TYPE_WPA2 = 6 +AKM_TYPE_WPA2PSK = 7 +AKM_TYPE_WPA3 = 8 +AKM_TYPE_WPA3SAE = 9 +AKM_TYPE_OWE = 10 +AKM_TYPE_WPA3ENT = 11 # Define ciphers. CIPHER_TYPE_NONE = 0 CIPHER_TYPE_WEP = 1 CIPHER_TYPE_TKIP = 2 -CIPHER_TYPE_CCMP = 3 -CIPHER_TYPE_UNKNOWN = 4 +CIPHER_TYPE_CCMP = 4 +CIPHER_TYPE_UNKNOWN = 5 KEY_TYPE_NETWORKKEY = 0 KEY_TYPE_PASSPHRASE = 1 diff --git a/pywifi/profile.py b/pywifi/profile.py index 85959e9..9240a69 100755 --- a/pywifi/profile.py +++ b/pywifi/profile.py @@ -12,16 +12,16 @@ def __init__(self): self.id = 0 self.auth = AUTH_ALG_OPEN - self.akm = [AKM_TYPE_NONE] + self.akm = AKM_TYPE_NONE self.cipher = CIPHER_TYPE_NONE self.ssid = None self.bssid = None self.key = None - def process_akm(self): + # def process_akm(self): - if len(self.akm) > 1: - self.akm = self.akm[-1:] + # if len(self.akm) > 1: + # self.akm = self.akm[-1:] def __eq__(self, profile): @@ -42,7 +42,11 @@ def __eq__(self, profile): return False if profile.akm: - if set(profile.akm).isdisjoint(set(self.akm)): + if profile.akm != self.akm: return False + + # if profile.akm: + # if set(profile.akm).isdisjoint(set(self.akm)): + # return False return True diff --git a/setup.py b/setup.py index 3f6d2a0..9a504a6 100755 --- a/setup.py +++ b/setup.py @@ -30,7 +30,7 @@ setup( name='pywifi', - version='1.1.12', + version='1.1.13', author='Jiang Sheng-Jhih', author_email='shengjhih@gmail.com', description="A cross-platform module for manipulating WiFi devices.", From c9ef8d67a9ea000a61f1be97beedeb976ab02767 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E6=81=92aead?= Date: Fri, 6 Sep 2024 11:54:10 +0800 Subject: [PATCH 3/3] =?UTF-8?q?[=E6=96=B0=E5=A2=9E]=20=E6=94=AF=E6=8C=81WP?= =?UTF-8?q?A3=E5=AE=89=E5=85=A8=E7=B1=BB=E5=9E=8B=EF=BC=88linux=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pywifi/_wifiutil_linux.py | 131 ++++++++++++++++++++++++++++++-------- 1 file changed, 104 insertions(+), 27 deletions(-) diff --git a/pywifi/_wifiutil_linux.py b/pywifi/_wifiutil_linux.py index b8b84bc..43bacde 100755 --- a/pywifi/_wifiutil_linux.py +++ b/pywifi/_wifiutil_linux.py @@ -7,6 +7,7 @@ import socket import stat import os +import re from .const import * from .profile import Profile @@ -32,19 +33,36 @@ AKM_TYPE_WPA: 'WPA-EAP', AKM_TYPE_WPAPSK: 'WPA-PSK', AKM_TYPE_WPA2: 'WPA-EAP', - AKM_TYPE_WPA2PSK: 'WPA-PSK' + AKM_TYPE_WPA2PSK: 'WPA-PSK', + AKM_TYPE_WPA3: 'WPA-EAP-SHA256', + AKM_TYPE_WPA3SAE: 'SAE', + AKM_TYPE_WPA3ENT: 'WPA-EAP-SHA256', } key_mgmt_to_proto_str = { AKM_TYPE_WPA: 'WPA', AKM_TYPE_WPAPSK: 'WPA', AKM_TYPE_WPA2: 'RSN', - AKM_TYPE_WPA2PSK: 'RSN' + AKM_TYPE_WPA2PSK: 'RSN', + AKM_TYPE_WPA3: 'WPA3', + AKM_TYPE_WPA3SAE: 'RSN', + AKM_TYPE_WPA3ENT: 'WPA3', +} + +display_str_to_key = { + 'open': AKM_TYPE_OPEN, + 'WPA': AKM_TYPE_WPA, + 'WPAPSK': AKM_TYPE_WPAPSK, + 'WPA2': AKM_TYPE_WPA2, + 'WPA2PSK': AKM_TYPE_WPA2PSK, + 'WPA3': AKM_TYPE_WPA3, + 'WPA3SAE': AKM_TYPE_WPA3SAE, + 'WPA3ENT': AKM_TYPE_WPA3ENT, } proto_to_key_mgmt_id = { 'WPA': AKM_TYPE_WPAPSK, - 'RSN': AKM_TYPE_WPA2PSK + 'RSN': AKM_TYPE_WPA2PSK, } cipher_str_to_value = { @@ -78,16 +96,57 @@ def scan_results(self, obj): bss.bssid = values[0] bss.freq = int(values[1]) bss.signal = int(values[2]) - bss.ssid = values[4] - bss.akm = [] + + # 定义一个正则表达式来匹配ssid转义序列 + pattern = r'\\x([0-9a-fA-F]{2}|[0-9a-fA-F]{4})' + # 使用lambda表达式来替换匹配到的ssid转义序列 + ssid = re.sub(pattern, lambda m: chr(int(m.group(1), 16)), values[4]) + + # * 该部分用于将SSID转换为UTF-8编码,可正常显示中文字符 p.s.由 PR #31 提供 + temp_cnt = 0 + temp_hex_res = 0 + bytes_list = [] + converted_name = "" + for bin_encode_char in ssid: + if (32 <= ord(bin_encode_char) <= 126): + converted_name += bin_encode_char + else: + temp_cnt += 1 + temp_now = int(str(bin(ord(bin_encode_char)))[2:6], 2) + temp_now1 = int(str(bin(ord(bin_encode_char)))[6:10], 2) + temp_hex_res = temp_hex_res + temp_now * 16 + temp_now1 + bytes_list.append(temp_hex_res) + temp_hex_res = 0 + # 收集到完整的UTF-8字符时(最多四个字节) + if temp_cnt >= 1 and temp_cnt <= 4: + try: + converted_name = converted_name + bytes(bytes_list).decode('utf-8') + bytes_list = [] + temp_hex_res = 0 + temp_cnt = 0 + except UnicodeDecodeError: + # 如果解码失败,忽略错误并继续处理下一个字符 + pass + # 处理末尾可能剩下的未完成的字节序列 + if bytes_list: + try: + decoded_chars = bytes(bytes_list).decode('utf-8', 'ignore') + converted_name += decoded_chars + except UnicodeDecodeError: + pass + bss.ssid = converted_name + + bss.akm = 7 if 'WPA-PSK' in values[3]: - bss.akm.append(AKM_TYPE_WPAPSK) - if 'WPA2-PSK' in values[3]: - bss.akm.append(AKM_TYPE_WPA2PSK) - if 'WPA-EAP' in values[3]: - bss.akm.append(AKM_TYPE_WPA) - if 'WPA2-EAP' in values[3]: - bss.akm.append(AKM_TYPE_WPA2) + bss.akm = AKM_TYPE_WPAPSK + elif 'WPA2-PSK' in values[3]: + bss.akm = AKM_TYPE_WPA2PSK + elif 'WPA2-SAE' in values[3]: + bss.akm = AKM_TYPE_WPA3SAE + elif 'WPA-EAP' in values[3]: + bss.akm = AKM_TYPE_WPA + elif 'WPA2-EAP' in values[3]: + bss.akm = AKM_TYPE_WPA2 bss.auth = AUTH_ALG_OPEN @@ -125,17 +184,21 @@ def add_network_profile(self, obj, params): network_id = self._send_cmd_to_wpas(obj['name'], 'ADD_NETWORK', True) network_id = network_id.strip() - params.process_akm() + # params.process_akm() self._send_cmd_to_wpas( obj['name'], 'SET_NETWORK {} ssid \"{}\"'.format(network_id, params.ssid)) key_mgmt = '' - if params.akm[-1] in [AKM_TYPE_WPAPSK, AKM_TYPE_WPA2PSK]: - key_mgmt = 'WPA-PSK' - elif params.akm[-1] in [AKM_TYPE_WPA, AKM_TYPE_WPA2]: - key_mgmt = 'WPA-EAP' + # if params.akm in [AKM_TYPE_WPAPSK, AKM_TYPE_WPA2PSK]: + # key_mgmt = 'WPA-PSK' + # elif params.akm in [AKM_TYPE_WPA, AKM_TYPE_WPA2]: + # key_mgmt = 'WPA-EAP' + # else: + # key_mgmt = 'NONE' + if params.akm in key_mgmt_to_str: + key_mgmt = key_mgmt_to_str[params.akm] else: key_mgmt = 'NONE' @@ -147,9 +210,13 @@ def add_network_profile(self, obj, params): key_mgmt)) proto = '' - if params.akm[-1] in [AKM_TYPE_WPAPSK, AKM_TYPE_WPA]: - proto = 'WPA' - elif params.akm[-1] in [AKM_TYPE_WPA2PSK, AKM_TYPE_WPA2]: + # if params.akm in [AKM_TYPE_WPAPSK, AKM_TYPE_WPA]: + # proto = 'WPA' + # elif params.akm in [AKM_TYPE_WPA2PSK, AKM_TYPE_WPA2]: + # proto = 'RSN' + if params.akm in key_mgmt_to_proto_str: + proto = key_mgmt_to_proto_str[params.akm] + else: proto = 'RSN' if proto: @@ -159,7 +226,7 @@ def add_network_profile(self, obj, params): network_id, proto)) - if params.akm[-1] in [AKM_TYPE_WPAPSK, AKM_TYPE_WPA2PSK]: + if params.akm in key_mgmt_to_str: self._send_cmd_to_wpas( obj['name'], 'SET_NETWORK {} psk \"{}\"'.format(network_id, params.key)) @@ -204,26 +271,36 @@ def network_profiles(self, obj): if key_mgmt.upper().startswith('FAIL'): continue else: - if key_mgmt.upper() in ['WPA-PSK']: + if key_mgmt.upper() == 'WPA-PSK': + proto = self._send_cmd_to_wpas( + obj['name'], + 'GET_NETWORK {} proto'.format(network_id), + True) + + if proto.upper() == 'RSN': + network.akm = AKM_TYPE_WPA2PSK + else: + network.akm = AKM_TYPE_WPAPSK + elif key_mgmt.upper() == 'SAE' or key_mgmt.upper() == "WPA-EAP-SHA256": proto = self._send_cmd_to_wpas( obj['name'], 'GET_NETWORK {} proto'.format(network_id), True) if proto.upper() == 'RSN': - network.akm.append(AKM_TYPE_WPA2PSK) + network.akm = AKM_TYPE_WPA3SAE else: - network.akm.append(AKM_TYPE_WPAPSK) - elif key_mgmt.upper() in ['WPA-EAP']: + network.akm = AKM_TYPE_WPA3 + elif key_mgmt.upper() == 'WPA-EAP': proto = self._send_cmd_to_wpas( obj['name'], 'GET_NETWORK {} proto'.format(network_id), True) if proto.upper() == 'RSN': - network.akm.append(AKM_TYPE_WPA2) + network.akm = AKM_TYPE_WPA2 else: - network.akm.append(AKM_TYPE_WPA) + network.akm = AKM_TYPE_WPA ciphers = self._send_cmd_to_wpas( obj['name'],