12#include "../3rdparty/catch2/catch.hpp"
14#include "../core/format.hpp"
15#include "../network/network_crypto_internal.h"
16#include "../network/core/packet.h"
17#include "../string_func.h"
19#include "../safeguards.h"
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 };
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.
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.
SocketHandler for all network sockets in OpenTTD.
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.
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'.
constexpr size_t X25519_KEY_SIZE
The number of bytes the public and secret keys are in X25519.
uint8_t PacketType
Identifier for the packet.
std::string FormatArrayAsHex(std::span< const uint8_t > data)
Format a byte array into a continuous hex string.
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.