Annotate

plugins/mod_s2s_auth_dane_in.lua @ 13419:41a587613a0e

mod_smacks: Adjust buckets for resumption age statistic Given that there are recommendations floating around recommending 24 hours session lifetime, having buckets up to 10 minutes wouldn't be useful in that case. Would be nice if we had some way to automatically assign suitable number series for buckets, scaled to what the configuration might be.
author Kim Alvefur <zash@zash.se>
date Fri, 16 Feb 2024 00:15:36 +0100
parent 13417:b1e2dd6e735b
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
13297
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
1 module:set_global();
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
2
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
3 local dns = require "prosody.net.adns";
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
4 local async = require "prosody.util.async";
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
5 local encodings = require "prosody.util.encodings";
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
6 local hashes = require "prosody.util.hashes";
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
7 local promise = require "prosody.util.promise";
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
8 local x509 = require "prosody.util.x509";
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
9
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
10 local idna_to_ascii = encodings.idna.to_ascii;
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
11 local sha256 = hashes.sha256;
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
12 local sha512 = hashes.sha512;
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
13
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
14 local use_dane = module:get_option_boolean("use_dane", nil);
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
15 if use_dane == nil then
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
16 module:log("warn", "DANE support incomplete, add use_dane = true in the global section to support outgoing s2s connections");
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
17 elseif use_dane == false then
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
18 module:log("debug", "DANE support disabled with use_dane = false, disabling.")
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
19 return
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
20 end
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
21
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
22 local function ensure_secure(r)
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
23 assert(r.secure, "insecure");
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
24 return r;
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
25 end
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
26
13417
b1e2dd6e735b mod_s2s_auth_dane_in: Try single TLSA lookup per draft-ietf-dance-client-auth
Kim Alvefur <zash@zash.se>
parents: 13416
diff changeset
27 local function ensure_nonempty(r)
b1e2dd6e735b mod_s2s_auth_dane_in: Try single TLSA lookup per draft-ietf-dance-client-auth
Kim Alvefur <zash@zash.se>
parents: 13416
diff changeset
28 assert(r[1], "empty");
b1e2dd6e735b mod_s2s_auth_dane_in: Try single TLSA lookup per draft-ietf-dance-client-auth
Kim Alvefur <zash@zash.se>
parents: 13416
diff changeset
29 return r;
b1e2dd6e735b mod_s2s_auth_dane_in: Try single TLSA lookup per draft-ietf-dance-client-auth
Kim Alvefur <zash@zash.se>
parents: 13416
diff changeset
30 end
b1e2dd6e735b mod_s2s_auth_dane_in: Try single TLSA lookup per draft-ietf-dance-client-auth
Kim Alvefur <zash@zash.se>
parents: 13416
diff changeset
31
13416
d8e885db9851 mod_s2s_auth_dane_in: Simplify result processing
Kim Alvefur <zash@zash.se>
parents: 13322
diff changeset
32 local function flatten(a)
d8e885db9851 mod_s2s_auth_dane_in: Simplify result processing
Kim Alvefur <zash@zash.se>
parents: 13322
diff changeset
33 local seen = {};
d8e885db9851 mod_s2s_auth_dane_in: Simplify result processing
Kim Alvefur <zash@zash.se>
parents: 13322
diff changeset
34 local ret = {};
d8e885db9851 mod_s2s_auth_dane_in: Simplify result processing
Kim Alvefur <zash@zash.se>
parents: 13322
diff changeset
35 for _, rrset in ipairs(a) do
d8e885db9851 mod_s2s_auth_dane_in: Simplify result processing
Kim Alvefur <zash@zash.se>
parents: 13322
diff changeset
36 for _, rr in ipairs(rrset) do
d8e885db9851 mod_s2s_auth_dane_in: Simplify result processing
Kim Alvefur <zash@zash.se>
parents: 13322
diff changeset
37 if not seen[tostring(rr)] then
d8e885db9851 mod_s2s_auth_dane_in: Simplify result processing
Kim Alvefur <zash@zash.se>
parents: 13322
diff changeset
38 table.insert(ret, rr);
d8e885db9851 mod_s2s_auth_dane_in: Simplify result processing
Kim Alvefur <zash@zash.se>
parents: 13322
diff changeset
39 seen[tostring(rr)] = true;
d8e885db9851 mod_s2s_auth_dane_in: Simplify result processing
Kim Alvefur <zash@zash.se>
parents: 13322
diff changeset
40 end
d8e885db9851 mod_s2s_auth_dane_in: Simplify result processing
Kim Alvefur <zash@zash.se>
parents: 13322
diff changeset
41 end
d8e885db9851 mod_s2s_auth_dane_in: Simplify result processing
Kim Alvefur <zash@zash.se>
parents: 13322
diff changeset
42 end
d8e885db9851 mod_s2s_auth_dane_in: Simplify result processing
Kim Alvefur <zash@zash.se>
parents: 13322
diff changeset
43 return ret;
d8e885db9851 mod_s2s_auth_dane_in: Simplify result processing
Kim Alvefur <zash@zash.se>
parents: 13322
diff changeset
44 end
d8e885db9851 mod_s2s_auth_dane_in: Simplify result processing
Kim Alvefur <zash@zash.se>
parents: 13322
diff changeset
45
13297
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
46 local lazy_tlsa_mt = {
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
47 __index = function(t, i)
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
48 if i == 1 then
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
49 local h = sha256(t[0]);
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
50 t[1] = h;
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
51 return h;
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
52 elseif i == 2 then
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
53 local h = sha512(t[0]);
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
54 t[1] = h;
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
55 return h;
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
56 end
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
57 end;
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
58 }
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
59 local function lazy_hash(t)
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
60 return setmetatable(t, lazy_tlsa_mt);
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
61 end
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
62
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
63 module:hook("s2s-check-certificate", function(event)
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
64 local session, host, cert = event.session, event.host, event.cert;
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
65 local log = session.log or module._log;
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
66
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
67 if not host or not cert or session.direction ~= "incoming" then
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
68 return
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
69 end
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
70
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
71 local by_select_match = {
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
72 [0] = lazy_hash {
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
73 -- cert
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
74 [0] = x509.pem2der(cert:pem());
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
75
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
76 };
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
77 }
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
78 if cert.pubkey then
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
79 by_select_match[1] = lazy_hash {
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
80 -- spki
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
81 [0] = x509.pem2der(cert:pubkey());
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
82 };
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
83 end
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
84
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
85 local resolver = dns.resolver();
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
86
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
87 local dns_domain = idna_to_ascii(host);
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
88
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
89 local function fetch_tlsa(res)
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
90 local tlsas = {};
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
91 for _, rr in ipairs(res) do
13322
28211ed70b4c mod_s2s_auth_dane_in: Bail out on explicit service denial
Kim Alvefur <zash@zash.se>
parents: 13297
diff changeset
92 if rr.srv.target == "." then return {}; end
13297
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
93 table.insert(tlsas, resolver:lookup_promise(("_%d._tcp.%s"):format(rr.srv.port, rr.srv.target), "TLSA"):next(ensure_secure));
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
94 end
13416
d8e885db9851 mod_s2s_auth_dane_in: Simplify result processing
Kim Alvefur <zash@zash.se>
parents: 13322
diff changeset
95 return promise.all(tlsas):next(flatten);
13297
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
96 end
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
97
13417
b1e2dd6e735b mod_s2s_auth_dane_in: Try single TLSA lookup per draft-ietf-dance-client-auth
Kim Alvefur <zash@zash.se>
parents: 13416
diff changeset
98 local ret = async.wait_for(resolver:lookup_promise("_xmpp-server." .. dns_domain, "TLSA"):next(ensure_secure):next(ensure_nonempty):catch(function()
b1e2dd6e735b mod_s2s_auth_dane_in: Try single TLSA lookup per draft-ietf-dance-client-auth
Kim Alvefur <zash@zash.se>
parents: 13416
diff changeset
99 return promise.all({
b1e2dd6e735b mod_s2s_auth_dane_in: Try single TLSA lookup per draft-ietf-dance-client-auth
Kim Alvefur <zash@zash.se>
parents: 13416
diff changeset
100 resolver:lookup_promise("_xmpps-server._tcp." .. dns_domain, "SRV"):next(ensure_secure):next(fetch_tlsa);
b1e2dd6e735b mod_s2s_auth_dane_in: Try single TLSA lookup per draft-ietf-dance-client-auth
Kim Alvefur <zash@zash.se>
parents: 13416
diff changeset
101 resolver:lookup_promise("_xmpp-server._tcp." .. dns_domain, "SRV"):next(ensure_secure):next(fetch_tlsa);
b1e2dd6e735b mod_s2s_auth_dane_in: Try single TLSA lookup per draft-ietf-dance-client-auth
Kim Alvefur <zash@zash.se>
parents: 13416
diff changeset
102 }):next(flatten);
b1e2dd6e735b mod_s2s_auth_dane_in: Try single TLSA lookup per draft-ietf-dance-client-auth
Kim Alvefur <zash@zash.se>
parents: 13416
diff changeset
103 end));
13297
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
104
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
105 if not ret then
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
106 return
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
107 end
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
108
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
109 local found_supported = false;
13416
d8e885db9851 mod_s2s_auth_dane_in: Simplify result processing
Kim Alvefur <zash@zash.se>
parents: 13322
diff changeset
110 for _, rr in ipairs(ret) do
d8e885db9851 mod_s2s_auth_dane_in: Simplify result processing
Kim Alvefur <zash@zash.se>
parents: 13322
diff changeset
111 if rr.tlsa.use == 3 and by_select_match[rr.tlsa.select] and rr.tlsa.match <= 2 then
d8e885db9851 mod_s2s_auth_dane_in: Simplify result processing
Kim Alvefur <zash@zash.se>
parents: 13322
diff changeset
112 found_supported = true;
d8e885db9851 mod_s2s_auth_dane_in: Simplify result processing
Kim Alvefur <zash@zash.se>
parents: 13322
diff changeset
113 if rr.tlsa.data == by_select_match[rr.tlsa.select][rr.tlsa.match] then
d8e885db9851 mod_s2s_auth_dane_in: Simplify result processing
Kim Alvefur <zash@zash.se>
parents: 13322
diff changeset
114 module:log("debug", "%s matches", rr)
d8e885db9851 mod_s2s_auth_dane_in: Simplify result processing
Kim Alvefur <zash@zash.se>
parents: 13322
diff changeset
115 session.cert_chain_status = "valid";
d8e885db9851 mod_s2s_auth_dane_in: Simplify result processing
Kim Alvefur <zash@zash.se>
parents: 13322
diff changeset
116 session.cert_identity_status = "valid";
d8e885db9851 mod_s2s_auth_dane_in: Simplify result processing
Kim Alvefur <zash@zash.se>
parents: 13322
diff changeset
117 return true;
13297
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
118 end
13416
d8e885db9851 mod_s2s_auth_dane_in: Simplify result processing
Kim Alvefur <zash@zash.se>
parents: 13322
diff changeset
119 else
d8e885db9851 mod_s2s_auth_dane_in: Simplify result processing
Kim Alvefur <zash@zash.se>
parents: 13322
diff changeset
120 log("debug", "Unsupported DANE TLSA record: %s", rr);
13297
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
121 end
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
122 end
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
123
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
124 if found_supported then
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
125 session.cert_chain_status = "invalid";
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
126 session.cert_identity_status = nil;
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
127 return true;
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
128 end
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
129
7264c4d16072 mod_s2s_auth_dane_in: DANE support for s2sin
Kim Alvefur <zash@zash.se>
parents:
diff changeset
130 end, 800);