1 local type, tostring, pairs
, ipairs
= type, tostring, pairs
, ipairs
;
2 local t_insert
, t_concat
= table.insert
, table.concat
;
3 local s_format
= string.format;
5 local oid_xmppaddr
= "1.3.6.1.5.5.7.8.5"; -- [XMPP-CORE]
6 local oid_dnssrv
= "1.3.6.1.5.5.7.8.7"; -- [SRV-ID]
8 local idna_to_ascii
= require
"util.encodings".idna
.to_ascii
;
14 local ssl_config
= {};
15 local ssl_config_mt
= { __index
= ssl_config
};
20 distinguished_name
= "distinguished_name",
21 req_extensions
= "certrequest",
22 x509_extensions
= "selfsigned",
25 distinguished_name
= {
27 -- stateOrProvinceName = "",
28 localityName
= "The Internet",
29 organizationName
= "Your Organisation",
30 organizationalUnitName
= "XMPP Department",
31 commonName
= "example.com",
32 emailAddress
= "xmpp@example.com",
35 basicConstraints
= "CA:FALSE",
36 keyUsage
= "digitalSignature,keyEncipherment",
37 extendedKeyUsage
= "serverAuth,clientAuth",
38 subjectAltName
= "@subject_alternative_name",
41 basicConstraints
= "CA:TRUE",
42 subjectAltName
= "@subject_alternative_name",
44 subject_alternative_name
= {
53 "stateOrProvinceName";
57 "organizationalUnitName";
61 _M
._DN_order
= DN_order
;
62 function ssl_config
:serialize()
64 for section
, t
in pairs(self
) do
65 s
= s
.. ("[%s]\n"):format(section
);
66 if section
== "subject_alternative_name" then
67 for san
, n
in pairs(t
) do
69 s
= s
.. s_format("%s.%d = %s\n", san
, i
-1, n
[i
]);
72 elseif section
== "distinguished_name" then
73 for _
, k
in ipairs(t
[1] and t
or DN_order
) do
76 s
= s
.. ("%s = %s\n"):format(k
, v
);
80 for k
, v
in pairs(t
) do
81 s
= s
.. ("%s = %s\n"):format(k
, v
);
89 local function utf8string(s
)
90 -- This is how we tell openssl not to encode UTF-8 strings as fake Latin1
91 return s_format("FORMAT:UTF8,UTF8:%s", s
);
94 local function ia5string(s
)
95 return s_format("IA5STRING:%s", s
);
99 utf8string
= utf8string
,
100 ia5string
= ia5string
,
103 function ssl_config
:add_dNSName(host
)
104 t_insert(self
.subject_alternative_name
.DNS
, idna_to_ascii(host
));
107 function ssl_config
:add_sRVName(host
, service
)
108 t_insert(self
.subject_alternative_name
.otherName
,
109 s_format("%s;%s", oid_dnssrv
, ia5string("_" .. service
.. "." .. idna_to_ascii(host
))));
112 function ssl_config
:add_xmppAddr(host
)
113 t_insert(self
.subject_alternative_name
.otherName
,
114 s_format("%s;%s", oid_xmppaddr
, utf8string(host
)));
117 function ssl_config
:from_prosody(hosts
, config
, certhosts
) -- luacheck: ignore 431/config
118 -- TODO Decide if this should go elsewhere
119 local found_matching_hosts
= false;
120 for i
= 1, #certhosts
do
121 local certhost
= certhosts
[i
];
122 for name
in pairs(hosts
) do
123 if name
== certhost
or name
:sub(-1-#certhost
) == "." .. certhost
then
124 found_matching_hosts
= true;
125 self
:add_dNSName(name
);
126 --print(name .. "#component_module: " .. (config.get(name, "component_module") or "nil"));
127 if config
.get(name
, "component_module") == nil then
128 self
:add_sRVName(name
, "xmpp-client");
130 --print(name .. "#anonymous_login: " .. tostring(config.get(name, "anonymous_login")));
131 if not (config
.get(name
, "anonymous_login") or
132 config
.get(name
, "authentication") == "anonymous") then
133 self
:add_sRVName(name
, "xmpp-server");
135 self
:add_xmppAddr(name
);
139 if not found_matching_hosts
then
140 return nil, "no-matching-hosts";
144 do -- Lua to shell calls.
145 local function shell_escape(s
)
146 return "'" .. tostring(s
):gsub("'",[['\'']]) .. "'";
149 local function serialize(command
, args
)
150 local commandline
= { "openssl", command
};
151 for k
, v
in pairs(args
) do
152 if type(k
) == "string" then
153 t_insert(commandline
, ("-%s"):format(k
));
155 t_insert(commandline
, shell_escape(v
));
159 for _
, v
in ipairs(args
) do
160 t_insert(commandline
, shell_escape(v
));
162 return t_concat(commandline
, " ");
165 local os_execute
= os
.execute;
167 __index
= function(_
, command
)
168 return function(opts
)
169 local ret
= os_execute(serialize(command
, type(opts
) == "table" and opts
or {}));
170 return ret
== true or ret
== 0;