annotate mod_s2s_auth_dane/mod_s2s_auth_dane.lua @ 1944:1950fa6aa0c0

mod_s2s_auth_dane: Consider the current certificate chain status before checking PKIX-{EE,CA} TLSA records
author Kim Alvefur <zash@zash.se>
date Thu, 05 Nov 2015 15:38:31 +0100
parents 7e04ca0aa757
children 7974a24d29b6
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1258
fc82d8eded7d mod_s2s_auth_dane: Experimental DANE implementation
Kim Alvefur <zash@zash.se>
parents:
diff changeset
1 -- mod_s2s_auth_dane
1332
08a0241f5d2c mod_s2s_auth_dane: Add some comments
Kim Alvefur <zash@zash.se>
parents: 1330
diff changeset
2 -- Copyright (C) 2013-2014 Kim Alvefur
1258
fc82d8eded7d mod_s2s_auth_dane: Experimental DANE implementation
Kim Alvefur <zash@zash.se>
parents:
diff changeset
3 --
1332
08a0241f5d2c mod_s2s_auth_dane: Add some comments
Kim Alvefur <zash@zash.se>
parents: 1330
diff changeset
4 -- This file is MIT/X11 licensed.
08a0241f5d2c mod_s2s_auth_dane: Add some comments
Kim Alvefur <zash@zash.se>
parents: 1330
diff changeset
5 --
1370
e3fe6c749bc3 mod_s2s_auth_dane: Merge functionality from mod_s2s_auth_dnssec_srv
Kim Alvefur <zash@zash.se>
parents: 1368
diff changeset
6 -- Implements DANE and Secure Delegation using DNS SRV as described in
e3fe6c749bc3 mod_s2s_auth_dane: Merge functionality from mod_s2s_auth_dnssec_srv
Kim Alvefur <zash@zash.se>
parents: 1368
diff changeset
7 -- http://tools.ietf.org/html/draft-miller-xmpp-dnssec-prooftype
1349
350e903b14ff mod_s2s_auth_dane: Comments and TODOs
Kim Alvefur <zash@zash.se>
parents: 1348
diff changeset
8 --
350e903b14ff mod_s2s_auth_dane: Comments and TODOs
Kim Alvefur <zash@zash.se>
parents: 1348
diff changeset
9 -- Known issues:
1332
08a0241f5d2c mod_s2s_auth_dane: Add some comments
Kim Alvefur <zash@zash.se>
parents: 1330
diff changeset
10 -- Could be done much cleaner if mod_s2s was using util.async
1349
350e903b14ff mod_s2s_auth_dane: Comments and TODOs
Kim Alvefur <zash@zash.se>
parents: 1348
diff changeset
11 --
350e903b14ff mod_s2s_auth_dane: Comments and TODOs
Kim Alvefur <zash@zash.se>
parents: 1348
diff changeset
12 -- TODO Things to test/handle:
350e903b14ff mod_s2s_auth_dane: Comments and TODOs
Kim Alvefur <zash@zash.se>
parents: 1348
diff changeset
13 -- Negative or bogus answers
350e903b14ff mod_s2s_auth_dane: Comments and TODOs
Kim Alvefur <zash@zash.se>
parents: 1348
diff changeset
14 -- No encryption offered
350e903b14ff mod_s2s_auth_dane: Comments and TODOs
Kim Alvefur <zash@zash.se>
parents: 1348
diff changeset
15 -- Different hostname before and after STARTTLS - mod_s2s should complain
350e903b14ff mod_s2s_auth_dane: Comments and TODOs
Kim Alvefur <zash@zash.se>
parents: 1348
diff changeset
16 -- Interaction with Dialback
1758
7ba877e2d660 mod_s2s_auth_dane: Ignore mutating of the 'module' global, that is ok in prosody plugins [luacheck]
Kim Alvefur <zash@zash.se>
parents: 1757
diff changeset
17 --
7ba877e2d660 mod_s2s_auth_dane: Ignore mutating of the 'module' global, that is ok in prosody plugins [luacheck]
Kim Alvefur <zash@zash.se>
parents: 1757
diff changeset
18 -- luacheck: ignore module
1258
fc82d8eded7d mod_s2s_auth_dane: Experimental DANE implementation
Kim Alvefur <zash@zash.se>
parents:
diff changeset
19
fc82d8eded7d mod_s2s_auth_dane: Experimental DANE implementation
Kim Alvefur <zash@zash.se>
parents:
diff changeset
20 module:set_global();
fc82d8eded7d mod_s2s_auth_dane: Experimental DANE implementation
Kim Alvefur <zash@zash.se>
parents:
diff changeset
21
1626
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
22 local noop = function () end
1348
6191613959dc mod_s2s_auth_dane: Make supported DANE usages configurable, default to DANE-EE
Kim Alvefur <zash@zash.se>
parents: 1347
diff changeset
23 local type = type;
1351
a052740bbf48 mod_s2s_auth_dane: Back to _port._tcp.srvtarget.example.net
Kim Alvefur <zash@zash.se>
parents: 1350
diff changeset
24 local t_insert = table.insert;
1348
6191613959dc mod_s2s_auth_dane: Make supported DANE usages configurable, default to DANE-EE
Kim Alvefur <zash@zash.se>
parents: 1347
diff changeset
25 local set = require"util.set";
1258
fc82d8eded7d mod_s2s_auth_dane: Experimental DANE implementation
Kim Alvefur <zash@zash.se>
parents:
diff changeset
26 local dns_lookup = require"net.adns".lookup;
fc82d8eded7d mod_s2s_auth_dane: Experimental DANE implementation
Kim Alvefur <zash@zash.se>
parents:
diff changeset
27 local hashes = require"util.hashes";
1412
d85695be0441 Backout 33f132c3f4b7 until 0.10
Kim Alvefur <zash@zash.se>
parents: 1411
diff changeset
28 local base64 = require"util.encodings".base64;
1347
52b419885f0a mod_s2s_auth_dane: Simplify, but diverge from DANE-SRV draft. Will now look for _xmpp-server.example.com IN TLSA for both directions
Kim Alvefur <zash@zash.se>
parents: 1344
diff changeset
29 local idna_to_ascii = require "util.encodings".idna.to_ascii;
1370
e3fe6c749bc3 mod_s2s_auth_dane: Merge functionality from mod_s2s_auth_dnssec_srv
Kim Alvefur <zash@zash.se>
parents: 1368
diff changeset
30 local idna_to_unicode = require"util.encodings".idna.to_unicode;
e3fe6c749bc3 mod_s2s_auth_dane: Merge functionality from mod_s2s_auth_dnssec_srv
Kim Alvefur <zash@zash.se>
parents: 1368
diff changeset
31 local nameprep = require"util.encodings".stringprep.nameprep;
e3fe6c749bc3 mod_s2s_auth_dane: Merge functionality from mod_s2s_auth_dnssec_srv
Kim Alvefur <zash@zash.se>
parents: 1368
diff changeset
32 local cert_verify_identity = require "util.x509".verify_identity;
1258
fc82d8eded7d mod_s2s_auth_dane: Experimental DANE implementation
Kim Alvefur <zash@zash.se>
parents:
diff changeset
33
1410
f4e497a53c6e mod_s2s_auth_dane: Change how TLSA support is detected
Kim Alvefur <zash@zash.se>
parents: 1409
diff changeset
34 do
f4e497a53c6e mod_s2s_auth_dane: Change how TLSA support is detected
Kim Alvefur <zash@zash.se>
parents: 1409
diff changeset
35 local net_dns = require"net.dns";
f4e497a53c6e mod_s2s_auth_dane: Change how TLSA support is detected
Kim Alvefur <zash@zash.se>
parents: 1409
diff changeset
36 if not net_dns.types or not net_dns.types[52] then
f4e497a53c6e mod_s2s_auth_dane: Change how TLSA support is detected
Kim Alvefur <zash@zash.se>
parents: 1409
diff changeset
37 module:log("error", "No TLSA support available, DANE will not be supported");
f4e497a53c6e mod_s2s_auth_dane: Change how TLSA support is detected
Kim Alvefur <zash@zash.se>
parents: 1409
diff changeset
38 return
f4e497a53c6e mod_s2s_auth_dane: Change how TLSA support is detected
Kim Alvefur <zash@zash.se>
parents: 1409
diff changeset
39 end
1358
497e1df4b7ee mod_s2s_auth_dane: Abort module loading if luaunbound is unavailable
Kim Alvefur <zash@zash.se>
parents: 1356
diff changeset
40 end
497e1df4b7ee mod_s2s_auth_dane: Abort module loading if luaunbound is unavailable
Kim Alvefur <zash@zash.se>
parents: 1356
diff changeset
41
1412
d85695be0441 Backout 33f132c3f4b7 until 0.10
Kim Alvefur <zash@zash.se>
parents: 1411
diff changeset
42 local pat = "%-%-%-%-%-BEGIN ([A-Z ]+)%-%-%-%-%-\r?\n"..
d85695be0441 Backout 33f132c3f4b7 until 0.10
Kim Alvefur <zash@zash.se>
parents: 1411
diff changeset
43 "([0-9A-Za-z=+/\r\n]*)\r?\n%-%-%-%-%-END %1%-%-%-%-%-";
d85695be0441 Backout 33f132c3f4b7 until 0.10
Kim Alvefur <zash@zash.se>
parents: 1411
diff changeset
44 local function pem2der(pem)
d85695be0441 Backout 33f132c3f4b7 until 0.10
Kim Alvefur <zash@zash.se>
parents: 1411
diff changeset
45 local typ, data = pem:match(pat);
d85695be0441 Backout 33f132c3f4b7 until 0.10
Kim Alvefur <zash@zash.se>
parents: 1411
diff changeset
46 if typ and data then
d85695be0441 Backout 33f132c3f4b7 until 0.10
Kim Alvefur <zash@zash.se>
parents: 1411
diff changeset
47 return base64.decode(data), typ;
d85695be0441 Backout 33f132c3f4b7 until 0.10
Kim Alvefur <zash@zash.se>
parents: 1411
diff changeset
48 end
d85695be0441 Backout 33f132c3f4b7 until 0.10
Kim Alvefur <zash@zash.se>
parents: 1411
diff changeset
49 end
1348
6191613959dc mod_s2s_auth_dane: Make supported DANE usages configurable, default to DANE-EE
Kim Alvefur <zash@zash.se>
parents: 1347
diff changeset
50 local use_map = { ["DANE-EE"] = 3; ["DANE-TA"] = 2; ["PKIX-EE"] = 1; ["PKIX-CA"] = 0 }
6191613959dc mod_s2s_auth_dane: Make supported DANE usages configurable, default to DANE-EE
Kim Alvefur <zash@zash.se>
parents: 1347
diff changeset
51
6191613959dc mod_s2s_auth_dane: Make supported DANE usages configurable, default to DANE-EE
Kim Alvefur <zash@zash.se>
parents: 1347
diff changeset
52 local implemented_uses = set.new { "DANE-EE", "PKIX-EE" };
1502
72ef98818b90 mod_s2s_auth_dane: Fix traceback caused by LuaSec not being loaded
Kim Alvefur <zash@zash.se>
parents: 1437
diff changeset
53 do
72ef98818b90 mod_s2s_auth_dane: Fix traceback caused by LuaSec not being loaded
Kim Alvefur <zash@zash.se>
parents: 1437
diff changeset
54 local cert_mt = debug.getregistry()["SSL:Certificate"];
72ef98818b90 mod_s2s_auth_dane: Fix traceback caused by LuaSec not being loaded
Kim Alvefur <zash@zash.se>
parents: 1437
diff changeset
55 if cert_mt and cert_mt.__index.issued then
72ef98818b90 mod_s2s_auth_dane: Fix traceback caused by LuaSec not being loaded
Kim Alvefur <zash@zash.se>
parents: 1437
diff changeset
56 -- Need cert:issued() for these
72ef98818b90 mod_s2s_auth_dane: Fix traceback caused by LuaSec not being loaded
Kim Alvefur <zash@zash.se>
parents: 1437
diff changeset
57 implemented_uses:add("DANE-TA");
72ef98818b90 mod_s2s_auth_dane: Fix traceback caused by LuaSec not being loaded
Kim Alvefur <zash@zash.se>
parents: 1437
diff changeset
58 implemented_uses:add("PKIX-CA");
72ef98818b90 mod_s2s_auth_dane: Fix traceback caused by LuaSec not being loaded
Kim Alvefur <zash@zash.se>
parents: 1437
diff changeset
59 else
72ef98818b90 mod_s2s_auth_dane: Fix traceback caused by LuaSec not being loaded
Kim Alvefur <zash@zash.se>
parents: 1437
diff changeset
60 module:log("warn", "Unable to support DANE-TA and PKIX-CA");
72ef98818b90 mod_s2s_auth_dane: Fix traceback caused by LuaSec not being loaded
Kim Alvefur <zash@zash.se>
parents: 1437
diff changeset
61 end
1396
cf4e39334ef7 mod_s2s_auth_dane: Add support for DANE-TA and PKIX-CA (requires LuaSec changes)
Kim Alvefur <zash@zash.se>
parents: 1395
diff changeset
62 end
cf4e39334ef7 mod_s2s_auth_dane: Add support for DANE-TA and PKIX-CA (requires LuaSec changes)
Kim Alvefur <zash@zash.se>
parents: 1395
diff changeset
63 local configured_uses = module:get_option_set("dane_uses", { "DANE-EE", "DANE-TA" });
1348
6191613959dc mod_s2s_auth_dane: Make supported DANE usages configurable, default to DANE-EE
Kim Alvefur <zash@zash.se>
parents: 1347
diff changeset
64 local enabled_uses = set.intersection(implemented_uses, configured_uses) / function(use) return use_map[use] end;
1258
fc82d8eded7d mod_s2s_auth_dane: Experimental DANE implementation
Kim Alvefur <zash@zash.se>
parents:
diff changeset
65
1626
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
66 -- Find applicable TLSA records
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
67 -- Takes a s2sin/out and a callback
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
68 local function dane_lookup(host_session, cb)
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
69 cb = cb or noop;
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
70 if host_session.dane ~= nil then return end -- Has already done a lookup
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
71
1351
a052740bbf48 mod_s2s_auth_dane: Back to _port._tcp.srvtarget.example.net
Kim Alvefur <zash@zash.se>
parents: 1350
diff changeset
72 if host_session.direction == "incoming" then
1674
7f4c64cfed09 mod_s2s_auth_dane: Abort earlier for sessions from hosts that don't say who they are
Kim Alvefur <zash@zash.se>
parents: 1673
diff changeset
73 if not host_session.from_host then
7f4c64cfed09 mod_s2s_auth_dane: Abort earlier for sessions from hosts that don't say who they are
Kim Alvefur <zash@zash.se>
parents: 1673
diff changeset
74 module:log("debug", "Session doesn't have a 'from' host set");
7f4c64cfed09 mod_s2s_auth_dane: Abort earlier for sessions from hosts that don't say who they are
Kim Alvefur <zash@zash.se>
parents: 1673
diff changeset
75 return;
7f4c64cfed09 mod_s2s_auth_dane: Abort earlier for sessions from hosts that don't say who they are
Kim Alvefur <zash@zash.se>
parents: 1673
diff changeset
76 end
1626
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
77 -- We don't know what hostname or port to use for Incoming connections
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
78 -- so we do a SRV lookup and then request TLSA records for each SRV
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
79 -- Most servers will probably use the same certificate on outgoing
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
80 -- and incoming connections, so this should work well
1362
920ac9a8480b mod_s2s_auth_dane: Fix tb when no hostname sent by remote
Kim Alvefur <zash@zash.se>
parents: 1359
diff changeset
81 local name = host_session.from_host and idna_to_ascii(host_session.from_host);
1626
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
82 if not name then
1673
aac5e56615ce mod_s2s_auth_dane: Demote log message about failure to ASCII-ify hostname from error to warning
Kim Alvefur <zash@zash.se>
parents: 1652
diff changeset
83 module:log("warn", "Could not convert '%s' to ASCII for DNS lookup", tostring(host_session.from_host));
aac5e56615ce mod_s2s_auth_dane: Demote log message about failure to ASCII-ify hostname from error to warning
Kim Alvefur <zash@zash.se>
parents: 1652
diff changeset
84 return;
aac5e56615ce mod_s2s_auth_dane: Demote log message about failure to ASCII-ify hostname from error to warning
Kim Alvefur <zash@zash.se>
parents: 1652
diff changeset
85 end
1626
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
86 host_session.dane = dns_lookup(function (answer, err)
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
87 host_session.dane = false; -- Mark that we already did the lookup
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
88
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
89 if not answer then
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
90 module:log("debug", "Resolver error: %s", tostring(err));
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
91 return cb(host_session);
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
92 end
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
93
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
94 if not answer.secure then
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
95 module:log("debug", "Results are not secure");
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
96 return cb(host_session);
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
97 end
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
98
1700
ab3175685f94 mod_s2s_auth_dane: Don't count number of RRs in DNS reply if the DNS lib already did
Kim Alvefur <zash@zash.se>
parents: 1674
diff changeset
99 local n = answer.n or #answer;
1626
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
100 if n == 0 then
1943
7e04ca0aa757 mod_s2s_auth_dane: Support servers without SRV records by falling back to port 5269 and the bare hostname for TLSA lookups
Kim Alvefur <zash@zash.se>
parents: 1758
diff changeset
101 -- No SRV records, synthesize fallback host and port
7e04ca0aa757 mod_s2s_auth_dane: Support servers without SRV records by falling back to port 5269 and the bare hostname for TLSA lookups
Kim Alvefur <zash@zash.se>
parents: 1758
diff changeset
102 -- this may behave oddly for connections in the other direction if
7e04ca0aa757 mod_s2s_auth_dane: Support servers without SRV records by falling back to port 5269 and the bare hostname for TLSA lookups
Kim Alvefur <zash@zash.se>
parents: 1758
diff changeset
103 -- mod_s2s doesn't keep the answer around
7e04ca0aa757 mod_s2s_auth_dane: Support servers without SRV records by falling back to port 5269 and the bare hostname for TLSA lookups
Kim Alvefur <zash@zash.se>
parents: 1758
diff changeset
104 answer[1] = { srv = { target = name, port = 5269 } };
7e04ca0aa757 mod_s2s_auth_dane: Support servers without SRV records by falling back to port 5269 and the bare hostname for TLSA lookups
Kim Alvefur <zash@zash.se>
parents: 1758
diff changeset
105 n = 1;
7e04ca0aa757 mod_s2s_auth_dane: Support servers without SRV records by falling back to port 5269 and the bare hostname for TLSA lookups
Kim Alvefur <zash@zash.se>
parents: 1758
diff changeset
106 elseif n == 1 and answer[1].srv.target == '.' then
1626
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
107 return cb(host_session); -- No service ... This shouldn't happen?
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
108 end
1351
a052740bbf48 mod_s2s_auth_dane: Back to _port._tcp.srvtarget.example.net
Kim Alvefur <zash@zash.se>
parents: 1350
diff changeset
109 local srv_hosts = { answer = answer };
a052740bbf48 mod_s2s_auth_dane: Back to _port._tcp.srvtarget.example.net
Kim Alvefur <zash@zash.se>
parents: 1350
diff changeset
110 host_session.srv_hosts = srv_hosts;
1701
9b429fc9e8a0 mod_s2s_auth_dane: Simplify cases where there are only one SRV record
Kim Alvefur <zash@zash.se>
parents: 1700
diff changeset
111 local dane;
1351
a052740bbf48 mod_s2s_auth_dane: Back to _port._tcp.srvtarget.example.net
Kim Alvefur <zash@zash.se>
parents: 1350
diff changeset
112 for _, record in ipairs(answer) do
a052740bbf48 mod_s2s_auth_dane: Back to _port._tcp.srvtarget.example.net
Kim Alvefur <zash@zash.se>
parents: 1350
diff changeset
113 t_insert(srv_hosts, record.srv);
a052740bbf48 mod_s2s_auth_dane: Back to _port._tcp.srvtarget.example.net
Kim Alvefur <zash@zash.se>
parents: 1350
diff changeset
114 dns_lookup(function(dane_answer)
a052740bbf48 mod_s2s_auth_dane: Back to _port._tcp.srvtarget.example.net
Kim Alvefur <zash@zash.se>
parents: 1350
diff changeset
115 n = n - 1;
1701
9b429fc9e8a0 mod_s2s_auth_dane: Simplify cases where there are only one SRV record
Kim Alvefur <zash@zash.se>
parents: 1700
diff changeset
116 -- There are three kinds of answers
9b429fc9e8a0 mod_s2s_auth_dane: Simplify cases where there are only one SRV record
Kim Alvefur <zash@zash.se>
parents: 1700
diff changeset
117 -- Insecure, Secure and Bogus
9b429fc9e8a0 mod_s2s_auth_dane: Simplify cases where there are only one SRV record
Kim Alvefur <zash@zash.se>
parents: 1700
diff changeset
118 --
9b429fc9e8a0 mod_s2s_auth_dane: Simplify cases where there are only one SRV record
Kim Alvefur <zash@zash.se>
parents: 1700
diff changeset
119 -- We collect Secure answers for later use
9b429fc9e8a0 mod_s2s_auth_dane: Simplify cases where there are only one SRV record
Kim Alvefur <zash@zash.se>
parents: 1700
diff changeset
120 --
9b429fc9e8a0 mod_s2s_auth_dane: Simplify cases where there are only one SRV record
Kim Alvefur <zash@zash.se>
parents: 1700
diff changeset
121 -- Insecure (legacy) answers are simply ignored
9b429fc9e8a0 mod_s2s_auth_dane: Simplify cases where there are only one SRV record
Kim Alvefur <zash@zash.se>
parents: 1700
diff changeset
122 --
9b429fc9e8a0 mod_s2s_auth_dane: Simplify cases where there are only one SRV record
Kim Alvefur <zash@zash.se>
parents: 1700
diff changeset
123 -- If we get a Bogus (dnssec error) reply, keep the
9b429fc9e8a0 mod_s2s_auth_dane: Simplify cases where there are only one SRV record
Kim Alvefur <zash@zash.se>
parents: 1700
diff changeset
124 -- status around. If there were only bogus replies, the
9b429fc9e8a0 mod_s2s_auth_dane: Simplify cases where there are only one SRV record
Kim Alvefur <zash@zash.se>
parents: 1700
diff changeset
125 -- connection will be aborted. If there were at least
9b429fc9e8a0 mod_s2s_auth_dane: Simplify cases where there are only one SRV record
Kim Alvefur <zash@zash.se>
parents: 1700
diff changeset
126 -- one non-Bogus reply, we proceed. If none of the
9b429fc9e8a0 mod_s2s_auth_dane: Simplify cases where there are only one SRV record
Kim Alvefur <zash@zash.se>
parents: 1700
diff changeset
127 -- replies matched, we consider the connection insecure.
9b429fc9e8a0 mod_s2s_auth_dane: Simplify cases where there are only one SRV record
Kim Alvefur <zash@zash.se>
parents: 1700
diff changeset
128
9b429fc9e8a0 mod_s2s_auth_dane: Simplify cases where there are only one SRV record
Kim Alvefur <zash@zash.se>
parents: 1700
diff changeset
129 if (dane_answer.bogus or dane_answer.secure) and not dane then
9b429fc9e8a0 mod_s2s_auth_dane: Simplify cases where there are only one SRV record
Kim Alvefur <zash@zash.se>
parents: 1700
diff changeset
130 -- The first answer we care about
9b429fc9e8a0 mod_s2s_auth_dane: Simplify cases where there are only one SRV record
Kim Alvefur <zash@zash.se>
parents: 1700
diff changeset
131 -- For services with only one SRV record, this will be the only one
9b429fc9e8a0 mod_s2s_auth_dane: Simplify cases where there are only one SRV record
Kim Alvefur <zash@zash.se>
parents: 1700
diff changeset
132 dane = dane_answer;
9b429fc9e8a0 mod_s2s_auth_dane: Simplify cases where there are only one SRV record
Kim Alvefur <zash@zash.se>
parents: 1700
diff changeset
133 elseif dane_answer.bogus then
1626
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
134 dane.bogus = dane_answer.bogus;
1351
a052740bbf48 mod_s2s_auth_dane: Back to _port._tcp.srvtarget.example.net
Kim Alvefur <zash@zash.se>
parents: 1350
diff changeset
135 elseif dane_answer.secure then
1652
9a3d2f1479a4 mod_s2s_auth_dane: Cleanup [luacheck]
Kim Alvefur <zash@zash.se>
parents: 1642
diff changeset
136 for _, dane_record in ipairs(dane_answer) do
9a3d2f1479a4 mod_s2s_auth_dane: Cleanup [luacheck]
Kim Alvefur <zash@zash.se>
parents: 1642
diff changeset
137 t_insert(dane, dane_record);
1351
a052740bbf48 mod_s2s_auth_dane: Back to _port._tcp.srvtarget.example.net
Kim Alvefur <zash@zash.se>
parents: 1350
diff changeset
138 end
a052740bbf48 mod_s2s_auth_dane: Back to _port._tcp.srvtarget.example.net
Kim Alvefur <zash@zash.se>
parents: 1350
diff changeset
139 end
1626
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
140 if n == 0 then
1701
9b429fc9e8a0 mod_s2s_auth_dane: Simplify cases where there are only one SRV record
Kim Alvefur <zash@zash.se>
parents: 1700
diff changeset
141 if dane then
9b429fc9e8a0 mod_s2s_auth_dane: Simplify cases where there are only one SRV record
Kim Alvefur <zash@zash.se>
parents: 1700
diff changeset
142 host_session.dane = dane;
9b429fc9e8a0 mod_s2s_auth_dane: Simplify cases where there are only one SRV record
Kim Alvefur <zash@zash.se>
parents: 1700
diff changeset
143 if #dane > 0 and dane.bogus then
9b429fc9e8a0 mod_s2s_auth_dane: Simplify cases where there are only one SRV record
Kim Alvefur <zash@zash.se>
parents: 1700
diff changeset
144 -- Got at least one non-bogus reply,
9b429fc9e8a0 mod_s2s_auth_dane: Simplify cases where there are only one SRV record
Kim Alvefur <zash@zash.se>
parents: 1700
diff changeset
145 -- This should trigger a failure if one of them did not match
9b429fc9e8a0 mod_s2s_auth_dane: Simplify cases where there are only one SRV record
Kim Alvefur <zash@zash.se>
parents: 1700
diff changeset
146 host_session.log("warn", "Ignoring bogus replies");
9b429fc9e8a0 mod_s2s_auth_dane: Simplify cases where there are only one SRV record
Kim Alvefur <zash@zash.se>
parents: 1700
diff changeset
147 dane.bogus = nil;
9b429fc9e8a0 mod_s2s_auth_dane: Simplify cases where there are only one SRV record
Kim Alvefur <zash@zash.se>
parents: 1700
diff changeset
148 end
9b429fc9e8a0 mod_s2s_auth_dane: Simplify cases where there are only one SRV record
Kim Alvefur <zash@zash.se>
parents: 1700
diff changeset
149 if #dane == 0 and dane.bogus == nil then
9b429fc9e8a0 mod_s2s_auth_dane: Simplify cases where there are only one SRV record
Kim Alvefur <zash@zash.se>
parents: 1700
diff changeset
150 -- Got no usable data
9b429fc9e8a0 mod_s2s_auth_dane: Simplify cases where there are only one SRV record
Kim Alvefur <zash@zash.se>
parents: 1700
diff changeset
151 host_session.dane = false;
9b429fc9e8a0 mod_s2s_auth_dane: Simplify cases where there are only one SRV record
Kim Alvefur <zash@zash.se>
parents: 1700
diff changeset
152 end
1626
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
153 end
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
154 return cb(host_session);
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
155 end
1351
a052740bbf48 mod_s2s_auth_dane: Back to _port._tcp.srvtarget.example.net
Kim Alvefur <zash@zash.se>
parents: 1350
diff changeset
156 end, ("_%d._tcp.%s."):format(record.srv.port, record.srv.target), "TLSA");
a052740bbf48 mod_s2s_auth_dane: Back to _port._tcp.srvtarget.example.net
Kim Alvefur <zash@zash.se>
parents: 1350
diff changeset
157 end
a052740bbf48 mod_s2s_auth_dane: Back to _port._tcp.srvtarget.example.net
Kim Alvefur <zash@zash.se>
parents: 1350
diff changeset
158 end, "_xmpp-server._tcp."..name..".", "SRV");
a052740bbf48 mod_s2s_auth_dane: Back to _port._tcp.srvtarget.example.net
Kim Alvefur <zash@zash.se>
parents: 1350
diff changeset
159 return true;
a052740bbf48 mod_s2s_auth_dane: Back to _port._tcp.srvtarget.example.net
Kim Alvefur <zash@zash.se>
parents: 1350
diff changeset
160 elseif host_session.direction == "outgoing" then
1626
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
161 -- Prosody has already done SRV lookups for outgoing session, so check if those are secure
1359
74769c0c79f8 mod_s2s_auth_dane: Verify that the SRV is secure
Kim Alvefur <zash@zash.se>
parents: 1358
diff changeset
162 local srv_hosts = host_session.srv_hosts;
1626
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
163 if not ( srv_hosts and srv_hosts.answer and srv_hosts.answer.secure ) then
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
164 return; -- No secure SRV records, fall back to non-DANE mode
1943
7e04ca0aa757 mod_s2s_auth_dane: Support servers without SRV records by falling back to port 5269 and the bare hostname for TLSA lookups
Kim Alvefur <zash@zash.se>
parents: 1758
diff changeset
165 -- Empty response were not kept by older mod_s2s/s2sout
1626
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
166 end
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
167 -- Do TLSA lookup for currently selected SRV record
1943
7e04ca0aa757 mod_s2s_auth_dane: Support servers without SRV records by falling back to port 5269 and the bare hostname for TLSA lookups
Kim Alvefur <zash@zash.se>
parents: 1758
diff changeset
168 local srv_choice = srv_hosts[host_session.srv_choice or 0] or { target = idna_to_ascii(host_session.to_host), port = 5269 };
1351
a052740bbf48 mod_s2s_auth_dane: Back to _port._tcp.srvtarget.example.net
Kim Alvefur <zash@zash.se>
parents: 1350
diff changeset
169 host_session.dane = dns_lookup(function(answer)
1409
151aa00559d1 mod_s2s_auth_dane: Fix logic precedence issue
Kim Alvefur <zash@zash.se>
parents: 1396
diff changeset
170 if answer and ((answer.secure and #answer > 0) or answer.bogus) then
1351
a052740bbf48 mod_s2s_auth_dane: Back to _port._tcp.srvtarget.example.net
Kim Alvefur <zash@zash.se>
parents: 1350
diff changeset
171 srv_choice.dane = answer;
a052740bbf48 mod_s2s_auth_dane: Back to _port._tcp.srvtarget.example.net
Kim Alvefur <zash@zash.se>
parents: 1350
diff changeset
172 else
a052740bbf48 mod_s2s_auth_dane: Back to _port._tcp.srvtarget.example.net
Kim Alvefur <zash@zash.se>
parents: 1350
diff changeset
173 srv_choice.dane = false;
a052740bbf48 mod_s2s_auth_dane: Back to _port._tcp.srvtarget.example.net
Kim Alvefur <zash@zash.se>
parents: 1350
diff changeset
174 end
a052740bbf48 mod_s2s_auth_dane: Back to _port._tcp.srvtarget.example.net
Kim Alvefur <zash@zash.se>
parents: 1350
diff changeset
175 host_session.dane = srv_choice.dane;
1626
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
176 return cb(host_session);
1351
a052740bbf48 mod_s2s_auth_dane: Back to _port._tcp.srvtarget.example.net
Kim Alvefur <zash@zash.se>
parents: 1350
diff changeset
177 end, ("_%d._tcp.%s."):format(srv_choice.port, srv_choice.target), "TLSA");
a052740bbf48 mod_s2s_auth_dane: Back to _port._tcp.srvtarget.example.net
Kim Alvefur <zash@zash.se>
parents: 1350
diff changeset
178 return true;
a052740bbf48 mod_s2s_auth_dane: Back to _port._tcp.srvtarget.example.net
Kim Alvefur <zash@zash.se>
parents: 1350
diff changeset
179 end
1347
52b419885f0a mod_s2s_auth_dane: Simplify, but diverge from DANE-SRV draft. Will now look for _xmpp-server.example.com IN TLSA for both directions
Kim Alvefur <zash@zash.se>
parents: 1344
diff changeset
180 end
52b419885f0a mod_s2s_auth_dane: Simplify, but diverge from DANE-SRV draft. Will now look for _xmpp-server.example.com IN TLSA for both directions
Kim Alvefur <zash@zash.se>
parents: 1344
diff changeset
181
1626
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
182 local function resume(host_session)
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
183 host_session.log("debug", "DANE lookup completed, resuming connection");
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
184 host_session.conn:resume()
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
185 end
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
186
1347
52b419885f0a mod_s2s_auth_dane: Simplify, but diverge from DANE-SRV draft. Will now look for _xmpp-server.example.com IN TLSA for both directions
Kim Alvefur <zash@zash.se>
parents: 1344
diff changeset
187 function module.add_host(module)
1394
50f986deb3f7 mod_s2s_auth_dane: Launch DANE queries when sending or receiving stream-features instead of monkeypatching s2sout.lib
Kim Alvefur <zash@zash.se>
parents: 1392
diff changeset
188 local function on_new_s2s(event)
1367
103d685e2153 mod_s2s_auth_dane: Pause s2sin while doing SRV and TLSA lookups, fixes race condition (Can haz util.async plz)
Kim Alvefur <zash@zash.se>
parents: 1362
diff changeset
189 local host_session = event.origin;
1626
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
190 if host_session.type == "s2sout" or host_session.type == "s2sin" then
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
191 return; -- Already authenticated
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
192 end
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
193 if host_session.dane ~= nil then
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
194 return; -- Already done DANE lookup
1367
103d685e2153 mod_s2s_auth_dane: Pause s2sin while doing SRV and TLSA lookups, fixes race condition (Can haz util.async plz)
Kim Alvefur <zash@zash.se>
parents: 1362
diff changeset
195 end
1435
cdc8f226a284 mod_s2s_auth_dane: Pause connection only if needed
Kim Alvefur <zash@zash.se>
parents: 1434
diff changeset
196 if dane_lookup(host_session, resume) then
cdc8f226a284 mod_s2s_auth_dane: Pause connection only if needed
Kim Alvefur <zash@zash.se>
parents: 1434
diff changeset
197 host_session.log("debug", "Pausing connection until DANE lookup is completed");
cdc8f226a284 mod_s2s_auth_dane: Pause connection only if needed
Kim Alvefur <zash@zash.se>
parents: 1434
diff changeset
198 host_session.conn:pause()
1367
103d685e2153 mod_s2s_auth_dane: Pause s2sin while doing SRV and TLSA lookups, fixes race condition (Can haz util.async plz)
Kim Alvefur <zash@zash.se>
parents: 1362
diff changeset
199 end
1394
50f986deb3f7 mod_s2s_auth_dane: Launch DANE queries when sending or receiving stream-features instead of monkeypatching s2sout.lib
Kim Alvefur <zash@zash.se>
parents: 1392
diff changeset
200 end
50f986deb3f7 mod_s2s_auth_dane: Launch DANE queries when sending or receiving stream-features instead of monkeypatching s2sout.lib
Kim Alvefur <zash@zash.se>
parents: 1392
diff changeset
201
50f986deb3f7 mod_s2s_auth_dane: Launch DANE queries when sending or receiving stream-features instead of monkeypatching s2sout.lib
Kim Alvefur <zash@zash.se>
parents: 1392
diff changeset
202 -- New outgoing connections
50f986deb3f7 mod_s2s_auth_dane: Launch DANE queries when sending or receiving stream-features instead of monkeypatching s2sout.lib
Kim Alvefur <zash@zash.se>
parents: 1392
diff changeset
203 module:hook("stanza/http://etherx.jabber.org/streams:features", on_new_s2s, 501);
50f986deb3f7 mod_s2s_auth_dane: Launch DANE queries when sending or receiving stream-features instead of monkeypatching s2sout.lib
Kim Alvefur <zash@zash.se>
parents: 1392
diff changeset
204 module:hook("s2sout-authenticate-legacy", on_new_s2s, 200);
50f986deb3f7 mod_s2s_auth_dane: Launch DANE queries when sending or receiving stream-features instead of monkeypatching s2sout.lib
Kim Alvefur <zash@zash.se>
parents: 1392
diff changeset
205
50f986deb3f7 mod_s2s_auth_dane: Launch DANE queries when sending or receiving stream-features instead of monkeypatching s2sout.lib
Kim Alvefur <zash@zash.se>
parents: 1392
diff changeset
206 -- New incoming connections
50f986deb3f7 mod_s2s_auth_dane: Launch DANE queries when sending or receiving stream-features instead of monkeypatching s2sout.lib
Kim Alvefur <zash@zash.se>
parents: 1392
diff changeset
207 module:hook("s2s-stream-features", on_new_s2s, 10);
1347
52b419885f0a mod_s2s_auth_dane: Simplify, but diverge from DANE-SRV draft. Will now look for _xmpp-server.example.com IN TLSA for both directions
Kim Alvefur <zash@zash.se>
parents: 1344
diff changeset
208
52b419885f0a mod_s2s_auth_dane: Simplify, but diverge from DANE-SRV draft. Will now look for _xmpp-server.example.com IN TLSA for both directions
Kim Alvefur <zash@zash.se>
parents: 1344
diff changeset
209 module:hook("s2s-authenticated", function(event)
52b419885f0a mod_s2s_auth_dane: Simplify, but diverge from DANE-SRV draft. Will now look for _xmpp-server.example.com IN TLSA for both directions
Kim Alvefur <zash@zash.se>
parents: 1344
diff changeset
210 local session = event.session;
1626
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
211 if session.dane and next(session.dane) ~= nil and not session.secure then
1347
52b419885f0a mod_s2s_auth_dane: Simplify, but diverge from DANE-SRV draft. Will now look for _xmpp-server.example.com IN TLSA for both directions
Kim Alvefur <zash@zash.se>
parents: 1344
diff changeset
212 -- TLSA record but no TLS, not ok.
52b419885f0a mod_s2s_auth_dane: Simplify, but diverge from DANE-SRV draft. Will now look for _xmpp-server.example.com IN TLSA for both directions
Kim Alvefur <zash@zash.se>
parents: 1344
diff changeset
213 -- TODO Optional?
52b419885f0a mod_s2s_auth_dane: Simplify, but diverge from DANE-SRV draft. Will now look for _xmpp-server.example.com IN TLSA for both directions
Kim Alvefur <zash@zash.se>
parents: 1344
diff changeset
214 -- Bogus replies should trigger this path
52b419885f0a mod_s2s_auth_dane: Simplify, but diverge from DANE-SRV draft. Will now look for _xmpp-server.example.com IN TLSA for both directions
Kim Alvefur <zash@zash.se>
parents: 1344
diff changeset
215 -- How does this interact with Dialback?
52b419885f0a mod_s2s_auth_dane: Simplify, but diverge from DANE-SRV draft. Will now look for _xmpp-server.example.com IN TLSA for both directions
Kim Alvefur <zash@zash.se>
parents: 1344
diff changeset
216 session:close({
52b419885f0a mod_s2s_auth_dane: Simplify, but diverge from DANE-SRV draft. Will now look for _xmpp-server.example.com IN TLSA for both directions
Kim Alvefur <zash@zash.se>
parents: 1344
diff changeset
217 condition = "policy-violation",
52b419885f0a mod_s2s_auth_dane: Simplify, but diverge from DANE-SRV draft. Will now look for _xmpp-server.example.com IN TLSA for both directions
Kim Alvefur <zash@zash.se>
parents: 1344
diff changeset
218 text = "Encrypted server-to-server communication is required but was not "
52b419885f0a mod_s2s_auth_dane: Simplify, but diverge from DANE-SRV draft. Will now look for _xmpp-server.example.com IN TLSA for both directions
Kim Alvefur <zash@zash.se>
parents: 1344
diff changeset
219 ..((session.direction == "outgoing" and "offered") or "used")
52b419885f0a mod_s2s_auth_dane: Simplify, but diverge from DANE-SRV draft. Will now look for _xmpp-server.example.com IN TLSA for both directions
Kim Alvefur <zash@zash.se>
parents: 1344
diff changeset
220 });
52b419885f0a mod_s2s_auth_dane: Simplify, but diverge from DANE-SRV draft. Will now look for _xmpp-server.example.com IN TLSA for both directions
Kim Alvefur <zash@zash.se>
parents: 1344
diff changeset
221 return false;
52b419885f0a mod_s2s_auth_dane: Simplify, but diverge from DANE-SRV draft. Will now look for _xmpp-server.example.com IN TLSA for both directions
Kim Alvefur <zash@zash.se>
parents: 1344
diff changeset
222 end
1392
d99c10fc4d19 mod_s2s_auth_dane: Clean up no longer needed DNS replies
Kim Alvefur <zash@zash.se>
parents: 1391
diff changeset
223 -- Cleanup
d99c10fc4d19 mod_s2s_auth_dane: Clean up no longer needed DNS replies
Kim Alvefur <zash@zash.se>
parents: 1391
diff changeset
224 session.dane = nil;
d99c10fc4d19 mod_s2s_auth_dane: Clean up no longer needed DNS replies
Kim Alvefur <zash@zash.se>
parents: 1391
diff changeset
225 session.srv_hosts = nil;
1347
52b419885f0a mod_s2s_auth_dane: Simplify, but diverge from DANE-SRV draft. Will now look for _xmpp-server.example.com IN TLSA for both directions
Kim Alvefur <zash@zash.se>
parents: 1344
diff changeset
226 end);
1258
fc82d8eded7d mod_s2s_auth_dane: Experimental DANE implementation
Kim Alvefur <zash@zash.se>
parents:
diff changeset
227 end
fc82d8eded7d mod_s2s_auth_dane: Experimental DANE implementation
Kim Alvefur <zash@zash.se>
parents:
diff changeset
228
1626
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
229 -- Compare one TLSA record against a certificate
1389
6bd9681d54b7 mod_s2s_auth_dane: Break out DANE check into a function
Kim Alvefur <zash@zash.se>
parents: 1383
diff changeset
230 local function one_dane_check(tlsa, cert)
6bd9681d54b7 mod_s2s_auth_dane: Break out DANE check into a function
Kim Alvefur <zash@zash.se>
parents: 1383
diff changeset
231 local select, match, certdata = tlsa.select, tlsa.match;
6bd9681d54b7 mod_s2s_auth_dane: Break out DANE check into a function
Kim Alvefur <zash@zash.se>
parents: 1383
diff changeset
232
6bd9681d54b7 mod_s2s_auth_dane: Break out DANE check into a function
Kim Alvefur <zash@zash.se>
parents: 1383
diff changeset
233 if select == 0 then
6bd9681d54b7 mod_s2s_auth_dane: Break out DANE check into a function
Kim Alvefur <zash@zash.se>
parents: 1383
diff changeset
234 certdata = pem2der(cert:pem());
6bd9681d54b7 mod_s2s_auth_dane: Break out DANE check into a function
Kim Alvefur <zash@zash.se>
parents: 1383
diff changeset
235 elseif select == 1 and cert.pubkey then
6bd9681d54b7 mod_s2s_auth_dane: Break out DANE check into a function
Kim Alvefur <zash@zash.se>
parents: 1383
diff changeset
236 certdata = pem2der(cert:pubkey());
6bd9681d54b7 mod_s2s_auth_dane: Break out DANE check into a function
Kim Alvefur <zash@zash.se>
parents: 1383
diff changeset
237 else
6bd9681d54b7 mod_s2s_auth_dane: Break out DANE check into a function
Kim Alvefur <zash@zash.se>
parents: 1383
diff changeset
238 module:log("warn", "DANE selector %s is unsupported", tlsa:getSelector() or select);
6bd9681d54b7 mod_s2s_auth_dane: Break out DANE check into a function
Kim Alvefur <zash@zash.se>
parents: 1383
diff changeset
239 return;
6bd9681d54b7 mod_s2s_auth_dane: Break out DANE check into a function
Kim Alvefur <zash@zash.se>
parents: 1383
diff changeset
240 end
6bd9681d54b7 mod_s2s_auth_dane: Break out DANE check into a function
Kim Alvefur <zash@zash.se>
parents: 1383
diff changeset
241
6bd9681d54b7 mod_s2s_auth_dane: Break out DANE check into a function
Kim Alvefur <zash@zash.se>
parents: 1383
diff changeset
242 if match == 1 then
6bd9681d54b7 mod_s2s_auth_dane: Break out DANE check into a function
Kim Alvefur <zash@zash.se>
parents: 1383
diff changeset
243 certdata = hashes.sha256(certdata);
6bd9681d54b7 mod_s2s_auth_dane: Break out DANE check into a function
Kim Alvefur <zash@zash.se>
parents: 1383
diff changeset
244 elseif match == 2 then
6bd9681d54b7 mod_s2s_auth_dane: Break out DANE check into a function
Kim Alvefur <zash@zash.se>
parents: 1383
diff changeset
245 certdata = hashes.sha512(certdata);
6bd9681d54b7 mod_s2s_auth_dane: Break out DANE check into a function
Kim Alvefur <zash@zash.se>
parents: 1383
diff changeset
246 elseif match ~= 0 then
6bd9681d54b7 mod_s2s_auth_dane: Break out DANE check into a function
Kim Alvefur <zash@zash.se>
parents: 1383
diff changeset
247 module:log("warn", "DANE match rule %s is unsupported", tlsa:getMatchType() or match);
6bd9681d54b7 mod_s2s_auth_dane: Break out DANE check into a function
Kim Alvefur <zash@zash.se>
parents: 1383
diff changeset
248 return;
6bd9681d54b7 mod_s2s_auth_dane: Break out DANE check into a function
Kim Alvefur <zash@zash.se>
parents: 1383
diff changeset
249 end
6bd9681d54b7 mod_s2s_auth_dane: Break out DANE check into a function
Kim Alvefur <zash@zash.se>
parents: 1383
diff changeset
250
1626
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
251 if #certdata ~= #tlsa.data then
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
252 module:log("warn", "Length mismatch: Cert: %d, TLSA: %d", #certdata, #tlsa.data);
aed20f9e78c8 mod_s2s_auth_dane: Comments and cleanup
Kim Alvefur <zash@zash.se>
parents: 1507
diff changeset
253 end
1389
6bd9681d54b7 mod_s2s_auth_dane: Break out DANE check into a function
Kim Alvefur <zash@zash.se>
parents: 1383
diff changeset
254 return certdata == tlsa.data;
6bd9681d54b7 mod_s2s_auth_dane: Break out DANE check into a function
Kim Alvefur <zash@zash.se>
parents: 1383
diff changeset
255 end
6bd9681d54b7 mod_s2s_auth_dane: Break out DANE check into a function
Kim Alvefur <zash@zash.se>
parents: 1383
diff changeset
256
1258
fc82d8eded7d mod_s2s_auth_dane: Experimental DANE implementation
Kim Alvefur <zash@zash.se>
parents:
diff changeset
257 module:hook("s2s-check-certificate", function(event)
1437
161bbe0b9dd3 mod_s2s_auth_dane: Tweak log messages
Kim Alvefur <zash@zash.se>
parents: 1436
diff changeset
258 local session, cert, host = event.session, event.cert, event.host;
1434
1caf971a2f0f mod_s2s_auth_dane: Return if no certificate found
Kim Alvefur <zash@zash.se>
parents: 1431
diff changeset
259 if not cert then return end
1431
33a796b2cb91 mod_s2s_auth_dane: Cache logger to save some table lookups and improve readability
Kim Alvefur <zash@zash.se>
parents: 1415
diff changeset
260 local log = session.log or module._log;
1347
52b419885f0a mod_s2s_auth_dane: Simplify, but diverge from DANE-SRV draft. Will now look for _xmpp-server.example.com IN TLSA for both directions
Kim Alvefur <zash@zash.se>
parents: 1344
diff changeset
261 local dane = session.dane;
52b419885f0a mod_s2s_auth_dane: Simplify, but diverge from DANE-SRV draft. Will now look for _xmpp-server.example.com IN TLSA for both directions
Kim Alvefur <zash@zash.se>
parents: 1344
diff changeset
262 if type(dane) == "table" then
1642
a4a6b4be973a mod_s2s_auth_dane: Update for recent changes in Zashs LuaSec branch
Kim Alvefur <zash@zash.se>
parents: 1626
diff changeset
263 local match_found, supported_found;
1347
52b419885f0a mod_s2s_auth_dane: Simplify, but diverge from DANE-SRV draft. Will now look for _xmpp-server.example.com IN TLSA for both directions
Kim Alvefur <zash@zash.se>
parents: 1344
diff changeset
264 for i = 1, #dane do
1642
a4a6b4be973a mod_s2s_auth_dane: Update for recent changes in Zashs LuaSec branch
Kim Alvefur <zash@zash.se>
parents: 1626
diff changeset
265 local tlsa = dane[i].tlsa;
1437
161bbe0b9dd3 mod_s2s_auth_dane: Tweak log messages
Kim Alvefur <zash@zash.se>
parents: 1436
diff changeset
266 module:log("debug", "TLSA #%d: %s", i, tostring(tlsa))
1642
a4a6b4be973a mod_s2s_auth_dane: Update for recent changes in Zashs LuaSec branch
Kim Alvefur <zash@zash.se>
parents: 1626
diff changeset
267 local use = tlsa.use;
1258
fc82d8eded7d mod_s2s_auth_dane: Experimental DANE implementation
Kim Alvefur <zash@zash.se>
parents:
diff changeset
268
1348
6191613959dc mod_s2s_auth_dane: Make supported DANE usages configurable, default to DANE-EE
Kim Alvefur <zash@zash.se>
parents: 1347
diff changeset
269 if enabled_uses:contains(use) then
1944
1950fa6aa0c0 mod_s2s_auth_dane: Consider the current certificate chain status before checking PKIX-{EE,CA} TLSA records
Kim Alvefur <zash@zash.se>
parents: 1943
diff changeset
270 -- DANE-EE or PKIX-EE
1950fa6aa0c0 mod_s2s_auth_dane: Consider the current certificate chain status before checking PKIX-{EE,CA} TLSA records
Kim Alvefur <zash@zash.se>
parents: 1943
diff changeset
271 if use == 3 or (use == 1 and session.cert_chain_status == "valid") then
1389
6bd9681d54b7 mod_s2s_auth_dane: Break out DANE check into a function
Kim Alvefur <zash@zash.se>
parents: 1383
diff changeset
272 -- Should we check if the cert subject matches?
1642
a4a6b4be973a mod_s2s_auth_dane: Update for recent changes in Zashs LuaSec branch
Kim Alvefur <zash@zash.se>
parents: 1626
diff changeset
273 local is_match = one_dane_check(tlsa, cert);
1389
6bd9681d54b7 mod_s2s_auth_dane: Break out DANE check into a function
Kim Alvefur <zash@zash.se>
parents: 1383
diff changeset
274 if is_match ~= nil then
6bd9681d54b7 mod_s2s_auth_dane: Break out DANE check into a function
Kim Alvefur <zash@zash.se>
parents: 1383
diff changeset
275 supported_found = true;
1348
6191613959dc mod_s2s_auth_dane: Make supported DANE usages configurable, default to DANE-EE
Kim Alvefur <zash@zash.se>
parents: 1347
diff changeset
276 end
1389
6bd9681d54b7 mod_s2s_auth_dane: Break out DANE check into a function
Kim Alvefur <zash@zash.se>
parents: 1383
diff changeset
277 if is_match then
1437
161bbe0b9dd3 mod_s2s_auth_dane: Tweak log messages
Kim Alvefur <zash@zash.se>
parents: 1436
diff changeset
278 log("info", "DANE validated ok for %s using %s", host, tlsa:getUsage());
1348
6191613959dc mod_s2s_auth_dane: Make supported DANE usages configurable, default to DANE-EE
Kim Alvefur <zash@zash.se>
parents: 1347
diff changeset
279 session.cert_identity_status = "valid";
6191613959dc mod_s2s_auth_dane: Make supported DANE usages configurable, default to DANE-EE
Kim Alvefur <zash@zash.se>
parents: 1347
diff changeset
280 if use == 3 then -- DANE-EE, chain status equals DNSSEC chain status
6191613959dc mod_s2s_auth_dane: Make supported DANE usages configurable, default to DANE-EE
Kim Alvefur <zash@zash.se>
parents: 1347
diff changeset
281 session.cert_chain_status = "valid";
6191613959dc mod_s2s_auth_dane: Make supported DANE usages configurable, default to DANE-EE
Kim Alvefur <zash@zash.se>
parents: 1347
diff changeset
282 -- for usage 1, PKIX-EE, the chain has to be valid already
6191613959dc mod_s2s_auth_dane: Make supported DANE usages configurable, default to DANE-EE
Kim Alvefur <zash@zash.se>
parents: 1347
diff changeset
283 end
6191613959dc mod_s2s_auth_dane: Make supported DANE usages configurable, default to DANE-EE
Kim Alvefur <zash@zash.se>
parents: 1347
diff changeset
284 match_found = true;
6191613959dc mod_s2s_auth_dane: Make supported DANE usages configurable, default to DANE-EE
Kim Alvefur <zash@zash.se>
parents: 1347
diff changeset
285 break;
1258
fc82d8eded7d mod_s2s_auth_dane: Experimental DANE implementation
Kim Alvefur <zash@zash.se>
parents:
diff changeset
286 end
1944
1950fa6aa0c0 mod_s2s_auth_dane: Consider the current certificate chain status before checking PKIX-{EE,CA} TLSA records
Kim Alvefur <zash@zash.se>
parents: 1943
diff changeset
287 -- DANE-TA or PKIX-CA
1950fa6aa0c0 mod_s2s_auth_dane: Consider the current certificate chain status before checking PKIX-{EE,CA} TLSA records
Kim Alvefur <zash@zash.se>
parents: 1943
diff changeset
288 elseif use == 2 or (use == 0 and session.cert_chain_status == "valid") then
1396
cf4e39334ef7 mod_s2s_auth_dane: Add support for DANE-TA and PKIX-CA (requires LuaSec changes)
Kim Alvefur <zash@zash.se>
parents: 1395
diff changeset
289 supported_found = true;
1642
a4a6b4be973a mod_s2s_auth_dane: Update for recent changes in Zashs LuaSec branch
Kim Alvefur <zash@zash.se>
parents: 1626
diff changeset
290 local chain = session.conn:socket():getpeerchain();
1652
9a3d2f1479a4 mod_s2s_auth_dane: Cleanup [luacheck]
Kim Alvefur <zash@zash.se>
parents: 1642
diff changeset
291 for c = 1, #chain do
9a3d2f1479a4 mod_s2s_auth_dane: Cleanup [luacheck]
Kim Alvefur <zash@zash.se>
parents: 1642
diff changeset
292 local cacert = chain[c];
1642
a4a6b4be973a mod_s2s_auth_dane: Update for recent changes in Zashs LuaSec branch
Kim Alvefur <zash@zash.se>
parents: 1626
diff changeset
293 local is_match = one_dane_check(tlsa, cacert);
1396
cf4e39334ef7 mod_s2s_auth_dane: Add support for DANE-TA and PKIX-CA (requires LuaSec changes)
Kim Alvefur <zash@zash.se>
parents: 1395
diff changeset
294 if is_match ~= nil then
cf4e39334ef7 mod_s2s_auth_dane: Add support for DANE-TA and PKIX-CA (requires LuaSec changes)
Kim Alvefur <zash@zash.se>
parents: 1395
diff changeset
295 supported_found = true;
cf4e39334ef7 mod_s2s_auth_dane: Add support for DANE-TA and PKIX-CA (requires LuaSec changes)
Kim Alvefur <zash@zash.se>
parents: 1395
diff changeset
296 end
1642
a4a6b4be973a mod_s2s_auth_dane: Update for recent changes in Zashs LuaSec branch
Kim Alvefur <zash@zash.se>
parents: 1626
diff changeset
297 if is_match and cacert:issued(cert, unpack(chain)) then
1437
161bbe0b9dd3 mod_s2s_auth_dane: Tweak log messages
Kim Alvefur <zash@zash.se>
parents: 1436
diff changeset
298 log("info", "DANE validated ok for %s using %s", host, tlsa:getUsage());
1396
cf4e39334ef7 mod_s2s_auth_dane: Add support for DANE-TA and PKIX-CA (requires LuaSec changes)
Kim Alvefur <zash@zash.se>
parents: 1395
diff changeset
299 if use == 2 then -- DANE-TA
cf4e39334ef7 mod_s2s_auth_dane: Add support for DANE-TA and PKIX-CA (requires LuaSec changes)
Kim Alvefur <zash@zash.se>
parents: 1395
diff changeset
300 session.cert_identity_status = "valid";
1757
d011b87b7f58 mod_s2s_auth_dane: Validate names of DANE-TA certs
Kim Alvefur <zash@zash.se>
parents: 1701
diff changeset
301 if cert_verify_identity(host, "xmpp-server", cert) then
d011b87b7f58 mod_s2s_auth_dane: Validate names of DANE-TA certs
Kim Alvefur <zash@zash.se>
parents: 1701
diff changeset
302 session.cert_chain_status = "valid";
d011b87b7f58 mod_s2s_auth_dane: Validate names of DANE-TA certs
Kim Alvefur <zash@zash.se>
parents: 1701
diff changeset
303 -- else -- TODO Check against SRV target?
d011b87b7f58 mod_s2s_auth_dane: Validate names of DANE-TA certs
Kim Alvefur <zash@zash.se>
parents: 1701
diff changeset
304 end
1396
cf4e39334ef7 mod_s2s_auth_dane: Add support for DANE-TA and PKIX-CA (requires LuaSec changes)
Kim Alvefur <zash@zash.se>
parents: 1395
diff changeset
305 -- for usage 0, PKIX-CA, identity and chain has to be valid already
cf4e39334ef7 mod_s2s_auth_dane: Add support for DANE-TA and PKIX-CA (requires LuaSec changes)
Kim Alvefur <zash@zash.se>
parents: 1395
diff changeset
306 end
cf4e39334ef7 mod_s2s_auth_dane: Add support for DANE-TA and PKIX-CA (requires LuaSec changes)
Kim Alvefur <zash@zash.se>
parents: 1395
diff changeset
307 match_found = true;
cf4e39334ef7 mod_s2s_auth_dane: Add support for DANE-TA and PKIX-CA (requires LuaSec changes)
Kim Alvefur <zash@zash.se>
parents: 1395
diff changeset
308 break;
cf4e39334ef7 mod_s2s_auth_dane: Add support for DANE-TA and PKIX-CA (requires LuaSec changes)
Kim Alvefur <zash@zash.se>
parents: 1395
diff changeset
309 end
cf4e39334ef7 mod_s2s_auth_dane: Add support for DANE-TA and PKIX-CA (requires LuaSec changes)
Kim Alvefur <zash@zash.se>
parents: 1395
diff changeset
310 end
cf4e39334ef7 mod_s2s_auth_dane: Add support for DANE-TA and PKIX-CA (requires LuaSec changes)
Kim Alvefur <zash@zash.se>
parents: 1395
diff changeset
311 if match_found then break end
1258
fc82d8eded7d mod_s2s_auth_dane: Experimental DANE implementation
Kim Alvefur <zash@zash.se>
parents:
diff changeset
312 end
fc82d8eded7d mod_s2s_auth_dane: Experimental DANE implementation
Kim Alvefur <zash@zash.se>
parents:
diff changeset
313 end
fc82d8eded7d mod_s2s_auth_dane: Experimental DANE implementation
Kim Alvefur <zash@zash.se>
parents:
diff changeset
314 end
1347
52b419885f0a mod_s2s_auth_dane: Simplify, but diverge from DANE-SRV draft. Will now look for _xmpp-server.example.com IN TLSA for both directions
Kim Alvefur <zash@zash.se>
parents: 1344
diff changeset
315 if supported_found and not match_found or dane.bogus then
1332
08a0241f5d2c mod_s2s_auth_dane: Add some comments
Kim Alvefur <zash@zash.se>
parents: 1330
diff changeset
316 -- No TLSA matched or response was bogus
1436
3944e364ba88 mod_s2s_auth_dane: Add some more info to log messages
Kim Alvefur <zash@zash.se>
parents: 1435
diff changeset
317 local why = "No TLSA matched certificate";
3944e364ba88 mod_s2s_auth_dane: Add some more info to log messages
Kim Alvefur <zash@zash.se>
parents: 1435
diff changeset
318 if dane.bogus then
3944e364ba88 mod_s2s_auth_dane: Add some more info to log messages
Kim Alvefur <zash@zash.se>
parents: 1435
diff changeset
319 why = "Bogus: "..tostring(dane.bogus);
3944e364ba88 mod_s2s_auth_dane: Add some more info to log messages
Kim Alvefur <zash@zash.se>
parents: 1435
diff changeset
320 end
1507
6ea13869753f mod_s2s_auth_dane: Include hostname when logging a failure
Kim Alvefur <zash@zash.se>
parents: 1506
diff changeset
321 log("warn", "DANE validation failed for %s: %s", host, why);
1262
1e84eebf3f46 mod_s2s_auth_dane: Invalidate trust if there are TLSA records but no matches, or bogus results
Kim Alvefur <zash@zash.se>
parents: 1261
diff changeset
322 session.cert_identity_status = "invalid";
1e84eebf3f46 mod_s2s_auth_dane: Invalidate trust if there are TLSA records but no matches, or bogus results
Kim Alvefur <zash@zash.se>
parents: 1261
diff changeset
323 session.cert_chain_status = "invalid";
1e84eebf3f46 mod_s2s_auth_dane: Invalidate trust if there are TLSA records but no matches, or bogus results
Kim Alvefur <zash@zash.se>
parents: 1261
diff changeset
324 end
1370
e3fe6c749bc3 mod_s2s_auth_dane: Merge functionality from mod_s2s_auth_dnssec_srv
Kim Alvefur <zash@zash.se>
parents: 1368
diff changeset
325 else
e3fe6c749bc3 mod_s2s_auth_dane: Merge functionality from mod_s2s_auth_dnssec_srv
Kim Alvefur <zash@zash.se>
parents: 1368
diff changeset
326 if session.cert_chain_status == "valid" and session.cert_identity_status ~= "valid"
1411
8626abe100e2 mod_s2s_auth_dane: Fix traceback if session.srv_hosts is nil
Kim Alvefur <zash@zash.se>
parents: 1410
diff changeset
327 and session.srv_hosts and session.srv_hosts.answer and session.srv_hosts.answer.secure then
1370
e3fe6c749bc3 mod_s2s_auth_dane: Merge functionality from mod_s2s_auth_dnssec_srv
Kim Alvefur <zash@zash.se>
parents: 1368
diff changeset
328 local srv_hosts, srv_choice, srv_target = session.srv_hosts, session.srv_choice;
e3fe6c749bc3 mod_s2s_auth_dane: Merge functionality from mod_s2s_auth_dnssec_srv
Kim Alvefur <zash@zash.se>
parents: 1368
diff changeset
329 for i = srv_choice or 1, srv_choice or #srv_hosts do
1415
8791fa8a18c8 mod_s2s_auth_dane: Fix potential traceback in logging if SRV target fails nameprep
Kim Alvefur <zash@zash.se>
parents: 1414
diff changeset
330 srv_target = session.srv_hosts[i].target:gsub("%.?$","");
1431
33a796b2cb91 mod_s2s_auth_dane: Cache logger to save some table lookups and improve readability
Kim Alvefur <zash@zash.se>
parents: 1415
diff changeset
331 log("debug", "Comparing certificate with Secure SRV target %s", srv_target);
1506
a40f9b8661d8 mod_s2s_auth_dane: Fix stringprepping when doing "DANE Light"
Kim Alvefur <zash@zash.se>
parents: 1502
diff changeset
332 srv_target = nameprep(idna_to_unicode(srv_target));
1370
e3fe6c749bc3 mod_s2s_auth_dane: Merge functionality from mod_s2s_auth_dnssec_srv
Kim Alvefur <zash@zash.se>
parents: 1368
diff changeset
333 if srv_target and cert_verify_identity(srv_target, "xmpp-server", cert) then
1437
161bbe0b9dd3 mod_s2s_auth_dane: Tweak log messages
Kim Alvefur <zash@zash.se>
parents: 1436
diff changeset
334 log("info", "Certificate for %s matches Secure SRV target %s", host, srv_target);
1370
e3fe6c749bc3 mod_s2s_auth_dane: Merge functionality from mod_s2s_auth_dnssec_srv
Kim Alvefur <zash@zash.se>
parents: 1368
diff changeset
335 session.cert_identity_status = "valid";
e3fe6c749bc3 mod_s2s_auth_dane: Merge functionality from mod_s2s_auth_dnssec_srv
Kim Alvefur <zash@zash.se>
parents: 1368
diff changeset
336 return;
e3fe6c749bc3 mod_s2s_auth_dane: Merge functionality from mod_s2s_auth_dnssec_srv
Kim Alvefur <zash@zash.se>
parents: 1368
diff changeset
337 end
e3fe6c749bc3 mod_s2s_auth_dane: Merge functionality from mod_s2s_auth_dnssec_srv
Kim Alvefur <zash@zash.se>
parents: 1368
diff changeset
338 end
e3fe6c749bc3 mod_s2s_auth_dane: Merge functionality from mod_s2s_auth_dnssec_srv
Kim Alvefur <zash@zash.se>
parents: 1368
diff changeset
339 end
1258
fc82d8eded7d mod_s2s_auth_dane: Experimental DANE implementation
Kim Alvefur <zash@zash.se>
parents:
diff changeset
340 end
fc82d8eded7d mod_s2s_auth_dane: Experimental DANE implementation
Kim Alvefur <zash@zash.se>
parents:
diff changeset
341 end);
fc82d8eded7d mod_s2s_auth_dane: Experimental DANE implementation
Kim Alvefur <zash@zash.se>
parents:
diff changeset
342