Commit 9f94a17e authored by Michael Fürmann's avatar Michael Fürmann

Server initialization and domain management (without ssl for now)

parent cdb2c68b
#! /bin/sh
#
# metronome Start/stop metronome server
#
### BEGIN INIT INFO
# Provides: metronome
# Required-Start: $remote_fs $network $named $time
# Required-Stop: $remote_fs $network $named $time
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Starts metronome server
# Description: Starts metronome server, an XMPP server written in Lua.
### END INIT INFO
METRONOME=/usr/bin/metronomectl
PIDDIR=/var/run/metronome
NAME=metronome
test -e $METRONOME || exit 0
start()
{
mkdir $PIDDIR -p
chown metronome:metronome $PIDDIR
chmod 750 $PIDDIR
$METRONOME start >> /dev/null
}
stop()
{
$METRONOME stop >> /dev/null
}
case "$1" in
start)
echo -n "Starting Metronome..."
start &
;;
stop)
echo -n "Stopping Metronome..."
stop &
;;
restart)
echo -n "Restarting Metronome..."
stop &
start &
;;
*)
echo "Usage: $0 {start|stop|restart}" >&2
exit 1
;;
esac
if [ $? -eq 0 ]; then
echo .
else
echo " failed!"
fi
exit 0
<?php
ini_set('display_errors', false);
$username = 'prosody';
$password = '23fm%4ks0';
/*
$soap_location = 'http://localhost:8080/ispconfig3/interface/web/remote/index.php';
$soap_uri = 'http://localhost:8080/ispconfig3/interface/web/remote/';
*/
$soap_location = 'https://tepin.spicyweb.de:8080/remote/index.php';
$soap_uri = 'https://tepin.spicyweb.de:8080/remote/';
$auth_keys = array(
'iplay-esports.de' => 'f47kmm5Yh5hJzSws2KTS',
'weirdempire.de' => 'scNDcU37gQ7MCMeBgaJX'
);
$arg_email = '';
$arg_password = '';
if(count($argv) == 4){
$arg_email = $argv[1].'@'.$argv[2];
$arg_password = $argv[3];
}
$client = new SoapClient(null, array('location' => $soap_location, 'uri' => $soap_uri));
try {
//* Login to the remote server
if($session_id = $client->login($username,$password)) {
//var_dump($client->mail_alias_get($session_id, array('source' => 'blablubb@divepage.net', 'type' => 'alias', 'active' => 'y')));
// Is Mail Alias?
$alias = $client->mail_alias_get($session_id, array('source' => $arg_email, 'type' => 'alias', 'active' => 'y'));
if(count($alias))
$arg_email = $alias[0]['destination'];
$mailbox = $client->mail_user_get($session_id, array('email' => $arg_email));
if(count($mailbox)){
$password = $mailbox[0]['password'];
echo checkAuth($argv[1], $argv[2], $arg_password, $password);//intval(crypt($arg_password, $password) == $password);
}
else
echo 0;
//* Logout
$client->logout($session_id);
}
else
echo 0;
} catch (SoapFault $e) {
echo 0;
}
function checkAuth($user, $domain, $pw, $pw_mailbox){
global $auth_keys;
if(crypt($pw, $pw_mailbox) == $pw_mailbox)
return intval(1);
if(array_key_exists($domain, $auth_keys)){
$datetime = new DateTime();
$datetime->setTimezone(new DateTimeZone("UTC"));
for($t = $datetime->getTimestamp(); $t >= $datetime->getTimestamp()-30; $t--){
$pw_api = md5($domain.'@'.$auth_keys[$domain].'@'.$user.'@'.$t);
if($pw_api == $pw)
return intval(1);
}
}
return intval(0);
}
?>
\ No newline at end of file
#!/bin/bash
IFS=":"
AUTH_OK=1
AUTH_FAILED=0
LOGFILE="/var/log/metronome/auth.log"
USELOG=true
while read ACTION USER HOST PASS ; do
[ $USELOG == true ] && { echo "Date: $(date) Action: $ACTION User: $USER Host: $HOST" >> $LOGFILE; }
case $ACTION in
"auth")
if [ `/usr/bin/php /usr/lib/metronome/spicy-modules/mod_auth_external/authenticate_isp.php $USER $HOST $PASS` == 1 ] ; then
echo $AUTH_OK
[ $USELOG == true ] && { echo "AUTH OK" >> $LOGFILE; }
else
echo $AUTH_FAILED
[ $USELOG == true ] && { echo "AUTH FAILED" >> $LOGFILE; }
fi
;;
"isuser")
if [ `/usr/bin/php /usr/lib/metronome/spicy-modules/mod_auth_external/isuser_isp.php $USER $HOST` == 1 ] ; then
echo $AUTH_OK
[ $USELOG == true ] && { echo "AUTH OK" >> $LOGFILE; }
else
echo $AUTH_FAILED
[ $USELOG == true ] && { echo "AUTH FAILED" >> $LOGFILE; }
fi
;;
*)
echo $AUTH_FAILED
[ $USELOG == true ] && { echo "NO ACTION GIVEN" >> $LOGFILE; }
;;
esac
done
<?php
ini_set('display_errors', false);
$username = 'prosody';
$password = '23fm%4ks0';
/*
$soap_location = 'http://localhost:8080/ispconfig3/interface/web/remote/index.php';
$soap_uri = 'http://localhost:8080/ispconfig3/interface/web/remote/';
*/
$soap_location = 'https://tepin.spicyweb.de:8080/remote/index.php';
$soap_uri = 'https://tepin.spicyweb.de:8080/remote/';
$arg_email = '';
if(count($argv) == 3){
$arg_email = $argv[1].'@'.$argv[2];
}
$client = new SoapClient(null, array('location' => $soap_location, 'uri' => $soap_uri));
try {
//* Login to the remote server
if($session_id = $client->login($username,$password)) {
//var_dump($client->mail_alias_get($session_id, array('source' => 'blablubb@divepage.net', 'type' => 'alias', 'active' => 'y')));
// Is Mail Alias?
$alias = $client->mail_alias_get($session_id, array('source' => $arg_email, 'type' => 'alias', 'active' => 'y'));
if(count($alias))
$arg_email = $alias[0]['destination'];
$mailbox = $client->mail_user_get($session_id, array('email' => $arg_email));
if(count($mailbox)){
echo 1;
//$password = $mailbox[0]['password'];
//echo intval(crypt($arg_password, $password) == $password);
}
else
echo 0;
//* Logout
$client->logout($session_id);
}
else
echo 0;
} catch (SoapFault $e) {
echo 0;
}
?>
\ No newline at end of file
local nodeprep = require "util.encodings".stringprep.nodeprep;
local lpc = require "lpc";
local config = require "core.configmanager";
local log = module._log;
local host = module.host;
local script_type = config.get(host, "external_auth_protocol") or "generic";
assert(script_type == "ejabberd" or script_type == "generic");
local command = config.get(host, "external_auth_command") or "";
assert(type(command) == "string");
assert(not host:find(":"));
local usermanager = require "core.usermanager";
local jid_bare = require "util.jid".bare;
local new_sasl = require "util.sasl".new;
local pid;
local readfile;
local writefile;
local function send_query(text)
if pid and lpc.wait(pid,1) ~= nil then
log("debug","error, process died, force reopen");
pid=nil;
end
if not pid then
log("debug", "Opening process " .. command);
pid, writefile, readfile = lpc.run(command);
end
if not pid then
log("debug", "Process failed to open");
return nil;
end
writefile:write(text);
writefile:flush();
if script_type == "ejabberd" then
return readfile:read(4);
elseif script_type == "generic" then
return readfile:read();
end
end
function do_query(kind, username, password)
if not username then return nil, "not-acceptable"; end
username = nodeprep(username);
if not username then return nil, "jid-malformed"; end
local query = (password and "%s:%s:%s:%s" or "%s:%s:%s"):format(kind, username, host, password);
local len = #query
if len > 1000 then return nil, "policy-violation"; end
if script_type == "ejabberd" then
local lo = len % 256;
local hi = (len - lo) / 256;
query = string.char(hi, lo)..query;
end
if script_type == "generic" then
query = query..'\n';
end
local response = send_query(query);
if (script_type == "ejabberd" and response == "\0\2\0\0") or
(script_type == "generic" and response == "0") then
return nil, "not-authorized";
elseif (script_type == "ejabberd" and response == "\0\2\0\1") or
(script_type == "generic" and response == "1") then
return true;
else
log("debug", "Nonsense back");
return nil, "internal-server-error";
end
end
function new_external_provider(host)
local provider = { name = "external" };
function provider.test_password(username, password)
return do_query("auth", username, password);
end
function provider.set_password(username, password)
return do_query("setpass", username, password);
end
function provider.user_exists(username)
return do_query("isuser", username);
end
function provider.create_user(username, password) return nil, "Account creation/modification not available."; end
function provider.get_sasl_handler()
local testpass_authentication_profile = {
plain_test = function(sasl, username, password, realm)
return usermanager.test_password(username, realm, password), true;
end,
};
return new_sasl(module.host, testpass_authentication_profile);
end
function provider.is_admin(jid)
local admins = config.get(host, "admins");
if admins ~= config.get("*", "admins") then
if type(admins) == "table" then
jid = jid_bare(jid);
for _,admin in ipairs(admins) do
if admin == jid then return true; end
end
elseif admins then
log("error", "Option 'admins' for host '%s' is not a table", host);
end
end
return usermanager.is_admin(jid);
end
return provider;
end
module:add_item("auth-provider", new_external_provider(host));
\ No newline at end of file
-- * Metronome IM *
--
-- This file is part of the Metronome XMPP server and is released under the
-- ISC License, please see the LICENSE file in this source package for more
-- information about copyright and licensing.
--
-- As per the sublicensing clause, this file is also MIT/X11 Licensed.
-- ** Copyright (c) 2009, Waqas Hussain
local st = require "util.stanza";
local result_query = st.stanza("query", {xmlns = "http://jabber.org/protocol/disco#items"});
for _, item in ipairs(module:get_option("disco_items") or {}) do
result_query:tag("item", {jid = item[1], name = item[2]}):up();
end
module:hook("iq/host/http://jabber.org/protocol/disco#items:query", function(event)
local stanza = event.stanza;
local query = stanza.tags[1];
if stanza.attr.type == "get" and not query.attr.node then
event.origin.send(st.reply(stanza):add_child(result_query));
return true;
end
end, 100);
module:depends("http");
local jid_split = require "util.jid".prepped_split;
local b64 = require "util.encodings".base64.encode;
local sha1 = require "util.hashes".sha1;
local stanza = require "util.stanza".stanza;
local json = require "util.json".encode_ordered;
local function require_resource(name)
local icon_path = module:get_option_string("presence_icons", "icons");
local f, err = module:load_resource(icon_path.."/"..name);
if f then
return f:read("*a");
end
module:log("warn", "Failed to open image file %s", icon_path..name);
return "";
end
local statuses = { online = {}, away = {}, xa = {}, dnd = {}, chat = {}, offline = {} };
local function handle_request(event, path)
local status, message;
local jid, type = path:match("([^/]+)/?(.*)$");
if jid then
local user, host = jid_split(jid);
if host and not user then
user, host = host, event.request.headers.host;
if host then host = host:gsub(":%d+$", ""); end
end
if user and host then
local user_sessions = hosts[host] and hosts[host].sessions[user];
if user_sessions then
status = user_sessions.top_resources[1];
if status and status.presence then
message = status.presence:child_with_name("status");
status = status.presence:child_with_name("show");
if not status then
status = "online";
else
status = status:get_text();
end
if message then
message = message:get_text();
end
end
end
end
end
status = status or "offline";
statuses[status].image = function()
return { status_code = 200, headers = { content_type = "image/png" },
body = require_resource("status_"..status..".png")
};
end;
statuses[status].html = function()
local jid_hash = sha1(jid, true);
return { status_code = 200, headers = { content_type = "text/html" },
body = [[<!DOCTYPE html>]]..
tostring(
stanza("html")
:tag("head")
:tag("title"):text("XMPP Status Page for "..jid):up():up()
:tag("body")
:tag("div", { id = jid_hash.."_status", class = "xmpp_status" })
:tag("img", { id = jid_hash.."_img", class = "xmpp_status_image xmpp_status_"..status,
src = "data:image/png;base64,"..b64(require_resource("status_"..status..".png")) }):up()
:tag("span", { id = jid_hash.."_status_name", class = "xmpp_status_name" })
:text("\194\160"..status):up()
:tag("span", { id = jid_hash.."_status_message", class = "xmpp_status_message" })
:text(message and "\194\160"..message.."" or "")
)
};
end;
statuses[status].text = function()
return { status_code = 200, headers = { content_type = "text/plain" },
body = status
};
end;
statuses[status].message = function()
return { status_code = 200, headers = { content_type = "text/plain" },
body = (message and message or "")
};
end;
statuses[status].json = function()
return { status_code = 200, headers = { content_type = "application/json" },
body = json({
jid = jid,
show = status,
status = (message and message or "null")
})
};
end;
statuses[status].xml = function()
return { status_code = 200, headers = { content_type = "application/xml" },
body = [[<?xml version="1.0" encoding="utf-8"?>]]..
tostring(
stanza("result")
:tag("jid"):text(jid):up()
:tag("show"):text(status):up()
:tag("status"):text(message)
)
};
end
if ((type == "") or (not statuses[status][type])) then
type = "image"
end;
return statuses[status][type]();
end
module:provides("http", {
default_path = "/status";
route = {
["GET /*"] = handle_request;
};
});
......@@ -222,5 +222,9 @@ $conf['cron']['init_script'] = 'cron';
$conf['cron']['crontab_dir'] = '/etc/cron.d';
$conf['cron']['wget'] = '/usr/bin/wget';
//* Metronome XMPP
$conf['xmpp']['installed'] = false;
$conf['xmpp']['init_script'] = 'metronome';
?>
......@@ -154,6 +154,10 @@ class installer extends installer_base {
*/
}
public function configure_xmpp() {
parent::configure_xmpp();
}
}
?>
......@@ -347,6 +347,13 @@ if($install_mode == 'standard') {
}
*/
//* Configure XMPP
if($conf['xmpp']['installed'] == true){
$conf['services']['xmpp'] = true;
swriteln('Configuring Metronome XMPP Server');
$inst->configure_xmpp();
}
//* Configure ISPConfig
swriteln('Installing ISPConfig');
......@@ -398,6 +405,7 @@ if($install_mode == 'standard') {
//if($conf['squid']['installed'] == true && $conf['squid']['init_script'] != '' && is_file($conf['init_scripts'].'/'.$conf['squid']['init_script'])) system($conf['init_scripts'].'/'.$conf['squid']['init_script'].' restart &> /dev/null');
if($conf['nginx']['installed'] == true && $conf['nginx']['init_script'] != '') system($inst->getinitcommand($conf['nginx']['init_script'], 'restart').' &> /dev/null');
if($conf['ufw']['installed'] == true && $conf['ufw']['init_script'] != '') system($inst->getinitcommand($conf['ufw']['init_script'], 'restart').' &> /dev/null');
if($conf['xmpp']['installed'] == true && $conf['xmpp']['init_script'] != '') system($inst->getinitcommand($conf['xmpp']['init_script'], 'restart').' &> /dev/null');
} else {
......@@ -408,6 +416,7 @@ if($install_mode == 'standard') {
$conf['services']['db'] = true;
$conf['services']['firewall'] = false;
$conf['services']['proxy'] = false;
$conf['services']['xmpp'] = false;
//** Get Server ID
......@@ -639,6 +648,16 @@ if($install_mode == 'standard') {
$inst->configure_firewall();
}*/
//** Configure XMPP
if($conf['xmpp']['installed'] == true){
if(strtolower($inst->simple_query('Configure Metronome XMPP Server', array('y', 'n'), 'y', 'configure_xmpp')) == 'y'){
$conf['services']['xmpp'] = true;
swriteln('Configuring Metronome XMPP Server');
$inst->configure_xmpp();
if($conf['xmpp']['installed'] == true && $conf['xmpp']['init_script'] != '') system($inst->getinitcommand($conf['xmpp']['init_script'], 'restart').' &> /dev/null');
}
}
//** Configure ISPConfig :-)
$install_ispconfig_interface_default = ($conf['mysql']['master_slave_setup'] == 'y')?'n':'y';
if(strtolower($inst->simple_query('Install ISPConfig Web Interface', array('y', 'n'), $install_ispconfig_interface_default,'install_ispconfig_web_interface')) == 'y') {
......
......@@ -155,6 +155,7 @@ class installer_base {
if(is_installed('fail2ban-server')) $conf['fail2ban']['installed'] = true;
if(is_installed('vzctl')) $conf['openvz']['installed'] = true;
if(is_dir("/etc/Bastille")) $conf['bastille']['installed'] = true;
if(is_installed('metronome') && is_installed('metronomectl')) $conf['xmpp']['installed'] = true;
if ($conf['services']['web'] && (($conf['apache']['installed'] && is_file($conf['apache']["vhost_conf_enabled_dir"]."/000-ispconfig.vhost")) || ($conf['nginx']['installed'] && is_file($conf['nginx']["vhost_conf_enabled_dir"]."/000-ispconfig.vhost")))) $this->ispconfig_interface_installed = true;
}
......@@ -1308,6 +1309,66 @@ class installer_base {
}
public function configure_xmpp() {
global $conf;
if($conf['xmpp']['installed'] == false) return;
//* Create the logging directory for xmpp server
if(!@is_dir('/var/log/metronome')) mkdir('/var/log/metronome', 0755, true);
chown('/var/log/metronome', 'metronome');
if(!@is_dir('/var/run/metronome')) mkdir('/var/run/metronome', 0755, true);
chown('/var/run/metronome', 'metronome');
if(!@is_dir('/var/lib/metronome')) mkdir('/var/lib/metronome', 0755, true);
chown('/var/lib/metronome', 'metronome');
if(!@is_dir('/etc/metronome/hosts')) mkdir('/etc/metronome/hosts', 0755, true);
if(!@is_dir('/etc/metronome/status')) mkdir('/etc/metronome/status', 0755, true);
unlink('/etc/metronome/metronome.cfg.lua');
$row = $this->db->queryOneRecord("SELECT server_name FROM server WHERE server_id = ".$conf["server_id"]."");
$server_name = $row["server_name"];
$tpl = new tpl('metronome_conf_main.master');
wf('/etc/metronome/metronome.cfg.lua', $tpl->grab());
unset($tpl);
$tpl = new tpl('metronome_conf_global.master');
$tpl->setVar('xmpp_admins','');
wf('/etc/metronome/global.cfg.lua', $tpl->grab());
unset($tpl);
// Copy isp libs
if(!@is_dir('/usr/lib/metronome/isp-modules')) mkdir('/usr/lib/metronome/isp-modules', 0755, true);
caselog('cp -rf apps/metronome_libs/* /usr/lib/metronome/isp-modules/', __FILE__, __LINE__);
// Copy init script
caselog('cp -f apps/metronome-init /etc/init.d/metronome', __FILE__, __LINE__);
caselog('chmod u+x /etc/init.d/metronome', __FILE__, __LINE__);
exec($this->getinitcommand('xmpp', 'restart'));
/*// Dont just copy over the virtualhost template but add some custom settings
$tpl = new tpl('apache_apps.vhost.master');
$tpl->setVar('apps_vhost_port',$conf['web']['apps_vhost_port']);
$tpl->setVar('apps_vhost_dir',$conf['web']['website_basedir'].'/apps');
$tpl->setVar('apps_vhost_basedir',$conf['web']['website_basedir']);
$tpl->setVar('apps_vhost_servername',$apps_vhost_servername);
$tpl->setVar('apache_version',getapacheversion());
// comment out the listen directive if port is 80 or 443
if($conf['web']['apps_vhost_ip'] == 80 or $conf['web']['apps_vhost_ip'] == 443) {
$tpl->setVar('vhost_port_listen','#');
} else {
$tpl->setVar('vhost_port_listen','');
}
wf($vhost_conf_dir.'/apps.vhost', $tpl->grab());
unset($tpl);*/
}
public function configure_apache() {
global $conf;
......@@ -1969,8 +2030,9 @@ class installer_base {
$vserver_server_enabled = ($conf['openvz']['installed'])?1:0;
$proxy_server_enabled = ($conf['services']['proxy'])?1:0;
$firewall_server_enabled = ($conf['services']['firewall'])?1:0;
$xmpp_server_enabled = ($conf['services']['xmpp'])?1:0;
$sql = "UPDATE `server` SET mail_server = '$mail_server_enabled', web_server = '$web_server_enabled', dns_server = '$dns_server_enabled', file_server = '$file_server_enabled', db_server = '$db_server_enabled', vserver_server = '$vserver_server_enabled', proxy_server = '$proxy_server_enabled', firewall_server = '$firewall_server_enabled' WHERE server_id = ".intval($conf['server_id']);
$sql = "UPDATE `server` SET mail_server = '$mail_server_enabled', web_server = '$web_server_enabled', dns_server = '$dns_server_enabled', file_server = '$file_server_enabled', db_server = '$db_server_enabled', vserver_server = '$vserver_server_enabled', proxy_server = '$proxy_server_enabled', firewall_server = '$firewall_server_enabled', xmpp_server = '.$xmpp_server_enabled.' WHERE server_id = ".intval($conf['server_id']);
if($conf['mysql']['master_slave_setup'] == 'y') {
$this->dbmaster->query($sql);
......
ALTER TABLE `server` ADD COLUMN `xmpp_server` tinyint(1) NOT NULL default '0' AFTER `firewall_server`;
ALTER TABLE `client`
ADD COLUMN `limit_xmpp_domain` int(11) NOT NULL DEFAULT '-1',
ADD COLUMN `limit_xmpp_user` int(11) NOT NULL DEFAULT '-1',
ADD COLUMN `limit_xmpp_muc` ENUM( 'n', 'y' ) NOT NULL default 'n',
ADD COLUMN `limit_xmpp_anon` ENUM( 'n', 'y' ) NOT NULL default 'n',
ADD COLUMN `limit_xmpp_auth_options` varchar(255) NOT NULL DEFAULT 'plain,hashed,isp',
ADD COLUMN `limit_xmpp_vjud` ENUM( 'n', 'y' ) NOT NULL default 'n',
ADD COLUMN `limit_xmpp_proxy` ENUM( 'n', 'y' ) NOT NULL default 'n',
ADD COLUMN `limit_xmpp_status` ENUM( 'n', 'y' ) NOT NULL default 'n',