# Enabling this automatically also enables ieee80211w, if not yet enabled.
# 0 = disabled (default)
# 1 = enabled
+# 2 = enabled in workaround mode - Allow STA that claims OCV capability to
+# connect even if the STA doesn't send OCI or negotiate PMF. This
+# workaround is to improve interoperability with legacy STAs which are
+# wrongly copying reserved bits of RSN capabilities from the AP's
+# RSNE into (Re)Association Request frames. When this configuration is
+# enabled, the AP considers STA is OCV capable only when the STA indicates
+# MFP capability in (Re)Association Request frames and sends OCI in
+# EAPOL-Key msg 2/4/FT Reassociation Request frame/FILS (Re)Association
+# Request frame; otherwise, the AP disables OCV for the current connection
+# with the STA. Enabling this workaround mode reduced OCV protection to
+# some extend since it allows misbehavior to go through. As such, this
+# should be enabled only if interoperability with misbehaving STAs is
+# needed.
#ocv=1
# disable_pmksa_caching: Disable PMKSA caching
struct wpa_channel_info ci;
int tx_chanwidth;
int tx_seg1_idx;
+ enum oci_verify_result res;
if (hostapd_drv_channel_info(hapd, &ci) != 0) {
wpa_printf(MSG_WARNING,
&tx_seg1_idx) < 0)
return WLAN_STATUS_UNSPECIFIED_FAILURE;
- if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci,
- tx_chanwidth, tx_seg1_idx) !=
- OCI_SUCCESS) {
+ res = ocv_verify_tx_params(elems.oci, elems.oci_len, &ci,
+ tx_chanwidth, tx_seg1_idx);
+ if (wpa_auth_uses_ocv(sta->wpa_sm) == 2 &&
+ res == OCI_NOT_FOUND) {
+ /* Work around misbehaving STAs */
+ wpa_printf(MSG_INFO,
+ "FILS: Disable OCV with a STA that does not send OCI");
+ wpa_auth_set_ocv(sta->wpa_sm, 0);
+ } else if (res != OCI_SUCCESS) {
wpa_printf(MSG_WARNING, "FILS: OCV failed: %s",
ocv_errorstr);
wpa_msg(hapd->msg_ctx, MSG_INFO, OCV_FAILURE "addr="
struct wpa_channel_info ci;
int tx_chanwidth;
int tx_seg1_idx;
+ enum oci_verify_result res;
if (wpa_channel_info(wpa_auth, &ci) != 0) {
wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
&tx_seg1_idx) < 0)
return;
- if (ocv_verify_tx_params(kde.oci, kde.oci_len, &ci,
- tx_chanwidth, tx_seg1_idx) !=
- OCI_SUCCESS) {
+ res = ocv_verify_tx_params(kde.oci, kde.oci_len, &ci,
+ tx_chanwidth, tx_seg1_idx);
+ if (wpa_auth_uses_ocv(sm) == 2 && res == OCI_NOT_FOUND) {
+ /* Work around misbehaving STAs */
+ wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
+ "Disable OCV with a STA that does not send OCI");
+ wpa_auth_set_ocv(sm, 0);
+ } else if (res != OCI_SUCCESS) {
wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
"OCV failed: %s", ocv_errorstr);
if (wpa_auth->conf.msg_ctx)
struct wpa_channel_info ci;
int tx_chanwidth;
int tx_seg1_idx;
+ enum oci_verify_result res;
if (wpa_channel_info(sm->wpa_auth, &ci) != 0) {
wpa_printf(MSG_WARNING,
&tx_seg1_idx) < 0)
return WLAN_STATUS_UNSPECIFIED_FAILURE;
- if (ocv_verify_tx_params(parse.oci, parse.oci_len, &ci,
- tx_chanwidth, tx_seg1_idx) !=
- OCI_SUCCESS) {
+ res = ocv_verify_tx_params(parse.oci, parse.oci_len, &ci,
+ tx_chanwidth, tx_seg1_idx);
+ if (wpa_auth_uses_ocv(sm) == 2 && res == OCI_NOT_FOUND) {
+ /* Work around misbehaving STAs */
+ wpa_printf(MSG_INFO,
+ "Disable OCV with a STA that does not send OCI");
+ wpa_auth_set_ocv(sm, 0);
+ } else if (res != OCI_SUCCESS) {
wpa_printf(MSG_WARNING, "OCV failed: %s", ocv_errorstr);
if (sm->wpa_auth->conf.msg_ctx)
wpa_msg(sm->wpa_auth->conf.msg_ctx, MSG_INFO,
#endif /* CONFIG_IEEE80211R_AP */
unsigned int is_wnmsleep:1;
unsigned int pmkid_set:1;
+
#ifdef CONFIG_OCV
- unsigned int ocv_enabled:1;
+ int ocv_enabled;
#endif /* CONFIG_OCV */
u8 req_replay_counter[WPA_REPLAY_COUNTER_LEN];
#ifdef CONFIG_OCV
if (wpa_auth->conf.ocv && (data.capabilities & WPA_CAPABILITY_OCVC) &&
!(data.capabilities & WPA_CAPABILITY_MFPC)) {
- wpa_printf(MSG_DEBUG,
- "Management frame protection required with OCV, but client did not enable it");
- return WPA_MGMT_FRAME_PROTECTION_VIOLATION;
+ /* Some legacy MFP incapable STAs wrongly copy OCVC bit from
+ * AP RSN capabilities. To improve interoperability with such
+ * legacy STAs allow connection without enabling OCV when the
+ * workaround mode (ocv=2) is enabled.
+ */
+ if (wpa_auth->conf.ocv == 2) {
+ wpa_printf(MSG_DEBUG,
+ "Allow connecting MFP incapable and OCV capable STA without enabling OCV");
+ wpa_auth_set_ocv(sm, 0);
+ } else {
+ wpa_printf(MSG_DEBUG,
+ "Management frame protection required with OCV, but client did not enable it");
+ return WPA_MGMT_FRAME_PROTECTION_VIOLATION;
+ }
+ } else {
+ wpa_auth_set_ocv(sm, (data.capabilities & WPA_CAPABILITY_OCVC) ?
+ wpa_auth->conf.ocv : 0);
}
- wpa_auth_set_ocv(sm, wpa_auth->conf.ocv &&
- (data.capabilities & WPA_CAPABILITY_OCVC));
#endif /* CONFIG_OCV */
if (wpa_auth->conf.ieee80211w == NO_MGMT_FRAME_PROTECTION ||