Add support for DW dedi authentication
This commit is contained in:
parent
6c859bf1d0
commit
e107d3fa23
61
src/game/demonware/services/bdDediAuth.cpp
Normal file
61
src/game/demonware/services/bdDediAuth.cpp
Normal file
@ -0,0 +1,61 @@
|
||||
#include <std_include.hpp>
|
||||
#include "bdDediAuth.hpp"
|
||||
#include "game/game.hpp"
|
||||
#include "steam/steam.hpp"
|
||||
#include "utils/cryptography.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
void bdDediAuth::call_service(i_server* server, const std::string& data)
|
||||
{
|
||||
bit_buffer buffer(data);
|
||||
|
||||
bool more_data;
|
||||
buffer.set_use_data_types(false);
|
||||
buffer.read_bool(&more_data);
|
||||
buffer.set_use_data_types(true);
|
||||
|
||||
uint32_t seed, title_id, ticket_size;
|
||||
buffer.read_uint32(&seed);
|
||||
buffer.read_uint32(&title_id);
|
||||
|
||||
uint8_t ticket[1024];
|
||||
buffer.read_bytes(std::min(ticket_size, static_cast<uint32_t>(sizeof(ticket))), ticket);
|
||||
|
||||
game::native::bdAuthTicket auth_ticket{};
|
||||
std::memset(&auth_ticket, 0xA, sizeof auth_ticket);
|
||||
|
||||
auth_ticket.m_magicNumber = 0x0EFBDADDE;
|
||||
auth_ticket.m_type = 0;
|
||||
auth_ticket.m_titleID = title_id;
|
||||
auth_ticket.m_userID = steam::SteamUser()->GetSteamID().bits;
|
||||
auth_ticket.m_licenseID = 4;
|
||||
|
||||
auto key = utils::cryptography::tiger::compute(SERVER_CD_KEY);
|
||||
|
||||
strcpy_s(auth_ticket.m_username, "Open-IW5 Server");
|
||||
std::memcpy(auth_ticket.m_sessionKey, key.data(), 24);
|
||||
auth_ticket.m_timeIssued = static_cast<uint32_t>(time(nullptr));
|
||||
|
||||
uint8_t lsg_ticket[128];
|
||||
ZeroMemory(&lsg_ticket, sizeof lsg_ticket);
|
||||
std::memcpy(lsg_ticket, key.data(), 24);
|
||||
|
||||
const auto iv = utils::cryptography::tiger::compute(std::string(reinterpret_cast<char*>(&seed), 4));
|
||||
|
||||
const std::string enc_key(reinterpret_cast<char*>(&ticket[32]), 24);
|
||||
auto enc_ticket = utils::cryptography::des3::encrypt(
|
||||
std::string(reinterpret_cast<char*>(&auth_ticket), sizeof(auth_ticket)), iv, enc_key);
|
||||
|
||||
bit_buffer response;
|
||||
response.set_use_data_types(false);
|
||||
response.write_bool(false);
|
||||
response.write_uint32(700);
|
||||
response.write_uint32(seed);
|
||||
response.write_bytes(enc_ticket.size(), enc_ticket.data());
|
||||
response.write_bytes(sizeof(lsg_ticket), lsg_ticket);
|
||||
|
||||
auto reply = server->create_message(29);
|
||||
reply->send(&response, false);
|
||||
}
|
||||
}
|
11
src/game/demonware/services/bdDediAuth.hpp
Normal file
11
src/game/demonware/services/bdDediAuth.hpp
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
#include "../i_service.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class bdDediAuth final : public i_generic_service<12>
|
||||
{
|
||||
public:
|
||||
void call_service(i_server* server, const std::string& data) override;
|
||||
};
|
||||
}
|
71
src/game/demonware/services/bdDediRSAAuth.cpp
Normal file
71
src/game/demonware/services/bdDediRSAAuth.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
#include <std_include.hpp>
|
||||
#include "bdDediRSAAuth.hpp"
|
||||
#include "game/game.hpp"
|
||||
#include "steam/steam.hpp"
|
||||
#include "utils/cryptography.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
void bdDediRSAAuth::call_service(i_server* server, const std::string& data)
|
||||
{
|
||||
bit_buffer buffer(data);
|
||||
|
||||
bool more_data;
|
||||
buffer.set_use_data_types(false);
|
||||
buffer.read_bool(&more_data);
|
||||
buffer.set_use_data_types(true);
|
||||
|
||||
uint32_t seed, title_id, ticket_size;
|
||||
buffer.read_uint32(&seed);
|
||||
buffer.read_uint32(&title_id);
|
||||
|
||||
unsigned char rsakey[140];
|
||||
buffer.read_bytes(sizeof(rsakey), rsakey);
|
||||
|
||||
uint8_t ticket[1024];
|
||||
buffer.read_bytes(std::min(ticket_size, static_cast<uint32_t>(sizeof(ticket))), ticket);
|
||||
|
||||
game::native::bdAuthTicket auth_ticket{};
|
||||
std::memset(&auth_ticket, 0xA, sizeof auth_ticket);
|
||||
|
||||
auth_ticket.m_magicNumber = 0x0EFBDADDE;
|
||||
auth_ticket.m_type = 0;
|
||||
auth_ticket.m_titleID = title_id;
|
||||
auth_ticket.m_userID = steam::SteamUser()->GetSteamID().bits;
|
||||
|
||||
auto key = utils::cryptography::tiger::compute(SERVER_CD_KEY);
|
||||
|
||||
strcpy_s(auth_ticket.m_username, "Open-IW5 Server");
|
||||
std::memcpy(auth_ticket.m_sessionKey, key.data(), 24);
|
||||
auth_ticket.m_timeIssued = static_cast<uint32_t>(time(nullptr));
|
||||
|
||||
uint8_t lsg_ticket[128];
|
||||
ZeroMemory(&lsg_ticket, sizeof lsg_ticket);
|
||||
std::memcpy(lsg_ticket, key.data(), 24);
|
||||
|
||||
const auto iv = utils::cryptography::tiger::compute(std::string(reinterpret_cast<char*>(&seed), 4));
|
||||
|
||||
const std::string enc_key(reinterpret_cast<char*>(&ticket[32]), 24);
|
||||
auto enc_ticket = utils::cryptography::des3::encrypt(
|
||||
std::string(reinterpret_cast<char*>(&auth_ticket), sizeof(auth_ticket)), iv, enc_key);
|
||||
|
||||
register_hash(&sha1_desc);
|
||||
register_prng(&yarrow_desc);
|
||||
|
||||
std::string encrypted_key = utils::cryptography::rsa::encrypt(std::string(SERVER_CD_KEY, 24),
|
||||
std::string("DW-RSAENC", 10),
|
||||
std::string(PCHAR(rsakey), sizeof(rsakey)));
|
||||
|
||||
bit_buffer response;
|
||||
response.set_use_data_types(false);
|
||||
response.write_bool(false);
|
||||
response.write_uint32(700);
|
||||
response.write_uint32(seed);
|
||||
response.write_bytes(enc_ticket.size(), enc_ticket.data());
|
||||
response.write_bytes(sizeof(lsg_ticket), lsg_ticket);
|
||||
response.write_bytes(encrypted_key.size(), encrypted_key.data());
|
||||
|
||||
auto reply = server->create_message(29);
|
||||
reply->send(&response, false);
|
||||
}
|
||||
}
|
11
src/game/demonware/services/bdDediRSAAuth.hpp
Normal file
11
src/game/demonware/services/bdDediRSAAuth.hpp
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
#include "../i_service.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class bdDediRSAAuth final : public i_generic_service<26>
|
||||
{
|
||||
public:
|
||||
void call_service(i_server* server, const std::string& data) override;
|
||||
};
|
||||
}
|
@ -5,6 +5,8 @@
|
||||
|
||||
#define SELECT_VALUE(sp, mp, dedi) (game::is_sp() ? (sp) : (game::is_mp() ? (mp) : (dedi)))
|
||||
|
||||
#define SERVER_CD_KEY "Open-IW5-CD-Key"
|
||||
|
||||
namespace game
|
||||
{
|
||||
namespace native
|
||||
|
1096
src/game/structs.hpp
1096
src/game/structs.hpp
File diff suppressed because it is too large
Load Diff
@ -7,8 +7,10 @@
|
||||
|
||||
#include "game/demonware/services/bdLSGHello.hpp" // 7
|
||||
#include "game/demonware/services/bdStorage.hpp" // 10
|
||||
#include "game/demonware/services/bdDediAuth.hpp" // 12
|
||||
#include "game/demonware/services/bdTitleUtilities.hpp" // 12
|
||||
#include "game/demonware/services/bdDML.hpp" // 27
|
||||
#include "game/demonware/services/bdDediRSAAuth.hpp" // 26
|
||||
#include "game/demonware/services/bdSteamAuth.hpp" // 28
|
||||
|
||||
namespace demonware
|
||||
@ -375,7 +377,9 @@ namespace demonware
|
||||
auto lsg_server = register_server("mw3-pc-lobby.prod.demonware.net");
|
||||
auto auth_server = register_server("mw3-pc-auth.prod.demonware.net");
|
||||
|
||||
auth_server->register_service<bdDediAuth>();
|
||||
auth_server->register_service<bdSteamAuth>();
|
||||
auth_server->register_service<bdDediRSAAuth>();
|
||||
|
||||
lsg_server->register_service<bdLSGHello>();
|
||||
lsg_server->register_service<bdStorage>();
|
||||
|
@ -127,6 +127,54 @@ namespace utils
|
||||
reinterpret_cast<const uint8_t*>(message.data()), message.size(), &result, key.get()) == CRYPT_OK && result != 0);
|
||||
}
|
||||
|
||||
std::string rsa::encrypt(const std::string& data, const std::string& hash, const std::string& key)
|
||||
{
|
||||
initialize();
|
||||
|
||||
const auto prng_id = find_prng("yarrow");
|
||||
|
||||
rsa_key new_key;
|
||||
rsa_import(PBYTE(key.data()), key.size(), &new_key);
|
||||
|
||||
prng_state yarrow;
|
||||
rng_make_prng(128, prng_id, &yarrow, nullptr);
|
||||
|
||||
unsigned char buffer[0x80];
|
||||
unsigned long length = sizeof(buffer);
|
||||
|
||||
const auto rsa_result = rsa_encrypt_key( //
|
||||
PBYTE(data.data()), //
|
||||
data.size(), //
|
||||
buffer, //
|
||||
&length, //
|
||||
PBYTE(hash.data()), //
|
||||
hash.size(), //
|
||||
&yarrow, //
|
||||
prng_id, //
|
||||
find_hash("sha1"), //
|
||||
&new_key);
|
||||
|
||||
rsa_free(&new_key);
|
||||
|
||||
if (rsa_result == CRYPT_OK)
|
||||
{
|
||||
return std::string(PCHAR(buffer), length);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void rsa::initialize()
|
||||
{
|
||||
static auto initialized = false;
|
||||
if (initialized) return;
|
||||
initialized = true;
|
||||
|
||||
ltc_mp = ltm_desc;
|
||||
register_hash(&sha1_desc);
|
||||
register_prng(&yarrow_desc);
|
||||
}
|
||||
|
||||
std::string des3::encrypt(const std::string& data, const std::string& iv, const std::string& key)
|
||||
{
|
||||
initialize();
|
||||
|
@ -39,6 +39,15 @@ namespace utils
|
||||
static bool verify_message(key key, const std::string& message, const std::string& signature);
|
||||
};
|
||||
|
||||
class rsa final
|
||||
{
|
||||
public:
|
||||
static std::string encrypt(const std::string& data, const std::string& hash, const std::string& key);
|
||||
|
||||
private:
|
||||
static void initialize();
|
||||
};
|
||||
|
||||
class des3 final
|
||||
{
|
||||
public:
|
||||
|
Loading…
Reference in New Issue
Block a user