[PATCH v2 3/4] cache list of PSK entries
Michael Braun
michael-dev
Fri Nov 16 07:12:57 PST 2012
---
src/ap/hostapd.c | 2 +
src/ap/ieee802_11.c | 16 ++++++----
src/ap/ieee802_11_auth.c | 75 +++++++++++++++++++++++++++++-----------------
src/ap/ieee802_11_auth.h | 2 +
4 files changed, 60 insertions(+), 35 deletions(-)
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 1c968a7..1e562d4 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -16,6 +16,7 @@
#include "drivers/driver.h"
#include "hostapd.h"
#include "authsrv.h"
+#include "ap_config.h"
#include "sta_info.h"
#include "accounting.h"
#include "ap_list.h"
@@ -29,7 +30,6 @@
#include "hw_features.h"
#include "wpa_auth_glue.h"
#include "ap_drv_ops.h"
-#include "ap_config.h"
#include "p2p_hostapd.h"
#include "gas_serv.h"
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 8d5268e..5f8cca9 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -23,6 +23,7 @@
#include "wps/wps.h"
#include "hostapd.h"
#include "beacon.h"
+#include "ap_config.h"
#include "ieee802_11_auth.h"
#include "sta_info.h"
#include "ieee802_1x.h"
@@ -30,7 +31,6 @@
#include "wmm.h"
#include "ap_list.h"
#include "accounting.h"
-#include "ap_config.h"
#include "ap_mlme.h"
#include "p2p_hostapd.h"
#include "ap_drv_ops.h"
@@ -443,8 +443,7 @@ static void handle_auth(struct hostapd_data *hapd,
const u8 *challenge = NULL;
u32 session_timeout, acct_interim_interval;
int vlan_id = 0;
- u8 psk[PMK_LEN];
- int has_psk = 0;
+ struct hostapd_sta_wpa_psk_short* psk = NULL;
u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
size_t resp_ies_len = 0;
char *identity = NULL;
@@ -514,7 +513,7 @@ static void handle_auth(struct hostapd_data *hapd,
res = hostapd_allowed_address(hapd, mgmt->sa, (u8 *) mgmt, len,
&session_timeout,
&acct_interim_interval, &vlan_id,
- psk, &has_psk, &identity, &radius_cui);
+ &psk, &identity, &radius_cui);
if (res == HOSTAPD_ACL_REJECT) {
printf("Station " MACSTR " not allowed to authenticate.\n",
@@ -553,11 +552,11 @@ static void handle_auth(struct hostapd_data *hapd,
HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id);
}
- if (has_psk && hapd->conf->wpa_psk_radius != PSK_RADIUS_IGNORED) {
+ if (psk && hapd->conf->wpa_psk_radius != PSK_RADIUS_IGNORED) {
os_free(sta->psk);
sta->psk = os_malloc(PMK_LEN);
if (sta->psk)
- os_memcpy(sta->psk, psk, PMK_LEN);
+ os_memcpy(sta->psk, psk->psk, PMK_LEN);
} else {
os_free(sta->psk);
sta->psk = NULL;
@@ -636,6 +635,11 @@ static void handle_auth(struct hostapd_data *hapd,
fail:
os_free(identity);
os_free(radius_cui);
+ while (psk) {
+ struct hostapd_sta_wpa_psk_short *prev = psk;
+ psk = psk->next;
+ os_free(prev);
+ }
send_auth_reply(hapd, mgmt->sa, mgmt->bssid, auth_alg,
auth_transaction + 1, resp, resp_ies, resp_ies_len);
diff --git a/src/ap/ieee802_11_auth.c b/src/ap/ieee802_11_auth.c
index 12b65b5..7fb2aed 100644
--- a/src/ap/ieee802_11_auth.c
+++ b/src/ap/ieee802_11_auth.c
@@ -36,8 +36,7 @@ struct hostapd_cached_radius_acl {
u32 session_timeout;
u32 acct_interim_interval;
int vlan_id;
- int has_psk;
- u8 psk[PMK_LEN];
+ struct hostapd_sta_wpa_psk_short* psk;
char *identity;
char *radius_cui;
};
@@ -58,6 +57,12 @@ static void hostapd_acl_cache_free_entry(struct hostapd_cached_radius_acl *e)
{
os_free(e->identity);
os_free(e->radius_cui);
+ struct hostapd_sta_wpa_psk_short* psk = e->psk;
+ while (psk) {
+ struct hostapd_sta_wpa_psk_short* prev = psk;
+ psk = psk->next;
+ os_free(prev);
+ }
os_free(e);
}
@@ -73,11 +78,10 @@ static void hostapd_acl_cache_free(struct hostapd_cached_radius_acl *acl_cache)
}
}
-
static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr,
u32 *session_timeout,
u32 *acct_interim_interval, int *vlan_id,
- u8 *psk, int *has_psk, char **identity,
+ struct hostapd_sta_wpa_psk_short **psk, char **identity,
char **radius_cui)
{
struct hostapd_cached_radius_acl *entry;
@@ -99,10 +103,21 @@ static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr,
entry->acct_interim_interval;
if (vlan_id)
*vlan_id = entry->vlan_id;
- if (psk)
- os_memcpy(psk, entry->psk, PMK_LEN);
- if (has_psk)
- *has_psk = entry->has_psk;
+ /* copy PSK linked list */
+ {
+ struct hostapd_sta_wpa_psk_short ** copy_to = psk;
+ struct hostapd_sta_wpa_psk_short * copy_from = entry->psk;
+ while (copy_from && copy_to) {
+ *copy_to = os_zalloc(sizeof(struct hostapd_sta_wpa_psk_short));
+ if (*copy_to == NULL)
+ break;
+ os_memcpy(*copy_to, copy_from, sizeof(struct hostapd_sta_wpa_psk_short));
+ copy_from = copy_from->next;
+ copy_to = &((*copy_to)->next);
+ }
+ if (copy_to)
+ *copy_to = NULL;
+ }
if (identity) {
if (entry->identity)
*identity = os_strdup(entry->identity);
@@ -200,8 +215,7 @@ static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr,
* @session_timeout: Buffer for returning session timeout (from RADIUS)
* @acct_interim_interval: Buffer for returning account interval (from RADIUS)
* @vlan_id: Buffer for returning VLAN ID
- * @psk: Buffer for returning WPA PSK
- * @has_psk: Buffer for indicating whether psk was filled
+ * @psk: Linked list buffer for returning WPA PSK
* @identity: Buffer for returning identity (from RADIUS)
* @radius_cui: Buffer for returning CUI (from RADIUS)
* Returns: HOSTAPD_ACL_ACCEPT, HOSTAPD_ACL_REJECT, or HOSTAPD_ACL_PENDING
@@ -212,7 +226,7 @@ static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr,
int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
const u8 *msg, size_t len, u32 *session_timeout,
u32 *acct_interim_interval, int *vlan_id,
- u8 *psk, int *has_psk, char **identity,
+ struct hostapd_sta_wpa_psk_short **psk, char **identity,
char **radius_cui)
{
if (session_timeout)
@@ -221,10 +235,8 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
*acct_interim_interval = 0;
if (vlan_id)
*vlan_id = 0;
- if (has_psk)
- *has_psk = 0;
if (psk)
- os_memset(psk, 0, PMK_LEN);
+ *psk = NULL;
if (identity)
*identity = NULL;
if (radius_cui)
@@ -253,7 +265,7 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
/* Check whether ACL cache has an entry for this station */
int res = hostapd_acl_cache_get(hapd, addr, session_timeout,
acct_interim_interval,
- vlan_id, psk, has_psk,
+ vlan_id, psk,
identity, radius_cui);
if (res == HOSTAPD_ACL_ACCEPT ||
res == HOSTAPD_ACL_ACCEPT_TIMEOUT)
@@ -456,6 +468,7 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
if (hdr->code == RADIUS_CODE_ACCESS_ACCEPT) {
int passphraselen;
char *passphrase;
+ size_t i;
u8 *buf;
size_t len;
@@ -477,27 +490,35 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
}
cache->vlan_id = radius_msg_get_vlanid(msg);
-
- passphrase = radius_msg_get_tunnel_password(
- msg, &passphraselen,
- hapd->conf->radius->auth_server->shared_secret,
- hapd->conf->radius->auth_server->shared_secret_len,
- req, 0);
- cache->has_psk = passphrase != NULL;
- if (passphrase != NULL) {
+ /* decode all tunnel passwords as PSK and save them into a linked list */
+ for (i=0;;i++) {
+ passphrase = radius_msg_get_tunnel_password(
+ msg, &passphraselen,
+ hapd->conf->radius->auth_server->shared_secret,
+ hapd->conf->radius->auth_server->shared_secret_len,
+ req, i);
+ /* passphrase is NULL iff there is no i-th Tunnel-Password attribute in msg */
+ if (passphrase == NULL)
+ break;
/* passphrase does not contain the NULL termination.
* Add it here as pbkdf2_sha1 requires it. */
char *strpassphrase = os_zalloc(passphraselen + 1);
- if (strpassphrase) {
+ struct hostapd_sta_wpa_psk_short* psk = os_zalloc(sizeof(struct hostapd_sta_wpa_psk_short));
+ if (strpassphrase && psk) {
os_memcpy(strpassphrase, passphrase,
passphraselen);
pbkdf2_sha1(strpassphrase,
hapd->conf->ssid.ssid,
hapd->conf->ssid.ssid_len, 4096,
- cache->psk, PMK_LEN);
- os_free(strpassphrase);
+ psk->psk, PMK_LEN);
+ psk->next = cache->psk;
+ cache->psk = psk;
+ psk = NULL;
}
+ os_free(strpassphrase);
+ os_free(psk);
os_free(passphrase);
+ passphrase = NULL;
}
if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_USER_NAME,
&buf, &len, NULL) == 0) {
@@ -514,7 +535,7 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
}
if (hapd->conf->wpa_psk_radius == PSK_RADIUS_REQUIRED &&
- !cache->has_psk)
+ !cache->psk)
cache->accepted = HOSTAPD_ACL_REJECT;
} else
cache->accepted = HOSTAPD_ACL_REJECT;
diff --git a/src/ap/ieee802_11_auth.h b/src/ap/ieee802_11_auth.h
index 0e8d1cb..a830115 100644
--- a/src/ap/ieee802_11_auth.h
+++ b/src/ap/ieee802_11_auth.h
@@ -19,7 +19,7 @@ enum {
int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
const u8 *msg, size_t len, u32 *session_timeout,
u32 *acct_interim_interval, int *vlan_id,
- u8 *psk, int *has_psk, char **identity,
+ struct hostapd_sta_wpa_psk_short **psk, char **identity,
char **radius_cui);
int hostapd_acl_init(struct hostapd_data *hapd);
void hostapd_acl_deinit(struct hostapd_data *hapd);
More information about the Hostap
mailing list