All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/3] storage: Refactor storage_tls_session_{load,sync}
@ 2022-11-17 13:56 Andrew Zaborowski
  2022-11-17 13:56 ` [PATCH 2/3] eap-tls: Add session caching Andrew Zaborowski
  2022-11-17 13:56 ` [PATCH 3/3] station, eapol: Set up eap-tls-common for " Andrew Zaborowski
  0 siblings, 2 replies; 4+ messages in thread
From: Andrew Zaborowski @ 2022-11-17 13:56 UTC (permalink / raw)
  To: iwd

Minor changes to these two methods resulting from two rewrites of them.
Actual changes are:
 * storage_tls_session_sync parameter is const,
 * more specific naming,
 * storage_tls_session_load will return an empty l_settings instead of
   NULL so eap-tls-common.c doesn't have to handle this.

storage.c makes no assumptions about the group names in the l_settings
object and keeps no reference to that object, eap-tls-common.c is going
to maintain the memory copy of the cache since this cache and the disk
copy of it are reserved for EAP methods only.
---
 src/storage.c | 39 +++++++++++++++++++++++----------------
 src/storage.h |  4 ++--
 2 files changed, 25 insertions(+), 18 deletions(-)

diff --git a/src/storage.c b/src/storage.c
index b2c5ed48..4200030c 100644
--- a/src/storage.c
+++ b/src/storage.c
@@ -53,7 +53,7 @@
 #define STORAGE_FILE_MODE (S_IRUSR | S_IWUSR)
 
 #define KNOWN_FREQ_FILENAME ".known_network.freq"
-#define TLS_CACHE_FILENAME ".tls-session-cache"
+#define EAP_TLS_CACHE_FILENAME ".eap-tls-session-cache"
 
 static char *storage_path = NULL;
 static char *storage_hotspot_path = NULL;
@@ -702,29 +702,35 @@ void storage_known_frequencies_sync(struct l_settings *known_freqs)
 	l_free(known_freq_file_path);
 }
 
-struct l_settings *storage_tls_session_cache_load(void)
+struct l_settings *storage_eap_tls_cache_load(void)
 {
-	_auto_(l_settings_free) struct l_settings *cache = l_settings_new();
-	_auto_(l_free) char *tls_cache_file_path =
-		storage_get_path("%s", TLS_CACHE_FILENAME);
+	_auto_(l_free) char *path =
+		storage_get_path("%s", EAP_TLS_CACHE_FILENAME);
+	struct l_settings *cache = l_settings_new();
 
-	if (unlikely(!l_settings_load_from_file(cache, tls_cache_file_path)))
-		return NULL;
+	if (!l_settings_load_from_file(cache, path))
+		l_debug("No session cache loaded from %s, starting with an "
+			"empty cache", path);
 
-	return l_steal_ptr(cache);
+	return cache;
 }
 
-void storage_tls_session_cache_sync(struct l_settings *cache)
+void storage_eap_tls_cache_sync(const struct l_settings *cache)
 {
-	_auto_(l_free) char *tls_cache_file_path = NULL;
+	_auto_(l_free) char *path =
+		storage_get_path("%s", EAP_TLS_CACHE_FILENAME);
+	_auto_(l_free) char *settings_data = NULL;
 	_auto_(l_free) char *data = NULL;
 	size_t len;
+	static const char comment[] =
+		"# External changes to this file are not tracked by IWD "
+		"and will be overwritten.\n\n";
+	static const size_t comment_len = L_ARRAY_SIZE(comment) - 1;
 
-	if (!cache)
-		return;
-
-	tls_cache_file_path = storage_get_path("%s", TLS_CACHE_FILENAME);
-	data = l_settings_to_data(cache, &len);
+	settings_data = l_settings_to_data(cache, &len);
+	data = l_malloc(comment_len + len);
+	memcpy(data, comment, comment_len);
+	memcpy(data + comment_len, settings_data, len);
 
 	/*
 	 * Note this data contains cryptographic secrets.  write_file()
@@ -732,7 +738,8 @@ void storage_tls_session_cache_sync(struct l_settings *cache)
 	 *
 	 * TODO: consider encrypting with system_key.
 	 */
-	write_file(data, len, false, "%s", tls_cache_file_path);
+	write_file(data, comment_len + len, false, "%s", path);
+	explicit_bzero(settings_data, len);
 	explicit_bzero(data, len);
 }
 
