Software / code / prosody
Comparison
plugins/mod_admin_telnet.lua @ 5024:d25e1b9332cc
Merge with Florob
| author | Matthew Wild <mwild1@gmail.com> |
|---|---|
| date | Sat, 28 Jul 2012 01:14:31 +0100 |
| parent | 5023:dcc8e789df36 |
| parent | 5013:ab693eea0869 |
| child | 5025:e68d1b85ee3a |
comparison
equal
deleted
inserted
replaced
| 5023:dcc8e789df36 | 5024:d25e1b9332cc |
|---|---|
| 11 local _G = _G; | 11 local _G = _G; |
| 12 | 12 |
| 13 local prosody = _G.prosody; | 13 local prosody = _G.prosody; |
| 14 local hosts = prosody.hosts; | 14 local hosts = prosody.hosts; |
| 15 | 15 |
| 16 local console_listener = { default_port = 5582; default_mode = "*l"; interface = "127.0.0.1" }; | 16 local console_listener = { default_port = 5582; default_mode = "*a"; interface = "127.0.0.1" }; |
| 17 | 17 |
| 18 local hostmanager = require "core.hostmanager"; | 18 local hostmanager = require "core.hostmanager"; |
| 19 local modulemanager = require "core.modulemanager"; | 19 local modulemanager = require "core.modulemanager"; |
| 20 | 20 |
| 21 local iterators = require "util.iterators"; | 21 local iterators = require "util.iterators"; |
| 28 local envloadfile = require "util.envload".envloadfile; | 28 local envloadfile = require "util.envload".envloadfile; |
| 29 | 29 |
| 30 local commands = module:shared("commands") | 30 local commands = module:shared("commands") |
| 31 local def_env = module:shared("env"); | 31 local def_env = module:shared("env"); |
| 32 local default_env_mt = { __index = def_env }; | 32 local default_env_mt = { __index = def_env }; |
| 33 local core_post_stanza = prosody.core_post_stanza; | |
| 33 | 34 |
| 34 local function redirect_output(_G, session) | 35 local function redirect_output(_G, session) |
| 35 local env = setmetatable({ print = session.print }, { __index = function (t, k) return rawget(_G, k); end }); | 36 local env = setmetatable({ print = session.print }, { __index = function (t, k) return rawget(_G, k); end }); |
| 36 env.dofile = function(name) | 37 env.dofile = function(name) |
| 37 local f, err = envloadfile(name, env); | 38 local f, err = envloadfile(name, env); |
| 79 end | 80 end |
| 80 | 81 |
| 81 function console_listener.onincoming(conn, data) | 82 function console_listener.onincoming(conn, data) |
| 82 local session = sessions[conn]; | 83 local session = sessions[conn]; |
| 83 | 84 |
| 84 -- Handle data | 85 local partial = session.partial_data; |
| 85 (function(session, data) | 86 if partial then |
| 86 local useglobalenv; | 87 data = partial..data; |
| 88 end | |
| 89 | |
| 90 for line in data:gmatch("[^\n]*[\n\004]") do | |
| 91 -- Handle data (loop allows us to break to add \0 after response) | |
| 92 repeat | |
| 93 local useglobalenv; | |
| 94 | |
| 95 if line:match("^>") then | |
| 96 line = line:gsub("^>", ""); | |
| 97 useglobalenv = true; | |
| 98 elseif line == "\004" then | |
| 99 commands["bye"](session, line); | |
| 100 break; | |
| 101 else | |
| 102 local command = line:match("^%w+") or line:match("%p"); | |
| 103 if commands[command] then | |
| 104 commands[command](session, line); | |
| 105 break; | |
| 106 end | |
| 107 end | |
| 108 | |
| 109 session.env._ = line; | |
| 110 | |
| 111 local chunkname = "=console"; | |
| 112 local env = (useglobalenv and redirect_output(_G, session)) or session.env or nil | |
| 113 local chunk, err = envload("return "..line, chunkname, env); | |
| 114 if not chunk then | |
| 115 chunk, err = envload(line, chunkname, env); | |
| 116 if not chunk then | |
| 117 err = err:gsub("^%[string .-%]:%d+: ", ""); | |
| 118 err = err:gsub("^:%d+: ", ""); | |
| 119 err = err:gsub("'<eof>'", "the end of the line"); | |
| 120 session.print("Sorry, I couldn't understand that... "..err); | |
| 121 break; | |
| 122 end | |
| 123 end | |
| 87 | 124 |
| 88 if data:match("^>") then | 125 local ranok, taskok, message = pcall(chunk); |
| 89 data = data:gsub("^>", ""); | 126 |
| 90 useglobalenv = true; | 127 if not (ranok or message or useglobalenv) and commands[line:lower()] then |
| 91 elseif data == "\004" then | 128 commands[line:lower()](session, line); |
| 92 commands["bye"](session, data); | 129 break; |
| 93 return; | 130 end |
| 94 else | 131 |
| 95 local command = data:lower(); | 132 if not ranok then |
| 96 command = data:match("^%w+") or data:match("%p"); | 133 session.print("Fatal error while running command, it did not complete"); |
| 97 if commands[command] then | 134 session.print("Error: "..taskok); |
| 98 commands[command](session, data); | 135 break; |
| 99 return; | 136 end |
| 100 end | 137 |
| 101 end | 138 if not message then |
| 102 | 139 session.print("Result: "..tostring(taskok)); |
| 103 session.env._ = data; | 140 break; |
| 141 elseif (not taskok) and message then | |
| 142 session.print("Command completed with a problem"); | |
| 143 session.print("Message: "..tostring(message)); | |
| 144 break; | |
| 145 end | |
| 146 | |
| 147 session.print("OK: "..tostring(message)); | |
| 148 until true | |
| 104 | 149 |
| 105 local chunkname = "=console"; | 150 session.send(string.char(0)); |
| 106 local env = (useglobalenv and redirect_output(_G, session)) or session.env or nil | 151 end |
| 107 local chunk, err = envload("return "..data, chunkname, env); | 152 session.partial_data = data:match("[^\n]+$"); |
| 108 if not chunk then | |
| 109 chunk, err = envload(data, chunkname, env); | |
| 110 if not chunk then | |
| 111 err = err:gsub("^%[string .-%]:%d+: ", ""); | |
| 112 err = err:gsub("^:%d+: ", ""); | |
| 113 err = err:gsub("'<eof>'", "the end of the line"); | |
| 114 session.print("Sorry, I couldn't understand that... "..err); | |
| 115 return; | |
| 116 end | |
| 117 end | |
| 118 | |
| 119 local ranok, taskok, message = pcall(chunk); | |
| 120 | |
| 121 if not (ranok or message or useglobalenv) and commands[data:lower()] then | |
| 122 commands[data:lower()](session, data); | |
| 123 return; | |
| 124 end | |
| 125 | |
| 126 if not ranok then | |
| 127 session.print("Fatal error while running command, it did not complete"); | |
| 128 session.print("Error: "..taskok); | |
| 129 return; | |
| 130 end | |
| 131 | |
| 132 if not message then | |
| 133 session.print("Result: "..tostring(taskok)); | |
| 134 return; | |
| 135 elseif (not taskok) and message then | |
| 136 session.print("Command completed with a problem"); | |
| 137 session.print("Message: "..tostring(message)); | |
| 138 return; | |
| 139 end | |
| 140 | |
| 141 session.print("OK: "..tostring(message)); | |
| 142 end)(session, data); | |
| 143 | |
| 144 session.send(string.char(0)); | |
| 145 end | 153 end |
| 146 | 154 |
| 147 function console_listener.ondisconnect(conn, err) | 155 function console_listener.ondisconnect(conn, err) |
| 148 local session = sessions[conn]; | 156 local session = sessions[conn]; |
| 149 if session then | 157 if session then |
| 189 print [[]] | 197 print [[]] |
| 190 print [[c2s - Commands to manage local client-to-server sessions]] | 198 print [[c2s - Commands to manage local client-to-server sessions]] |
| 191 print [[s2s - Commands to manage sessions between this server and others]] | 199 print [[s2s - Commands to manage sessions between this server and others]] |
| 192 print [[module - Commands to load/reload/unload modules/plugins]] | 200 print [[module - Commands to load/reload/unload modules/plugins]] |
| 193 print [[host - Commands to activate, deactivate and list virtual hosts]] | 201 print [[host - Commands to activate, deactivate and list virtual hosts]] |
| 202 print [[user - Commands to create and delete users, and change their passwords]] | |
| 194 print [[server - Uptime, version, shutting down, etc.]] | 203 print [[server - Uptime, version, shutting down, etc.]] |
| 195 print [[config - Reloading the configuration, etc.]] | 204 print [[config - Reloading the configuration, etc.]] |
| 196 print [[console - Help regarding the console itself]] | 205 print [[console - Help regarding the console itself]] |
| 197 elseif section == "c2s" then | 206 elseif section == "c2s" then |
| 198 print [[c2s:show(jid) - Show all client sessions with the specified JID (or all if no JID given)]] | 207 print [[c2s:show(jid) - Show all client sessions with the specified JID (or all if no JID given)]] |
| 200 print [[c2s:show_secure() - Show all encrypted client connections]] | 209 print [[c2s:show_secure() - Show all encrypted client connections]] |
| 201 print [[c2s:close(jid) - Close all sessions for the specified JID]] | 210 print [[c2s:close(jid) - Close all sessions for the specified JID]] |
| 202 elseif section == "s2s" then | 211 elseif section == "s2s" then |
| 203 print [[s2s:show(domain) - Show all s2s connections for the given domain (or all if no domain given)]] | 212 print [[s2s:show(domain) - Show all s2s connections for the given domain (or all if no domain given)]] |
| 204 print [[s2s:close(from, to) - Close a connection from one domain to another]] | 213 print [[s2s:close(from, to) - Close a connection from one domain to another]] |
| 214 print [[s2s:closeall(host) - Close all the incoming/outgoing s2s sessions to specified host]] | |
| 205 elseif section == "module" then | 215 elseif section == "module" then |
| 206 print [[module:load(module, host) - Load the specified module on the specified host (or all hosts if none given)]] | 216 print [[module:load(module, host) - Load the specified module on the specified host (or all hosts if none given)]] |
| 207 print [[module:reload(module, host) - The same, but unloads and loads the module (saving state if the module supports it)]] | 217 print [[module:reload(module, host) - The same, but unloads and loads the module (saving state if the module supports it)]] |
| 208 print [[module:unload(module, host) - The same, but just unloads the module from memory]] | 218 print [[module:unload(module, host) - The same, but just unloads the module from memory]] |
| 209 print [[module:list(host) - List the modules loaded on the specified host]] | 219 print [[module:list(host) - List the modules loaded on the specified host]] |
| 210 elseif section == "host" then | 220 elseif section == "host" then |
| 211 print [[host:activate(hostname) - Activates the specified host]] | 221 print [[host:activate(hostname) - Activates the specified host]] |
| 212 print [[host:deactivate(hostname) - Disconnects all clients on this host and deactivates]] | 222 print [[host:deactivate(hostname) - Disconnects all clients on this host and deactivates]] |
| 213 print [[host:list() - List the currently-activated hosts]] | 223 print [[host:list() - List the currently-activated hosts]] |
| 224 elseif section == "user" then | |
| 225 print [[user:create(jid, password) - Create the specified user account]] | |
| 226 print [[user:password(jid, password) - Set the password for the specified user account]] | |
| 227 print [[user:delete(jid, password) - Permanently remove the specified user account]] | |
| 214 elseif section == "server" then | 228 elseif section == "server" then |
| 215 print [[server:version() - Show the server's version number]] | 229 print [[server:version() - Show the server's version number]] |
| 216 print [[server:uptime() - Show how long the server has been running]] | 230 print [[server:uptime() - Show how long the server has been running]] |
| 217 print [[server:shutdown(reason) - Shut down the server, with an optional reason to be broadcast to all connections]] | 231 print [[server:shutdown(reason) - Shut down the server, with an optional reason to be broadcast to all connections]] |
| 218 elseif section == "config" then | 232 elseif section == "config" then |
| 677 end | 691 end |
| 678 end | 692 end |
| 679 end | 693 end |
| 680 local domain_certs = array.collect(values(cert_set)); | 694 local domain_certs = array.collect(values(cert_set)); |
| 681 -- Phew. We now have a array of unique certificates presented by domain. | 695 -- Phew. We now have a array of unique certificates presented by domain. |
| 682 local print = self.session.print; | |
| 683 local n_certs = #domain_certs; | 696 local n_certs = #domain_certs; |
| 684 | 697 |
| 685 if n_certs == 0 then | 698 if n_certs == 0 then |
| 686 return "No certificates found for "..domain; | 699 return "No certificates found for "..domain; |
| 687 end | 700 end |
| 769 else | 782 else |
| 770 return false, "Neither of the hostnames you specified are being used on this server"; | 783 return false, "Neither of the hostnames you specified are being used on this server"; |
| 771 end | 784 end |
| 772 | 785 |
| 773 return true, "Closed "..count.." s2s session"..((count == 1 and "") or "s"); | 786 return true, "Closed "..count.." s2s session"..((count == 1 and "") or "s"); |
| 787 end | |
| 788 | |
| 789 function def_env.s2s:closeall(host) | |
| 790 local count = 0; | |
| 791 | |
| 792 if not host or type(host) ~= "string" then return false, "wrong syntax: please use s2s:closeall('hostname.tld')"; end | |
| 793 if hosts[host] then | |
| 794 for session in pairs(incoming_s2s) do | |
| 795 if session.to_host == host then | |
| 796 (session.close or s2smanager.destroy_session)(session); | |
| 797 count = count + 1; | |
| 798 end | |
| 799 end | |
| 800 for _, session in pairs(hosts[host].s2sout) do | |
| 801 (session.close or s2smanager.destroy_session)(session); | |
| 802 count = count + 1; | |
| 803 end | |
| 804 else | |
| 805 for session in pairs(incoming_s2s) do | |
| 806 if session.from_host == host then | |
| 807 (session.close or s2smanager.destroy_session)(session); | |
| 808 count = count + 1; | |
| 809 end | |
| 810 end | |
| 811 for _, h in pairs(hosts) do | |
| 812 if h.s2sout[host] then | |
| 813 (h.s2sout[host].close or s2smanager.destroy_session)(h.s2sout[host]); | |
| 814 count = count + 1; | |
| 815 end | |
| 816 end | |
| 817 end | |
| 818 | |
| 819 if count == 0 then return false, "No sessions to close."; | |
| 820 else return true, "Closed "..count.." s2s session"..((count == 1 and "") or "s"); end | |
| 774 end | 821 end |
| 775 | 822 |
| 776 def_env.host = {}; def_env.hosts = def_env.host; | 823 def_env.host = {}; def_env.hosts = def_env.host; |
| 777 | 824 |
| 778 function def_env.host:activate(hostname, config) | 825 function def_env.host:activate(hostname, config) |
| 858 return nil, "No such room: "..room_jid; | 905 return nil, "No such room: "..room_jid; |
| 859 end | 906 end |
| 860 return setmetatable({ room = room_obj }, console_room_mt); | 907 return setmetatable({ room = room_obj }, console_room_mt); |
| 861 end | 908 end |
| 862 | 909 |
| 910 local um = require"core.usermanager"; | |
| 911 | |
| 912 def_env.user = {}; | |
| 913 function def_env.user:create(jid, password) | |
| 914 local username, host = jid_split(jid); | |
| 915 local ok, err = um.create_user(username, password, host); | |
| 916 if ok then | |
| 917 return true, "User created"; | |
| 918 else | |
| 919 return nil, "Could not create user: "..err; | |
| 920 end | |
| 921 end | |
| 922 | |
| 923 function def_env.user:delete(jid) | |
| 924 local username, host = jid_split(jid); | |
| 925 local ok, err = um.delete_user(username, host); | |
| 926 if ok then | |
| 927 return true, "User deleted"; | |
| 928 else | |
| 929 return nil, "Could not delete user: "..err; | |
| 930 end | |
| 931 end | |
| 932 | |
| 933 function def_env.user:passwd(jid, password) | |
| 934 local username, host = jid_split(jid); | |
| 935 local ok, err = um.set_password(username, password, host); | |
| 936 if ok then | |
| 937 return true, "User created"; | |
| 938 else | |
| 939 return nil, "Could not change password for user: "..err; | |
| 940 end | |
| 941 end | |
| 942 | |
| 943 def_env.xmpp = {}; | |
| 944 | |
| 945 local st = require "util.stanza"; | |
| 946 function def_env.xmpp:ping(localhost, remotehost) | |
| 947 if hosts[localhost] then | |
| 948 core_post_stanza(hosts[localhost], | |
| 949 st.iq{ from=localhost, to=remotehost, type="get", id="ping" } | |
| 950 :tag("ping", {xmlns="urn:xmpp:ping"})); | |
| 951 return true, "Sent ping"; | |
| 952 else | |
| 953 return nil, "No such host"; | |
| 954 end | |
| 955 end | |
| 956 | |
| 863 ------------- | 957 ------------- |
| 864 | 958 |
| 865 function printbanner(session) | 959 function printbanner(session) |
| 866 local option = config.get("*", "core", "console_banner"); | 960 local option = config.get("*", "core", "console_banner"); |
| 867 if option == nil or option == "full" or option == "graphic" then | 961 if option == nil or option == "full" or option == "graphic" then |