t8-mod/source/proxy-dll/demonware/servers/auth3_server.cpp
2023-11-10 13:52:20 -08:00

185 lines
5.7 KiB
C++

#include <std_include.hpp>
#include "auth3_server.hpp"
#include "../keys.hpp"
#include <utilities/cryptography.hpp>
#include <utilities/string.hpp>
namespace demonware
{
namespace
{
#pragma pack(push, 1)
struct auth_ticket
{
unsigned int m_magicNumber;
char m_type;
unsigned int m_titleID;
unsigned int m_timeIssued;
unsigned int m_timeExpires;
unsigned __int64 m_licenseID;
unsigned __int64 m_userID;
char m_username[64];
char m_sessionKey[24];
char m_usingHashMagicNumber[3];
char m_hash[4];
};
#pragma pack(pop)
}
void auth3_server::send_reply(reply* data)
{
if (!data) return;
this->send(data->data());
}
void auth3_server::handle(const std::string& packet)
{
if (packet.starts_with("POST /auth/"))
{
#ifndef NDEBUG
logger::write(logger::LOG_TYPE_DEBUG, "[DW]: [auth]: user requested authentication.");
#endif
return;
}
unsigned int title_id = 0;
unsigned int iv_seed = 0;
std::string identity{};
std::string session_token{};
std::string account_token{};
rapidjson::Document j;
j.Parse(packet.data(), packet.size());
if (j.HasMember("title_id") && j["title_id"].IsString())
{
title_id = std::stoul(j["title_id"].GetString());
}
if (j.HasMember("iv_seed") && j["iv_seed"].IsString())
{
iv_seed = std::stoul(j["iv_seed"].GetString());
}
if (j.HasMember("identity") && j["identity"].IsString())
{
identity = j["identity"].GetString();
}
if (j.HasMember("extra_data") && j["extra_data"].IsString())
{
rapidjson::Document extra_data;
auto& ed = j["extra_data"];
extra_data.Parse(ed.GetString(), ed.GetStringLength());
if (extra_data.HasMember("session_token") && extra_data["session_token"].IsString())
{
auto& token_field = extra_data["session_token"];
std::string token_b64(token_field.GetString(), token_field.GetStringLength());
session_token = token_b64;
}
if (extra_data.HasMember("account_token") && extra_data["account_token"].IsString())
{
auto& token_field = extra_data["account_token"];
std::string token_b64(token_field.GetString(), token_field.GetStringLength());
account_token = utilities::cryptography::base64::decode(token_b64);
}
}
std::string session_key(
"\x13\x37\x13\x37\x13\x37\x13\x37\x13\x37\x13\x37\x13\x37\x13\x37\x13\x37\x13\x37\x13\x37\x13\x37", 24);
// client_ticket
auth_ticket ticket{};
std::memset(&ticket, 0x0, sizeof ticket);
ticket.m_magicNumber = 0xEFBDADDE;
ticket.m_type = 0;
ticket.m_titleID = title_id;
ticket.m_timeIssued = static_cast<uint32_t>(time(nullptr));
ticket.m_timeExpires = ticket.m_timeIssued + 30000;
ticket.m_licenseID = 0;
ticket.m_userID = 0;
strncpy_s(ticket.m_username, sizeof(ticket.m_username), session_token.data(), session_token.length());
std::memcpy(ticket.m_sessionKey, session_key.data(), 24);
const auto client_ticket_b64 = utilities::cryptography::base64::encode(reinterpret_cast<const unsigned char*>(&ticket), sizeof(ticket));
// server_ticket
uint8_t server_ticket[128];
std::memset(&server_ticket, 0, sizeof server_ticket);
std::memcpy(server_ticket, session_key.data(), 24);
const auto server_ticket_b64 = utilities::cryptography::base64::encode(server_ticket, 128);
demonware::set_session_key(session_key);
// header time
char date[64];
const auto now = time(nullptr);
tm gmtm{};
gmtime_s(&gmtm, &now);
strftime(date, 64, "%a, %d %b %G %T", &gmtm);
rapidjson::Document extra;
extra.SetObject();
std::string username = std::string(ticket.m_username, sizeof(ticket.m_username)).data();
extra.AddMember("username", username, extra.GetAllocator());
extra.AddMember("time_to_live", 9999, extra.GetAllocator());
const auto lul = utilities::cryptography::base64::encode("lul");
extra.AddMember("extended_data", lul, extra.GetAllocator());
rapidjson::StringBuffer extra_buffer{};
rapidjson::Writer<rapidjson::StringBuffer, rapidjson::Document::EncodingType, rapidjson::ASCII<>>
extra_writer(extra_buffer);
extra.Accept(extra_writer);
std::string extra_data{};
extra_data.append(extra_buffer.GetString(), extra_buffer.GetLength());
// json content
rapidjson::Document doc;
doc.SetObject();
doc.AddMember("auth_task", "85", doc.GetAllocator());
doc.AddMember("code", "700", doc.GetAllocator());
auto seed = std::to_string(iv_seed);
doc.AddMember("iv_seed", seed, doc.GetAllocator());
doc.AddMember("client_ticket", client_ticket_b64, doc.GetAllocator());
doc.AddMember("server_ticket", server_ticket_b64, doc.GetAllocator());
doc.AddMember("client_id", "treyarch-cod-t8-bnet", doc.GetAllocator());
doc.AddMember("account_type", "bnet", doc.GetAllocator());
doc.AddMember("crossplay_enabled", false, doc.GetAllocator());
doc.AddMember("loginqueue_eanbled", false, doc.GetAllocator());
doc.AddMember("identity", identity, doc.GetAllocator());
doc.AddMember("extra_data", extra_data, doc.GetAllocator());
doc.AddMember("service_level", "paid", doc.GetAllocator());
rapidjson::Value value{};
doc.AddMember("lsg_endpoint", value, doc.GetAllocator());
rapidjson::StringBuffer buffer{};
rapidjson::Writer<rapidjson::StringBuffer, rapidjson::Document::EncodingType, rapidjson::ASCII<>>
writer(buffer);
doc.Accept(writer);
// http stuff
std::string result;
result.append("HTTP/1.1 200 OK\r\n");
result.append("Server: TornadoServer/4.5.3\r\n");
result.append("Content-Type: application/json\r\n");
result.append(utilities::string::va("Date: %s GMT\r\n", date));
result.append(utilities::string::va("Content-Length: %d\r\n\r\n", buffer.GetLength()));
result.append(buffer.GetString(), buffer.GetLength());
raw_reply reply(result);
this->send_reply(&reply);
#ifndef NDEBUG
logger::write(logger::LOG_TYPE_DEBUG, "[DW]: [auth]: user successfully authenticated.");
#endif
}
}