diff --git a/src/storage.h b/src/storage.h
index fe6ddbf5..04b50882 100644
--- a/src/storage.h
+++ b/src/storage.h
@@ -51,8 +51,8 @@ int storage_network_remove(enum security type, const char *ssid);
 struct l_settings *storage_known_frequencies_load(void);
 void storage_known_frequencies_sync(struct l_settings *known_freqs);
 
-struct l_settings *storage_tls_session_cache_load(void);
-void storage_tls_session_cache_sync(struct l_settings *cache);
+struct l_settings *storage_eap_tls_cache_load(void);
+void storage_eap_tls_cache_sync(const struct l_settings *cache);
 
 int __storage_decrypt(struct l_settings *settings, const char *ssid,
 				bool *changed);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/3] eap-tls: Add session caching
  2022-11-17 13:56 [PATCH 1/3] storage: Refactor storage_tls_session_{load,sync} Andrew Zaborowski
@ 2022-11-17 13:56 ` Andrew Zaborowski
  2022-11-17 13:56 ` [PATCH 3/3] station, eapol: Set up eap-tls-common for " Andrew Zaborowski
  1 sibling, 0 replies; 4+ messages in thread
From: Andrew Zaborowski @ 2022-11-17 13:56 UTC (permalink / raw)
  To: iwd

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 --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);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 3/3] station, eapol: Set up eap-tls-common for session caching
  2022-11-17 13:56 [PATCH 1/3] storage: Refactor storage_tls_session_{load,sync} Andrew Zaborowski
  2022-11-17 13:56 ` [PATCH 2/3] eap-tls: Add session caching Andrew Zaborowski
@ 2022-11-17 13:56 ` Andrew Zaborowski
  2022-11-17 16:22   ` Denis Kenzior
  1 sibling, 1 reply; 4+ messages in thread
From: Andrew Zaborowski @ 2022-11-17 13:56 UTC (permalink / raw)
  To: iwd

Use eap_set_peer_id() to set a string identifying the TLS server,
currently the hex-encoded SSID of the network, to be used as group name
and primary key in the session cache l_settings object.  Provide pointers
to storage_eap_tls_cache_{load,sync} to eap-tls-common.c using
eap_tls_set_session_cache_ops().  Listen to Known Network removed
signals and call eap_tls_forget_peer() to have any session related to
the network also dropped from the cache.
---
 src/eapol.c   |  6 ++++++
 src/station.c | 28 ++++++++++++++++++++++++++++
 2 files changed, 34 insertions(+)

diff --git a/src/eapol.c b/src/eapol.c
index 4a1abd28..4d4e201d 100644
--- a/src/eapol.c
+++ b/src/eapol.c
@@ -2770,6 +2770,8 @@ void eapol_register(struct eapol_sm *sm)
 bool eapol_start(struct eapol_sm *sm)
 {
 	if (sm->handshake->settings_8021x) {
+		_auto_(l_free) char *network_id = NULL;
+
 		sm->eap = eap_new(eapol_eap_msg_cb, eapol_eap_complete_cb, sm);
 
 		if (!sm->eap)
@@ -2785,6 +2787,10 @@ bool eapol_start(struct eapol_sm *sm)
 
 		eap_set_key_material_func(sm->eap, eapol_eap_results_cb);
 		eap_set_event_func(sm->eap, eapol_eap_event_cb);
+
+		network_id = l_util_hexstring(sm->handshake->ssid,
+						sm->handshake->ssid_len);
+		eap_set_peer_id(sm->eap, network_id);
 	}
 
 	sm->started = true;
diff --git a/src/station.c b/src/station.c
index eab16eff..4aab7828 100644
--- a/src/station.c
+++ b/src/station.c
@@ -60,6 +60,9 @@
 #include "src/sysfs.h"
 #include "src/band.h"
 #include "src/ft.h"
+#include "src/eap.h"
+#include "src/eap-tls-common.h"
+#include "src/storage.h"
 
 static struct l_queue *station_list;
 static uint32_t netdev_watch;
@@ -69,6 +72,7 @@ static bool anqp_disabled;
 static bool supports_arp_evict_nocarrier;
 static bool supports_ndisc_evict_nocarrier;
 static struct watchlist event_watches;
+static uint32_t known_networks_watch;
 
 struct station {
 	enum station_state state;
@@ -5087,6 +5091,22 @@ static void station_netdev_watch(struct netdev *netdev,
 	}
 }
 
+static void station_known_networks_changed(enum known_networks_event event,
+						const struct network_info *info,
+						void *user_data)
+{
+	_auto_(l_free) char *network_id = NULL;
+
+	if (event != KNOWN_NETWORKS_EVENT_REMOVED)
+		return;
+
+	if (info->type != SECURITY_8021X)
+		return;
+
+	network_id = l_util_hexstring(info->ssid, strlen(info->ssid));
+	eap_tls_forget_peer(network_id);
+}
+
 static int station_init(void)
 {
 	station_list = l_queue_new();
@@ -5139,6 +5159,12 @@ static int station_init(void)
 
 	watchlist_init(&event_watches, NULL);
 
+	eap_tls_set_session_cache_ops(storage_eap_tls_cache_load,
+					storage_eap_tls_cache_sync);
+	known_networks_watch = known_networks_watch_add(
+						station_known_networks_changed,
+						NULL, NULL);
+
 	return 0;
 }
 
@@ -5154,6 +5180,8 @@ static void station_exit(void)
 	l_queue_destroy(station_list, NULL);
 	station_list = NULL;
 	watchlist_destroy(&event_watches);
+	known_networks_watch_remove(known_networks_watch);
+	known_networks_watch = 0;
 }
 
 IWD_MODULE(station, station_init, station_exit)
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 3/3] station, eapol: Set up eap-tls-common for session caching
  2022-11-17 13:56 ` [PATCH 3/3] station, eapol: Set up eap-tls-common for " Andrew Zaborowski
