diff mbox series

[2/3] eap-tls: Add session caching

Message ID 20221117135610.1162965-2-andrew.zaborowski@intel.com (mailing list archive)
State Accepted, archived
Headers show
Series [1/3] storage: Refactor storage_tls_session_{load,sync} | expand

Checks

Context Check Description
tedd_an/pre-ci_am success Success
prestwoj/iwd-ci-gitlint success GitLint

Commit Message

Andrew Zaborowski Nov. 17, 2022, 1:56 p.m. UTC
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.
---
 src/eap-tls-common.c | 58 ++++++++++++++++++++++++++++++++++++++++++++
 src/eap-tls-common.h |  7 ++++++
 src/eap.c            | 13 ++++++++++
 src/eap.h            |  3 +++
 4 files changed, 81 insertions(+)
diff mbox series

Patch

diff --git a/src/eap-tls-common.c b/src/eap-tls-common.c
index acc5b387..9a4450e9 100644
--- a/src/eap-tls-common.c
+++ b/src/eap-tls-common.c
@@ -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);
diff --git a/src/eap-tls-common.h b/src/eap-tls-common.h
index 174770c0..25f668e2 100644
--- a/src/eap-tls-common.h
+++ b/src/eap-tls-common.h
@@ -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);
diff --git a/src/eap.c b/src/eap.c
index 6f523f2f..981b6388 100644
--- a/src/eap.c
+++ b/src/eap.c
@@ -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;
diff --git a/src/eap.h b/src/eap.h
index f1e867f5..702caf24 100644
--- a/src/eap.h
+++ b/src/eap.h
@@ -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);