forked from alterware/s1-mod
init
This commit is contained in:
167
src/client/game/demonware/servers/auth3_server.cpp
Normal file
167
src/client/game/demonware/servers/auth3_server.cpp
Normal file
@ -0,0 +1,167 @@
|
||||
#include <std_include.hpp>
|
||||
|
||||
#include "auth3_server.hpp"
|
||||
#include "../keys.hpp"
|
||||
|
||||
#include <utils/cryptography.hpp>
|
||||
#include <utils/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/"))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("[DW]: [auth]: user requested authentication.\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int title_id = 0;
|
||||
unsigned int iv_seed = 0;
|
||||
std::string identity{};
|
||||
std::string token{};
|
||||
|
||||
rapidjson::Document j;
|
||||
const rapidjson::ParseResult parse_result = j.Parse(packet);
|
||||
|
||||
if (!parse_result || !j.IsObject())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
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("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("token") && extra_data["token"].IsString())
|
||||
{
|
||||
auto& token_field = extra_data["token"];
|
||||
std::string token_b64(token_field.GetString(), token_field.GetStringLength());
|
||||
token = utils::cryptography::base64::decode(token_b64);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("[DW]: [auth]: authenticating user %s\n", token.data() + 64);
|
||||
#endif
|
||||
|
||||
std::string auth_key(reinterpret_cast<char*>(token.data() + 32), 24);
|
||||
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 = 0x0EFBDADDE;
|
||||
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 = reinterpret_cast<uint64_t>(token.data() + 56);
|
||||
strncpy_s(ticket.m_username, sizeof(ticket.m_username), reinterpret_cast<char*>(token.data() + 64), 64);
|
||||
std::memcpy(ticket.m_sessionKey, session_key.data(), 24);
|
||||
|
||||
const auto iv = utils::cryptography::tiger::compute(std::string(reinterpret_cast<char*>(&iv_seed), 4));
|
||||
const auto ticket_enc = utils::cryptography::des3::encrypt(
|
||||
std::string(reinterpret_cast<char*>(&ticket), sizeof(ticket)), iv, auth_key);
|
||||
const auto ticket_b64 = utils::cryptography::base64::encode(
|
||||
reinterpret_cast<const unsigned char*>(ticket_enc.data()), 128);
|
||||
|
||||
// server_ticket
|
||||
uint8_t auth_data[128];
|
||||
std::memset(&auth_data, 0, sizeof auth_data);
|
||||
std::memcpy(auth_data, session_key.data(), 24);
|
||||
const auto auth_data_b64 = utils::cryptography::base64::encode(auth_data, 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);
|
||||
|
||||
// json content
|
||||
rapidjson::Document doc;
|
||||
doc.SetObject();
|
||||
|
||||
doc.AddMember("auth_task", "29", doc.GetAllocator());
|
||||
doc.AddMember("code", "700", doc.GetAllocator());
|
||||
|
||||
auto seed = std::to_string(iv_seed);
|
||||
doc.AddMember("iv_seed", rapidjson::StringRef(seed.data(), seed.size()), doc.GetAllocator());
|
||||
doc.AddMember("client_ticket", rapidjson::StringRef(ticket_b64.data(), ticket_b64.size()), doc.GetAllocator());
|
||||
doc.AddMember("server_ticket", rapidjson::StringRef(auth_data_b64.data(), auth_data_b64.size()),
|
||||
doc.GetAllocator());
|
||||
doc.AddMember("client_id", "", doc.GetAllocator());
|
||||
doc.AddMember("account_type", "steam", doc.GetAllocator());
|
||||
doc.AddMember("crossplay_enabled", false, doc.GetAllocator());
|
||||
doc.AddMember("loginqueue_eanbled", false, 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(utils::string::va("Date: %s GMT\r\n", date));
|
||||
result.append(utils::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);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("[DW]: [auth]: user successfully authenticated.\n");
|
||||
#endif
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user