comparison util/x509.lua @ 14110:f587496eb08f 13.0

util.x509: Add support for iPAddress certs Issued by Let's Encrypt and requested by some users.
author Kim Alvefur <zash@zash.se>
date Tue, 13 Jan 2026 07:13:25 +0100
parents b50eadfddd57
children
comparison
equal deleted inserted replaced
14105:4ed802e45af6 14110:f587496eb08f
23 local idna_to_ascii = require "prosody.util.encodings".idna.to_ascii; 23 local idna_to_ascii = require "prosody.util.encodings".idna.to_ascii;
24 local idna_to_unicode = require "prosody.util.encodings".idna.to_unicode; 24 local idna_to_unicode = require "prosody.util.encodings".idna.to_unicode;
25 local base64 = require "prosody.util.encodings".base64; 25 local base64 = require "prosody.util.encodings".base64;
26 local log = require "prosody.util.logger".init("x509"); 26 local log = require "prosody.util.logger".init("x509");
27 local mt = require "prosody.util.multitable"; 27 local mt = require "prosody.util.multitable";
28 local ip = require "prosody.util.ip";
28 local s_format = string.format; 29 local s_format = string.format;
29 local ipairs = ipairs; 30 local ipairs = ipairs;
30 31
31 local _ENV = nil; 32 local _ENV = nil;
32 -- luacheck: std none 33 -- luacheck: std none
64 local rest_name = name:gsub("^[^.]+%.", "") 65 local rest_name = name:gsub("^[^.]+%.", "")
65 if host_chopped == rest_name:lower() then 66 if host_chopped == rest_name:lower() then
66 log("debug", "Cert dNSName %s matched hostname", name); 67 log("debug", "Cert dNSName %s matched hostname", name);
67 return true 68 return true
68 end 69 end
70 end
71 end
72
73 return false
74 end
75
76 local function compare_ipaddress(host, asserted_names)
77 local host_ip = ip.new_ip(host:match("^%[([%x:.]+)%]$") or host);
78 if not host_ip then return false end
79
80 for i=1,#asserted_names do
81 if ip.new_ip(asserted_names[i]) == host_ip then
82 log("debug", "Cert iPAddress %s matched IP address", host_ip);
83 return true;
69 end 84 end
70 end 85 end
71 86
72 return false 87 return false
73 end 88 end
170 end 185 end
171 186
172 if sans["dNSName"] then 187 if sans["dNSName"] then
173 if compare_dnsname(host, sans["dNSName"]) then return true end 188 if compare_dnsname(host, sans["dNSName"]) then return true end
174 end 189 end
190 if sans["iPAddress"] then
191 if compare_ipaddress(host, sans["iPAddress"]) then return true end
192 end
175 end 193 end
176 194
177 -- Per [TLS-IDENT] ignore the Common Name 195 -- Per [TLS-IDENT] ignore the Common Name
178 -- The server identity can only be expressed in the subjectAltNames extension; 196 -- The server identity can only be expressed in the subjectAltNames extension;
179 -- it is no longer valid to use the commonName RDN, known as CN-ID in [TLS-CERTS]. 197 -- it is no longer valid to use the commonName RDN, known as CN-ID in [TLS-CERTS].
222 names:set(name, srv, true); 240 names:set(name, srv, true);
223 end 241 end
224 end 242 end
225 end 243 end
226 end 244 end
245 if sans["iPAddress"] then
246 for _, addr in ipairs(sans["iPAddress"]) do
247 if addr:find(":") then
248 names:set("[" .. addr .. "]", "*", true);
249 else
250 names:set(addr, "*", true);
251 end
252 end
253 end
227 end 254 end
228 255
229 local subject = cert:subject(); 256 local subject = cert:subject();
230 for i = 1, #subject do 257 for i = 1, #subject do
231 local dn = subject[i]; 258 local dn = subject[i];