Software /
code /
prosody
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 |
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 }; |