]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
DPP: Automatic network profile creation
authorJouni Malinen <jouni@qca.qualcomm.com>
Wed, 21 Jun 2017 15:01:51 +0000 (18:01 +0300)
committerJouni Malinen <j@w1.fi>
Wed, 21 Jun 2017 15:03:34 +0000 (18:03 +0300)
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>
src/common/dpp.c
src/common/dpp.h
src/common/wpa_ctrl.h
wpa_supplicant/config.c
wpa_supplicant/config.h
wpa_supplicant/config_file.c
wpa_supplicant/dpp_supplicant.c

index 4b21254cd013eae8082575715e35eea23bb1a7e2..361a9d7dd369d940081057cbd969a350b50ebaf4 100644 (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;
index 9cf4a13fe51886a1c99c80b8d607326314507b49..76d7b2553811cf23550e405bfb958792d76d5dd1 100644 (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;
index c715743f3ef24cc44910ec04b2d437dbcdbb4ae1..f7b063a5c74e98c4ffd462ce3821e43fcdef26ba 100644 (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 "
index 8bf4b38d96cf3358abc8519615e3749b155a9a56..a89bf90bea42dc944a26e5c66024b653b5d8ead4 100644 (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
index c883c18c3845fbe26da6cc33738dcb5af5039e2e..b429939617e05cc92d87315826227f420f5173df 100644 (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;
 };
 
 
index dead8ad1f688416b9bf92c48e2b0c59342c26c03..7de043821a9582b578ca8fc2c42cf8d289f17e20 100644 (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);
 
 }
 
index bd0ffa4d9ae82eb33b87e06aecf56ec489fe0597..edc61baf7ab954d0aca85878273e780254374236 100644 (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;