From 2e21e805864a515c38e70c19fdf4b278ba63ce72 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Tue, 26 Mar 2024 19:03:28 +0100 Subject: [PATCH] Feature: encrypt admin connection when using secure join --- src/network/core/tcp_admin.cpp | 2 ++ src/network/core/tcp_admin.h | 9 +++++++++ src/network/network_admin.cpp | 15 +++++++++++++++ src/network/network_admin.h | 1 + 4 files changed, 27 insertions(+) diff --git a/src/network/core/tcp_admin.cpp b/src/network/core/tcp_admin.cpp index fedb83ca2c..044950940c 100644 --- a/src/network/core/tcp_admin.cpp +++ b/src/network/core/tcp_admin.cpp @@ -94,6 +94,7 @@ NetworkRecvStatus NetworkAdminSocketHandler::HandlePacket(Packet &p) case ADMIN_PACKET_SERVER_RCON_END: return this->Receive_SERVER_RCON_END(p); case ADMIN_PACKET_SERVER_PONG: return this->Receive_SERVER_PONG(p); case ADMIN_PACKET_SERVER_AUTH_REQUEST: return this->Receive_SERVER_AUTH_REQUEST(p); + case ADMIN_PACKET_SERVER_ENABLE_ENCRYPTION: return this->Receive_SERVER_ENABLE_ENCRYPTION(p); default: Debug(net, 0, "[tcp/admin] Received invalid packet type {} from '{}' ({})", type, this->admin_name, this->admin_version); @@ -171,3 +172,4 @@ NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_CMD_LOGGING(Packet & NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_RCON_END(Packet &) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_RCON_END); } NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_PONG(Packet &) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_PONG); } NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_AUTH_REQUEST(Packet &) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_AUTH_REQUEST); } +NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_ENABLE_ENCRYPTION(Packet &) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_ENABLE_ENCRYPTION); } diff --git a/src/network/core/tcp_admin.h b/src/network/core/tcp_admin.h index 808cbdf583..e3433effbc 100644 --- a/src/network/core/tcp_admin.h +++ b/src/network/core/tcp_admin.h @@ -64,6 +64,7 @@ enum PacketAdminType : uint8_t { ADMIN_PACKET_SERVER_PONG, ///< The server replies to a ping request from the admin. ADMIN_PACKET_SERVER_CMD_LOGGING, ///< The server gives the admin copies of incoming command packets. ADMIN_PACKET_SERVER_AUTH_REQUEST, ///< The server gives the admin the used authentication method and required parameters. + ADMIN_PACKET_SERVER_ENABLE_ENCRYPTION, ///< The server tells that authentication has completed and requests to enable encryption with the keys of the last \c ADMIN_PACKET_ADMIN_AUTH_RESPONSE. INVALID_ADMIN_PACKET = 0xFF, ///< An invalid marker for admin packets. }; @@ -513,6 +514,14 @@ protected: */ virtual NetworkRecvStatus Receive_SERVER_AUTH_REQUEST(Packet &p); + /** + * Indication to the client that authentication is complete and encryption has to be used from here on forward. + * The encryption uses the shared keys generated by the last AUTH_REQUEST key exchange. + * 24 * uint8_t Nonce for encrypted connection. + * @param p The packet that was just received. + */ + virtual NetworkRecvStatus Receive_SERVER_ENABLE_ENCRYPTION(Packet &p); + /** * Send a ping-reply (pong) to the admin that sent us the ping packet. * uint32_t Integer identifier - should be the same as read from the admins ping packet. diff --git a/src/network/network_admin.cpp b/src/network/network_admin.cpp index 7a5a06a6bf..b635bca1a5 100644 --- a/src/network/network_admin.cpp +++ b/src/network/network_admin.cpp @@ -845,6 +845,17 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendAuthRequest() return NETWORK_RECV_STATUS_OKAY; } +NetworkRecvStatus ServerNetworkAdminSocketHandler::SendEnableEncryption() +{ + if (this->status != ADMIN_STATUS_AUTHENTICATE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED); + + auto p = std::make_unique(this, ADMIN_PACKET_SERVER_ENABLE_ENCRYPTION); + this->authentication_handler->SendEnableEncryption(*p); + this->SendPacket(std::move(p)); + + return NETWORK_RECV_STATUS_OKAY; +} + NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_AUTH_RESPONSE(Packet &p) { if (this->status != ADMIN_STATUS_AUTHENTICATE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED); @@ -853,6 +864,10 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_AUTH_RESPONSE(P case NetworkAuthenticationServerHandler::AUTHENTICATED: Debug(net, 3, "[admin] '{}' ({}) authenticated", this->admin_name, this->admin_version); + this->SendEnableEncryption(); + + this->receive_encryption_handler = this->authentication_handler->CreateClientToServerEncryptionHandler(); + this->send_encryption_handler = this->authentication_handler->CreateServerToClientEncryptionHandler(); this->authentication_handler = nullptr; return this->SendProtocol(); diff --git a/src/network/network_admin.h b/src/network/network_admin.h index 91863d05b2..4984ea6847 100644 --- a/src/network/network_admin.h +++ b/src/network/network_admin.h @@ -41,6 +41,7 @@ protected: NetworkRecvStatus SendProtocol(); NetworkRecvStatus SendPong(uint32_t d1); NetworkRecvStatus SendAuthRequest(); + NetworkRecvStatus SendEnableEncryption(); public: AdminUpdateFrequency update_frequency[ADMIN_UPDATE_END]; ///< Admin requested update intervals. std::chrono::steady_clock::time_point connect_time; ///< Time of connection.