文章参考的是Android 7.1的源码
本文主要研究EAP类型网络的身份验证过程,从而简化Android平台EAP类型网络的身份验证过程。
上篇文章Wi-Fi EAP网络验证过程与Android平台拓展实例(一)已经分析出IOS和Android平台在EAP类型网络认证上的差异,即提供给认证服务器的EAP方法不同。那么这篇文章就通过分析Android源码来大概了解下整个认证过程。
1. wpa_supplicant.conf
在看源码之前,我们先看看Android中AP配置信息的保存。在Android7.1及其以下的版本中,AP的基本配置信息,如身份,密码,加密类型等,都保存在data/misc/wifi/wpa_supplicant.conf
这个文件中,那么我们来看看连接TPLINK-TTLS(加密方式EAP-TTLS)的情况下,该AP的保存信息:
unknown:/ # cat data/misc/wifi/wpa_supplicant.conf
...
network={
ssid="TPLINK-TTLS"
key_mgmt=WPA-EAP IEEE8021X
eap=PEAP
identity="ulangch"
password="12345678"
phase2=""
priority=3
proactive_key_caching=1
disabled=1
id_str="%7B%22creatorUid%22%3A%221000%22%2C%22configKey%22%3A%22%5C%22TPLINK-TTLS%5C%22-WPA_EAP%22%7D"
}
如上所示,在我们选择了PEAP方法时,wpa_supplicant.conf
中保存了"eap=PEAP"
的信息,如果我们把该文件pull出来修改成"eap=TTLS"
push回去再重启Wi-Fi连接该AP,则也可以正常连上。
2. EAP网络-Framework
我们先看看EAP网络信息在framework中的保存过程是什么样的,如果大家对framework中AP的保存过程非常熟悉,建议跳过该节内容,直接查看wpa_supplicant中的部分。
WifiStateMachine在收到WifiService传递过来的SAVE_NETWORK
消息后,调用WifiConfigManager进行了保存操作:
/** WifiStateMachine.java*/
case WifiManager.SAVE_NETWORK:
case WifiStateMachine.CMD_AUTO_SAVE_NETWORK:
...
// 调用WifiConfigManager.saveNetwork来保存WifiConfiguration
result = mWifiConfigManager.saveNetwork(config, WifiConfiguration.UNKNOWN_UID);
...
WifiConfigManager开始进行保存和更新,经过一系列的检查,最终会使用WifiConfigStore来保存
/** WifiConfigManager.java*/
NetworkUpdateResult saveNetwork(WifiConfiguration config, int uid) {
...
NetworkUpdateResult result = addOrUpdateNetworkNative(config, uid);
}
/** WifiConfigManager.java*/
private NetworkUpdateResult addOrUpdateNetworkNative(WifiConfiguration config, int uid) {
...
if (!mWifiConfigStore.addOrUpdateNetwork(config, currentConfig)) {
return new NetworkUpdateResult(INVALID_NETWORK_ID);
}
}
WifiConfigStore在经过检查和保存AP的基本信息后,对于EAP相关的配置信息,如身份,密码,CA证书等会通过WifiEnterpriseConfig中提供的接口进行保存:
/**WifiConfigStore.java*/
public boolean addOrUpdateNetwork(WifiConfiguration config, WifiConfiguration existingConfig) {
...
if (!saveNetwork(config, netId)) {
if (newNetwork) {
mWifiNative.removeNetwork(netId);
loge("Failed to set a network variable, removed network: " + netId);
}
return false;
}
if (config.enterpriseConfig != null
&& config.enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE) {
return updateNetworkKeys(config, existingConfig);
}
}
/** WifiConfigStore.java*/
private boolean updateNetworkKeys(WifiConfiguration config, WifiConfiguration existingConfig) {
...
// WifiConfigStore#SupplicantSaver继承自WifiEnterpriseConfig#SupplicantSaver,
// 因此最终还是会回到WifiConfigStore中进行保存操作
if (!enterpriseConfig.saveToSupplicant(
new SupplicantSaver(config.networkId, config.SSID))) {
removeKeys(enterpriseConfig);
return false;
}