12#include "../3rdparty/catch2/catch.hpp"
27 MockNetworkSocketHandler(std::unique_ptr<NetworkEncryptionHandler> &&receive = {}, std::unique_ptr<NetworkEncryptionHandler> &&send = {})
42 auto transfer_in = [&source](std::span<uint8_t> dest_data) {
43 auto transfer_out = [&dest_data](std::span<const uint8_t> source_data) {
44 std::ranges::copy(source_data, dest_data.begin());
45 return source_data.size();
49 dest.TransferIn(transfer_in);
51 bool valid = dest.PrepareToRead();
53 return { dest, valid };
60 TestPasswordRequestHandler(std::string &password) :
password(password) {}
62 void AskUserForPassword(std::shared_ptr<NetworkAuthenticationPasswordRequest> request)
override { request->Reply(this->password); }
73 std::tie(request, valid) = CreatePacketForReading(request, &mock_socket_handler);
80 std::tie(response, valid) = CreatePacketForReading(response, &mock_socket_handler);
86TEST_CASE(
"Authentication_KeyExchangeOnly")
95static void TestAuthenticationPAKE(std::string server_password, std::string client_password,
105TEST_CASE(
"Authentication_PAKE")
107 SECTION(
"Correct password") {
111 SECTION(
"Empty password") {
115 SECTION(
"Wrong password") {
134TEST_CASE(
"Authentication_AuthorizedKey")
140 SECTION(
"Correct public key") {
144 SECTION(
"Incorrect public key") {
150TEST_CASE(
"Authentication_Combined")
158 valid_authorized_keys.
Add(client_public_key_str);
162 invalid_authorized_keys.
Add(
"not-a-valid-authorized-key");
168 std::string no_password =
"";
170 std::string valid_password =
"sikrit";
172 std::string invalid_password =
"secret";
177 SECTION(
"Invalid authorized keys, invalid password") {
184 SECTION(
"Invalid authorized keys, valid password") {
191 SECTION(
"Valid authorized keys, valid password") {
197 SECTION(
"No authorized keys, invalid password") {
203 SECTION(
"No authorized keys, valid password") {
209 SECTION(
"No authorized keys, no password") {
220 uint64_t sent_value = 0x1234567890ABCDEF;
221 std::set<PacketType> encrypted_packet_types;
223 for (
int i = 0; i < 10; i++) {
224 Packet request(sending_socket_handler, sent_packet_type);
225 request.Send_uint64(sent_value);
227 auto [response, valid] = CreatePacketForReading(request, receiving_socket_handler);
229 CHECK(response.Recv_uint64() == sent_value);
231 encrypted_packet_types.insert(request.GetPacketType());
244 CHECK(encrypted_packet_types.size() != 1);
248TEST_CASE(
"Encryption handling")
259 std::tie(packet, valid) = CreatePacketForReading(packet, &mock_socket_handler);
266 SECTION(
"Encryption happening client -> server") {
267 CheckEncryption(&client_socket_handler, &server_socket_handler);
270 SECTION(
"Encryption happening server -> client") {
271 CheckEncryption(&server_socket_handler, &client_socket_handler);
274 SECTION(
"Unencrypted packet sent causes invalid read packet") {
278 auto [response, valid] = CreatePacketForReading(request, &client_socket_handler);
Base class for client side cryptographic authentication handlers.
RequestResult
The processing result of receiving a request.
@ AwaitUserInput
We have requested some user input, but must wait on that.
@ ReadyForResponse
We do not have to wait for user input, and can immediately respond to the server.
virtual bool ReceiveEnableEncryption(struct Packet &p)=0
Read the request to enable encryption from the server.
virtual RequestResult ReceiveRequest(struct Packet &p)=0
Read a request from the server.
virtual bool SendResponse(struct Packet &p)=0
Create the response to send to the server.
static std::unique_ptr< NetworkAuthenticationClientHandler > Create(std::shared_ptr< NetworkAuthenticationPasswordRequestHandler > password_handler, std::string &secret_key, std::string &public_key)
Create a NetworkAuthenticationClientHandler.
Default implementation for the authorized key handler.
Default implementation of the password provider.
virtual std::unique_ptr< NetworkEncryptionHandler > CreateServerToClientEncryptionHandler() const =0
Create a NetworkEncryptionHandler to encrypt or decrypt messages from the server to the client.
virtual std::unique_ptr< NetworkEncryptionHandler > CreateClientToServerEncryptionHandler() const =0
Create a NetworkEncryptionHandler to encrypt or decrypt messages from the client to the server.
Callback interface for client implementations to provide the handling of the password requests.
std::string password
The entered password.
Base class for server side cryptographic authentication handlers.
virtual ResponseResult ReceiveResponse(struct Packet &p)=0
Read the response from the client.
virtual void SendEnableEncryption(struct Packet &p)=0
Create the request to enable encryption to the client.
virtual void SendRequest(struct Packet &p)=0
Create the request to send to the client.
static std::unique_ptr< NetworkAuthenticationServerHandler > Create(const NetworkAuthenticationPasswordProvider *password_provider, const NetworkAuthenticationAuthorizedKeyHandler *authorized_key_handler, NetworkAuthenticationMethodMask client_supported_method_mask={NetworkAuthenticationMethod::X25519_KeyExchangeOnly, NetworkAuthenticationMethod::X25519_PAKE, NetworkAuthenticationMethod::X25519_AuthorizedKey})
Create a NetworkAuthenticationServerHandler.
ResponseResult
The processing result of receiving a response.
@ RetryNextMethod
The client failed to authenticate, but there is another method to try.
@ NotAuthenticated
All authentications for this handler have been exhausted.
@ Authenticated
The client was authenticated successfully.
Simple helper to (more easily) manage authorized keys.
bool Add(std::string_view key)
Add the given key to the authorized keys, when it is not already contained.
std::unique_ptr< class NetworkEncryptionHandler > send_encryption_handler
The handler for encrypting sent packets.
std::unique_ptr< class NetworkEncryptionHandler > receive_encryption_handler
The handler for decrypting received packets.
NetworkSocketHandler()=default
Create a new unbound socket.
void SendResponse() override
Callback to trigger sending the response for the password request.
void AskUserForPassword(std::shared_ptr< NetworkAuthenticationPasswordRequest > request) override
Callback to trigger asking the user for the password.
Handler for clients using a X25519 key exchange to perform authentication via a set of authorized (pu...
Handler for servers using a X25519 key exchange to perform authentication via a set of authorized (pu...
Client side handler for using X25519 without actual authentication.
Server side handler for using X25519 without actual authentication.
Client side handler for using X25519 with a password-authenticated key exchange.
Server side handler for using X25519 with a password-authenticated key exchange.
static const uint NETWORK_SECRET_KEY_LENGTH
The maximum length of the hexadecimal encoded secret keys, in bytes including '\0'.
static const size_t COMPAT_MTU
Number of bytes we can pack in a single packet for backward compatibility.
static const uint NETWORK_PUBLIC_KEY_LENGTH
The maximum length of the hexadecimal encoded public keys, in bytes including '\0'.
Internal bits to the crypto of the network handling.
constexpr size_t X25519_KEY_SIZE
The number of bytes the public and secret keys are in X25519.
Basic functions to create, fill and read packets.
uint8_t PacketType
Identifier for the packet.
A number of safeguards to prevent using unsafe methods.
Definition of base types and functions in a cross-platform compatible way.
std::string FormatArrayAsHex(std::span< const uint8_t > data)
Format a byte array into a continuous hex string.
Functions related to low-level strings.
Internal entity of a packet.
size_t Size() const
Get the number of bytes in the packet.
ssize_t TransferOutWithLimit(F transfer_function, size_t limit)
Transfer data from the packet to the given function.
void PrepareToSend()
Writes the packet size from the raw packet from packet->size.
void Send_uint64(uint64_t data)
Package a 64 bits integer in the packet.
Container for a X25519 public key.
Container for a X25519 secret key.
X25519PublicKey CreatePublicKey() const
Create the public key associated with this secret key.
static X25519SecretKey CreateRandom()
Create a new secret key that's filled with random bytes.