aboutsummaryrefslogtreecommitdiffstats
path: root/plugins/mod_admin_telnet.lua
diff options
context:
space:
mode:
authorMatthew Wild <mwild1@gmail.com>2014-04-02 17:41:38 +0100
committerMatthew Wild <mwild1@gmail.com>2014-04-02 17:41:38 +0100
commitda820882348572de470a13a1a50f529a51243aa5 (patch)
tree39ca42dddf3935546a0c3c37b2e2456a554899f1 /plugins/mod_admin_telnet.lua
parent618661cda2a68afbe445ce079c15af25bdaa177b (diff)
parentf7d4b04bf17c8b634eae00e814a995a88c5ba6cb (diff)
downloadprosody-da820882348572de470a13a1a50f529a51243aa5.tar.gz
prosody-da820882348572de470a13a1a50f529a51243aa5.zip
Merge 0.9->0.10
Diffstat (limited to 'plugins/mod_admin_telnet.lua')
-rw-r--r--plugins/mod_admin_telnet.lua296
1 files changed, 125 insertions, 171 deletions
diff --git a/plugins/mod_admin_telnet.lua b/plugins/mod_admin_telnet.lua
index 2572e982..2aa9bd9b 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" };
@@ -60,20 +59,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;
@@ -87,9 +86,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);
@@ -103,20 +102,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;
@@ -125,7 +124,7 @@ function console:process_line(session, line)
session.print("Message: "..tostring(message));
return;
end
-
+
session.print("OK: "..tostring(message));
end
@@ -344,9 +343,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
@@ -367,15 +366,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
@@ -433,7 +432,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)..":");
@@ -483,6 +482,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)
@@ -501,7 +519,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
@@ -518,15 +536,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
@@ -537,7 +550,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
@@ -548,7 +561,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
@@ -564,96 +577,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
@@ -685,14 +682,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;
@@ -731,18 +723,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];
@@ -783,76 +775,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
@@ -1076,12 +1030,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