Remove obsolete ClientRequestOld and RpcHandler classes
This commit is contained in:
parent
395e6b95ff
commit
23262bc0a6
5 changed files with 17 additions and 386 deletions
|
@ -2,14 +2,9 @@
|
||||||
|
|
||||||
namespace Socialbox\Abstracts;
|
namespace Socialbox\Abstracts;
|
||||||
|
|
||||||
use Socialbox\Enums\StandardError;
|
|
||||||
use Socialbox\Exceptions\DatabaseOperationException;
|
|
||||||
use Socialbox\Exceptions\StandardException;
|
use Socialbox\Exceptions\StandardException;
|
||||||
use Socialbox\Interfaces\SerializableInterface;
|
use Socialbox\Interfaces\SerializableInterface;
|
||||||
use Socialbox\Managers\SessionManager;
|
|
||||||
use Socialbox\Objects\ClientRequest;
|
use Socialbox\Objects\ClientRequest;
|
||||||
use Socialbox\Objects\ClientRequestOld;
|
|
||||||
use Socialbox\Objects\Database\SessionRecord;
|
|
||||||
use Socialbox\Objects\RpcRequest;
|
use Socialbox\Objects\RpcRequest;
|
||||||
|
|
||||||
abstract class Method
|
abstract class Method
|
||||||
|
|
|
@ -1,198 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Socialbox\Classes;
|
|
||||||
|
|
||||||
use Exception;
|
|
||||||
use InvalidArgumentException;
|
|
||||||
use RuntimeException;
|
|
||||||
use Socialbox\Enums\StandardHeaders;
|
|
||||||
use Socialbox\Exceptions\DatabaseOperationException;
|
|
||||||
use Socialbox\Exceptions\RequestException;
|
|
||||||
use Socialbox\Exceptions\RpcException;
|
|
||||||
use Socialbox\Exceptions\StandardException;
|
|
||||||
use Socialbox\Managers\SessionManager;
|
|
||||||
use Socialbox\Objects\ClientRequestOld;
|
|
||||||
use Socialbox\Objects\RpcRequest;
|
|
||||||
|
|
||||||
class RpcHandler
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Gets the incoming ClientRequest object, validates if the request is valid & if a session UUID is provided
|
|
||||||
* checks if the request signature matches the client's provided public key.
|
|
||||||
*
|
|
||||||
* @return ClientRequestOld The parsed ClientRequest object
|
|
||||||
* @throws RequestException
|
|
||||||
* @throws RpcException Thrown if the request is invalid
|
|
||||||
*/
|
|
||||||
public static function getClientRequest(): ClientRequestOld
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
$headers = Utilities::getRequestHeaders();
|
|
||||||
foreach(StandardHeaders::getRequiredHeaders() as $header)
|
|
||||||
{
|
|
||||||
if (!isset($headers[$header]))
|
|
||||||
{
|
|
||||||
throw new RequestException("Missing required header: $header", 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate the headers
|
|
||||||
switch(StandardHeaders::tryFrom($header))
|
|
||||||
{
|
|
||||||
case StandardHeaders::CLIENT_VERSION:
|
|
||||||
if($headers[$header] !== '1.0')
|
|
||||||
{
|
|
||||||
throw new RpcException(sprintf("Unsupported Client Version: %s", $headers[$header]));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case StandardHeaders::CONTENT_TYPE:
|
|
||||||
if(!str_contains($headers[$header], 'application/json'))
|
|
||||||
{
|
|
||||||
throw new RpcException(sprintf("Invalid Content-Type header: Expected application/json, got %s", $headers[$header]), 400);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case StandardHeaders::FROM_PEER:
|
|
||||||
if(!Validator::validatePeerAddress($headers[$header]))
|
|
||||||
{
|
|
||||||
throw new RpcException("Invalid From-Peer header: " . $headers[$header], 400);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(RuntimeException $e)
|
|
||||||
{
|
|
||||||
throw new RpcException("Failed to parse request: " . $e->getMessage(), 400, $e);
|
|
||||||
}
|
|
||||||
|
|
||||||
$clientRequest = new ClientRequestOld($headers, self::getRpcRequests(), self::getRequestHash());
|
|
||||||
|
|
||||||
// Verify the session & request signature
|
|
||||||
if($clientRequest->getSessionUuid() !== null)
|
|
||||||
{
|
|
||||||
// If no signature is provided, it must be required if the client is providing a Session UUID
|
|
||||||
if($clientRequest->getSignature() === null)
|
|
||||||
{
|
|
||||||
throw new RpcException(sprintf('Unauthorized request, signature required for session based requests'), 401);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
$session = SessionManager::getSession($clientRequest->getSessionUuid());
|
|
||||||
}
|
|
||||||
catch(StandardException $e)
|
|
||||||
{
|
|
||||||
throw new RpcException($e->getMessage(), 400);
|
|
||||||
}
|
|
||||||
catch(DatabaseOperationException $e)
|
|
||||||
{
|
|
||||||
throw new RpcException('Failed to verify session', 500, $e);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if(!Cryptography::verifyContent($clientRequest->getHash(), $clientRequest->getSignature(), $session->getPublicKey()))
|
|
||||||
{
|
|
||||||
throw new RpcException('Request signature check failed', 400);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(RpcException $e)
|
|
||||||
{
|
|
||||||
throw $e;
|
|
||||||
}
|
|
||||||
catch(Exception $e)
|
|
||||||
{
|
|
||||||
throw new RpcException('Request signature check failed (Cryptography Error): ' . $e->getMessage(), 400, $e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $clientRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the request hash by hashing the request body using SHA256
|
|
||||||
*
|
|
||||||
* @return string Returns the request hash in SHA256 representation
|
|
||||||
*/
|
|
||||||
private static function getRequestHash(): string
|
|
||||||
{
|
|
||||||
return hash('sha1', file_get_contents('php://input'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles a POST request, returning an array of RpcRequest objects
|
|
||||||
* expects a JSON encoded body with either a single RpcRequest object or an array of RpcRequest objects
|
|
||||||
*
|
|
||||||
* @return RpcRequest[] The parsed RpcRequest objects
|
|
||||||
* @throws RpcException Thrown if the request is invalid
|
|
||||||
*/
|
|
||||||
private static function getRpcRequests(): array
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Decode the request body
|
|
||||||
$body = Utilities::jsonDecode(file_get_contents('php://input'));
|
|
||||||
}
|
|
||||||
catch(InvalidArgumentException $e)
|
|
||||||
{
|
|
||||||
throw new RpcException("Invalid JSON in request body: " . $e->getMessage(), 400, $e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(isset($body['method']))
|
|
||||||
{
|
|
||||||
// If it only contains a method, we assume it's a single request
|
|
||||||
return [self::parseRequest($body)];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, we assume it's an array of requests
|
|
||||||
return array_map(fn($request) => self::parseRequest($request), $body);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses the raw request data into an RpcRequest object
|
|
||||||
*
|
|
||||||
* @param array $data The raw request data
|
|
||||||
* @return RpcRequest The parsed RpcRequest object
|
|
||||||
* @throws RpcException If the request is invalid
|
|
||||||
*/
|
|
||||||
private static function parseRequest(array $data): RpcRequest
|
|
||||||
{
|
|
||||||
if(!isset($data['method']))
|
|
||||||
{
|
|
||||||
throw new RpcException("Missing 'method' key in request", 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(isset($data['id']))
|
|
||||||
{
|
|
||||||
if(!is_string($data['id']))
|
|
||||||
{
|
|
||||||
throw new RpcException("Invalid 'id' key in request: Expected string", 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(strlen($data['id']) === 0)
|
|
||||||
{
|
|
||||||
throw new RpcException("Invalid 'id' key in request: Expected non-empty string", 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(strlen($data['id']) > 8)
|
|
||||||
{
|
|
||||||
throw new RpcException("Invalid 'id' key in request: Expected string of length <= 8", 400);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(isset($data['parameters']))
|
|
||||||
{
|
|
||||||
if(!is_array($data['parameters']))
|
|
||||||
{
|
|
||||||
throw new RpcException("Invalid 'parameters' key in request: Expected array", 400);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new RpcRequest($data['method'], $data['id'] ?? null, $data['parameters'] ?? null);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,7 +5,6 @@
|
||||||
use Socialbox\Abstracts\Method;
|
use Socialbox\Abstracts\Method;
|
||||||
use Socialbox\Interfaces\SerializableInterface;
|
use Socialbox\Interfaces\SerializableInterface;
|
||||||
use Socialbox\Objects\ClientRequest;
|
use Socialbox\Objects\ClientRequest;
|
||||||
use Socialbox\Objects\ClientRequestOld;
|
|
||||||
use Socialbox\Objects\RpcRequest;
|
use Socialbox\Objects\RpcRequest;
|
||||||
|
|
||||||
class Ping extends Method
|
class Ping extends Method
|
||||||
|
|
|
@ -3,17 +3,14 @@
|
||||||
namespace Socialbox\Classes\StandardMethods;
|
namespace Socialbox\Classes\StandardMethods;
|
||||||
|
|
||||||
use Socialbox\Abstracts\Method;
|
use Socialbox\Abstracts\Method;
|
||||||
use Socialbox\Enums\Flags\PeerFlags;
|
|
||||||
use Socialbox\Enums\Flags\SessionFlags;
|
use Socialbox\Enums\Flags\SessionFlags;
|
||||||
use Socialbox\Enums\StandardError;
|
use Socialbox\Enums\StandardError;
|
||||||
use Socialbox\Exceptions\DatabaseOperationException;
|
use Socialbox\Exceptions\DatabaseOperationException;
|
||||||
use Socialbox\Exceptions\StandardException;
|
use Socialbox\Exceptions\StandardException;
|
||||||
use Socialbox\Interfaces\SerializableInterface;
|
use Socialbox\Interfaces\SerializableInterface;
|
||||||
use Socialbox\Managers\CaptchaManager;
|
use Socialbox\Managers\CaptchaManager;
|
||||||
use Socialbox\Managers\RegisteredPeerManager;
|
|
||||||
use Socialbox\Managers\SessionManager;
|
use Socialbox\Managers\SessionManager;
|
||||||
use Socialbox\Objects\ClientRequest;
|
use Socialbox\Objects\ClientRequest;
|
||||||
use Socialbox\Objects\ClientRequestOld;
|
|
||||||
use Socialbox\Objects\RpcRequest;
|
use Socialbox\Objects\RpcRequest;
|
||||||
|
|
||||||
class VerificationAnswerImageCaptcha extends Method
|
class VerificationAnswerImageCaptcha extends Method
|
||||||
|
|
|
@ -1,162 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Socialbox\Objects;
|
|
||||||
|
|
||||||
use RuntimeException;
|
|
||||||
use Socialbox\Classes\Cryptography;
|
|
||||||
use Socialbox\Enums\SessionState;
|
|
||||||
use Socialbox\Enums\StandardError;
|
|
||||||
use Socialbox\Enums\StandardHeaders;
|
|
||||||
use Socialbox\Exceptions\CryptographyException;
|
|
||||||
use Socialbox\Exceptions\DatabaseOperationException;
|
|
||||||
use Socialbox\Exceptions\StandardException;
|
|
||||||
use Socialbox\Managers\SessionManager;
|
|
||||||
|
|
||||||
class ClientRequestOld
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private array $headers;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var RpcRequest[]
|
|
||||||
*/
|
|
||||||
private array $requests;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private string $requestHash;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ClientRequest constructor.
|
|
||||||
*
|
|
||||||
* @param array $headers The headers of the request
|
|
||||||
* @param RpcRequest[] $requests The RPC requests of the client
|
|
||||||
*/
|
|
||||||
public function __construct(array $headers, array $requests, string $requestHash)
|
|
||||||
{
|
|
||||||
$this->headers = $headers;
|
|
||||||
$this->requests = $requests;
|
|
||||||
$this->requestHash = $requestHash;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function getHeaders(): array
|
|
||||||
{
|
|
||||||
return $this->headers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return RpcRequest[]
|
|
||||||
*/
|
|
||||||
public function getRequests(): array
|
|
||||||
{
|
|
||||||
return $this->requests;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getHash(): string
|
|
||||||
{
|
|
||||||
return $this->requestHash;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getClientName(): string
|
|
||||||
{
|
|
||||||
return $this->headers[StandardHeaders::CLIENT_NAME->value];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getClientVersion(): string
|
|
||||||
{
|
|
||||||
return $this->headers[StandardHeaders::CLIENT_VERSION->value];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getSessionUuid(): ?string
|
|
||||||
{
|
|
||||||
if(!isset($this->headers[StandardHeaders::SESSION_UUID->value]))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->headers[StandardHeaders::SESSION_UUID->value];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getFromPeer(): ?PeerAddress
|
|
||||||
{
|
|
||||||
if(!isset($this->headers[StandardHeaders::FROM_PEER->value]))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return PeerAddress::fromAddress($this->headers[StandardHeaders::FROM_PEER->value]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getSignature(): ?string
|
|
||||||
{
|
|
||||||
if(!isset($this->headers[StandardHeaders::SIGNATURE->value]))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->headers[StandardHeaders::SIGNATURE->value];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function validateSession(): void
|
|
||||||
{
|
|
||||||
if($this->getSessionUuid() == null)
|
|
||||||
{
|
|
||||||
throw new StandardException(StandardError::SESSION_REQUIRED->getMessage(), StandardError::SESSION_REQUIRED);
|
|
||||||
}
|
|
||||||
|
|
||||||
$session = SessionManager::getSession($this->getSessionUuid());
|
|
||||||
|
|
||||||
switch($session->getState())
|
|
||||||
{
|
|
||||||
case SessionState::AWAITING_DHE:
|
|
||||||
throw new StandardException(StandardError::SESSION_DHE_REQUIRED->getMessage(), StandardError::SESSION_DHE_REQUIRED);
|
|
||||||
|
|
||||||
case SessionState::EXPIRED:
|
|
||||||
throw new StandardException(StandardError::SESSION_EXPIRED->getMessage(), StandardError::SESSION_EXPIRED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
* @throws DatabaseOperationException
|
|
||||||
*/
|
|
||||||
public function verifySignature(): bool
|
|
||||||
{
|
|
||||||
$signature = $this->getSignature();
|
|
||||||
$sessionUuid = $this->getSessionUuid();
|
|
||||||
|
|
||||||
if($signature == null || $sessionUuid == null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
$session = SessionManager::getSession($sessionUuid);
|
|
||||||
}
|
|
||||||
catch(StandardException $e)
|
|
||||||
{
|
|
||||||
if($e->getStandardError() == StandardError::SESSION_NOT_FOUND)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new RuntimeException($e);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return Cryptography::verifyContent($this->getHash(), $signature, $session->getPublicKey());
|
|
||||||
}
|
|
||||||
catch(CryptographyException $e)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue