Software /
code /
prosody
Changeset
13278:aa17086a9c8a
mod_saslauth: Derive hash from certificate per tls-server-end-point
This originally used a WIP implementation of cert:sigalg(), a method to
retrieve certificate signature algorithm, but it was never submitted
upstream. https://github.com/Zash/luasec/tree/zash/sigalg
cert:getsignaturename() was merged in
https://github.com/brunoos/luasec/commit/de393417b7c7566caf1e0a0ad54132942ac4f049
XEP-0440 v0.3.0 made implementing tls-server-end-point a MUST
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Tue, 29 Jun 2021 00:22:36 +0200 |
parents | 13277:0b4c3573b248 |
children | 13279:140f7926946b |
files | plugins/mod_saslauth.lua |
diffstat | 1 files changed, 34 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/plugins/mod_saslauth.lua Mon Dec 07 19:53:26 2020 +0100 +++ b/plugins/mod_saslauth.lua Tue Jun 29 00:22:36 2021 +0200 @@ -15,6 +15,9 @@ local set = require "prosody.util.set"; local errors = require "prosody.util.error"; local hex = require "prosody.util.hex"; +local pem2der = require"util.x509".pem2der; +local hashes = require"util.hashes"; +local ssl = require "ssl"; -- FIXME Isolate LuaSec from the rest of the code local usermanager_get_sasl_handler = require "prosody.core.usermanager".get_sasl_handler; @@ -260,6 +263,30 @@ local function tls_server_end_point(self) local cert_hash = self.userdata["tls-server-end-point"]; if cert_hash then return hex.from(cert_hash); end + + -- Hash function selection, see RFC 5929 §4.1 + local certfile = self.userdata["tls-server-end-point-cert"]; + if not certfile then return end + local f = io.open(certfile); + if not f then return end + local hash = hashes.sha256; + + -- FIXME TOCTOU + -- We don't know that this is the right cert, it could have been replaced on + -- disk since we started. Best would be if we could extract the cert used + -- from the SSL context. + local certdata = f:read("*"); + local cert = ssl.loadcertificate(certdata); + + if cert.getsignaturename then + local sigalg = cert:getsignaturename():lower():match("sha%d+"); + if sigalg and sigalg ~= "sha1" and hashes[sigalg] then + -- This should have ruled out MD5 and SHA1 + hash = hashes[sigalg]; + end + end + + return hash(pem2der(cert)); end local mechanisms_attr = { xmlns='urn:ietf:params:xml:ns:xmpp-sasl' }; @@ -295,14 +322,21 @@ else log("debug", "Channel binding 'tls-unique' not supported (by LuaSec?)"); end + local certfile = origin.ssl_cfg and origin.ssl_cfg.certificate; + -- FIXME .ssl_cfg is set by mod_tls and thus only available with starttls if tls_server_end_point_hash then log("debug", "Channel binding 'tls-server-end-point' can be offered with the configured certificate hash"); sasl_handler:add_cb_handler("tls-server-end-point", tls_server_end_point); channel_bindings:add("tls-server-end-point"); + elseif certfile then + log("debug", "Channel binding 'tls-server-end-point' can be offered based on the certificate used"); + sasl_handler:add_cb_handler("tls-server-end-point", tls_server_end_point); + channel_bindings:add("tls-server-end-point"); end sasl_handler["userdata"] = { ["tls-unique"] = origin.conn; ["tls-exporter"] = origin.conn; + ["tls-server-end-point-cert"] = certfile; ["tls-server-end-point"] = tls_server_end_point_hash; }; else