@ 2022-11-17 16:22   ` Denis Kenzior
  0 siblings, 0 replies; 4+ messages in thread
From: Denis Kenzior @ 2022-11-17 16:22 UTC (permalink / raw)
  To: Andrew Zaborowski, iwd

Hi Andrew,

On 11/17/22 07:56, Andrew Zaborowski wrote:
> Use eap_set_peer_id() to set a string identifying the TLS server,
> currently the hex-encoded SSID of the network, to be used as group name
> and primary key in the session cache l_settings object.  Provide pointers
> to storage_eap_tls_cache_{load,sync} to eap-tls-common.c using
> eap_tls_set_session_cache_ops().  Listen to Known Network removed
> signals and call eap_tls_forget_peer() to have any session related to
> the network also dropped from the cache.
> ---
>   src/eapol.c   |  6 ++++++
>   src/station.c | 28 ++++++++++++++++++++++++++++
>   2 files changed, 34 insertions(+)
> 

<snip>

> @@ -5139,6 +5159,12 @@ static int station_init(void)
>   
>   	watchlist_init(&event_watches, NULL);
>   
> +	eap_tls_set_session_cache_ops(storage_eap_tls_cache_load,
> +					storage_eap_tls_cache_sync);
> +	known_networks_watch = known_networks_watch_add(
> +						station_known_networks_changed,
> +						NULL, NULL);

This requires a dependency between station and known_networks module since the 
watchlist is initialized in known_networks_init.  I added this in a follow on 
commit.  Please have a look.

> +
>   	return 0;
>   }
>   

All three applied, thanks.

Regards,
-Denis

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2022-11-17 16:22 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-17 13:56 [PATCH 1/3] storage: Refactor storage_tls_session_{load,sync} Andrew Zaborowski
2022-11-17 13:56 ` [PATCH 2/3] eap-tls: Add session caching Andrew Zaborowski
2022-11-17 13:56 ` [PATCH 3/3] station, eapol: Set up eap-tls-common for " Andrew Zaborowski
2022-11-17 16:22   ` Denis Kenzior

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.