Comparison

util/sslconfig.lua @ 12480:7e9ebdc75ce4

net: isolate LuaSec-specifics For this, various accessor functions are now provided directly on the sockets, which reach down into the LuaSec implementation to obtain the information. While this may seem of little gain at first, it hides the implementation detail of the LuaSec+LuaSocket combination that the actual socket and the TLS layer are separate objects. The net gain here is that an alternative implementation does not have to emulate that specific implementation detail and "only" has to expose LuaSec-compatible data structures on the new functions.
author Jonas Schäfer <jonas@wielicki.name>
date Wed, 27 Apr 2022 17:44:14 +0200
parent 10920:c171b4c59bd1
child 12481:2ee27587fec7
comparison
equal deleted inserted replaced
12478:82270a6b1234 12480:7e9ebdc75ce4
1 -- util to easily merge multiple sets of LuaSec context options 1 -- util to easily merge multiple sets of LuaSec context options
2 2
3 local type = type; 3 local type = type;
4 local pairs = pairs; 4 local pairs = pairs;
5 local rawset = rawset; 5 local rawset = rawset;
6 local rawget = rawget;
7 local error = error;
6 local t_concat = table.concat; 8 local t_concat = table.concat;
7 local t_insert = table.insert; 9 local t_insert = table.insert;
8 local setmetatable = setmetatable; 10 local setmetatable = setmetatable;
11 local config_path = prosody.paths.config or ".";
12 local resolve_path = require"util.paths".resolve_relative_path;
13
14 -- TODO: use net.server directly here
15 local tls_impl = require"net.tls_luasec";
9 16
10 local _ENV = nil; 17 local _ENV = nil;
11 -- luacheck: std none 18 -- luacheck: std none
12 19
13 local handlers = { }; 20 local handlers = { };
32 options[key] = value; 39 options[key] = value;
33 else -- list item 40 else -- list item
34 options[value] = true; 41 options[value] = true;
35 end 42 end
36 end 43 end
37 config[field] = options; 44 rawset(config, field, options)
38 end 45 end
39 46
40 handlers.verifyext = handlers.options; 47 handlers.verifyext = handlers.options;
41 48
42 -- finalisers take something produced by handlers and return what luasec 49 -- finalisers take something produced by handlers and return what luasec
68 finalisers.curveslist = finalisers.ciphers; 75 finalisers.curveslist = finalisers.ciphers;
69 76
70 -- TLS 1.3 ciphers 77 -- TLS 1.3 ciphers
71 finalisers.ciphersuites = finalisers.ciphers; 78 finalisers.ciphersuites = finalisers.ciphers;
72 79
80 -- Path expansion
81 function finalisers.key(path)
82 if type(path) == "string" then
83 return resolve_path(config_path, path);
84 else
85 return nil
86 end
87 end
88 finalisers.certificate = finalisers.key;
89 finalisers.cafile = finalisers.key;
90 finalisers.capath = finalisers.key;
91 -- XXX: copied from core/certmanager.lua, but this seems odd, because it would remove a dhparam function from the config
92 finalisers.dhparam = finalisers.key;
93
73 -- protocol = "x" should enable only that protocol 94 -- protocol = "x" should enable only that protocol
74 -- protocol = "x+" should enable x and later versions 95 -- protocol = "x+" should enable x and later versions
75 96
76 local protocols = { "sslv2", "sslv3", "tlsv1", "tlsv1_1", "tlsv1_2", "tlsv1_3" }; 97 local protocols = { "sslv2", "sslv3", "tlsv1", "tlsv1_1", "tlsv1_2", "tlsv1_3" };
77 for i = 1, #protocols do protocols[protocols[i] .. "+"] = i - 1; end 98 for i = 1, #protocols do protocols[protocols[i] .. "+"] = i - 1; end
87 end 108 end
88 end 109 end
89 110
90 -- Merge options from 'new' config into 'config' 111 -- Merge options from 'new' config into 'config'
91 local function apply(config, new) 112 local function apply(config, new)
113 -- 0 == cache
114 rawset(config, 0, nil);
92 if type(new) == "table" then 115 if type(new) == "table" then
93 for field, value in pairs(new) do 116 for field, value in pairs(new) do
94 (handlers[field] or rawset)(config, field, value); 117 (handlers[field] or rawset)(config, field, value);
95 end 118 end
96 end 119 end
120 return config
97 end 121 end
98 122
99 -- Finalize the config into the form LuaSec expects 123 -- Finalize the config into the form LuaSec expects
100 local function final(config) 124 local function final(config)
101 local output = { }; 125 local output = { };
105 -- Need to handle protocols last because it adds to the options list 129 -- Need to handle protocols last because it adds to the options list
106 protocol(output); 130 protocol(output);
107 return output; 131 return output;
108 end 132 end
109 133
134 local function build(config)
135 local cached = rawget(config, 0);
136 if cached then
137 return cached, nil
138 end
139
140 local ctx, err = tls_impl.new_context(config:final(), config);
141 if ctx then
142 rawset(config, 0, ctx);
143 end
144 return ctx, err
145 end
146
110 local sslopts_mt = { 147 local sslopts_mt = {
111 __index = { 148 __index = {
112 apply = apply; 149 apply = apply;
113 final = final; 150 final = final;
151 build = build;
114 }; 152 };
153 __newindex = function()
154 error("SSL config objects cannot be modified directly. Use :apply()")
155 end;
115 }; 156 };
157
116 158
117 local function new() 159 local function new()
118 return setmetatable({options={}}, sslopts_mt); 160 return setmetatable({options={}}, sslopts_mt);
119 end 161 end
162
163 local function clone(config)
164 local result = new();
165 for k, v in pairs(config) do
166 rawset(result, k, v);
167 end
168 return result
169 end
170
171 sslopts_mt.__index.clone = clone;
120 172
121 return { 173 return {
122 apply = apply; 174 apply = apply;
123 final = final; 175 final = final;
124 new = new; 176 new = new;