Made message signing in Cryptography use SHA512 as the message content for... #1
20 changed files with 523 additions and 662 deletions
|
@ -166,6 +166,10 @@
|
||||||
// value that exceeds this limit, the server will use this limit instead.
|
// value that exceeds this limit, the server will use this limit instead.
|
||||||
// recommendation: 100
|
// recommendation: 100
|
||||||
$config->setDefault('policies.get_contacts_limit', 100);
|
$config->setDefault('policies.get_contacts_limit', 100);
|
||||||
|
$config->setDefault('policies.get_encryption_channel_requests_limit', 100);
|
||||||
|
$config->setDefault('policies.get_encryption_channels_limit', 100);
|
||||||
|
$config->setDefault('policies.get_encryption_channel_incoming_limit', 100);
|
||||||
|
$config->setDefault('policies.get_encryption_channel_outgoing_limit', 100);
|
||||||
|
|
||||||
// Default privacy states for information fields associated with the peer
|
// Default privacy states for information fields associated with the peer
|
||||||
$config->setDefault('policies.default_display_picture_privacy', 'PUBLIC');
|
$config->setDefault('policies.default_display_picture_privacy', 'PUBLIC');
|
||||||
|
|
|
@ -12,6 +12,10 @@
|
||||||
private int $imageCaptchaExpires;
|
private int $imageCaptchaExpires;
|
||||||
private int $peerSyncInterval;
|
private int $peerSyncInterval;
|
||||||
private int $getContactsLimit;
|
private int $getContactsLimit;
|
||||||
|
private int $getEncryptionChannelRequestsLimit;
|
||||||
|
private int $getEncryptionChannelsLimit;
|
||||||
|
private int $getEncryptionChannelIncomingLimit;
|
||||||
|
private int $getEncryptionChannelOutgoingLimit;
|
||||||
private PrivacyState $defaultDisplayPicturePrivacy;
|
private PrivacyState $defaultDisplayPicturePrivacy;
|
||||||
private PrivacyState $defaultFirstNamePrivacy;
|
private PrivacyState $defaultFirstNamePrivacy;
|
||||||
private PrivacyState $defaultMiddleNamePrivacy;
|
private PrivacyState $defaultMiddleNamePrivacy;
|
||||||
|
@ -43,6 +47,10 @@
|
||||||
$this->imageCaptchaExpires = $data['image_captcha_expires'];
|
$this->imageCaptchaExpires = $data['image_captcha_expires'];
|
||||||
$this->peerSyncInterval = $data['peer_sync_interval'];
|
$this->peerSyncInterval = $data['peer_sync_interval'];
|
||||||
$this->getContactsLimit = $data['get_contacts_limit'];
|
$this->getContactsLimit = $data['get_contacts_limit'];
|
||||||
|
$this->getEncryptionChannelRequestsLimit = $data['get_encryption_channel_requests_limit'];
|
||||||
|
$this->getEncryptionChannelsLimit = $data['get_encryption_channels_limit'];
|
||||||
|
$this->getEncryptionChannelIncomingLimit = $data['get_encryption_channel_incoming_limit'];
|
||||||
|
$this->getEncryptionChannelOutgoingLimit = $data['get_encryption_channel_outgoing_limit'];
|
||||||
$this->defaultDisplayPicturePrivacy = PrivacyState::tryFrom($data['default_display_picture_privacy']) ?? PrivacyState::PRIVATE;
|
$this->defaultDisplayPicturePrivacy = PrivacyState::tryFrom($data['default_display_picture_privacy']) ?? PrivacyState::PRIVATE;
|
||||||
$this->defaultFirstNamePrivacy = PrivacyState::tryFrom($data['default_first_name_privacy']) ?? PrivacyState::PRIVATE;
|
$this->defaultFirstNamePrivacy = PrivacyState::tryFrom($data['default_first_name_privacy']) ?? PrivacyState::PRIVATE;
|
||||||
$this->defaultMiddleNamePrivacy = PrivacyState::tryFrom($data['default_middle_name_privacy']) ?? PrivacyState::PRIVATE;
|
$this->defaultMiddleNamePrivacy = PrivacyState::tryFrom($data['default_middle_name_privacy']) ?? PrivacyState::PRIVATE;
|
||||||
|
@ -110,6 +118,46 @@
|
||||||
return $this->getContactsLimit;
|
return $this->getContactsLimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the maximum number of encryption channel requests that can be retrieved in a single request
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getEncryptionChannelRequestsLimit(): int
|
||||||
|
{
|
||||||
|
return $this->getEncryptionChannelRequestsLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the maximum number of encryption channels that can be retrieved in a single request
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getEncryptionChannelsLimit(): int
|
||||||
|
{
|
||||||
|
return $this->getEncryptionChannelsLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the maximum number of incoming encryption channels that can be retrieved in a single request
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getEncryptionChannelIncomingLimit(): int
|
||||||
|
{
|
||||||
|
return $this->getEncryptionChannelIncomingLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the maximum number of outgoing encryption channels that can be retrieved in a single request
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getEncryptionChannelOutgoingLimit(): int
|
||||||
|
{
|
||||||
|
return $this->getEncryptionChannelOutgoingLimit;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the default privacy state for the display picture
|
* Returns the default privacy state for the display picture
|
||||||
*
|
*
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
use Socialbox\Exceptions\DatabaseOperationException;
|
use Socialbox\Exceptions\DatabaseOperationException;
|
||||||
use Socialbox\Exceptions\ResolutionException;
|
use Socialbox\Exceptions\ResolutionException;
|
||||||
use Socialbox\Exceptions\RpcException;
|
use Socialbox\Exceptions\RpcException;
|
||||||
|
use Socialbox\Objects\Client\EncryptionChannelSecret;
|
||||||
use Socialbox\Objects\Client\ExportedSession;
|
use Socialbox\Objects\Client\ExportedSession;
|
||||||
use Socialbox\Objects\Client\SignatureKeyPair;
|
use Socialbox\Objects\Client\SignatureKeyPair;
|
||||||
use Socialbox\Objects\KeyPair;
|
use Socialbox\Objects\KeyPair;
|
||||||
|
@ -39,6 +40,7 @@
|
||||||
private string $sessionUuid;
|
private string $sessionUuid;
|
||||||
private ?string $defaultSigningKey;
|
private ?string $defaultSigningKey;
|
||||||
private array $signingKeys;
|
private array $signingKeys;
|
||||||
|
private array $encryptionChannelSecrets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new instance with the specified peer address.
|
* Constructs a new instance with the specified peer address.
|
||||||
|
@ -78,6 +80,7 @@
|
||||||
$this->serverTransportEncryptionKey = $exportedSession->getServerTransportEncryptionKey();
|
$this->serverTransportEncryptionKey = $exportedSession->getServerTransportEncryptionKey();
|
||||||
$this->signingKeys = $exportedSession->getSigningKeys();
|
$this->signingKeys = $exportedSession->getSigningKeys();
|
||||||
$this->defaultSigningKey = $exportedSession->getDefaultSigningKey();
|
$this->defaultSigningKey = $exportedSession->getDefaultSigningKey();
|
||||||
|
$this->encryptionChannelSecrets = $exportedSession->getEncryptionChannelSecrets();
|
||||||
|
|
||||||
// Still solve the server information
|
// Still solve the server information
|
||||||
$this->serverInformation = self::getServerInformation();
|
$this->serverInformation = self::getServerInformation();
|
||||||
|
@ -107,6 +110,7 @@
|
||||||
|
|
||||||
// Set the initial properties
|
// Set the initial properties
|
||||||
$this->signingKeys = [];
|
$this->signingKeys = [];
|
||||||
|
$this->encryptionChannelSecrets = [];
|
||||||
$this->defaultSigningKey = null;
|
$this->defaultSigningKey = null;
|
||||||
$this->identifiedAs = $identifiedAs;
|
$this->identifiedAs = $identifiedAs;
|
||||||
$this->remoteServer = $server ?? $identifiedAs->getDomain();
|
$this->remoteServer = $server ?? $identifiedAs->getDomain();
|
||||||
|
@ -771,6 +775,17 @@
|
||||||
return $this->signingKeys[$uuid] ?? null;
|
return $this->signingKeys[$uuid] ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a signing key from the current instance.
|
||||||
|
*
|
||||||
|
* @param string $uuid The UUID of the signing key to be deleted.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function deleteSigningKey(string $uuid): void
|
||||||
|
{
|
||||||
|
unset($this->signingKeys[$uuid]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the default signing key associated with the current instance.
|
* Retrieves the default signing key associated with the current instance.
|
||||||
*
|
*
|
||||||
|
@ -797,6 +812,71 @@
|
||||||
$this->defaultSigningKey = $uuid;
|
$this->defaultSigningKey = $uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the encryption channel keys associated with the current instance.
|
||||||
|
*
|
||||||
|
* @return EncryptionChannelSecret[] The encryption channel keys.
|
||||||
|
*/
|
||||||
|
public function getEncryptionChannelSecrets(): array
|
||||||
|
{
|
||||||
|
return $this->encryptionChannelSecrets;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new encryption channel key to the current instance.
|
||||||
|
*
|
||||||
|
* @param EncryptionChannelSecret $key The encryption channel key to be added.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function addEncryptionChannelSecret(EncryptionChannelSecret $key): void
|
||||||
|
{
|
||||||
|
$this->encryptionChannelSecrets[$key->getChannelUuid()] = $key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes an encryption channel key from the current instance.
|
||||||
|
*
|
||||||
|
* @param string $uuid The UUID of the encryption channel key to be removed.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function removeEncryptionChannelKey(string $uuid): void
|
||||||
|
{
|
||||||
|
unset($this->encryptionChannelSecrets[$uuid]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the encryption channel key associated with the specified UUID.
|
||||||
|
*
|
||||||
|
* @param string $uuid The UUID of the encryption channel key to be retrieved.
|
||||||
|
* @return EncryptionChannelSecret|null The encryption channel key associated with the UUID, or null if not found.
|
||||||
|
*/
|
||||||
|
public function getEncryptionChannelKey(string $uuid): ?EncryptionChannelSecret
|
||||||
|
{
|
||||||
|
return $this->encryptionChannelSecrets[$uuid] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if an encryption channel key exists with the specified UUID.
|
||||||
|
*
|
||||||
|
* @param string $uuid The UUID of the encryption channel key to check.
|
||||||
|
* @return bool True if the encryption channel key exists, false otherwise.
|
||||||
|
*/
|
||||||
|
public function encryptionChannelKeyExists(string $uuid): bool
|
||||||
|
{
|
||||||
|
return isset($this->encryptionChannelSecrets[$uuid]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes an encryption channel key from the current instance.
|
||||||
|
*
|
||||||
|
* @param string $uuid The UUID of the encryption channel key to be deleted.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function deleteEncryptionChannelKey(string $uuid): void
|
||||||
|
{
|
||||||
|
unset($this->encryptionChannelSecrets[$uuid]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exports the current session details into an ExportedSession object.
|
* Exports the current session details into an ExportedSession object.
|
||||||
*
|
*
|
||||||
|
@ -821,7 +901,8 @@
|
||||||
'client_transport_encryption_key' => $this->clientTransportEncryptionKey,
|
'client_transport_encryption_key' => $this->clientTransportEncryptionKey,
|
||||||
'server_transport_encryption_key' => $this->serverTransportEncryptionKey,
|
'server_transport_encryption_key' => $this->serverTransportEncryptionKey,
|
||||||
'default_signing_key' => $this->defaultSigningKey,
|
'default_signing_key' => $this->defaultSigningKey,
|
||||||
'signing_keys' => array_map(fn(SignatureKeyPair $key) => $key->toArray(), $this->signingKeys)
|
'signing_keys' => array_map(fn(SignatureKeyPair $key) => $key->toArray(), $this->signingKeys),
|
||||||
|
'encryption_channel_secrets' => array_map(fn(EncryptionChannelSecret $key) => $key->toArray(), $this->encryptionChannelSecrets)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,6 +5,7 @@
|
||||||
use Exception;
|
use Exception;
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
use Socialbox\Abstracts\Method;
|
use Socialbox\Abstracts\Method;
|
||||||
|
use Socialbox\Classes\Validator;
|
||||||
use Socialbox\Enums\StandardError;
|
use Socialbox\Enums\StandardError;
|
||||||
use Socialbox\Exceptions\Standard\InvalidRpcArgumentException;
|
use Socialbox\Exceptions\Standard\InvalidRpcArgumentException;
|
||||||
use Socialbox\Exceptions\Standard\MissingRpcArgumentException;
|
use Socialbox\Exceptions\Standard\MissingRpcArgumentException;
|
||||||
|
@ -16,7 +17,7 @@
|
||||||
use Socialbox\Socialbox;
|
use Socialbox\Socialbox;
|
||||||
use Symfony\Component\Uid\Uuid;
|
use Symfony\Component\Uid\Uuid;
|
||||||
|
|
||||||
class ResolvePeerSignature extends Method
|
class ResolveSignature extends Method
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,30 +31,17 @@
|
||||||
throw new MissingRpcArgumentException('peer');
|
throw new MissingRpcArgumentException('peer');
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!$rpcRequest->containsParameter('uuid'))
|
if(!$rpcRequest->containsParameter('signature_uuid'))
|
||||||
{
|
{
|
||||||
throw new MissingRpcArgumentException('uuid');
|
throw new MissingRpcArgumentException('signature_uuid');
|
||||||
|
}
|
||||||
|
elseif(!Validator::validateUuid($rpcRequest->getParameter('signature_uuid')))
|
||||||
|
{
|
||||||
|
throw new InvalidRpcArgumentException('signature_uuid', 'Invalid UUID V4');
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
return $rpcRequest->produceResponse(Socialbox::resolvePeerSignature(
|
||||||
{
|
$rpcRequest->getParameter('peer'), $rpcRequest->getParameter('signature_uuid')
|
||||||
$uuid = Uuid::fromString($rpcRequest->getParameter('uuid'));
|
));
|
||||||
}
|
|
||||||
catch(InvalidArgumentException $e)
|
|
||||||
{
|
|
||||||
throw new InvalidRpcArgumentException('uuid', $e);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the peer address
|
|
||||||
try
|
|
||||||
{
|
|
||||||
$peerAddress = PeerAddress::fromAddress($rpcRequest->getParameter('peer'));
|
|
||||||
}
|
|
||||||
catch(InvalidArgumentException $e)
|
|
||||||
{
|
|
||||||
throw new InvalidRpcArgumentException('peer', $e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $rpcRequest->produceResponse(Socialbox::resolvePeerSignature($peerAddress, $uuid->toRfc4122()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
use Socialbox\Objects\RpcRequest;
|
use Socialbox\Objects\RpcRequest;
|
||||||
use Socialbox\Socialbox;
|
use Socialbox\Socialbox;
|
||||||
|
|
||||||
class VerifyPeerSignature extends Method
|
class VerifySignature extends Method
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,11 +37,6 @@
|
||||||
throw new InvalidRpcArgumentException('signature_uuid', 'Invalid UUID V4');
|
throw new InvalidRpcArgumentException('signature_uuid', 'Invalid UUID V4');
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!$rpcRequest->containsParameter('signature_public_key'))
|
|
||||||
{
|
|
||||||
throw new MissingRpcArgumentException('signature_public_key');
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!$rpcRequest->containsParameter('signature'))
|
if(!$rpcRequest->containsParameter('signature'))
|
||||||
{
|
{
|
||||||
throw new MissingRpcArgumentException('signature');
|
throw new MissingRpcArgumentException('signature');
|
||||||
|
@ -66,27 +61,25 @@
|
||||||
throw new InvalidRpcArgumentException('peer', $e);
|
throw new InvalidRpcArgumentException('peer', $e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if($rpcRequest->containsParameter('signature_time'))
|
if($rpcRequest->containsParameter('time'))
|
||||||
{
|
{
|
||||||
if(!is_numeric($rpcRequest->getParameter('signature_time')))
|
if(!is_numeric($rpcRequest->getParameter('time')))
|
||||||
{
|
{
|
||||||
throw new InvalidRpcArgumentException('signature_time', 'Invalid timestamp, must be a Unix Timestamp');
|
throw new InvalidRpcArgumentException('time', 'Invalid timestamp, must be a Unix Timestamp');
|
||||||
}
|
}
|
||||||
|
|
||||||
return $rpcRequest->produceResponse(Socialbox::verifyTimedSignature(
|
return $rpcRequest->produceResponse(Socialbox::verifyTimedSignature(
|
||||||
signingPeer: $peerAddress,
|
signingPeer: $peerAddress,
|
||||||
signatureUuid: $rpcRequest->getParameter('signature_uuid'),
|
signatureUuid: $rpcRequest->getParameter('signature_uuid'),
|
||||||
signatureKey: $rpcRequest->getParameter('signature_public_key'),
|
|
||||||
signature: $rpcRequest->getParameter('signature'),
|
signature: $rpcRequest->getParameter('signature'),
|
||||||
messageHash: $rpcRequest->getParameter('sha512'),
|
messageHash: $rpcRequest->getParameter('sha512'),
|
||||||
signatureTime: (int)$rpcRequest->getParameter('signature_time')
|
signatureTime: (int)$rpcRequest->getParameter('time')
|
||||||
)->value);
|
)->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $rpcRequest->produceResponse(Socialbox::verifySignature(
|
return $rpcRequest->produceResponse(Socialbox::verifySignature(
|
||||||
signingPeer: $peerAddress,
|
signingPeer: $peerAddress,
|
||||||
signatureUuid: $rpcRequest->getParameter('signature_uuid'),
|
signatureUuid: $rpcRequest->getParameter('signature_uuid'),
|
||||||
signatureKey: $rpcRequest->getParameter('signature_public_key'),
|
|
||||||
signature: $rpcRequest->getParameter('signature'),
|
signature: $rpcRequest->getParameter('signature'),
|
||||||
messageHash: $rpcRequest->getParameter('sha512'),
|
messageHash: $rpcRequest->getParameter('sha512'),
|
||||||
)->value);
|
)->value);
|
|
@ -1,31 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Socialbox\Classes\StandardMethods\Encryption;
|
|
||||||
|
|
||||||
use Exception;
|
|
||||||
use InvalidArgumentException;
|
|
||||||
use Socialbox\Abstracts\Method;
|
|
||||||
use Socialbox\Classes\Cryptography;
|
|
||||||
use Socialbox\Classes\Validator;
|
|
||||||
use Socialbox\Enums\ReservedUsernames;
|
|
||||||
use Socialbox\Enums\StandardError;
|
|
||||||
use Socialbox\Exceptions\Standard\InvalidRpcArgumentException;
|
|
||||||
use Socialbox\Exceptions\Standard\MissingRpcArgumentException;
|
|
||||||
use Socialbox\Exceptions\Standard\StandardRpcException;
|
|
||||||
use Socialbox\Interfaces\SerializableInterface;
|
|
||||||
use Socialbox\Managers\EncryptionChannelManager;
|
|
||||||
use Socialbox\Objects\ClientRequest;
|
|
||||||
use Socialbox\Objects\PeerAddress;
|
|
||||||
use Socialbox\Objects\RpcRequest;
|
|
||||||
|
|
||||||
class EncryptionAcceptChannel extends Method
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
public static function execute(ClientRequest $request, RpcRequest $rpcRequest): ?SerializableInterface
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,317 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Socialbox\Classes\StandardMethods\Encryption;
|
|
||||||
|
|
||||||
use Exception;
|
|
||||||
use InvalidArgumentException;
|
|
||||||
use Socialbox\Abstracts\Method;
|
|
||||||
use Socialbox\Classes\Configuration;
|
|
||||||
use Socialbox\Classes\Cryptography;
|
|
||||||
use Socialbox\Classes\Validator;
|
|
||||||
use Socialbox\Enums\ReservedUsernames;
|
|
||||||
use Socialbox\Enums\SigningKeyState;
|
|
||||||
use Socialbox\Enums\StandardError;
|
|
||||||
use Socialbox\Exceptions\DatabaseOperationException;
|
|
||||||
use Socialbox\Exceptions\Standard\InvalidRpcArgumentException;
|
|
||||||
use Socialbox\Exceptions\Standard\MissingRpcArgumentException;
|
|
||||||
use Socialbox\Exceptions\Standard\StandardRpcException;
|
|
||||||
use Socialbox\Interfaces\SerializableInterface;
|
|
||||||
use Socialbox\Managers\EncryptionChannelManager;
|
|
||||||
use Socialbox\Objects\ClientRequest;
|
|
||||||
use Socialbox\Objects\PeerAddress;
|
|
||||||
use Socialbox\Objects\RpcRequest;
|
|
||||||
use Socialbox\Objects\Standard\Signature;
|
|
||||||
use Socialbox\Socialbox;
|
|
||||||
|
|
||||||
class EncryptionCreateChannel extends Method
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
public static function execute(ClientRequest $request, RpcRequest $rpcRequest): ?SerializableInterface
|
|
||||||
{
|
|
||||||
// Check the calling peer, if a server is making the request, it must be identified
|
|
||||||
// Otherwise, we assume the authenticated user is the calling peer
|
|
||||||
// But a server must provide a UUID. This is to prevent a user from creating a channel with a UUID
|
|
||||||
$callingPeer = self::getCallingPeer($request, $rpcRequest);
|
|
||||||
$callingPeerSignature = self::getCallingSignature($callingPeer, $rpcRequest);
|
|
||||||
$receivingPeer = self::getReceivingPeer($rpcRequest);
|
|
||||||
$receivingPeerSignature = self::getReceivingSignature($receivingPeer, $rpcRequest);
|
|
||||||
$channelUuid = self::getChannelUuid($request, $rpcRequest);
|
|
||||||
|
|
||||||
// Verify the calling encryption public key
|
|
||||||
if(!$rpcRequest->containsParameter('calling_encryption_public_key'))
|
|
||||||
{
|
|
||||||
throw new MissingRpcArgumentException('calling_encryption_public_key');
|
|
||||||
}
|
|
||||||
if(!Cryptography::validatePublicEncryptionKey($rpcRequest->getParameter('calling_encryption_public_key')))
|
|
||||||
{
|
|
||||||
throw new InvalidRpcArgumentException('calling_encryption_public_key', 'Invalid calling encryption public key');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transport Algorithm Validation
|
|
||||||
if(!$rpcRequest->containsParameter('transport_encryption_algorithm'))
|
|
||||||
{
|
|
||||||
throw new MissingRpcArgumentException('transport_encryption_algorithm');
|
|
||||||
}
|
|
||||||
if(!Cryptography::isSupportedAlgorithm($rpcRequest->getParameter('transport_encryption_algorithm')))
|
|
||||||
{
|
|
||||||
throw new InvalidRpcArgumentException('transport_encryption_algorithm', 'Unsupported Transport Encryption Algorithm');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create/Import the encryption channel
|
|
||||||
try
|
|
||||||
{
|
|
||||||
$channelUuid = EncryptionChannelManager::createChannel(
|
|
||||||
callingPeer: $callingPeer,
|
|
||||||
receivingPeer: $receivingPeer,
|
|
||||||
signatureUuid: $callingPeerSignature->getUuid(),
|
|
||||||
signingPublicKey: $callingPeerSignature->getPublicKey(),
|
|
||||||
encryptionPublicKey: $rpcRequest->getParameter('calling_encryption_public_key'),
|
|
||||||
transportEncryptionAlgorithm: $rpcRequest->getParameter('transport_encryption_algorithm'),
|
|
||||||
uuid: $channelUuid
|
|
||||||
);
|
|
||||||
}
|
|
||||||
catch (DatabaseOperationException $e)
|
|
||||||
{
|
|
||||||
throw new StandardRpcException('Failed to create the encryption channel', StandardError::INTERNAL_SERVER_ERROR, $e);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the receiving peer resides on an external server, then we need to tell the external server
|
|
||||||
// about the encryption channel so that the receiving peer can see it.
|
|
||||||
if($receivingPeer->getDomain() !== Configuration::getInstanceConfiguration()->getDomain())
|
|
||||||
{
|
|
||||||
$rpcClient = Socialbox::getExternalSession($receivingPeer->getDomain());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return $rpcRequest->produceResponse($channelUuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the PeerAddress of the calling peer, if a server is making a request then the server must provide
|
|
||||||
* both the UUID of the encryption channel and the PeerAddress of the calling peer to prevent UUID conflicts
|
|
||||||
*
|
|
||||||
* Otherwise, the calling peer is assumed to be the authenticated user and no UUID is required
|
|
||||||
*
|
|
||||||
* @param ClientRequest $request The full client request
|
|
||||||
* @param RpcRequest $rpcRequest The focused RPC request
|
|
||||||
* @return PeerAddress The calling peer
|
|
||||||
* @throws StandardRpcException If the calling peer cannot be resolved
|
|
||||||
*/
|
|
||||||
private static function getCallingPeer(ClientRequest $request, RpcRequest $rpcRequest): PeerAddress
|
|
||||||
{
|
|
||||||
if($request->getIdentifyAs() !== null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Prevent UUID conflicts if the server is trying to use an UUID that already exists on this server
|
|
||||||
if (EncryptionChannelManager::channelExists($rpcRequest->getParameter('uuid')))
|
|
||||||
{
|
|
||||||
throw new StandardRpcException('UUID Conflict, a channel with this UUID already exists', StandardError::UUID_CONFLICT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (DatabaseOperationException $e)
|
|
||||||
{
|
|
||||||
throw new StandardRpcException('Failed to resolve channel UUID', StandardError::INTERNAL_SERVER_ERROR, $e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if($request->getIdentifyAs()->getUsername() == ReservedUsernames::HOST)
|
|
||||||
{
|
|
||||||
throw new StandardRpcException('The identifier cannot be a host', StandardError::BAD_REQUEST);
|
|
||||||
}
|
|
||||||
|
|
||||||
if($request->getIdentifyAs()->getDomain() !== Configuration::getInstanceConfiguration()->getDomain())
|
|
||||||
{
|
|
||||||
Socialbox::resolvePeer($request->getIdentifyAs());
|
|
||||||
}
|
|
||||||
|
|
||||||
return $request->getIdentifyAs();
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return PeerAddress::fromAddress($request->getPeer()->getAddress());
|
|
||||||
}
|
|
||||||
catch(StandardRpcException $e)
|
|
||||||
{
|
|
||||||
throw $e;
|
|
||||||
}
|
|
||||||
catch(Exception $e)
|
|
||||||
{
|
|
||||||
throw new StandardRpcException('The calling peer cannot be resolved', StandardError::INTERNAL_SERVER_ERROR, $e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolves and returns the calling peer's signing key, if the calling peer is coming from an external server
|
|
||||||
* then the signature returned is the resolved signature from the external server, otherwise the signature
|
|
||||||
* is locally resolved and returned
|
|
||||||
*
|
|
||||||
* @param PeerAddress $callingPeer The calling peer
|
|
||||||
* @param RpcRequest $rpcRequest The focused RPC request
|
|
||||||
* @return Signature The resolved signing key
|
|
||||||
* @throws InvalidRpcArgumentException If one or more RPC parameters are invalid
|
|
||||||
* @throws MissingRpcArgumentException If one or more RPC parameters are missing
|
|
||||||
* @throws StandardRpcException If the calling signature cannot be resolved
|
|
||||||
*/
|
|
||||||
private static function getCallingSignature(PeerAddress $callingPeer, RpcRequest $rpcRequest): Signature
|
|
||||||
{
|
|
||||||
// Caller signature verification
|
|
||||||
if(!$rpcRequest->containsParameter('calling_signature_uuid'))
|
|
||||||
{
|
|
||||||
throw new MissingRpcArgumentException('calling_signature_uuid');
|
|
||||||
}
|
|
||||||
if(!Validator::validateUuid($rpcRequest->getParameter('calling_signature_uuid')))
|
|
||||||
{
|
|
||||||
throw new InvalidRpcArgumentException('calling_signature_uuid', 'Invalid UUID V4');
|
|
||||||
}
|
|
||||||
if(!$rpcRequest->containsParameter('calling_signature_public_key'))
|
|
||||||
{
|
|
||||||
throw new MissingRpcArgumentException('calling_signature_public_key');
|
|
||||||
}
|
|
||||||
if(!Cryptography::validatePublicSigningKey($rpcRequest->getParameter('calling_signature_public_key')))
|
|
||||||
{
|
|
||||||
throw new InvalidRpcArgumentException('calling_signature_public_key', 'Invalid Public Key');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resolve the signature
|
|
||||||
$resolvedCallingSignature = Socialbox::resolvePeerSignature($callingPeer, $rpcRequest->getParameter('calling_signature_uuid'));
|
|
||||||
if($resolvedCallingSignature->getPublicKey() !== $rpcRequest->getParameter('calling_signature_public_key'))
|
|
||||||
{
|
|
||||||
throw new InvalidRpcArgumentException('calling_signature_public_key', 'Public signing key of the calling peer does not match the resolved signature');
|
|
||||||
}
|
|
||||||
if($resolvedCallingSignature->getState() === SigningKeyState::EXPIRED)
|
|
||||||
{
|
|
||||||
throw new StandardRpcException('The public signing key of the calling peer has expired', StandardError::EXPIRED);
|
|
||||||
}
|
|
||||||
|
|
||||||
$resolvedSignature = Socialbox::resolvePeerSignature($callingPeer, $rpcRequest->getParameter('calling_signature_uuid'));
|
|
||||||
if($resolvedSignature === null)
|
|
||||||
{
|
|
||||||
throw new StandardRpcException('The calling peer signature could not be resolved', StandardError::NOT_FOUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $resolvedSignature;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the PeerAddress of the receiving peer, if the receiving peer is from an external server then the
|
|
||||||
* receiving peer is resolved and returned, otherwise the receiving peer is locally resolved and returned
|
|
||||||
*
|
|
||||||
* @param RpcRequest $rpcRequest The focused RPC request
|
|
||||||
* @return PeerAddress The receiving peer
|
|
||||||
* @throws InvalidRpcArgumentException If one or more RPC parameters are invalid
|
|
||||||
* @throws MissingRpcArgumentException If one or more RPC parameters are missing
|
|
||||||
* @throws StandardRpcException If the receiving peer cannot be resolved
|
|
||||||
*/
|
|
||||||
private static function getReceivingPeer(RpcRequest $rpcRequest): PeerAddress
|
|
||||||
{
|
|
||||||
if(!$rpcRequest->containsParameter('receiving_peer'))
|
|
||||||
{
|
|
||||||
throw new MissingRpcArgumentException('receiving_peer');
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
$receivingPeer = PeerAddress::fromAddress($rpcRequest->getParameter('receiving_peer'));
|
|
||||||
}
|
|
||||||
catch(InvalidArgumentException $e)
|
|
||||||
{
|
|
||||||
throw new InvalidRpcArgumentException('receiving_peer', $e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if($receivingPeer->getUsername() == ReservedUsernames::HOST)
|
|
||||||
{
|
|
||||||
throw new InvalidRpcArgumentException('receiving_peer', 'Hosts cannot receive channels');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resolve the receiving peer if it's from an external server
|
|
||||||
if($receivingPeer->getDomain() !== Configuration::getInstanceConfiguration()->getDomain())
|
|
||||||
{
|
|
||||||
Socialbox::resolvePeer($receivingPeer);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $receivingPeer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param PeerAddress $receivingPeer
|
|
||||||
* @param RpcRequest $rpcRequest
|
|
||||||
* @return Signature
|
|
||||||
* @throws InvalidRpcArgumentException
|
|
||||||
* @throws MissingRpcArgumentException
|
|
||||||
* @throws StandardRpcException
|
|
||||||
*/
|
|
||||||
private static function getReceivingSignature(PeerAddress $receivingPeer, RpcRequest $rpcRequest): Signature
|
|
||||||
{
|
|
||||||
// Receiving signature verification
|
|
||||||
if(!$rpcRequest->containsParameter('receiving_signature_uuid'))
|
|
||||||
{
|
|
||||||
throw new MissingRpcArgumentException('receiving_signature_uuid');
|
|
||||||
}
|
|
||||||
if(!Validator::validateUuid($rpcRequest->getParameter('receiving_signature_uuid')))
|
|
||||||
{
|
|
||||||
throw new InvalidRpcArgumentException('receiving_signature_uuid', 'Invalid UUID V4');
|
|
||||||
}
|
|
||||||
if(!$rpcRequest->containsParameter('receiving_signature_public_key'))
|
|
||||||
{
|
|
||||||
throw new MissingRpcArgumentException('receiving_signature_public_key');
|
|
||||||
}
|
|
||||||
if(!Cryptography::validatePublicSigningKey($rpcRequest->getParameter('receiving_signature_public_key')))
|
|
||||||
{
|
|
||||||
throw new InvalidRpcArgumentException('receiving_signature_public_key', 'Invalid Public Key');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resolve the signature
|
|
||||||
$resolvedReceivingSignature = Socialbox::resolvePeerSignature($receivingPeer, $rpcRequest->getParameter('receiving_signature_uuid'));
|
|
||||||
if($resolvedReceivingSignature->getPublicKey() !== $rpcRequest->getParameter('receiving_signature_public_key'))
|
|
||||||
{
|
|
||||||
throw new InvalidRpcArgumentException('receiving_signature_public_key', 'Public signing key of the receiving peer does not match the resolved signature');
|
|
||||||
}
|
|
||||||
if($resolvedReceivingSignature->getState() === SigningKeyState::EXPIRED)
|
|
||||||
{
|
|
||||||
throw new StandardRpcException('The public signing key of the receiving peer has expired', StandardError::EXPIRED);
|
|
||||||
}
|
|
||||||
|
|
||||||
$resolvedSignature = Socialbox::resolvePeerSignature($receivingPeer, $rpcRequest->getParameter('receiving_signature_uuid'));
|
|
||||||
if($resolvedSignature === null)
|
|
||||||
{
|
|
||||||
throw new StandardRpcException('The receiving peer signature could not be resolved', StandardError::NOT_FOUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $resolvedSignature;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param ClientRequest $request
|
|
||||||
* @param RpcRequest $rpcRequest
|
|
||||||
* @return string|null
|
|
||||||
* @throws InvalidRpcArgumentException
|
|
||||||
* @throws MissingRpcArgumentException
|
|
||||||
*/
|
|
||||||
private static function getChannelUuid(ClientRequest $request, RpcRequest $rpcRequest): ?string
|
|
||||||
{
|
|
||||||
if($request->getIdentifyAs() !== null)
|
|
||||||
{
|
|
||||||
if(!$rpcRequest->containsParameter('uuid'))
|
|
||||||
{
|
|
||||||
throw new MissingRpcArgumentException('uuid');
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!Validator::validateUuid($rpcRequest->getParameter('uuid')))
|
|
||||||
{
|
|
||||||
throw new InvalidRpcArgumentException('uuid', 'Invalid UUID V4');
|
|
||||||
}
|
|
||||||
|
|
||||||
if(EncryptionChannelManager::channelExists($rpcRequest->getParameter('uuid')))
|
|
||||||
{
|
|
||||||
throw new StandardRpcException('UUID Conflict, a channel with this UUID already exists', StandardError::UUID_CONFLICT);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $rpcRequest->getParameter('uuid');
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -16,8 +16,11 @@
|
||||||
use Socialbox\Classes\StandardMethods\Core\GetSessionState;
|
use Socialbox\Classes\StandardMethods\Core\GetSessionState;
|
||||||
use Socialbox\Classes\StandardMethods\Core\Ping;
|
use Socialbox\Classes\StandardMethods\Core\Ping;
|
||||||
use Socialbox\Classes\StandardMethods\Core\ResolvePeer;
|
use Socialbox\Classes\StandardMethods\Core\ResolvePeer;
|
||||||
use Socialbox\Classes\StandardMethods\Core\ResolvePeerSignature;
|
use Socialbox\Classes\StandardMethods\Core\ResolveSignature;
|
||||||
use Socialbox\Classes\StandardMethods\Core\VerifyPeerSignature;
|
use Socialbox\Classes\StandardMethods\Core\VerifySignature;
|
||||||
|
use Socialbox\Classes\StandardMethods\Encryption\EncryptionAcceptChannel;
|
||||||
|
use Socialbox\Classes\StandardMethods\Encryption\EncryptionCloseChannel;
|
||||||
|
use Socialbox\Classes\StandardMethods\Encryption\EncryptionCreateChannel;
|
||||||
use Socialbox\Classes\StandardMethods\ServerDocuments\AcceptCommunityGuidelines;
|
use Socialbox\Classes\StandardMethods\ServerDocuments\AcceptCommunityGuidelines;
|
||||||
use Socialbox\Classes\StandardMethods\ServerDocuments\AcceptPrivacyPolicy;
|
use Socialbox\Classes\StandardMethods\ServerDocuments\AcceptPrivacyPolicy;
|
||||||
use Socialbox\Classes\StandardMethods\ServerDocuments\AcceptTermsOfService;
|
use Socialbox\Classes\StandardMethods\ServerDocuments\AcceptTermsOfService;
|
||||||
|
@ -127,14 +130,6 @@
|
||||||
// MISC
|
// MISC
|
||||||
case GET_STATE = 'getState';
|
case GET_STATE = 'getState';
|
||||||
|
|
||||||
// End-to-End channels for communication purposes
|
|
||||||
case END_TO_END_CREATE_REQUEST = 'e2eCreateRequest';
|
|
||||||
case END_TO_END_GET_REQUESTS = 'e2eGetRequests';
|
|
||||||
case END_TO_END_ACCEPT_REQUEST = 'e2eAcceptRequest';
|
|
||||||
case END_TO_END_REJECT_REQUEST = 'e2eRejectRequest';
|
|
||||||
case END_TO_END_GET_CHANNELS = 'e2eGetChannels';
|
|
||||||
case END_TO_END_CLOSE_CHANNEL = 'e2eCloseChannel';
|
|
||||||
|
|
||||||
// Messaging methods
|
// Messaging methods
|
||||||
case MESSAGES_GET_INBOX = 'messagesGetInbox';
|
case MESSAGES_GET_INBOX = 'messagesGetInbox';
|
||||||
case MESSAGES_GET_UNTRUSTED = 'messagesGetUntrusted';
|
case MESSAGES_GET_UNTRUSTED = 'messagesGetUntrusted';
|
||||||
|
@ -189,8 +184,8 @@
|
||||||
self::GET_SESSION_STATE => GetSessionState::execute($request, $rpcRequest),
|
self::GET_SESSION_STATE => GetSessionState::execute($request, $rpcRequest),
|
||||||
self::PING => Ping::execute($request, $rpcRequest),
|
self::PING => Ping::execute($request, $rpcRequest),
|
||||||
self::RESOLVE_PEER => ResolvePeer::execute($request, $rpcRequest),
|
self::RESOLVE_PEER => ResolvePeer::execute($request, $rpcRequest),
|
||||||
self::RESOLVE_PEER_SIGNATURE => ResolvePeerSignature::execute($request, $rpcRequest),
|
self::RESOLVE_PEER_SIGNATURE => ResolveSignature::execute($request, $rpcRequest),
|
||||||
self::VERIFY_PEER_SIGNATURE => VerifyPeerSignature::execute($request, $rpcRequest),
|
self::VERIFY_PEER_SIGNATURE => VerifySignature::execute($request, $rpcRequest),
|
||||||
|
|
||||||
// Server Document Methods
|
// Server Document Methods
|
||||||
self::ACCEPT_PRIVACY_POLICY => AcceptPrivacyPolicy::execute($request, $rpcRequest),
|
self::ACCEPT_PRIVACY_POLICY => AcceptPrivacyPolicy::execute($request, $rpcRequest),
|
||||||
|
@ -235,18 +230,13 @@
|
||||||
* Checks if the access method is allowed for the given client request.
|
* Checks if the access method is allowed for the given client request.
|
||||||
*
|
*
|
||||||
* @param ClientRequest $clientRequest The client request instance to check access against.
|
* @param ClientRequest $clientRequest The client request instance to check access against.
|
||||||
* @return void
|
|
||||||
* @throws DatabaseOperationException If an error occurs while checking the database for session information.
|
* @throws DatabaseOperationException If an error occurs while checking the database for session information.
|
||||||
* @throws StandardRpcException If the method is not allowed for the given client request.
|
* @throws StandardRpcException If the method is not allowed for the given client request.
|
||||||
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function checkAccess(ClientRequest $clientRequest): void
|
public function checkAccess(ClientRequest $clientRequest): bool
|
||||||
{
|
{
|
||||||
if(in_array($this, self::getAllowedMethods($clientRequest)))
|
return in_array($this, self::getAllowedMethods($clientRequest));
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new StandardRpcException(StandardError::METHOD_NOT_ALLOWED->getMessage(), StandardError::METHOD_NOT_ALLOWED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -5,32 +5,32 @@
|
||||||
enum SignatureVerificationStatus : string
|
enum SignatureVerificationStatus : string
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The provided signature does not match the expected signature.
|
* Returned if the signature is invalid
|
||||||
*/
|
*/
|
||||||
case INVALID = 'INVALID';
|
case INVALID = 'INVALID';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The provided signature was valid, but the public key used to verify the signature was not the expected public key.
|
* Returned if one or more of the parameters are invalid resulting in a failure to verify the signature
|
||||||
*/
|
*/
|
||||||
case PUBLIC_KEY_MISMATCH = 'PUBLIC_KEY_MISMATCH';
|
case ERROR = 'ERROR';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The provided signature was valid, but the UUID used to verify the signature was not the expected UUID.
|
* Returned if the signing key is not found
|
||||||
*/
|
*/
|
||||||
case UUID_MISMATCH = 'UUID_MISMATCH';
|
case NOT_FOUND = 'NOT_FOUND';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The provided signature was valid, but the signing key has expired.
|
* Returned if the signature has expired
|
||||||
*/
|
*/
|
||||||
case EXPIRED = 'EXPIRED';
|
case EXPIRED = 'EXPIRED';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The provided signature was valid but unable to be verified against the peer's known public key.
|
* Returned if there was an error while trying to resolve the signature locally or externally
|
||||||
*/
|
*/
|
||||||
case UNVERIFIED = 'UNVERIFIED';
|
case RESOLUTION_ERROR = 'RESOLUTION_ERROR';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The provided signature was valid and verified locally and against the peer's known public key successfully.
|
* Returned if the signature has been successfully verified
|
||||||
*/
|
*/
|
||||||
case VERIFIED = 'VERIFIED';
|
case VERIFIED = 'VERIFIED';
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
|
||||||
namespace Socialbox\Managers;
|
namespace Socialbox\Managers;
|
||||||
|
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
|
@ -14,7 +15,6 @@
|
||||||
use Socialbox\Objects\Database\ChannelMessageRecord;
|
use Socialbox\Objects\Database\ChannelMessageRecord;
|
||||||
use Socialbox\Objects\Database\EncryptionChannelRecord;
|
use Socialbox\Objects\Database\EncryptionChannelRecord;
|
||||||
use Socialbox\Objects\PeerAddress;
|
use Socialbox\Objects\PeerAddress;
|
||||||
use Socialbox\Objects\Standard\EncryptionChannelMessage;
|
|
||||||
|
|
||||||
class EncryptionChannelManager
|
class EncryptionChannelManager
|
||||||
{
|
{
|
||||||
|
@ -24,14 +24,13 @@
|
||||||
* @param PeerAddress|string $callingPeer The peer that is creating the channel.
|
* @param PeerAddress|string $callingPeer The peer that is creating the channel.
|
||||||
* @param PeerAddress|string $receivingPeer The peer that is receiving the channel.
|
* @param PeerAddress|string $receivingPeer The peer that is receiving the channel.
|
||||||
* @param string $signatureUuid The UUID of the signature used to create the channel.
|
* @param string $signatureUuid The UUID of the signature used to create the channel.
|
||||||
* @param string $signingPublicKey The public key used for signing.
|
|
||||||
* @param string $encryptionPublicKey The public key used for encryption.
|
* @param string $encryptionPublicKey The public key used for encryption.
|
||||||
* @param string $transportEncryptionAlgorithm The algorithm used for transport encryption.
|
* @param string $transportEncryptionAlgorithm The algorithm used for transport encryption.
|
||||||
* @return string The UUID of the created channel.
|
* @return string The UUID of the created channel.
|
||||||
* @throws DatabaseOperationException If an error occurs while creating the channel.
|
* @throws DatabaseOperationException If an error occurs while creating the channel.
|
||||||
*/
|
*/
|
||||||
public static function createChannel(PeerAddress|string $callingPeer, PeerAddress|string $receivingPeer,
|
public static function createChannel(PeerAddress|string $callingPeer, PeerAddress|string $receivingPeer,
|
||||||
string $signatureUuid, string $signingPublicKey, string $encryptionPublicKey, string $transportEncryptionAlgorithm,
|
string $signatureUuid, string $encryptionPublicKey, string $transportEncryptionAlgorithm,
|
||||||
?string $uuid=null
|
?string $uuid=null
|
||||||
): string
|
): string
|
||||||
{
|
{
|
||||||
|
@ -45,10 +44,6 @@
|
||||||
$receivingPeer = PeerAddress::fromAddress($receivingPeer);
|
$receivingPeer = PeerAddress::fromAddress($receivingPeer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!Cryptography::validatePublicSigningKey($signingPublicKey))
|
|
||||||
{
|
|
||||||
throw new InvalidArgumentException('Invalid signing public key provided');
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!Cryptography::validatePublicEncryptionKey($encryptionPublicKey))
|
if(!Cryptography::validatePublicEncryptionKey($encryptionPublicKey))
|
||||||
{
|
{
|
||||||
|
@ -68,12 +63,11 @@
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$stmt = Database::getConnection()->prepare('INSERT INTO encryption_channels (uuid, calling_peer, calling_signature_uuid, calling_signature_public_key, calling_encryption_public_key, receiving_peer, transport_encryption_algorithm) VALUES (:uuid, :calling_peer, :calling_signature_uuid, :calling_signature_public_key, :calling_encryption_public_key, :receiving_peer, :transport_encryption_algorithm)');
|
$stmt = Database::getConnection()->prepare('INSERT INTO encryption_channels (uuid, calling_peer, calling_signature_uuid, calling_encryption_public_key, receiving_peer, transport_encryption_algorithm) VALUES (:uuid, :calling_peer, :calling_signature_uuid, :calling_encryption_public_key, :receiving_peer, :transport_encryption_algorithm)');
|
||||||
$stmt->bindParam(':uuid', $uuid);
|
$stmt->bindParam(':uuid', $uuid);
|
||||||
$callingPeerAddress = $callingPeer->getAddress();
|
$callingPeerAddress = $callingPeer->getAddress();
|
||||||
$stmt->bindParam(':calling_peer', $callingPeerAddress);
|
$stmt->bindParam(':calling_peer', $callingPeerAddress);
|
||||||
$stmt->bindParam(':calling_signature_uuid', $signatureUuid);
|
$stmt->bindParam(':calling_signature_uuid', $signatureUuid);
|
||||||
$stmt->bindParam(':calling_signature_public_key', $signingPublicKey);
|
|
||||||
$stmt->bindParam(':calling_encryption_public_key', $encryptionPublicKey);
|
$stmt->bindParam(':calling_encryption_public_key', $encryptionPublicKey);
|
||||||
$receivingPeerAddress = $receivingPeer->getAddress();
|
$receivingPeerAddress = $receivingPeer->getAddress();
|
||||||
$stmt->bindParam(':receiving_peer', $receivingPeerAddress);
|
$stmt->bindParam(':receiving_peer', $receivingPeerAddress);
|
||||||
|
@ -96,7 +90,6 @@
|
||||||
* @param int $page The page of channels to retrieve.
|
* @param int $page The page of channels to retrieve.
|
||||||
* @return EncryptionChannelRecord[] The incoming channels for the peer.
|
* @return EncryptionChannelRecord[] The incoming channels for the peer.
|
||||||
* @throws DatabaseOperationException If an error occurs while retrieving the channels.
|
* @throws DatabaseOperationException If an error occurs while retrieving the channels.
|
||||||
* @throws \DateMalformedStringException If the created date is not a valid date string.
|
|
||||||
*/
|
*/
|
||||||
public static function getChannels(string|PeerAddress $peerAddress, int $limit=100, int $page=0): array
|
public static function getChannels(string|PeerAddress $peerAddress, int $limit=100, int $page=0): array
|
||||||
{
|
{
|
||||||
|
@ -137,7 +130,6 @@
|
||||||
* @param int $page The page of channels to retrieve.
|
* @param int $page The page of channels to retrieve.
|
||||||
* @return EncryptionChannelRecord[] The incoming channels for the peer.
|
* @return EncryptionChannelRecord[] The incoming channels for the peer.
|
||||||
* @throws DatabaseOperationException If an error occurs while retrieving the channels.
|
* @throws DatabaseOperationException If an error occurs while retrieving the channels.
|
||||||
* @throws \DateMalformedStringException If the created date is not a valid date string.
|
|
||||||
*/
|
*/
|
||||||
public static function getRequests(string|PeerAddress $peerAddress, int $limit=100, int $page=0): array
|
public static function getRequests(string|PeerAddress $peerAddress, int $limit=100, int $page=0): array
|
||||||
{
|
{
|
||||||
|
@ -180,7 +172,6 @@
|
||||||
* @param int $page The page of channels to retrieve.
|
* @param int $page The page of channels to retrieve.
|
||||||
* @return EncryptionChannelRecord[] The incoming channels for the peer.
|
* @return EncryptionChannelRecord[] The incoming channels for the peer.
|
||||||
* @throws DatabaseOperationException If an error occurs while retrieving the channels.
|
* @throws DatabaseOperationException If an error occurs while retrieving the channels.
|
||||||
* @throws \DateMalformedStringException If the created date is not a valid date string.
|
|
||||||
*/
|
*/
|
||||||
public static function getIncomingChannels(string|PeerAddress $peerAddress, int $limit=100, int $page=0): array
|
public static function getIncomingChannels(string|PeerAddress $peerAddress, int $limit=100, int $page=0): array
|
||||||
{
|
{
|
||||||
|
@ -221,7 +212,6 @@
|
||||||
* @param int $page The page of channels to retrieve.
|
* @param int $page The page of channels to retrieve.
|
||||||
* @return EncryptionChannelRecord[] The outgoing channels for the specified peer.
|
* @return EncryptionChannelRecord[] The outgoing channels for the specified peer.
|
||||||
* @throws DatabaseOperationException If an error occurs while retrieving the channels.
|
* @throws DatabaseOperationException If an error occurs while retrieving the channels.
|
||||||
* @throws \DateMalformedStringException If the created date is not a valid date string.
|
|
||||||
*/
|
*/
|
||||||
public static function getOutgoingChannels(string|PeerAddress $peerAddress, int $limit=100, int $page=0): array
|
public static function getOutgoingChannels(string|PeerAddress $peerAddress, int $limit=100, int $page=0): array
|
||||||
{
|
{
|
||||||
|
@ -281,23 +271,19 @@
|
||||||
*
|
*
|
||||||
* @param string $channelUuid The UUID of the channel to accept.
|
* @param string $channelUuid The UUID of the channel to accept.
|
||||||
* @param string $signatureUuid The UUID of the signature used to create the channel.
|
* @param string $signatureUuid The UUID of the signature used to create the channel.
|
||||||
* @param string $signaturePublicKey The public key used for signing.
|
|
||||||
* @param string $encryptionPublicKey The public key used for encryption.
|
* @param string $encryptionPublicKey The public key used for encryption.
|
||||||
* @param string $transportEncryptionAlgorithm The algorithm used for transport encryption.
|
|
||||||
* @param string $encryptedTransportEncryptionKey The encrypted transport encryption key.
|
* @param string $encryptedTransportEncryptionKey The encrypted transport encryption key.
|
||||||
* @throws DatabaseOperationException If an error occurs while accepting the channel.
|
* @throws DatabaseOperationException If an error occurs while accepting the channel.
|
||||||
*/
|
*/
|
||||||
public static function acceptChannel(string $channelUuid, string $signatureUuid, string $signaturePublicKey, string $encryptionPublicKey, string $transportEncryptionAlgorithm, string $encryptedTransportEncryptionKey): void
|
public static function acceptChannel(string $channelUuid, string $signatureUuid, string $encryptionPublicKey, string $encryptedTransportEncryptionKey): void
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$stmt = Database::getConnection()->prepare('UPDATE encryption_channels SET state=:state, receiving_signature_uuid=:receiving_signature_uuid, receiving_signature_public_key=:receiving_signature_public_key, receiving_encryption_public_key=:receiving_encryption_public_key, transport_encryption_algorithm=:transport_encryption_algorithm, transport_encryption_key=:transport_encryption_key WHERE uuid=:uuid');
|
$stmt = Database::getConnection()->prepare('UPDATE encryption_channels SET state=:state, receiving_signature_uuid=:receiving_signature_uuid, receiving_encryption_public_key=:receiving_encryption_public_key, transport_encryption_algorithm=:transport_encryption_algorithm, transport_encryption_key=:transport_encryption_key WHERE uuid=:uuid');
|
||||||
$state = EncryptionChannelState::OPENED->value;
|
$state = EncryptionChannelState::OPENED->value;
|
||||||
$stmt->bindParam(':state', $state);
|
$stmt->bindParam(':state', $state);
|
||||||
$stmt->bindParam(':receiving_signature_uuid', $signatureUuid);
|
$stmt->bindParam(':receiving_signature_uuid', $signatureUuid);
|
||||||
$stmt->bindParam(':receiving_signature_public_key', $signaturePublicKey);
|
|
||||||
$stmt->bindParam(':receiving_encryption_public_key', $encryptionPublicKey);
|
$stmt->bindParam(':receiving_encryption_public_key', $encryptionPublicKey);
|
||||||
$stmt->bindParam(':transport_encryption_algorithm', $transportEncryptionAlgorithm);
|
|
||||||
$stmt->bindParam(':transport_encryption_key', $encryptedTransportEncryptionKey);
|
$stmt->bindParam(':transport_encryption_key', $encryptedTransportEncryptionKey);
|
||||||
$stmt->bindParam(':uuid', $channelUuid);
|
$stmt->bindParam(':uuid', $channelUuid);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
|
@ -314,7 +300,6 @@
|
||||||
* @param string $channelUuid The UUID of the channel to retrieve.
|
* @param string $channelUuid The UUID of the channel to retrieve.
|
||||||
* @return EncryptionChannelRecord|null The record of the encryption channel. Null if the channel does not exist.
|
* @return EncryptionChannelRecord|null The record of the encryption channel. Null if the channel does not exist.
|
||||||
* @throws DatabaseOperationException If an error occurs while retrieving the channel.
|
* @throws DatabaseOperationException If an error occurs while retrieving the channel.
|
||||||
* @throws \DateMalformedStringException If the created date is not a valid date string.
|
|
||||||
*/
|
*/
|
||||||
public static function getChannel(string $channelUuid): ?EncryptionChannelRecord
|
public static function getChannel(string $channelUuid): ?EncryptionChannelRecord
|
||||||
{
|
{
|
||||||
|
@ -343,7 +328,7 @@
|
||||||
*
|
*
|
||||||
* @param string $channelUuid The UUID of the channel to delete.
|
* @param string $channelUuid The UUID of the channel to delete.
|
||||||
* @return void
|
* @return void
|
||||||
*@throws DatabaseOperationException If an error occurs while deleting the channel.
|
* @throws DatabaseOperationException If an error occurs while deleting the channel.
|
||||||
*/
|
*/
|
||||||
public static function deleteChannel(string $channelUuid): void
|
public static function deleteChannel(string $channelUuid): void
|
||||||
{
|
{
|
||||||
|
@ -503,7 +488,6 @@
|
||||||
* @param string $messageUuid The UUID of the message to retrieve.
|
* @param string $messageUuid The UUID of the message to retrieve.
|
||||||
* @return ChannelMessageRecord|null The message with the specified UUID. Null if the message does not exist.
|
* @return ChannelMessageRecord|null The message with the specified UUID. Null if the message does not exist.
|
||||||
* @throws DatabaseOperationException If an error occurs while retrieving the message.
|
* @throws DatabaseOperationException If an error occurs while retrieving the message.
|
||||||
* @throws \DateMalformedStringException If the created date is not a valid date string.
|
|
||||||
*/
|
*/
|
||||||
public static function getData(string $channelUuid, string $messageUuid): ?ChannelMessageRecord
|
public static function getData(string $channelUuid, string $messageUuid): ?ChannelMessageRecord
|
||||||
{
|
{
|
||||||
|
@ -531,23 +515,29 @@
|
||||||
/**
|
/**
|
||||||
* Imports the specified message data into the database.
|
* Imports the specified message data into the database.
|
||||||
*
|
*
|
||||||
* @param EncryptionChannelMessage|ChannelMessageRecord $message The message data to import.
|
* @param ChannelMessageRecord $message The message data to import.
|
||||||
* @throws DatabaseOperationException If an error occurs while importing the message.
|
* @throws DatabaseOperationException If an error occurs while importing the message.
|
||||||
*/
|
*/
|
||||||
public static function importData(EncryptionChannelMessage|ChannelMessageRecord $message): void
|
public static function importData(ChannelMessageRecord $message): void
|
||||||
{
|
{
|
||||||
$data = $message->toArray();
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$stmt = Database::getConnection()->prepare('INSERT INTO channel_com (uuid, channel_uuid, recipient, message, signature, received, timestamp) VALUES (:uuid, :channel_uuid, :recipient, :message, :signature, :received, :timestamp)');
|
$stmt = Database::getConnection()->prepare('INSERT INTO channel_com (uuid, channel_uuid, recipient, message, signature, received, timestamp) VALUES (:uuid, :channel_uuid, :recipient, :message, :signature, :received, :timestamp)');
|
||||||
$stmt->bindParam(':uuid', $data['uuid']);
|
$uuid = $message->getUuid();
|
||||||
$stmt->bindParam(':channel_uuid', $data['channel_uuid']);
|
$stmt->bindParam(':uuid', $uuid);
|
||||||
$stmt->bindParam(':recipient', $data['recipient']);
|
$channelUuid = $message->getChannelUuid();
|
||||||
$stmt->bindParam(':message', $data['message']);
|
$stmt->bindParam(':channel_uuid', $channelUuid);
|
||||||
$stmt->bindParam(':signature', $data['signature']);
|
$recipient = $message->getRecipient()->value;
|
||||||
$stmt->bindParam(':received', $data['received']);
|
$stmt->bindParam(':recipient', $recipient);
|
||||||
$stmt->bindParam(':timestamp', $data['timestamp']);
|
$messageData = $message->getMessage();
|
||||||
|
$stmt->bindParam(':message', $messageData);
|
||||||
|
$signature = $message->getSignature();
|
||||||
|
$stmt->bindParam(':signature', $signature);
|
||||||
|
$received = $message->isReceived() ? 1 : 0;
|
||||||
|
$stmt->bindParam(':received', $received);
|
||||||
|
$timestamp = $message->getTimestamp();
|
||||||
|
$stmt->bindParam(':timestamp', $timestamp);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
}
|
}
|
||||||
catch(PDOException $e)
|
catch(PDOException $e)
|
||||||
|
|
|
@ -34,8 +34,8 @@
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$statement = Database::getConnection()->prepare('SELECT COUNT(*) FROM peers WHERE username=?');
|
$statement = Database::getConnection()->prepare("SELECT COUNT(*) FROM peers WHERE username=:username AND server='host'");
|
||||||
$statement->bindParam(1, $username);
|
$statement->bindParam(':username', $username);
|
||||||
$statement->execute();
|
$statement->execute();
|
||||||
|
|
||||||
$result = $statement->fetchColumn();
|
$result = $statement->fetchColumn();
|
||||||
|
@ -163,9 +163,9 @@
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$statement = Database::getConnection()->prepare('SELECT * FROM peers WHERE username=? AND server=?');
|
$statement = Database::getConnection()->prepare('SELECT * FROM peers WHERE username=:username AND server=:server');
|
||||||
$username = $address->getUsername();
|
$username = $address->getUsername();
|
||||||
$statement->bindParam(1, $username);
|
$statement->bindParam(':username', $username);
|
||||||
$server = $address->getDomain();
|
$server = $address->getDomain();
|
||||||
|
|
||||||
// Convert to 'host' if the domain is the same as the server's host
|
// Convert to 'host' if the domain is the same as the server's host
|
||||||
|
@ -174,7 +174,7 @@
|
||||||
$server = 'host';
|
$server = 'host';
|
||||||
}
|
}
|
||||||
|
|
||||||
$statement->bindParam(2, $server);
|
$statement->bindParam(':server', $server);
|
||||||
$statement->execute();
|
$statement->execute();
|
||||||
|
|
||||||
$result = $statement->fetch(PDO::FETCH_ASSOC);
|
$result = $statement->fetch(PDO::FETCH_ASSOC);
|
||||||
|
|
129
src/Socialbox/Objects/Client/EncryptionChannelSecret.php
Normal file
129
src/Socialbox/Objects/Client/EncryptionChannelSecret.php
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Socialbox\Objects\Client;
|
||||||
|
|
||||||
|
use Socialbox\Interfaces\SerializableInterface;
|
||||||
|
use Socialbox\Objects\PeerAddress;
|
||||||
|
|
||||||
|
class EncryptionChannelSecret implements SerializableInterface
|
||||||
|
{
|
||||||
|
private string $channelUuid;
|
||||||
|
private PeerAddress $receiver;
|
||||||
|
private string $signatureUuid;
|
||||||
|
private string $publicEncryptionKey;
|
||||||
|
private string $privateEncryptionKey;
|
||||||
|
private string $transportEncryptionAlgorithm;
|
||||||
|
private ?string $transportEncryptionKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public constructor
|
||||||
|
*
|
||||||
|
* @param array $data The data to create the object
|
||||||
|
*/
|
||||||
|
public function __construct(array $data)
|
||||||
|
{
|
||||||
|
$this->channelUuid = $data['uuid'];
|
||||||
|
$this->receiver = PeerAddress::fromAddress($data['receiver']);
|
||||||
|
$this->signatureUuid = $data['signature_uuid'];
|
||||||
|
$this->publicEncryptionKey = $data['public_encryption_key'];
|
||||||
|
$this->privateEncryptionKey = $data['private_encryption_key'];
|
||||||
|
$this->transportEncryptionAlgorithm = $data['transport_encryption_algorithm'];
|
||||||
|
$this->transportEncryptionKey = $data['transport_encryption_key'] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the UUID of the key pair
|
||||||
|
*
|
||||||
|
* @return string The UUID of the key pair
|
||||||
|
*/
|
||||||
|
public function getChannelUuid(): string
|
||||||
|
{
|
||||||
|
return $this->channelUuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return PeerAddress
|
||||||
|
*/
|
||||||
|
public function getReceiver(): PeerAddress
|
||||||
|
{
|
||||||
|
return $this->receiver;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the UUID of the signature
|
||||||
|
*
|
||||||
|
* @return string The UUID of the signature
|
||||||
|
*/
|
||||||
|
public function getSignatureUuid(): string
|
||||||
|
{
|
||||||
|
return $this->signatureUuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the public key of the key pair
|
||||||
|
*
|
||||||
|
* @return string The public key of the key pair
|
||||||
|
*/
|
||||||
|
public function getPublicEncryptionKey(): string
|
||||||
|
{
|
||||||
|
return $this->publicEncryptionKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the private key of the key pair
|
||||||
|
*
|
||||||
|
* @return string The private key of the key pair
|
||||||
|
*/
|
||||||
|
public function getPrivateEncryptionKey(): string
|
||||||
|
{
|
||||||
|
return $this->privateEncryptionKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getTransportEncryptionAlgorithm(): string
|
||||||
|
{
|
||||||
|
return $this->transportEncryptionAlgorithm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function getTransportEncryptionKey(): ?string
|
||||||
|
{
|
||||||
|
return $this->transportEncryptionKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|null $transportEncryptionKey
|
||||||
|
*/
|
||||||
|
public function setTransportEncryptionKey(?string $transportEncryptionKey): void
|
||||||
|
{
|
||||||
|
$this->transportEncryptionKey = $transportEncryptionKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public static function fromArray(array $data): EncryptionChannelSecret
|
||||||
|
{
|
||||||
|
return new self($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function toArray(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'uuid' => $this->channelUuid,
|
||||||
|
'receiver' => $this->receiver->getAddress(),
|
||||||
|
'signature_uuid' => $this->signatureUuid,
|
||||||
|
'public_key' => $this->publicEncryptionKey,
|
||||||
|
'private_key' => $this->privateEncryptionKey,
|
||||||
|
'transport_encryption_algorithm' => $this->transportEncryptionAlgorithm,
|
||||||
|
'transport_encryption_key' => $this->transportEncryptionKey
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,6 +29,10 @@
|
||||||
* @var SignatureKeyPair[]
|
* @var SignatureKeyPair[]
|
||||||
*/
|
*/
|
||||||
private array $signingKeys;
|
private array $signingKeys;
|
||||||
|
/**
|
||||||
|
* @var EncryptionChannelSecret[]
|
||||||
|
*/
|
||||||
|
private array $encryptionChannelSecrets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor method to initialize class properties from the provided data array.
|
* Constructor method to initialize class properties from the provided data array.
|
||||||
|
@ -62,6 +66,7 @@
|
||||||
$this->serverTransportEncryptionKey = $data['server_transport_encryption_key'];
|
$this->serverTransportEncryptionKey = $data['server_transport_encryption_key'];
|
||||||
$this->defaultSigningKey = $data['default_signing_key'] ?? null;
|
$this->defaultSigningKey = $data['default_signing_key'] ?? null;
|
||||||
$this->signingKeys = array_map(fn($key) => SignatureKeyPair::fromArray($key), $data['signing_keys']);
|
$this->signingKeys = array_map(fn($key) => SignatureKeyPair::fromArray($key), $data['signing_keys']);
|
||||||
|
$this->encryptionChannelSecrets = array_map(fn($key) => EncryptionChannelSecret::fromArray($key), $data['encryption_channel_secrets']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -234,6 +239,60 @@
|
||||||
return $this->signingKeys;
|
return $this->signingKeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the encrypted channel keys associated with the current instance.
|
||||||
|
*
|
||||||
|
* @return EncryptionChannelSecret[] The encrypted channel keys.
|
||||||
|
*/
|
||||||
|
public function getEncryptionChannelSecrets(): array
|
||||||
|
{
|
||||||
|
return $this->encryptionChannelSecrets;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the signing key associated with the provided UUID.
|
||||||
|
*
|
||||||
|
* @param string $uuid The UUID of the signing key.
|
||||||
|
* @return SignatureKeyPair|null The signing key.
|
||||||
|
*/
|
||||||
|
public function getEncryptionChannelSecret(string $uuid): ?EncryptionChannelSecret
|
||||||
|
{
|
||||||
|
return $this->encryptionChannelSecrets[$uuid] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new signing key to the current instance.
|
||||||
|
*
|
||||||
|
* @param EncryptionChannelSecret $key The signing key to add.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function addEncryptionChannelSecret(EncryptionChannelSecret $key): void
|
||||||
|
{
|
||||||
|
$this->encryptionChannelSecrets[$key->getChannelUuid()] = $key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the signing key associated with the provided UUID.
|
||||||
|
*
|
||||||
|
* @param string $uuid The UUID of the signing key to remove.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function removeEncryptionChannelSecret(string $uuid): void
|
||||||
|
{
|
||||||
|
unset($this->encryptionChannelSecrets[$uuid]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a signing key exists for the provided UUID.
|
||||||
|
*
|
||||||
|
* @param string $uuid The UUID of the signing key.
|
||||||
|
* @return bool True if the signing key exists, false otherwise.
|
||||||
|
*/
|
||||||
|
public function encryptionChannelSecretExists(string $uuid): bool
|
||||||
|
{
|
||||||
|
return isset($this->encryptionChannelSecrets[$uuid]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
|
@ -256,7 +315,8 @@
|
||||||
'client_transport_encryption_key' => $this->clientTransportEncryptionKey,
|
'client_transport_encryption_key' => $this->clientTransportEncryptionKey,
|
||||||
'server_transport_encryption_key' => $this->serverTransportEncryptionKey,
|
'server_transport_encryption_key' => $this->serverTransportEncryptionKey,
|
||||||
'default_signing_key' => $this->defaultSigningKey,
|
'default_signing_key' => $this->defaultSigningKey,
|
||||||
'signing_keys' => array_map(fn($key) => $key->toArray(), $this->signingKeys)
|
'signing_keys' => array_map(fn($key) => $key->toArray(), $this->signingKeys),
|
||||||
|
'encryption_channel_secrets' => array_map(fn($key) => $key->toArray(), $this->encryptionChannelSecrets),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -170,7 +170,6 @@
|
||||||
*
|
*
|
||||||
* @return SessionRecord|null Returns the associated SessionRecord if the session UUID exists, or null if no session UUID is set.
|
* @return SessionRecord|null Returns the associated SessionRecord if the session UUID exists, or null if no session UUID is set.
|
||||||
* @throws DatabaseOperationException Thrown if an error occurs while retrieving the session.
|
* @throws DatabaseOperationException Thrown if an error occurs while retrieving the session.
|
||||||
* @throws StandardRpcException Thrown if the session UUID is invalid.
|
|
||||||
*/
|
*/
|
||||||
public function getSession(): ?SessionRecord
|
public function getSession(): ?SessionRecord
|
||||||
{
|
{
|
||||||
|
@ -187,7 +186,6 @@
|
||||||
*
|
*
|
||||||
* @return PeerDatabaseRecord|null Returns the associated RegisteredPeerRecord if available, or null if no session exists.
|
* @return PeerDatabaseRecord|null Returns the associated RegisteredPeerRecord if available, or null if no session exists.
|
||||||
* @throws DatabaseOperationException Thrown if an error occurs while retrieving the peer.
|
* @throws DatabaseOperationException Thrown if an error occurs while retrieving the peer.
|
||||||
* @throws StandardRpcException Thrown if the session UUID is invalid.
|
|
||||||
*/
|
*/
|
||||||
public function getPeer(): ?PeerDatabaseRecord
|
public function getPeer(): ?PeerDatabaseRecord
|
||||||
{
|
{
|
||||||
|
@ -201,6 +199,36 @@
|
||||||
return RegisteredPeerManager::getPeer($session->getPeerUuid());
|
return RegisteredPeerManager::getPeer($session->getPeerUuid());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Peer Database Record of the identified peer of the request
|
||||||
|
*
|
||||||
|
* @return PeerDatabaseRecord|null The Peer Database Record of the identified peer or null if not set
|
||||||
|
* @throws DatabaseOperationException Thrown if an error occurs while retrieving the peer.
|
||||||
|
*/
|
||||||
|
public function getIdentifiedAsPeer(): ?PeerDatabaseRecord
|
||||||
|
{
|
||||||
|
$identifiedAs = $this->getIdentifyAs();
|
||||||
|
if($identifiedAs === null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RegisteredPeerManager::getPeerByAddress($identifiedAs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the request is external or not. As in, if the request is coming from server rather than
|
||||||
|
* a client.
|
||||||
|
*
|
||||||
|
* @return bool True if the request is external, false otherwise.
|
||||||
|
* @throws DatabaseOperationException Thrown if an error occurs while retrieving the peer.
|
||||||
|
* @throws StandardRpcException Thrown if the session UUID is invalid.
|
||||||
|
*/
|
||||||
|
public function isExternal(): bool
|
||||||
|
{
|
||||||
|
return $this->getPeer()->isExternal();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the signature value.
|
* Retrieves the signature value.
|
||||||
*
|
*
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
* - 'signature' (string): The signature.
|
* - 'signature' (string): The signature.
|
||||||
* - 'received' (bool): Whether the message has been received.
|
* - 'received' (bool): Whether the message has been received.
|
||||||
* - 'timestamp' (int|string|\DateTime): The timestamp of the message.
|
* - 'timestamp' (int|string|\DateTime): The timestamp of the message.
|
||||||
* @throws DateMalformedStringException If the timestamp is a string that cannot be parsed.
|
|
||||||
*/
|
*/
|
||||||
public function __construct(array $data)
|
public function __construct(array $data)
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
private string $callingEncryptionPublicKey;
|
private string $callingEncryptionPublicKey;
|
||||||
private PeerAddress $receivingPeer;
|
private PeerAddress $receivingPeer;
|
||||||
private ?string $receivingSignatureUuid;
|
private ?string $receivingSignatureUuid;
|
||||||
private ?string $receivingSignaturePublicKey;
|
|
||||||
private ?string $receivingEncryptionPublicKey;
|
private ?string $receivingEncryptionPublicKey;
|
||||||
private string $transportEncryptionAlgorithm;
|
private string $transportEncryptionAlgorithm;
|
||||||
private ?string $transportEncryptionKey;
|
private ?string $transportEncryptionKey;
|
||||||
|
@ -28,7 +27,6 @@
|
||||||
* Public Constructor for the encryption channel record
|
* Public Constructor for the encryption channel record
|
||||||
*
|
*
|
||||||
* @param array $data
|
* @param array $data
|
||||||
* @throws \DateMalformedStringException
|
|
||||||
*/
|
*/
|
||||||
public function __construct(array $data)
|
public function __construct(array $data)
|
||||||
{
|
{
|
||||||
|
@ -78,7 +76,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->receivingSignatureUuid = $data['receiving_signature_uuid'] ?? null;
|
$this->receivingSignatureUuid = $data['receiving_signature_uuid'] ?? null;
|
||||||
$this->receivingSignaturePublicKey = $data['receiving_signature_public_key'] ?? null;
|
|
||||||
$this->receivingEncryptionPublicKey = $data['receiving_encryption_public_key'] ?? null;
|
$this->receivingEncryptionPublicKey = $data['receiving_encryption_public_key'] ?? null;
|
||||||
$this->transportEncryptionAlgorithm = $data['transport_encryption_algorithm'];
|
$this->transportEncryptionAlgorithm = $data['transport_encryption_algorithm'];
|
||||||
$this->transportEncryptionKey = $data['transport_encryption_key'] ?? null;
|
$this->transportEncryptionKey = $data['transport_encryption_key'] ?? null;
|
||||||
|
@ -169,16 +166,6 @@
|
||||||
return $this->receivingSignatureUuid;
|
return $this->receivingSignatureUuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the public key of the signing keypair that the receiver is using
|
|
||||||
*
|
|
||||||
* @return string|null
|
|
||||||
*/
|
|
||||||
public function getReceivingSignaturePublicKey(): ?string
|
|
||||||
{
|
|
||||||
return $this->receivingSignaturePublicKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the public key of the encryption keypair that the receiver is using
|
* Returns the public key of the encryption keypair that the receiver is using
|
||||||
*
|
*
|
||||||
|
@ -249,7 +236,6 @@
|
||||||
'calling_encryption_public_key' => $this->callingEncryptionPublicKey,
|
'calling_encryption_public_key' => $this->callingEncryptionPublicKey,
|
||||||
'receiving_peer' => $this->receivingPeer->getAddress(),
|
'receiving_peer' => $this->receivingPeer->getAddress(),
|
||||||
'receiving_signature_uuid' => $this->receivingSignatureUuid,
|
'receiving_signature_uuid' => $this->receivingSignatureUuid,
|
||||||
'receiving_signature_public_key' => $this->receivingSignaturePublicKey,
|
|
||||||
'receiving_encryption_public_key' => $this->receivingEncryptionPublicKey,
|
'receiving_encryption_public_key' => $this->receivingEncryptionPublicKey,
|
||||||
'transport_encryption_algorithm' => $this->transportEncryptionAlgorithm,
|
'transport_encryption_algorithm' => $this->transportEncryptionAlgorithm,
|
||||||
'transport_encryption_key' => $this->transportEncryptionKey,
|
'transport_encryption_key' => $this->transportEncryptionKey,
|
||||||
|
|
|
@ -83,7 +83,7 @@
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->username === ReservedUsernames::HOST->value;
|
return $this->domain !== Configuration::getInstanceConfiguration()->getDomain();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -87,6 +87,26 @@
|
||||||
return isset($this->parameters[$parameter]);
|
return isset($this->parameters[$parameter]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the parameters exist within the RPC request
|
||||||
|
*
|
||||||
|
* @param array $parameters The parameters to check
|
||||||
|
* @param bool $nullAllowed True if the parameter value can be null, False otherwise.
|
||||||
|
* @return bool True if the parameters exist, False otherwise.
|
||||||
|
*/
|
||||||
|
public function containsParameters(array $parameters, bool $nullAllowed=false): bool
|
||||||
|
{
|
||||||
|
foreach($parameters as $parameter)
|
||||||
|
{
|
||||||
|
if(!$this->containsParameter($parameter, $nullAllowed))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the parameter value from the RPC request
|
* Returns the parameter value from the RPC request
|
||||||
*
|
*
|
||||||
|
|
|
@ -76,53 +76,6 @@
|
||||||
return $uuid;
|
return $uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new encryption channel with the given peer, using the signature UUID to identify the calling peer.
|
|
||||||
* This method is a wrapper around the encryptionCreateChannel method, and is used to simplify the process of
|
|
||||||
* creating a new encryption channel. The signature UUID is used to identify the calling peer, and the public key
|
|
||||||
* of the signature is used as the encryption key.
|
|
||||||
*
|
|
||||||
* @param PeerAddress|string $receivingPeer
|
|
||||||
* @param string $signatureUuid
|
|
||||||
* @param string $transportEncryptionAlgorithm
|
|
||||||
* @return string
|
|
||||||
* @throws CryptographyException
|
|
||||||
* @throws RpcException
|
|
||||||
*/
|
|
||||||
public function newEncryptionChannel(PeerAddress|string $receivingPeer, string $signatureUuid, string $transportEncryptionAlgorithm): string
|
|
||||||
{
|
|
||||||
if(!$this->signingKeyExists($signatureUuid))
|
|
||||||
{
|
|
||||||
throw new InvalidArgumentException('The signature UUID does not exist in the client');
|
|
||||||
}
|
|
||||||
|
|
||||||
$signature = $this->getSigningKey($signatureUuid);
|
|
||||||
if($signature === null)
|
|
||||||
{
|
|
||||||
throw new InvalidArgumentException('The signature UUID does not exist in the client');
|
|
||||||
}
|
|
||||||
|
|
||||||
$encryptionKeypair = Cryptography::generateEncryptionKeyPair();
|
|
||||||
$channelUuid = $this->encryptionCreateChannel(
|
|
||||||
receivingPeer: $receivingPeer,
|
|
||||||
signatureUUid: $signature->getUuid(),
|
|
||||||
encryptionPublicKey: $encryptionKeypair->getPublicKey(),
|
|
||||||
transportEncryptionAlgorithm: $transportEncryptionAlgorithm
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->addEncryptionChannelSecret(new EncryptionChannelSecret([
|
|
||||||
'uuid' => $channelUuid,
|
|
||||||
'receiver' => $receivingPeer->getAddress(),
|
|
||||||
'signature_uuid' => $signature->getUuid(),
|
|
||||||
'public_encryption_key' => $encryptionKeypair->getPublicKey(),
|
|
||||||
'private_encryption_key' => $encryptionKeypair->getPrivateKey(),
|
|
||||||
'transport_encryption_algorithm' => $transportEncryptionAlgorithm,
|
|
||||||
'transport_encryption_key' => null
|
|
||||||
]));
|
|
||||||
|
|
||||||
return $channelUuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a new peer to the AddressBook, returns True upon success or False if the contact already exists in
|
* Adds a new peer to the AddressBook, returns True upon success or False if the contact already exists in
|
||||||
* the address book.
|
* the address book.
|
||||||
|
@ -459,74 +412,6 @@
|
||||||
)->getResponse()->getResult()) ?? SignatureVerificationStatus::INVALID;
|
)->getResponse()->getResult()) ?? SignatureVerificationStatus::INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function encryptionAcceptChannel(string $channelUuid, string $signatureUuid, string $encryptionPublicKey, string $encryptedTransportEncryptionKey, null|PeerAddress|string $identifiedAs=null): true
|
|
||||||
{
|
|
||||||
if($identifiedAs instanceof PeerAddress)
|
|
||||||
{
|
|
||||||
$identifiedAs = $identifiedAs->getAddress();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->sendRequest(
|
|
||||||
new RpcRequest(StandardMethods::ENCRYPTION_ACCEPT_CHANNEL, parameters: [
|
|
||||||
'channel_uuid' => $channelUuid,
|
|
||||||
'signature_uuid' => $signatureUuid,
|
|
||||||
'encryption_public_key' => $encryptionPublicKey,
|
|
||||||
'encrypted_transport_encryption_key' => $encryptedTransportEncryptionKey
|
|
||||||
]),
|
|
||||||
identifiedAs: $identifiedAs
|
|
||||||
)->getResponse()->getResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function encryptionCloseChannel(string $channelUuid, null|PeerAddress|string $identifiedAs=null): true
|
|
||||||
{
|
|
||||||
if($identifiedAs instanceof PeerAddress)
|
|
||||||
{
|
|
||||||
$identifiedAs = $identifiedAs->getAddress();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->sendRequest(
|
|
||||||
new RpcRequest(StandardMethods::ENCRYPTION_CLOSE_CHANNEL, parameters: [
|
|
||||||
'channel_uuid' => $channelUuid,
|
|
||||||
]),
|
|
||||||
identifiedAs: $identifiedAs
|
|
||||||
)->getResponse()->getResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Accepts an encryption channel request, returns True if the channel was accepted.
|
|
||||||
*
|
|
||||||
* @param PeerAddress|string $receivingPeer The address of the receiving peer that the channel is being requested to
|
|
||||||
* @param string $signatureUUid The UUID of the calling signature
|
|
||||||
* @param string $encryptionPublicKey The public key of the calling encryption key
|
|
||||||
* @param string $transportEncryptionAlgorithm The transport encryption algorithm to use
|
|
||||||
* @param string|null $identifyAs Optional. The address of the peer to identify as
|
|
||||||
* @param string|null $channelUuid Optional. If calling to an external server, the server must provide the other server the UUID to use
|
|
||||||
* @return string Returns True if the channel was accepted
|
|
||||||
* @throws RpcException Thrown if there was an error with the RPC request
|
|
||||||
*/
|
|
||||||
public function encryptionCreateChannel(
|
|
||||||
PeerAddress|string $receivingPeer, string $signatureUUid,
|
|
||||||
string $encryptionPublicKey, string $transportEncryptionAlgorithm='xchacha20',
|
|
||||||
?string $identifyAs=null, ?string $channelUuid=null
|
|
||||||
): string
|
|
||||||
{
|
|
||||||
if($receivingPeer instanceof PeerAddress)
|
|
||||||
{
|
|
||||||
$receivingPeer = $receivingPeer->getAddress();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->sendRequest(
|
|
||||||
new RpcRequest(StandardMethods::ENCRYPTION_CREATE_CHANNEL, parameters: [
|
|
||||||
'receiving_peer' => $receivingPeer,
|
|
||||||
'signature_uuid' => $signatureUUid,
|
|
||||||
'encryption_public_key' => $encryptionPublicKey,
|
|
||||||
'transport_encryption_algorithm' => $transportEncryptionAlgorithm,
|
|
||||||
'channel_uuid' => $channelUuid
|
|
||||||
]),
|
|
||||||
identifiedAs: $identifyAs
|
|
||||||
)->getResponse()->getResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Accepts the community guidelines, returns True if the guidelines were accepted.
|
* Accepts the community guidelines, returns True if the guidelines were accepted.
|
||||||
*
|
*
|
||||||
|
|
|
@ -200,7 +200,7 @@
|
||||||
// Prevent the peer from identifying as the host unless it's coming from an external domain
|
// Prevent the peer from identifying as the host unless it's coming from an external domain
|
||||||
if($clientRequest->getIdentifyAs()->getUsername() === ReservedUsernames::HOST->value)
|
if($clientRequest->getIdentifyAs()->getUsername() === ReservedUsernames::HOST->value)
|
||||||
{
|
{
|
||||||
self::returnError(403, StandardError::FORBIDDEN, 'Unauthorized: Not allowed to identify as the host');
|
self::returnError(403, StandardError::FORBIDDEN, 'Forbidden: Not allowed to identify as the host');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -225,7 +225,7 @@
|
||||||
}
|
}
|
||||||
catch (Exception $e)
|
catch (Exception $e)
|
||||||
{
|
{
|
||||||
self::returnError(502, StandardError::RESOLUTION_FAILED, 'Conflict: Failed to resolve the host domain: ' . $e->getMessage(), $e);
|
self::returnError(502, StandardError::RESOLUTION_FAILED, 'Conflict: Failed to resolve incoming host, ' . $e->getMessage(), $e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -258,14 +258,6 @@
|
||||||
RegisteredPeerManager::enablePeer($peerUuid);
|
RegisteredPeerManager::enablePeer($peerUuid);
|
||||||
$registeredPeer = RegisteredPeerManager::getPeer($peerUuid);
|
$registeredPeer = RegisteredPeerManager::getPeer($peerUuid);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// If the host is registered, but disabled, enable it
|
|
||||||
if(!$registeredPeer->isEnabled())
|
|
||||||
{
|
|
||||||
RegisteredPeerManager::enablePeer($registeredPeer->getUuid());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if($registeredPeer === null)
|
if($registeredPeer === null)
|
||||||
|
@ -355,7 +347,16 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
$session = $clientRequest->getSession();
|
$session = $clientRequest->getSession();
|
||||||
|
}
|
||||||
|
catch (DatabaseOperationException $e)
|
||||||
|
{
|
||||||
|
self::returnError(500, StandardError::INTERNAL_SERVER_ERROR, 'Failed to retrieve session', $e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if($session === null)
|
if($session === null)
|
||||||
{
|
{
|
||||||
self::returnError(404, StandardError::SESSION_NOT_FOUND, 'Session not found');
|
self::returnError(404, StandardError::SESSION_NOT_FOUND, 'Session not found');
|
||||||
|
@ -525,36 +526,41 @@
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$peer = $clientRequest->getPeer();
|
$hostPeer = $clientRequest->getPeer();
|
||||||
}
|
}
|
||||||
catch (DatabaseOperationException $e)
|
catch (DatabaseOperationException $e)
|
||||||
{
|
{
|
||||||
self::returnError(500, StandardError::INTERNAL_SERVER_ERROR, 'Failed to resolve host peer', $e);
|
self::returnError(500, StandardError::INTERNAL_SERVER_ERROR, 'Failed to resolve host peer', $e);
|
||||||
}
|
|
||||||
|
|
||||||
// First check if the client is identifying as the host
|
|
||||||
if($peer->getAddress() !== ReservedUsernames::HOST->value)
|
|
||||||
{
|
|
||||||
// TODO: Maybe allow user client to change identification but within an RPC method rather than the headers
|
|
||||||
self::returnError(403, StandardError::FORBIDDEN, 'Unauthorized: Not allowed to identify as a different peer');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($clientRequest->getIdentifyAs()->getDomain() != $)
|
// If for some reason the host peer was not found, this shouldn't happen.
|
||||||
|
if($hostPeer === null)
|
||||||
|
{
|
||||||
|
self::returnError(404, StandardError::INTERNAL_SERVER_ERROR, 'The host peer was not found in the system');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// First check if the client is identifying as the host
|
||||||
|
elseif($hostPeer->getAddress() !== ReservedUsernames::HOST->value)
|
||||||
|
{
|
||||||
|
self::returnError(403, StandardError::FORBIDDEN, 'Forbidden: External servers must identify as a host');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Secondly, check if the peer's server belongs to another server than the server is identified as
|
||||||
|
elseif($hostPeer->getServer() !== $clientRequest->getIdentifyAs()->getDomain())
|
||||||
|
{
|
||||||
|
self::returnError(403, StandardError::FORBIDDEN, 'Forbidden: Not allowed to identify as a peer outside from the host server');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Synchronize the peer
|
// Synchronize the peer
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
self::resolvePeer($clientRequest->getIdentifyAs());
|
self::resolvePeer($clientRequest->getIdentifyAs());
|
||||||
}
|
}
|
||||||
catch (DatabaseOperationException $e)
|
catch (StandardRpcException $e)
|
||||||
{
|
{
|
||||||
self::returnError(500, StandardError::INTERNAL_SERVER_ERROR, 'Failed to synchronize external peer', $e);
|
throw new ResolutionException(sprintf('Failed to resolve peer %s: %s', $clientRequest->getIdentifyAs()->getAddress(), $e->getMessage()), $e->getCode(), $e);
|
||||||
return;
|
|
||||||
}
|
|
||||||
catch (Exception $e)
|
|
||||||
{
|
|
||||||
throw new ResolutionException(sprintf('Failed to synchronize external peer %s: %s', $clientRequest->getIdentifyAs()->getAddress(), $e->getMessage()), $e->getCode(), $e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -568,68 +574,76 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(count($clientRequests) === 0)
|
||||||
|
{
|
||||||
|
Logger::getLogger()->warning(sprintf('Received no RPC requests from %s', $_SERVER['REMOTE_ADDR']));
|
||||||
|
http_response_code(204);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Logger::getLogger()->verbose(sprintf('Received %d RPC request(s) from %s', count($clientRequests), $_SERVER['REMOTE_ADDR']));
|
Logger::getLogger()->verbose(sprintf('Received %d RPC request(s) from %s', count($clientRequests), $_SERVER['REMOTE_ADDR']));
|
||||||
|
|
||||||
$results = [];
|
$results = [];
|
||||||
foreach($clientRequests as $rpcRequest)
|
foreach($clientRequests as $rpcRequest)
|
||||||
{
|
{
|
||||||
$method = StandardMethods::tryFrom($rpcRequest->getMethod());
|
$method = StandardMethods::tryFrom($rpcRequest->getMethod());
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
$method->checkAccess($clientRequest);
|
|
||||||
}
|
|
||||||
catch (StandardRpcException $e)
|
|
||||||
{
|
|
||||||
$response = $e->produceError($rpcRequest);
|
|
||||||
$results[] = $response->toArray();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($method === false)
|
if($method === false)
|
||||||
{
|
{
|
||||||
Logger::getLogger()->warning('The requested method does not exist');
|
Logger::getLogger()->warning('The requested method does not exist');
|
||||||
$response = $rpcRequest->produceError(StandardError::RPC_METHOD_NOT_FOUND, 'The requested method does not exist');
|
$results[] = $rpcRequest->produceError(StandardError::RPC_METHOD_NOT_FOUND, 'The requested method does not exist');
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
|
if (!$method->checkAccess($clientRequest))
|
||||||
|
{
|
||||||
|
$results[] = $rpcRequest->produceError(StandardError::METHOD_NOT_ALLOWED, 'Insufficient access requirements to invoke the session');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (DatabaseOperationException $e)
|
||||||
|
{
|
||||||
|
Logger::getLogger()->error('Failed to check method access', $e);
|
||||||
|
$results[] = $rpcRequest->produceError(StandardError::INTERNAL_SERVER_ERROR, 'Failed to check method access due to an internal server error');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
catch (StandardRpcException $e)
|
||||||
|
{
|
||||||
|
$results[] = $e->produceError($rpcRequest);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Logger::getLogger()->debug(sprintf('Processing RPC request for method %s', $rpcRequest->getMethod()));
|
Logger::getLogger()->debug(sprintf('Processing RPC request for method %s', $rpcRequest->getMethod()));
|
||||||
$response = $method->execute($clientRequest, $rpcRequest);
|
$results[] = $method->execute($clientRequest, $rpcRequest);
|
||||||
Logger::getLogger()->debug(sprintf('%s method executed successfully', $rpcRequest->getMethod()));
|
Logger::getLogger()->debug(sprintf('%s method executed successfully', $rpcRequest->getMethod()));
|
||||||
}
|
}
|
||||||
catch(StandardRpcException $e)
|
catch(StandardRpcException $e)
|
||||||
{
|
{
|
||||||
Logger::getLogger()->error('An error occurred while processing the RPC request', $e);
|
Logger::getLogger()->error('An error occurred while processing the RPC request', $e);
|
||||||
$response = $e->produceError($rpcRequest);
|
$results[] = $e->produceError($rpcRequest);
|
||||||
}
|
}
|
||||||
catch(Exception $e)
|
catch(Exception $e)
|
||||||
{
|
{
|
||||||
Logger::getLogger()->error('An internal error occurred while processing the RPC request', $e);
|
Logger::getLogger()->error('An internal error occurred while processing the RPC request', $e);
|
||||||
if(Configuration::getSecurityConfiguration()->isDisplayInternalExceptions())
|
if(Configuration::getSecurityConfiguration()->isDisplayInternalExceptions())
|
||||||
{
|
{
|
||||||
$response = $rpcRequest->produceError(StandardError::INTERNAL_SERVER_ERROR, Utilities::throwableToString($e));
|
$results[] = $rpcRequest->produceError(StandardError::INTERNAL_SERVER_ERROR, Utilities::throwableToString($e));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$response = $rpcRequest->produceError(StandardError::INTERNAL_SERVER_ERROR);
|
$results[] = $rpcRequest->produceError(StandardError::INTERNAL_SERVER_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($response !== null)
|
$results = array_map(fn($result) => $result->toArray(), $results);
|
||||||
{
|
|
||||||
Logger::getLogger()->debug(sprintf('Producing response for method %s', $rpcRequest->getMethod()));
|
|
||||||
$results[] = $response->toArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = null;
|
|
||||||
|
|
||||||
if(count($results) == 0)
|
if(count($results) == 0)
|
||||||
{
|
{
|
||||||
$response = null;
|
http_response_code(204);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
elseif(count($results) == 1)
|
elseif(count($results) == 1)
|
||||||
{
|
{
|
||||||
|
@ -640,12 +654,6 @@
|
||||||
$response = json_encode($results, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
$response = json_encode($results, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if($response === null)
|
|
||||||
{
|
|
||||||
http_response_code(204);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$session = $clientRequest->getSession();
|
$session = $clientRequest->getSession();
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
Loading…
Add table
Reference in a new issue