Patchwork [PATCHv2,07/21] 802.1X: release unused VLAN-WEP-Keys

login
register
mail settings
Submitter michael-dev@fami-braun.de
Date May 17, 2013, 9:15 a.m.
Message ID <a961f9f134319f435f1e38fe9c052016ad4d928d.1370512966.git.michael-dev@fami-braun.de>
Download mbox | patch
Permalink /patch/249365/
State Changes Requested
Headers show

Comments

michael-dev@fami-braun.de - May 17, 2013, 9:15 a.m.
Reuse the WEP rekeying timer to remove keys for which no sta exists.

Signed-hostap: Michael Braun <michael-dev@fami-braun.de>
Jouni Malinen - June 25, 2013, 9:15 a.m.
On Fri, May 17, 2013 at 11:15:57AM +0200, Michael Braun wrote:
> Reuse the WEP rekeying timer to remove keys for which no sta exists.

Is rekeying timer the correct place for this? Wouldn't the key become
unneeded when the last STA using it gets removed? Anyway, WEP should not
really be used today, so I'm not sure it would be justifiable to add any
more complexity here unless this is required for something else to work.
Would be more valuable to consider just removing support for dynamic WEP
keys with VLAN altogether..

Patch

diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 7a3a8d9..c9e62ce 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -383,7 +383,7 @@  static void hostapd_config_free_eap_user(struct hostapd_eap_user *user)
 }
 
 
-static void hostapd_config_free_wep(struct hostapd_wep_keys *keys)
+void hostapd_config_free_wep(struct hostapd_wep_keys *keys)
 {
 	int i;
 	for (i = 0; i < NUM_WEP_KEYS; i++) {
@@ -393,6 +393,15 @@  static void hostapd_config_free_wep(struct hostapd_wep_keys *keys)
 }
 
 
+void hostapd_config_free_vlan_wep(struct hostapd_vlan_wep_keys *key)
+{
+	if (!key)
+		return;
+	hostapd_config_free_wep(&key->key);
+	os_free(key);
+}
+
+
 static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
 {
 	struct hostapd_wpa_psk *psk, *prev;
@@ -454,10 +463,8 @@  static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
 		struct hostapd_ssid *ssid = &conf->ssid;
 		size_t i;
 		for (i = 0; i <= ssid->count_dyn_vlan_keys; i++) {
-			if (ssid->dyn_vlan_keys[i] == NULL)
-				continue;
-			hostapd_config_free_wep(&ssid->dyn_vlan_keys[i]->key);
-			os_free(ssid->dyn_vlan_keys[i]);
+			hostapd_config_free_vlan_wep(ssid->dyn_vlan_keys[i]);
+			ssid->dyn_vlan_keys[i] = NULL;
 		}
 		os_free(ssid->dyn_vlan_keys);
 		ssid->dyn_vlan_keys = NULL;
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 7ca4647..2d918f0 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -42,6 +42,7 @@  struct hostapd_wep_keys {
 
 struct hostapd_vlan_wep_keys {
 	int vlan_id;
+	int numSTAonLastRekey;
 	struct hostapd_wep_keys key;
 };
 
@@ -549,6 +550,8 @@  int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
 int hostapd_rate_found(int *list, int rate);
 int hostapd_wep_key_cmp(struct hostapd_wep_keys *a,
 			struct hostapd_wep_keys *b);
+void hostapd_config_free_wep(struct hostapd_wep_keys *keys);
+void hostapd_config_free_vlan_wep(struct hostapd_vlan_wep_keys *key);
 const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
 			   const u8 *addr, const u8 *prev_psk);
 int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf);
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index 8b5076d..9486516 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -1579,6 +1579,67 @@  static int ieee802_1x_rekey_broadcast(struct hostapd_data *hapd)
 }
 
 
+#ifndef CONFIG_NO_VLAN
+static int ieee802_1x_sta_check_group(struct hostapd_data *hapd,
+                                      struct sta_info *sta, void *ctx)
+{
+	int i;
+	struct hostapd_ssid *ssid = sta->ssid;
+
+	if (sta->vlan_id <= 0)
+		return 0;
+	
+	for (i = 0; i < ssid->count_dyn_vlan_keys; i++) {
+		struct hostapd_vlan_wep_keys *key = ssid->dyn_vlan_keys[i];
+		if (!key)
+			continue;
+		if (key->vlan_id == sta->vlan_id)
+			continue;
+		key->numSTAonLastRekey++;
+	}
+	return 0;
+}
+
+static void ieee802_1x_cleanup_vlan_keys(struct hostapd_data *hapd)
+{
+	int i, offs;
+        struct hostapd_ssid *ssid = &hapd->conf->ssid;
+	struct hostapd_vlan_wep_keys **tmp;
+
+	for (i = 0; i < ssid->count_dyn_vlan_keys; i++) {
+		struct hostapd_vlan_wep_keys *key = ssid->dyn_vlan_keys[i];
+		if (!key)
+			continue;
+		key->numSTAonLastRekey = 0;
+	}
+	ap_for_each_sta(hapd, ieee802_1x_sta_check_group, NULL);
+	for (i = 0, offs = 0; i < ssid->count_dyn_vlan_keys; i++) {
+		struct hostapd_vlan_wep_keys *key = ssid->dyn_vlan_keys[i];
+		if (!key) {
+			offs++;
+		} else if (key->numSTAonLastRekey == 0) {
+			hostapd_config_free_vlan_wep(key);
+			ssid->dyn_vlan_keys[i] = NULL;
+			offs++;
+		} else if (offs > 0) {
+			ssid->dyn_vlan_keys[i - offs] = ssid->dyn_vlan_keys[i];
+			ssid->dyn_vlan_keys[i] = NULL;
+		}
+	}
+	if (offs > ssid->count_dyn_vlan_keys / 2) {
+		/* half of memory is free */
+		tmp = os_realloc_array(ssid->dyn_vlan_keys,
+		                       ssid->count_dyn_vlan_keys / 2,
+				       sizeof(*ssid->dyn_vlan_keys));
+		if (!tmp) {
+			return;
+		}
+		ssid->dyn_vlan_keys = tmp;
+		ssid->count_dyn_vlan_keys = ssid->count_dyn_vlan_keys / 2;
+	}
+}
+#endif /* CONFIG_NO_VLAN */
+
 static int ieee802_1x_sta_key_available(struct hostapd_data *hapd,
 					struct sta_info *sta, void *ctx)
 {
@@ -1629,6 +1690,9 @@  static void ieee802_1x_rekey(void *eloop_ctx, void *timeout_ctx)
 	}
 
 	ap_for_each_sta(hapd, ieee802_1x_sta_key_available, NULL);
+	#ifndef CONFIG_NO_VLAN
+	ieee802_1x_cleanup_vlan_keys(hapd);
+	#endif
 
 	if (hapd->conf->wep_rekeying_period > 0) {
 		eloop_register_timeout(hapd->conf->wep_rekeying_period, 0,