Browse Source

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>
Jouni Malinen 7 years ago
parent
commit
8528994e21

+ 12 - 6
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;

+ 3 - 0
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;

+ 1 - 0
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 "

+ 1 - 0
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

+ 15 - 0
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;
 };
 
 

+ 3 - 0
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);
 
 }
 

+ 100 - 0
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;