Mercurial > prosody-hg
comparison plugins/mod_saslauth.lua @ 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 | 0b4c3573b248 |
| children | 288ddca37639 |
comparison
equal
deleted
inserted
replaced
| 13277:0b4c3573b248 | 13278:aa17086a9c8a |
|---|---|
| 13 local sm_make_authenticated = require "prosody.core.sessionmanager".make_authenticated; | 13 local sm_make_authenticated = require "prosody.core.sessionmanager".make_authenticated; |
| 14 local base64 = require "prosody.util.encodings".base64; | 14 local base64 = require "prosody.util.encodings".base64; |
| 15 local set = require "prosody.util.set"; | 15 local set = require "prosody.util.set"; |
| 16 local errors = require "prosody.util.error"; | 16 local errors = require "prosody.util.error"; |
| 17 local hex = require "prosody.util.hex"; | 17 local hex = require "prosody.util.hex"; |
| 18 local pem2der = require"util.x509".pem2der; | |
| 19 local hashes = require"util.hashes"; | |
| 20 local ssl = require "ssl"; -- FIXME Isolate LuaSec from the rest of the code | |
| 18 | 21 |
| 19 local usermanager_get_sasl_handler = require "prosody.core.usermanager".get_sasl_handler; | 22 local usermanager_get_sasl_handler = require "prosody.core.usermanager".get_sasl_handler; |
| 20 | 23 |
| 21 local secure_auth_only = module:get_option_boolean("c2s_require_encryption", module:get_option_boolean("require_encryption", true)); | 24 local secure_auth_only = module:get_option_boolean("c2s_require_encryption", module:get_option_boolean("require_encryption", true)); |
| 22 local allow_unencrypted_plain_auth = module:get_option_boolean("allow_unencrypted_plain_auth", false) | 25 local allow_unencrypted_plain_auth = module:get_option_boolean("allow_unencrypted_plain_auth", false) |
| 258 end | 261 end |
| 259 | 262 |
| 260 local function tls_server_end_point(self) | 263 local function tls_server_end_point(self) |
| 261 local cert_hash = self.userdata["tls-server-end-point"]; | 264 local cert_hash = self.userdata["tls-server-end-point"]; |
| 262 if cert_hash then return hex.from(cert_hash); end | 265 if cert_hash then return hex.from(cert_hash); end |
| 266 | |
| 267 -- Hash function selection, see RFC 5929 ยง4.1 | |
| 268 local certfile = self.userdata["tls-server-end-point-cert"]; | |
| 269 if not certfile then return end | |
| 270 local f = io.open(certfile); | |
| 271 if not f then return end | |
| 272 local hash = hashes.sha256; | |
| 273 | |
| 274 -- FIXME TOCTOU | |
| 275 -- We don't know that this is the right cert, it could have been replaced on | |
| 276 -- disk since we started. Best would be if we could extract the cert used | |
| 277 -- from the SSL context. | |
| 278 local certdata = f:read("*"); | |
| 279 local cert = ssl.loadcertificate(certdata); | |
| 280 | |
| 281 if cert.getsignaturename then | |
| 282 local sigalg = cert:getsignaturename():lower():match("sha%d+"); | |
| 283 if sigalg and sigalg ~= "sha1" and hashes[sigalg] then | |
| 284 -- This should have ruled out MD5 and SHA1 | |
| 285 hash = hashes[sigalg]; | |
| 286 end | |
| 287 end | |
| 288 | |
| 289 return hash(pem2der(cert)); | |
| 263 end | 290 end |
| 264 | 291 |
| 265 local mechanisms_attr = { xmlns='urn:ietf:params:xml:ns:xmpp-sasl' }; | 292 local mechanisms_attr = { xmlns='urn:ietf:params:xml:ns:xmpp-sasl' }; |
| 266 local bind_attr = { xmlns='urn:ietf:params:xml:ns:xmpp-bind' }; | 293 local bind_attr = { xmlns='urn:ietf:params:xml:ns:xmpp-bind' }; |
| 267 local xmpp_session_attr = { xmlns='urn:ietf:params:xml:ns:xmpp-session' }; | 294 local xmpp_session_attr = { xmlns='urn:ietf:params:xml:ns:xmpp-session' }; |
| 293 sasl_handler:add_cb_handler("tls-unique", tls_unique); | 320 sasl_handler:add_cb_handler("tls-unique", tls_unique); |
| 294 channel_bindings:add("tls-unique"); | 321 channel_bindings:add("tls-unique"); |
| 295 else | 322 else |
| 296 log("debug", "Channel binding 'tls-unique' not supported (by LuaSec?)"); | 323 log("debug", "Channel binding 'tls-unique' not supported (by LuaSec?)"); |
| 297 end | 324 end |
| 325 local certfile = origin.ssl_cfg and origin.ssl_cfg.certificate; | |
| 326 -- FIXME .ssl_cfg is set by mod_tls and thus only available with starttls | |
| 298 if tls_server_end_point_hash then | 327 if tls_server_end_point_hash then |
| 299 log("debug", "Channel binding 'tls-server-end-point' can be offered with the configured certificate hash"); | 328 log("debug", "Channel binding 'tls-server-end-point' can be offered with the configured certificate hash"); |
| 329 sasl_handler:add_cb_handler("tls-server-end-point", tls_server_end_point); | |
| 330 channel_bindings:add("tls-server-end-point"); | |
| 331 elseif certfile then | |
| 332 log("debug", "Channel binding 'tls-server-end-point' can be offered based on the certificate used"); | |
| 300 sasl_handler:add_cb_handler("tls-server-end-point", tls_server_end_point); | 333 sasl_handler:add_cb_handler("tls-server-end-point", tls_server_end_point); |
| 301 channel_bindings:add("tls-server-end-point"); | 334 channel_bindings:add("tls-server-end-point"); |
| 302 end | 335 end |
| 303 sasl_handler["userdata"] = { | 336 sasl_handler["userdata"] = { |
| 304 ["tls-unique"] = origin.conn; | 337 ["tls-unique"] = origin.conn; |
| 305 ["tls-exporter"] = origin.conn; | 338 ["tls-exporter"] = origin.conn; |
| 339 ["tls-server-end-point-cert"] = certfile; | |
| 306 ["tls-server-end-point"] = tls_server_end_point_hash; | 340 ["tls-server-end-point"] = tls_server_end_point_hash; |
| 307 }; | 341 }; |
| 308 else | 342 else |
| 309 log("debug", "Channel binding not supported by SASL handler"); | 343 log("debug", "Channel binding not supported by SASL handler"); |
| 310 end | 344 end |
