Merge branch 'master' into jgrpp
# Conflicts: # .github/workflows/release-windows.yml # src/autoreplace_gui.cpp # src/cargotype.cpp # src/company_base.h # src/company_cmd.cpp # src/company_gui.cpp # src/currency.h # src/date_gui.cpp # src/dropdown.cpp # src/dropdown_func.h # src/dropdown_type.h # src/game/game_gui.cpp # src/genworld.cpp # src/genworld_gui.cpp # src/ground_vehicle.hpp # src/group_gui.cpp # src/house.h # src/industry_gui.cpp # src/network/network_client.cpp # src/network/network_server.cpp # src/network/network_type.h # src/newgrf_class_func.h # src/newgrf_house.cpp # src/newgrf_roadstop.h # src/openttd.cpp # src/order_gui.cpp # src/saveload/saveload.cpp # src/saveload/saveload.h # src/screenshot_gui.cpp # src/settings_gui.cpp # src/settings_type.h # src/slider.cpp # src/smallmap_gui.cpp # src/station_cmd.cpp # src/stdafx.h # src/survey.cpp # src/tile_map.h # src/town_cmd.cpp # src/town_gui.cpp # src/vehicle.cpp # src/vehicle_gui.cpp # src/vehicle_gui_base.h
This commit is contained in:
		@@ -26,10 +26,9 @@
 | 
			
		||||
 */
 | 
			
		||||
enum PacketGameType : uint8_t {
 | 
			
		||||
	/*
 | 
			
		||||
	 * These first four pair of packets (thus eight in
 | 
			
		||||
	 * total) must remain in this order for backward
 | 
			
		||||
	 * and forward compatibility between clients that
 | 
			
		||||
	 * are trying to join directly.
 | 
			
		||||
	 * These first ten packets must remain in this order for backward and forward compatibility
 | 
			
		||||
	 * between clients that are trying to join directly. These packets can be received and/or sent
 | 
			
		||||
	 * by the server before the server has processed the 'join' packet from the client.
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	/* Packets sent by socket accepting code without ever constructing a client socket instance. */
 | 
			
