plugins/mod_admin_telnet.lua
changeset 4684 dc70c4ffb66d
parent 4517 2e274e088ddc
parent 4674 f44726a910a0
child 4779 9f2639b3d9b1
equal deleted inserted replaced
4529:12621337471f 4684:dc70c4ffb66d
     4 -- 
     4 -- 
     5 -- This project is MIT/X11 licensed. Please see the
     5 -- This project is MIT/X11 licensed. Please see the
     6 -- COPYING file in the source package for more information.
     6 -- COPYING file in the source package for more information.
     7 --
     7 --
     8 
     8 
     9 module.host = "*";
     9 module:set_global();
    10 
    10 
    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 local connlisteners_register = require "net.connlisteners".register;
    15 
    16 
    16 local console_listener = { default_port = 5582; default_mode = "*l"; interface = "127.0.0.1" };
    17 local console_listener = { default_port = 5582; default_mode = "*l"; default_interface = "127.0.0.1" };
    17 
    18 
    18 local iterators = require "util.iterators";
    19 require "util.iterators";
    19 local keys, values = iterators.keys, iterators.values;
    20 local jid_bare = require "util.jid".bare;
    20 local jid_bare = require "util.jid".bare;
    21 local set, array = require "util.set", require "util.array";
    21 local set, array = require "util.set", require "util.array";
    22 local cert_verify_identity = require "util.x509".verify_identity;
    22 local cert_verify_identity = require "util.x509".verify_identity;
    23 
    23 
    24 local commands = {};
    24 local commands = module:shared("commands")
    25 local def_env = {};
    25 local def_env = module:shared("env");
    26 local default_env_mt = { __index = def_env };
    26 local default_env_mt = { __index = def_env };
    27 
       
    28 prosody.console = { commands = commands, env = def_env };
       
    29 
    27 
    30 local function redirect_output(_G, session)
    28 local function redirect_output(_G, session)
    31 	local env = setmetatable({ print = session.print }, { __index = function (t, k) return rawget(_G, k); end });
    29 	local env = setmetatable({ print = session.print }, { __index = function (t, k) return rawget(_G, k); end });
    32 	env.dofile = function(name)
    30 	env.dofile = function(name)
    33 		local f, err = loadfile(name);
    31 		local f, err = loadfile(name);
   146 	if session then
   144 	if session then
   147 		session.disconnect();
   145 		session.disconnect();
   148 		sessions[conn] = nil;
   146 		sessions[conn] = nil;
   149 	end
   147 	end
   150 end
   148 end
   151 
       
   152 connlisteners_register('console', console_listener);
       
   153 
   149 
   154 -- Console commands --
   150 -- Console commands --
   155 -- These are simple commands, not valid standalone in Lua
   151 -- These are simple commands, not valid standalone in Lua
   156 
   152 
   157 function commands.bye(session)
   153 function commands.bye(session)
   279 		end
   275 		end
   280 	elseif type(hosts) == "string" then
   276 	elseif type(hosts) == "string" then
   281 		return set.new { hosts };
   277 		return set.new { hosts };
   282 	elseif hosts == nil then
   278 	elseif hosts == nil then
   283 		local mm = require "modulemanager";
   279 		local mm = require "modulemanager";
   284 		return set.new(array.collect(keys(prosody.hosts)))
   280 		local hosts_set = set.new(array.collect(keys(prosody.hosts)))
   285 			/ function (host) return prosody.hosts[host].type == "local" or module and mm.is_loaded(host, module); end;
   281 			/ function (host) return prosody.hosts[host].type == "local" or module and mm.is_loaded(host, module); end;
       
   282 		if module and mm.get_module("*", module) then
       
   283 			hosts_set:add("*");
       
   284 		end
       
   285 		return hosts_set;
   286 	end
   286 	end
   287 end
   287 end
   288 
   288 
   289 function def_env.module:load(name, hosts, config)
   289 function def_env.module:load(name, hosts, config)
   290 	local mm = require "modulemanager";
   290 	local mm = require "modulemanager";
   291 	
   291 	
   292 	hosts = get_hosts_set(hosts);
   292 	hosts = get_hosts_set(hosts);
   293 	
   293 	
   294 	-- Load the module for each host
   294 	-- Load the module for each host
   295 	local ok, err, count = true, nil, 0;
   295 	local ok, err, count, mod = true, nil, 0, nil;
   296 	for host in hosts do
   296 	for host in hosts do
   297 		if (not mm.is_loaded(host, name)) then
   297 		if (not mm.is_loaded(host, name)) then
   298 			ok, err = mm.load(host, name, config);
   298 			mod, err = mm.load(host, name, config);
   299 			if not ok then
   299 			if not mod then
   300 				ok = false;
   300 				ok = false;
       
   301 				if err == "global-module-already-loaded" then
       
   302 					if count > 0 then
       
   303 						ok, err, count = true, nil, 1;
       
   304 					end
       
   305 					break;
       
   306 				end
   301 				self.session.print(err or "Unknown error loading module");
   307 				self.session.print(err or "Unknown error loading module");
   302 			else
   308 			else
   303 				count = count + 1;
   309 				count = count + 1;
   304 				self.session.print("Loaded for "..host);
   310 				self.session.print("Loaded for "..mod.module.host);
   305 			end
   311 			end
   306 		end
   312 		end
   307 	end
   313 	end
   308 	
   314 	
   309 	return ok, (ok and "Module loaded onto "..count.." host"..(count ~= 1 and "s" or "")) or ("Last error: "..tostring(err));	
   315 	return ok, (ok and "Module loaded onto "..count.." host"..(count ~= 1 and "s" or "")) or ("Last error: "..tostring(err));	
   332 end
   338 end
   333 
   339 
   334 function def_env.module:reload(name, hosts)
   340 function def_env.module:reload(name, hosts)
   335 	local mm = require "modulemanager";
   341 	local mm = require "modulemanager";
   336 
   342 
   337 	hosts = get_hosts_set(hosts, name);
   343 	hosts = array.collect(get_hosts_set(hosts, name)):sort(function (a, b)
   338 	
   344 		if a == "*" then return true
       
   345 		elseif b == "*" then return false
       
   346 		else return a < b; end
       
   347 	end);
       
   348 
   339 	-- Reload the module for each host
   349 	-- Reload the module for each host
   340 	local ok, err, count = true, nil, 0;
   350 	local ok, err, count = true, nil, 0;
   341 	for host in hosts do
   351 	for _, host in ipairs(hosts) do
   342 		if mm.is_loaded(host, name) then
   352 		if mm.is_loaded(host, name) then
   343 			ok, err = mm.reload(host, name);
   353 			ok, err = mm.reload(host, name);
   344 			if not ok then
   354 			if not ok then
   345 				ok = false;
   355 				ok = false;
   346 				self.session.print(err or "Unknown error reloading module");
   356 				self.session.print(err or "Unknown error reloading module");
   357 end
   367 end
   358 
   368 
   359 function def_env.module:list(hosts)
   369 function def_env.module:list(hosts)
   360 	if hosts == nil then
   370 	if hosts == nil then
   361 		hosts = array.collect(keys(prosody.hosts));
   371 		hosts = array.collect(keys(prosody.hosts));
       
   372 		table.insert(hosts, 1, "*");
   362 	end
   373 	end
   363 	if type(hosts) == "string" then
   374 	if type(hosts) == "string" then
   364 		hosts = { hosts };
   375 		hosts = { hosts };
   365 	end
   376 	end
   366 	if type(hosts) ~= "table" then
   377 	if type(hosts) ~= "table" then
   367 		return false, "Please supply a host or a list of hosts you would like to see";
   378 		return false, "Please supply a host or a list of hosts you would like to see";
   368 	end
   379 	end
   369 	
   380 	
   370 	local print = self.session.print;
   381 	local print = self.session.print;
   371 	for _, host in ipairs(hosts) do
   382 	for _, host in ipairs(hosts) do
   372 		print(host..":");
   383 		print((host == "*" and "Global" or host)..":");
   373 		local modules = array.collect(keys(prosody.hosts[host] and prosody.hosts[host].modules or {})):sort();
   384 		local modules = array.collect(keys(modulemanager.get_modules(host) or {})):sort();
   374 		if #modules == 0 then
   385 		if #modules == 0 then
   375 			if prosody.hosts[host] then
   386 			if prosody.hosts[host] then
   376 				print("    No modules loaded");
   387 				print("    No modules loaded");
   377 			else
   388 			else
   378 				print("    Host not found");
   389 				print("    Host not found");
   764 		print(host);
   775 		print(host);
   765 	end
   776 	end
   766 	return true, i.." hosts";
   777 	return true, i.." hosts";
   767 end
   778 end
   768 
   779 
       
   780 def_env.port = {};
       
   781 
       
   782 function def_env.port:list()
       
   783 	local print = self.session.print;
       
   784 	local services = portmanager.get_active_services().data;
       
   785 	local ordered_services, n_ports = {}, 0;
       
   786 	for service, interfaces in pairs(services) do
       
   787 		table.insert(ordered_services, service);
       
   788 	end
       
   789 	table.sort(ordered_services);
       
   790 	for _, service in ipairs(ordered_services) do
       
   791 		local ports_list = {};
       
   792 		for interface, ports in pairs(services[service]) do
       
   793 			for port in pairs(ports) do
       
   794 				table.insert(ports_list, "["..interface.."]:"..port);
       
   795 			end
       
   796 		end
       
   797 		n_ports = n_ports + #ports_list;
       
   798 		print(service..": "..table.concat(ports_list, ", "));
       
   799 	end
       
   800 	return true, #ordered_services.." services listening on "..n_ports.." ports";
       
   801 end
       
   802 
       
   803 function def_env.port:close(close_port, close_interface)
       
   804 	close_port = assert(tonumber(close_port), "Invalid port number");
       
   805 	local n_closed = 0;
       
   806 	local services = portmanager.get_active_services().data;
       
   807 	for service, interfaces in pairs(services) do
       
   808 		for interface, ports in pairs(interfaces) do
       
   809 			if not close_interface or close_interface == interface then
       
   810 				if ports[close_port] then
       
   811 					self.session.print("Closing ["..interface.."]:"..close_port.."...");
       
   812 					local ok, err = portmanager.close(interface, close_port)
       
   813 					if not ok then
       
   814 						self.session.print("Failed to close "..interface.." "..port..": "..err);
       
   815 					else
       
   816 						n_closed = n_closed + 1;
       
   817 					end
       
   818 				end
       
   819 			end
       
   820 		end
       
   821 	end
       
   822 	return true, "Closed "..n_closed.." ports";
       
   823 end
       
   824 
   769 -------------
   825 -------------
   770 
   826 
   771 function printbanner(session)
   827 function printbanner(session)
   772 	local option = config.get("*", "core", "console_banner");
   828 	local option = config.get("*", "core", "console_banner");
   773 if option == nil or option == "full" or option == "graphic" then
   829 if option == nil or option == "full" or option == "graphic" then
   794 		pcall(option, session);
   850 		pcall(option, session);
   795 	end
   851 	end
   796 end
   852 end
   797 end
   853 end
   798 
   854 
   799 prosody.net_activate_ports("console", "console", {5582}, "tcp");
   855 module:add_item("net-provider", {
       
   856 	name = "console";
       
   857 	listener = console_listener;
       
   858 	default_port = 5582;
       
   859 	private = true;
       
   860 });