]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
P2P2: SSID randomization on group reinvoke
authorVinay Gannevaram <quic_vganneva@quicinc.com>
Sat, 11 Jan 2025 06:08:10 +0000 (11:38 +0530)
committerJouni Malinen <j@w1.fi>
Fri, 24 Jan 2025 09:22:40 +0000 (11:22 +0200)
P2P R2 allows the GO to randomize SSID and Group BSSID when a group is
reinvoked. Add support to fetch the group details based on the device
identity block info of the peer with which the group reinvoke is
initiated. As the previous SSID of the network is no longer valid, fetch
the network details based on the ID of the device identity block.

Signed-off-by: Vinay Gannevaram <quic_vganneva@quicinc.com>
src/p2p/p2p.c
src/p2p/p2p.h
src/p2p/p2p_i.h
src/p2p/p2p_invitation.c
wpa_supplicant/config.c
wpa_supplicant/config.h
wpa_supplicant/p2p_supplicant.c

index 1afdc0ad6945cd054ec7a4a08b7a854066e5f982..8ff26dc65b5851062f037d743e2fe595549e02a3 100644 (file)
@@ -4304,7 +4304,8 @@ static void p2p_timeout_invite_listen(struct p2p_data *p2p)
                        p2p_dbg(p2p, "Invitation Request retry limit reached");
                        if (p2p->cfg->invitation_result)
                                p2p->cfg->invitation_result(
-                                       p2p->cfg->cb_ctx, -1, NULL, NULL,
+                                       p2p->cfg->cb_ctx, -1, NULL, 0, NULL,
+                                       NULL,
                                        p2p->invite_peer->info.p2p_device_addr,
                                        0, 0, NULL, NULL, 0);
                }
@@ -6197,6 +6198,18 @@ void p2p_process_usd_elems(struct p2p_data *p2p, const u8 *ies, u16 ies_len,
 }
 
 
+int p2p_get_dik_id(struct p2p_data *p2p, const u8 *peer)
+{
+       struct p2p_device *dev;
+
+       dev = p2p_get_device(p2p, peer);
+       if (!dev)
+               return 0;
+
+       return dev->info.dik_id;
+}
+
+
 #ifdef CONFIG_PASN
 
 int p2p_config_sae_password(struct p2p_data *p2p, const char *pw)
index 8203a68ae62cdd127fed5a157f8d6dc0b59c457b..0089d784a1efea0622216258d0366d25779e334c 100644 (file)
@@ -1091,6 +1091,8 @@ struct p2p_config {
         *      used
         * @p2p2: Whether invitation request was wrapped in PASN authentication
         * received from a P2P2 device
+        * @new_ssid: Pointer to hold new SSID
+        * @new_ssid_len: Length of new SSID buffer in octets
         * Returns: Status code (P2P_SC_*)
         *
         * This optional callback can be used to implement persistent reconnect
@@ -1113,7 +1115,8 @@ struct p2p_config {
                                 size_t ssid_len, int *go, u8 *group_bssid,
                                 int *force_freq, int persistent_group,
                                 const struct p2p_channels *channels,
-                                int dev_pw_id, bool p2p2);
+                                int dev_pw_id, bool p2p2, const u8 **new_ssid,
+                                size_t *new_ssid_len);
 
        /**
         * invitation_received - Callback on Invitation Request RX
@@ -1142,6 +1145,8 @@ struct p2p_config {
         * invitation_result - Callback on Invitation result
         * @ctx: Callback context from cb_ctx
         * @status: Negotiation result (Status Code)
+        * @new_ssid: New SSID received in invitation response
+        * @new_ssid_len: Length of new SSID received
         * @bssid: P2P Group BSSID or %NULL if not received
         * @channels: Available operating channels for the group
         * @addr: Peer address
@@ -1155,7 +1160,8 @@ struct p2p_config {
         * (P2P_SC_SUCCESS) indicating success or -1 to indicate a timeout or a
         * local failure in transmitting the Invitation Request.
         */
-       void (*invitation_result)(void *ctx, int status, const u8 *bssid,
+       void (*invitation_result)(void *ctx, int status, const u8 *new_ssid,
+                                 size_t new_ssid_len, const u8 *bssid,
                                  const struct p2p_channels *channels,
                                  const u8 *addr, int freq, int peer_oper_freq,
                                  const u8 *pmkid, const u8 *pmk,
@@ -2734,6 +2740,7 @@ int p2p_channel_to_freq(int op_class, int channel);
 struct wpabuf * p2p_usd_elems(struct p2p_data *p2p);
 void p2p_process_usd_elems(struct p2p_data *p2p, const u8 *ies, u16 ies_len,
                           const u8 *peer_addr, unsigned int freq);
+int p2p_get_dik_id(struct p2p_data *p2p, const u8 *peer);
 
 void p2p_set_pairing_setup(struct p2p_data *p2p, int pairing_setup);
 void p2p_set_pairing_cache(struct p2p_data *p2p, int pairing_cache);
index 4b0be618a20b7d853f9555b95ecf32a75241cf99..a2b763b9f40f55a0cfa0705d8474e61d1c16b701 100644 (file)
@@ -203,6 +203,8 @@ struct p2p_device {
        int inv_freq;
        int inv_peer_oper_freq;
        u8 inv_bssid[ETH_ALEN];
+       u8 inv_ssid[SSID_MAX_LEN];
+       size_t inv_ssid_len;
        bool inv_all_channels;
 };
 
index 766b63e6510ab7ea1fce8df7fce2c317759b19c0..90c4f63bb0aede5dd0736cf257303c8bbbd711f1 100644 (file)
@@ -117,7 +117,9 @@ static struct wpabuf * p2p_build_invitation_resp(struct p2p_data *p2p,
                                                 u8 dialog_token, u8 status,
                                                 const u8 *group_bssid,
                                                 u8 reg_class, u8 channel,
-                                                struct p2p_channels *channels)
+                                                struct p2p_channels *channels,
+                                                const u8 *ssid,
+                                                size_t ssid_len)
 {
        struct wpabuf *buf;
        u8 *len;
@@ -162,6 +164,18 @@ static struct wpabuf * p2p_build_invitation_resp(struct p2p_data *p2p,
                                              reg_class, channel);
        if (group_bssid)
                p2p_buf_add_group_bssid(buf, group_bssid);
+
+       if (ssid_len && ssid) {
+               const u8 *dev_addr;
+
+               if (p2p->inv_role == P2P_INVITE_ROLE_CLIENT)
+                       dev_addr = peer->info.p2p_device_addr;
+               else
+                       dev_addr = p2p->cfg->dev_addr;
+
+               p2p_buf_add_group_id(buf, dev_addr, ssid, ssid_len);
+       }
+
        if (channels) {
                bool is_6ghz_capab;
 
@@ -196,6 +210,8 @@ struct wpabuf * p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa,
        u8 group_bssid[ETH_ALEN], *bssid;
        int op_freq = 0;
        u8 reg_class = 0, channel = 0;
+       const u8 *new_ssid;
+       size_t new_ssid_len = 0;
        struct p2p_channels all_channels, intersection, *channels = NULL;
        int persistent;
 
@@ -272,7 +288,7 @@ struct wpabuf * p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa,
                        msg.group_id + ETH_ALEN, msg.group_id_len - ETH_ALEN,
                        &go, group_bssid, &op_freq, persistent, &intersection,
                        msg.dev_password_id_present ? msg.dev_password_id : -1,
-                       p2p2);
+                       p2p2, &new_ssid, &new_ssid_len);
        }
 
        if (go) {
@@ -401,7 +417,8 @@ fail:
        else
                bssid = NULL;
        resp = p2p_build_invitation_resp(p2p, dev, msg.dialog_token, status,
-                                        bssid, reg_class, channel, channels);
+                                        bssid, reg_class, channel, channels,
+                                        new_ssid, new_ssid_len);
 
        /*
         * Store copy of invitation data to be used when processing TX status
@@ -413,7 +430,12 @@ fail:
                p2p->inv_group_bssid_ptr = p2p->inv_group_bssid;
        } else
                p2p->inv_group_bssid_ptr = NULL;
-       if (msg.group_id) {
+
+       if (p2p2 && new_ssid_len) {
+               os_memcpy(p2p->inv_ssid, new_ssid, new_ssid_len);
+               p2p->inv_ssid_len = new_ssid_len;
+               os_memcpy(p2p->inv_go_dev_addr, p2p->cfg->dev_addr, ETH_ALEN);
+       } else if (msg.group_id) {
                if (msg.group_id_len - ETH_ALEN <= SSID_MAX_LEN) {
                        os_memcpy(p2p->inv_ssid, msg.group_id + ETH_ALEN,
                                  msg.group_id_len - ETH_ALEN);
@@ -593,10 +615,17 @@ void p2p_process_invitation_resp(struct p2p_data *p2p, const u8 *sa,
                        if (msg.group_bssid)
                                os_memcpy(dev->inv_bssid, msg.group_bssid,
                                          ETH_ALEN);
+                       if (msg.group_id) {
+                               dev->inv_ssid_len = msg.group_id_len - ETH_ALEN;
+                               os_memcpy(dev->inv_ssid,
+                                         msg.group_id + ETH_ALEN,
+                                         dev->inv_ssid_len);
+                       }
                        goto out;
                }
 
                p2p->cfg->invitation_result(p2p->cfg->cb_ctx, *msg.status,
+                                           NULL, 0,
                                            msg.group_bssid, channels, sa,
                                            freq, peer_oper_freq, NULL, NULL,
                                            0);
@@ -638,6 +667,7 @@ void p2p_start_invitation_connect(struct p2p_data *p2p, struct p2p_device *dev)
        p2p_dbg(p2p, "Invitation connect: msg status %d", dev->inv_status);
        if (p2p->cfg->invitation_result)
                p2p->cfg->invitation_result(p2p->cfg->cb_ctx, dev->inv_status,
+                                           dev->inv_ssid, dev->inv_ssid_len,
                                            dev->inv_bssid, inv_channels,
                                            dev->info.p2p_device_addr,
                                            dev->inv_freq,
@@ -650,6 +680,8 @@ void p2p_start_invitation_connect(struct p2p_data *p2p, struct p2p_device *dev)
 
        p2p_clear_timeout(p2p);
        p2p_set_state(p2p, P2P_IDLE);
+       os_memset(dev->inv_ssid, 0, sizeof(dev->inv_ssid));
+       dev->inv_ssid_len = 0;
        p2p->invite_peer = NULL;
 }
 #endif /* CONFIG_PASN */
index 551701af5221dff541c6aff899e99b3215368d41..6dfb3165a9872e5fa38a8d98553403bcfb664a31 100644 (file)
@@ -3190,6 +3190,35 @@ struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id)
 }
 
 
+#ifdef CONFIG_P2P
+/**
+ * wpa_config_get_network_with_dik_id - Get configured network based on ID of
+ *     device identity block
+ * @config: Configuration data from wpa_config_read()
+ * @dik_id: DIK ID to search for
+ * Returns: Network configuration or %NULL if not found
+ */
+struct wpa_ssid * wpa_config_get_network_with_dik_id(struct wpa_config *config,
+                                                    int dik_id)
+{
+       struct wpa_ssid *ssid;
+
+       for (ssid = config->ssid; ssid; ssid = ssid->next) {
+               if (ssid->disabled != 2)
+                       continue;
+
+               if (ssid->go_dik_id == dik_id)
+                       return ssid;
+
+               if (int_array_includes(ssid->p2p2_client_list, dik_id))
+                       return ssid;
+       }
+
+       return NULL;
+}
+#endif /* CONFIG_P2P */
+
+
 /**
  * wpa_config_add_network - Add a new network with empty configuration
  * @config: Configuration data from wpa_config_read()
index 8dac97932ee8da9f56d3fea7202654d01c73d23b..ca227a82e59769f6e15b64df4841520d85047a3d 100644 (file)
@@ -1921,6 +1921,8 @@ void wpa_config_foreach_network(struct wpa_config *config,
                                void (*func)(void *, struct wpa_ssid *),
                                void *arg);
 struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id);
+struct wpa_ssid * wpa_config_get_network_with_dik_id(struct wpa_config *config,
+                                                    int dik_id);
 struct wpa_ssid * wpa_config_add_network(struct wpa_config *config);
 int wpa_config_remove_network(struct wpa_config *config, int id);
 void wpa_config_set_network_defaults(struct wpa_ssid *ssid);
index 95f4e4e62c3c6fb1609f7225d3f694b6b5faef34..8d472f0d605105dc760be220b95fcb5a13ffb4c4 100644 (file)
@@ -3665,7 +3665,8 @@ static u8 wpas_invitation_process(void *ctx, const u8 *sa, const u8 *bssid,
                                  size_t ssid_len, int *go, u8 *group_bssid,
                                  int *force_freq, int persistent_group,
                                  const struct p2p_channels *channels,
-                                 int dev_pw_id, bool p2p2)
+                                 int dev_pw_id, bool p2p2, const u8 **new_ssid,
+                                 size_t *new_ssid_len)
 {
        struct wpa_supplicant *wpa_s = ctx;
        struct wpa_ssid *s;
@@ -3735,7 +3736,41 @@ static u8 wpas_invitation_process(void *ctx, const u8 *sa, const u8 *bssid,
                        break;
        }
 
-       if (!s) {
+       if (p2p2) {
+               int dik_id;
+               u8 go_ssid[SSID_MAX_LEN];
+
+               dik_id = p2p_get_dik_id(wpa_s->global->p2p, sa);
+               s = wpa_config_get_network_with_dik_id(wpa_s->conf, dik_id);
+               if (!s) {
+                       wpa_printf(MSG_DEBUG, "P2P2: Invitation from " MACSTR
+                                  " requested reinvocation of an unknown group",
+                                  MAC2STR(sa));
+                       return P2P_SC_FAIL_UNKNOWN_GROUP;
+               }
+               os_free(s->ssid);
+               if (s->mode == WPAS_MODE_P2P_GO) {
+                       p2p_build_ssid(wpa_s->global->p2p, go_ssid,
+                                      &s->ssid_len);
+                       s->ssid = os_memdup(go_ssid, s->ssid_len);
+                       if (!s->ssid) {
+                               s->ssid_len = 0;
+                               return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
+                       }
+                       wpa_printf(MSG_DEBUG,
+                                  "P2P: New random SSID for the group: %s",
+                                  wpa_ssid_txt(s->ssid, s->ssid_len));
+                       *new_ssid = s->ssid;
+                       *new_ssid_len = s->ssid_len;
+               } else {
+                       s->ssid_len = ssid_len;
+                       s->ssid = os_memdup(ssid, ssid_len);
+                       if (!s->ssid) {
+                               s->ssid_len = 0;
+                               return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
+                       }
+               }
+       } else if (!s) {
                wpa_printf(MSG_DEBUG, "P2P: Invitation from " MACSTR
                           " requested reinvocation of an unknown group",
                           MAC2STR(sa));
@@ -3980,7 +4015,8 @@ static void wpas_remove_persistent_client(struct wpa_supplicant *wpa_s,
 }
 
 
-static void wpas_invitation_result(void *ctx, int status, const u8 *bssid,
+static void wpas_invitation_result(void *ctx, int status, const u8 *new_ssid,
+                                  size_t new_ssid_len, const u8 *bssid,
                                   const struct p2p_channels *channels,
                                   const u8 *peer, int neg_freq,
                                   int peer_oper_freq, const u8 *pmkid,
@@ -4067,6 +4103,16 @@ static void wpas_invitation_result(void *ctx, int status, const u8 *bssid,
                return;
        }
 
+       if (new_ssid && new_ssid_len) {
+               os_free(ssid->ssid);
+               ssid->ssid = os_memdup(new_ssid, new_ssid_len);
+               if (!ssid->ssid) {
+                       ssid->ssid_len = 0;
+                       return;
+               }
+               ssid->ssid_len = new_ssid_len;
+       }
+
        /*
         * The peer could have missed our ctrl::ack frame for Invitation
         * Response and continue retransmitting the frame. To reduce the
@@ -8674,6 +8720,19 @@ int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
        else
                os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
 
+       if (wpa_s->global->p2p && p2p2 && !ssid && peer_addr) {
+               int dik_id;
+
+               dik_id = p2p_get_dik_id(wpa_s->global->p2p, peer_addr);
+               ssid = wpa_config_get_network_with_dik_id(wpa_s->conf, dik_id);
+               if (!ssid) {
+                       wpa_printf(MSG_DEBUG,
+                                  "P2P: Could not find SSID for P2P2 peer "
+                                  MACSTR, MAC2STR(peer_addr));
+                       return -1;
+               }
+       }
+
        wpa_s->p2p_persistent_go_freq = freq;
        wpa_s->p2p_go_ht40 = !!ht40;
        wpa_s->p2p_go_vht = !!vht;