wpa_printf(MSG_DEBUG, "DPP: Set configurator parameters: %s", cmd);
+ if (os_strstr(cmd, " conf=query")) {
+ auth->configurator_set = 0;
+ auth->use_config_query = true;
+ ret = 0;
+ goto fail;
+ }
+
pos = os_strstr(cmd, " configurator=");
if (!auth->conf && pos) {
pos += 14;
}
+static int dpp_get_peer_bi_id(struct dpp_authentication *auth)
+{
+ struct dpp_bootstrap_info *bi;
+
+ if (auth->peer_bi)
+ return auth->peer_bi->id;
+ if (auth->tmp_peer_bi)
+ return auth->tmp_peer_bi->id;
+
+ bi = os_zalloc(sizeof(*bi));
+ if (!bi)
+ return -1;
+ bi->id = dpp_next_id(auth->global);
+ dl_list_add(&auth->global->bootstrap, &bi->list);
+ auth->tmp_peer_bi = bi;
+ return bi->id;
+}
+
+
static struct wpabuf *
dpp_build_conf_obj(struct dpp_authentication *auth, enum dpp_netrole netrole,
int idx, bool cert_req)
conf = auth->conf2_ap;
}
if (!conf) {
- if (idx == 0)
+ if (idx == 0) {
+ if (auth->use_config_query) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: No configuration available for Enrollee(%s) - waiting for configuration",
+ dpp_netrole_str(netrole));
+ auth->waiting_config = true;
+ dpp_get_peer_bi_id(auth);
+ return NULL;
+ }
wpa_printf(MSG_DEBUG,
"DPP: No configuration available for Enrollee(%s) - reject configuration request",
dpp_netrole_str(netrole));
+ }
return NULL;
}
}
}
+ if (!conf && auth->waiting_config)
+ return NULL;
if (conf || env_data)
status = DPP_STATUS_OK;
else if (!cert_req && netrole == DPP_NETROLE_STA && auth->conf_sta &&
goto cont;
}
- if (auth->peer_bi) {
- id = auth->peer_bi->id;
- } else if (auth->tmp_peer_bi) {
- id = auth->tmp_peer_bi->id;
- } else {
- struct dpp_bootstrap_info *bi;
-
- bi = os_zalloc(sizeof(*bi));
- if (!bi)
- goto fail;
- bi->id = dpp_next_id(auth->global);
- dl_list_add(&auth->global->bootstrap, &bi->list);
- auth->tmp_peer_bi = bi;
- id = bi->id;
- }
+ id = dpp_get_peer_bi_id(auth);
+ if (id < 0)
+ goto fail;
wpa_printf(MSG_DEBUG, "DPP: CSR is valid - forward to CA/RA");
txt = base64_encode_no_lf(wpabuf_head(cert_req),
WLAN_PA_GAS_INITIAL_RESP);
}
+ if (!resp && auth->waiting_config && auth->peer_bi) {
+ char *buf = NULL, *name = "";
+ char band[200], *b_pos, *b_end;
+ int i, res, *opclass = auth->e_band_support;
+ char *mud_url = "N/A";
+
+ wpa_printf(MSG_DEBUG, "DPP: Configuration not yet ready");
+ if (auth->e_name) {
+ size_t e_len = os_strlen(auth->e_name);
+
+ buf = os_malloc(e_len * 4 + 1);
+ if (buf) {
+ printf_encode(buf, len * 4 + 1,
+ (const u8 *) auth->e_name, e_len);
+ name = buf;
+ }
+ }
+ band[0] = '\0';
+ b_pos = band;
+ b_end = band + sizeof(band);
+ for (i = 0; opclass && opclass[i]; i++) {
+ res = os_snprintf(b_pos, b_end - b_pos, "%s%d",
+ b_pos == band ? "" : ",", opclass[i]);
+ if (os_snprintf_error(b_end - b_pos, res)) {
+ *b_pos = '\0';
+ break;
+ }
+ b_pos += res;
+ }
+ if (auth->e_mud_url) {
+ size_t e_len = os_strlen(auth->e_mud_url);
+
+ if (!has_ctrl_char((const u8 *) auth->e_mud_url, e_len))
+ mud_url = auth->e_mud_url;
+ }
+ wpa_msg(conn->msg_ctx, MSG_INFO, DPP_EVENT_CONF_NEEDED
+ "peer=%d net_role=%s name=\"%s\" opclass=%s mud_url=%s",
+ auth->peer_bi->id, dpp_netrole_str(auth->e_netrole),
+ name, band, mud_url);
+ os_free(buf);
+
+ conn->gas_comeback_in_progress = 1;
+ return dpp_tcp_send_comeback_delay(conn,
+ WLAN_PA_GAS_INITIAL_RESP);
+ }
+
return dpp_tcp_send_gas_resp(conn, WLAN_PA_GAS_INITIAL_RESP, resp);
}
}
+static void wpas_dpp_gas_initial_resp_timeout(void *eloop_ctx,
+ void *timeout_ctx)
+{
+ struct wpa_supplicant *wpa_s = eloop_ctx;
+ struct dpp_authentication *auth = wpa_s->dpp_auth;
+
+ if (!auth || !auth->waiting_config || !auth->config_resp_ctx)
+ return;
+
+ wpa_printf(MSG_DEBUG,
+ "DPP: No configuration available from upper layers - send initial response with comeback delay");
+ gas_server_set_comeback_delay(wpa_s->gas_server, auth->config_resp_ctx,
+ 500);
+}
+
+
static struct wpabuf *
wpas_dpp_gas_req_handler(void *ctx, void *resp_ctx, const u8 *sa,
const u8 *query, size_t query_len, int *comeback_delay)
MAC2STR(sa));
resp = dpp_conf_req_rx(auth, query, query_len);
+ auth->gas_server_ctx = resp_ctx;
+
#ifdef CONFIG_DPP2
if (!resp && auth->waiting_cert) {
wpa_printf(MSG_DEBUG, "DPP: Certificate not yet ready");
- auth->cert_resp_ctx = resp_ctx;
+ auth->config_resp_ctx = resp_ctx;
*comeback_delay = 500;
return NULL;
}
#endif /* CONFIG_DPP2 */
+ if (!resp && auth->waiting_config &&
+ (auth->peer_bi || auth->tmp_peer_bi)) {
+ char *buf = NULL, *name = "";
+ char band[200], *pos, *end;
+ int i, res, *opclass = auth->e_band_support;
+ char *mud_url = "N/A";
+
+ wpa_printf(MSG_DEBUG, "DPP: Configuration not yet ready");
+ auth->config_resp_ctx = resp_ctx;
+ *comeback_delay = -1;
+ if (auth->e_name) {
+ size_t len = os_strlen(auth->e_name);
+
+ buf = os_malloc(len * 4 + 1);
+ if (buf) {
+ printf_encode(buf, len * 4 + 1,
+ (const u8 *) auth->e_name, len);
+ name = buf;
+ }
+ }
+ band[0] = '\0';
+ pos = band;
+ end = band + sizeof(band);
+ for (i = 0; opclass && opclass[i]; i++) {
+ res = os_snprintf(pos, end - pos, "%s%d",
+ pos == band ? "" : ",", opclass[i]);
+ if (os_snprintf_error(end - pos, res)) {
+ *pos = '\0';
+ break;
+ }
+ pos += res;
+ }
+ if (auth->e_mud_url) {
+ size_t len = os_strlen(auth->e_mud_url);
+
+ if (!has_ctrl_char((const u8 *) auth->e_mud_url, len))
+ mud_url = auth->e_mud_url;
+ }
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_NEEDED "peer=%d src="
+ MACSTR " net_role=%s name=\"%s\" opclass=%s mud_url=%s",
+ auth->peer_bi ? auth->peer_bi->id :
+ auth->tmp_peer_bi->id, MAC2STR(sa),
+ dpp_netrole_str(auth->e_netrole), name, band, mud_url);
+ os_free(buf);
+
+ eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s,
+ NULL);
+ eloop_register_timeout(0, 50000,
+ wpas_dpp_gas_initial_resp_timeout, wpa_s,
+ NULL);
+ return NULL;
+ }
+
if (!resp)
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
auth->conf_resp = resp;
- auth->gas_server_ctx = resp_ctx;
return resp;
}
eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
+ eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s, NULL);
#ifdef CONFIG_DPP2
eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
}
+static int wpas_dpp_build_conf_resp(struct wpa_supplicant *wpa_s,
+ struct dpp_authentication *auth, bool tcp)
+{
+ struct wpabuf *resp;
+
+ resp = dpp_build_conf_resp(auth, auth->e_nonce, auth->curve->nonce_len,
+ auth->e_netrole, true);
+ if (!resp)
+ return -1;
+
+ if (tcp) {
+ auth->conf_resp_tcp = resp;
+ return 0;
+ }
+
+ eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s, NULL);
+ if (gas_server_set_resp(wpa_s->gas_server, auth->config_resp_ctx,
+ resp) < 0) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Could not find pending GAS response");
+ wpabuf_free(resp);
+ return -1;
+ }
+ auth->conf_resp = resp;
+ return 0;
+}
+
+
+int wpas_dpp_conf_set(struct wpa_supplicant *wpa_s, const char *cmd)
+{
+ int peer;
+ const char *pos;
+ struct dpp_authentication *auth = wpa_s->dpp_auth;
+ bool tcp = false;
+
+ pos = os_strstr(cmd, " peer=");
+ if (!pos)
+ return -1;
+ peer = atoi(pos + 6);
+#ifdef CONFIG_DPP2
+ if (!auth || !auth->waiting_config ||
+ (auth->peer_bi &&
+ (unsigned int) peer != auth->peer_bi->id)) {
+ auth = dpp_controller_get_auth(wpa_s->dpp, peer);
+ tcp = true;
+ }
+#endif /* CONFIG_DPP2 */
+
+ if (!auth || !auth->waiting_config) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: No authentication exchange waiting for configuration information");
+ return -1;
+ }
+
+ if ((!auth->peer_bi ||
+ (unsigned int) peer != auth->peer_bi->id) &&
+ (!auth->tmp_peer_bi ||
+ (unsigned int) peer != auth->tmp_peer_bi->id)) {
+ wpa_printf(MSG_DEBUG, "DPP: Peer mismatch");
+ return -1;
+ }
+
+ pos = os_strstr(cmd, " comeback=");
+ if (pos) {
+ eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s,
+ NULL);
+ gas_server_set_comeback_delay(wpa_s->gas_server,
+ auth->config_resp_ctx,
+ atoi(pos + 10));
+ return 0;
+ }
+
+ if (dpp_set_configurator(auth, cmd) < 0)
+ return -1;
+
+ auth->use_config_query = false;
+ auth->waiting_config = false;
+ return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
+}
+
+
#ifdef CONFIG_DPP2
int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd)
}
-static int wpas_dpp_build_conf_resp(struct wpa_supplicant *wpa_s,
- struct dpp_authentication *auth, bool tcp)
-{
- struct wpabuf *resp;
-
- resp = dpp_build_conf_resp(auth, auth->e_nonce, auth->curve->nonce_len,
- auth->e_netrole, true);
- if (!resp)
- return -1;
-
- if (tcp) {
- auth->conf_resp_tcp = resp;
- return 0;
- }
-
- if (gas_server_set_resp(wpa_s->gas_server, auth->cert_resp_ctx,
- resp) < 0) {
- wpa_printf(MSG_DEBUG,
- "DPP: Could not find pending GAS response");
- wpabuf_free(resp);
- return -1;
- }
- auth->conf_resp = resp;
- return 0;
-}
-
-
int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd)
{
int peer = -1;