[PATCH v2 3/4] Clone SSID twins to enable encrypted catchall APs
Stefan Tomanek
stefan.tomanek
Sun Apr 26 06:43:29 PDT 2015
This change makes it possible to use encryption with catchall networks.
Upon associating a new client with a custom SSID, a new "twin" of the existing
ssid structure is created and keys are regenerated using the new SSID and the
existing origin configuration as a template. So multiple clones of the same
network can coexist using different SSID names - hence the term "twin".
Signed-off-by: Stefan Tomanek <stefan.tomanek at wertarbyte.de>
---
src/ap/ap_config.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++----
src/ap/ap_config.h | 12 ++++++++-
src/ap/beacon.c | 12 +++++++--
src/ap/ieee802_11.c | 7 ++++--
src/ap/sta_info.c | 6 +++++
src/ap/wpa_auth_glue.c | 2 +-
6 files changed, 95 insertions(+), 11 deletions(-)
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index cccbfab..553397b 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -18,6 +18,7 @@
#include "wpa_auth.h"
#include "sta_info.h"
#include "ap_config.h"
+#include "hostapd.h"
static void hostapd_config_free_vlan(struct hostapd_bss_config *bss)
@@ -314,10 +315,8 @@ static int hostapd_derive_psk(struct hostapd_ssid *ssid)
}
-int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf)
+static int hostapd_setup_wpa_ssid_psk(struct hostapd_ssid *ssid, struct hostapd_bss_config *conf)
{
- struct hostapd_ssid *ssid = &conf->ssid;
-
if (ssid->wpa_passphrase != NULL) {
if (ssid->wpa_psk != NULL) {
wpa_printf(MSG_DEBUG, "Using pre-configured WPA PSK "
@@ -340,6 +339,11 @@ int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf)
return 0;
}
+int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf)
+{
+ return hostapd_setup_wpa_ssid_psk(&conf->ssid, conf);
+}
+
static void hostapd_config_free_radius(struct hostapd_radius_server *servers,
int num_servers)
@@ -666,12 +670,17 @@ const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan, int vlan_id)
}
-const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
+const u8 * hostapd_get_psk(struct hostapd_data *hapd,
const u8 *addr, const u8 *p2p_dev_addr,
const u8 *prev_psk)
{
struct hostapd_wpa_psk *psk;
int next_ok = prev_psk == NULL;
+ struct hostapd_bss_config *conf = hapd->conf;
+ struct hostapd_ssid *ssid = &conf->ssid;
+ struct sta_info *sta = ap_get_sta(hapd, addr);
+ if (sta && sta->ssid)
+ ssid = sta->ssid;
if (p2p_dev_addr && !is_zero_ether_addr(p2p_dev_addr)) {
wpa_printf(MSG_DEBUG, "Searching a PSK for " MACSTR
@@ -684,7 +693,7 @@ const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
MAC2STR(addr), prev_psk);
}
- for (psk = conf->ssid.wpa_psk; psk != NULL; psk = psk->next) {
+ for (psk = ssid->wpa_psk; psk != NULL; psk = psk->next) {
if (next_ok &&
(psk->group ||
(addr && os_memcmp(psk->addr, addr, ETH_ALEN) == 0) ||
@@ -946,3 +955,51 @@ void hostapd_set_security_params(struct hostapd_bss_config *bss,
bss->wpa_key_mgmt = WPA_KEY_MGMT_NONE;
}
}
+
+#ifdef CONFIG_MULTI_SSID
+/**
+ * hostapd_clone_twin_ssid - Create a copy of an SSID struct
+ * @bss: The BSS to use as template for the cloning
+ * @ssid: The SSID identifier to use for the twin network
+ * @ssid_len: The length of the SSID identifier to be used
+ * Returns: The cloned hostapd_ssid struct.
+ *
+ * Create an independent copy of the hostapd_ssid struct used
+ * by the BSS instance and substitute the identifier; if a WPA
+ * passphrase is used, the new keys are derived using the new
+ * network identifier.
+ */
+struct hostapd_ssid * hostapd_clone_twin_ssid(struct hostapd_bss_config *bss,
+ const u8 *ssid, size_t ssid_len) {
+ /* clone ssid struct */
+ struct hostapd_ssid *orig = &bss->ssid;
+ struct hostapd_ssid *clone = os_zalloc(sizeof(*orig));
+ if (clone == NULL)
+ return NULL;
+ os_memcpy(clone, orig, sizeof(*orig));
+ clone->origin = orig;
+ /* insert new SSID */
+ os_memcpy(&clone->ssid, ssid, ssid_len);
+ clone->ssid_len = ssid_len;
+ /* clear and reinitialize WPA keys */
+ clone->wpa_psk = NULL;
+ hostapd_setup_wpa_ssid_psk(clone, bss);
+ return clone;
+}
+
+/**
+ * hostapd_free_cloned_ssid - Destroy a cloned SSID structure
+ * @ssid: The SSID structure to free
+ *
+ * Free the memory allocated for the hostapd_ssid structure
+ * and its contained WPA keys if the instance has been cloned
+ * instead of originating from the BSS config.
+ */
+void hostapd_free_cloned_ssid(struct hostapd_ssid *ssid) {
+ /* is this ssid a clone? */
+ if (!ssid || !ssid->origin)
+ return;
+ hostapd_config_clear_wpa_psk(&ssid->wpa_psk);
+ os_free(ssid);
+}
+#endif /* CONFIG_MULTI_SSID */
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 52359d5..dd99a85 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -15,6 +15,7 @@
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
#include "wps/wps.h"
+#include "sta_info.h"
/**
* mesh_conf - local MBSS state and settings
@@ -108,6 +109,10 @@ struct hostapd_ssid {
#ifdef CONFIG_FULL_DYNAMIC_VLAN
char *vlan_tagged_interface;
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
+
+#ifdef CONFIG_MULTI_SSID
+ struct hostapd_ssid *origin;
+#endif /* CONFIG_MULTI_SSID */
};
@@ -668,7 +673,7 @@ void hostapd_config_free(struct hostapd_config *conf);
int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
const u8 *addr, int *vlan_id);
int hostapd_rate_found(int *list, int rate);
-const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
+const u8 * hostapd_get_psk(struct hostapd_data *hapd,
const u8 *addr, const u8 *p2p_dev_addr,
const u8 *prev_psk);
int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf);
@@ -681,4 +686,9 @@ int hostapd_config_check(struct hostapd_config *conf, int full_config);
void hostapd_set_security_params(struct hostapd_bss_config *bss,
int full_config);
+#ifdef CONFIG_MULTI_SSID
+struct hostapd_ssid *hostapd_clone_twin_ssid(struct hostapd_bss_config *bss,
+ const u8 *ssid, size_t ssid_len);
+void hostapd_free_cloned_ssid(struct hostapd_ssid *ssid);
+#endif /* CONFIG_MULTI_SSID */
#endif /* HOSTAPD_CONFIG_H */
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index 53c1a61..24af671 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -690,8 +690,16 @@ void handle_probe_req(struct hostapd_data *hapd,
#endif /* CONFIG_MULTI_SSID */
if (res != NO_SSID_MATCH) {
- if (sta)
- sta->ssid_probe = &hapd->conf->ssid;
+ if (sta) {
+ #ifdef CONFIG_MULTI_SSID
+ hostapd_free_cloned_ssid(sta->ssid_probe);
+ sta->ssid_probe = NULL;
+ if (res == CATCHALL_SSID_MATCH)
+ sta->ssid_probe = hostapd_clone_twin_ssid(hapd->conf, ssid, ssid_len);
+ else
+ #endif /* CONFIG_MULTI_SSID */
+ sta->ssid_probe = &hapd->conf->ssid;
+ }
} else {
if (!(mgmt->da[0] & 0x01)) {
wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index a4884cc..42ab25f 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -1197,6 +1197,9 @@ static u16 check_ssid(struct hostapd_data *hapd, struct sta_info *sta,
HOSTAPD_LEVEL_INFO,
"Station associating with catchall network, requested SSID "
"'%s'", wpa_ssid_txt(ssid_ie, ssid_ie_len));
+ sta->ssid = hostapd_clone_twin_ssid(hapd->conf, ssid_ie, ssid_ie_len);
+ if (sta->ssid == NULL)
+ return WLAN_STATUS_UNSPECIFIED_FAILURE;
return WLAN_STATUS_SUCCESS;
}
#endif /* CONFIG_MULTI_SSID */
@@ -2409,8 +2412,8 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO,
- "associated (aid %d)",
- sta->aid);
+ "associated (aid %d) [%s]",
+ sta->aid, wpa_ssid_txt(sta->ssid->ssid, sta->ssid->ssid_len));
if (sta->flags & WLAN_STA_ASSOC)
new_assoc = 0;
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index 1576db9..5c31009 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -311,6 +311,12 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
os_free(sta->sae);
#endif /* CONFIG_SAE */
+#ifdef CONFIG_MULTI_SSID
+ /* free cloned SSIDs */
+ hostapd_free_cloned_ssid(sta->ssid);
+ hostapd_free_cloned_ssid(sta->ssid_probe);
+#endif /* CONFIG_MULTI_SSID */
+
os_free(sta);
}
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index 7cd0b6c..2f8246c 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -229,7 +229,7 @@ static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr,
}
#endif /* CONFIG_SAE */
- psk = hostapd_get_psk(hapd->conf, addr, p2p_dev_addr, prev_psk);
+ psk = hostapd_get_psk(hapd, addr, p2p_dev_addr, prev_psk);
/*
* This is about to iterate over all psks, prev_psk gives the last
* returned psk which should not be returned again.
--
2.1.4
More information about the Hostap
mailing list