📄 wpa_supplicant.c
字号:
}
/**
* wpa_supplicant_reload_configuration - Reload configuration data
* @wpa_s: Pointer to wpa_supplicant data
* Returns: 0 on success or -1 if configuration parsing failed
*
* This function can be used to request that the configuration data is reloaded
* (e.g., after configuration file change). This function is reloading
* configuration only for one interface, so this may need to be called multiple
* times if %wpa_supplicant is controlling multiple interfaces and all
* interfaces need reconfiguration.
*/
int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
{
struct wpa_config *conf;
int reconf_ctrl;
if (wpa_s->confname == NULL)
return -1;
conf = wpa_config_read(wpa_s->confname);
if (conf == NULL) {
wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
"file '%s' - exiting", wpa_s->confname);
return -1;
}
reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
|| (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
os_strcmp(conf->ctrl_interface,
wpa_s->conf->ctrl_interface) != 0);
if (reconf_ctrl && wpa_s->ctrl_iface) {
wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
wpa_s->ctrl_iface = NULL;
}
eapol_sm_invalidate_cached_session(wpa_s->eapol);
wpa_s->current_ssid = NULL;
/*
* TODO: should notify EAPOL SM about changes in opensc_engine_path,
* pkcs11_engine_path, pkcs11_module_path.
*/
eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
wpa_sm_set_config(wpa_s->wpa, NULL);
wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
rsn_preauth_deinit(wpa_s->wpa);
wpa_config_free(wpa_s->conf);
wpa_s->conf = conf;
if (reconf_ctrl)
wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
wpa_supplicant_clear_status(wpa_s);
wpa_s->reassociate = 1;
wpa_supplicant_req_scan(wpa_s, 0, 0);
wpa_msg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
return 0;
}
static void wpa_supplicant_reconfig(int sig, void *eloop_ctx,
void *signal_ctx)
{
struct wpa_global *global = eloop_ctx;
struct wpa_supplicant *wpa_s;
wpa_printf(MSG_DEBUG, "Signal %d received - reconfiguring", sig);
for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
eloop_terminate();
}
}
}
static void wpa_supplicant_gen_assoc_event(struct wpa_supplicant *wpa_s)
{
struct wpa_ssid *ssid;
union wpa_event_data data;
ssid = wpa_supplicant_get_ssid(wpa_s);
if (ssid == NULL)
return;
if (wpa_s->current_ssid == NULL)
wpa_s->current_ssid = ssid;
wpa_supplicant_initiate_eapol(wpa_s);
wpa_printf(MSG_DEBUG, "Already associated with a configured network - "
"generating associated event");
os_memset(&data, 0, sizeof(data));
wpa_supplicant_event(wpa_s, EVENT_ASSOC, &data);
}
static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
{
struct wpa_supplicant *wpa_s = eloop_ctx;
struct wpa_ssid *ssid;
int enabled, scan_req = 0, ret;
if (wpa_s->disconnected)
return;
enabled = 0;
ssid = wpa_s->conf->ssid;
while (ssid) {
if (!ssid->disabled) {
enabled++;
break;
}
ssid = ssid->next;
}
if (!enabled && !wpa_s->scan_req) {
wpa_printf(MSG_DEBUG, "No enabled networks - do not scan");
wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
return;
}
scan_req = wpa_s->scan_req;
wpa_s->scan_req = 0;
if (wpa_s->conf->ap_scan != 0 &&
wpa_s->driver && os_strcmp(wpa_s->driver->name, "wired") == 0) {
wpa_printf(MSG_DEBUG, "Using wired driver - overriding "
"ap_scan configuration");
wpa_s->conf->ap_scan = 0;
}
if (wpa_s->conf->ap_scan == 0) {
wpa_supplicant_gen_assoc_event(wpa_s);
return;
}
if (wpa_s->wpa_state == WPA_DISCONNECTED ||
wpa_s->wpa_state == WPA_INACTIVE)
wpa_supplicant_set_state(wpa_s, WPA_SCANNING);
ssid = wpa_s->conf->ssid;
if (wpa_s->prev_scan_ssid != BROADCAST_SSID_SCAN) {
while (ssid) {
if (ssid == wpa_s->prev_scan_ssid) {
ssid = ssid->next;
break;
}
ssid = ssid->next;
}
}
while (ssid) {
if (!ssid->disabled &&
(ssid->scan_ssid || wpa_s->conf->ap_scan == 2))
break;
ssid = ssid->next;
}
if (scan_req != 2 && wpa_s->conf->ap_scan == 2) {
/*
* ap_scan=2 mode - try to associate with each SSID instead of
* scanning for each scan_ssid=1 network.
*/
if (ssid == NULL) {
wpa_printf(MSG_DEBUG, "wpa_supplicant_scan: Reached "
"end of scan list - go back to beginning");
wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN;
wpa_supplicant_req_scan(wpa_s, 0, 0);
return;
}
if (ssid->next) {
/* Continue from the next SSID on the next attempt. */
wpa_s->prev_scan_ssid = ssid;
} else {
/* Start from the beginning of the SSID list. */
wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN;
}
wpa_supplicant_associate(wpa_s, NULL, ssid);
return;
}
wpa_printf(MSG_DEBUG, "Starting AP scan (%s SSID)",
ssid ? "specific": "broadcast");
if (ssid) {
wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID",
ssid->ssid, ssid->ssid_len);
wpa_s->prev_scan_ssid = ssid;
} else
wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN;
if (wpa_s->scan_res_tried == 0 && wpa_s->conf->ap_scan == 1) {
wpa_s->scan_res_tried++;
wpa_printf(MSG_DEBUG, "Trying to get current scan results "
"first without requesting a new scan to speed up "
"initial association");
wpa_supplicant_event(wpa_s, EVENT_SCAN_RESULTS, NULL);
return;
}
if (wpa_s->use_client_mlme) {
ret = ieee80211_sta_req_scan(wpa_s, ssid ? ssid->ssid : NULL,
ssid ? ssid->ssid_len : 0);
} else {
ret = wpa_drv_scan(wpa_s, ssid ? ssid->ssid : NULL,
ssid ? ssid->ssid_len : 0);
}
if (ret) {
wpa_printf(MSG_WARNING, "Failed to initiate AP scan.");
wpa_supplicant_req_scan(wpa_s, 10, 0);
}
}
static wpa_cipher cipher_suite2driver(int cipher)
{
switch (cipher) {
case WPA_CIPHER_NONE:
return CIPHER_NONE;
case WPA_CIPHER_WEP40:
return CIPHER_WEP40;
case WPA_CIPHER_WEP104:
return CIPHER_WEP104;
case WPA_CIPHER_CCMP:
return CIPHER_CCMP;
case WPA_CIPHER_TKIP:
default:
return CIPHER_TKIP;
}
}
static wpa_key_mgmt key_mgmt2driver(int key_mgmt)
{
switch (key_mgmt) {
case WPA_KEY_MGMT_NONE:
return KEY_MGMT_NONE;
case WPA_KEY_MGMT_IEEE8021X_NO_WPA:
return KEY_MGMT_802_1X_NO_WPA;
case WPA_KEY_MGMT_IEEE8021X:
return KEY_MGMT_802_1X;
case WPA_KEY_MGMT_WPA_NONE:
return KEY_MGMT_WPA_NONE;
case WPA_KEY_MGMT_PSK:
default:
return KEY_MGMT_PSK;
}
}
static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid,
struct wpa_ie_data *ie)
{
int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
if (ret) {
if (ret == -2) {
wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
"from association info");
}
return -1;
}
wpa_printf(MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set cipher "
"suites");
if (!(ie->group_cipher & ssid->group_cipher)) {
wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
"cipher 0x%x (mask 0x%x) - reject",
ie->group_cipher, ssid->group_cipher);
return -1;
}
if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
"cipher 0x%x (mask 0x%x) - reject",
ie->pairwise_cipher, ssid->pairwise_cipher);
return -1;
}
if (!(ie->key_mgmt & ssid->key_mgmt)) {
wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
"management 0x%x (mask 0x%x) - reject",
ie->key_mgmt, ssid->key_mgmt);
return -1;
}
#ifdef CONFIG_IEEE80211W
if (!(ie->capabilities & WPA_CAPABILITY_MGMT_FRAME_PROTECTION) &&
ssid->ieee80211w == IEEE80211W_REQUIRED) {
wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
"that does not support management frame protection - "
"reject");
return -1;
}
#endif /* CONFIG_IEEE80211W */
return 0;
}
/**
* wpa_supplicant_set_suites - Set authentication and encryption parameters
* @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
* @wpa_ie: Buffer for the WPA/RSN IE
* @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
* used buffer length in case the functions returns success.
* Returns: 0 on success or -1 on failure
*
* This function is used to configure authentication and encryption parameters
* based on the network configuration and scan result for the selected BSS (if
* available).
*/
int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
struct wpa_scan_result *bss,
struct wpa_ssid *ssid,
u8 *wpa_ie, size_t *wpa_ie_len)
{
struct wpa_ie_data ie;
int sel, proto;
if (bss && bss->rsn_ie_len && (ssid->proto & WPA_PROTO_RSN) &&
wpa_parse_wpa_ie(bss->rsn_ie, bss->rsn_ie_len, &ie) == 0 &&
#ifndef CONFIG_DRIVER_RALINK
(ie.group_cipher & ssid->group_cipher) &&
#endif
(ie.pairwise_cipher & ssid->pairwise_cipher) &&
(ie.key_mgmt & ssid->key_mgmt)) {
wpa_msg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
proto = WPA_PROTO_RSN;
} else if (bss && bss->wpa_ie_len && (ssid->proto & WPA_PROTO_WPA) &&
wpa_parse_wpa_ie(bss->wpa_ie, bss->wpa_ie_len, &ie) == 0 &&
#ifndef CONFIG_DRIVER_RALINK
(ie.group_cipher & ssid->group_cipher) &&
#endif
(ie.pairwise_cipher & ssid->pairwise_cipher) &&
(ie.key_mgmt & ssid->key_mgmt)) {
wpa_msg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
proto = WPA_PROTO_WPA;
} else if (bss) {
wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
return -1;
} else {
if (ssid->proto & WPA_PROTO_RSN)
proto = WPA_PROTO_RSN;
else
proto = WPA_PROTO_WPA;
if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
os_memset(&ie, 0, sizeof(ie));
ie.group_cipher = ssid->group_cipher;
ie.pairwise_cipher = ssid->pairwise_cipher;
ie.key_mgmt = ssid->key_mgmt;
#ifdef CONFIG_IEEE80211W
ie.mgmt_group_cipher =
ssid->ieee80211w != NO_IEEE80211W ?
WPA_CIPHER_AES_128_CMAC : 0;
#endif /* CONFIG_IEEE80211W */
wpa_printf(MSG_DEBUG, "WPA: Set cipher suites based "
"on configuration");
} else
proto = ie.proto;
}
wpa_printf(MSG_DEBUG, "WPA: Selected cipher suites: group %d "
"pairwise %d key_mgmt %d proto %d",
ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
#ifdef CONFIG_IEEE80211W
if (ssid->ieee80211w) {
wpa_printf(MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
ie.mgmt_group_cipher);
}
#endif /* CONFIG_IEEE80211W */
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss ? bss->wpa_ie : NULL,
bss ? bss->wpa_ie_len : 0) ||
wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss ? bss->rsn_ie : NULL,
bss ? bss->rsn_ie_len : 0))
return -1;
#ifndef CONFIG_DRIVER_RALINK
sel = ie.group_cipher & ssid->group_cipher;
#else
sel = ie.group_cipher;
#endif
if (sel & WPA_CIPHER_CCMP) {
wpa_s->group_cipher = WPA_CIPHER_CCMP;
wpa_msg(wpa_s, MSG_DEBUG, "WPA: using GTK CCMP");
} else if (sel & WPA_CIPHER_TKIP) {
wpa_s->group_cipher = WPA_CIPHER_TKIP;
wpa_msg(wpa_s, MSG_DEBUG, "WPA: using GTK TKIP");
} else if (sel & WPA_CIPHER_WEP104) {
wpa_s->group_cipher = WPA_CIPHER_WEP104;
wpa_msg(wpa_s, MSG_DEBUG, "WPA: using GTK WEP104");
} else if (sel & WPA_CIPHER_WEP40) {
wpa_s->group_cipher = WPA_CIPHER_WEP40;
wpa_msg(wpa_s, MSG_DEBUG, "WPA: using GTK WEP40");
} else {
wpa_printf(MSG_WARNING, "WPA: Failed to select group cipher.");
return -1;
}
sel = ie.pairwise_cipher & ssid->pairwise_cipher;
if (sel & WPA_CIPHER_CCMP) {
wpa_s->pairwise_cipher = WPA_CIPHER_CCMP;
wpa_msg(wpa_s, MSG_DEBUG, "WPA: using PTK CCMP");
} else if (sel & WPA_CIPHER_TKIP) {
wpa_s->pairwise_cipher = WPA_CIPHER_TKIP;
wpa_msg(wpa_s, MSG_DEBUG, "WPA: using PTK TKIP");
} else if (sel & WPA_CIPHER_NONE) {
wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
wpa_msg(wpa_s, MSG_DEBUG, "WPA: using PTK NONE");
} else {
wpa_printf(MSG_WARNING, "WPA: Failed to select pairwise "
"cipher.");
return -1;
}
sel = ie.key_mgmt & ssid->key_mgmt;
if (sel & WPA_KEY_MGMT_IEEE8021X) {
wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
wpa_msg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
} else if (sel & WPA_KEY_MGMT_PSK) {
wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
wpa_msg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
} else if (sel & WPA_KEY_MGMT_WPA_NONE) {
wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
wpa_msg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
} else {
wpa_printf(MSG_WARNING, "WPA: Failed to select authenticated "
"key management type.");
return -1;
}
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
wpa_s->pairwise_cipher);
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
#ifdef CONFIG_IEEE80211W
sel = ie.mgmt_group_cipher;
if (ssid->ieee80211w == NO_IEEE80211W ||
!(ie.capabilities & WPA_CAPABILITY_MGMT_FRAME_PROTECTION))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -