local nameprep = require "util.encodings".stringprep.nameprep;
local idna_to_ascii = require "util.encodings".idna.to_ascii;
+local base64 = require "util.encodings".base64;
local log = require "util.logger".init("x509");
-local pairs, ipairs = pairs, ipairs;
local s_format = string.format;
-local t_insert = table.insert;
-local t_concat = table.concat;
-module "x509"
+local _ENV = nil;
local oid_commonname = "2.5.4.3"; -- [LDAP] 2.3
local oid_subjectaltname = "2.5.29.17"; -- [PKIX] 4.2.1.6
return false
end
-function verify_identity(host, service, cert)
+local function verify_identity(host, service, cert)
+ if cert.setencode then
+ cert:setencode("utf8");
+ end
local ext = cert:extensions()
if ext[oid_subjectaltname] then
local sans = ext[oid_subjectaltname];
if sans[oid_xmppaddr] then
had_supported_altnames = true
- if compare_xmppaddr(host, sans[oid_xmppaddr]) then return true end
+ if service == "_xmpp-client" or service == "_xmpp-server" then
+ if compare_xmppaddr(host, sans[oid_xmppaddr]) then return true end
+ end
end
if sans[oid_dnssrv] then
return false
end
--- TODO Rename? Split out subroutines?
--- Also, this is probably openssl specific, what TODO about that?
-function genx509san(hosts, config, certhosts, raw) -- recive config through that or some better way?
- local function utf8string(s)
- -- This is how we tell openssl not to encode UTF-8 strings as Latin1
- return s_format("FORMAT:UTF8,UTF8:%s", s);
- end
-
- local function ia5string(s)
- return s_format("IA5STRING:%s", s);
- end
-
- local function dnsname(t, host)
- t_insert(t.DNS, idna_to_ascii(host));
- end
-
- local function srvname(t, host, service)
- t_insert(t.otherName, s_format("%s;%s", oid_dnssrv, ia5string("_" .. service .."." .. idna_to_ascii(host))));
- end
-
- local function xmppAddr(t, host)
- t_insert(t.otherName, s_format("%s;%s", oid_xmppaddr, utf8string(host)));
- end
-
- -----------------------------
-
- local san = {
- DNS = {};
- otherName = {};
- };
-
- local sslsanconf = { };
+local pat = "%-%-%-%-%-BEGIN ([A-Z ]+)%-%-%-%-%-\r?\n"..
+"([0-9A-Za-z+/=\r\n]*)\r?\n%-%-%-%-%-END %1%-%-%-%-%-";
- for i = 1,#certhosts do
- local certhost = certhosts[i];
- for name, host in pairs(hosts) do
- if name == certhost or name:sub(-1-#certhost) == "."..certhost then
- dnsname(san, name);
- --print(name .. "#component_module: " .. (config.get(name, "core", "component_module") or "nil"));
- if config.get(name, "core", "component_module") == nil then
- srvname(san, name, "xmpp-client");
- end
- --print(name .. "#anonymous_login: " .. tostring(config.get(name, "core", "anonymous_login")));
- if not (config.get(name, "core", "anonymous_login") or
- config.get(name, "core", "authentication") == "anonymous") then
- srvname(san, name, "xmpp-server");
- end
- xmppAddr(san, name);
- end
- end
- end
-
- for t, n in pairs(san) do
- for i = 1,#n do
- t_insert(sslsanconf, s_format("%s.%d = %s", t, i -1, n[i]));
- end
+local function pem2der(pem)
+ local typ, data = pem:match(pat);
+ if typ and data then
+ return base64.decode(data), typ;
end
-
- return raw and sslsanconf or t_concat(sslsanconf, "\n");
end
-function baseconf()
- return {
- req = {
- distinguished_name = "distinguished_name",
- req_extensions = "v3_extensions",
- x509_extensions = "v3_extensions",
- prompt = "no",
- },
- distinguished_name = {
- commonName = "example.com",
- countryName = "GB",
- localityName = "The Internet",
- organizationName = "Your Organisation",
- organizationalUnitName = "XMPP Department",
- emailAddress = "xmpp@example.com",
- },
- v3_extensions = {
- basicConstraints = "CA:FALSE",
- keyUsage = "digitalSignature,keyEncipherment",
- extendedKeyUsage = "serverAuth,clientAuth",
- subjectAltName = "@subject_alternative_name",
- },
- subject_alternative_name = { },
- }
-end
+local wrap = ('.'):rep(64);
+local envelope = "-----BEGIN %s-----\n%s\n-----END %s-----\n"
-function serialize_conf(conf)
- local s = "";
- for k, t in pairs(conf) do
- s = s .. ("[%s]\n"):format(k);
- if t[1] then
- for i, v in ipairs(t) do
- s = s .. ("%s\n"):format(v);
- end
- else
- for k, v in pairs(t) do
- s = s .. ("%s = %s\n"):format(k, v);
- end
- end
- s = s .. "\n";
- end
- return s;
+local function der2pem(data, typ)
+ typ = typ and typ:upper() or "CERTIFICATE";
+ data = base64.encode(data);
+ return s_format(envelope, typ, data:gsub(wrap, '%0\n', (#data-1)/64), typ);
end
-return _M;
+return {
+ verify_identity = verify_identity;
+ pem2der = pem2der;
+ der2pem = der2pem;
+};