📄 wpa_supplicant.c
字号:
sel = 0;
if (sel & WPA_CIPHER_AES_128_CMAC) {
wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
wpa_msg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
"AES-128-CMAC");
} else {
wpa_s->mgmt_group_cipher = 0;
wpa_msg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
}
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
wpa_s->mgmt_group_cipher);
#endif /* CONFIG_IEEE80211W */
if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
wpa_printf(MSG_WARNING, "WPA: Failed to generate WPA IE.");
return -1;
}
if (ssid->key_mgmt & WPA_KEY_MGMT_PSK)
wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN);
else
wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
return 0;
}
/**
* wpa_supplicant_associate - Request association
* @wpa_s: Pointer to wpa_supplicant data
* @bss: Scan results for the selected BSS, or %NULL if not available
* @ssid: Configuration data for the selected network
*
* This function is used to request %wpa_supplicant to associate with a BSS.
*/
void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
struct wpa_scan_result *bss,
struct wpa_ssid *ssid)
{
u8 wpa_ie[80];
size_t wpa_ie_len;
int use_crypt, ret, i;
int algs = AUTH_ALG_OPEN_SYSTEM;
wpa_cipher cipher_pairwise, cipher_group;
struct wpa_driver_associate_params params;
int wep_keys_set = 0;
struct wpa_driver_capa capa;
int assoc_failed = 0;
wpa_s->reassociate = 0;
if (bss) {
wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
" (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
os_memset(wpa_s->bssid, 0, ETH_ALEN);
os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
} else {
wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
}
wpa_supplicant_cancel_scan(wpa_s);
/* Starting new association, so clear the possibly used WPA IE from the
* previous association. */
wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
#ifdef IEEE8021X_EAPOL
if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
if (ssid->leap) {
if (ssid->non_leap == 0)
algs = AUTH_ALG_LEAP;
else
algs |= AUTH_ALG_LEAP;
}
}
#endif /* IEEE8021X_EAPOL */
wpa_printf(MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
if (ssid->auth_alg) {
algs = 0;
if (ssid->auth_alg & WPA_AUTH_ALG_OPEN)
algs |= AUTH_ALG_OPEN_SYSTEM;
if (ssid->auth_alg & WPA_AUTH_ALG_SHARED)
algs |= AUTH_ALG_SHARED_KEY;
if (ssid->auth_alg & WPA_AUTH_ALG_LEAP)
algs |= AUTH_ALG_LEAP;
wpa_printf(MSG_DEBUG, "Overriding auth_alg selection: 0x%x",
algs);
}
wpa_drv_set_auth_alg(wpa_s, algs);
if (bss && (bss->wpa_ie_len || bss->rsn_ie_len) &&
(ssid->key_mgmt & (WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_PSK))) {
int try_opportunistic;
try_opportunistic = ssid->proactive_key_caching &&
(ssid->proto & WPA_PROTO_RSN);
if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
wpa_s->current_ssid,
try_opportunistic) == 0)
eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1);
wpa_ie_len = sizeof(wpa_ie);
if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
wpa_ie, &wpa_ie_len)) {
wpa_printf(MSG_WARNING, "WPA: Failed to set WPA key "
"management and encryption suites");
return;
}
} else if (ssid->key_mgmt &
(WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X |
WPA_KEY_MGMT_WPA_NONE)) {
wpa_ie_len = sizeof(wpa_ie);
if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
wpa_ie, &wpa_ie_len)) {
wpa_printf(MSG_WARNING, "WPA: Failed to set WPA key "
"management and encryption suites (no scan "
"results)");
return;
}
} else {
wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
wpa_ie_len = 0;
}
wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
use_crypt = 1;
cipher_pairwise = cipher_suite2driver(wpa_s->pairwise_cipher);
cipher_group = cipher_suite2driver(wpa_s->group_cipher);
if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
use_crypt = 0;
for (i = 0; i < NUM_WEP_KEYS; i++) {
if (ssid->wep_key_len[i]) {
use_crypt = 1;
wep_keys_set = 1;
wpa_set_wep_key(wpa_s,
i == ssid->wep_tx_keyidx,
i, ssid->wep_key[i],
ssid->wep_key_len[i]);
}
}
}
#ifdef IEEE8021X_EAPOL
if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
if ((ssid->eapol_flags &
(EAPOL_FLAG_REQUIRE_KEY_UNICAST |
EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
!wep_keys_set) {
use_crypt = 0;
} else {
/* Assume that dynamic WEP-104 keys will be used and
* set cipher suites in order for drivers to expect
* encryption. */
cipher_pairwise = cipher_group = CIPHER_WEP104;
}
}
#endif /* IEEE8021X_EAPOL */
if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
/* Set the key before (and later after) association */
wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
}
wpa_drv_set_drop_unencrypted(wpa_s, use_crypt);
wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
os_memset(¶ms, 0, sizeof(params));
if (bss) {
params.bssid = bss->bssid;
params.ssid = bss->ssid;
params.ssid_len = bss->ssid_len;
params.freq = bss->freq;
} else {
params.ssid = ssid->ssid;
params.ssid_len = ssid->ssid_len;
}
params.wpa_ie = wpa_ie;
params.wpa_ie_len = wpa_ie_len;
params.pairwise_suite = cipher_pairwise;
params.group_suite = cipher_group;
params.key_mgmt_suite = key_mgmt2driver(wpa_s->key_mgmt);
params.auth_alg = algs;
params.mode = ssid->mode;
for (i = 0; i < NUM_WEP_KEYS; i++) {
if (ssid->wep_key_len[i])
params.wep_key[i] = ssid->wep_key[i];
params.wep_key_len[i] = ssid->wep_key_len[i];
}
params.wep_tx_keyidx = ssid->wep_tx_keyidx;
#ifdef CONFIG_IEEE80211W
switch (ssid->ieee80211w) {
case NO_IEEE80211W:
params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
break;
case IEEE80211W_OPTIONAL:
params.mgmt_frame_protection = MGMT_FRAME_PROTECTION_OPTIONAL;
break;
case IEEE80211W_REQUIRED:
params.mgmt_frame_protection = MGMT_FRAME_PROTECTION_REQUIRED;
break;
}
#endif /* CONFIG_IEEE80211W */
if (wpa_s->use_client_mlme)
ret = ieee80211_sta_associate(wpa_s, ¶ms);
else
ret = wpa_drv_associate(wpa_s, ¶ms);
if (ret < 0) {
wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
"failed");
/* try to continue anyway; new association will be tried again
* after timeout */
assoc_failed = 1;
}
if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
/* Set the key after the association just in case association
* cleared the previously configured key. */
wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
/* No need to timeout authentication since there is no key
* management. */
wpa_supplicant_cancel_auth_timeout(wpa_s);
wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
} else {
/* Timeout for IEEE 802.11 authentication and association */
int timeout;
if (assoc_failed)
timeout = 5;
else if (wpa_s->conf->ap_scan == 1)
timeout = 10;
else
timeout = 60;
wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
}
if (wep_keys_set && wpa_drv_get_capa(wpa_s, &capa) == 0 &&
capa.flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC) {
/* Set static WEP keys again */
int j;
for (j = 0; j < NUM_WEP_KEYS; j++) {
if (ssid->wep_key_len[j]) {
wpa_set_wep_key(wpa_s,
j == ssid->wep_tx_keyidx,
j, ssid->wep_key[j],
ssid->wep_key_len[j]);
}
}
}
if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
/*
* Do not allow EAP session resumption between different
* network configurations.
*/
eapol_sm_invalidate_cached_session(wpa_s->eapol);
}
wpa_s->current_ssid = ssid;
wpa_sm_set_config(wpa_s->wpa, wpa_s->current_ssid);
wpa_supplicant_initiate_eapol(wpa_s);
}
/**
* wpa_supplicant_disassociate - Disassociate the current connection
* @wpa_s: Pointer to wpa_supplicant data
* @reason_code: IEEE 802.11 reason code for the disassociate frame
*
* This function is used to request %wpa_supplicant to disassociate with the
* current AP.
*/
void wpa_supplicant_disassociate(struct wpa_supplicant *wpa_s,
int reason_code)
{
u8 *addr = NULL;
if (os_memcmp(wpa_s->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) != 0)
{
if (wpa_s->use_client_mlme)
ieee80211_sta_disassociate(wpa_s, reason_code);
else
wpa_drv_disassociate(wpa_s, wpa_s->bssid, reason_code);
addr = wpa_s->bssid;
}
wpa_clear_keys(wpa_s, addr);
wpa_supplicant_mark_disassoc(wpa_s);
wpa_s->current_ssid = NULL;
wpa_sm_set_config(wpa_s->wpa, NULL);
eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
}
/**
* wpa_supplicant_deauthenticate - Deauthenticate the current connection
* @wpa_s: Pointer to wpa_supplicant data
* @reason_code: IEEE 802.11 reason code for the deauthenticate frame
*
* This function is used to request %wpa_supplicant to disassociate with the
* current AP.
*/
void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
int reason_code)
{
u8 *addr = NULL;
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
if (os_memcmp(wpa_s->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) != 0)
{
if (wpa_s->use_client_mlme)
ieee80211_sta_deauthenticate(wpa_s, reason_code);
else
wpa_drv_deauthenticate(wpa_s, wpa_s->bssid,
reason_code);
addr = wpa_s->bssid;
}
wpa_clear_keys(wpa_s, addr);
wpa_s->current_ssid = NULL;
wpa_sm_set_config(wpa_s->wpa, NULL);
eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
}
/**
* wpa_supplicant_get_scan_results - Get scan results
* @wpa_s: Pointer to wpa_supplicant data
* Returns: 0 on success, -1 on failure
*
* This function is request the current scan results from the driver and stores
* a local copy of the results in wpa_s->scan_results.
*/
int wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s)
{
#define SCAN_AP_LIMIT 128
struct wpa_scan_result *results, *tmp;
int num;
results = os_malloc(SCAN_AP_LIMIT * sizeof(struct wpa_scan_result));
if (results == NULL) {
wpa_printf(MSG_WARNING, "Failed to allocate memory for scan "
"results");
return -1;
}
if (wpa_s->use_client_mlme) {
num = ieee80211_sta_get_scan_results(wpa_s, results,
SCAN_AP_LIMIT);
} else
num = wpa_drv_get_scan_results(wpa_s, results, SCAN_AP_LIMIT);
wpa_printf(MSG_DEBUG, "Scan results: %d", num);
if (num < 0) {
wpa_printf(MSG_DEBUG, "Failed to get scan results");
os_free(results);
return -1;
}
if (num > SCAN_AP_LIMIT) {
wpa_printf(MSG_INFO, "Not enough room for all APs (%d < %d)",
num, SCAN_AP_LIMIT);
num = SCAN_AP_LIMIT;
}
/* Free unneeded memory for unused scan result entries */
tmp = os_realloc(results, num * sizeof(struct wpa_scan_result));
if (tmp || num == 0) {
results = tmp;
}
os_free(wpa_s->scan_results);
wpa_s->scan_results = results;
wpa_s->num_scan_results = num;
return 0;
}
#ifndef CONFIG_NO_WPA
static int wpa_get_beacon_ie(struct wpa_supplicant *wpa_s)
{
int i, ret = 0;
struct wpa_scan_result *results, *curr = NULL;
results = wpa_s->scan_results;
if (results == NULL) {
return -1;
}
for (i = 0; i < wpa_s->num_scan_results; i++) {
struct wpa_ssid *ssid = wpa_s->current_ssid;
if (os_memcmp(results[i].bssid, wpa_s->bssid, ETH_ALEN) != 0)
continue;
if (ssid == NULL ||
((results[i].ssid_len == ssid->ssid_len &&
os_memcmp(results[i].ssid, ssid->ssid, ssid->ssid_len)
== 0) ||
ssid->ssid_len == 0)) {
curr = &results[i];
break;
}
}
if (curr) {
if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, curr->wpa_ie,
curr->wpa_ie_len) ||
wpa_sm_set_ap_rsn_ie(wpa_s->wpa, curr->rsn_ie,
curr->rsn_ie_len))
ret = -1;
} else {
ret = -1;
}
return ret;
}
static int wpa_supplicant_get_beacon_ie(void *ctx)
{
struct wpa_supplicant *wpa_s = ctx;
if (wpa_get_beacon_ie(wpa_s) == 0) {
return 0;
}
/* No WPA/RSN IE found in the cached scan results. Try to get updated
* scan results from the driver. */
if (wpa_supplicant_get_scan_results(wpa_s) < 0) {
return -1;
}
return wpa_get_beacon_ie(wpa_s);
}
#endif /* CONFIG_NO_WPA */
/**
* wpa_supplicant_get_ssid - Get a pointer to the current network structure
* @wpa_s: Pointer to wpa_supplicant data
* Returns: A pointer to the current network structure or %NULL on failure
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -