Made message signing in Cryptography use SHA512 as the message content for... #1
7 changed files with 272 additions and 47 deletions
1
.idea/sqldialects.xml
generated
1
.idea/sqldialects.xml
generated
|
@ -8,6 +8,7 @@
|
||||||
<file url="file://$PROJECT_DIR$/src/Socialbox/Classes/Resources/database/sessions.sql" dialect="MariaDB" />
|
<file url="file://$PROJECT_DIR$/src/Socialbox/Classes/Resources/database/sessions.sql" dialect="MariaDB" />
|
||||||
<file url="file://$PROJECT_DIR$/src/Socialbox/Classes/Resources/database/variables.sql" dialect="MariaDB" />
|
<file url="file://$PROJECT_DIR$/src/Socialbox/Classes/Resources/database/variables.sql" dialect="MariaDB" />
|
||||||
<file url="file://$PROJECT_DIR$/src/Socialbox/Managers/CaptchaManager.php" dialect="MariaDB" />
|
<file url="file://$PROJECT_DIR$/src/Socialbox/Managers/CaptchaManager.php" dialect="MariaDB" />
|
||||||
|
<file url="file://$PROJECT_DIR$/src/Socialbox/Managers/ExternalSessionManager.php" dialect="MariaDB" />
|
||||||
<file url="file://$PROJECT_DIR$/src/Socialbox/Managers/OneTimePasswordManager.php" dialect="MariaDB" />
|
<file url="file://$PROJECT_DIR$/src/Socialbox/Managers/OneTimePasswordManager.php" dialect="MariaDB" />
|
||||||
<file url="file://$PROJECT_DIR$/src/Socialbox/Managers/PasswordManager.php" dialect="MariaDB" />
|
<file url="file://$PROJECT_DIR$/src/Socialbox/Managers/PasswordManager.php" dialect="MariaDB" />
|
||||||
<file url="file://$PROJECT_DIR$/src/Socialbox/Managers/RegisteredPeerManager.php" dialect="MariaDB" />
|
<file url="file://$PROJECT_DIR$/src/Socialbox/Managers/RegisteredPeerManager.php" dialect="MariaDB" />
|
||||||
|
|
|
@ -1,35 +1,22 @@
|
||||||
create table external_sessions
|
create table external_sessions
|
||||||
(
|
(
|
||||||
uuid varchar(36) default uuid() not null comment 'The UUID of the session for the external connection'
|
domain varchar(256) not null comment 'The unique domain name that this session belongs to'
|
||||||
primary key comment 'The Unique Primary Index for the session UUID',
|
primary key comment 'The Unique Primary index for the external session',
|
||||||
peer_uuid varchar(36) not null comment 'The peer UUID that opened the connection',
|
rpc_endpoint text not null comment 'The RPC endpoint of the external connection',
|
||||||
session_uuid varchar(36) null comment 'The UUID of the parent session responsible for this external session',
|
session_uuid varchar(36) not null comment 'The UUID of the session to the external server',
|
||||||
server varchar(255) null comment 'The domain of the remote server that ths external session is authorized for',
|
transport_encryption_algorithm enum ('xchacha20', 'chacha20', 'aes256gcm') default 'xchacha20' not null comment 'The transport encryption algorithm used',
|
||||||
|
server_keypair_expires int not null comment 'The Timestamp for when the server keypair expires',
|
||||||
|
server_public_signing_key varchar(64) not null comment 'The public signing key of the server resolved from DNS records',
|
||||||
|
server_public_encryption_key varchar(64) not null comment 'The public encryption key of the server for this session',
|
||||||
|
host_public_encryption_key varchar(64) not null comment 'The public encryption key for the host',
|
||||||
|
host_private_encryption_key varchar(64) not null comment 'The private encryption key for host',
|
||||||
|
private_shared_secret varchar(64) not null comment 'The private shared secret obtained from the DHE procedure',
|
||||||
|
host_transport_encryption_key varchar(64) not null comment 'The transport encryption key for the host',
|
||||||
|
server_transport_encryption_key varchar(64) not null comment 'The transport encryption key for the server',
|
||||||
|
last_accessed timestamp default current_timestamp() not null comment 'The Timestamp for when the record was last accessed',
|
||||||
created timestamp default current_timestamp() not null comment 'The Timestamp for when this record was created',
|
created timestamp default current_timestamp() not null comment 'The Timestamp for when this record was created',
|
||||||
last_used timestamp default current_timestamp() not null comment 'The Timestamp for when this session was last used',
|
constraint external_sessions_domain_uindex
|
||||||
constraint external_sessions_uuid_uindex
|
unique (domain) comment 'The Unique Primary index for the external session'
|
||||||
unique (uuid) comment 'The Unique Primary Index for the session UUID',
|
|
||||||
constraint external_sessions_registered_peers_uuid_fk
|
|
||||||
foreign key (peer_uuid) references registered_peers (uuid)
|
|
||||||
on update cascade on delete cascade,
|
|
||||||
constraint external_sessions_sessions_uuid_fk
|
|
||||||
foreign key (session_uuid) references sessions (uuid)
|
|
||||||
)
|
)
|
||||||
comment 'Table for housing external sessions from local to remote servers';
|
comment 'Table for housing external sessions to external servers';
|
||||||
|
|
||||||
create index external_sessions_created_index
|
|
||||||
on external_sessions (created)
|
|
||||||
comment 'The Index for the created column';
|
|
||||||
|
|
||||||
create index external_sessions_last_used_index
|
|
||||||
on external_sessions (last_used)
|
|
||||||
comment 'The inex for the last used column';
|
|
||||||
|
|
||||||
create index external_sessions_peer_uuid_index
|
|
||||||
on external_sessions (peer_uuid)
|
|
||||||
comment 'The Index for the peer UUID';
|
|
||||||
|
|
||||||
create index external_sessions_session_uuid_index
|
|
||||||
on external_sessions (session_uuid)
|
|
||||||
comment 'The index for the original session uuid';
|
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
use Socialbox\Enums\StandardHeaders;
|
use Socialbox\Enums\StandardHeaders;
|
||||||
use Socialbox\Enums\Types\RequestType;
|
use Socialbox\Enums\Types\RequestType;
|
||||||
use Socialbox\Exceptions\CryptographyException;
|
use Socialbox\Exceptions\CryptographyException;
|
||||||
|
use Socialbox\Exceptions\DatabaseOperationException;
|
||||||
use Socialbox\Exceptions\ResolutionException;
|
use Socialbox\Exceptions\ResolutionException;
|
||||||
use Socialbox\Exceptions\RpcException;
|
use Socialbox\Exceptions\RpcException;
|
||||||
use Socialbox\Objects\ExportedSession;
|
use Socialbox\Objects\ExportedSession;
|
||||||
|
@ -21,7 +22,7 @@
|
||||||
private const string CLIENT_VERSION = '1.0';
|
private const string CLIENT_VERSION = '1.0';
|
||||||
|
|
||||||
private bool $bypassSignatureVerification;
|
private bool $bypassSignatureVerification;
|
||||||
private PeerAddress $peerAddress;
|
private PeerAddress $identifiedAs;
|
||||||
private string $serverPublicSigningKey;
|
private string $serverPublicSigningKey;
|
||||||
private string $serverPublicEncryptionKey;
|
private string $serverPublicEncryptionKey;
|
||||||
private KeyPair $clientSigningKeyPair;
|
private KeyPair $clientSigningKeyPair;
|
||||||
|
@ -31,18 +32,21 @@
|
||||||
private string $serverTransportEncryptionKey;
|
private string $serverTransportEncryptionKey;
|
||||||
private ServerInformation $serverInformation;
|
private ServerInformation $serverInformation;
|
||||||
private string $rpcEndpoint;
|
private string $rpcEndpoint;
|
||||||
|
private string $remoteServer;
|
||||||
private string $sessionUuid;
|
private string $sessionUuid;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new instance with the specified peer address.
|
* Constructs a new instance with the specified peer address.
|
||||||
*
|
*
|
||||||
* @param string|PeerAddress $peerAddress The peer address to be used for the instance (eg; johndoe@example.com)
|
* @param string|PeerAddress $identifiedAs The peer address to be used for the instance (eg; johndoe@example.com)
|
||||||
|
* @param string|null $server Optional. The domain of the server to connect to if different from the identified
|
||||||
* @param ExportedSession|null $exportedSession Optional. An exported session to be used to re-connect.
|
* @param ExportedSession|null $exportedSession Optional. An exported session to be used to re-connect.
|
||||||
* @throws CryptographyException If there is an error in the cryptographic operations.
|
* @throws CryptographyException If there is an error in the cryptographic operations.
|
||||||
* @throws RpcException If there is an error in the RPC request or if no response is received.
|
|
||||||
* @throws ResolutionException If there is an error in the resolution process.
|
* @throws ResolutionException If there is an error in the resolution process.
|
||||||
|
* @throws RpcException If there is an error in the RPC request or if no response is received.
|
||||||
|
* @throws DatabaseOperationException
|
||||||
*/
|
*/
|
||||||
public function __construct(string|PeerAddress $peerAddress, ?ExportedSession $exportedSession=null)
|
public function __construct(string|PeerAddress $identifiedAs, ?string $server=null, ?ExportedSession $exportedSession=null)
|
||||||
{
|
{
|
||||||
$this->bypassSignatureVerification = false;
|
$this->bypassSignatureVerification = false;
|
||||||
|
|
||||||
|
@ -56,8 +60,9 @@
|
||||||
throw new RpcException('The server keypair has expired, a new session must be created');
|
throw new RpcException('The server keypair has expired, a new session must be created');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->peerAddress = PeerAddress::fromAddress($exportedSession->getPeerAddress());
|
$this->identifiedAs = PeerAddress::fromAddress($exportedSession->getPeerAddress());
|
||||||
$this->rpcEndpoint = $exportedSession->getRpcEndpoint();
|
$this->rpcEndpoint = $exportedSession->getRpcEndpoint();
|
||||||
|
$this->remoteServer = $exportedSession->getRemoteServer();
|
||||||
$this->sessionUuid = $exportedSession->getSessionUuid();
|
$this->sessionUuid = $exportedSession->getSessionUuid();
|
||||||
$this->serverPublicSigningKey = $exportedSession->getServerPublicSigningKey();
|
$this->serverPublicSigningKey = $exportedSession->getServerPublicSigningKey();
|
||||||
$this->serverPublicEncryptionKey = $exportedSession->getServerPublicEncryptionKey();
|
$this->serverPublicEncryptionKey = $exportedSession->getServerPublicEncryptionKey();
|
||||||
|
@ -86,16 +91,17 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the peer address is a string, we need to convert it to a PeerAddress object
|
// If the peer address is a string, we need to convert it to a PeerAddress object
|
||||||
if(is_string($peerAddress))
|
if(is_string($identifiedAs))
|
||||||
{
|
{
|
||||||
$peerAddress = PeerAddress::fromAddress($peerAddress);
|
$identifiedAs = PeerAddress::fromAddress($identifiedAs);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the initial properties
|
// Set the initial properties
|
||||||
$this->peerAddress = $peerAddress;
|
$this->identifiedAs = $identifiedAs;
|
||||||
|
$this->remoteServer = $server ?? $identifiedAs->getDomain();
|
||||||
|
|
||||||
// Resolve the domain and get the server's Public Key & RPC Endpoint
|
// Resolve the domain and get the server's Public Key & RPC Endpoint
|
||||||
$resolvedServer = ServerResolver::resolveDomain($this->peerAddress->getDomain(), false);
|
$resolvedServer = ServerResolver::resolveDomain($this->remoteServer, false);
|
||||||
|
|
||||||
// Import the RPC Endpoint & the server's public key.
|
// Import the RPC Endpoint & the server's public key.
|
||||||
$this->serverPublicSigningKey = $resolvedServer->getPublicSigningKey();
|
$this->serverPublicSigningKey = $resolvedServer->getPublicSigningKey();
|
||||||
|
@ -117,7 +123,7 @@
|
||||||
|
|
||||||
// If the username is `host` and the domain is the same as this server's domain, we use our signing keypair
|
// If the username is `host` and the domain is the same as this server's domain, we use our signing keypair
|
||||||
// Essentially this is a special case for the server to contact another server
|
// Essentially this is a special case for the server to contact another server
|
||||||
if($this->peerAddress->isHost())
|
if($this->identifiedAs->isHost())
|
||||||
{
|
{
|
||||||
$this->clientSigningKeyPair = new KeyPair(Configuration::getCryptographyConfiguration()->getHostPublicKey(), Configuration::getCryptographyConfiguration()->getHostPrivateKey());
|
$this->clientSigningKeyPair = new KeyPair(Configuration::getCryptographyConfiguration()->getHostPublicKey(), Configuration::getCryptographyConfiguration()->getHostPrivateKey());
|
||||||
}
|
}
|
||||||
|
@ -157,14 +163,14 @@
|
||||||
StandardHeaders::REQUEST_TYPE->value . ': ' . RequestType::INITIATE_SESSION->value,
|
StandardHeaders::REQUEST_TYPE->value . ': ' . RequestType::INITIATE_SESSION->value,
|
||||||
StandardHeaders::CLIENT_NAME->value . ': ' . self::CLIENT_NAME,
|
StandardHeaders::CLIENT_NAME->value . ': ' . self::CLIENT_NAME,
|
||||||
StandardHeaders::CLIENT_VERSION->value . ': ' . self::CLIENT_VERSION,
|
StandardHeaders::CLIENT_VERSION->value . ': ' . self::CLIENT_VERSION,
|
||||||
StandardHeaders::IDENTIFY_AS->value . ': ' . $this->peerAddress->getAddress(),
|
StandardHeaders::IDENTIFY_AS->value . ': ' . $this->identifiedAs->getAddress(),
|
||||||
// Always provide our generated encrypted public key
|
// Always provide our generated encrypted public key
|
||||||
StandardHeaders::ENCRYPTION_PUBLIC_KEY->value . ': ' . $this->clientEncryptionKeyPair->getPublicKey()
|
StandardHeaders::ENCRYPTION_PUBLIC_KEY->value . ': ' . $this->clientEncryptionKeyPair->getPublicKey()
|
||||||
];
|
];
|
||||||
|
|
||||||
// If we're not connecting as the host, we need to provide our public key
|
// If we're not connecting as the host, we need to provide our public key
|
||||||
// Otherwise, the server will obtain the public key itself from DNS records rather than trusting the client
|
// Otherwise, the server will obtain the public key itself from DNS records rather than trusting the client
|
||||||
if(!$this->peerAddress->isHost())
|
if(!$this->identifiedAs->isHost())
|
||||||
{
|
{
|
||||||
$headers[] = StandardHeaders::SIGNING_PUBLIC_KEY->value . ': ' . $this->clientSigningKeyPair->getPublicKey();
|
$headers[] = StandardHeaders::SIGNING_PUBLIC_KEY->value . ': ' . $this->clientSigningKeyPair->getPublicKey();
|
||||||
}
|
}
|
||||||
|
@ -567,8 +573,9 @@
|
||||||
public function exportSession(): ExportedSession
|
public function exportSession(): ExportedSession
|
||||||
{
|
{
|
||||||
return new ExportedSession([
|
return new ExportedSession([
|
||||||
'peer_address' => $this->peerAddress->getAddress(),
|
'peer_address' => $this->identifiedAs->getAddress(),
|
||||||
'rpc_endpoint' => $this->rpcEndpoint,
|
'rpc_endpoint' => $this->rpcEndpoint,
|
||||||
|
'remote_server' => $this->remoteServer,
|
||||||
'session_uuid' => $this->sessionUuid,
|
'session_uuid' => $this->sessionUuid,
|
||||||
'transport_encryption_algorithm' => $this->serverInformation->getTransportEncryptionAlgorithm(),
|
'transport_encryption_algorithm' => $this->serverInformation->getTransportEncryptionAlgorithm(),
|
||||||
'server_keypair_expires' => $this->serverInformation->getServerKeypairExpires(),
|
'server_keypair_expires' => $this->serverInformation->getServerKeypairExpires(),
|
||||||
|
|
167
src/Socialbox/Managers/ExternalSessionManager.php
Normal file
167
src/Socialbox/Managers/ExternalSessionManager.php
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Socialbox\Managers;
|
||||||
|
|
||||||
|
use PDOException;
|
||||||
|
use Socialbox\Classes\Configuration;
|
||||||
|
use Socialbox\Classes\Database;
|
||||||
|
use Socialbox\Enums\ReservedUsernames;
|
||||||
|
use Socialbox\Exceptions\DatabaseOperationException;
|
||||||
|
use Socialbox\Objects\ExportedSession;
|
||||||
|
|
||||||
|
class ExternalSessionManager
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Checks if a session exists in the database for the specified domain.
|
||||||
|
*
|
||||||
|
* @param string $domain The domain to check for an existing session in the external_sessions table.
|
||||||
|
* @return bool Returns true if a session exists for the specified domain, otherwise false.
|
||||||
|
* @throws DatabaseOperationException If the database operation fails.
|
||||||
|
*/
|
||||||
|
public static function sessionExists(string $domain): bool
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$stmt = Database::getConnection()->prepare("SELECT COUNT(*) FROM external_sessions WHERE domain=:domain LIMIT 1");
|
||||||
|
$stmt->bindParam(':domain', $domain);
|
||||||
|
$stmt->execute();
|
||||||
|
|
||||||
|
return $stmt->fetchColumn() > 0;
|
||||||
|
}
|
||||||
|
catch(PDOException $e)
|
||||||
|
{
|
||||||
|
throw new DatabaseOperationException('Failed to check if a session exists in the database', $e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new external session to the database.
|
||||||
|
*
|
||||||
|
* @param ExportedSession $exportedSession The session data to be added, containing all necessary attributes
|
||||||
|
* such as server keys, client keys, and other metadata.
|
||||||
|
* @return void
|
||||||
|
* @throws DatabaseOperationException If the database operation fails.
|
||||||
|
*/
|
||||||
|
public static function addSession(ExportedSession $exportedSession): void
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$stmt = Database::getConnection()->prepare("INSERT INTO external_sessions (domain, rpc_endpoint, session_uuid, server_keypair_expires, server_public_signing_key, server_public_encryption_key, host_public_encryption_key, host_private_encryption_key, private_shared_secret, host_transport_encryption_key, server_transport_encryption_key) VALUES (:domain, :rpc_endpoint, :session_uuid, :server_keypair_expires, :server_public_signing_key, :server_public_encryption_key, :host_public_encryption_key, :host_private_encryption_key, :private_shared_secret, :host_transport_encryption_key, :server_transport_encryption_key)");
|
||||||
|
$domain = $exportedSession->getRemoteServer();
|
||||||
|
$stmt->bindParam(':domain', $domain);
|
||||||
|
$rpcEndpoint = $exportedSession->getRpcEndpoint();
|
||||||
|
$stmt->bindParam(':rpc_endpoint', $rpcEndpoint);
|
||||||
|
$sessionUuid = $exportedSession->getSessionUuid();
|
||||||
|
$stmt->bindParam(':session_uuid', $sessionUuid);
|
||||||
|
$serverKeypairExpires = $exportedSession->getServerKeypairExpires();
|
||||||
|
$stmt->bindParam(':server_keypair_expires', $serverKeypairExpires);
|
||||||
|
$serverPublicSigningKey = $exportedSession->getServerPublicSigningKey();
|
||||||
|
$stmt->bindParam(':server_public_signing_key', $serverPublicSigningKey);
|
||||||
|
$serverPublicEncryptionKey = $exportedSession->getServerPublicEncryptionKey();
|
||||||
|
$stmt->bindParam(':server_public_encryption_key', $serverPublicEncryptionKey);
|
||||||
|
$hostPublicEncryptionKey = $exportedSession->getClientPublicEncryptionKey();
|
||||||
|
$stmt->bindParam(':host_public_encryption_key', $hostPublicEncryptionKey);
|
||||||
|
$hostPrivateEncryptionKey = $exportedSession->getClientPrivateEncryptionKey();
|
||||||
|
$stmt->bindParam(':host_private_encryption_key', $hostPrivateEncryptionKey);
|
||||||
|
$privateSharedSecret = $exportedSession->getPrivateSharedSecret();
|
||||||
|
$stmt->bindParam(':private_shared_secret', $privateSharedSecret);
|
||||||
|
$hostTransportEncryptionKey = $exportedSession->getClientTransportEncryptionKey();
|
||||||
|
$stmt->bindParam(':host_transport_encryption_key', $hostTransportEncryptionKey);
|
||||||
|
$serverTransportEncryptionKey = $exportedSession->getServerTransportEncryptionKey();
|
||||||
|
$stmt->bindParam(':server_transport_encryption_key', $serverTransportEncryptionKey);
|
||||||
|
|
||||||
|
$stmt->execute();
|
||||||
|
}
|
||||||
|
catch(PDOException $e)
|
||||||
|
{
|
||||||
|
throw new DatabaseOperationException('Failed to add a session to the database', $e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a session associated with the specified domain from the database.
|
||||||
|
*
|
||||||
|
* @param string $domain The domain for which the session should be retrieved.
|
||||||
|
* @return ExportedSession|null The retrieved session as an ExportedSession object, or null if no session is found.
|
||||||
|
* @throws DatabaseOperationException If the operation fails due to a database error.
|
||||||
|
*/
|
||||||
|
public static function getSession(string $domain): ?ExportedSession
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$stmt = Database::getConnection()->prepare("SELECT * FROM external_sessions WHERE domain=:domain LIMIT 1");
|
||||||
|
$stmt->bindParam(':domain', $domain);
|
||||||
|
$stmt->execute();
|
||||||
|
$result = $stmt->fetch();
|
||||||
|
|
||||||
|
if($result === false)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(PDOException $e)
|
||||||
|
{
|
||||||
|
throw new DatabaseOperationException('Failed to retrieve the session from the database', $e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ExportedSession::fromArray([
|
||||||
|
'peer_address' => sprintf('%s@%s', ReservedUsernames::HOST->value, Configuration::getInstanceConfiguration()->getDomain()),
|
||||||
|
'rpc_endpoint' => $result['rpc_endpoint'],
|
||||||
|
'remote_server' => $result['domain'],
|
||||||
|
'session_uuid' => $result['session_uuid'],
|
||||||
|
'transport_encryption_algorithm' => $result['transport_encryption_algorithm'],
|
||||||
|
'server_keypair_expires' => $result['server_keypair_expires'],
|
||||||
|
'server_public_encryption_key' => $result['server_public_encryption_key'],
|
||||||
|
'client_public_signing_key' => Configuration::getCryptographyConfiguration()->getHostPublicKey(),
|
||||||
|
'client_private_signing_key' => Configuration::getCryptographyConfiguration()->getHostPrivateKey(),
|
||||||
|
'client_public_encryption_key' => $result['host_public_encryption_key'],
|
||||||
|
'client_private_encryption_key' => $result['host_private_encryption_key'],
|
||||||
|
'private_shared_secret' => $result['private_shared_secret'],
|
||||||
|
'client_transport_encryption_key' => $result['host_transport_encryption_key'],
|
||||||
|
'server_transport_encryption_key' => $result['server_transport_encryption_key']
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a session associated with the specified domain from the database.
|
||||||
|
*
|
||||||
|
* @param string $domain The domain for which the session should be removed.
|
||||||
|
* @return void
|
||||||
|
* @throws DatabaseOperationException If the operation fails due to a database error.
|
||||||
|
*/
|
||||||
|
public static function removeSession(string $domain): void
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$stmt = Database::getConnection()->prepare("DELETE FROM external_sessions WHERE domain=:domain");
|
||||||
|
$stmt->bindParam(':domain', $domain);
|
||||||
|
$stmt->execute();
|
||||||
|
}
|
||||||
|
catch(PDOException $e)
|
||||||
|
{
|
||||||
|
throw new DatabaseOperationException('Failed to remove a session from the database', $e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the last accessed timestamp for a specific external session in the database.
|
||||||
|
*
|
||||||
|
* @param string $domain The domain associated with the external session to update.
|
||||||
|
* @return void
|
||||||
|
* @throws DatabaseOperationException If the update operation fails.
|
||||||
|
*/
|
||||||
|
public static function updateLastAccessed(string $domain): void
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$stmt = Database::getConnection()->prepare("UPDATE external_sessions SET last_accessed=CURRENT_TIMESTAMP WHERE domain=:domain");
|
||||||
|
$stmt->bindParam(':domain', $domain);
|
||||||
|
$stmt->execute();
|
||||||
|
}
|
||||||
|
catch(PDOException $e)
|
||||||
|
{
|
||||||
|
throw new DatabaseOperationException('Failed to update the last accessed time of a session in the database', $e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,7 @@
|
||||||
{
|
{
|
||||||
private string $peerAddress;
|
private string $peerAddress;
|
||||||
private string $rpcEndpoint;
|
private string $rpcEndpoint;
|
||||||
|
private string $remoteServer;
|
||||||
private string $sessionUUID;
|
private string $sessionUUID;
|
||||||
private string $transportEncryptionAlgorithm;
|
private string $transportEncryptionAlgorithm;
|
||||||
private int $serverKeypairExpires;
|
private int $serverKeypairExpires;
|
||||||
|
@ -41,6 +42,7 @@
|
||||||
{
|
{
|
||||||
$this->peerAddress = $data['peer_address'];
|
$this->peerAddress = $data['peer_address'];
|
||||||
$this->rpcEndpoint = $data['rpc_endpoint'];
|
$this->rpcEndpoint = $data['rpc_endpoint'];
|
||||||
|
$this->remoteServer = $data['remote_server'];
|
||||||
$this->sessionUUID = $data['session_uuid'];
|
$this->sessionUUID = $data['session_uuid'];
|
||||||
$this->transportEncryptionAlgorithm = $data['transport_encryption_algorithm'];
|
$this->transportEncryptionAlgorithm = $data['transport_encryption_algorithm'];
|
||||||
$this->serverKeypairExpires = $data['server_keypair_expires'];
|
$this->serverKeypairExpires = $data['server_keypair_expires'];
|
||||||
|
@ -75,6 +77,16 @@
|
||||||
return $this->rpcEndpoint;
|
return $this->rpcEndpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the remote server.
|
||||||
|
*
|
||||||
|
* @return string The remote server.
|
||||||
|
*/
|
||||||
|
public function getRemoteServer(): string
|
||||||
|
{
|
||||||
|
return $this->remoteServer;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the session UUID associated with the current instance.
|
* Retrieves the session UUID associated with the current instance.
|
||||||
*
|
*
|
||||||
|
@ -203,6 +215,7 @@
|
||||||
return [
|
return [
|
||||||
'peer_address' => $this->peerAddress,
|
'peer_address' => $this->peerAddress,
|
||||||
'rpc_endpoint' => $this->rpcEndpoint,
|
'rpc_endpoint' => $this->rpcEndpoint,
|
||||||
|
'remote_server' => $this->remoteServer,
|
||||||
'session_uuid' => $this->sessionUUID,
|
'session_uuid' => $this->sessionUUID,
|
||||||
'transport_encryption_algorithm' => $this->transportEncryptionAlgorithm,
|
'transport_encryption_algorithm' => $this->transportEncryptionAlgorithm,
|
||||||
'server_keypair_expires' => $this->serverKeypairExpires,
|
'server_keypair_expires' => $this->serverKeypairExpires,
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
use Socialbox\Classes\Utilities;
|
use Socialbox\Classes\Utilities;
|
||||||
use Socialbox\Enums\StandardMethods;
|
use Socialbox\Enums\StandardMethods;
|
||||||
use Socialbox\Exceptions\CryptographyException;
|
use Socialbox\Exceptions\CryptographyException;
|
||||||
|
use Socialbox\Exceptions\DatabaseOperationException;
|
||||||
use Socialbox\Exceptions\ResolutionException;
|
use Socialbox\Exceptions\ResolutionException;
|
||||||
use Socialbox\Exceptions\RpcException;
|
use Socialbox\Exceptions\RpcException;
|
||||||
use Socialbox\Objects\ExportedSession;
|
use Socialbox\Objects\ExportedSession;
|
||||||
|
@ -22,15 +23,17 @@
|
||||||
/**
|
/**
|
||||||
* Constructs the object from an array of data.
|
* Constructs the object from an array of data.
|
||||||
*
|
*
|
||||||
* @param string|PeerAddress $peerAddress The address of the peer to connect to.
|
* @param string|PeerAddress $identifiedAs The address of the peer to connect to.
|
||||||
|
* @param string|null $server Optional. The domain of the server to connect to if different from the identified
|
||||||
* @param ExportedSession|null $exportedSession Optional. The exported session to use for communication.
|
* @param ExportedSession|null $exportedSession Optional. The exported session to use for communication.
|
||||||
* @throws CryptographyException If the public key is invalid.
|
* @throws CryptographyException If the public key is invalid.
|
||||||
|
* @throws DatabaseOperationException If the database operation fails.
|
||||||
* @throws ResolutionException If the domain cannot be resolved.
|
* @throws ResolutionException If the domain cannot be resolved.
|
||||||
* @throws RpcException If the RPC request fails.
|
* @throws RpcException If the RPC request fails.
|
||||||
*/
|
*/
|
||||||
public function __construct(string|PeerAddress $peerAddress, ?ExportedSession $exportedSession=null)
|
public function __construct(string|PeerAddress $identifiedAs, ?string $server=null, ?ExportedSession $exportedSession=null)
|
||||||
{
|
{
|
||||||
parent::__construct($peerAddress, $exportedSession);
|
parent::__construct($identifiedAs, $server, $exportedSession);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
use Socialbox\Classes\Cryptography;
|
use Socialbox\Classes\Cryptography;
|
||||||
use Socialbox\Classes\DnsHelper;
|
use Socialbox\Classes\DnsHelper;
|
||||||
use Socialbox\Classes\Logger;
|
use Socialbox\Classes\Logger;
|
||||||
|
use Socialbox\Classes\RpcClient;
|
||||||
use Socialbox\Classes\ServerResolver;
|
use Socialbox\Classes\ServerResolver;
|
||||||
use Socialbox\Classes\Utilities;
|
use Socialbox\Classes\Utilities;
|
||||||
use Socialbox\Classes\Validator;
|
use Socialbox\Classes\Validator;
|
||||||
|
@ -20,7 +21,10 @@
|
||||||
use Socialbox\Exceptions\CryptographyException;
|
use Socialbox\Exceptions\CryptographyException;
|
||||||
use Socialbox\Exceptions\DatabaseOperationException;
|
use Socialbox\Exceptions\DatabaseOperationException;
|
||||||
use Socialbox\Exceptions\RequestException;
|
use Socialbox\Exceptions\RequestException;
|
||||||
|
use Socialbox\Exceptions\ResolutionException;
|
||||||
|
use Socialbox\Exceptions\RpcException;
|
||||||
use Socialbox\Exceptions\StandardException;
|
use Socialbox\Exceptions\StandardException;
|
||||||
|
use Socialbox\Managers\ExternalSessionManager;
|
||||||
use Socialbox\Managers\RegisteredPeerManager;
|
use Socialbox\Managers\RegisteredPeerManager;
|
||||||
use Socialbox\Managers\SessionManager;
|
use Socialbox\Managers\SessionManager;
|
||||||
use Socialbox\Objects\ClientRequest;
|
use Socialbox\Objects\ClientRequest;
|
||||||
|
@ -598,6 +602,39 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves an external session associated with the given domain.
|
||||||
|
*
|
||||||
|
* If a session already exists for the specified domain, it retrieves and uses the existing session.
|
||||||
|
* Otherwise, it establishes a new connection, creates a session, and stores it for later use.
|
||||||
|
*
|
||||||
|
* @param string $domain The domain for which the external session is to be retrieved.
|
||||||
|
* @return RpcClient The RPC client initialized with the external session for the given domain.
|
||||||
|
* @throws CryptographyException If there was an error in the cryptography
|
||||||
|
* @throws DatabaseOperationException If there was an error while processing the session against the database
|
||||||
|
* @throws RpcException If there is an RPC exception while connecting to the remote server
|
||||||
|
* @throws ResolutionException If the connection to the remote server fails.
|
||||||
|
*/
|
||||||
|
public static function getExternalSession(string $domain): RpcClient
|
||||||
|
{
|
||||||
|
if(ExternalSessionManager::sessionExists($domain))
|
||||||
|
{
|
||||||
|
return new SocialClient(self::getServerAddress(), $domain, ExternalSessionManager::getSession($domain));
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$client = new SocialClient(self::getServerAddress(), $domain);
|
||||||
|
}
|
||||||
|
catch (Exception $e)
|
||||||
|
{
|
||||||
|
throw new ResolutionException(sprintf('Failed to connect to remote server %s: %s', $domain, $e->getMessage()), $e->getCode(), $e);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExternalSessionManager::addSession($client->exportSession());
|
||||||
|
return $client;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the server information by assembling data from the configuration settings.
|
* Retrieves the server information by assembling data from the configuration settings.
|
||||||
*
|
*
|
||||||
|
@ -613,6 +650,16 @@
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the server address.
|
||||||
|
*
|
||||||
|
* @return PeerAddress The constructed server address containing the host and domain information.
|
||||||
|
*/
|
||||||
|
public static function getServerAddress(): PeerAddress
|
||||||
|
{
|
||||||
|
return new PeerAddress(ReservedUsernames::HOST->value, Configuration::getInstanceConfiguration()->getDomain());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the DNS record by generating a TXT record using the RPC endpoint,
|
* Retrieves the DNS record by generating a TXT record using the RPC endpoint,
|
||||||
* host public key, and host key pair expiration from the configuration.
|
* host public key, and host key pair expiration from the configuration.
|
||||||
|
|
Loading…
Add table
Reference in a new issue