Software / code / prosody
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.") |