Comparison

util/sslconfig.lua @ 12802:4a8740e01813

Merge 0.12->trunk
author Kim Alvefur <zash@zash.se>
date Mon, 12 Dec 2022 07:10:54 +0100
parent 12481:2ee27587fec7
child 12975:d10957394a3c
comparison
equal deleted inserted replaced
12801:ebd6b4d8bf04 12802:4a8740e01813
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 resolve_path = require"util.paths".resolve_relative_path;
9 12
10 local _ENV = nil; 13 local _ENV = nil;
11 -- luacheck: std none 14 -- luacheck: std none
12 15
13 local handlers = { }; 16 local handlers = { };
32 options[key] = value; 35 options[key] = value;
33 else -- list item 36 else -- list item
34 options[value] = true; 37 options[value] = true;
35 end 38 end
36 end 39 end
37 config[field] = options; 40 rawset(config, field, options)
38 end 41 end
39 42
40 handlers.verifyext = handlers.options; 43 handlers.verifyext = handlers.options;
41 44
42 -- finalisers take something produced by handlers and return what luasec 45 -- finalisers take something produced by handlers and return what luasec
68 finalisers.curveslist = finalisers.ciphers; 71 finalisers.curveslist = finalisers.ciphers;
69 72
70 -- TLS 1.3 ciphers 73 -- TLS 1.3 ciphers
71 finalisers.ciphersuites = finalisers.ciphers; 74 finalisers.ciphersuites = finalisers.ciphers;
72 75
76 -- Path expansion
77 function finalisers.key(path, config)
78 if type(path) == "string" then
79 return resolve_path(config._basedir, path);
80 else
81 return nil
82 end
83 end
84 finalisers.certificate = finalisers.key;
85 finalisers.cafile = finalisers.key;
86 finalisers.capath = finalisers.key;
87 -- XXX: copied from core/certmanager.lua, but this seems odd, because it would remove a dhparam function from the config
88 finalisers.dhparam = finalisers.key;
89
73 -- protocol = "x" should enable only that protocol 90 -- protocol = "x" should enable only that protocol
74 -- protocol = "x+" should enable x and later versions 91 -- protocol = "x+" should enable x and later versions
75 92
76 local protocols = { "sslv2", "sslv3", "tlsv1", "tlsv1_1", "tlsv1_2", "tlsv1_3" }; 93 local protocols = { "sslv2", "sslv3", "tlsv1", "tlsv1_1", "tlsv1_2", "tlsv1_3" };
77 for i = 1, #protocols do protocols[protocols[i] .. "+"] = i - 1; end 94 for i = 1, #protocols do protocols[protocols[i] .. "+"] = i - 1; end
87 end 104 end
88 end 105 end
89 106
90 -- Merge options from 'new' config into 'config' 107 -- Merge options from 'new' config into 'config'
91 local function apply(config, new) 108 local function apply(config, new)
109 rawset(config, "_cache", nil);
92 if type(new) == "table" then 110 if type(new) == "table" then
93 for field, value in pairs(new) do 111 for field, value in pairs(new) do
94 (handlers[field] or rawset)(config, field, value); 112 -- exclude keys which are internal to the config builder
113 if field:sub(1, 1) ~= "_" then
114 (handlers[field] or rawset)(config, field, value);
115 end
95 end 116 end
96 end 117 end
118 return config
97 end 119 end
98 120
99 -- Finalize the config into the form LuaSec expects 121 -- Finalize the config into the form LuaSec expects
100 local function final(config) 122 local function final(config)
101 local output = { }; 123 local output = { };
102 for field, value in pairs(config) do 124 for field, value in pairs(config) do
103 output[field] = (finalisers[field] or id)(value); 125 -- exclude keys which are internal to the config builder
126 if field:sub(1, 1) ~= "_" then
127 output[field] = (finalisers[field] or id)(value, config);
128 end
104 end 129 end
105 -- Need to handle protocols last because it adds to the options list 130 -- Need to handle protocols last because it adds to the options list
106 protocol(output); 131 protocol(output);
107 return output; 132 return output;
108 end 133 end
109 134
135 local function build(config)
136 local cached = rawget(config, "_cache");
137 if cached then
138 return cached, nil
139 end
140
141 local ctx, err = rawget(config, "_context_factory")(config:final(), config);
142 if ctx then
143 rawset(config, "_cache", ctx);
144 end
145 return ctx, err
146 end
147
110 local sslopts_mt = { 148 local sslopts_mt = {
111 __index = { 149 __index = {
112 apply = apply; 150 apply = apply;
113 final = final; 151 final = final;
152 build = build;
114 }; 153 };
154 __newindex = function()
155 error("SSL config objects cannot be modified directly. Use :apply()")
156 end;
115 }; 157 };
116 158
117 local function new() 159
118 return setmetatable({options={}}, sslopts_mt); 160 -- passing basedir through everything is required to avoid sslconfig depending
161 -- on prosody.paths.config
162 local function new(context_factory, basedir)
163 return setmetatable({
164 _context_factory = context_factory,
165 _basedir = basedir,
166 options={},
167 }, sslopts_mt);
119 end 168 end
169
170 local function clone(config)
171 local result = new();
172 for k, v in pairs(config) do
173 -- note that we *do* copy the internal keys on clone -- we have to carry
174 -- both the factory and the cache with us
175 rawset(result, k, v);
176 end
177 return result
178 end
179
180 sslopts_mt.__index.clone = clone;
120 181
121 return { 182 return {
122 apply = apply; 183 apply = apply;
123 final = final; 184 final = final;
124 new = new; 185 _new = new;
125 }; 186 };