# to external program(s)
# Note: With wps_cred_processing=1, skip_cred_build should be set to 1 and
# extra_cred be used to provide the Credential data for Enrollees.
+#
+# wps_cred_processing=1 will disabled automatic updates of hostapd.conf file
+# both for Credential processing and for marking AP Setup Locked based on
+# validation failures of AP PIN. An external program is responsible on updating
+# the configuration appropriately in this case.
#wps_cred_processing=0
# AP Settings Attributes for M7
size_t wps_beacon_ie_len;
u8 *wps_probe_resp_ie;
size_t wps_probe_resp_ie_len;
+ unsigned int ap_pin_failures;
#endif /* CONFIG_WPS */
};
}
+static void hostapd_pwd_auth_fail(struct hostapd_data *hapd,
+ struct wps_event_pwd_auth_fail *data)
+{
+ FILE *f;
+
+ if (!data->enrollee)
+ return;
+
+ /*
+ * Registrar failed to prove its knowledge of the AP PIN. Lock AP setup
+ * if this happens multiple times.
+ */
+ hapd->ap_pin_failures++;
+ if (hapd->ap_pin_failures < 4)
+ return;
+
+ wpa_msg(hapd, MSG_INFO, WPS_EVENT_AP_SETUP_LOCKED);
+ hapd->wps->ap_setup_locked = 1;
+
+ wps_registrar_update_ie(hapd->wps->registrar);
+
+ if (hapd->conf->wps_cred_processing == 1)
+ return;
+
+ f = fopen(hapd->iface->config_fname, "a");
+ if (f == NULL) {
+ wpa_printf(MSG_WARNING, "WPS: Could not append to the current "
+ "configuration file");
+ return;
+ }
+
+ fprintf(f, "# WPS AP Setup Locked based on possible attack\n");
+ fprintf(f, "ap_setup_locked=1\n");
+ fclose(f);
+
+ /* TODO: dualband AP may need to update multiple configuration files */
+
+ wpa_printf(MSG_DEBUG, "WPS: AP configuration updated");
+}
+
+
+static void hostapd_wps_event_cb(void *ctx, enum wps_event event,
+ union wps_event_data *data)
+{
+ struct hostapd_data *hapd = ctx;
+
+ if (event == WPS_EV_PWD_AUTH_FAIL)
+ hostapd_pwd_auth_fail(hapd, &data->pwd_auth_fail);
+}
+
+
static void hostapd_wps_clear_ies(struct hostapd_data *hapd)
{
os_free(hapd->wps_beacon_ie);
return -1;
wps->cred_cb = hostapd_wps_cred_cb;
+ wps->event_cb = hostapd_wps_event_cb;
wps->cb_ctx = hapd;
os_memset(&cfg, 0, sizeof(cfg));
#define WPS_EVENT_PIN_NEEDED "WPS-PIN-NEEDED "
#define WPS_EVENT_NEW_AP_SETTINGS "WPS-NEW-AP-SETTINGS "
#define WPS_EVENT_REG_SUCCESS "WPS-REG-SUCCESS "
+#define WPS_EVENT_AP_SETUP_LOCKED "WPS-AP-SETUP-LOCKED "
/* wpa_supplicant/hostapd control interface access */
/**
* WPS_EV_SUCCESS - Registration succeeded
*/
- WPS_EV_SUCCESS
+ WPS_EV_SUCCESS,
+
+ /**
+ * WPS_EV_PWD_AUTH_FAIL - Password authentication failed
+ */
+ WPS_EV_PWD_AUTH_FAIL
};
/**
struct wps_event_fail {
int msg;
} fail;
+
+ struct wps_event_pwd_auth_fail {
+ int enrollee;
+ int part;
+ } pwd_auth_fail;
};
/**
int wps_registrar_button_pushed(struct wps_registrar *reg);
void wps_registrar_probe_req_rx(struct wps_registrar *reg, const u8 *addr,
const struct wpabuf *wps_data);
+int wps_registrar_update_ie(struct wps_registrar *reg);
unsigned int wps_pin_checksum(unsigned int pin);
unsigned int wps_pin_valid(unsigned int pin);
wps->event_cb(wps->cb_ctx, WPS_EV_SUCCESS, NULL);
}
+
+
+void wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part)
+{
+ union wps_event_data data;
+
+ if (wps->event_cb == NULL)
+ return;
+
+ os_memset(&data, 0, sizeof(data));
+ data.pwd_auth_fail.enrollee = enrollee;
+ data.pwd_auth_fail.part = part;
+ wps->event_cb(wps->cb_ctx, WPS_EV_PWD_AUTH_FAIL, &data);
+}
wpa_printf(MSG_DEBUG, "WPS: R-Hash1 derived from R-S1 does "
"not match with the pre-committed value");
wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE;
+ wps_pwd_auth_fail_event(wps->wps, 1, 1);
return -1;
}
wpa_printf(MSG_DEBUG, "WPS: R-Hash2 derived from R-S2 does "
"not match with the pre-committed value");
wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE;
+ wps_pwd_auth_fail_event(wps->wps, 1, 2);
return -1;
}
size_t encr_len);
void wps_fail_event(struct wps_context *wps, enum wps_msg_type msg);
void wps_success_event(struct wps_context *wps);
+void wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part);
/* wps_attr_parse.c */
int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr);
wpa_printf(MSG_DEBUG, "WPS: E-Hash1 derived from E-S1 does "
"not match with the pre-committed value");
wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE;
+ wps_pwd_auth_fail_event(wps->wps, 0, 1);
return -1;
}
"not match with the pre-committed value");
wps_registrar_invalidate_pin(wps->wps->registrar, wps->uuid_e);
wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE;
+ wps_pwd_auth_fail_event(wps->wps, 0, 2);
return -1;
}
return WPS_FAILURE;
}
}
+
+
+int wps_registrar_update_ie(struct wps_registrar *reg)
+{
+ return wps_set_ie(reg);
+}
case WPS_EV_SUCCESS:
wpa_supplicant_wps_event_success(wpa_s);
break;
+ case WPS_EV_PWD_AUTH_FAIL:
+ break;
}
}