changeset 5773:3a7349aa95c7

mod_sasl_ssdp: New module implementing XEP-0474 SASL SCRAM Downgrade Protection
author Matthew Wild <mwild1@gmail.com>
date Tue, 05 Dec 2023 12:39:00 +0000
parents 5ff8022466ab
children 7b722955c59b
files mod_sasl_ssdp/README.markdown mod_sasl_ssdp/mod_sasl_ssdp.lua
diffstat 2 files changed, 66 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mod_sasl_ssdp/README.markdown	Tue Dec 05 12:39:00 2023 +0000
@@ -0,0 +1,30 @@
+---
+labels:
+- 'Stage-Alpha'
+summary: 'XEP-0474: SASL SCRAM Downgrade Protection'
+...
+
+Introduction
+============
+
+This module implements the experimental XEP-0474: SASL SCRAM Downgrade
+Protection. It provides an alternative downgrade protection mechanism to
+client-side pinning which is currently the most common method of downgrade
+protection.
+
+**Note:** This module implements version 0.3.0 of XEP-0474. As of 2023-12-05,
+this version is not yet published on xmpp.org. Version 0.3.0 of the XEP is
+implemented in Monal 6.0.1. No other clients are currently known to implement
+the XEP at the time of writing.
+
+# Configuration
+
+There are no configuration options for this module, just load it as normal.
+
+# Compatibility
+
+For SASL2 (XEP-0388) clients, it is compatible with the mod_sasl2 community module.
+
+For clients using RFC 6120 SASL, it requires Prosody trunk 33e5edbd6a4a or
+later. It is not compatible with Prosody 0.12 (it will load, but simply
+won't do anything) for "legacy SASL".
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mod_sasl_ssdp/mod_sasl_ssdp.lua	Tue Dec 05 12:39:00 2023 +0000
@@ -0,0 +1,36 @@
+local array = require "util.array";
+local hashes = require "util.hashes";
+local it = require "util.iterators";
+local base64_enc = require "util.encodings".base64.encode;
+
+local hash_functions = {
+	["SCRAM-SHA-1"] = hashes.sha1;
+	["SCRAM-SHA-1-PLUS"] = hashes.sha1;
+	["SCRAM-SHA-256"] = hashes.sha256;
+	["SCRAM-SHA-256-PLUS"] = hashes.sha256;
+};
+
+function add_ssdp_info(event)
+	local sasl_handler = event.session.sasl_handler;
+	local hash = hash_functions[sasl_handler.selected];
+	if not hash then
+		module:log("debug", "Not enabling SSDP for unsupported mechanism: %s", sasl_handler.selected);
+		return;
+	end
+	local mechanism_list = array.collect(it.keys(sasl_handler:mechanisms())):sort();
+	local cb = sasl_handler.profile.cb;
+	local cb_list = cb and array.collect(it.keys(cb)):sort();
+	local ssdp_string;
+	if cb_list then
+		ssdp_string = mechanism_list:concat(",").."|"..cb_list:concat(",");
+	else
+		ssdp_string = mechanism_list:concat(",");
+	end
+	module:log("debug", "Calculated SSDP string: %s", ssdp_string);
+	event.message = event.message..",d="..base64_enc(hash(ssdp_string));
+	sasl_handler.state.server_first_message = event.message;
+end
+
+module:hook("sasl/reply/challenge", add_ssdp_info, 1);
+module:hook("sasl2/c2s/challenge", add_ssdp_info, 1);
+