diff --git a/src/common/dpp.c b/src/common/dpp.c index 4b21254cd..361a9d7dd 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -3294,7 +3294,6 @@ static int dpp_parse_cred_legacy(struct dpp_authentication *auth, struct json_token *cred) { struct json_token *pass, *psk_hex; - u8 psk[32]; wpa_printf(MSG_DEBUG, "DPP: Legacy akm=psk credential"); @@ -3302,16 +3301,23 @@ static int dpp_parse_cred_legacy(struct dpp_authentication *auth, psk_hex = json_get_member(cred, "psk_hex"); if (pass && pass->type == JSON_STRING) { + size_t len = os_strlen(pass->string); + wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Legacy passphrase", - pass->string, os_strlen(pass->string)); + pass->string, len); + if (len < 8 || len > 63) + return -1; + os_strlcpy(auth->passphrase, pass->string, + sizeof(auth->passphrase)); } else if (psk_hex && psk_hex->type == JSON_STRING) { - if (os_strlen(psk_hex->string) != sizeof(psk) * 2 || - hexstr2bin(psk_hex->string, psk, sizeof(psk)) < 0) { + if (os_strlen(psk_hex->string) != PMK_LEN * 2 || + hexstr2bin(psk_hex->string, auth->psk, PMK_LEN) < 0) { wpa_printf(MSG_DEBUG, "DPP: Invalid psk_hex encoding"); return -1; } - wpa_hexdump_key(MSG_DEBUG, "DPP: Legacy PSK", psk, sizeof(psk)); - os_memset(psk, 0, sizeof(psk)); + wpa_hexdump_key(MSG_DEBUG, "DPP: Legacy PSK", + auth->psk, PMK_LEN); + auth->psk_set = 1; } else { wpa_printf(MSG_DEBUG, "DPP: No pass or psk_hex strings found"); return -1; diff --git a/src/common/dpp.h b/src/common/dpp.h index 9cf4a13fe..76d7b2553 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -154,6 +154,9 @@ struct dpp_authentication { char *connector; /* received signedConnector */ u8 ssid[SSID_MAX_LEN]; u8 ssid_len; + char passphrase[64]; + u8 psk[PMK_LEN]; + int psk_set; struct wpabuf *net_access_key; os_time_t net_access_key_expiry; struct wpabuf *c_sign_key; diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h index c715743f3..f7b063a5c 100644 --- a/src/common/wpa_ctrl.h +++ b/src/common/wpa_ctrl.h @@ -156,6 +156,7 @@ extern "C" { #define DPP_EVENT_C_SIGN_KEY "DPP-C-SIGN-KEY " #define DPP_EVENT_NET_ACCESS_KEY "DPP-NET-ACCESS-KEY " #define DPP_EVENT_MISSING_CONNECTOR "DPP-MISSING-CONNECTOR " +#define DPP_EVENT_NETWORK_ID "DPP-NETWORK-ID " /* MESH events */ #define MESH_GROUP_STARTED "MESH-GROUP-STARTED " diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 8bf4b38d9..a89bf90be 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -4577,6 +4577,7 @@ static const struct global_parse_data global_fields[] = { { INT_RANGE(ftm_initiator, 0, 1), 0 }, { INT(gas_rand_addr_lifetime), 0 }, { INT_RANGE(gas_rand_mac_addr, 0, 2), 0 }, + { INT_RANGE(dpp_config_processing, 0, 2), 0 }, }; #undef FUNC diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index c883c18c3..b42993961 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -1366,6 +1366,21 @@ struct wpa_config { * 2 = like 1, but maintain OUI (with local admin bit set) */ int gas_rand_mac_addr; + + /** + * dpp_config_processing - How to process DPP configuration + * + * 0 = report received configuration to an external program for + * processing; do not generate any network profile internally + * 1 = report received configuration to an external program and generate + * a network profile internally, but do not automatically connect + * to the created (disabled) profile; the network profile id is + * reported to external programs + * 2 = report received configuration to an external program, generate + * a network profile internally, try to connect to the created + * profile automatically + */ + int dpp_config_processing; }; diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index dead8ad1f..7de043821 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -1455,6 +1455,9 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) config->gas_rand_addr_lifetime); if (config->gas_rand_mac_addr) fprintf(f, "gas_rand_mac_addr=%d\n", config->gas_rand_mac_addr); + if (config->dpp_config_processing) + fprintf(f, "dpp_config_processing=%d\n", + config->dpp_config_processing); } diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index bd0ffa4d9..edc61baf7 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -22,6 +22,7 @@ #include "gas_query.h" #include "bss.h" #include "scan.h" +#include "notify.h" #include "dpp_supplicant.h" @@ -819,6 +820,102 @@ static void wpas_dpp_start_gas_server(struct wpa_supplicant *wpa_s) } +static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s, + struct dpp_authentication *auth) +{ + struct wpa_ssid *ssid; + + ssid = wpa_config_add_network(wpa_s->conf); + if (!ssid) + return NULL; + wpas_notify_network_added(wpa_s, ssid); + wpa_config_set_network_defaults(ssid); + ssid->disabled = 1; + + ssid->ssid = os_malloc(auth->ssid_len); + if (!ssid->ssid) + goto fail; + os_memcpy(ssid->ssid, auth->ssid, auth->ssid_len); + ssid->ssid_len = auth->ssid_len; + + if (auth->connector) { + ssid->key_mgmt = WPA_KEY_MGMT_DPP; + ssid->dpp_connector = os_strdup(auth->connector); + if (!ssid->dpp_connector) + goto fail; + } + + if (auth->c_sign_key) { + ssid->dpp_csign = os_malloc(wpabuf_len(auth->c_sign_key)); + if (!ssid->dpp_csign) + goto fail; + os_memcpy(ssid->dpp_csign, wpabuf_head(auth->c_sign_key), + wpabuf_len(auth->c_sign_key)); + ssid->dpp_csign_len = wpabuf_len(auth->c_sign_key); + ssid->dpp_csign_expiry = auth->c_sign_key_expiry; + } + + if (auth->net_access_key) { + ssid->dpp_netaccesskey = + os_malloc(wpabuf_len(auth->net_access_key)); + if (!ssid->dpp_netaccesskey) + goto fail; + os_memcpy(ssid->dpp_netaccesskey, + wpabuf_head(auth->net_access_key), + wpabuf_len(auth->net_access_key)); + ssid->dpp_netaccesskey_len = wpabuf_len(auth->net_access_key); + ssid->dpp_netaccesskey_expiry = auth->net_access_key_expiry; + } + + if (!auth->connector) { + ssid->key_mgmt = WPA_KEY_MGMT_PSK; + if (auth->passphrase[0]) { + if (wpa_config_set_quoted(ssid, "psk", + auth->passphrase) < 0) + goto fail; + wpa_config_update_psk(ssid); + ssid->export_keys = 1; + } else { + ssid->psk_set = auth->psk_set; + os_memcpy(ssid->psk, auth->psk, PMK_LEN); + } + } + + return ssid; +fail: + wpas_notify_network_removed(wpa_s, ssid); + wpa_config_remove_network(wpa_s->conf, ssid->id); + return NULL; +} + + +static void wpas_dpp_process_config(struct wpa_supplicant *wpa_s, + struct dpp_authentication *auth) +{ + struct wpa_ssid *ssid; + + if (wpa_s->conf->dpp_config_processing < 1) + return; + + ssid = wpas_dpp_add_network(wpa_s, auth); + if (!ssid) + return; + + wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_NETWORK_ID "%d", ssid->id); + if (wpa_s->conf->dpp_config_processing < 2) + return; + + wpa_printf(MSG_DEBUG, "DPP: Trying to connect to the new network"); + ssid->disabled = 0; + wpa_s->disconnected = 0; + wpa_s->reassociate = 1; + wpa_s->scan_runs = 0; + wpa_s->normal_scans = 0; + wpa_supplicant_cancel_sched_scan(wpa_s); + wpa_supplicant_req_scan(wpa_s, 0, 0); +} + + static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token, enum gas_query_result result, const struct wpabuf *adv_proto, @@ -916,6 +1013,9 @@ static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token, os_free(hex); } } + + wpas_dpp_process_config(wpa_s, auth); + dpp_auth_deinit(wpa_s->dpp_auth); wpa_s->dpp_auth = NULL; return;