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 |