aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKim Alvefur <zash@zash.se>2017-04-21 15:11:25 +0200
committerKim Alvefur <zash@zash.se>2017-04-21 15:11:25 +0200
commit279badc8aec122e4533560e2b34cf9021a8a75c4 (patch)
treeef9530b2df0d65649cb32f6bfd39f9e90e736af1
parente90ec99152efd2932a3c0ae32215e968cbf5ac8f (diff)
downloadprosody-279badc8aec122e4533560e2b34cf9021a8a75c4.tar.gz
prosody-279badc8aec122e4533560e2b34cf9021a8a75c4.zip
prosodyctl: cert import: Command to copy certificates into prosodys certificate directory (fixes #892)
-rwxr-xr-xprosodyctl66
1 files changed, 66 insertions, 0 deletions
diff --git a/prosodyctl b/prosodyctl
index 637fdd12..cc410f5a 100755
--- a/prosodyctl
+++ b/prosodyctl
@@ -829,6 +829,72 @@ function cert_commands.generate(arg)
end
end
+local function sh_esc(s)
+ return "'" .. s:gsub("'", "'\\''") .. "'";
+end
+
+local function copy(from, to, umask, owner, group)
+ local old_umask = umask and pposix.umask(umask);
+ local attrs = lfs.attributes(to);
+ if attrs then -- Move old file out of the way
+ local backup = to..".bkp~"..os.date("%FT%T", attrs.change);
+ os.rename(to, backup);
+ end
+ -- FIXME friendlier error handling, maybe move above backup back?
+ local input = assert(io.open(from));
+ local output = assert(io.open(to, "w"));
+ local data = input:read(2^11);
+ while data and output:write(data) do
+ data = input:read(2^11);
+ end
+ assert(input:close());
+ assert(output:close());
+ if owner and group then
+ local ok = os.execute(("chown %s.%s %s"):format(sh_esc(owner), sh_esc(group), sh_esc(to)));
+ assert(ok == true or ok == 0, "Failed to change ownership of "..to);
+ end
+ if old_umask then pposix.umask(old_umask); end
+ return true;
+end
+
+function cert_commands.import(arg)
+ local hostnames = {};
+ -- Move hostname arguments out of arg, the rest should be a list of paths
+ while arg[1] and prosody.hosts[ arg[1] ] do
+ table.insert(hostnames, table.remove(arg, 1));
+ end
+ if not arg[1] or arg[1] == "--help" then -- Probably forgot the path
+ show_usage("cert import HOSTNAME [HOSTNAME+] /path/to/certs [/other/paths/]+",
+ "Copies certificates to "..cert_basedir);
+ return 1;
+ end
+ local owner, group;
+ if pposix.getuid() == 0 then -- We need root to change ownership
+ owner = config.get("*", "prosody_user") or "prosody";
+ group = config.get("*", "prosody_group") or owner;
+ end
+ for _, host in ipairs(hostnames) do
+ for _, dir in ipairs(arg) do
+ if lfs.attributes(dir .. "/" .. host .. "/fullchain.pem")
+ and lfs.attributes(dir .. "/" .. host .. "/privkey.pem") then
+ copy(dir .. "/" .. host .. "/fullchain.pem", cert_basedir .. "/" .. host .. ".crt", nil, owner, group);
+ copy(dir .. "/" .. host .. "/privkey.pem", cert_basedir .. "/" .. host .. ".key", "0377", owner, group);
+ show_message("Imported certificate and key for "..host);
+ elseif lfs.attributes(dir .. "/" .. host .. ".crt")
+ and lfs.attributes(dir .. "/" .. host .. ".key") then
+ copy(dir .. "/" .. host .. ".crt", cert_basedir .. "/" .. host .. ".crt", nil, owner, group);
+ copy(dir .. "/" .. host .. ".key", cert_basedir .. "/" .. host .. ".key", "0377", owner, group);
+ show_message("Imported certificate and key for "..host);
+ else
+ show_warning("No certificate for host "..host.." found :(");
+ end
+ -- TODO Additional checks
+ -- Certificate names matches the hostname
+ -- Private key matches public key in certificate
+ end
+ end
+end
+
function commands.cert(arg)
if #arg >= 1 and arg[1] ~= "--help" then
openssl = require "util.openssl";