Modular WebSocket engine, added ssh and telnet to quickshell extension
This commit is contained in:
parent
bb2faca479
commit
6c52462c8c
|
@ -1,65 +1,203 @@
|
|||
<?php
|
||||
// ______ __ _______ _______ _______
|
||||
// | __ \.---.-.-----.--| |.-----.----.---.-. | ___| | | __|
|
||||
// | __/| _ | | _ || _ | _| _ | | ___| |__ |
|
||||
// |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
|
||||
//
|
||||
// ============================================================================
|
||||
// Copyright (c) 2007-2018 Artica Soluciones Tecnologicas, http://www.artica.es
|
||||
// This code is NOT free software. This code is NOT licenced under GPL2 licence
|
||||
// You cannnot redistribute it without written permission of copyright holder.
|
||||
// ============================================================================
|
||||
require_once 'include/functions.php';
|
||||
require_once 'include/functions_groupview.php';
|
||||
require_once 'include/auth/mysql.php';
|
||||
/**
|
||||
* Quick Shell extension.
|
||||
*
|
||||
* @category Extension
|
||||
* @package Pandora FMS
|
||||
* @subpackage QuickShell
|
||||
* @version 1.0.0
|
||||
* @license See below
|
||||
*
|
||||
* ______ ___ _______ _______ ________
|
||||
* | __ \.-----.--.--.--| |.-----.----.-----. | ___| | | __|
|
||||
* | __/| _ | | _ || _ | _| _ | | ___| |__ |
|
||||
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
|
||||
*
|
||||
* ============================================================================
|
||||
* Copyright (c) 2005-2019 Artica Soluciones Tecnologicas
|
||||
* Please see http://pandorafms.org for full contribution list
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation for version 2.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* ============================================================================
|
||||
*/
|
||||
|
||||
check_login();
|
||||
// Begin.
|
||||
global $config;
|
||||
|
||||
if (! check_acl($config['id_user'], 0, 'PM')) {
|
||||
db_pandora_audit(
|
||||
'ACL Violation',
|
||||
'Trying to access Profile Management'
|
||||
);
|
||||
include 'general/noaccess.php';
|
||||
return;
|
||||
}
|
||||
require_once $config['homedir'].'/include/functions_agents.php';
|
||||
require_once $config['homedir'].'/godmode/wizards/Wizard.main.php';
|
||||
|
||||
|
||||
function mainWetty()
|
||||
/**
|
||||
* Show Quick Shell interface.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function quickShell()
|
||||
{
|
||||
global $config;
|
||||
|
||||
if (!isset($config['wetty_ip'])) {
|
||||
config_update_value('wetty_ip', $_SERVER['SERVER_ADDR']);
|
||||
check_login();
|
||||
|
||||
if (! check_acl($config['id_user'], 0, 'PM')) {
|
||||
db_pandora_audit(
|
||||
'ACL Violation',
|
||||
'Trying to access Profile Management'
|
||||
);
|
||||
include 'general/noaccess.php';
|
||||
return;
|
||||
}
|
||||
|
||||
if ($config['wetty_ip'] == '127.0.0.1') {
|
||||
config_update_value('wetty_ip', $_SERVER['SERVER_ADDR']);
|
||||
$agent_id = get_parameter('id_agente', 0);
|
||||
$username = get_parameter('username', null);
|
||||
$method = get_parameter('method', null);
|
||||
$method_port = get_parameter('port', null);
|
||||
|
||||
// Retrieve main IP Address.
|
||||
$address = agents_get_address($agent_id);
|
||||
|
||||
ui_require_css_file('wizard');
|
||||
ui_require_css_file('discovery');
|
||||
|
||||
// Username. Retrieve from form.
|
||||
if (empty($username) === true) {
|
||||
// No username provided, ask for it.
|
||||
$wiz = new Wizard();
|
||||
$wiz->printForm(
|
||||
[
|
||||
'form' => [
|
||||
'id' => 'pene',
|
||||
'action' => '#',
|
||||
'class' => 'wizard',
|
||||
'method' => 'post',
|
||||
],
|
||||
'inputs' => [
|
||||
[
|
||||
'label' => __('Username'),
|
||||
'arguments' => [
|
||||
'type' => 'text',
|
||||
'name' => 'username',
|
||||
],
|
||||
],
|
||||
[
|
||||
'label' => __('Port'),
|
||||
'arguments' => [
|
||||
'type' => 'text',
|
||||
'id' => 'port',
|
||||
'name' => 'port',
|
||||
'value' => 22,
|
||||
],
|
||||
],
|
||||
[
|
||||
'label' => __('Method'),
|
||||
'arguments' => [
|
||||
'type' => 'select',
|
||||
'name' => 'method',
|
||||
'fields' => [
|
||||
'ssh' => __('SSH'),
|
||||
'telnet' => __('Telnet'),
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'arguments' => [
|
||||
'type' => 'submit',
|
||||
'label' => __('Connect'),
|
||||
'attributes' => 'class="sub next"',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
false,
|
||||
true
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isset($config['wetty_port'])) {
|
||||
config_update_value('wetty_port', '3000');
|
||||
// WebSocket host, where to connect.
|
||||
if (isset($config['ws_host']) === false) {
|
||||
config_update_value('ws_host', $_SERVER['SERVER_ADDR']);
|
||||
}
|
||||
|
||||
$buttons['maps'] = [
|
||||
'active' => false,
|
||||
'text' => '<a href="index.php?login=1&extension_in_menu=gextensions&sec=gextensions&sec2=extensions/wetty_conf">'.html_print_image('images/setup.png', true, ['title' => __('Wetty settings')]).'</a>',
|
||||
];
|
||||
if (isset($config['ws_port']) === false) {
|
||||
config_update_value('ws_port', 8080);
|
||||
}
|
||||
|
||||
ui_print_page_header(__('Wetty'), 'images/extensions.png', false, '', true, $buttons);
|
||||
if (isset($config['gotty_host']) === false) {
|
||||
config_update_value('gotty_host', '127.0.0.1');
|
||||
}
|
||||
|
||||
$host = '127.0.0.1';
|
||||
$port = 8080;
|
||||
if (isset($config['gotty_telnet_port']) === false) {
|
||||
config_update_value('gotty_telnet_port', 8082);
|
||||
}
|
||||
|
||||
if (isset($config['gotty_ssh_port']) === false) {
|
||||
config_update_value('gotty_ssh_port', 8081);
|
||||
}
|
||||
|
||||
$host = $config['gotty_host'];
|
||||
if ($method == 'ssh') {
|
||||
// SSH.
|
||||
$port = $config['gotty_ssh_port'];
|
||||
$command_arguments = "var args = '?arg=".$username.'@'.$address;
|
||||
$command_arguments .= '&arg=-p '.$method_port."';";
|
||||
} else if ($method == 'telnet') {
|
||||
// Telnet.
|
||||
$port = $config['gotty_telnet_port'];
|
||||
$command_arguments = "var args = '?arg=-l ".$username;
|
||||
$command_arguments .= '&arg= '.$address;
|
||||
$command_arguments .= '&arg= '.$method_port."';";
|
||||
} else {
|
||||
ui_print_error_message(__('Please use SSH or Telnet.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$r = file_get_contents('http://'.$host.':'.$port.'/js/hterm.js');
|
||||
$r .= file_get_contents('http://'.$host.':'.$port.'/auth_token.js');
|
||||
|
||||
if (empty($r) === true) {
|
||||
echo 'No hay nadie al volante, peligro constante';
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($config['gotty_user'])
|
||||
&& empty($config['gotty_pass'])
|
||||
) {
|
||||
$r .= "var gotty_auth_token = '';";
|
||||
} else {
|
||||
$r .= "var gotty_auth_token = '";
|
||||
$r .= $config['gotty_user'].':'.$gotty_pass."';";
|
||||
}
|
||||
|
||||
$gotty = file_get_contents('http://'.$host.':'.$port.'/js/gotty.js');
|
||||
|
||||
// Set websocket target.
|
||||
$url = "var url = (httpsEnabled ? 'wss://' : 'ws://') + window.location.host + window.location.pathname + 'ws';";
|
||||
$new = "var url = (httpsEnabled ? 'wss://' : 'ws://') + window.location.host + ':8081' + window.location.pathname;";
|
||||
if (empty($config['ws_proxy_url']) === true) {
|
||||
$new = "var url = (httpsEnabled ? 'wss://' : 'ws://')";
|
||||
$new .= " + window.location.host + ':";
|
||||
$new .= $config['ws_port'].'/'.$method."';";
|
||||
} else {
|
||||
$new = "var url = (httpsEnabled ? 'wss://' : 'ws://') + ";
|
||||
$new .= 'window.location.host + ';
|
||||
$new .= "'".$config['ws_proxy_url'].'/'.$method."';";
|
||||
}
|
||||
|
||||
// Update url.
|
||||
$gotty = str_replace($url, $new, $gotty);
|
||||
|
||||
// Update websocket arguments.
|
||||
$args = 'var args = window.location.search;';
|
||||
$new = $command_arguments;
|
||||
|
||||
// Update arguments.
|
||||
$gotty = str_replace($args, $new, $gotty);
|
||||
|
||||
?>
|
||||
<style>#terminal {
|
||||
height: 650px;
|
||||
|
@ -79,31 +217,24 @@ function mainWetty()
|
|||
<?php echo $gotty; ?>
|
||||
</script>
|
||||
<?php
|
||||
/*
|
||||
$table->width = '100%';
|
||||
$table->class = 'databox data';
|
||||
$table->data = [];
|
||||
$table->head = [];
|
||||
$table->align = [];
|
||||
// $table->align[3] = 'left';
|
||||
$table->style = [];
|
||||
$table->size = [];
|
||||
// $table->size[3] = '10%';
|
||||
$table->style[0] = 'font-weight: bold';
|
||||
|
||||
$table->head[0] = __('Wetty');
|
||||
|
||||
// $data[0] = '<iframe scrolling="auto" frameborder="0" width="100%" height="600px" src="http://192.168.70.64:3000/"></iframe>';
|
||||
$data[0] = '<iframe scrolling="auto" frameborder="0" width="100%" height="600px" src="http://'.$config['wetty_ip'].':'.$config['wetty_port'].'/"></iframe>';
|
||||
|
||||
// $data[0] .= '<div id="terminal" style="background-color:black;width:100%;height:600px;overflow: hidden;"><div>';
|
||||
array_push($table->data, $data);
|
||||
|
||||
html_print_table($table);
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
extensions_add_godmode_menu_option(__('Wetty'), 'AW', 'gextensions', null, 'v1');
|
||||
extensions_add_godmode_function('mainWetty');
|
||||
extensions_add_opemode_tab_agent(
|
||||
// TabId.
|
||||
'quick_shell',
|
||||
// TabName.
|
||||
__('QuickShell'),
|
||||
// TabIcon.
|
||||
'images/ehorus/terminal.png',
|
||||
// TabFunction.
|
||||
'quickShell',
|
||||
// Version.
|
||||
'N/A',
|
||||
// Acl.
|
||||
'PM'
|
||||
);
|
||||
|
||||
// extensions_add_godmode_menu_option(__('Quick Shell'), 'AW', 'gextensions', null, 'v1');
|
||||
// extensions_add_godmode_function('quickShell');
|
||||
|
|
|
@ -63,9 +63,20 @@ if (is_ajax()) {
|
|||
|
||||
$test_address = get_parameter('test_address', '');
|
||||
|
||||
$res = enterprise_hook('send_email_attachment', [$test_address, __('This is an email test sent from Pandora FMS. If you can read this, your configuration works.'), __('Testing Pandora FMS email'), null]);
|
||||
$res = enterprise_hook(
|
||||
'send_email_attachment',
|
||||
[
|
||||
$test_address,
|
||||
__('This is an email test sent from Pandora FMS. If you can read this, your configuration works.'),
|
||||
__('Testing Pandora FMS email'),
|
||||
null,
|
||||
]
|
||||
);
|
||||
|
||||
echo $res;
|
||||
|
||||
// Exit after ajax response.
|
||||
exit();
|
||||
}
|
||||
|
||||
$table = new StdClass();
|
||||
|
@ -389,6 +400,42 @@ html_print_input_hidden('update_config', 1);
|
|||
html_print_table($table_mail_conf);
|
||||
|
||||
|
||||
echo '</fieldset>';
|
||||
|
||||
echo '<fieldset>';
|
||||
echo '<legend>'.__('WebSocket settings').'</legend>';
|
||||
|
||||
$t = new StdClass();
|
||||
$t->data = [];
|
||||
$t->width = '100%';
|
||||
$t->class = 'databox filters';
|
||||
$t->data = [];
|
||||
$t->style[0] = 'font-weight: bold';
|
||||
|
||||
$t->data[0][0] = __('Bind address');
|
||||
$t->data[0][1] = html_print_input_text(
|
||||
'ws_bind_address',
|
||||
$config['ws_bind_address'],
|
||||
'',
|
||||
30,
|
||||
100,
|
||||
true
|
||||
);
|
||||
|
||||
$t->data[1][0] = __('Bind port');
|
||||
$t->data[1][2] = html_print_input_text(
|
||||
'ws_port',
|
||||
$config['ws_port'],
|
||||
'',
|
||||
30,
|
||||
100,
|
||||
true
|
||||
);
|
||||
|
||||
html_print_input_hidden('update_config', 1);
|
||||
html_print_table($t);
|
||||
|
||||
|
||||
echo '</fieldset>';
|
||||
|
||||
echo '<div class="action-buttons" style="width: '.$table->width.'">';
|
||||
|
|
|
@ -2354,26 +2354,52 @@ class ConsoleSupervisor
|
|||
public function checkConsoleServerVersions()
|
||||
{
|
||||
global $config;
|
||||
// List all servers except satellite server
|
||||
// List all servers except satellite server.
|
||||
$server_version_list = db_get_all_rows_sql(
|
||||
'SELECT name, version FROM tserver WHERE server_type != '.SERVER_TYPE_ENTERPRISE_SATELLITE
|
||||
sprintf(
|
||||
'SELECT `name`, `version`
|
||||
FROM tserver
|
||||
WHERE server_type != %d
|
||||
GROUP BY `version`',
|
||||
SERVER_TYPE_ENTERPRISE_SATELLITE
|
||||
)
|
||||
);
|
||||
|
||||
foreach ($server_version_list as $server) {
|
||||
if (strpos($server['version'], $config['current_package_enterprise']) === false) {
|
||||
$title_ver_misaligned = $server['name'].' version misaligned with Console';
|
||||
$message_ver_misaligned = 'Server '.$server['name'].' and this console have different versions. This might cause several malfunctions. Please, update this server.';
|
||||
$missed = 0;
|
||||
|
||||
$this->notify(
|
||||
[
|
||||
'type' => 'NOTIF.SERVER.MISALIGNED',
|
||||
'title' => __($title_ver_misaligned),
|
||||
'message' => __($message_ver_misaligned),
|
||||
'url' => ui_get_full_url('index.php?sec=messages&sec2=godmode/update_manager/update_manager&tab=online'),
|
||||
]
|
||||
);
|
||||
if (is_array($server_version_list) === true) {
|
||||
foreach ($server_version_list as $server) {
|
||||
if (strpos(
|
||||
$server['version'],
|
||||
$config['current_package_enterprise']
|
||||
) === false
|
||||
) {
|
||||
$missed++;
|
||||
$title_ver_misaligned = __(
|
||||
'%s version misaligned with Console',
|
||||
$server['name']
|
||||
);
|
||||
$message_ver_misaligned = __(
|
||||
'Server %s and this console have different versions. This might cause several malfunctions. Please, update this server.',
|
||||
$server['name']
|
||||
);
|
||||
|
||||
$this->notify(
|
||||
[
|
||||
'type' => 'NOTIF.SERVER.MISALIGNED',
|
||||
'title' => __($title_ver_misaligned),
|
||||
'message' => __($message_ver_misaligned),
|
||||
'url' => ui_get_full_url('index.php?sec=messages&sec2=godmode/update_manager/update_manager&tab=online'),
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup notifications if exception is recovered.
|
||||
if ($missed == 0) {
|
||||
$this->cleanNotifications('NOTIF.SERVER.MISALIGNED');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -353,6 +353,14 @@ function config_update_config()
|
|||
if (!config_update_value('email_password', get_parameter('email_password'))) {
|
||||
$error_update[] = __('Email password');
|
||||
}
|
||||
|
||||
if (!config_update_value('ws_bind_address', get_parameter('ws_bind_address'))) {
|
||||
$error_update[] = __('WebSocket bind address');
|
||||
}
|
||||
|
||||
if (!config_update_value('ws_port', get_parameter('ws_port'))) {
|
||||
$error_update[] = __('WebSocket port');
|
||||
}
|
||||
break;
|
||||
|
||||
case 'enterprise':
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* PHP WebSocketServer Proxy.
|
||||
* PHP WebSocketServer Manager.
|
||||
*
|
||||
* Adapted to PandoraFMS by Fco de Borja Sanchez <fborja.sanchez@artica.es>
|
||||
* Compatible with PHP >= 7.0
|
||||
|
@ -52,7 +52,7 @@ require_once __DIR__.'/../functions.php';
|
|||
/**
|
||||
* Redirects ws communication between two endpoints.
|
||||
*/
|
||||
class WSProxy extends WebSocketServer
|
||||
class WSManager extends WebSocketServer
|
||||
{
|
||||
|
||||
/**
|
||||
|
@ -82,14 +82,14 @@ class WSProxy extends WebSocketServer
|
|||
*
|
||||
* @var integer
|
||||
*/
|
||||
protected $maxBufferSize = 1048576;
|
||||
public $maxBufferSize = 1048576;
|
||||
|
||||
/**
|
||||
* Interactive mode.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $interative = true;
|
||||
public $interative = true;
|
||||
|
||||
/**
|
||||
* Use a timeout of 100 milliseconds to search for messages..
|
||||
|
@ -98,37 +98,104 @@ class WSProxy extends WebSocketServer
|
|||
*/
|
||||
public $timeout = 250;
|
||||
|
||||
/**
|
||||
* Handlers for connected step:
|
||||
* 'protocol' => 'function';
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $handlerConnected = [];
|
||||
|
||||
/**
|
||||
* Handlers for process step:
|
||||
* 'protocol' => 'function';
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $handlerProcess = [];
|
||||
|
||||
/**
|
||||
* Handlers for processRaw step:
|
||||
* 'protocol' => 'function';
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $handlerProcessRaw = [];
|
||||
|
||||
/**
|
||||
* Handlers for tick step:
|
||||
* 'protocol' => 'function';
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $handlerTick = [];
|
||||
|
||||
|
||||
/**
|
||||
* Builder.
|
||||
*
|
||||
* @param string $listen_addr Target address (external).
|
||||
* @param integer $listen_port Target port (external).
|
||||
* @param string $to_addr Target address (internal).
|
||||
* @param integer $to_port Target port (internal).
|
||||
* @param integer $to_url Target url (internal).
|
||||
* @param array $connected Handlers for <connected> step.
|
||||
* @param array $process Handlers for <process> step.
|
||||
* @param array $processRaw Handlers for <processRaw> step.
|
||||
* @param array $tick Handlers for <tick> step.
|
||||
* @param integer $bufferLength Max buffer size.
|
||||
* @param boolean $debug Enable traces.
|
||||
*/
|
||||
public function __construct(
|
||||
$listen_addr,
|
||||
$listen_port,
|
||||
$to_addr,
|
||||
$to_port,
|
||||
$to_url='/ws',
|
||||
$connected=[],
|
||||
$process=[],
|
||||
$processRaw=[],
|
||||
$tick=[],
|
||||
$bufferLength=1048576,
|
||||
$debug=false
|
||||
) {
|
||||
$this->intHost = $to_addr;
|
||||
$this->intPort = $to_port;
|
||||
$this->intUrl = $to_url;
|
||||
$this->maxBufferSize = $bufferLength;
|
||||
$this->debug = $debug;
|
||||
|
||||
// Configure handlers.
|
||||
$this->handlerConnected = $connected;
|
||||
$this->handlerProcess = $process;
|
||||
$this->handlerProcessRaw = $processRaw;
|
||||
$this->handlerTick = $tick;
|
||||
|
||||
$this->userClass = '\\PandoraFMS\\Websockets\\WebSocketUser';
|
||||
parent::__construct($listen_addr, $listen_port, $bufferLength);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call a target handler function.
|
||||
*
|
||||
* @param User $user User.
|
||||
* @param array $handler Internal handler.
|
||||
* @param array $arguments Arguments for handler function.
|
||||
*
|
||||
* @return mixed handler return or null.
|
||||
*/
|
||||
public function callHandler($user, $handler, $arguments)
|
||||
{
|
||||
if (isset($user->headers['sec-websocket-protocol'])) {
|
||||
$proto = $user->headers['sec-websocket-protocol'];
|
||||
if (isset($handler[$proto])
|
||||
&& function_exists($handler[$proto])
|
||||
) {
|
||||
// Launch configured handler.
|
||||
$this->stderr('Calling '.$handler[$proto]);
|
||||
return call_user_func_array(
|
||||
$handler[$proto],
|
||||
$arguments
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read from user's socket.
|
||||
*
|
||||
|
@ -136,7 +203,7 @@ class WSProxy extends WebSocketServer
|
|||
*
|
||||
* @return string Buffer.
|
||||
*/
|
||||
protected function readSocket($user)
|
||||
public function readSocket($user)
|
||||
{
|
||||
$buffer;
|
||||
|
||||
|
@ -171,7 +238,7 @@ class WSProxy extends WebSocketServer
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function writeSocket($user, $message)
|
||||
public function writeSocket($user, $message)
|
||||
{
|
||||
if (is_resource($user->socket)) {
|
||||
if (!socket_write($user->socket, $message)) {
|
||||
|
@ -186,53 +253,6 @@ class WSProxy extends WebSocketServer
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Connects to internal socket.
|
||||
*
|
||||
* @param array $headers Communication headers.
|
||||
*
|
||||
* @return socket Active socket or null.
|
||||
*/
|
||||
protected function connectInt($headers)
|
||||
{
|
||||
$intSocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
|
||||
$connect = socket_connect(
|
||||
$intSocket,
|
||||
$this->intHost,
|
||||
$this->intPort
|
||||
);
|
||||
if (!$connect) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$c_str = 'GET '.$this->intUrl." HTTP/1.1\r\n";
|
||||
$c_str .= 'Host: '.$this->intHost."\r\n";
|
||||
$c_str .= "Upgrade: websocket\r\n";
|
||||
$c_str .= "Connection: Upgrade\r\n";
|
||||
$c_str .= 'Origin: http://'.$this->intHost."\r\n";
|
||||
$c_str .= 'Sec-WebSocket-Key: '.$headers['Sec-WebSocket-Key']."\r\n";
|
||||
$c_str .= 'Sec-WebSocket-Version: '.$headers['Sec-WebSocket-Version']."\r\n";
|
||||
if (isset($headers['Sec-WebSocket-Protocol'])) {
|
||||
$c_str .= 'Sec-WebSocket-Protocol: '.$headers['Sec-WebSocket-Protocol']."\r\n";
|
||||
}
|
||||
|
||||
$c_str .= "\r\n";
|
||||
|
||||
// Send.
|
||||
// Register user - internal.
|
||||
$intUser = new $this->userClass('INTERNAL-'.uniqid('u'), $intSocket);
|
||||
|
||||
$intUser->headers = [
|
||||
'get' => $this->intUrl.' HTTP/1.1',
|
||||
'host' => $this->intHost,
|
||||
'origin' => $this->intHost,
|
||||
];
|
||||
$this->writeSocket($intUser, $c_str);
|
||||
|
||||
return $intUser;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* User already connected.
|
||||
*
|
||||
|
@ -240,7 +260,7 @@ class WSProxy extends WebSocketServer
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function connected($user)
|
||||
public function connected($user)
|
||||
{
|
||||
global $config;
|
||||
|
||||
|
@ -275,31 +295,15 @@ class WSProxy extends WebSocketServer
|
|||
// Disconnect previous sessions.
|
||||
$this->cleanupSocketByCookie($user);
|
||||
|
||||
/*
|
||||
* $user->intSocket is connected to internal.
|
||||
* $user->socket is connected to external.
|
||||
*/
|
||||
|
||||
// Create a new socket connection (internal).
|
||||
$intUser = $this->connectInt($this->rawHeaders);
|
||||
if ($intUser === null) {
|
||||
$this->disconnect($user->socket);
|
||||
return;
|
||||
}
|
||||
|
||||
// Map user.
|
||||
$user->intUser = $intUser;
|
||||
// And socket.
|
||||
$user->intSocket = $intUser->socket;
|
||||
$user->redirect = $intUser;
|
||||
$intUser->redirect = $user;
|
||||
|
||||
// Keep an eye on changes.
|
||||
$this->remoteSockets[$intUser->id] = $intUser->socket;
|
||||
$this->remoteUsers[$intUser->id] = $intUser;
|
||||
|
||||
// Ignore. Cleanup socket.
|
||||
$response = $this->readSocket($user->intUser);
|
||||
// Launch registered handler.
|
||||
$this->callHandler(
|
||||
$user,
|
||||
$this->handlerConnected,
|
||||
[
|
||||
$this,
|
||||
$user,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
@ -310,12 +314,34 @@ class WSProxy extends WebSocketServer
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function processProtocol($protocol): string
|
||||
public function processProtocol($protocol): string
|
||||
{
|
||||
return 'Sec-Websocket-Protocol: '.$protocol."\r\n";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Process programattic function
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function tick()
|
||||
{
|
||||
foreach ($this->users as $user) {
|
||||
// Launch registered handler.
|
||||
$this->callHandler(
|
||||
$user,
|
||||
$this->handlerTick,
|
||||
[
|
||||
$this,
|
||||
$user,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Process undecoded user message.
|
||||
*
|
||||
|
@ -324,18 +350,18 @@ class WSProxy extends WebSocketServer
|
|||
*
|
||||
* @return boolean
|
||||
*/
|
||||
protected function processRaw($user, $buffer)
|
||||
public function processRaw($user, $buffer)
|
||||
{
|
||||
if (!isset($user->redirect)) {
|
||||
$this->disconnect($user->socket);
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->stderr($user->id.' >> '.$user->redirect->id);
|
||||
$this->stderr($this->dump($buffer));
|
||||
$this->writeSocket($user->redirect, $buffer);
|
||||
|
||||
return true;
|
||||
// Launch registered handler.
|
||||
return $this->callHandler(
|
||||
$user,
|
||||
$this->handlerProcessRaw,
|
||||
[
|
||||
$this,
|
||||
$user,
|
||||
$buffer,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
@ -348,12 +374,24 @@ class WSProxy extends WebSocketServer
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function process($user, $message, $str_message)
|
||||
public function process($user, $message, $str_message)
|
||||
{
|
||||
if ($str_message === true) {
|
||||
$remmitent = $user->address.'('.$user->account->idUser.')';
|
||||
$this->stderr($remmitent.': '.$message);
|
||||
}
|
||||
|
||||
// Launch registered handler.
|
||||
$this->callHandler(
|
||||
$user,
|
||||
$this->handlerProcess,
|
||||
[
|
||||
$this,
|
||||
$user,
|
||||
$message,
|
||||
$str_message,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
@ -364,7 +402,7 @@ class WSProxy extends WebSocketServer
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function closed($user)
|
||||
public function closed($user)
|
||||
{
|
||||
if ($user->account) {
|
||||
$_SERVER['REMOTE_ADDR'] = $user->address;
|
|
@ -1,89 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* PHP WebSocketUser Proxy.
|
||||
*
|
||||
* Adapted to PandoraFMS by Fco de Borja Sanchez <fborja.sanchez@artica.es>
|
||||
* Compatible with PHP >= 7.0
|
||||
*
|
||||
* @category External library
|
||||
* @package Pandora FMS
|
||||
* @subpackage WebSocketServer
|
||||
* @version 1.0.0
|
||||
* @license See below
|
||||
* @filesource https://github.com/ghedipunk/PHP-Websockets
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of PHP WebSockets nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// Begin.
|
||||
namespace PandoraFMS\WebSockets;
|
||||
|
||||
use \PandoraFMS\WebSockets\WebSocketUser;
|
||||
|
||||
|
||||
/**
|
||||
* WebSocket proxy user.
|
||||
*/
|
||||
class WSProxyUser extends WebSocketUser
|
||||
{
|
||||
|
||||
/**
|
||||
* Redirection socket.
|
||||
*
|
||||
* @var socket
|
||||
*/
|
||||
public $intSocket;
|
||||
|
||||
/**
|
||||
* Pair resend packages.
|
||||
*
|
||||
* @var WSProxyUser
|
||||
*/
|
||||
public $redirect;
|
||||
|
||||
/**
|
||||
* User identifier.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $myId;
|
||||
|
||||
|
||||
/**
|
||||
* Builder.
|
||||
*
|
||||
* @param string $id Identifier.
|
||||
* @param socket $socket Socket (origin).
|
||||
*/
|
||||
public function __construct($id, $socket)
|
||||
{
|
||||
parent::__construct($id, $socket);
|
||||
$this->myId = $id;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -56,7 +56,7 @@ abstract class WebSocketServer
|
|||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $userClass = 'WebSocketUser';
|
||||
public $userClass = 'WebSocketUser';
|
||||
|
||||
/**
|
||||
* Redefine this if you want a custom user class. The custom user class
|
||||
|
@ -64,91 +64,91 @@ abstract class WebSocketServer
|
|||
*
|
||||
* @var integer
|
||||
*/
|
||||
protected $maxBufferSize;
|
||||
public $maxBufferSize;
|
||||
|
||||
/**
|
||||
* Max. concurrent connections.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
protected $maxConnections = 20;
|
||||
public $maxConnections = 20;
|
||||
|
||||
/**
|
||||
* Undocumented variable
|
||||
*
|
||||
* @var [type]
|
||||
*/
|
||||
protected $master;
|
||||
public $master;
|
||||
|
||||
/**
|
||||
* Incoming sockets.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $sockets = [];
|
||||
public $sockets = [];
|
||||
|
||||
/**
|
||||
* Outgoing sockets.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $remoteSockets = [];
|
||||
public $remoteSockets = [];
|
||||
|
||||
/**
|
||||
* Client list.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $users = [];
|
||||
public $users = [];
|
||||
|
||||
/**
|
||||
* Servers list.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $remoteUsers = [];
|
||||
public $remoteUsers = [];
|
||||
|
||||
/**
|
||||
* Undocumented variable
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $heldMessages = [];
|
||||
public $heldMessages = [];
|
||||
|
||||
/**
|
||||
* Show output.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $interactive = true;
|
||||
public $interactive = true;
|
||||
|
||||
/**
|
||||
* Debug.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $debug = false;
|
||||
public $debug = false;
|
||||
|
||||
/**
|
||||
* Undocumented variable
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $headerOriginRequired = false;
|
||||
public $headerOriginRequired = false;
|
||||
|
||||
/**
|
||||
* Undocumented variable
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $headerSecWebSocketProtocolRequired = false;
|
||||
public $headerSecWebSocketProtocolRequired = false;
|
||||
|
||||
/**
|
||||
* Undocumented variable
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $headerSecWebSocketExtensionsRequired = false;
|
||||
public $headerSecWebSocketExtensionsRequired = false;
|
||||
|
||||
/**
|
||||
* Stored raw headers for redirection.
|
||||
|
@ -217,7 +217,7 @@ abstract class WebSocketServer
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
abstract protected function process($user, $message, $str_message);
|
||||
abstract public function process($user, $message, $str_message);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -228,7 +228,7 @@ abstract class WebSocketServer
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function processRaw($user, $buffer)
|
||||
public function processRaw($user, $buffer)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -241,7 +241,7 @@ abstract class WebSocketServer
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
abstract protected function connected($user);
|
||||
abstract public function connected($user);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -251,7 +251,7 @@ abstract class WebSocketServer
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
abstract protected function closed($user);
|
||||
abstract public function closed($user);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -263,7 +263,7 @@ abstract class WebSocketServer
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function connecting($user)
|
||||
public function connecting($user)
|
||||
{
|
||||
// Optional implementation.
|
||||
}
|
||||
|
@ -277,9 +277,8 @@ abstract class WebSocketServer
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function send($user, $message)
|
||||
public function send($user, $message)
|
||||
{
|
||||
var_dump($user->handshake);
|
||||
if ($user->handshake) {
|
||||
$message = $this->frame($message, $user);
|
||||
$result = socket_write($user->socket, $message, strlen($message));
|
||||
|
@ -301,7 +300,7 @@ abstract class WebSocketServer
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function tick()
|
||||
public function tick()
|
||||
{
|
||||
// Optional implementation.
|
||||
}
|
||||
|
@ -312,7 +311,7 @@ abstract class WebSocketServer
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function pTick()
|
||||
public function pTick()
|
||||
{
|
||||
// Core maintenance processes, such as retrying failed messages.
|
||||
foreach ($this->heldMessages as $key => $hm) {
|
||||
|
@ -532,7 +531,7 @@ abstract class WebSocketServer
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function connect($socket)
|
||||
public function connect($socket)
|
||||
{
|
||||
$user = new $this->userClass(
|
||||
uniqid('u'),
|
||||
|
@ -553,7 +552,7 @@ abstract class WebSocketServer
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function disconnect(
|
||||
public function disconnect(
|
||||
$socket,
|
||||
bool $triggerClosed=true,
|
||||
$sockErrNo=null
|
||||
|
@ -606,7 +605,7 @@ abstract class WebSocketServer
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function doHandshake($user, $buffer)
|
||||
public function doHandshake($user, $buffer)
|
||||
{
|
||||
$magicGUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
|
||||
$headers = [];
|
||||
|
@ -742,7 +741,7 @@ abstract class WebSocketServer
|
|||
*
|
||||
* @return boolean Ok or not.
|
||||
*/
|
||||
protected function checkHost($hostName): bool
|
||||
public function checkHost($hostName): bool
|
||||
{
|
||||
// Override and return false if host is not one that you would expect.
|
||||
// Ex: You only want to accept hosts from the my-domain.com domain,
|
||||
|
@ -758,7 +757,7 @@ abstract class WebSocketServer
|
|||
*
|
||||
* @return boolean Allowed or not.
|
||||
*/
|
||||
protected function checkOrigin($origin): bool
|
||||
public function checkOrigin($origin): bool
|
||||
{
|
||||
// Override and return false if origin is not one that you would expect.
|
||||
return true;
|
||||
|
@ -772,7 +771,7 @@ abstract class WebSocketServer
|
|||
*
|
||||
* @return boolean Expected or not.
|
||||
*/
|
||||
protected function checkWebsocProtocol($protocol): bool
|
||||
public function checkWebsocProtocol($protocol): bool
|
||||
{
|
||||
// Override and return false if a protocol is not found that you
|
||||
// would expect.
|
||||
|
@ -787,7 +786,7 @@ abstract class WebSocketServer
|
|||
*
|
||||
* @return boolean Allowed or not.
|
||||
*/
|
||||
protected function checkWebsocExtensions($extensions): bool
|
||||
public function checkWebsocExtensions($extensions): bool
|
||||
{
|
||||
// Override and return false if an extension is not found that you
|
||||
// would expect.
|
||||
|
@ -810,7 +809,7 @@ abstract class WebSocketServer
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function processProtocol($protocol): string
|
||||
public function processProtocol($protocol): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
@ -825,7 +824,7 @@ abstract class WebSocketServer
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function processExtensions($extensions): string
|
||||
public function processExtensions($extensions): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
@ -838,7 +837,7 @@ abstract class WebSocketServer
|
|||
*
|
||||
* @return object
|
||||
*/
|
||||
protected function getUserBySocket($socket)
|
||||
public function getUserBySocket($socket)
|
||||
{
|
||||
foreach ($this->users as $user) {
|
||||
if ($user->socket == $socket) {
|
||||
|
@ -863,7 +862,7 @@ abstract class WebSocketServer
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function cleanupSocketByCookie($user)
|
||||
public function cleanupSocketByCookie($user)
|
||||
{
|
||||
$cookie = $user->headers['cookie'];
|
||||
foreach ($this->users as $u) {
|
||||
|
@ -884,7 +883,7 @@ abstract class WebSocketServer
|
|||
*
|
||||
* @return object
|
||||
*/
|
||||
protected function getIntUserBySocket($socket)
|
||||
public function getIntUserBySocket($socket)
|
||||
{
|
||||
foreach ($this->users as $user) {
|
||||
if ($user->intSocket == $socket) {
|
||||
|
@ -941,7 +940,7 @@ abstract class WebSocketServer
|
|||
*
|
||||
* @return string Framed message.
|
||||
*/
|
||||
protected function frame(
|
||||
public function frame(
|
||||
$message,
|
||||
$user,
|
||||
$messageType='text',
|
||||
|
@ -1046,7 +1045,7 @@ abstract class WebSocketServer
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function splitPacket(
|
||||
public function splitPacket(
|
||||
int $length,
|
||||
$packet,
|
||||
$user
|
||||
|
@ -1106,7 +1105,7 @@ abstract class WebSocketServer
|
|||
*
|
||||
* @return integer Calculated offset.
|
||||
*/
|
||||
protected function calcOffset(array $headers): int
|
||||
public function calcOffset(array $headers): int
|
||||
{
|
||||
$offset = 2;
|
||||
if ($headers['hasmask']) {
|
||||
|
@ -1131,7 +1130,7 @@ abstract class WebSocketServer
|
|||
*
|
||||
* @return boolean Process ok or not.
|
||||
*/
|
||||
protected function deframe(
|
||||
public function deframe(
|
||||
$message,
|
||||
&$user
|
||||
) {
|
||||
|
@ -1226,7 +1225,7 @@ abstract class WebSocketServer
|
|||
*
|
||||
* @return array Headers.
|
||||
*/
|
||||
protected function extractHeaders($message): array
|
||||
public function extractHeaders($message): array
|
||||
{
|
||||
$header = [
|
||||
'fin' => ($message[0] & chr(128)),
|
||||
|
@ -1304,7 +1303,7 @@ abstract class WebSocketServer
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function extractPayload(
|
||||
public function extractPayload(
|
||||
$message,
|
||||
array $headers
|
||||
) {
|
||||
|
@ -1331,7 +1330,7 @@ abstract class WebSocketServer
|
|||
*
|
||||
* @return string Xor.
|
||||
*/
|
||||
protected function applyMask(
|
||||
public function applyMask(
|
||||
array $headers,
|
||||
$payload
|
||||
) {
|
||||
|
@ -1373,7 +1372,7 @@ abstract class WebSocketServer
|
|||
*
|
||||
* @return boolean OK or not.
|
||||
*/
|
||||
protected function checkRSVBits(
|
||||
public function checkRSVBits(
|
||||
array $headers,
|
||||
$user
|
||||
): bool {
|
||||
|
@ -1400,7 +1399,7 @@ abstract class WebSocketServer
|
|||
*
|
||||
* @return string HEX string.
|
||||
*/
|
||||
protected function strtohex(
|
||||
public function strtohex(
|
||||
$str=''
|
||||
): string {
|
||||
$strout = '';
|
||||
|
@ -1441,7 +1440,7 @@ abstract class WebSocketServer
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function printHeaders($headers)
|
||||
public function printHeaders($headers)
|
||||
{
|
||||
echo "Array\n(\n";
|
||||
foreach ($headers as $key => $value) {
|
||||
|
@ -1468,7 +1467,7 @@ abstract class WebSocketServer
|
|||
// Init.
|
||||
$hexi = '';
|
||||
$ascii = '';
|
||||
$dump = '';
|
||||
$dump = "Hex Message:\n";
|
||||
$offset = 0;
|
||||
$len = strlen($data);
|
||||
|
||||
|
|
|
@ -0,0 +1,189 @@
|
|||
<?php
|
||||
/**
|
||||
* Extra functionality for PandoraFMS WebSockets.
|
||||
*
|
||||
* Register here your methods to handle different WebSocket steps.
|
||||
* * connected
|
||||
* * process
|
||||
* * disconnect
|
||||
* * tick
|
||||
*
|
||||
* DO NOT FORGET TO REGISTER THEM TO ws.php!!
|
||||
*
|
||||
* @category Websocket
|
||||
* @package Pandora FMS
|
||||
* @subpackage Console
|
||||
* @version 1.0.0
|
||||
* @license See below
|
||||
*
|
||||
* ______ ___ _______ _______ ________
|
||||
* | __ \.-----.--.--.--| |.-----.----.-----. | ___| | | __|
|
||||
* | __/| _ | | _ || _ | _| _ | | ___| |__ |
|
||||
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
|
||||
*
|
||||
* ============================================================================
|
||||
* Copyright (c) 2005-2019 Artica Soluciones Tecnologicas
|
||||
* Please see http://pandorafms.org for full contribution list
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation for version 2.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* ============================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* ============================================================================
|
||||
* * GOTTY PROTOCOL: PROXY
|
||||
* ============================================================================
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Connects to internal socket.
|
||||
*
|
||||
* @param WSManager $ws_object Main WebSocket manager object.
|
||||
* @param array $headers Communication headers.
|
||||
* @param string $to_addr Target address (internal).
|
||||
* @param integer $to_port Target port (internal).
|
||||
* @param integer $to_url Target url (internal).
|
||||
*
|
||||
* @return socket Active socket or null.
|
||||
*/
|
||||
function connectInt(
|
||||
$ws_object,
|
||||
$headers,
|
||||
$to_addr,
|
||||
$to_port,
|
||||
$to_url
|
||||
) {
|
||||
$intSocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
|
||||
$connect = socket_connect(
|
||||
$intSocket,
|
||||
$to_addr,
|
||||
$to_port
|
||||
);
|
||||
if (!$connect) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$c_str = 'GET '.$to_url." HTTP/1.1\r\n";
|
||||
$c_str .= 'Host: '.$to_addr."\r\n";
|
||||
$c_str .= "Upgrade: websocket\r\n";
|
||||
$c_str .= "Connection: Upgrade\r\n";
|
||||
$c_str .= 'Origin: http://'.$to_addr."\r\n";
|
||||
$c_str .= 'Sec-WebSocket-Key: '.$headers['Sec-WebSocket-Key']."\r\n";
|
||||
$c_str .= 'Sec-WebSocket-Version: '.$headers['Sec-WebSocket-Version']."\r\n";
|
||||
if (isset($headers['Sec-WebSocket-Protocol'])) {
|
||||
$c_str .= 'Sec-WebSocket-Protocol: '.$headers['Sec-WebSocket-Protocol']."\r\n";
|
||||
}
|
||||
|
||||
$c_str .= "\r\n";
|
||||
|
||||
// Send.
|
||||
// Register user - internal.
|
||||
$intUser = new $ws_object->userClass('INTERNAL-'.uniqid('u'), $intSocket);
|
||||
|
||||
$intUser->headers = [
|
||||
'get' => $to_url.' HTTP/1.1',
|
||||
'host' => $to_addr,
|
||||
'origin' => $to_addr,
|
||||
'sec-websocket-protocol' => 'gotty',
|
||||
];
|
||||
$ws_object->writeSocket($intUser, $c_str);
|
||||
|
||||
return $intUser;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Process a connected step on proxied protocols.
|
||||
*
|
||||
* @param WSManager $ws_object Main WebSocket manager object.
|
||||
* @param User $user WebSocketUser.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function proxyConnected(
|
||||
$ws_object,
|
||||
$user
|
||||
) {
|
||||
global $config;
|
||||
|
||||
/*
|
||||
* $user->redirect is connected to internal (reflexive).
|
||||
* $user->socket is connected to external.
|
||||
*/
|
||||
|
||||
// Gotty. Based on the command selected, redirect to a target port.
|
||||
if ($user->requestedResource == '/ssh') {
|
||||
$port = $config['gotty_ssh_port'];
|
||||
} else if ($user->requestedResource == '/telnet') {
|
||||
$port = $config['gotty_telnet_port'];
|
||||
} else {
|
||||
$ws_object->disconnect($user->socket);
|
||||
return;
|
||||
}
|
||||
|
||||
// Switch between ports...
|
||||
// Create a new socket connection (internal).
|
||||
$intUser = connectInt(
|
||||
$ws_object,
|
||||
$ws_object->rawHeaders,
|
||||
$config['gotty_host'],
|
||||
$port,
|
||||
'/ws'
|
||||
);
|
||||
|
||||
if ($intUser === null) {
|
||||
$ws_object->disconnect($user->socket);
|
||||
return;
|
||||
}
|
||||
|
||||
// Map user.
|
||||
$user->intUser = $intUser;
|
||||
// And socket.
|
||||
$user->intSocket = $intUser->socket;
|
||||
$user->redirect = $intUser;
|
||||
$intUser->redirect = $user;
|
||||
|
||||
// Keep an eye on changes.
|
||||
$ws_object->remoteSockets[$intUser->id] = $intUser->socket;
|
||||
$ws_object->remoteUsers[$intUser->id] = $intUser;
|
||||
|
||||
// Ignore. Cleanup socket.
|
||||
$response = $ws_object->readSocket($user->intUser);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Redirects input from user to redirection stabished.
|
||||
*
|
||||
* @param WSManager $ws_object Main WebSocket manager object.
|
||||
* @param WebSocketUser $user WebSocket user.
|
||||
* @param string $buffer Buffer.
|
||||
*
|
||||
* @return boolean Ok or not.
|
||||
*/
|
||||
function proxyProcessRaw($ws_object, $user, $buffer)
|
||||
{
|
||||
if (isset($user->redirect) !== true) {
|
||||
$ws_object->disconnect($user->socket);
|
||||
return false;
|
||||
}
|
||||
|
||||
$ws_object->stderr($user->id.' >> '.$user->redirect->id);
|
||||
$ws_object->stderr($ws_object->dump($buffer));
|
||||
$ws_object->writeSocket($user->redirect, $buffer);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ============================================================================
|
||||
* * ENDS: GOTTY PROTOCOL: PROXY
|
||||
* ============================================================================
|
||||
*/
|
|
@ -308,8 +308,7 @@ return array(
|
|||
'Mpdf\\Utils\\PdfDate' => $vendorDir . '/mpdf/mpdf/src/Utils/PdfDate.php',
|
||||
'Mpdf\\Utils\\UtfString' => $vendorDir . '/mpdf/mpdf/src/Utils/UtfString.php',
|
||||
'PandoraFMS\\User' => $baseDir . '/include/lib/User.php',
|
||||
'PandoraFMS\\WebSockets\\WSProxy' => $baseDir . '/include/lib/WSProxy.php',
|
||||
'PandoraFMS\\WebSockets\\WSProxyUser' => $baseDir . '/include/lib/WSProxyUser.php',
|
||||
'PandoraFMS\\WebSockets\\WSManager' => $baseDir . '/include/lib/WSManager.php',
|
||||
'PandoraFMS\\Websockets\\WebSocketServer' => $baseDir . '/include/lib/WebSocketServer.php',
|
||||
'PandoraFMS\\Websockets\\WebSocketUser' => $baseDir . '/include/lib/WebSocketUser.php',
|
||||
'Psr\\Log\\AbstractLogger' => $vendorDir . '/psr/log/Psr/Log/AbstractLogger.php',
|
||||
|
|
|
@ -390,8 +390,7 @@ class ComposerStaticInitfdecadadce22e6dde51e9535fe4ad7aa
|
|||
'Mpdf\\Utils\\PdfDate' => __DIR__ . '/..' . '/mpdf/mpdf/src/Utils/PdfDate.php',
|
||||
'Mpdf\\Utils\\UtfString' => __DIR__ . '/..' . '/mpdf/mpdf/src/Utils/UtfString.php',
|
||||
'PandoraFMS\\User' => __DIR__ . '/../..' . '/include/lib/User.php',
|
||||
'PandoraFMS\\WebSockets\\WSProxy' => __DIR__ . '/../..' . '/include/lib/WSProxy.php',
|
||||
'PandoraFMS\\WebSockets\\WSProxyUser' => __DIR__ . '/../..' . '/include/lib/WSProxyUser.php',
|
||||
'PandoraFMS\\WebSockets\\WSManager' => __DIR__ . '/../..' . '/include/lib/WSManager.php',
|
||||
'PandoraFMS\\Websockets\\WebSocketServer' => __DIR__ . '/../..' . '/include/lib/WebSocketServer.php',
|
||||
'PandoraFMS\\Websockets\\WebSocketUser' => __DIR__ . '/../..' . '/include/lib/WebSocketUser.php',
|
||||
'Psr\\Log\\AbstractLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/AbstractLogger.php',
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
// Begin.
|
||||
require_once __DIR__.'/vendor/autoload.php';
|
||||
use \PandoraFMS\WebSockets\WSProxy;
|
||||
use \PandoraFMS\WebSockets\WSManager;
|
||||
|
||||
// Set to true to get full output.
|
||||
$debug = false;
|
||||
|
@ -48,10 +48,11 @@ $_SERVER['DOCUMENT_ROOT'] = __DIR__.'/../';
|
|||
|
||||
// Don't start a session before this import.
|
||||
// The session is configured and started inside the config process.
|
||||
require_once 'include/config.php';
|
||||
require_once 'include/functions.php';
|
||||
require_once 'include/functions_db.php';
|
||||
require_once 'include/auth/mysql.php';
|
||||
require_once __DIR__.'/include/config.php';
|
||||
require_once __DIR__.'/include/functions.php';
|
||||
require_once __DIR__.'/include/functions_db.php';
|
||||
require_once __DIR__.'/include/auth/mysql.php';
|
||||
require_once __DIR__.'/include/websocket_registrations.php';
|
||||
|
||||
// Enterprise support.
|
||||
if (file_exists(ENTERPRISE_DIR.'/load_enterprise.php') === true) {
|
||||
|
@ -67,7 +68,23 @@ if (isset($_SERVER['REMOTE_ADDR']) === true) {
|
|||
|
||||
|
||||
if (isset($config['ws_port']) === false) {
|
||||
config_update_value('ws_port', 8081);
|
||||
config_update_value('ws_port', 8080);
|
||||
}
|
||||
|
||||
if (isset($config['ws_bind_address']) === false) {
|
||||
config_update_value('ws_bind_address', '0.0.0.0');
|
||||
}
|
||||
|
||||
if (isset($config['gotty_host']) === false) {
|
||||
config_update_value('gotty_host', '127.0.0.1');
|
||||
}
|
||||
|
||||
if (isset($config['gotty_telnet_port']) === false) {
|
||||
config_update_value('gotty_telnet_port', 8082);
|
||||
}
|
||||
|
||||
if (isset($config['gotty_ssh_port']) === false) {
|
||||
config_update_value('gotty_ssh_port', 8081);
|
||||
}
|
||||
|
||||
if (isset($config['gotty']) === false) {
|
||||
|
@ -80,25 +97,44 @@ error_reporting(E_ALL);
|
|||
|
||||
$os = strtolower(PHP_OS);
|
||||
if (substr($os, 0, 3) !== 'win') {
|
||||
// Launch gotty.
|
||||
$cmd = 'nohup "'.$config['gotty'].'" -a 127.0.0.1 -w /bin/bash';
|
||||
$cmd .= ' >> '.__DIR__.'/pandora_console.log 2>&1 &';
|
||||
// Kill previous gotty running.
|
||||
shell_exec('killall "'.$config['gotty'].'" >/dev/null 2>&1');
|
||||
|
||||
// Common.
|
||||
$base_cmd = 'nohup "'.$config['gotty'].'"';
|
||||
$base_cmd .= ' --permit-arguments -a 127.0.0.1 -w ';
|
||||
|
||||
// Launch gotty - SSH.
|
||||
$cmd = $base_cmd.' --port '.$config['gotty_ssh_port'];
|
||||
$cmd .= ' ssh >> '.__DIR__.'/pandora_console.log 2>&1 &';
|
||||
shell_exec($cmd);
|
||||
|
||||
// Launch gotty - telnet.
|
||||
$cmd = $base_cmd.' --port '.$config['gotty_telnet_port'];
|
||||
$cmd .= ' telnet >> '.__DIR__.'/pandora_console.log 2>&1 &';
|
||||
shell_exec($cmd);
|
||||
}
|
||||
|
||||
// Start Web SocketProxy.
|
||||
$wsproxy = new WSProxy(
|
||||
'0.0.0.0',
|
||||
$ws = new WSManager(
|
||||
// Bind address.
|
||||
$config['ws_bind_address'],
|
||||
// Bind port.
|
||||
$config['ws_port'],
|
||||
'127.0.0.1',
|
||||
'8080',
|
||||
'/ws',
|
||||
// Connected handlers.
|
||||
['gotty' => 'proxyConnected'],
|
||||
// Process handlers.
|
||||
[],
|
||||
// ProcessRaw handlers.
|
||||
['gotty' => 'proxyProcessRaw'],
|
||||
// Tick handlers.
|
||||
[],
|
||||
$bufferSize,
|
||||
$debug
|
||||
);
|
||||
|
||||
try {
|
||||
$wsproxy->run();
|
||||
$ws->run();
|
||||
} catch (Exception $e) {
|
||||
$wsproxy->stdout($e->getMessage());
|
||||
$ws->stdout($e->getMessage());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue