Mercurial > prosody-hg
comparison util/openssl.lua @ 4823:a61e78b4a2b3
util.openssl: Add wrapper for the openssl cli tool and move certificate config logic from util.x509 into it.
| author | Kim Alvefur <zash@zash.se> |
|---|---|
| date | Wed, 09 May 2012 00:12:53 +0200 |
| parents | |
| children | befb1923527d |
comparison
equal
deleted
inserted
replaced
| 4821:deec69fc33e5 | 4823:a61e78b4a2b3 |
|---|---|
| 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; | |
| 4 | |
| 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] | |
| 7 | |
| 8 local idna_to_ascii = require "util.encodings".idna.to_ascii; | |
| 9 | |
| 10 local _M = {}; | |
| 11 local config = {}; | |
| 12 _M.config = config; | |
| 13 | |
| 14 local ssl_config = {}; | |
| 15 local ssl_config_mt = {__index=ssl_config}; | |
| 16 | |
| 17 function config.new() | |
| 18 return setmetatable({ | |
| 19 req = { | |
| 20 distinguished_name = "distinguished_name", | |
| 21 req_extensions = "v3_extensions", | |
| 22 x509_extensions = "v3_extensions", | |
| 23 prompt = "no", | |
| 24 }, | |
| 25 distinguished_name = { | |
| 26 commonName = "example.com", | |
| 27 countryName = "GB", | |
| 28 localityName = "The Internet", | |
| 29 organizationName = "Your Organisation", | |
| 30 organizationalUnitName = "XMPP Department", | |
| 31 emailAddress = "xmpp@example.com", | |
| 32 }, | |
| 33 v3_extensions = { | |
| 34 basicConstraints = "CA:FALSE", | |
| 35 keyUsage = "digitalSignature,keyEncipherment", | |
| 36 extendedKeyUsage = "serverAuth,clientAuth", | |
| 37 subjectAltName = "@subject_alternative_name", | |
| 38 }, | |
| 39 subject_alternative_name = { | |
| 40 DNS = {}, | |
| 41 otherName = {}, | |
| 42 }, | |
| 43 }, ssl_config_mt); | |
| 44 end | |
| 45 | |
| 46 function ssl_config:serialize() | |
| 47 local s = ""; | |
| 48 for k, t in pairs(self) do | |
| 49 s = s .. ("[%s]\n"):format(k); | |
| 50 if k == "subject_alternative_name" then | |
| 51 for san, n in pairs(t) do | |
| 52 for i = 1,#n do | |
| 53 s = s .. s_format("%s.%d = %s\n", san, i -1, n[i]); | |
| 54 end | |
| 55 end | |
| 56 else | |
| 57 for k, v in pairs(t) do | |
| 58 s = s .. ("%s = %s\n"):format(k, v); | |
| 59 end | |
| 60 end | |
| 61 s = s .. "\n"; | |
| 62 end | |
| 63 return s; | |
| 64 end | |
| 65 | |
| 66 local function utf8string(s) | |
| 67 -- This is how we tell openssl not to encode UTF-8 strings as fake Latin1 | |
| 68 return s_format("FORMAT:UTF8,UTF8:%s", s); | |
| 69 end | |
| 70 | |
| 71 local function ia5string(s) | |
| 72 return s_format("IA5STRING:%s", s); | |
| 73 end | |
| 74 | |
| 75 local util = {}; | |
| 76 _M.util = { | |
| 77 utf8string = utf8string, | |
| 78 ia5string = ia5string, | |
| 79 }; | |
| 80 | |
| 81 local function xmppAddr(t, host) | |
| 82 end | |
| 83 | |
| 84 function ssl_config:add_dNSName(host) | |
| 85 t_insert(self.subject_alternative_name.DNS, idna_to_ascii(host)); | |
| 86 end | |
| 87 | |
| 88 function ssl_config:add_sRVName(host, service) | |
| 89 t_insert(self.subject_alternative_name.otherName, | |
| 90 s_format("%s;%s", oid_dnssrv, ia5string("_" .. service .."." .. idna_to_ascii(host)))); | |
| 91 end | |
| 92 | |
| 93 function ssl_config:add_xmppAddr(host) | |
| 94 t_insert(self.subject_alternative_name.otherName, | |
| 95 s_format("%s;%s", oid_xmppaddr, utf8string(host))); | |
| 96 end | |
| 97 | |
| 98 function ssl_config:from_prosody(hosts, config, certhosts, raw) | |
| 99 -- TODO Decide if this should go elsewhere | |
| 100 local found_matching_hosts = false; | |
| 101 for i = 1,#certhosts do | |
| 102 local certhost = certhosts[i]; | |
| 103 for name, host in pairs(hosts) do | |
| 104 if name == certhost or name:sub(-1-#certhost) == "."..certhost then | |
| 105 found_matching_hosts = true; | |
| 106 self:add_dNSName(name); | |
| 107 --print(name .. "#component_module: " .. (config.get(name, "core", "component_module") or "nil")); | |
| 108 if config.get(name, "core", "component_module") == nil then | |
| 109 self:add_sRVName(name, "xmpp-client"); | |
| 110 end | |
| 111 --print(name .. "#anonymous_login: " .. tostring(config.get(name, "core", "anonymous_login"))); | |
| 112 if not (config.get(name, "core", "anonymous_login") or | |
| 113 config.get(name, "core", "authentication") == "anonymous") then | |
| 114 self:add_sRVName(name, "xmpp-server"); | |
| 115 end | |
| 116 self:add_xmppAddr(name); | |
| 117 end | |
| 118 end | |
| 119 end | |
| 120 if not found_matching_hosts then | |
| 121 return nil, "no-matching-hosts"; | |
| 122 end | |
| 123 end | |
| 124 | |
| 125 do -- Lua to shell calls. | |
| 126 local function shell_escape(s) | |
| 127 return s:gsub("'",[['\'']]); | |
| 128 end | |
| 129 | |
| 130 local function serialize(f,o) | |
| 131 local r = {"openssl", f}; | |
| 132 for k,v in pairs(o) do | |
| 133 if type(k) == "string" then | |
| 134 t_insert(r, ("-%s"):format(k)); | |
| 135 if v ~= true then | |
| 136 t_insert(r, ("'%s'"):format(shell_escape(tostring(v)))); | |
| 137 end | |
| 138 end | |
| 139 end | |
| 140 for k,v in ipairs(o) do | |
| 141 t_insert(r, ("'%s'"):format(shell_escape(tostring(v)))); | |
| 142 end | |
| 143 return t_concat(r, " "); | |
| 144 end | |
| 145 | |
| 146 local os_execute = os.execute; | |
| 147 setmetatable(_M, { | |
| 148 __index=function(self,f) | |
| 149 return function(opts) | |
| 150 return 0 == os_execute(serialize(f, type(opts) == "table" and opts or {})); | |
| 151 end; | |
| 152 end; | |
| 153 }); | |
| 154 end | |
| 155 | |
| 156 return _M; |
