From 461d904086e090c569b818e6eb8dd7b58891c2b1 Mon Sep 17 00:00:00 2001
From: Martin Weinelt <martin@darmstadt.freifunk.net>
Date: Tue, 5 Feb 2019 02:34:12 +0100
Subject: [PATCH] Add gluon-mesh-wireless-sae package

This package adds support for SAE on 802.11s mesh connections.

Enabling this package will require all 802.11s mesh connections
to be encrypted using the SAE key agreement scheme. The security
of SAE relies upon the authentication through a shared secret.

In the context of public mesh networks a shared secret is an
obvious oxymoron. Still this functionality provides an improvement
over unencrypted mesh connections in that it protects against a
passive attacker who did not observe the key agreement. In addition
Management Frame Protection (802.11w) gets automatically enabled on
mesh interfaces to prevent protocol-level deauthentication attacks.

If `wifi.mesh.sae` is enabled a shared secret will automatically be
derived from the `prefix6` variable. This is as secure as it gets
for a public mesh network.

For *private* mesh networks `wifi.mesh.sae_passphrase` should be
set to your shared secret.

Fixes #1636
---
 docs/index.rst                                |  1 +
 docs/package/gluon-mesh-wireless-sae.rst      | 49 +++++++++++++++++++
 package/gluon-mesh-wireless-sae/Makefile      | 13 +++++
 .../gluon-mesh-wireless-sae/check_site.lua    |  2 +
 .../lib/gluon/upgrade/205-wireless-mesh-sae   | 29 +++++++++++
 5 files changed, 94 insertions(+)
 create mode 100644 docs/package/gluon-mesh-wireless-sae.rst
 create mode 100644 package/gluon-mesh-wireless-sae/Makefile
 create mode 100644 package/gluon-mesh-wireless-sae/check_site.lua
 create mode 100755 package/gluon-mesh-wireless-sae/luasrc/lib/gluon/upgrade/205-wireless-mesh-sae

diff --git a/docs/index.rst b/docs/index.rst
index c3010fc81..f11dd702e 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -65,6 +65,7 @@ Several Freifunk communities in Germany use Gluon as the foundation of their Fre
    package/gluon-ebtables-source-filter
    package/gluon-hoodselector
    package/gluon-mesh-batman-adv
+   package/gluon-mesh-wireless-sae
    package/gluon-radv-filterd
    package/gluon-scheduled-domain-switch
    package/gluon-web-admin
diff --git a/docs/package/gluon-mesh-wireless-sae.rst b/docs/package/gluon-mesh-wireless-sae.rst
new file mode 100644
index 000000000..7572580e9
--- /dev/null
+++ b/docs/package/gluon-mesh-wireless-sae.rst
@@ -0,0 +1,49 @@
+gluon-mesh-wireless-sae
+=======================
+
+This package adds support for SAE on 802.11s mesh connections.
+
+Enabling this package will require all 802.11s mesh connections
+to be encrypted using the SAE key agreement scheme. The security
+of SAE relies upon the authentication through a shared secret.
+
+In the context of public mesh networks a shared secret is an
+obvious oxymoron. Still, this functionality may provide an improvement
+over unencrypted mesh connections in that it protects against a
+passive attacker who did not observe the key agreement. In addition
+Management Frame Protection (802.11w) gets automatically enabled on
+wireless mesh interfaces to prevent protocol-level deauthentication attacks.
+
+If `wifi.mesh.sae` is enabled, a shared secret will automatically be
+derived from the `prefix6` variable. This is as secure as it gets
+for a public mesh network.
+
+For *private* mesh networks `wifi.mesh.sae_passphrase` should be
+set to your shared secret.
+
+site.conf
+---------
+These settings apply to all 802.11s mesh interfaces on all radios.
+
+wifi.mesh.sae \: optional
+  - ``true`` enables SAE on 802.11s mesh connections
+  - ``false`` disables SAE on 802.11s mesh connections
+  - defaults to ``false``
+
+wifi.mesh.sae_passphrase \: optional
+  - sets a shared secret used to authenticate any two mesh nodes,
+    crucial for private mesh networks
+  - should not be set, if the shared secret is shared with untrusted
+    third parties, like in a publish mesh network
+  - defaults to an autogenerated value derived from ``prefix6``
+
+
+Example::
+
+  wifi = {
+    mesh = {
+      sae = true,
+      -- sae_passphrase = "<shared secret>",
+    },
+  },
+
diff --git a/package/gluon-mesh-wireless-sae/Makefile b/package/gluon-mesh-wireless-sae/Makefile
new file mode 100644
index 000000000..32b867a42
--- /dev/null
+++ b/package/gluon-mesh-wireless-sae/Makefile
@@ -0,0 +1,13 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=gluon-mesh-wireless-sae
+PKG_VERSION:=1
+
+include ../gluon.mk
+
+define Package/gluon-mesh-wireless-sae
+  TITLE:=Encryption of 802.11s Mesh Links through SAE
+  DEPENDS:=+gluon-core +wpa-supplicant-openssl
+endef
+
+$(eval $(call BuildPackageGluon,gluon-mesh-wireless-sae))
diff --git a/package/gluon-mesh-wireless-sae/check_site.lua b/package/gluon-mesh-wireless-sae/check_site.lua
new file mode 100644
index 000000000..be0f957bd
--- /dev/null
+++ b/package/gluon-mesh-wireless-sae/check_site.lua
@@ -0,0 +1,2 @@
+need_boolean({'wifi', 'mesh', 'sae'}, false)
+need_string({'wifi', 'mesh', 'sae_passphrase'}, false)
diff --git a/package/gluon-mesh-wireless-sae/luasrc/lib/gluon/upgrade/205-wireless-mesh-sae b/package/gluon-mesh-wireless-sae/luasrc/lib/gluon/upgrade/205-wireless-mesh-sae
new file mode 100755
index 000000000..ee1fae073
--- /dev/null
+++ b/package/gluon-mesh-wireless-sae/luasrc/lib/gluon/upgrade/205-wireless-mesh-sae
@@ -0,0 +1,29 @@
+#!/usr/bin/lua
+
+local util = require 'gluon.util'
+local site = require 'gluon.site'
+local hash = require 'hash'
+local uci = require('simple-uci').cursor()
+
+
+local function configure_sae(vif)
+	uci:set('wireless', vif, 'encryption', 'sae')
+	uci:set('wireless', vif, 'key', site.wifi.mesh.sae_passphrase() or hash.md5(site.prefix6()))
+end
+
+util.foreach_radio(uci, function(radio, _, _)
+	local radio_name = radio['.name']
+	local vif = 'mesh_' .. radio_name
+	local enable = site.wifi.mesh.sae(false)
+
+	if uci:get('wireless', vif) then
+		uci:delete('wireless', vif, 'encryption')
+		uci:delete('wireless', vif, 'key')
+
+		if enable then
+			configure_sae(vif)
+		end
+	end
+end)
+
+uci:save('wireless')
-- 
GitLab