mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2025-12-23 15:52:55 +01:00
Fix #8802: public key signature being null terminated.
This commit is contained in:
@@ -159,8 +159,7 @@ public:
|
|||||||
|
|
||||||
void Client_Send_TOKEN();
|
void Client_Send_TOKEN();
|
||||||
void Client_Send_AUTH(
|
void Client_Send_AUTH(
|
||||||
const std::string& name, const std::string& password, const std::string& pubkey, const std::string& sig,
|
const std::string& name, const std::string& password, const std::string& pubkey, const std::vector<uint8_t>& signature);
|
||||||
size_t sigsize);
|
|
||||||
void Server_Send_AUTH(NetworkConnection& connection);
|
void Server_Send_AUTH(NetworkConnection& connection);
|
||||||
void Server_Send_TOKEN(NetworkConnection& connection);
|
void Server_Send_TOKEN(NetworkConnection& connection);
|
||||||
void Server_Send_MAP(NetworkConnection* connection = nullptr);
|
void Server_Send_MAP(NetworkConnection* connection = nullptr);
|
||||||
@@ -1358,7 +1357,7 @@ void Network::Client_Send_TOKEN()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Network::Client_Send_AUTH(
|
void Network::Client_Send_AUTH(
|
||||||
const std::string& name, const std::string& password, const std::string& pubkey, const std::string& sig, size_t sigsize)
|
const std::string& name, const std::string& password, const std::string& pubkey, const std::vector<uint8_t>& signature)
|
||||||
{
|
{
|
||||||
std::unique_ptr<NetworkPacket> packet(NetworkPacket::Allocate());
|
std::unique_ptr<NetworkPacket> packet(NetworkPacket::Allocate());
|
||||||
*packet << (uint32_t)NETWORK_COMMAND_AUTH;
|
*packet << (uint32_t)NETWORK_COMMAND_AUTH;
|
||||||
@@ -1366,9 +1365,9 @@ void Network::Client_Send_AUTH(
|
|||||||
packet->WriteString(name.c_str());
|
packet->WriteString(name.c_str());
|
||||||
packet->WriteString(password.c_str());
|
packet->WriteString(password.c_str());
|
||||||
packet->WriteString(pubkey.c_str());
|
packet->WriteString(pubkey.c_str());
|
||||||
assert(sigsize <= (size_t)UINT32_MAX);
|
assert(signature.size() <= (size_t)UINT32_MAX);
|
||||||
*packet << (uint32_t)sigsize;
|
*packet << (uint32_t)signature.size();
|
||||||
packet->Write((const uint8_t*)sig.c_str(), sigsize);
|
packet->Write(signature.data(), signature.size());
|
||||||
_serverConnection->AuthStatus = NETWORK_AUTH_REQUESTED;
|
_serverConnection->AuthStatus = NETWORK_AUTH_REQUESTED;
|
||||||
_serverConnection->QueuePacket(std::move(packet));
|
_serverConnection->QueuePacket(std::move(packet));
|
||||||
}
|
}
|
||||||
@@ -2195,12 +2194,12 @@ void Network::Client_Handle_TOKEN(NetworkConnection& connection, NetworkPacket&
|
|||||||
uint32_t challenge_size;
|
uint32_t challenge_size;
|
||||||
packet >> challenge_size;
|
packet >> challenge_size;
|
||||||
const char* challenge = (const char*)packet.Read(challenge_size);
|
const char* challenge = (const char*)packet.Read(challenge_size);
|
||||||
size_t sigsize;
|
|
||||||
char* signature;
|
std::vector<uint8_t> signature;
|
||||||
const std::string pubkey = _key.PublicKeyString();
|
const std::string pubkey = _key.PublicKeyString();
|
||||||
_challenge.resize(challenge_size);
|
_challenge.resize(challenge_size);
|
||||||
std::memcpy(_challenge.data(), challenge, challenge_size);
|
std::memcpy(_challenge.data(), challenge, challenge_size);
|
||||||
bool ok = _key.Sign(_challenge.data(), _challenge.size(), &signature, &sigsize);
|
bool ok = _key.Sign(_challenge.data(), _challenge.size(), signature);
|
||||||
if (!ok)
|
if (!ok)
|
||||||
{
|
{
|
||||||
log_error("Failed to sign server's challenge.");
|
log_error("Failed to sign server's challenge.");
|
||||||
@@ -2213,9 +2212,7 @@ void Network::Client_Handle_TOKEN(NetworkConnection& connection, NetworkPacket&
|
|||||||
_key.Unload();
|
_key.Unload();
|
||||||
|
|
||||||
const char* password = String::IsNullOrEmpty(gCustomPassword) ? "" : gCustomPassword;
|
const char* password = String::IsNullOrEmpty(gCustomPassword) ? "" : gCustomPassword;
|
||||||
Client_Send_AUTH(gConfigNetwork.player_name.c_str(), password, pubkey.c_str(), signature, sigsize);
|
Client_Send_AUTH(gConfigNetwork.player_name.c_str(), password, pubkey.c_str(), signature);
|
||||||
|
|
||||||
delete[] signature;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Network::Client_Handle_AUTH(NetworkConnection& connection, NetworkPacket& packet)
|
void Network::Client_Handle_AUTH(NetworkConnection& connection, NetworkPacket& packet)
|
||||||
@@ -2403,20 +2400,24 @@ void Network::Server_Handle_AUTH(NetworkConnection& connection, NetworkPacket& p
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const char* signature = (const char*)packet.Read(sigsize);
|
std::vector<uint8_t> signature;
|
||||||
if (signature == nullptr)
|
signature.resize(sigsize);
|
||||||
|
|
||||||
|
const uint8_t* signatureData = (const uint8_t*)packet.Read(sigsize);
|
||||||
|
if (signatureData == nullptr)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Failed to read packet.");
|
throw std::runtime_error("Failed to read packet.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::memcpy(signature.data(), signatureData, sigsize);
|
||||||
|
|
||||||
auto ms = MemoryStream(pubkey, strlen(pubkey));
|
auto ms = MemoryStream(pubkey, strlen(pubkey));
|
||||||
if (!connection.Key.LoadPublic(&ms))
|
if (!connection.Key.LoadPublic(&ms))
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Failed to load public key.");
|
throw std::runtime_error("Failed to load public key.");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool verified = connection.Key.Verify(
|
bool verified = connection.Key.Verify(connection.Challenge.data(), connection.Challenge.size(), signature);
|
||||||
connection.Challenge.data(), connection.Challenge.size(), signature, sigsize);
|
|
||||||
const std::string hash = connection.Key.PublicKeyHash();
|
const std::string hash = connection.Key.PublicKeyHash();
|
||||||
if (verified)
|
if (verified)
|
||||||
{
|
{
|
||||||
@@ -3812,14 +3813,13 @@ void network_send_password(const std::string& password)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const std::string pubkey = gNetwork._key.PublicKeyString();
|
const std::string pubkey = gNetwork._key.PublicKeyString();
|
||||||
size_t sigsize;
|
|
||||||
char* signature;
|
std::vector<uint8_t> signature;
|
||||||
gNetwork._key.Sign(gNetwork._challenge.data(), gNetwork._challenge.size(), &signature, &sigsize);
|
gNetwork._key.Sign(gNetwork._challenge.data(), gNetwork._challenge.size(), signature);
|
||||||
// Don't keep private key in memory. There's no need and it may get leaked
|
// Don't keep private key in memory. There's no need and it may get leaked
|
||||||
// when process dump gets collected at some point in future.
|
// when process dump gets collected at some point in future.
|
||||||
gNetwork._key.Unload();
|
gNetwork._key.Unload();
|
||||||
gNetwork.Client_Send_AUTH(gConfigNetwork.player_name.c_str(), password, pubkey.c_str(), signature, sigsize);
|
gNetwork.Client_Send_AUTH(gConfigNetwork.player_name.c_str(), password, pubkey.c_str(), signature);
|
||||||
delete[] signature;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void network_set_password(const char* password)
|
void network_set_password(const char* password)
|
||||||
|
|||||||
@@ -194,32 +194,27 @@ std::string NetworkKey::PublicKeyHash()
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NetworkKey::Sign(const uint8_t* md, const size_t len, char** signature, size_t* out_size)
|
bool NetworkKey::Sign(const uint8_t* md, const size_t len, std::vector<uint8_t>& signature)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auto rsa = Crypt::CreateRSA();
|
auto rsa = Crypt::CreateRSA();
|
||||||
auto sig = rsa->SignData(*_key, md, len);
|
signature = rsa->SignData(*_key, md, len);
|
||||||
*out_size = sig.size();
|
|
||||||
*signature = new char[sig.size()];
|
|
||||||
std::memcpy(*signature, sig.data(), sig.size());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
log_error("NetworkKey::Sign failed: %s", e.what());
|
log_error("NetworkKey::Sign failed: %s", e.what());
|
||||||
*signature = nullptr;
|
|
||||||
*out_size = 0;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NetworkKey::Verify(const uint8_t* md, const size_t len, const char* sig, const size_t siglen)
|
bool NetworkKey::Verify(const uint8_t* md, const size_t len, const std::vector<uint8_t>& signature)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auto rsa = Crypt::CreateRSA();
|
auto rsa = Crypt::CreateRSA();
|
||||||
return rsa->VerifyData(*_key, md, len, sig, siglen);
|
return rsa->VerifyData(*_key, md, len, signature.data(), signature.size());
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
# include <memory>
|
# include <memory>
|
||||||
# include <string>
|
# include <string>
|
||||||
|
# include <vector>
|
||||||
|
|
||||||
interface IStream;
|
interface IStream;
|
||||||
|
|
||||||
@@ -37,8 +38,8 @@ public:
|
|||||||
std::string PublicKeyString();
|
std::string PublicKeyString();
|
||||||
std::string PublicKeyHash();
|
std::string PublicKeyHash();
|
||||||
void Unload();
|
void Unload();
|
||||||
bool Sign(const uint8_t* md, const size_t len, char** signature, size_t* out_size);
|
bool Sign(const uint8_t* md, const size_t len, std::vector<uint8_t>& signature);
|
||||||
bool Verify(const uint8_t* md, const size_t len, const char* sig, const size_t siglen);
|
bool Verify(const uint8_t* md, const size_t len, const std::vector<uint8_t>& signature);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NetworkKey(const NetworkKey&) = delete;
|
NetworkKey(const NetworkKey&) = delete;
|
||||||
|
|||||||
Reference in New Issue
Block a user