diff options
Diffstat (limited to 'plugins/mod_admin_telnet.lua')
-rw-r--r-- | plugins/mod_admin_telnet.lua | 296 |
1 files changed, 125 insertions, 171 deletions
diff --git a/plugins/mod_admin_telnet.lua b/plugins/mod_admin_telnet.lua index 131689c5..e13d27c2 100644 --- a/plugins/mod_admin_telnet.lua +++ b/plugins/mod_admin_telnet.lua @@ -1,7 +1,7 @@ -- Prosody IM -- Copyright (C) 2008-2010 Matthew Wild -- Copyright (C) 2008-2010 Waqas Hussain --- +-- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. -- @@ -17,7 +17,6 @@ local _G = _G; local prosody = _G.prosody; local hosts = prosody.hosts; -local incoming_s2s = prosody.incoming_s2s; local console_listener = { default_port = 5582; default_mode = "*a"; interface = "127.0.0.1" }; @@ -61,20 +60,20 @@ function console:new_session(conn) disconnect = function () conn:close(); end; }; session.env = setmetatable({}, default_env_mt); - + -- Load up environment with helper objects for name, t in pairs(def_env) do if type(t) == "table" then session.env[name] = setmetatable({ session = session }, { __index = t }); end end - + return session; end function console:process_line(session, line) local useglobalenv; - + if line:match("^>") then line = line:gsub("^>", ""); useglobalenv = true; @@ -88,9 +87,9 @@ function console:process_line(session, line) return; end end - + session.env._ = line; - + local chunkname = "=console"; local env = (useglobalenv and redirect_output(_G, session)) or session.env or nil local chunk, err = envload("return "..line, chunkname, env); @@ -104,20 +103,20 @@ function console:process_line(session, line) return; end end - + local ranok, taskok, message = pcall(chunk); - + if not (ranok or message or useglobalenv) and commands[line:lower()] then commands[line:lower()](session, line); return; end - + if not ranok then session.print("Fatal error while running command, it did not complete"); session.print("Error: "..taskok); return; end - + if not message then session.print("Result: "..tostring(taskok)); return; @@ -126,7 +125,7 @@ function console:process_line(session, line) session.print("Message: "..tostring(message)); return; end - + session.print("OK: "..tostring(message)); end @@ -345,9 +344,9 @@ end function def_env.module:load(name, hosts, config) local mm = require "modulemanager"; - + hosts = get_hosts_set(hosts); - + -- Load the module for each host local ok, err, count, mod = true, nil, 0, nil; for host in hosts do @@ -368,15 +367,15 @@ function def_env.module:load(name, hosts, config) end end end - - return ok, (ok and "Module loaded onto "..count.." host"..(count ~= 1 and "s" or "")) or ("Last error: "..tostring(err)); + + return ok, (ok and "Module loaded onto "..count.." host"..(count ~= 1 and "s" or "")) or ("Last error: "..tostring(err)); end function def_env.module:unload(name, hosts) local mm = require "modulemanager"; hosts = get_hosts_set(hosts, name); - + -- Unload the module for each host local ok, err, count = true, nil, 0; for host in hosts do @@ -434,7 +433,7 @@ function def_env.module:list(hosts) if type(hosts) ~= "table" then return false, "Please supply a host or a list of hosts you would like to see"; end - + local print = self.session.print; for _, host in ipairs(hosts) do print((host == "*" and "Global" or host)..":"); @@ -484,6 +483,25 @@ end function def_env.hosts:add(name) end +local function session_flags(session, line) + line = line or {}; + if session.cert_identity_status == "valid" then + line[#line+1] = "(secure)"; + elseif session.secure then + line[#line+1] = "(encrypted)"; + end + if session.compressed then + line[#line+1] = "(compressed)"; + end + if session.smacks then + line[#line+1] = "(sm)"; + end + if session.ip and session.ip:match(":") then + line[#line+1] = "(IPv6)"; + end + return table.concat(line, " "); +end + def_env.c2s = {}; local function show_c2s(callback) @@ -502,7 +520,7 @@ function def_env.c2s:count(match_jid) show_c2s(function (jid, session) if (not match_jid) or jid:match(match_jid) then count = count + 1; - end + end end); return true, "Total: "..count.." clients"; end @@ -519,15 +537,10 @@ function def_env.c2s:show(match_jid) count = count + 1; local status, priority = "unavailable", tostring(session.priority or "-"); if session.presence then - status = session.presence:child_with_name("show"); - if status then - status = status:get_text() or "[invalid!]"; - else - status = "available"; - end + status = session.presence:get_child_text("show") or "available"; end - print(" "..jid.." - "..status.."("..priority..")"); - end + print(session_flags(session, { " "..jid.." - "..status.."("..priority..")" })); + end end); return true, "Total: "..count.." clients"; end @@ -538,7 +551,7 @@ function def_env.c2s:show_insecure(match_jid) if ((not match_jid) or jid:match(match_jid)) and not session.secure then count = count + 1; print(jid); - end + end end); return true, "Total: "..count.." insecure client connections"; end @@ -549,7 +562,7 @@ function def_env.c2s:show_secure(match_jid) if ((not match_jid) or jid:match(match_jid)) and session.secure then count = count + 1; print(jid); - end + end end); return true, "Total: "..count.." secure client connections"; end @@ -565,96 +578,80 @@ function def_env.c2s:close(match_jid) return true, "Total: "..count.." sessions closed"; end -local function session_flags(session, line) - if session.cert_identity_status == "valid" then - line[#line+1] = "(secure)"; - elseif session.secure then - line[#line+1] = "(encrypted)"; - end - if session.compressed then - line[#line+1] = "(compressed)"; - end - if session.smacks then - line[#line+1] = "(sm)"; - end - if session.conn and session.conn:ip():match(":") then - line[#line+1] = "(IPv6)"; - end - return table.concat(line, " "); -end def_env.s2s = {}; function def_env.s2s:show(match_jid) - local _print = self.session.print; local print = self.session.print; - + local count_in, count_out = 0,0; - - for host, host_session in pairs(hosts) do - print = function (...) _print(host); _print(...); print = _print; end - for remotehost, session in pairs(host_session.s2sout) do - if (not match_jid) or remotehost:match(match_jid) or host:match(match_jid) then - count_out = count_out + 1; - print(session_flags(session, {" ", host, "->", remotehost})); - if session.sendq then - print(" There are "..#session.sendq.." queued outgoing stanzas for this connection"); - end - if session.type == "s2sout_unauthed" then - if session.connecting then - print(" Connection not yet established"); - if not session.srv_hosts then - if not session.conn then - print(" We do not yet have a DNS answer for this host's SRV records"); - else - print(" This host has no SRV records, using A record instead"); - end - elseif session.srv_choice then - print(" We are on SRV record "..session.srv_choice.." of "..#session.srv_hosts); - local srv_choice = session.srv_hosts[session.srv_choice]; - print(" Using "..(srv_choice.target or ".")..":"..(srv_choice.port or 5269)); + local s2s_list = { }; + + local s2s_sessions = module:shared"/*/s2s/sessions"; + for _, session in pairs(s2s_sessions) do + local remotehost, localhost, direction; + if session.direction == "outgoing" then + direction = "->"; + count_out = count_out + 1; + remotehost, localhost = session.to_host or "?", session.from_host or "?"; + else + direction = "<-"; + count_in = count_in + 1; + remotehost, localhost = session.from_host or "?", session.to_host or "?"; + end + local sess_lines = { l = localhost, r = remotehost, + session_flags(session, { "", direction, remotehost or "?", + "["..session.type..tostring(session):match("[a-f0-9]*$").."]" })}; + + if (not match_jid) or remotehost:match(match_jid) or localhost:match(match_jid) then + table.insert(s2s_list, sess_lines); + local print = function (s) table.insert(sess_lines, " "..s); end + if session.sendq then + print("There are "..#session.sendq.." queued outgoing stanzas for this connection"); + end + if session.type == "s2sout_unauthed" then + if session.connecting then + print("Connection not yet established"); + if not session.srv_hosts then + if not session.conn then + print("We do not yet have a DNS answer for this host's SRV records"); + else + print("This host has no SRV records, using A record instead"); end - elseif session.notopen then - print(" The <stream> has not yet been opened"); - elseif not session.dialback_key then - print(" Dialback has not been initiated yet"); - elseif session.dialback_key then - print(" Dialback has been requested, but no result received"); + elseif session.srv_choice then + print("We are on SRV record "..session.srv_choice.." of "..#session.srv_hosts); + local srv_choice = session.srv_hosts[session.srv_choice]; + print("Using "..(srv_choice.target or ".")..":"..(srv_choice.port or 5269)); end + elseif session.notopen then + print("The <stream> has not yet been opened"); + elseif not session.dialback_key then + print("Dialback has not been initiated yet"); + elseif session.dialback_key then + print("Dialback has been requested, but no result received"); end end - end - local subhost_filter = function (h) - return (match_jid and h:match(match_jid)); - end - for session in pairs(incoming_s2s) do - if session.to_host == host and ((not match_jid) or host:match(match_jid) - or (session.from_host and session.from_host:match(match_jid)) - -- Pft! is what I say to list comprehensions - or (session.hosts and #array.collect(keys(session.hosts)):filter(subhost_filter)>0)) then - count_in = count_in + 1; - print(session_flags(session, {" ", host, "<-", session.from_host or "(unknown)"})); - if session.type == "s2sin_unauthed" then - print(" Connection not yet authenticated"); - end + if session.type == "s2sin_unauthed" then + print("Connection not yet authenticated"); + elseif session.type == "s2sin" then for name in pairs(session.hosts) do if name ~= session.from_host then - print(" also hosts "..tostring(name)); + print("also hosts "..tostring(name)); end end end end - - print = _print; end - - for session in pairs(incoming_s2s) do - if not session.to_host and ((not match_jid) or session.from_host and session.from_host:match(match_jid)) then - count_in = count_in + 1; - print("Other incoming s2s connections"); - print(" (unknown) <- "..(session.from_host or "(unknown)")); - end + + -- Sort by local host, then remote host + table.sort(s2s_list, function(a,b) + if a.l == b.l then return a.r < b.r; end + return a.l < b.l; + end); + local lasthost; + for _, sess_lines in ipairs(s2s_list) do + if sess_lines.l ~= lasthost then print(sess_lines.l); lasthost=sess_lines.l end + for _, line in ipairs(sess_lines) do print(line); end end - return true, "Total: "..count_out.." outgoing, "..count_in.." incoming connections"; end @@ -686,14 +683,9 @@ end function def_env.s2s:showcert(domain) local ser = require "util.serialization".serialize; local print = self.session.print; - local domain_sessions = set.new(array.collect(keys(incoming_s2s))) - /function(session) return session.from_host == domain and session or nil; end; - for local_host in values(prosody.hosts) do - local s2sout = local_host.s2sout; - if s2sout and s2sout[domain] then - domain_sessions:add(s2sout[domain]); - end - end + local s2s_sessions = module:shared"/*/s2s/sessions"; + local domain_sessions = set.new(array.collect(values(s2s_sessions))) + /function(session) return (session.to_host == domain or session.from_host == domain) and session or nil; end; local cert_set = {}; for session in domain_sessions do local conn = session.conn; @@ -732,18 +724,18 @@ function def_env.s2s:showcert(domain) local domain_certs = array.collect(values(cert_set)); -- Phew. We now have a array of unique certificates presented by domain. local n_certs = #domain_certs; - + if n_certs == 0 then return "No certificates found for "..domain; end - + local function _capitalize_and_colon(byte) return string.upper(byte)..":"; end local function pretty_fingerprint(hash) return hash:gsub("..", _capitalize_and_colon):sub(1, -2); end - + for cert_info in values(domain_certs) do local certs = cert_info.certs; local cert = certs[1]; @@ -784,76 +776,38 @@ end function def_env.s2s:close(from, to) local print, count = self.session.print, 0; - - if not (from and to) then + local s2s_sessions = module:shared"/*/s2s/sessions"; + + local match_id; + if from and not to then + match_id, from = from; + elseif not to then return false, "Syntax: s2s:close('from', 'to') - Closes all s2s sessions from 'from' to 'to'"; elseif from == to then return false, "Both from and to are the same... you can't do that :)"; end - - if hosts[from] and not hosts[to] then - -- Is an outgoing connection - local session = hosts[from].s2sout[to]; - if not session then - print("No outgoing connection from "..from.." to "..to) - else + + for _, session in pairs(s2s_sessions) do + local id = session.type..tostring(session):match("[a-f0-9]+$"); + if (match_id and match_id == id) + or (session.from_host == from and session.to_host == to) then + print(("Closing connection from %s to %s [%s]"):format(session.from_host, session.to_host, id)); (session.close or s2smanager.destroy_session)(session); - count = count + 1; - print("Closed outgoing session from "..from.." to "..to); + count = count + 1 ; end - elseif hosts[to] and not hosts[from] then - -- Is an incoming connection - for session in pairs(incoming_s2s) do - if session.to_host == to and session.from_host == from then - (session.close or s2smanager.destroy_session)(session); - count = count + 1; end - end - - if count == 0 then - print("No incoming connections from "..from.." to "..to); - else - print("Closed "..count.." incoming session"..((count == 1 and "") or "s").." from "..from.." to "..to); - end - elseif hosts[to] and hosts[from] then - return false, "Both of the hostnames you specified are local, there are no s2s sessions to close"; - else - return false, "Neither of the hostnames you specified are being used on this server"; - end - return true, "Closed "..count.." s2s session"..((count == 1 and "") or "s"); end function def_env.s2s:closeall(host) local count = 0; - - if not host or type(host) ~= "string" then return false, "wrong syntax: please use s2s:closeall('hostname.tld')"; end - if hosts[host] then - for session in pairs(incoming_s2s) do - if session.to_host == host then - (session.close or s2smanager.destroy_session)(session); + local s2s_sessions = module:shared"/*/s2s/sessions"; + for _,session in pairs(s2s_sessions) do + if not host or session.from_host == host or session.to_host == host then + session:close(); count = count + 1; end end - for _, session in pairs(hosts[host].s2sout) do - (session.close or s2smanager.destroy_session)(session); - count = count + 1; - end - else - for session in pairs(incoming_s2s) do - if session.from_host == host then - (session.close or s2smanager.destroy_session)(session); - count = count + 1; - end - end - for _, h in pairs(hosts) do - if h.s2sout[host] then - (h.s2sout[host].close or s2smanager.destroy_session)(h.s2sout[host]); - count = count + 1; - end - end - end - if count == 0 then return false, "No sessions to close."; else return true, "Closed "..count.." s2s session"..((count == 1 and "") or "s"); end end @@ -1077,12 +1031,12 @@ function printbanner(session) local option = module:get_option("console_banner"); if option == nil or option == "full" or option == "graphic" then session.print [[ - ____ \ / _ - | _ \ _ __ ___ ___ _-_ __| |_ _ + ____ \ / _ + | _ \ _ __ ___ ___ _-_ __| |_ _ | |_) | '__/ _ \/ __|/ _ \ / _` | | | | | __/| | | (_) \__ \ |_| | (_| | |_| | |_| |_| \___/|___/\___/ \__,_|\__, | - A study in simplicity |___/ + A study in simplicity |___/ ]] end |