eap-tls: Add session caching

Use l_tls_set_session_cache() to enable session cache/resume in the
TLS-based EAP methods.  Sessions for all 802.1x networks are stored in
one l_settings object.

eap_{get,set}_peer_id() API is added for the upper layers to set the
identifier of the authenticator (or the supplicant if we're the
authenticator, if there's ever a use case for that.)

eap-tls-common.c can't call storage_eap_tls_cache_{load,sync}()
or known_networks_watch_add() (to handle known network removals) because
it's linked into some executables that don't have storage.o,
knownnetworks.o or common.o so an upper layer (station.c) will call
eap_tls_set_session_cache_ops() and eap_tls_forget_peer() as needed.
This commit is contained in:
Andrew Zaborowski 2022-11-17 14:56:09 +01:00 committed by Denis Kenzior
parent e63c5bf4f8
commit ef81917e8d
4 changed files with 81 additions and 0 deletions

View File

@ -28,7 +28,9 @@
#include <errno.h>
#include <ell/ell.h>
#include "ell/useful.h"
#include "src/missing.h"
#include "src/module.h"
#include "src/eap.h"
#include "src/eap-private.h"
#include "src/eap-tls-common.h"
@ -123,6 +125,10 @@ struct eap_tls_state {
void *variant_data;
};
static struct l_settings *eap_tls_session_cache;
static eap_tls_session_cache_load_func_t eap_tls_session_cache_load;
static eap_tls_session_cache_sync_func_t eap_tls_session_cache_sync;
static void __eap_tls_common_state_reset(struct eap_tls_state *eap_tls)
{
eap_tls->version_negotiated = EAP_TLS_VERSION_NOT_NEGOTIATED;
@ -571,6 +577,15 @@ static int eap_tls_handle_fragmented_request(struct eap_state *eap,
return r;
}
static void eap_tls_session_cache_update(void *user_data)
{
if (L_WARN_ON(!eap_tls_session_cache_sync) ||
L_WARN_ON(!eap_tls_session_cache))
return;
eap_tls_session_cache_sync(eap_tls_session_cache);
}
static bool eap_tls_tunnel_init(struct eap_state *eap)
{
struct eap_tls_state *eap_tls = eap_get_data(eap);
@ -633,6 +648,17 @@ static bool eap_tls_tunnel_init(struct eap_state *eap)
if (eap_tls->domain_mask)
l_tls_set_domain_mask(eap_tls->tunnel, eap_tls->domain_mask);
if (!eap_tls_session_cache_load)
goto start;
if (!eap_tls_session_cache)
eap_tls_session_cache = eap_tls_session_cache_load();
l_tls_set_session_cache(eap_tls->tunnel, eap_tls_session_cache,
eap_get_peer_id(eap),
24 * 3600 * L_USEC_PER_SEC, 0,
eap_tls_session_cache_update, NULL);
start:
if (!l_tls_start(eap_tls->tunnel)) {
l_error("%s: Failed to start the TLS client",
@ -1085,3 +1111,35 @@ void eap_tls_common_tunnel_close(struct eap_state *eap)
l_tls_close(eap_tls->tunnel);
}
void eap_tls_set_session_cache_ops(eap_tls_session_cache_load_func_t load,
eap_tls_session_cache_sync_func_t sync)
{
eap_tls_session_cache_load = load;
eap_tls_session_cache_sync = sync;
}
void eap_tls_forget_peer(const char *peer_id)
{
if (L_WARN_ON(!eap_tls_session_cache_sync))
return;
if (!eap_tls_session_cache)
eap_tls_session_cache = eap_tls_session_cache_load();
if (l_settings_remove_group(eap_tls_session_cache, peer_id))
eap_tls_session_cache_sync(eap_tls_session_cache);
}
static int eap_tls_common_init(void)
{
return 0;
}
static void eap_tls_common_exit(void)
{
l_settings_free(eap_tls_session_cache);
eap_tls_session_cache = NULL;
}
IWD_MODULE(eap_tls_common, eap_tls_common_init, eap_tls_common_exit);

View File

@ -20,6 +20,9 @@
*
*/
typedef struct l_settings *(*eap_tls_session_cache_load_func_t)(void);
typedef void (*eap_tls_session_cache_sync_func_t)(const struct l_settings *);
enum eap_tls_version {
EAP_TLS_VERSION_0 = 0x00,
EAP_TLS_VERSION_1 = 0x01,
@ -81,3 +84,7 @@ bool eap_tls_common_tunnel_prf_get_bytes(struct eap_state *eap,
void eap_tls_common_tunnel_send(struct eap_state *eap, const uint8_t *data,
size_t data_len);
void eap_tls_common_tunnel_close(struct eap_state *eap);
void eap_tls_set_session_cache_ops(eap_tls_session_cache_load_func_t load,
eap_tls_session_cache_sync_func_t sync);
void eap_tls_forget_peer(const char *peer_id);

View File

@ -59,6 +59,7 @@ struct eap_state {
char *identity;
char *identity_setting;
bool authenticator;
char *peer_id;
int last_id;
void *method_state;
@ -154,6 +155,7 @@ void eap_free(struct eap_state *eap)
eap_free_common(eap);
l_timeout_remove(eap->complete_timeout);
eap_set_peer_id(eap, NULL);
l_free(eap);
}
@ -837,6 +839,17 @@ err:
return false;
}
void eap_set_peer_id(struct eap_state *eap, const char *id)
{
l_free(eap->peer_id);
eap->peer_id = l_strdup(id);
}
const char *eap_get_peer_id(struct eap_state *eap)
{
return eap->peer_id;
}
void eap_set_data(struct eap_state *eap, void *data)
{
eap->method_state = data;

View File

@ -94,6 +94,9 @@ const char *eap_get_identity(struct eap_state *eap);
void eap_rx_packet(struct eap_state *eap, const uint8_t *pkt, size_t len);
void eap_set_peer_id(struct eap_state *eap, const char *id);
const char *eap_get_peer_id(struct eap_state *eap);
void __eap_set_config(struct l_settings *config);
int eap_init(void);