Comparison

prosodyctl @ 8112:d8ecefcb7c97

Merge 0.10->trunk
author Kim Alvefur <zash@zash.se>
date Fri, 21 Apr 2017 15:22:17 +0200
parent 8103:a0b498ec0b22
parent 8111:3cbb311f8468
child 8121:a33a87f13155
comparison
equal deleted inserted replaced
8103:a0b498ec0b22 8112:d8ecefcb7c97
137 137
138 local want_pposix_version = "0.4.0"; 138 local want_pposix_version = "0.4.0";
139 local have_pposix, pposix = pcall(require, "util.pposix"); 139 local have_pposix, pposix = pcall(require, "util.pposix");
140 140
141 if have_pposix and pposix then 141 if have_pposix and pposix then
142 if pposix._VERSION ~= want_pposix_version then print(string.format("Unknown version (%s) of binary pposix module, expected %s", tostring(pposix._VERSION), want_pposix_version)); return; end 142 if pposix._VERSION ~= want_pposix_version then
143 print(string.format("Unknown version (%s) of binary pposix module, expected %s",
144 tostring(pposix._VERSION), want_pposix_version)); return;
145 end
143 current_uid = pposix.getuid(); 146 current_uid = pposix.getuid();
144 local arg_root = arg[1] == "--root"; 147 local arg_root = arg[1] == "--root";
145 if arg_root then table.remove(arg, 1); end 148 if arg_root then table.remove(arg, 1); end
146 if current_uid == 0 and config.get("*", "run_as_root") ~= true and not arg_root then 149 if current_uid == 0 and config.get("*", "run_as_root") ~= true and not arg_root then
147 -- We haz root! 150 -- We haz root!
816 if key_filename and conf_filename and cert_filename 819 if key_filename and conf_filename and cert_filename
817 and openssl.req{new=true, x509=true, nodes=true, key=key_filename, 820 and openssl.req{new=true, x509=true, nodes=true, key=key_filename,
818 days=365, sha256=true, utf8=true, config=conf_filename, out=cert_filename} then 821 days=365, sha256=true, utf8=true, config=conf_filename, out=cert_filename} then
819 show_message("Certificate written to ".. cert_filename); 822 show_message("Certificate written to ".. cert_filename);
820 print(); 823 print();
821 show_message(("Example config:\n\nssl = {\n\tcertificate = %q;\n\tkey = %q;\n}"):format(cert_filename, key_filename));
822 else 824 else
823 show_message("There was a problem, see OpenSSL output"); 825 show_message("There was a problem, see OpenSSL output");
824 end 826 end
825 else 827 else
826 show_usage("cert generate HOSTNAME [HOSTNAME+]", "Generates a self-signed certificate for the current hostname(s)") 828 show_usage("cert generate HOSTNAME [HOSTNAME+]", "Generates a self-signed certificate for the current hostname(s)")
829 end
830 end
831
832 local function sh_esc(s)
833 return "'" .. s:gsub("'", "'\\''") .. "'";
834 end
835
836 local function copy(from, to, umask, owner, group)
837 local old_umask = umask and pposix.umask(umask);
838 local attrs = lfs.attributes(to);
839 if attrs then -- Move old file out of the way
840 local backup = to..".bkp~"..os.date("%FT%T", attrs.change);
841 os.rename(to, backup);
842 end
843 -- FIXME friendlier error handling, maybe move above backup back?
844 local input = assert(io.open(from));
845 local output = assert(io.open(to, "w"));
846 local data = input:read(2^11);
847 while data and output:write(data) do
848 data = input:read(2^11);
849 end
850 assert(input:close());
851 assert(output:close());
852 if owner and group then
853 local ok = os.execute(("chown %s.%s %s"):format(sh_esc(owner), sh_esc(group), sh_esc(to)));
854 assert(ok == true or ok == 0, "Failed to change ownership of "..to);
855 end
856 if old_umask then pposix.umask(old_umask); end
857 return true;
858 end
859
860 function cert_commands.import(arg)
861 local hostnames = {};
862 -- Move hostname arguments out of arg, the rest should be a list of paths
863 while arg[1] and prosody.hosts[ arg[1] ] do
864 table.insert(hostnames, table.remove(arg, 1));
865 end
866 if not arg[1] or arg[1] == "--help" then -- Probably forgot the path
867 show_usage("cert import HOSTNAME [HOSTNAME+] /path/to/certs [/other/paths/]+",
868 "Copies certificates to "..cert_basedir);
869 return 1;
870 end
871 local owner, group;
872 if pposix.getuid() == 0 then -- We need root to change ownership
873 owner = config.get("*", "prosody_user") or "prosody";
874 group = config.get("*", "prosody_group") or owner;
875 end
876 for _, host in ipairs(hostnames) do
877 for _, dir in ipairs(arg) do
878 if lfs.attributes(dir .. "/" .. host .. "/fullchain.pem")
879 and lfs.attributes(dir .. "/" .. host .. "/privkey.pem") then
880 copy(dir .. "/" .. host .. "/fullchain.pem", cert_basedir .. "/" .. host .. ".crt", nil, owner, group);
881 copy(dir .. "/" .. host .. "/privkey.pem", cert_basedir .. "/" .. host .. ".key", "0377", owner, group);
882 show_message("Imported certificate and key for "..host);
883 elseif lfs.attributes(dir .. "/" .. host .. ".crt")
884 and lfs.attributes(dir .. "/" .. host .. ".key") then
885 copy(dir .. "/" .. host .. ".crt", cert_basedir .. "/" .. host .. ".crt", nil, owner, group);
886 copy(dir .. "/" .. host .. ".key", cert_basedir .. "/" .. host .. ".key", "0377", owner, group);
887 show_message("Imported certificate and key for "..host);
888 else
889 show_warning("No certificate for host "..host.." found :(");
890 end
891 -- TODO Additional checks
892 -- Certificate names matches the hostname
893 -- Private key matches public key in certificate
894 end
827 end 895 end
828 end 896 end
829 897
830 function commands.cert(arg) 898 function commands.cert(arg)
831 if #arg >= 1 and arg[1] ~= "--help" then 899 if #arg >= 1 and arg[1] ~= "--help" then
832 openssl = require "util.openssl"; 900 openssl = require "util.openssl";
833 lfs = require "lfs"; 901 lfs = require "lfs";
902 local cert_dir_attrs = lfs.attributes(cert_basedir);
903 if not cert_dir_attrs then
904 show_warning("The directory "..cert_basedir.." does not exist");
905 return 1; -- TODO Should we create it?
906 end
907 if pposix.getuid() ~= cert_dir_attrs.uid then
908 show_warning("The directory "..cert_basedir.." is not owned by the current user, won't be able to write files to it");
909 return 1;
910 elseif cert_dir_attrs.permissions:match("^%.w..%-..%-.$") then
911 show_warning("The directory "..cert_basedir.." not only writable by its owner");
912 return 1;
913 end
834 local subcmd = table.remove(arg, 1); 914 local subcmd = table.remove(arg, 1);
835 if type(cert_commands[subcmd]) == "function" then 915 if type(cert_commands[subcmd]) == "function" then
836 if not arg[1] then 916 if not arg[1] then
837 show_message"You need to supply at least one hostname" 917 show_message"You need to supply at least one hostname"
838 arg = { "--help" }; 918 arg = { "--help" };
839 end 919 end
840 if arg[1] ~= "--help" and not hosts[arg[1]] then 920 if arg[1] ~= "--help" and not hosts[arg[1]] then
841 show_message(error_messages["no-such-host"]); 921 show_message(error_messages["no-such-host"]);
842 return 922 return 1;
843 end 923 end
844 return cert_commands[subcmd](arg); 924 return cert_commands[subcmd](arg);
845 end 925 end
846 end 926 end
847 show_usage("cert config|request|generate|key", "Helpers for generating X.509 certificates and keys.") 927 show_usage("cert config|request|generate|key", "Helpers for generating X.509 certificates and keys.")