Wlan学习—wpa_supplicant

WPAS几个重要的命令:

·ADD_NETWORK:为WPAS添加一个新的无线网络。它将返回此新无线网络的ID(从0开始)。注意,此network id非常重要,客户端后续将通过它来指明自己想操作的无线网络。
·SET_NETWORK<network id><variable><value>:network id是无线网络的ID。此命令用于设置指定无线网络的信息。其中variable为参数名,value为参数的值。
·ENABLE_NETWORK<network id>:使能某个无线网络。此命令最终将促使WPAS发起一系列操作以加入该无线网络。


Android平台中WifiService是WPAS的客户端,它和WPAS交互时必须使用wpa_supplicant
提供的API。这些API声明于wpa_ctrl.h中

Wlan学习—wpa_supplicant
                                           wpa_supplicant.conf文件内容

1.wpa_ssid结构体
wpa_ssid用于存储某个无线网络的配置信息(如所支持的安全类型、优先级等)。它其
实是图4-6所示wpa_supplicant.conf中无线网络配置项在代码中的反映(conf文件中每一个
network项都对应一个wpa_ssid对象)。它的一些主要数据成员如下图所示
Wlan学习—wpa_supplicant
一些数据成员非常重要,下面分别介绍它们。
(1)安全相关成员变量及背景知识和安全相关的成员变量如下所示。
1)passphrase:该变量只和WPA/WPA2-PSK模式有关,用于存储我们输入的字符串密
码。而实际上,规范要求使用的却是图4-10中的psk变量。结合3.3.7节中关于key和password
的介绍可知,用户一般只设置字符串形式的password。而WPAS将根据它和ssid进行一定的计
算以得到最终使用的PSK。参考资料[3]中有PSK计算方法。

2)pairwise_cipher和group_cipher:这两个变量和规范中的cipher suite(加密套件)定义
有关。cipher suite用于指明数据收发两方使用的数据加密方法。pairwise_cipher和
group_cipher分别代表为该无线网络设置的单播和组播数据加密方法。。WPAS中的定义如下。
// 位于defs.h中
#define WPA_CIPHER_NONE BIT(0) // 不保护。BIT(N)是一个宏,代表1左移N位后的值
#define WPA_CIPHER_WEP40 BIT(1) // WEP40(即5个ASCII字符密码)
#define WPA_CIPHER_WEP104 BIT(2) // WEP104(即13个ASCII字符密码)
#define WPA_CIPHER_TKIP BIT(3) // TKIP
#define WPA_CIPHER_CCMP BIT(4) // CCMP
// 系统还定义了两个宏用于表示默认支持的加密套件类型:(位于config_ssid.h中)
#define DEFAULT_PAIRWISE (WPA_CIPHER_CCMP | WPA_CIPHER_TKIP)
#define DEFAULT_GROUP (WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | \
WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40)

3)key_mgmt:该成员和802.11中的AKM suite相关。AKM(Authentication and Key
Managment,身份验证和**管理)suite定义了一套算法用于在Supplicant和Authenticator之间
交换身份和密匙信息。WPAS中定义的key_mgmt可取值如下。
// 位于defs.h中
#define WPA_KEY_MGMT_IEEE8021X BIT(0) // 不同的AKM suite有对应的流程与算法。不详细介绍
#define WPA_KEY_MGMT_PSK BIT(1)
#define WPA_KEY_MGMT_NONE BIT(2)
#define WPA_KEY_MGMT_IEEE8021X_NO_WPA BIT(3)
#define WPA_KEY_MGMT_WPA_NONE BIT(4)
#define WPA_KEY_MGMT_FT_IEEE8021X BIT(5) // FT(Fast Transition)用于ESS中快速切换BSS
#define WPA_KEY_MGMT_FT_PSK BIT(6)
#define WPA_KEY_MGMT_IEEE8021X_SHA256 BIT(7) // SHA256表示key派生时使用SHA256做算法
#define WPA_KEY_MGMT_PSK_SHA256 BIT(8)
#define WPA_KEY_MGMT_WPS BIT(9)
// 位于config_ssid.h中
#define DEFAULT_KEY_MGMT (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X)
// 默认的AKM suite

4)proto:代表该无线网络支持的安全协议类型。其可取值如下。
// 位于defs.h中
#define WPA_PROTO_WPA BIT(0)
#define WPA_PROTO_RSN BIT(1) // RSN其实就是WPA2
// 位于config_ssid.h中
#define DEFAULT_PROTO (WPA_PROTO_WPA | WPA_PROTO_RSN) // 默认支持两种协议

5)auth_alg:表示该无线网络所支持的身份验证算法,其可取值如下。
// 位于defs.h中
#define WPA_AUTH_ALG_OPEN BIT(0) // Open System,如果要使用WPA或RSN,必须选择它
#define WPA_AUTH_ALG_SHARED BIT(1) // Shared Key算法
#define WPA_AUTH_ALG_LEAP BIT(2) // LEAP算法,LEAP是思科公司提出的身份验证方法
#define WPA_AUTH_ALG_FT BIT(3) // 和FT有关

6)eapol_flags:和动态WEP Key有关,其取值包括如下。
// 位于config_ssid.h中
#define EAPOL_FLAG_REQUIRE_KEY_UNICAST BIT(0)
#define EAPOL_FLAG_REQUIRE_KEY_BROADCAST BIT(1)
7)disable:该变量取值为0(代表该无线网络可用)、1(代表该无线网络被禁止使用,但可通过命令来启用它)、2(表示该无线网络和P2P有关)。

