DPP: Allow Configurator parameters to be provided during config exchange
This provides an alternative mechanism for upper layer components to control configuration parameters to be used by the local Configurator. Instead of the previously used design where the Configurator parameters had to be provided before initiating the DPP Authentication exchange, the new alternative approach allows the DPP Authentication exchange to be started before any Configurator parameters have been determined and wpa_supplicant will then request the parameters once the DPP Configuration Request has been received from the Enrollee. This allows the Config Request information to be used at upper layers to determine how the Enrollee should be configured. For example for an Initiator: CTRL: DPP_QR_CODE <URI from Responder/Enrollee> CTRL: DPP_AUTH_INIT peer=1 conf=query <3>DPP-CONF-NEEDED peer=1 src=02:00:00:00:00:00 net_role=sta name="Test" opclass=81,82,83,84,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130 mud_url=N/A (upper layer processing; potentially including user interaction) CTRL: DPP_CONF_SET peer=1 conf=sta-sae ssid=736165 pass=70617373776f7264 <3>DPP-CONF-SENT For example for a Responder: CTRL: SET dpp_configurator_params conf=query CTRL: DPP_LISTEN 2412 role=configurator <3>DPP-CONF-NEEDED peer=2 src=02:00:00:00:01:00 net_role=sta name="Test" opclass=81,82,83,84,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130 mud_url=N/A (upper layer processing; potentially including user interaction) CTRL: DPP_CONF_SET peer=2 conf=sta-sae ssid=736165 pass=70617373776f7264 <3>DPP-CONF-SENT For example for an Initiator that can act both as a Configurator and an Enrollee in a case where the Initiator becomes the Enrollee: CTRL: DPP_AUTH_INIT peer=1 role=either conf=query <3>DPP-CONF-RECEIVED Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
parent
d4961a7755
commit
033ad6ffaa
7 changed files with 250 additions and 46 deletions
|
@ -1209,6 +1209,13 @@ int dpp_set_configurator(struct dpp_authentication *auth, const char *cmd)
|
|||
|
||||
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;
|
||||
|
@ -1639,6 +1646,25 @@ dpp_build_conf_obj_legacy(struct dpp_authentication *auth,
|
|||
}
|
||||
|
||||
|
||||
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)
|
||||
|
@ -1667,10 +1693,19 @@ dpp_build_conf_obj(struct dpp_authentication *auth, enum dpp_netrole netrole,
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -1724,6 +1759,8 @@ dpp_build_conf_resp(struct dpp_authentication *auth, const u8 *e_nonce,
|
|||
}
|
||||
}
|
||||
|
||||
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 &&
|
||||
|
@ -2069,21 +2106,9 @@ dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start,
|
|||
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),
|
||||
|
|
|
@ -352,8 +352,10 @@ struct dpp_authentication {
|
|||
char *trusted_eap_server_name;
|
||||
struct wpabuf *cacert;
|
||||
struct wpabuf *certbag;
|
||||
void *cert_resp_ctx;
|
||||
void *config_resp_ctx;
|
||||
void *gas_server_ctx;
|
||||
bool use_config_query;
|
||||
bool waiting_config;
|
||||
char *e_name;
|
||||
char *e_mud_url;
|
||||
int *e_band_support;
|
||||
|
|
|
@ -1328,6 +1328,52 @@ static int dpp_controller_rx_gas_req(struct dpp_connection *conn, const u8 *msg,
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -212,6 +212,7 @@ extern "C" {
|
|||
#define DPP_EVENT_BAND_SUPPORT "DPP-BAND-SUPPORT "
|
||||
#define DPP_EVENT_CSR "DPP-CSR "
|
||||
#define DPP_EVENT_CHIRP_RX "DPP-CHIRP-RX "
|
||||
#define DPP_EVENT_CONF_NEEDED "DPP-CONF-NEEDED "
|
||||
|
||||
/* MESH events */
|
||||
#define MESH_GROUP_STARTED "MESH-GROUP-STARTED "
|
||||
|
|
|
@ -12334,6 +12334,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
|
|||
} else if (os_strncmp(buf, "DPP_PKEX_REMOVE ", 16) == 0) {
|
||||
if (wpas_dpp_pkex_remove(wpa_s, buf + 16) < 0)
|
||||
reply_len = -1;
|
||||
} else if (os_strncmp(buf, "DPP_CONF_SET ", 13) == 0) {
|
||||
if (wpas_dpp_conf_set(wpa_s, buf + 12) < 0)
|
||||
reply_len = -1;
|
||||
#ifdef CONFIG_DPP2
|
||||
} else if (os_strncmp(buf, "DPP_CONTROLLER_START ", 21) == 0) {
|
||||
if (wpas_dpp_controller_start(wpa_s, buf + 20) < 0)
|
||||
|
|
|
@ -3140,6 +3140,22 @@ void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
|
|||
}
|
||||
|
||||
|
||||
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)
|
||||
|
@ -3174,19 +3190,73 @@ wpas_dpp_gas_req_handler(void *ctx, void *resp_ctx, const u8 *sa,
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -3651,6 +3721,7 @@ void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
|
|||
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,
|
||||
|
@ -3676,6 +3747,87 @@ void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
|
|||
}
|
||||
|
||||
|
||||
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)
|
||||
|
@ -4094,33 +4246,6 @@ int wpas_dpp_reconfig(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;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* wpa_supplicant - DPP
|
||||
* Copyright (c) 2017, Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018-2020, The Linux Foundation
|
||||
* Copyright (c) 2022, Qualcomm Innovation Center, Inc.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
|
@ -41,5 +42,6 @@ int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd);
|
|||
void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s);
|
||||
int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, const char *cmd);
|
||||
int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd);
|
||||
int wpas_dpp_conf_set(struct wpa_supplicant *wpa_s, const char *cmd);
|
||||
|
||||
#endif /* DPP_SUPPLICANT_H */
|
||||
|
|
Loading…
Reference in a new issue