Mercurial > prosody-hg
comparison util/sslconfig.lua @ 12481:2ee27587fec7
net: refactor sslconfig to not depend on LuaSec
This now requires that the network backend exposes a tls_builder
function, which essentially wraps the former util.sslconfig.new()
function, passing a factory to create the eventual SSL context.
That allows a net.server backend to pick whatever it likes as SSL
context factory, as long as it understands the config table passed by
the SSL config builder. Heck, a backend could even mock and replace the
entire SSL config builder API.
| author | Jonas Schäfer <jonas@wielicki.name> |
|---|---|
| date | Sat, 02 Apr 2022 11:15:33 +0200 |
| parents | 7e9ebdc75ce4 |
| children | d10957394a3c |
comparison
equal
deleted
inserted
replaced
| 12480:7e9ebdc75ce4 | 12481:2ee27587fec7 |
|---|---|
| 6 local rawget = rawget; | 6 local rawget = rawget; |
| 7 local error = error; | 7 local error = error; |
| 8 local t_concat = table.concat; | 8 local t_concat = table.concat; |
| 9 local t_insert = table.insert; | 9 local t_insert = table.insert; |
| 10 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; | 11 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"; | |
| 16 | 12 |
| 17 local _ENV = nil; | 13 local _ENV = nil; |
| 18 -- luacheck: std none | 14 -- luacheck: std none |
| 19 | 15 |
| 20 local handlers = { }; | 16 local handlers = { }; |
| 76 | 72 |
| 77 -- TLS 1.3 ciphers | 73 -- TLS 1.3 ciphers |
| 78 finalisers.ciphersuites = finalisers.ciphers; | 74 finalisers.ciphersuites = finalisers.ciphers; |
| 79 | 75 |
| 80 -- Path expansion | 76 -- Path expansion |
| 81 function finalisers.key(path) | 77 function finalisers.key(path, config) |
| 82 if type(path) == "string" then | 78 if type(path) == "string" then |
| 83 return resolve_path(config_path, path); | 79 return resolve_path(config._basedir, path); |
| 84 else | 80 else |
| 85 return nil | 81 return nil |
| 86 end | 82 end |
| 87 end | 83 end |
| 88 finalisers.certificate = finalisers.key; | 84 finalisers.certificate = finalisers.key; |
| 108 end | 104 end |
| 109 end | 105 end |
| 110 | 106 |
| 111 -- Merge options from 'new' config into 'config' | 107 -- Merge options from 'new' config into 'config' |
| 112 local function apply(config, new) | 108 local function apply(config, new) |
| 113 -- 0 == cache | 109 rawset(config, "_cache", nil); |
| 114 rawset(config, 0, nil); | |
| 115 if type(new) == "table" then | 110 if type(new) == "table" then |
| 116 for field, value in pairs(new) do | 111 for field, value in pairs(new) do |
| 117 (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 | |
| 118 end | 116 end |
| 119 end | 117 end |
| 120 return config | 118 return config |
| 121 end | 119 end |
| 122 | 120 |
| 123 -- Finalize the config into the form LuaSec expects | 121 -- Finalize the config into the form LuaSec expects |
| 124 local function final(config) | 122 local function final(config) |
| 125 local output = { }; | 123 local output = { }; |
| 126 for field, value in pairs(config) do | 124 for field, value in pairs(config) do |
| 127 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 | |
| 128 end | 129 end |
| 129 -- 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 |
| 130 protocol(output); | 131 protocol(output); |
| 131 return output; | 132 return output; |
| 132 end | 133 end |
| 133 | 134 |
| 134 local function build(config) | 135 local function build(config) |
| 135 local cached = rawget(config, 0); | 136 local cached = rawget(config, "_cache"); |
| 136 if cached then | 137 if cached then |
| 137 return cached, nil | 138 return cached, nil |
| 138 end | 139 end |
| 139 | 140 |
| 140 local ctx, err = tls_impl.new_context(config:final(), config); | 141 local ctx, err = rawget(config, "_context_factory")(config:final(), config); |
| 141 if ctx then | 142 if ctx then |
| 142 rawset(config, 0, ctx); | 143 rawset(config, "_cache", ctx); |
| 143 end | 144 end |
| 144 return ctx, err | 145 return ctx, err |
| 145 end | 146 end |
| 146 | 147 |
| 147 local sslopts_mt = { | 148 local sslopts_mt = { |
| 154 error("SSL config objects cannot be modified directly. Use :apply()") | 155 error("SSL config objects cannot be modified directly. Use :apply()") |
| 155 end; | 156 end; |
| 156 }; | 157 }; |
| 157 | 158 |
| 158 | 159 |
| 159 local function new() | 160 -- passing basedir through everything is required to avoid sslconfig depending |
| 160 return setmetatable({options={}}, sslopts_mt); | 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); | |
| 161 end | 168 end |
| 162 | 169 |
| 163 local function clone(config) | 170 local function clone(config) |
| 164 local result = new(); | 171 local result = new(); |
| 165 for k, v in pairs(config) do | 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 | |
| 166 rawset(result, k, v); | 175 rawset(result, k, v); |
| 167 end | 176 end |
| 168 return result | 177 return result |
| 169 end | 178 end |
| 170 | 179 |
| 171 sslopts_mt.__index.clone = clone; | 180 sslopts_mt.__index.clone = clone; |
| 172 | 181 |
| 173 return { | 182 return { |
| 174 apply = apply; | 183 apply = apply; |
| 175 final = final; | 184 final = final; |
| 176 new = new; | 185 _new = new; |
| 177 }; | 186 }; |
