Cumulative patch from commit 3e7f1c7980c6e9fc7173f78aa72b2761fcd8924d (DO NOT MERGE)
3e7f1c7 GnuTLS: Add TLS event callbacks for chain success/failure and peer cert
0eb2ed0 GnuTLS: Add support for OCSP stapling as a client
cf08e9b Add MESH to modes capabilities
db5adfe Add SAE to auth_alg capabilities
0e1bb94 GnuTLS: Verify that server certificate EKU is valid for a server
d4d1f5c GnuTLS: Fix tls_disable_time_checks=1 processing
594d1fc GnuTLS: Add support for private_key and client_cert as blobs
79b1dd9 GnuTLS: Fix DER encoding certificate parsing
a165145 Add "GET tls_library" to provide information on TLS library and version
c3bb84b GnuTLS: Add event callbacks
8ddcd6b GnuTLS: Add support for domain_suffix_match
4bc13bf GnuTLS: Check for any unknown verification failure
e0d431a GnuTLS: Add more debug prints for version and session status
65ec7f4 GnuTLS: Move peer certificate validation into callback function
7c82457 GnuTLS: Remove support for versions older than 2.12.x
e1d63f6 GnuTLS: Remove old version number checks for 1.3.2
ae0a23a GnuTLS: Remove GNUTLS_INTERNAL_STRUCTURE_HACK
db4cf40 GnuTLS: Add support for ca_cert as a blob
224104d TLS: Reject openssl_ciphers parameter in non-OpenSSL cases
b09baf3 Work around Windows build issues
6dbbef9 Define host_to_le32() for Windows builds
7d28e46 Fix os_win32 build
0b40247 Remove Network Security Service (NSS) support
d166947 schannel: Reject subject_match, altsubject_match, suffix_match
59051f8 TLS: Reject subject_match, altsubject_match, suffix_match
f8717ac GnuTLS: Reject subject_match, altsubject_match, suffix_match
e24aef1 Fix a typo in domain_suffix_match documentation
394b547 Improve subject_match and domain_suffix_match documentation
8a42a07 trace: Fix out-of-memory testing logic
79cd993 Add address masks to BSSID lists
b83e455 Add network specific BSSID black and white lists
b3d6a0a Add generic parser for MAC address lists
21c74e8 nl80211: Use a helper function to put mesh_id
85e1fad nl80211: Use a helper function for putting beacon interval
6dfc557 Remove mesh_ht_mode network block parameter
54fe48b mesh: Use the shared function with IBSS to determine channel parameters
f7e889f mesh: Convert channel configuration to use common routines
6334330 mesh: Use a separate variable to track whether HT is enabled
1fc4ab2 nl80211: Move debug prints into nl80211_put_freq_params()
cae87ab nl80211: Add a helper function for putting basic rates
6b8b077 ibss/mesh: Enable HT40 if supported
a828f62 Make check_40mhz_2g4 common
fdd989d Make check_20mhz_bss common
0e550fe Make check_40mhz_5g common
6d5d098 Make get_pri_sec_chan() common
5144274 Introduce common allowed_ht40_channel_pair()
5f10b7f Use common hw_get_freq/hw_get_chan helpers in hostapd
269dfe2 Introduce common hw features
1830817 IBSS: Add WPA_DRIVER_FLAGS_HT_IBSS
f3b8ad4 SAE: Implement retransmission timer
a206e2a SAE: Centralize function for sending initial COMMIT
28c91ee bsd: Fix parsing of ieee80211req_scan_result on FreeBSD and DragonFly
96d1d97 Android: Remove hardcoded ICU include paths from hs20-osu-client
a354bcc D-Bus: Use NoMemory error message from CreateInterface
635874b Handle interface disabled/enabled more consistently
8f2cf37 P2P: Indicate reason=UNAVAILABLE for group netdev going down
86a7fbb Verify that eloop_register_read_sock() succeeds for ctrl_iface setup
27d9701 Fix a memory leak on WPA authenticator error path
c1c07dc Fix hostapd interface addition error path
a156ffd Add support for testing memory allocation failures
52b3943 D-Bus: Fix interface unregistration on error path
96dc9a6 D-Bus (old): Fix interface unregistration on error path
ef03557 Fix memory leak on wpa_supplicant_init_wpa() error path
52a8058 TDLS: Fix an interface addition error path
f2d5728 D-Bus: Fix string array dict entry parser in out-of-memory case
c61bc23 D-Bus: Fix byte array dict entry parser in out-of-memory case
dacf605 D-Bus: Fix Introspect() in case of os_strdup() failure
68a8669 D-Bus (old): Fix wpsReg error message
f0614bc D-Bus (old): Fix message handler error paths
a2af1c7 D-Bus (old): Fix memory leak on error path
3d2e2d5 trace: Fix compiler warning on 32-bit builds with bfd support
b9f6560 eloop: Fix WPA_TRACE tracking in case of realloc failure
e10422c Fix memory leak on hostapd BSS addition error path
2801659 Fix hostapd initialization error path on allocation failure
d58ade2 nl80211: Fix compilation with libnl 1.1 and 2.0
51f3427 crypto: Clear temporary stack buffers after use
77a2c39 crypto: Clear temporary heap allocations before freeing
a15a7fc DH: Clear memory explicitly on private key deinit
77c45e2 Add wpabuf_clear_free() to allow clearing of freed memory
a90c7d9 OpenSSL: Fix pbkdf2_sha1() wrapper
f6ebbcf AES-SIV: Make aes_s2v() static
dcf8fbc nl80211: Simplify event processing error paths
38751d8 nl80211: Remove cfg80211 state mismatch workaround for authentication
64ae244 nl80211: Check support for rekey offload on first use
Change-Id: Ice94c3cf8e39a6d2cac993aacd0f6d45b31c7c15
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 2103747..6e4169b 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -1872,33 +1872,37 @@
}
-static struct hostapd_iface * hostapd_data_alloc(
- struct hapd_interfaces *interfaces, struct hostapd_config *conf)
+static int hostapd_data_alloc(struct hostapd_iface *hapd_iface,
+ struct hostapd_config *conf)
{
size_t i;
- struct hostapd_iface *hapd_iface =
- interfaces->iface[interfaces->count - 1];
struct hostapd_data *hapd;
- hapd_iface->conf = conf;
- hapd_iface->num_bss = conf->num_bss;
-
hapd_iface->bss = os_calloc(conf->num_bss,
sizeof(struct hostapd_data *));
if (hapd_iface->bss == NULL)
- return NULL;
+ return -1;
for (i = 0; i < conf->num_bss; i++) {
hapd = hapd_iface->bss[i] =
hostapd_alloc_bss_data(hapd_iface, conf, conf->bss[i]);
- if (hapd == NULL)
- return NULL;
+ if (hapd == NULL) {
+ while (i > 0) {
+ i--;
+ os_free(hapd_iface->bss[i]);
+ hapd_iface->bss[i] = NULL;
+ }
+ os_free(hapd_iface->bss);
+ hapd_iface->bss = NULL;
+ return -1;
+ }
hapd->msg_ctx = hapd;
}
- hapd_iface->interfaces = interfaces;
+ hapd_iface->conf = conf;
+ hapd_iface->num_bss = conf->num_bss;
- return hapd_iface;
+ return 0;
}
@@ -1945,13 +1949,10 @@
}
if (new_iface) {
- if (interfaces->driver_init(hapd_iface)) {
- interfaces->count--;
+ if (interfaces->driver_init(hapd_iface))
goto fail;
- }
if (hostapd_setup_interface(hapd_iface)) {
- interfaces->count--;
hostapd_deinit_driver(
hapd_iface->bss[0]->driver,
hapd_iface->bss[0]->drv_priv,
@@ -1975,6 +1976,8 @@
hapd_iface->num_bss--;
wpa_printf(MSG_DEBUG, "%s: free hapd %p %s",
__func__, hapd, hapd->conf->iface);
+ hostapd_config_free_bss(hapd->conf);
+ hapd->conf = NULL;
os_free(hapd);
return -1;
}
@@ -2005,6 +2008,7 @@
"for interface", __func__);
goto fail;
}
+ new_iface = hapd_iface;
if (conf_file && interfaces->config_read_cb) {
conf = interfaces->config_read_cb(conf_file);
@@ -2019,17 +2023,18 @@
goto fail;
}
- hapd_iface = hostapd_data_alloc(interfaces, conf);
- if (hapd_iface == NULL) {
+ if (hostapd_data_alloc(hapd_iface, conf) < 0) {
wpa_printf(MSG_ERROR, "%s: Failed to allocate memory "
"for hostapd", __func__);
goto fail;
}
+ conf = NULL;
if (start_ctrl_iface(hapd_iface) < 0)
goto fail;
- wpa_printf(MSG_INFO, "Add interface '%s'", conf->bss[0]->iface);
+ wpa_printf(MSG_INFO, "Add interface '%s'",
+ hapd_iface->conf->bss[0]->iface);
return 0;
@@ -2056,6 +2061,10 @@
os_free(hapd_iface->bss);
hapd_iface->bss = NULL;
}
+ if (new_iface) {
+ interfaces->count--;
+ interfaces->iface[interfaces->count] = NULL;
+ }
hostapd_cleanup_iface(hapd_iface);
}
return -1;
@@ -2076,6 +2085,7 @@
wpa_printf(MSG_DEBUG, "%s: free hapd %p (%s)",
__func__, hapd, hapd->conf->iface);
hostapd_config_free_bss(hapd->conf);
+ hapd->conf = NULL;
os_free(hapd);
iface->num_bss--;
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index f959215..6b0a72d 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -15,6 +15,7 @@
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
#include "common/wpa_ctrl.h"
+#include "common/hw_features_common.h"
#include "hostapd.h"
#include "ap_config.h"
#include "ap_drv_ops.h"
@@ -223,66 +224,16 @@
#ifdef CONFIG_IEEE80211N
static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface)
{
- int sec_chan, ok, j, first;
- int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
- 184, 192 };
- size_t k;
+ int pri_chan, sec_chan;
if (!iface->conf->secondary_channel)
return 1; /* HT40 not used */
- sec_chan = iface->conf->channel + iface->conf->secondary_channel * 4;
- wpa_printf(MSG_DEBUG, "HT40: control channel: %d "
- "secondary channel: %d",
- iface->conf->channel, sec_chan);
+ pri_chan = iface->conf->channel;
+ sec_chan = pri_chan + iface->conf->secondary_channel * 4;
- /* Verify that HT40 secondary channel is an allowed 20 MHz
- * channel */
- ok = 0;
- for (j = 0; j < iface->current_mode->num_channels; j++) {
- struct hostapd_channel_data *chan =
- &iface->current_mode->channels[j];
- if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
- chan->chan == sec_chan) {
- ok = 1;
- break;
- }
- }
- if (!ok) {
- wpa_printf(MSG_ERROR, "HT40 secondary channel %d not allowed",
- sec_chan);
- return 0;
- }
-
- /*
- * Verify that HT40 primary,secondary channel pair is allowed per
- * IEEE 802.11n Annex J. This is only needed for 5 GHz band since
- * 2.4 GHz rules allow all cases where the secondary channel fits into
- * the list of allowed channels (already checked above).
- */
- if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A)
- return 1;
-
- if (iface->conf->secondary_channel > 0)
- first = iface->conf->channel;
- else
- first = sec_chan;
-
- ok = 0;
- for (k = 0; k < ARRAY_SIZE(allowed); k++) {
- if (first == allowed[k]) {
- ok = 1;
- break;
- }
- }
- if (!ok) {
- wpa_printf(MSG_ERROR, "HT40 channel pair (%d, %d) not allowed",
- iface->conf->channel,
- iface->conf->secondary_channel);
- return 0;
- }
-
- return 1;
+ return allowed_ht40_channel_pair(iface->current_mode, pri_chan,
+ sec_chan);
}
@@ -298,214 +249,34 @@
}
-static void ieee80211n_get_pri_sec_chan(struct wpa_scan_res *bss,
- int *pri_chan, int *sec_chan)
-{
- struct ieee80211_ht_operation *oper;
- struct ieee802_11_elems elems;
-
- *pri_chan = *sec_chan = 0;
-
- ieee802_11_parse_elems((u8 *) (bss + 1), bss->ie_len, &elems, 0);
- if (elems.ht_operation &&
- elems.ht_operation_len >= sizeof(*oper)) {
- oper = (struct ieee80211_ht_operation *) elems.ht_operation;
- *pri_chan = oper->primary_chan;
- if (oper->ht_param & HT_INFO_HT_PARAM_STA_CHNL_WIDTH) {
- int sec = oper->ht_param &
- HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
- if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
- *sec_chan = *pri_chan + 4;
- else if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
- *sec_chan = *pri_chan - 4;
- }
- }
-}
-
-
static int ieee80211n_check_40mhz_5g(struct hostapd_iface *iface,
struct wpa_scan_results *scan_res)
{
- int pri_chan, sec_chan, pri_freq, sec_freq, pri_bss, sec_bss;
- int bss_pri_chan, bss_sec_chan;
- size_t i;
- int match;
+ int pri_chan, sec_chan;
+ int res;
pri_chan = iface->conf->channel;
sec_chan = pri_chan + iface->conf->secondary_channel * 4;
- pri_freq = hostapd_hw_get_freq(iface->bss[0], pri_chan);
- if (iface->conf->secondary_channel > 0)
- sec_freq = pri_freq + 20;
- else
- sec_freq = pri_freq - 20;
- /*
- * Switch PRI/SEC channels if Beacons were detected on selected SEC
- * channel, but not on selected PRI channel.
- */
- pri_bss = sec_bss = 0;
- for (i = 0; i < scan_res->num; i++) {
- struct wpa_scan_res *bss = scan_res->res[i];
- if (bss->freq == pri_freq)
- pri_bss++;
- else if (bss->freq == sec_freq)
- sec_bss++;
- }
- if (sec_bss && !pri_bss) {
- wpa_printf(MSG_INFO, "Switch own primary and secondary "
- "channel to get secondary channel with no Beacons "
- "from other BSSes");
+ res = check_40mhz_5g(iface->current_mode, scan_res, pri_chan, sec_chan);
+
+ if (res == 2)
ieee80211n_switch_pri_sec(iface);
- return 1;
- }
- /*
- * Match PRI/SEC channel with any existing HT40 BSS on the same
- * channels that we are about to use (if already mixed order in
- * existing BSSes, use own preference).
- */
- match = 0;
- for (i = 0; i < scan_res->num; i++) {
- struct wpa_scan_res *bss = scan_res->res[i];
- ieee80211n_get_pri_sec_chan(bss, &bss_pri_chan, &bss_sec_chan);
- if (pri_chan == bss_pri_chan &&
- sec_chan == bss_sec_chan) {
- match = 1;
- break;
- }
- }
- if (!match) {
- for (i = 0; i < scan_res->num; i++) {
- struct wpa_scan_res *bss = scan_res->res[i];
- ieee80211n_get_pri_sec_chan(bss, &bss_pri_chan,
- &bss_sec_chan);
- if (pri_chan == bss_sec_chan &&
- sec_chan == bss_pri_chan) {
- wpa_printf(MSG_INFO, "Switch own primary and "
- "secondary channel due to BSS "
- "overlap with " MACSTR,
- MAC2STR(bss->bssid));
- ieee80211n_switch_pri_sec(iface);
- break;
- }
- }
- }
-
- return 1;
-}
-
-
-static int ieee80211n_check_20mhz_bss(struct wpa_scan_res *bss, int pri_freq,
- int start, int end)
-{
- struct ieee802_11_elems elems;
- struct ieee80211_ht_operation *oper;
-
- if (bss->freq < start || bss->freq > end || bss->freq == pri_freq)
- return 0;
-
- ieee802_11_parse_elems((u8 *) (bss + 1), bss->ie_len, &elems, 0);
- if (!elems.ht_capabilities) {
- wpa_printf(MSG_DEBUG, "Found overlapping legacy BSS: "
- MACSTR " freq=%d", MAC2STR(bss->bssid), bss->freq);
- return 1;
- }
-
- if (elems.ht_operation &&
- elems.ht_operation_len >= sizeof(*oper)) {
- oper = (struct ieee80211_ht_operation *) elems.ht_operation;
- if (oper->ht_param & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK)
- return 0;
-
- wpa_printf(MSG_DEBUG, "Found overlapping 20 MHz HT BSS: "
- MACSTR " freq=%d", MAC2STR(bss->bssid), bss->freq);
- return 1;
- }
- return 0;
+ return !!res;
}
static int ieee80211n_check_40mhz_2g4(struct hostapd_iface *iface,
struct wpa_scan_results *scan_res)
{
- int pri_freq, sec_freq;
- int affected_start, affected_end;
- size_t i;
+ int pri_chan, sec_chan;
- pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel);
- if (iface->conf->secondary_channel > 0)
- sec_freq = pri_freq + 20;
- else
- sec_freq = pri_freq - 20;
- affected_start = (pri_freq + sec_freq) / 2 - 25;
- affected_end = (pri_freq + sec_freq) / 2 + 25;
- wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz",
- affected_start, affected_end);
- for (i = 0; i < scan_res->num; i++) {
- struct wpa_scan_res *bss = scan_res->res[i];
- int pri = bss->freq;
- int sec = pri;
- int sec_chan, pri_chan;
- struct ieee802_11_elems elems;
+ pri_chan = iface->conf->channel;
+ sec_chan = pri_chan + iface->conf->secondary_channel * 4;
- /* Check for overlapping 20 MHz BSS */
- if (ieee80211n_check_20mhz_bss(bss, pri_freq, affected_start,
- affected_end)) {
- wpa_printf(MSG_DEBUG,
- "Overlapping 20 MHz BSS is found");
- return 0;
- }
-
- ieee80211n_get_pri_sec_chan(bss, &pri_chan, &sec_chan);
-
- if (sec_chan) {
- if (sec_chan < pri_chan)
- sec = pri - 20;
- else
- sec = pri + 20;
- }
-
- if ((pri < affected_start || pri > affected_end) &&
- (sec < affected_start || sec > affected_end))
- continue; /* not within affected channel range */
-
- wpa_printf(MSG_DEBUG, "Neighboring BSS: " MACSTR
- " freq=%d pri=%d sec=%d",
- MAC2STR(bss->bssid), bss->freq, pri_chan, sec_chan);
-
- if (sec_chan) {
- if (pri_freq != pri || sec_freq != sec) {
- wpa_printf(MSG_DEBUG, "40 MHz pri/sec "
- "mismatch with BSS " MACSTR
- " <%d,%d> (chan=%d%c) vs. <%d,%d>",
- MAC2STR(bss->bssid),
- pri, sec, pri_chan,
- sec > pri ? '+' : '-',
- pri_freq, sec_freq);
- return 0;
- }
- }
-
- ieee802_11_parse_elems((u8 *) (bss + 1), bss->ie_len, &elems,
- 0);
- if (elems.ht_capabilities &&
- elems.ht_capabilities_len >=
- sizeof(struct ieee80211_ht_capabilities)) {
- struct ieee80211_ht_capabilities *ht_cap =
- (struct ieee80211_ht_capabilities *)
- elems.ht_capabilities;
-
- if (le_to_host16(ht_cap->ht_capabilities_info) &
- HT_CAP_INFO_40MHZ_INTOLERANT) {
- wpa_printf(MSG_DEBUG,
- "40 MHz Intolerant is set on channel %d in BSS "
- MACSTR, pri, MAC2STR(bss->bssid));
- return 0;
- }
- }
- }
-
- return 1;
+ return check_40mhz_2g4(iface->current_mode, scan_res, pri_chan,
+ sec_chan);
}
@@ -1143,35 +914,11 @@
int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan)
{
- int i;
-
- if (!hapd->iface->current_mode)
- return 0;
-
- for (i = 0; i < hapd->iface->current_mode->num_channels; i++) {
- struct hostapd_channel_data *ch =
- &hapd->iface->current_mode->channels[i];
- if (ch->chan == chan)
- return ch->freq;
- }
-
- return 0;
+ return hw_get_freq(hapd->iface->current_mode, chan);
}
int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq)
{
- int i;
-
- if (!hapd->iface->current_mode)
- return 0;
-
- for (i = 0; i < hapd->iface->current_mode->num_channels; i++) {
- struct hostapd_channel_data *ch =
- &hapd->iface->current_mode->channels[i];
- if (ch->freq == freq)
- return ch->chan;
- }
-
- return 0;
+ return hw_get_chan(hapd->iface->current_mode, freq);
}
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 97f98f2..3d4488a 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -328,6 +328,10 @@
#ifdef CONFIG_SAE
+#define dot11RSNASAERetransPeriod 40 /* msec */
+#define dot11RSNASAESync 5 /* attempts */
+
+
static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
struct sta_info *sta, int update)
{
@@ -483,6 +487,66 @@
}
+static int sae_check_big_sync(struct sta_info *sta)
+{
+ if (sta->sae->sync > dot11RSNASAESync) {
+ sta->sae->state = SAE_NOTHING;
+ sta->sae->sync = 0;
+ return -1;
+ }
+ return 0;
+}
+
+
+static void auth_sae_retransmit_timer(void *eloop_ctx, void *eloop_data)
+{
+ struct hostapd_data *hapd = eloop_ctx;
+ struct sta_info *sta = eloop_data;
+ int ret;
+
+ if (sae_check_big_sync(sta))
+ return;
+ sta->sae->sync++;
+
+ switch (sta->sae->state) {
+ case SAE_COMMITTED:
+ ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0);
+ eloop_register_timeout(0, dot11RSNASAERetransPeriod * 1000,
+ auth_sae_retransmit_timer, hapd, sta);
+ break;
+ case SAE_CONFIRMED:
+ ret = auth_sae_send_confirm(hapd, sta, hapd->own_addr);
+ eloop_register_timeout(0, dot11RSNASAERetransPeriod * 1000,
+ auth_sae_retransmit_timer, hapd, sta);
+ break;
+ default:
+ ret = -1;
+ break;
+ }
+
+ if (ret != WLAN_STATUS_SUCCESS)
+ wpa_printf(MSG_INFO, "SAE: Failed to retransmit: ret=%d", ret);
+}
+
+
+void sae_clear_retransmit_timer(struct hostapd_data *hapd, struct sta_info *sta)
+{
+ eloop_cancel_timeout(auth_sae_retransmit_timer, hapd, sta);
+}
+
+
+static void sae_set_retransmit_timer(struct hostapd_data *hapd,
+ struct sta_info *sta)
+{
+ if (!(hapd->conf->mesh & MESH_ENABLED))
+ return;
+
+ eloop_cancel_timeout(auth_sae_retransmit_timer, hapd, sta);
+ eloop_register_timeout(0, dot11RSNASAERetransPeriod * 1000,
+ auth_sae_retransmit_timer, hapd, sta);
+}
+
+
static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *bssid, u8 auth_transaction)
{
@@ -530,6 +594,8 @@
* when receiving Confirm from STA.
*/
}
+ sta->sae->sync = 0;
+ sae_set_retransmit_timer(hapd, sta);
} else {
hostapd_logger(hapd, sta->addr,
HOSTAPD_MODULE_IEEE80211,
@@ -538,6 +604,7 @@
}
break;
case SAE_COMMITTED:
+ sae_clear_retransmit_timer(hapd, sta);
if (auth_transaction == 1) {
if (sae_process_commit(sta->sae) < 0)
return WLAN_STATUS_UNSPECIFIED_FAILURE;
@@ -546,14 +613,22 @@
if (ret)
return ret;
sta->sae->state = SAE_CONFIRMED;
+ sta->sae->sync = 0;
+ sae_set_retransmit_timer(hapd, sta);
} else if (hapd->conf->mesh & MESH_ENABLED) {
/*
* In mesh case, follow SAE finite state machine and
- * send Commit now.
+ * send Commit now, if sync count allows.
*/
+ if (sae_check_big_sync(sta))
+ return WLAN_STATUS_SUCCESS;
+ sta->sae->sync++;
+
ret = auth_sae_send_commit(hapd, sta, bssid, 1);
if (ret)
return ret;
+
+ sae_set_retransmit_timer(hapd, sta);
} else {
/*
* For instructure BSS, send the postponed Confirm from
@@ -575,7 +650,12 @@
}
break;
case SAE_CONFIRMED:
+ sae_clear_retransmit_timer(hapd, sta);
if (auth_transaction == 1) {
+ if (sae_check_big_sync(sta))
+ return WLAN_STATUS_SUCCESS;
+ sta->sae->sync++;
+
ret = auth_sae_send_commit(hapd, sta, bssid, 1);
if (ret)
return ret;
@@ -586,6 +666,8 @@
ret = auth_sae_send_confirm(hapd, sta, bssid);
if (ret)
return ret;
+
+ sae_set_retransmit_timer(hapd, sta);
} else {
sta->flags |= WLAN_STA_AUTH;
sta->auth_alg = WLAN_AUTH_SAE;
@@ -603,6 +685,10 @@
MAC2STR(sta->addr));
ap_free_sta(hapd, sta);
} else {
+ if (sae_check_big_sync(sta))
+ return WLAN_STATUS_SUCCESS;
+ sta->sae->sync++;
+
ret = auth_sae_send_confirm(hapd, sta, bssid);
sae_clear_temp_data(sta->sae);
if (ret)
@@ -632,6 +718,7 @@
if (sta->sae == NULL)
return;
sta->sae->state = SAE_NOTHING;
+ sta->sae->sync = 0;
}
if (auth_transaction == 1) {
@@ -685,6 +772,8 @@
return;
}
sta->sae->state = SAE_COMMITTED;
+ sta->sae->sync = 0;
+ sae_set_retransmit_timer(hapd, sta);
return;
}
@@ -755,6 +844,39 @@
}
wpabuf_free(data);
}
+
+
+/**
+ * auth_sae_init_committed - Send COMMIT and start SAE in committed state
+ * @hapd: BSS data for the device initiating the authentication
+ * @sta: the peer to which commit authentication frame is sent
+ *
+ * This function implements Init event handling (IEEE Std 802.11-2012,
+ * 11.3.8.6.3) in which initial COMMIT message is sent. Prior to calling, the
+ * sta->sae structure should be initialized appropriately via a call to
+ * sae_prepare_commit().
+ */
+int auth_sae_init_committed(struct hostapd_data *hapd, struct sta_info *sta)
+{
+ int ret;
+
+ if (!sta->sae || !sta->sae->tmp)
+ return -1;
+
+ if (sta->sae->state != SAE_NOTHING)
+ return -1;
+
+ ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0);
+ if (ret)
+ return -1;
+
+ sta->sae->state = SAE_COMMITTED;
+ sta->sae->sync = 0;
+ sae_set_retransmit_timer(hapd, sta);
+
+ return 0;
+}
+
#endif /* CONFIG_SAE */
diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
index cf0d3f2..beaeac5 100644
--- a/src/ap/ieee802_11.h
+++ b/src/ap/ieee802_11.h
@@ -89,4 +89,15 @@
void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr);
u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid);
+int auth_sae_init_committed(struct hostapd_data *hapd, struct sta_info *sta);
+#ifdef CONFIG_SAE
+void sae_clear_retransmit_timer(struct hostapd_data *hapd,
+ struct sta_info *sta);
+#else /* CONFIG_SAE */
+static inline void sae_clear_retransmit_timer(struct hostapd_data *hapd,
+ struct sta_info *sta)
+{
+}
+#endif /* CONFIG_SAE */
+
#endif /* IEEE802_11_H */
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index debdc06..1c2197a 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -250,6 +250,7 @@
eloop_cancel_timeout(ap_handle_session_warning_timer, hapd, sta);
eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta);
eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta);
+ sae_clear_retransmit_timer(hapd, sta);
ieee802_1x_free_station(sta);
wpa_auth_sta_deinit(sta->wpa_sm);
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index da2073c..059b884 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -415,6 +415,7 @@
wpa_auth);
if (wpa_auth->pmksa == NULL) {
wpa_printf(MSG_ERROR, "PMKSA cache initialization failed.");
+ os_free(wpa_auth->group);
os_free(wpa_auth->wpa_ie);
os_free(wpa_auth);
return NULL;
@@ -424,6 +425,7 @@
wpa_auth->ft_pmk_cache = wpa_ft_pmk_cache_init();
if (wpa_auth->ft_pmk_cache == NULL) {
wpa_printf(MSG_ERROR, "FT PMK cache initialization failed.");
+ os_free(wpa_auth->group);
os_free(wpa_auth->wpa_ie);
pmksa_cache_auth_deinit(wpa_auth->pmksa);
os_free(wpa_auth);