view plugins/mod_s2s_auth_certs.lua @ 14103:27e97e5b2c16 13.0

util.jid: Fix to reject IPv6 literal hosts without brackets From RFC 7622: > Implementation Note: Reuse of the IP-literal rule from [RFC6874] > implies that IPv6 addresses are enclosed within square brackets (i.e., > beginning with '[' and ending with ']'), , which was not the case with > the definition of the XMPP address format in [RFC3920] but which was > changed in [RFC6122].
author Kim Alvefur <zash@zash.se>
date Sat, 14 Mar 2026 01:16:14 +0100
parents 3c219effe707
children
line wrap: on
line source

module:set_global();

local cert_verify_identity = require "prosody.util.x509".verify_identity;
local log = module._log;

local measure_cert_statuses = module:metric("counter", "checked", "", "Certificate validation results",
	{ "chain"; "identity" })

module:hook("s2s-check-certificate", function(event)
	local session, host, cert = event.session, event.host, event.cert;
	local conn = session.conn;
	local log = session.log or log;

	local secure_hostname = conn.extra and conn.extra.secure_hostname;

	if not cert then
		log("warn", "No certificate provided by %s", host or "unknown host");
		return;
	end

	local chain_valid, errors = conn:ssl_peerverification();
	-- Is there any interest in printing out all/the number of errors here?
	if not chain_valid then
		log("debug", "certificate chain validation result: invalid");
		if type(errors) == "table" then
			for depth, t in pairs(errors) do
				log("debug", "certificate error(s) at depth %d: %s", depth-1, table.concat(t, ", "));
			end
		else
			log("debug", "certificate error: %s", errors);
		end
		session.cert_chain_status = "invalid";
		session.cert_chain_errors = errors;
	else
		log("debug", "certificate chain validation result: valid");
		session.cert_chain_status = "valid";

		-- We'll go ahead and verify the asserted identity if the
		-- connecting server specified one.
		if host then
			if cert_verify_identity(host, "xmpp-server", cert) then
				session.cert_identity_status = "valid"
			else
				session.cert_identity_status = "invalid"
			end
			log("debug", "certificate identity validation result: %s", session.cert_identity_status);
		end

		-- Check for DNSSEC-signed SRV hostname
		if secure_hostname and session.cert_identity_status ~= "valid" then
			if cert_verify_identity(secure_hostname, "xmpp-server", cert) then
				module:log("info", "Secure SRV name delegation %q -> %q", secure_hostname, host);
				session.cert_identity_status = "valid"
			end
		end
	end
	measure_cert_statuses:with_labels(session.cert_chain_status or "unknown", session.cert_identity_status or "unknown"):add(1);
end, 509);