从auth_alg参数注释可以看出,WPA和WPA2(RSN)属于Open System认证方式,而不是Shared Key算法方式,虽然RSNA过程需要用到PSK(pre shared key),但是psk应该不是用在anthentication过程的,而是用于RSNA过程,psk是PMK(主**)的来源。所以在调用Wifimanager#connect(config, listener)时,无论psk是否正确,总是回调回调Listener的onSuccess(),原因应该正在于此。只是一开始那个anthentication过程并没有使用psk。真正起到身份验证的作用的是最后的RSNA过程。
从proto的注释可以看出,WPA和WPA2(RSN)的安全协议是不一样的。安全协议与加密方式是不一样的,因为pairwise_cipher和group_cipher参数就是定义单播和组播的加密方式的。


wpa_supplicant结构体

Wlan学习—wpa_supplicant
此处先解释几个比较简单的成员变量。
·drv_priv和global_drv_priv:WPAS为driver wrapper一共定义了两个上下文信息。这是因为driver i/f接口定义了两个初始化函数(以nl80211 driver为例,它们分别是global_init和init2)。其中,global_init返回值为driver wrapper全局上下文信息,它将保存在wpa_global的drv_priv数组中(见图4-7)。每个wpa_supplicant都对应有一个driver wrapper对象,故它也需要保存对应的全局上下文信息。init2返回值则是driver wrapper上下文信息,它保存在wpa_supplicant的driv_priv中。
·current_bss:该变量类型为wpa_bss。wpa_bss是无线网络在wpa_supplicant中的代表。wpa_bss中的成员主要描述了无线网络的bssid、ssid、频率(freq,以MHz为单位)、Beacon心跳时间(以TU为单位)、capability信息(网络性能,见3.3.5节定长字段介绍)、信号强度等。wpa_bss的作用很重要,不过其数据结构相对比较简单,此处不介绍。以后用到它时再来介绍。

wpa_supplicant也定义了一些和安全相关的成员变量。
·pairwise_cipher、group_cipher、key_mgmt、wpa_proto、mgmt_group_cipher:这几个变量表示该wpa_supplicant最终选择的安全策略。其中mgmt_group_cipher和IEEE 802.11w(定义了管理帧加密的规范)有关。为节约篇幅,图4-11中仅列出pairwise_cipher一个变量。
·countermeasures:该变量名可译为“策略”,和TKIP的MIC(Message Integrity Check,消息完整性校验)有关。因为TKIP MIC所使用的Michael算法在某些情况下容易被攻破,所以规范特别定义了TKIP MIC countermeasures用于处理这类事情。例如,一旦检测到60秒内发生两次以上MIC错误,则停止TKIP通信60秒。


过命令行发送命令的方式触发wpa_supplicant进行相关工作,使手机加入一个利用WPA-PSK进行认证的无线网络

adb root #获取手机root用户权限。只有root被**的手机才能成功
adb shell #登录手机shell
#笔者事先已编译wpa_cli并将其放到/system/bin目录中。这个命令用于启动wpa_cli,-i参数指明unix域控制
#socket文件名,它应该和wpa_supplicant启动时设置的控制接口文件名一致
wpa_cli -iwlan0 #该命令执行后,将进入wpa_cli进程,后续操作都在此进程中开展
#发送ADD_NETWORK命令给wpa_supplicant,它将返回一个新网络配置项的编号
#请参考4.3.3节wpas_ssid结构体介绍
ADD_NETWORK #假设wpa_supplicant返回的新网络配置项编号为0
SET_NETWORK 0 ssid "Test" #设置0号网络的ssid为"Test"
SET_NETWORK 0 key_mgmt WPA-PSK #设置0号网络的key_mgmt为"WPA-PSK"
SET_NETWORK 0 psk "12345Test" #设置0号网络的psk为"12345Test"
ENABLE_NETWORK 0 #使能0号网络,它将触发wpa_supplicant扫描、关联等一系列操作直到加入无线网络"Test"
CTRL+C #退出wpa_cli
dhcpcd wlan0 #启动dhcpd,wlan0为无线接口设备名。dhcpcd可为手机从AP那获取一个IP




隐藏SSID的扫描:
有一些AP被设置为hidden ssid。即它不响应wildcard ssid扫描的Probe Request,同时,自己发送的Beacon帧也不携带ssid信息。这样,只有知道ssid的STA才能和这些AP连接上,其安全性略有提高。scan_ssid就是用来判断此无线网络是否需要指明ssid。本例中的"Test"无线网络没有隐藏 ssid,所以scan_ssid值为0。否则需要通过SET_NETWORK 0 scan_ssid 1来设置它。

扫描时指定目标无线网络的工作信道:

处理扫描时的频率选择。如果已经知道目标无线网络的工作信道,可以直接设定频率参数以
优化扫描过程。否则,无线网卡将尝试在各个信道上搜索目标无线网络。本例没有使用频率参数。

关联无线网络(Association)

和scan请求类似,关联无线网络处理流程主要是为了填充一个wpa_driver_associate_params类型的对象。不过该对象中各个参数的设置颇有来头,需要对802.11规范有相当了解才可以做到正确无误,WPAS就把wpa_driver_associate_params类型的对象随CONNECT请求发给了驱动,驱动将完成Authentication帧和Association Request帧的处理