		||||
@@ -48,6 +47,10 @@ enum PacketGameType : uint8_t {
 | 
			
		||||
	PACKET_SERVER_GAME_INFO,             ///< Information about the server.
 | 
			
		||||
	PACKET_CLIENT_GAME_INFO,             ///< Request information about the server.
 | 
			
		||||
 | 
			
		||||
	/* A server quitting this game. */
 | 
			
		||||
	PACKET_SERVER_NEWGAME,               ///< The server is preparing to start a new game.
 | 
			
		||||
	PACKET_SERVER_SHUTDOWN,              ///< The server is shutting down.
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Packets after here assume that the client
 | 
			
		||||
	 * and server are running the same version. As
 | 
			
		||||
@@ -127,10 +130,6 @@ enum PacketGameType : uint8_t {
 | 
			
		||||
	PACKET_SERVER_COMPANY_UPDATE,        ///< Information (password) of a company changed.
 | 
			
		||||
	PACKET_SERVER_CONFIG_UPDATE,         ///< Some network configuration important to the client changed.
 | 
			
		||||
 | 
			
		||||
	/* A server quitting this game. */
 | 
			
		||||
	PACKET_SERVER_NEWGAME,               ///< The server is preparing to start a new game.
 | 
			
		||||
	PACKET_SERVER_SHUTDOWN,              ///< The server is shutting down.
 | 
			
		||||
 | 
			
		||||
	/* A client quitting. */
 | 
			
		||||
	PACKET_CLIENT_QUIT,                  ///< A client tells the server it is going to quit.
 | 
			
		||||
	PACKET_SERVER_QUIT,                  ///< A server tells that a client has quit.
 | 
			
		||||
@@ -228,14 +227,14 @@ protected:
 | 
			
		||||
	/**
 | 
			
		||||
	 * The client tells the server about the identity of the client:
 | 
			
		||||
	 * string  Name of the client (max NETWORK_NAME_LENGTH).
 | 
			
		||||
	 * uint8_t ID of the company to play as (1..MAX_COMPANIES).
 | 
			
		||||
	 * uint8_t ID of the company to play as (1..MAX_COMPANIES, or COMPANY_SPECTATOR).
 | 
			
		||||
	 * @param p The packet that was just received.
 | 
			
		||||
	 */
 | 
			
		||||
	virtual NetworkRecvStatus Receive_CLIENT_IDENTIFY(Packet &p);
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Indication to the client that it needs to authenticate:
 | 
			
		||||
	 * bool Whether to use the password in the key exchange.
 | 
			
		||||
	 * uint8_t The \c NetworkAuthenticationMethod to use.
 | 
			
		||||
	 * 32 * uint8_t Public key of the server.
 | 
			
		||||
	 * 24 * uint8_t Nonce for the key exchange.
 | 
			
		||||
	 * @param p The packet that was just received.
 | 
			
		||||
@@ -253,14 +252,16 @@ protected:
 | 
			
		||||
	/**
 | 
			
		||||
	 * Send the response to the authentication request:
 | 
			
		||||
	 * 32 * uint8_t Public key of the client.
 | 
			
		||||
	 *  8 * uint8_t Random message that got encoded and signed.
 | 
			
		||||
	 * 16 * uint8_t Message authentication code.
 | 
			
		||||
	 *  8 * uint8_t Random message that got encoded and signed.
 | 
			
		||||
	 * @param p The packet that was just received.
 | 
			
		||||
	 */
 | 
			
		||||
	virtual NetworkRecvStatus Receive_CLIENT_AUTH_RESPONSE(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);
 | 
			
		||||
@@ -299,7 +300,6 @@ protected:
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Request the map from the server.
 | 
			
		||||
	 * uint32_t  NewGRF version (release versions of OpenTTD only).
 | 
			
		||||
	 * @param p The packet that was just received.
 | 
			
		||||
	 */
 | 
			
		||||
	virtual NetworkRecvStatus Receive_CLIENT_GETMAP(Packet &p);
 | 
			
		||||
 
 | 
			
		||||
@@ -151,6 +151,57 @@ NetworkClientInfo::~NetworkClientInfo()
 | 
			
		||||
	return nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Simple helper to find the location of the given authorized key in the authorized keys.
 | 
			
		||||
 * @param authorized_keys The keys to look through.
 | 
			
		||||
 * @param authorized_key The key to look for.
 | 
			
		||||
 * @return The iterator to the location of the authorized key, or \c authorized_keys.end().
 | 
			
		||||
 */
 | 
			
		||||
static auto FindKey(auto *authorized_keys, std::string_view authorized_key)
 | 
			
		||||
{
 | 
			
		||||
	return std::find_if(authorized_keys->begin(), authorized_keys->end(), [authorized_key](auto &value) { return StrEqualsIgnoreCase(value, authorized_key); });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Check whether the given key is contains in these authorized keys.
 | 
			
		||||
 * @param key The key to look for.
 | 
			
		||||
 * @return \c true when the key has been found, otherwise \c false.
 | 
			
		||||
 */
 | 
			
		||||
bool NetworkAuthorizedKeys::Contains(std::string_view key) const
 | 
			
		||||
{
 | 
			
		||||
	return FindKey(this, key) != this->end();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Add the given key to the authorized keys, when it is not already contained.
 | 
			
		||||
 * @param key The key to add.
 | 
			
		||||
 * @return \c true when the key was added, \c false when the key already existed.
 | 
			
		||||
 */
 | 
			
		||||
bool NetworkAuthorizedKeys::Add(std::string_view key)
 | 
			
		||||
{
 | 
			
		||||
	auto iter = FindKey(this, key);
 | 
			
		||||
	if (iter != this->end()) return false;
 | 
			
		||||
 | 
			
		||||
	this->emplace_back(key);
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Remove the given key from the authorized keys, when it is exists.
 | 
			
		||||
 * @param key The key to remove.
 | 
			
		||||
 * @return \c true when the key was removed, \c false when the key did not exist.
 | 
			
		||||
 */
 | 
			
		||||
bool NetworkAuthorizedKeys::Remove(std::string_view key)
 | 
			
		||||
{
 | 
			
		||||
	auto iter = FindKey(this, key);
 | 
			
		||||
	if (iter == this->end()) return false;
 | 
			
		||||
 | 
			
		||||
	this->erase(iter);
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
uint8_t NetworkSpectatorCount()
 | 
			
		||||
{
 | 
			
		||||
	uint8_t count = 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -953,10 +953,12 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_AUTH_REQUEST(Pa
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_ENABLE_ENCRYPTION(Packet &)
 | 
			
		||||
NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_ENABLE_ENCRYPTION(Packet &p)
 | 
			
		||||
{
 | 
			
		||||
	if (this->status != STATUS_AUTH_GAME || this->authentication_handler == nullptr) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
 | 
			
		||||
 | 
			
		||||
	if (!this->authentication_handler->ReceiveEnableEncryption(p)) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
 | 
			
		||||
 | 
			
		||||
	this->receive_encryption_handler = this->authentication_handler->CreateServerToClientEncryptionHandler();
 | 
			
		||||
	this->send_encryption_handler = this->authentication_handler->CreateClientToServerEncryptionHandler();
 | 
			
		||||
	this->authentication_handler = nullptr;
 | 
			
		||||
 
 | 
			
		||||
@@ -183,14 +183,15 @@ X25519Nonce::~X25519Nonce()
 | 
			
		||||
 * @param secret_key The secret key to use for this handler. Defaults to secure random data.
 | 
			
		||||
 */
 | 
			
		||||
X25519AuthenticationHandler::X25519AuthenticationHandler(const X25519SecretKey &secret_key) :
 | 
			
		||||
	our_secret_key(secret_key), our_public_key(secret_key.CreatePublicKey()), nonce(X25519Nonce::CreateRandom())
 | 
			
		||||
	our_secret_key(secret_key), our_public_key(secret_key.CreatePublicKey()),
 | 
			
		||||
	key_exchange_nonce(X25519Nonce::CreateRandom()), encryption_nonce(X25519Nonce::CreateRandom())
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* virtual */ void X25519AuthenticationHandler::SendRequest(Packet &p)
 | 
			
		||||
{
 | 
			
		||||
	p.Send_bytes(this->our_public_key);
 | 
			
		||||
	p.Send_bytes(this->nonce);
 | 
			
		||||
	p.Send_bytes(this->key_exchange_nonce);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -206,7 +207,7 @@ bool X25519AuthenticationHandler::ReceiveRequest(Packet &p)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	p.Recv_bytes(this->peer_public_key);
 | 
			
		||||
	p.Recv_bytes(this->nonce);
 | 
			
		||||
	p.Recv_bytes(this->key_exchange_nonce);
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -228,7 +229,7 @@ bool X25519AuthenticationHandler::SendResponse(Packet &p, std::string_view deriv
 | 
			
		||||
	RandomBytesWithFallback(message);
 | 
			
		||||
	X25519Mac mac;
 | 
			
		||||
 | 
			
		||||
	crypto_aead_lock(message.data(), mac.data(), this->derived_keys.ClientToServer().data(), nonce.data(),
 | 
			
		||||
	crypto_aead_lock(message.data(), mac.data(), this->derived_keys.ClientToServer().data(), this->key_exchange_nonce.data(),
 | 
			
		||||
			this->our_public_key.data(), this->our_public_key.size(), message.data(), message.size());
 | 
			
		||||
 | 
			
		||||
	p.Send_bytes(this->our_public_key);
 | 
			
		||||
@@ -246,14 +247,33 @@ std::string X25519AuthenticationHandler::GetPeerPublicKey() const
 | 
			
		||||
	return FormatArrayAsHex(this->peer_public_key);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Send the initial nonce for the encrypted connection.
 | 
			
		||||
 * @param p The packet to send the data in.
 | 
			
		||||
 */
 | 
			
		||||
void X25519AuthenticationHandler::SendEnableEncryption(struct Packet &p) const
 | 
			
		||||
{
 | 
			
		||||
	p.Send_bytes(this->encryption_nonce);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Receive the initial nonce for the encrypted connection.
 | 
			
		||||
 * @param p The packet to read the data from.
 | 
			
		||||
 * @return \c true when enough bytes could be read for the nonce, otherwise \c false.
 | 
			
		||||
 */
 | 
			
		||||
bool X25519AuthenticationHandler::ReceiveEnableEncryption(struct Packet &p)
 | 
			
		||||
{
 | 
			
		||||
	return p.Recv_bytes(this->encryption_nonce) == this->encryption_nonce.size();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<NetworkEncryptionHandler> X25519AuthenticationHandler::CreateClientToServerEncryptionHandler() const
 | 
			
		||||
{
 | 
			
		||||
	return std::make_unique<X25519EncryptionHandler>(this->derived_keys.ClientToServer(), this->nonce);
 | 
			
		||||
	return std::make_unique<X25519EncryptionHandler>(this->derived_keys.ClientToServer(), this->encryption_nonce);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<NetworkEncryptionHandler> X25519AuthenticationHandler::CreateServerToClientEncryptionHandler() const
 | 
			
		||||
{
 | 
			
		||||
	return std::make_unique<X25519EncryptionHandler>(this->derived_keys.ServerToClient(), this->nonce);
 | 
			
		||||
	return std::make_unique<X25519EncryptionHandler>(this->derived_keys.ServerToClient(), this->encryption_nonce);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -283,7 +303,7 @@ NetworkAuthenticationServerHandler::ResponseResult X25519AuthenticationHandler::
 | 
			
		||||
		return NetworkAuthenticationServerHandler::NOT_AUTHENTICATED;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (crypto_aead_unlock(message.data(), mac.data(), this->derived_keys.ClientToServer().data(), nonce.data(),
 | 
			
		||||
	if (crypto_aead_unlock(message.data(), mac.data(), this->derived_keys.ClientToServer().data(), this->key_exchange_nonce.data(),
 | 
			
		||||
			this->peer_public_key.data(), this->peer_public_key.size(), message.data(), message.size()) != 0) {
 | 
			
		||||
		/*
 | 
			
		||||
		 * The ciphertext and the message authentication code do not match with the encryption key.
 | 
			
		||||
@@ -424,14 +444,6 @@ void CombinedAuthenticationServerHandler::Add(CombinedAuthenticationServerHandle
 | 
			
		||||
	this->SendResponse();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* virtual */ bool NetworkAuthenticationDefaultAuthorizedKeyHandler::IsAllowed(std::string_view peer_public_key) const
 | 
			
		||||
{
 | 
			
		||||
	for (const auto &allowed : *this->authorized_keys) {
 | 
			
		||||
		if (StrEqualsIgnoreCase(allowed, peer_public_key)) return true;
 | 
			
		||||
	}
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Create a NetworkAuthenticationClientHandler.
 | 
			
		||||
 
 | 
			
		||||
@@ -33,6 +33,8 @@
 | 
			
		||||
#ifndef NETWORK_CRYPTO_H
 | 
			
		||||
#define NETWORK_CRYPTO_H
 | 
			
		||||
 | 
			
		||||
#include "network_type.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Base class for handling the encryption (or decryption) of a network connection.
 | 
			
		||||
 */
 | 
			
		||||
@@ -158,16 +160,16 @@ public:
 | 
			
		||||
 */
 | 
			
		||||
class NetworkAuthenticationDefaultAuthorizedKeyHandler : public NetworkAuthenticationAuthorizedKeyHandler {
 | 
			
		||||
private:
 | 
			
		||||
	const std::vector<std::string> *authorized_keys; ///< The authorized keys to check against.
 | 
			
		||||
	const NetworkAuthorizedKeys *authorized_keys; ///< The authorized keys to check against.
 | 
			
		||||
public:
 | 
			
		||||
	/**
 | 
			
		||||
	 * Create the handler that uses the given authorized keys to check against.
 | 
			
		||||
	 * @param authorized_keys The reference to the authorized keys to check against.
 | 
			
		||||
	 */
 | 
			
		||||
	NetworkAuthenticationDefaultAuthorizedKeyHandler(const std::vector<std::string> &authorized_keys) : authorized_keys(&authorized_keys) {}
 | 
			
		||||
	NetworkAuthenticationDefaultAuthorizedKeyHandler(const NetworkAuthorizedKeys &authorized_keys) : authorized_keys(&authorized_keys) {}
 | 
			
		||||
 | 
			
		||||
	bool CanBeUsed() const override { return !this->authorized_keys->empty(); }
 | 
			
		||||
	bool IsAllowed(std::string_view peer_public_key) const override;
 | 
			
		||||
	bool IsAllowed(std::string_view peer_public_key) const override { return authorized_keys->Contains(peer_public_key); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -240,6 +242,12 @@ public:
 | 
			
		||||
	 */
 | 
			
		||||
	virtual bool SendResponse(struct Packet &p) = 0;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Read the request to enable encryption from the server.
 | 
			
		||||
	 * @param p The request from the server.
 | 
			
		||||
	 */
 | 
			
		||||
	virtual bool ReceiveEnableEncryption(struct Packet &p) = 0;
 | 
			
		||||
 | 
			
		||||
	static std::unique_ptr<NetworkAuthenticationClientHandler> Create(std::shared_ptr<NetworkAuthenticationPasswordRequestHandler> password_handler, std::string &secret_key, std::string &public_key);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -268,6 +276,12 @@ public:
 | 
			
		||||
	 */
 | 
			
		||||
	virtual ResponseResult ReceiveResponse(struct Packet &p) = 0;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Create the request to enable encryption to the client.
 | 
			
		||||
	 * @param p The packet to write the enable encryption request to.
 | 
			
		||||
	 */
 | 
			
		||||
	virtual void SendEnableEncryption(struct Packet &p) = 0;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Checks whether this handler can be used with the current configuration.
 | 
			
		||||
	 * For example when there is no password, the handler cannot be used.
 | 
			
		||||
 
 | 
			
		||||
@@ -105,10 +105,12 @@ class X25519AuthenticationHandler {
 | 
			
		||||
private:
 | 
			
		||||
	X25519SecretKey our_secret_key; ///< The secret key used by us.
 | 
			
		||||
	X25519PublicKey our_public_key; ///< The public key used by us.
 | 
			
		||||
	X25519Nonce nonce; ///< The nonce to prevent replay attacks.
 | 
			
		||||
	X25519Nonce key_exchange_nonce; ///< The nonce to prevent replay attacks of the key exchange.
 | 
			
		||||
	X25519DerivedKeys derived_keys; ///< Keys derived from the authentication process.
 | 
			
		||||
	X25519PublicKey peer_public_key; ///< The public key used by our peer.
 | 
			
		||||
 | 
			
		||||
	X25519Nonce encryption_nonce; ///< The nonce to prevent replay attacks the encrypted connection.
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
	X25519AuthenticationHandler(const X25519SecretKey &secret_key);
 | 
			
		||||
 | 
			
		||||
@@ -119,6 +121,8 @@ protected:
 | 
			
		||||
 | 
			
		||||
	std::string GetPeerPublicKey() const;
 | 
			
		||||
 | 
			
		||||
	void SendEnableEncryption(struct Packet &p) const;
 | 
			
		||||
	bool ReceiveEnableEncryption(struct Packet &p);
 | 
			
		||||
	std::unique_ptr<NetworkEncryptionHandler> CreateClientToServerEncryptionHandler() const;
 | 
			
		||||
	std::unique_ptr<NetworkEncryptionHandler> CreateServerToClientEncryptionHandler() const;
 | 
			
		||||
};
 | 
			
		||||
@@ -142,6 +146,7 @@ public:
 | 
			
		||||
	virtual std::string_view GetName() const override { return "X25519-KeyExchangeOnly-client"; }
 | 
			
		||||
	virtual NetworkAuthenticationMethod GetAuthenticationMethod() const override { return NETWORK_AUTH_METHOD_X25519_KEY_EXCHANGE_ONLY; }
 | 
			
		||||
 | 
			
		||||
	virtual bool ReceiveEnableEncryption(struct Packet &p) override { return this->X25519AuthenticationHandler::ReceiveEnableEncryption(p); }
 | 
			
		||||
	virtual std::unique_ptr<NetworkEncryptionHandler> CreateClientToServerEncryptionHandler() const override { return this->X25519AuthenticationHandler::CreateClientToServerEncryptionHandler(); }
 | 
			
		||||
	virtual std::unique_ptr<NetworkEncryptionHandler> CreateServerToClientEncryptionHandler() const override { return this->X25519AuthenticationHandler::CreateServerToClientEncryptionHandler(); }
 | 
			
		||||
};
 | 
			
		||||
@@ -167,6 +172,7 @@ public:
 | 
			
		||||
	virtual bool CanBeUsed() const override { return true; }
 | 
			
		||||
 | 
			
		||||
	virtual std::string GetPeerPublicKey() const override { return this->X25519AuthenticationHandler::GetPeerPublicKey(); }
 | 
			
		||||
	virtual void SendEnableEncryption(struct Packet &p) override { this->X25519AuthenticationHandler::SendEnableEncryption(p); }
 | 
			
		||||
	virtual std::unique_ptr<NetworkEncryptionHandler> CreateClientToServerEncryptionHandler() const override { return this->X25519AuthenticationHandler::CreateClientToServerEncryptionHandler(); }
 | 
			
		||||
	virtual std::unique_ptr<NetworkEncryptionHandler> CreateServerToClientEncryptionHandler() const override { return this->X25519AuthenticationHandler::CreateServerToClientEncryptionHandler(); }
 | 
			
		||||
};
 | 
			
		||||
@@ -194,6 +200,7 @@ public:
 | 
			
		||||
	virtual std::string_view GetName() const override { return "X25519-PAKE-client"; }
 | 
			
		||||
	virtual NetworkAuthenticationMethod GetAuthenticationMethod() const override { return NETWORK_AUTH_METHOD_X25519_PAKE; }
 | 
			
		||||
 | 
			
		||||
	virtual bool ReceiveEnableEncryption(struct Packet &p) override { return this->X25519AuthenticationHandler::ReceiveEnableEncryption(p); }
 | 
			
		||||
	virtual std::unique_ptr<NetworkEncryptionHandler> CreateClientToServerEncryptionHandler() const override { return this->X25519AuthenticationHandler::CreateClientToServerEncryptionHandler(); }
 | 
			
		||||
	virtual std::unique_ptr<NetworkEncryptionHandler> CreateServerToClientEncryptionHandler() const override { return this->X25519AuthenticationHandler::CreateServerToClientEncryptionHandler(); }
 | 
			
		||||
};
 | 
			
		||||
@@ -222,6 +229,7 @@ public:
 | 
			
		||||
	virtual bool CanBeUsed() const override { return !this->password_provider->GetPassword().empty(); }
 | 
			
		||||
 | 
			
		||||
	virtual std::string GetPeerPublicKey() const override { return this->X25519AuthenticationHandler::GetPeerPublicKey(); }
 | 
			
		||||
	virtual void SendEnableEncryption(struct Packet &p) override { this->X25519AuthenticationHandler::SendEnableEncryption(p); }
 | 
			
		||||
	virtual std::unique_ptr<NetworkEncryptionHandler> CreateClientToServerEncryptionHandler() const override { return this->X25519AuthenticationHandler::CreateClientToServerEncryptionHandler(); }
 | 
			
		||||
	virtual std::unique_ptr<NetworkEncryptionHandler> CreateServerToClientEncryptionHandler() const override { return this->X25519AuthenticationHandler::CreateServerToClientEncryptionHandler(); }
 | 
			
		||||
};
 | 
			
		||||
@@ -247,6 +255,7 @@ public:
 | 
			
		||||
	virtual std::string_view GetName() const override { return "X25519-AuthorizedKey-client"; }
 | 
			
		||||
	virtual NetworkAuthenticationMethod GetAuthenticationMethod() const override { return NETWORK_AUTH_METHOD_X25519_AUTHORIZED_KEY; }
 | 
			
		||||
 | 
			
		||||
	virtual bool ReceiveEnableEncryption(struct Packet &p) override { return this->X25519AuthenticationHandler::ReceiveEnableEncryption(p); }
 | 
			
		||||
	virtual std::unique_ptr<NetworkEncryptionHandler> CreateClientToServerEncryptionHandler() const override { return this->X25519AuthenticationHandler::CreateClientToServerEncryptionHandler(); }
 | 
			
		||||
	virtual std::unique_ptr<NetworkEncryptionHandler> CreateServerToClientEncryptionHandler() const override { return this->X25519AuthenticationHandler::CreateServerToClientEncryptionHandler(); }
 | 
			
		||||
 | 
			
		||||
@@ -278,6 +287,7 @@ public:
 | 
			
		||||
	virtual bool CanBeUsed() const override { return this->authorized_key_handler->CanBeUsed(); }
 | 
			
		||||
 | 
			
		||||
	virtual std::string GetPeerPublicKey() const override { return this->X25519AuthenticationHandler::GetPeerPublicKey(); }
 | 
			
		||||
	virtual void SendEnableEncryption(struct Packet &p) override { this->X25519AuthenticationHandler::SendEnableEncryption(p); }
 | 
			
		||||
	virtual std::unique_ptr<NetworkEncryptionHandler> CreateClientToServerEncryptionHandler() const override { return this->X25519AuthenticationHandler::CreateClientToServerEncryptionHandler(); }
 | 
			
		||||
	virtual std::unique_ptr<NetworkEncryptionHandler> CreateServerToClientEncryptionHandler() const override { return this->X25519AuthenticationHandler::CreateServerToClientEncryptionHandler(); }
 | 
			
		||||
};
 | 
			
		||||
@@ -308,6 +318,7 @@ public:
 | 
			
		||||
	virtual std::string_view GetName() const override;
 | 
			
		||||
	virtual NetworkAuthenticationMethod GetAuthenticationMethod() const override;
 | 
			
		||||
 | 
			
		||||
	virtual bool ReceiveEnableEncryption(struct Packet &p) override { return this->current_handler->ReceiveEnableEncryption(p); }
 | 
			
		||||
	virtual std::unique_ptr<NetworkEncryptionHandler> CreateClientToServerEncryptionHandler() const override { return this->current_handler->CreateClientToServerEncryptionHandler(); }
 | 
			
		||||
	virtual std::unique_ptr<NetworkEncryptionHandler> CreateServerToClientEncryptionHandler() const override { return this->current_handler->CreateServerToClientEncryptionHandler(); }
 | 
			
		||||
};
 | 
			
		||||
@@ -334,6 +345,7 @@ public:
 | 
			
		||||
	virtual bool CanBeUsed() const override;
 | 
			
		||||
 | 
			
		||||
	virtual std::string GetPeerPublicKey() const override { return this->handlers.back()->GetPeerPublicKey(); }
 | 
			
		||||
	virtual void SendEnableEncryption(struct Packet &p) override { this->handlers.back()->SendEnableEncryption(p); }
 | 
			
		||||
	virtual std::unique_ptr<NetworkEncryptionHandler> CreateClientToServerEncryptionHandler() const override { return this->handlers.back()->CreateClientToServerEncryptionHandler(); }
 | 
			
		||||
	virtual std::unique_ptr<NetworkEncryptionHandler> CreateServerToClientEncryptionHandler() const override { return this->handlers.back()->CreateServerToClientEncryptionHandler(); }
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -24,8 +24,8 @@
 | 
			
		||||
#include "network_udp.h"
 | 
			
		||||
#include "../window_func.h"
 | 
			
		||||
#include "../gfx_func.h"
 | 
			
		||||
#include "../widgets/dropdown_type.h"
 | 
			
		||||
#include "../widgets/dropdown_func.h"
 | 
			
		||||
#include "../dropdown_type.h"
 | 
			
		||||
#include "../dropdown_func.h"
 | 
			
		||||
#include "../querystring_gui.h"
 | 
			
		||||
#include "../sortlist_type.h"
 | 
			
		||||
#include "../company_func.h"
 | 
			
		||||
 
 | 
			
		||||
@@ -316,7 +316,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::CloseConnection(NetworkRecvSta
 | 
			
		||||
 | 
			
		||||
		/* Inform other clients of this... strange leaving ;) */
 | 
			
		||||
		for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
 | 
			
		||||
			if (new_cs->status > STATUS_AUTHORIZED && this != new_cs) {
 | 
			
		||||
			if (new_cs->status >= STATUS_AUTHORIZED && this != new_cs) {
 | 
			
		||||
				new_cs->SendErrorQuit(this->client_id, NETWORK_ERROR_CONNECTION_LOST);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
@@ -443,7 +443,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendError(NetworkErrorCode err
 | 
			
		||||
	StringID strid = GetNetworkErrorMsg(error);
 | 
			
		||||
 | 
			
		||||
	/* Only send when the current client was in game */
 | 
			
		||||
	if (this->status > STATUS_AUTHORIZED) {
 | 
			
		||||
	if (this->status >= STATUS_AUTHORIZED) {
 | 
			
		||||
		char client_name[NETWORK_CLIENT_NAME_LENGTH];
 | 
			
		||||
 | 
			
		||||
		this->GetClientName(client_name, lastof(client_name));
 | 
			
		||||
@@ -542,6 +542,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendEnableEncryption()
 | 
			
		||||
	if (this->status != STATUS_AUTH_GAME) return this->CloseConnection(NETWORK_RECV_STATUS_MALFORMED_PACKET);
 | 
			
		||||
 | 
			
		||||
	auto p = std::make_unique<Packet>(this, PACKET_SERVER_ENABLE_ENCRYPTION, TCP_MTU);
 | 
			
		||||
	this->authentication_handler->SendEnableEncryption(*p);
 | 
			
		||||
	this->SendPacket(std::move(p));
 | 
			
		||||
	return NETWORK_RECV_STATUS_OKAY;
 | 
			
		||||
}
 | 
			
		||||
@@ -1038,7 +1039,8 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_IDENTIFY(Packet
 | 
			
		||||
	DEBUG(desync, 1, "client: %s; client: %02x; company: %02x", debug_date_dumper().HexDate(), (int)ci->index, (int)ci->client_playas);
 | 
			
		||||
 | 
			
		||||
	/* Make sure companies to which people try to join are not autocleaned */
 | 
			
		||||
	if (Company::IsValidID(playas)) _network_company_states[playas].months_empty = 0;
 | 
			
		||||
	Company *c = Company::GetIfValid(playas);
 | 
			
		||||
	if (c != nullptr) c->months_empty = 0;
 | 
			
		||||
 | 
			
		||||
	return this->SendNewGRFCheck();
 | 
			
		||||
}
 | 
			
		||||
@@ -1528,7 +1530,7 @@ void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, co
 | 
			
		||||
			} else {
 | 
			
		||||
				/* Else find the client to send the message to */
 | 
			
		||||
				for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
 | 
			
		||||
					if (cs->client_id == (ClientID)dest) {
 | 
			
		||||
					if (cs->client_id == (ClientID)dest && cs->status >= ServerNetworkGameSocketHandler::STATUS_AUTHORIZED) {
 | 
			
		||||
						cs->SendChat(action, from_id, false, msg, data);
 | 
			
		||||
						break;
 | 
			
		||||
					}
 | 
			
		||||
@@ -1545,7 +1547,7 @@ void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, co
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
 | 
			
		||||
						if (cs->client_id == from_id) {
 | 
			
		||||
						if (cs->client_id == from_id && cs->status >= ServerNetworkGameSocketHandler::STATUS_AUTHORIZED) {
 | 
			
		||||
							cs->SendChat(action, (ClientID)dest, true, msg, data);
 | 
			
		||||
							break;
 | 
			
		||||
						}
 | 
			
		||||
@@ -1560,7 +1562,7 @@ void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, co
 | 
			
		||||
			ci_to = nullptr;
 | 
			
		||||
			for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
 | 
			
		||||
				ci = cs->GetInfo();
 | 
			
		||||
				if (ci != nullptr && ci->client_playas == (CompanyID)dest) {
 | 
			
		||||
				if (ci != nullptr && ci->client_playas == (CompanyID)dest && cs->status >= ServerNetworkGameSocketHandler::STATUS_AUTHORIZED) {
 | 
			
		||||
					cs->SendChat(action, from_id, false, msg, data);
 | 
			
		||||
					if (cs->client_id == from_id) show_local = false;
 | 
			
		||||
					ci_to = ci; // Remember a client that is in the company for company-name
 | 
			
		||||
@@ -1592,7 +1594,7 @@ void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, co
 | 
			
		||||
					NetworkTextMessage(action, GetDrawStringCompanyColour(ci_own->client_playas), true, name, msg, data);
 | 
			
		||||
				} else {
 | 
			
		||||
					for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
 | 
			
		||||
						if (cs->client_id == from_id) {
 | 
			
		||||
						if (cs->client_id == from_id && cs->status >= ServerNetworkGameSocketHandler::STATUS_AUTHORIZED) {
 | 
			
		||||
							cs->SendChat(action, ci_to->client_id, true, msg, data);
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
@@ -1607,7 +1609,7 @@ void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, co
 | 
			
		||||
		case DESTTYPE_BROADCAST:
 | 
			
		||||
		case DESTTYPE_BROADCAST_SS:
 | 
			
		||||
			for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
 | 
			
		||||
				cs->SendChat(action, from_id, (desttype == DESTTYPE_BROADCAST_SS && from_id == cs->client_id), msg, data);
 | 
			
		||||
				if (cs->status >= ServerNetworkGameSocketHandler::STATUS_AUTHORIZED) cs->SendChat(action, from_id, (desttype == DESTTYPE_BROADCAST_SS && from_id == cs->client_id), msg, data);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
 | 
			
		||||
@@ -1631,7 +1633,7 @@ void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, co
 | 
			
		||||
void NetworkServerSendExternalChat(const std::string &source, TextColour colour, const std::string &user, const std::string &msg)
 | 
			
		||||
{
 | 
			
		||||
	for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
 | 
			
		||||
		cs->SendExternalChat(source, colour, user, msg);
 | 
			
		||||
		if (cs->status >= ServerNetworkGameSocketHandler::STATUS_AUTHORIZED) cs->SendExternalChat(source, colour, user, msg);
 | 
			
		||||
	}
 | 
			
		||||
	NetworkTextMessage(NETWORK_ACTION_EXTERNAL_CHAT, colour, false, user, msg, {}, source.c_str());
 | 
			
		||||
}
 | 
			
		||||
@@ -1903,37 +1905,37 @@ static void NetworkAutoCleanCompanies()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Go through all the companies */
 | 
			
		||||
	for (const Company *c : Company::Iterate()) {
 | 
			
		||||
	for (Company *c : Company::Iterate()) {
 | 
			
		||||
		/* Skip the non-active once */
 | 
			
		||||
		if (c->is_ai) continue;
 | 
			
		||||
 | 
			
		||||
		if (!HasBit(has_clients, c->index)) {
 | 
			
		||||
			/* The company is empty for one month more */
 | 
			
		||||
			_network_company_states[c->index].months_empty++;
 | 
			
		||||
			if (c->months_empty != std::numeric_limits<decltype(c->months_empty)>::max()) c->months_empty++;
 | 
			
		||||
 | 
			
		||||
			/* Is the company empty for autoclean_unprotected-months, and is there no protection? */
 | 
			
		||||
			if (_settings_client.network.autoclean_unprotected != 0 && _network_company_states[c->index].months_empty > _settings_client.network.autoclean_unprotected && _network_company_states[c->index].password.empty()) {
 | 
			
		||||
			if (_settings_client.network.autoclean_unprotected != 0 && c->months_empty > _settings_client.network.autoclean_unprotected && _network_company_states[c->index].password.empty()) {
 | 
			
		||||
				/* Shut the company down */
 | 
			
		||||
				DoCommandP(0, CCA_DELETE | c->index << 16 | CRR_AUTOCLEAN << 24, 0, CMD_COMPANY_CTRL);
 | 
			
		||||
				IConsolePrintF(CC_DEFAULT, "Auto-cleaned company #%d with no password", c->index + 1);
 | 
			
		||||
			}
 | 
			
		||||
			/* Is the company empty for autoclean_protected-months, and there is a protection? */
 | 
			
		||||
			if (_settings_client.network.autoclean_protected != 0 && _network_company_states[c->index].months_empty > _settings_client.network.autoclean_protected && !_network_company_states[c->index].password.empty()) {
 | 
			
		||||
			if (_settings_client.network.autoclean_protected != 0 && c->months_empty > _settings_client.network.autoclean_protected && !_network_company_states[c->index].password.empty()) {
 | 
			
		||||
				/* Unprotect the company */
 | 
			
		||||
				_network_company_states[c->index].password.clear();
 | 
			
		||||
				IConsolePrintF(CC_DEFAULT, "Auto-removed protection from company #%d", c->index + 1);
 | 
			
		||||
				_network_company_states[c->index].months_empty = 0;
 | 
			
		||||
				c->months_empty = 0;
 | 
			
		||||
				NetworkServerUpdateCompanyPassworded(c->index, false);
 | 
			
		||||
			}
 | 
			
		||||
			/* Is the company empty for autoclean_novehicles-months, and has no vehicles? */
 | 
			
		||||
			if (_settings_client.network.autoclean_novehicles != 0 && _network_company_states[c->index].months_empty > _settings_client.network.autoclean_novehicles && !HasBit(has_vehicles, c->index)) {
 | 
			
		||||
			if (_settings_client.network.autoclean_novehicles != 0 && c->months_empty > _settings_client.network.autoclean_novehicles && !HasBit(has_vehicles, c->index)) {
 | 
			
		||||
				/* Shut the company down */
 | 
			
		||||
				DoCommandP(0, CCA_DELETE | c->index << 16 | CRR_AUTOCLEAN << 24, 0, CMD_COMPANY_CTRL);
 | 
			
		||||
				IConsolePrintF(CC_DEFAULT, "Auto-cleaned company #%d with no vehicles", c->index + 1);
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			/* It is not empty, reset the date */
 | 
			
		||||
			_network_company_states[c->index].months_empty = 0;
 | 
			
		||||
			c->months_empty = 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -2522,7 +2524,6 @@ void NetworkServerNewCompany(const Company *c, NetworkClientInfo *ci)
 | 
			
		||||
 | 
			
		||||
	if (!_network_server) return;
 | 
			
		||||
 | 
			
		||||
	_network_company_states[c->index].months_empty = 0;
 | 
			
		||||
	_network_company_states[c->index].password.clear();
 | 
			
		||||
	NetworkServerUpdateCompanyPassworded(c->index, false);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -73,7 +73,6 @@ struct NetworkCompanyStats {
 | 
			
		||||
/** Some state information of a company, especially for servers */
 | 
			
		||||
struct NetworkCompanyState {
 | 
			
		||||
	std::string password; ///< The password for the company
 | 
			
		||||
	uint16_t months_empty;  ///< How many months the company is empty
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct NetworkClientInfo;
 | 
			
		||||
@@ -169,4 +168,17 @@ struct NetworkTextMessageData {
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Simple helper to (more easily) manage authorized keys.
 | 
			
		||||
 *
 | 
			
		||||
 * The authorized keys are hexadecimal representations of their binary form.
 | 
			
		||||
 * The authorized keys are case insensitive.
 | 
			
		||||
 */
 | 
			
		||||
class NetworkAuthorizedKeys : public std::vector<std::string> {
 | 
			
		||||
public:
 | 
			
		||||
	bool Contains(std::string_view key) const;
 | 
			
		||||
	bool Add(std::string_view key);
 | 
			
		||||
	bool Remove(std::string_view key);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif /* NETWORK_TYPE_H */
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user