mirror of
https://github.com/vanhoefm/fragattacks.git
synced 2024-11-28 18:28:23 -05:00
WPS: Add a workaround for TKIP/CCMP mixed mode credentials
Many deployed APs do not handle negotiation of security parameters well when both TKIP and CCMP (or both WPA and WPA2) are enabled. The most common end result seems to be ending up with the least secure option.. As a workaround, check whether the AP advertises WPA2/CCMP in Beacon frames and add those options for the credential if needed. This allows the client to select the most secure configuration regardless of how broken the AP's WPS implementation is as far as auth/encr type negotiation is concerned.
This commit is contained in:
parent
d85825e355
commit
7cc1b6c900
@ -26,6 +26,7 @@
|
||||
#include "ctrl_iface_dbus.h"
|
||||
#include "eap_common/eap_wsc_common.h"
|
||||
#include "blacklist.h"
|
||||
#include "wpa.h"
|
||||
#include "wps_supplicant.h"
|
||||
#include "dh_groups.h"
|
||||
|
||||
@ -84,6 +85,102 @@ int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s)
|
||||
}
|
||||
|
||||
|
||||
static void wpas_wps_security_workaround(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_ssid *ssid,
|
||||
const struct wps_credential *cred)
|
||||
{
|
||||
struct wpa_driver_capa capa;
|
||||
size_t i;
|
||||
struct wpa_scan_res *bss;
|
||||
const u8 *ie;
|
||||
struct wpa_ie_data adv;
|
||||
int wpa2 = 0, ccmp = 0;
|
||||
|
||||
/*
|
||||
* Many existing WPS APs do not know how to negotiate WPA2 or CCMP in
|
||||
* case they are configured for mixed mode operation (WPA+WPA2 and
|
||||
* TKIP+CCMP). Try to use scan results to figure out whether the AP
|
||||
* actually supports stronger security and select that if the client
|
||||
* has support for it, too.
|
||||
*/
|
||||
|
||||
if (wpa_drv_get_capa(wpa_s, &capa))
|
||||
return; /* Unknown what driver supports */
|
||||
|
||||
if (wpa_supplicant_get_scan_results(wpa_s) || wpa_s->scan_res == NULL)
|
||||
return; /* Could not get scan results for checking advertised
|
||||
* parameters */
|
||||
|
||||
for (i = 0; i < wpa_s->scan_res->num; i++) {
|
||||
bss = wpa_s->scan_res->res[i];
|
||||
if (os_memcmp(bss->bssid, cred->mac_addr, ETH_ALEN) != 0)
|
||||
continue;
|
||||
ie = wpa_scan_get_ie(bss, WLAN_EID_SSID);
|
||||
if (ie == NULL)
|
||||
continue;
|
||||
if (ie[1] != ssid->ssid_len || ssid->ssid == NULL ||
|
||||
os_memcmp(ie + 2, ssid->ssid, ssid->ssid_len) != 0)
|
||||
continue;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "WPS: AP found from scan results");
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == wpa_s->scan_res->num) {
|
||||
wpa_printf(MSG_DEBUG, "WPS: The AP was not found from scan "
|
||||
"results - use credential as-is");
|
||||
return;
|
||||
}
|
||||
|
||||
ie = wpa_scan_get_ie(bss, WLAN_EID_RSN);
|
||||
if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &adv) == 0) {
|
||||
wpa2 = 1;
|
||||
if (adv.pairwise_cipher & WPA_CIPHER_CCMP)
|
||||
ccmp = 1;
|
||||
} else {
|
||||
ie = wpa_scan_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
|
||||
if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &adv) == 0 &&
|
||||
adv.pairwise_cipher & WPA_CIPHER_CCMP)
|
||||
ccmp = 1;
|
||||
}
|
||||
|
||||
if (ie == NULL && (ssid->proto & WPA_PROTO_WPA) &&
|
||||
(ssid->pairwise_cipher & WPA_CIPHER_TKIP)) {
|
||||
/*
|
||||
* TODO: This could be the initial AP configuration and the
|
||||
* Beacon contents could change shortly. Should request a new
|
||||
* scan and delay addition of the network until the updated
|
||||
* scan results are available.
|
||||
*/
|
||||
wpa_printf(MSG_DEBUG, "WPS: The AP did not yet advertise WPA "
|
||||
"support - use credential as-is");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ccmp && !(ssid->pairwise_cipher & WPA_CIPHER_CCMP) &&
|
||||
(ssid->pairwise_cipher & WPA_CIPHER_TKIP) &&
|
||||
(capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
|
||||
wpa_printf(MSG_DEBUG, "WPS: Add CCMP into the credential "
|
||||
"based on scan results");
|
||||
if (wpa_s->conf->ap_scan == 1)
|
||||
ssid->pairwise_cipher |= WPA_CIPHER_CCMP;
|
||||
else
|
||||
ssid->pairwise_cipher = WPA_CIPHER_CCMP;
|
||||
}
|
||||
|
||||
if (wpa2 && !(ssid->proto & WPA_PROTO_RSN) &&
|
||||
(ssid->proto & WPA_PROTO_WPA) &&
|
||||
(capa.enc & WPA_DRIVER_CAPA_ENC_CCMP)) {
|
||||
wpa_printf(MSG_DEBUG, "WPS: Add WPA2 into the credential "
|
||||
"based on scan results");
|
||||
if (wpa_s->conf->ap_scan == 1)
|
||||
ssid->proto |= WPA_PROTO_RSN;
|
||||
else
|
||||
ssid->proto = WPA_PROTO_RSN;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int wpa_supplicant_wps_cred(void *ctx,
|
||||
const struct wps_credential *cred)
|
||||
{
|
||||
@ -250,6 +347,8 @@ static int wpa_supplicant_wps_cred(void *ctx,
|
||||
}
|
||||
}
|
||||
|
||||
wpas_wps_security_workaround(wpa_s, ssid, cred);
|
||||
|
||||
#ifndef CONFIG_NO_CONFIG_WRITE
|
||||
if (wpa_s->conf->update_config &&
|
||||
wpa_config_write(wpa_s->confname, wpa_s->conf)) {
|
||||
|
Loading…
Reference in New Issue
Block a user