Annotate

net/tls_luasec.lua @ 13115:749376d75b40

net.certmanager: Move LuaSec feature detection to net.tls_luasec Further isolates LuaSec from Prosody core, with the ultimate goal of allowing LuaSec to be replaced more easily.
author Kim Alvefur <zash@zash.se>
date Sat, 27 May 2023 15:39:26 +0200
parent 12486:ee93df086926
child 13116:58e793288d9c
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
12480
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
1 -- Prosody IM
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
2 -- Copyright (C) 2021 Prosody folks
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
3 --
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
4 -- This project is MIT/X11 licensed. Please see the
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
5 -- COPYING file in the source package for more information.
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
6 --
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
7
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
8 --[[
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
9 This file provides a shim abstraction over LuaSec, consolidating some code
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
10 which was previously spread between net.server backends, portmanager and
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
11 certmanager.
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
12
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
13 The goal is to provide a more or less well-defined API on top of LuaSec which
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
14 abstracts away some of the things which are not needed and simplifies usage of
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
15 commonly used things (such as SNI contexts). Eventually, network backends
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
16 which do not rely on LuaSocket+LuaSec should be able to provide *this* API
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
17 instead of having to mimic LuaSec.
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
18 ]]
12486
ee93df086926 net.tls_luasec: Harden dependency on LuaSec
Kim Alvefur <zash@zash.se>
parents: 12480
diff changeset
19 local ssl = require "ssl";
12480
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
20 local ssl_newcontext = ssl.newcontext;
12486
ee93df086926 net.tls_luasec: Harden dependency on LuaSec
Kim Alvefur <zash@zash.se>
parents: 12480
diff changeset
21 local ssl_context = ssl.context or require "ssl.context";
12480
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
22 local io_open = io.open;
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
23
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
24 local context_api = {};
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
25 local context_mt = {__index = context_api};
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
26
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
27 function context_api:set_sni_host(host, cert, key)
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
28 local ctx, err = self._builder:clone():apply({
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
29 certificate = cert,
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
30 key = key,
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
31 }):build();
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
32 if not ctx then
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
33 return false, err
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
34 end
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
35
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
36 self._sni_contexts[host] = ctx._inner
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
37
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
38 return true, nil
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
39 end
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
40
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
41 function context_api:remove_sni_host(host)
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
42 self._sni_contexts[host] = nil
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
43 end
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
44
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
45 function context_api:wrap(sock)
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
46 local ok, conn, err = pcall(ssl.wrap, sock, self._inner);
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
47 if not ok then
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
48 return nil, err
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
49 end
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
50 return conn, nil
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
51 end
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
52
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
53 local function new_context(cfg, builder)
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
54 -- LuaSec expects dhparam to be a callback that takes two arguments.
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
55 -- We ignore those because it is mostly used for having a separate
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
56 -- set of params for EXPORT ciphers, which we don't have by default.
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
57 if type(cfg.dhparam) == "string" then
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
58 local f, err = io_open(cfg.dhparam);
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
59 if not f then return nil, "Could not open DH parameters: "..err end
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
60 local dhparam = f:read("*a");
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
61 f:close();
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
62 cfg.dhparam = function() return dhparam; end
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
63 end
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
64
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
65 local inner, err = ssl_newcontext(cfg);
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
66 if not inner then
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
67 return nil, err
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
68 end
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
69
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
70 -- COMPAT Older LuaSec ignores the cipher list from the config, so we have to take care
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
71 -- of it ourselves (W/A for #x)
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
72 if inner and cfg.ciphers then
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
73 local success;
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
74 success, err = ssl_context.setcipher(inner, cfg.ciphers);
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
75 if not success then
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
76 return nil, err
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
77 end
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
78 end
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
79
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
80 return setmetatable({
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
81 _inner = inner,
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
82 _builder = builder,
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
83 _sni_contexts = {},
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
84 }, context_mt), nil
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
85 end
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
86
13115
749376d75b40 net.certmanager: Move LuaSec feature detection to net.tls_luasec
Kim Alvefur <zash@zash.se>
parents: 12486
diff changeset
87 -- Feature detection / guessing
749376d75b40 net.certmanager: Move LuaSec feature detection to net.tls_luasec
Kim Alvefur <zash@zash.se>
parents: 12486
diff changeset
88 local function test_option(option)
749376d75b40 net.certmanager: Move LuaSec feature detection to net.tls_luasec
Kim Alvefur <zash@zash.se>
parents: 12486
diff changeset
89 return not not ssl_newcontext({mode="server",protocol="sslv23",options={ option }});
749376d75b40 net.certmanager: Move LuaSec feature detection to net.tls_luasec
Kim Alvefur <zash@zash.se>
parents: 12486
diff changeset
90 end
749376d75b40 net.certmanager: Move LuaSec feature detection to net.tls_luasec
Kim Alvefur <zash@zash.se>
parents: 12486
diff changeset
91 local luasec_major, luasec_minor = ssl._VERSION:match("^(%d+)%.(%d+)");
749376d75b40 net.certmanager: Move LuaSec feature detection to net.tls_luasec
Kim Alvefur <zash@zash.se>
parents: 12486
diff changeset
92 local luasec_version = tonumber(luasec_major) * 100 + tonumber(luasec_minor);
749376d75b40 net.certmanager: Move LuaSec feature detection to net.tls_luasec
Kim Alvefur <zash@zash.se>
parents: 12486
diff changeset
93 local luasec_has = ssl.config or {
749376d75b40 net.certmanager: Move LuaSec feature detection to net.tls_luasec
Kim Alvefur <zash@zash.se>
parents: 12486
diff changeset
94 algorithms = {
749376d75b40 net.certmanager: Move LuaSec feature detection to net.tls_luasec
Kim Alvefur <zash@zash.se>
parents: 12486
diff changeset
95 ec = luasec_version >= 5;
749376d75b40 net.certmanager: Move LuaSec feature detection to net.tls_luasec
Kim Alvefur <zash@zash.se>
parents: 12486
diff changeset
96 };
749376d75b40 net.certmanager: Move LuaSec feature detection to net.tls_luasec
Kim Alvefur <zash@zash.se>
parents: 12486
diff changeset
97 capabilities = {
749376d75b40 net.certmanager: Move LuaSec feature detection to net.tls_luasec
Kim Alvefur <zash@zash.se>
parents: 12486
diff changeset
98 curves_list = luasec_version >= 7;
749376d75b40 net.certmanager: Move LuaSec feature detection to net.tls_luasec
Kim Alvefur <zash@zash.se>
parents: 12486
diff changeset
99 };
749376d75b40 net.certmanager: Move LuaSec feature detection to net.tls_luasec
Kim Alvefur <zash@zash.se>
parents: 12486
diff changeset
100 options = {
749376d75b40 net.certmanager: Move LuaSec feature detection to net.tls_luasec
Kim Alvefur <zash@zash.se>
parents: 12486
diff changeset
101 cipher_server_preference = test_option("cipher_server_preference");
749376d75b40 net.certmanager: Move LuaSec feature detection to net.tls_luasec
Kim Alvefur <zash@zash.se>
parents: 12486
diff changeset
102 no_ticket = test_option("no_ticket");
749376d75b40 net.certmanager: Move LuaSec feature detection to net.tls_luasec
Kim Alvefur <zash@zash.se>
parents: 12486
diff changeset
103 no_compression = test_option("no_compression");
749376d75b40 net.certmanager: Move LuaSec feature detection to net.tls_luasec
Kim Alvefur <zash@zash.se>
parents: 12486
diff changeset
104 single_dh_use = test_option("single_dh_use");
749376d75b40 net.certmanager: Move LuaSec feature detection to net.tls_luasec
Kim Alvefur <zash@zash.se>
parents: 12486
diff changeset
105 single_ecdh_use = test_option("single_ecdh_use");
749376d75b40 net.certmanager: Move LuaSec feature detection to net.tls_luasec
Kim Alvefur <zash@zash.se>
parents: 12486
diff changeset
106 no_renegotiation = test_option("no_renegotiation");
749376d75b40 net.certmanager: Move LuaSec feature detection to net.tls_luasec
Kim Alvefur <zash@zash.se>
parents: 12486
diff changeset
107 };
749376d75b40 net.certmanager: Move LuaSec feature detection to net.tls_luasec
Kim Alvefur <zash@zash.se>
parents: 12486
diff changeset
108 };
749376d75b40 net.certmanager: Move LuaSec feature detection to net.tls_luasec
Kim Alvefur <zash@zash.se>
parents: 12486
diff changeset
109
12480
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
110 return {
13115
749376d75b40 net.certmanager: Move LuaSec feature detection to net.tls_luasec
Kim Alvefur <zash@zash.se>
parents: 12486
diff changeset
111 features = luasec_has;
12480
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
112 new_context = new_context,
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
113 };