DPP: Automatic network profile creation

wpa_supplicant can now be configured to generate a network profile
automatically based on DPP configuration. The following
dpp_config_processing values can be used to specify the behavior:
0 = report received configuration to an external program for
    processing; do not generate any network profile internally (default)
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

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Jouni Malinen 2017-06-21 18:01:51 +03:00 committed by Jouni Malinen
parent da143f7fb9
commit 8528994e21
7 changed files with 135 additions and 6 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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 "

View file

@ -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

View file

@ -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;
};

View file

@ -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);
}

View file

@ -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;