WSProxy ACL check
This commit is contained in:
parent
e24024d2f4
commit
1cf77cc8f1
|
@ -44,8 +44,11 @@ namespace PandoraFMS\WebSockets;
|
|||
|
||||
use \PandoraFMS\Websockets\WebSocketServer;
|
||||
use \PandoraFMS\Websockets\WebSocketUser;
|
||||
use \PandoraFMS\User;
|
||||
|
||||
|
||||
require_once __DIR__.'/../functions.php';
|
||||
|
||||
/**
|
||||
* Redirects ws communication between two endpoints.
|
||||
*/
|
||||
|
@ -86,14 +89,14 @@ class WSProxy extends WebSocketServer
|
|||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $interative = false;
|
||||
protected $interative = true;
|
||||
|
||||
/**
|
||||
* Use a timeout of 0.1 second to search for messages..
|
||||
* Use a timeout of 100 milliseconds to search for messages..
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $timeout = 0.1;
|
||||
public $timeout = 250;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -120,7 +123,7 @@ class WSProxy extends WebSocketServer
|
|||
$this->intPort = $to_port;
|
||||
$this->intUrl = $to_url;
|
||||
$this->maxBufferSize = $bufferLength;
|
||||
$this->interactive = $debug;
|
||||
$this->debug = $debug;
|
||||
$this->userClass = '\\PandoraFMS\\Websockets\\WebSocketUser';
|
||||
parent::__construct($listen_addr, $listen_port, $bufferLength);
|
||||
}
|
||||
|
@ -239,6 +242,36 @@ class WSProxy extends WebSocketServer
|
|||
*/
|
||||
protected function connected($user)
|
||||
{
|
||||
global $config;
|
||||
|
||||
$php_session_id = \str_replace(
|
||||
'PHPSESSID=',
|
||||
'',
|
||||
$user->headers['cookie']
|
||||
);
|
||||
|
||||
$user->account = new User(['phpsessionid' => $php_session_id]);
|
||||
$_SERVER['REMOTE_ADDR'] = $user->address;
|
||||
|
||||
// Ensure user is allowed to connect.
|
||||
if (\check_login(false) === false) {
|
||||
$this->disconnect($user->socket);
|
||||
\db_pandora_audit(
|
||||
'WebSockets engine',
|
||||
'Trying to access websockets engine without a valid session',
|
||||
'N/A'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// User exists, and session is valid.
|
||||
\db_pandora_audit(
|
||||
'WebSockets engine',
|
||||
'WebSocket connection started',
|
||||
$user->account->idUser
|
||||
);
|
||||
$this->stderr('ONLINE '.$user->address.'('.$user->account->idUser.')');
|
||||
|
||||
// Disconnect previous sessions.
|
||||
$this->cleanupSocketByCookie($user);
|
||||
|
||||
|
@ -250,7 +283,7 @@ class WSProxy extends WebSocketServer
|
|||
// Create a new socket connection (internal).
|
||||
$intUser = $this->connectInt($this->rawHeaders);
|
||||
if ($intUser === null) {
|
||||
$this->disconnect($user);
|
||||
$this->disconnect($user->socket);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -293,8 +326,13 @@ class WSProxy extends WebSocketServer
|
|||
*/
|
||||
protected function processRaw($user, $buffer)
|
||||
{
|
||||
$this->stdout(date('D M j G:i:s').' - '.$user->id.' >> '.$user->redirect->id);
|
||||
$this->stdout($this->dump($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;
|
||||
|
@ -304,14 +342,18 @@ class WSProxy extends WebSocketServer
|
|||
/**
|
||||
* Process user message. Implement.
|
||||
*
|
||||
* @param object $user User.
|
||||
* @param string $message Message.
|
||||
* @param object $user User.
|
||||
* @param string $message Message.
|
||||
* @param boolean $str_message String message or not.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function process($user, $message)
|
||||
protected function process($user, $message, $str_message)
|
||||
{
|
||||
|
||||
if ($str_message === true) {
|
||||
$remmitent = $user->address.'('.$user->account->idUser.')';
|
||||
$this->stderr($remmitent.': '.$message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -324,8 +366,22 @@ class WSProxy extends WebSocketServer
|
|||
*/
|
||||
protected function closed($user)
|
||||
{
|
||||
$this->disconnect($user);
|
||||
$this->disconnect($user->redirect);
|
||||
if ($user->account) {
|
||||
$_SERVER['REMOTE_ADDR'] = $user->address;
|
||||
\db_pandora_audit(
|
||||
'WebSockets engine',
|
||||
'WebSocket connection finished',
|
||||
$user->account->idUser
|
||||
);
|
||||
|
||||
$this->stderr('OFFLINE '.$user->address.'('.$user->account->idUser.')');
|
||||
}
|
||||
|
||||
// Ensure both sockets are disconnected.
|
||||
$this->disconnect($user->socket);
|
||||
if ($user->redirect) {
|
||||
$this->disconnect($user->redirect->socket);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -116,12 +116,19 @@ abstract class WebSocketServer
|
|||
protected $heldMessages = [];
|
||||
|
||||
/**
|
||||
* Undocumented variable
|
||||
* Show output.
|
||||
*
|
||||
* @var array
|
||||
* @var boolean
|
||||
*/
|
||||
protected $interactive = true;
|
||||
|
||||
/**
|
||||
* Debug.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $debug = false;
|
||||
|
||||
/**
|
||||
* Undocumented variable
|
||||
*
|
||||
|
@ -195,8 +202,8 @@ abstract class WebSocketServer
|
|||
$__tmp || die('Failed: socket_listen()');
|
||||
|
||||
$this->sockets['m'] = $this->master;
|
||||
$this->stdout("Server started\nListening on: ".$addr.':'.$port."\n");
|
||||
$this->stdout('Master socket: '.$this->master."\n");
|
||||
$this->stderr('Listening on: '.$addr.':'.$port);
|
||||
$this->stderr('Master socket: '.$this->master."\n");
|
||||
|
||||
}
|
||||
|
||||
|
@ -204,12 +211,13 @@ abstract class WebSocketServer
|
|||
/**
|
||||
* Process user message. Implement.
|
||||
*
|
||||
* @param object $user User.
|
||||
* @param string $message Message.
|
||||
* @param object $user User.
|
||||
* @param string $message Message.
|
||||
* @param boolean $str_message String message or not.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
abstract protected function process($user, $message);
|
||||
abstract protected function process($user, $message, $str_message);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -414,7 +422,7 @@ abstract class WebSocketServer
|
|||
$write = null;
|
||||
$this->pTick();
|
||||
$this->tick();
|
||||
socket_select($read, $write, $except, $this->timeout);
|
||||
socket_select($read, $write, $except, 0, $this->timeout);
|
||||
foreach ($read as $socket) {
|
||||
if ($socket == $this->master) {
|
||||
// External to master connection. New client.
|
||||
|
@ -424,9 +432,14 @@ abstract class WebSocketServer
|
|||
continue;
|
||||
} else {
|
||||
$this->connect($client);
|
||||
$this->stdout('Client connected. '.$client);
|
||||
$this->stderr('Client connected. '.$client);
|
||||
}
|
||||
} else {
|
||||
if (!$socket) {
|
||||
$this->disconnect($socket);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Updates on 'read' socket.
|
||||
$numBytes = socket_recv(
|
||||
$socket,
|
||||
|
@ -454,7 +467,7 @@ abstract class WebSocketServer
|
|||
|
||||
$this->doHandshake($user, $buffer);
|
||||
} else {
|
||||
if (!$this->processRaw($user, $buffer)) {
|
||||
if ($this->processRaw($user, $buffer)) {
|
||||
// Split packet into frame and send it to deframe.
|
||||
$this->splitPacket(
|
||||
$numBytes,
|
||||
|
@ -470,7 +483,7 @@ abstract class WebSocketServer
|
|||
// Remote updates.
|
||||
$remotes = $this->remoteSockets;
|
||||
if (count($remotes) > 0) {
|
||||
socket_select($remotes, $write, $except, $this->timeout);
|
||||
socket_select($remotes, $write, $except, 0, $this->timeout);
|
||||
foreach ($remotes as $socket) {
|
||||
// Remote updates - internal. We're client of this sockets.
|
||||
if (!$socket) {
|
||||
|
@ -492,8 +505,6 @@ abstract class WebSocketServer
|
|||
);
|
||||
} else {
|
||||
$user = $this->getUserBySocket($socket);
|
||||
echo '>>>>> EEH, recibo:['.$user->id."]\n";
|
||||
echo $this->dump($buffer);
|
||||
if (!$user) {
|
||||
$this->disconnect($socket);
|
||||
$this->stderr(
|
||||
|
@ -571,7 +582,7 @@ abstract class WebSocketServer
|
|||
|
||||
if ($triggerClosed) {
|
||||
$this->closed($user);
|
||||
$this->stdout(
|
||||
$this->stderr(
|
||||
'Client disconnected. '.$user->socket
|
||||
);
|
||||
socket_close($user->socket);
|
||||
|
@ -912,8 +923,10 @@ abstract class WebSocketServer
|
|||
*/
|
||||
public function stderr($message=null)
|
||||
{
|
||||
if ($this->interactive) {
|
||||
echo $message."\n";
|
||||
if ($this->interactive === true
|
||||
&& $this->debug === true
|
||||
) {
|
||||
echo date('D M j G:i:s').' - '.$message."\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1064,18 +1077,17 @@ abstract class WebSocketServer
|
|||
if ($user->hasSentClose) {
|
||||
$this->disconnect($user->socket);
|
||||
} else {
|
||||
$str_message = false;
|
||||
if ((preg_match('//u', $message))
|
||||
|| ($headers['opcode'] == 2)
|
||||
) {
|
||||
/*
|
||||
* Debug purposes.
|
||||
* $this->stdout("Text msg encoded UTF-8 or Binary msg\n".$message);
|
||||
*/
|
||||
|
||||
$this->process($user, $message);
|
||||
$str_message = true;
|
||||
} else {
|
||||
$this->stderr("not UTF-8\n");
|
||||
$str_message = false;
|
||||
}
|
||||
|
||||
$this->process($user, $message, $str_message);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1152,7 +1164,7 @@ abstract class WebSocketServer
|
|||
default:
|
||||
/*
|
||||
* TODO: fail connection.
|
||||
* $this->disconnect($user);
|
||||
* $this->disconnect($user->socket);
|
||||
*/
|
||||
|
||||
$willClose = true;
|
||||
|
@ -1371,7 +1383,7 @@ abstract class WebSocketServer
|
|||
if ($len > 0) {
|
||||
/*
|
||||
* TODO: fail connection.
|
||||
* $this->disconnect($user);
|
||||
* $this->disconnect($user->socket);
|
||||
*/
|
||||
|
||||
return true;
|
||||
|
|
|
@ -129,6 +129,20 @@ class WebSocketUser
|
|||
*/
|
||||
public $redirect;
|
||||
|
||||
/**
|
||||
* Pandora FMS user account.
|
||||
*
|
||||
* @var User
|
||||
*/
|
||||
public $account;
|
||||
|
||||
/**
|
||||
* Remote address.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $address;
|
||||
|
||||
|
||||
/**
|
||||
* Initializes a websocket user.
|
||||
|
@ -138,6 +152,7 @@ class WebSocketUser
|
|||
*/
|
||||
public function __construct($id, $socket)
|
||||
{
|
||||
socket_getpeername($socket, $this->address);
|
||||
$this->id = $id;
|
||||
$this->socket = $socket;
|
||||
}
|
||||
|
|
|
@ -307,6 +307,7 @@ return array(
|
|||
'Mpdf\\Utils\\NumericString' => $vendorDir . '/mpdf/mpdf/src/Utils/NumericString.php',
|
||||
'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\\WebSocketServer' => $baseDir . '/include/lib/WebSocketServer.php',
|
||||
|
|
|
@ -389,6 +389,7 @@ class ComposerStaticInitfdecadadce22e6dde51e9535fe4ad7aa
|
|||
'Mpdf\\Utils\\NumericString' => __DIR__ . '/..' . '/mpdf/mpdf/src/Utils/NumericString.php',
|
||||
'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\\WebSocketServer' => __DIR__ . '/../..' . '/include/lib/WebSocketServer.php',
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#!/usr/bin/env php
|
||||
<?php
|
||||
/**
|
||||
* PHP script to manage Pandora FMS websockets.
|
||||
|
@ -31,16 +30,66 @@
|
|||
require_once __DIR__.'/vendor/autoload.php';
|
||||
use \PandoraFMS\WebSockets\WSProxy;
|
||||
|
||||
ini_set('display_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
// Set to true to get full output.
|
||||
$debug = false;
|
||||
|
||||
// 1MB.
|
||||
$bufferSize = 1048576;
|
||||
|
||||
if (file_exists(__DIR__.'/include/config.php') === false
|
||||
|| is_readable(__DIR__.'/include/config.php') === false
|
||||
) {
|
||||
echo "Main console configuration file not found.\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
// Simulate.
|
||||
$_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';
|
||||
|
||||
// Enterprise support.
|
||||
if (file_exists(ENTERPRISE_DIR.'/load_enterprise.php') === true) {
|
||||
include_once ENTERPRISE_DIR.'/load_enterprise.php';
|
||||
}
|
||||
|
||||
// Avoid direct access through browsers.
|
||||
if (isset($_SERVER['REMOTE_ADDR']) === true) {
|
||||
// Force redirection.
|
||||
header('Location: '.ui_get_full_url('index.php'));
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
if (isset($config['ws_port']) === false) {
|
||||
config_update_value('ws_port', 8081);
|
||||
}
|
||||
|
||||
if (isset($config['gotty']) === false) {
|
||||
config_update_value('gotty', '/usr/bin/gotty');
|
||||
}
|
||||
|
||||
|
||||
ini_set('display_errors', 1);
|
||||
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 &';
|
||||
shell_exec($cmd);
|
||||
}
|
||||
|
||||
// Start Web SocketProxy.
|
||||
$wsproxy = new WSProxy(
|
||||
'0.0.0.0',
|
||||
'8081',
|
||||
$config['ws_port'],
|
||||
'127.0.0.1',
|
||||
'8080',
|
||||
'/ws',
|
||||
|
@ -49,7 +98,6 @@ $wsproxy = new WSProxy(
|
|||
);
|
||||
|
||||
try {
|
||||
echo "Server running \n";
|
||||
$wsproxy->run();
|
||||
} catch (Exception $e) {
|
||||
$wsproxy->stdout($e->getMessage());
|
||||
|
|
Loading…
Reference in New Issue