201 lines
4.4 KiB
C++
201 lines
4.4 KiB
C++
#include <std_include.hpp>
|
|
#include "module/dw.hpp"
|
|
#include "utils/cryptography.hpp"
|
|
|
|
namespace demonware
|
|
{
|
|
std::string unencrypted_reply::get_data()
|
|
{
|
|
byte_buffer result;
|
|
result.set_use_data_types(false);
|
|
|
|
result.write_int32(static_cast<int>(this->buffer_.size()) + 2);
|
|
result.write_bool(false);
|
|
result.write_byte(this->get_type());
|
|
result.write(this->buffer_);
|
|
|
|
return result.get_buffer();
|
|
}
|
|
|
|
std::string encrypted_reply::get_data()
|
|
{
|
|
byte_buffer result;
|
|
result.set_use_data_types(false);
|
|
|
|
byte_buffer enc_buffer;
|
|
enc_buffer.set_use_data_types(false);
|
|
enc_buffer.write_int32(0xDEADBEEF);
|
|
enc_buffer.write_byte(this->get_type());
|
|
enc_buffer.write(this->buffer_);
|
|
|
|
auto data = enc_buffer.get_buffer();
|
|
|
|
auto size = enc_buffer.size();
|
|
size = ~7 & (size + 7); // 8 byte align
|
|
data.resize(size);
|
|
|
|
result.write_int32(static_cast<int>(size) + 5);
|
|
result.write_byte(true);
|
|
|
|
auto seed = 0x13371337;
|
|
result.write_int32(seed);
|
|
|
|
const auto iv = utils::cryptography::tiger::compute(std::string(reinterpret_cast<char*>(&seed), 4));
|
|
|
|
const std::string key(reinterpret_cast<char*>(dw::get_key(true)), 24);
|
|
result.write(utils::cryptography::des3::encrypt(data, iv, key));
|
|
|
|
return result.get_buffer();
|
|
}
|
|
|
|
service_server::service_server(std::string _name) : name_(std::move(_name))
|
|
{
|
|
this->address_ = utils::cryptography::jenkins_one_at_a_time::compute(this->name_);
|
|
}
|
|
|
|
unsigned long service_server::get_address() const
|
|
{
|
|
return this->address_;
|
|
}
|
|
|
|
int service_server::send(const char* buf, const int len)
|
|
{
|
|
if (len <= 3) return -1;
|
|
std::lock_guard<std::recursive_mutex> _(this->mutex_);
|
|
|
|
this->incoming_queue_.push(std::string(buf, len));
|
|
|
|
return len;
|
|
}
|
|
|
|
int service_server::recv(char* buf, int len)
|
|
{
|
|
if (len > 0 && !this->outgoing_queue_.empty())
|
|
{
|
|
std::lock_guard<std::recursive_mutex> _(this->mutex_);
|
|
|
|
len = std::min(len, static_cast<int>(this->outgoing_queue_.size()));
|
|
for (auto i = 0; i < len; ++i)
|
|
{
|
|
buf[i] = this->outgoing_queue_.front();
|
|
this->outgoing_queue_.pop();
|
|
}
|
|
|
|
return len;
|
|
}
|
|
|
|
return SOCKET_ERROR;
|
|
}
|
|
|
|
void service_server::send_reply(reply* data)
|
|
{
|
|
if (!data) return;
|
|
|
|
std::lock_guard _(this->mutex_);
|
|
|
|
this->reply_sent_ = true;
|
|
const auto buffer = data->get_data();
|
|
for (auto& byte : buffer)
|
|
{
|
|
this->outgoing_queue_.push(byte);
|
|
}
|
|
}
|
|
|
|
void service_server::call_handler(const uint8_t type, const std::string& data)
|
|
{
|
|
if (this->services_.find(type) != this->services_.end())
|
|
{
|
|
this->services_[type]->call_service(this, data);
|
|
}
|
|
else
|
|
{
|
|
printf("DW: Missing handler of type %d\n", type);
|
|
}
|
|
}
|
|
|
|
void service_server::run_frame()
|
|
{
|
|
if (!this->incoming_queue_.empty())
|
|
{
|
|
std::lock_guard _(this->mutex_);
|
|
const auto packet = this->incoming_queue_.front();
|
|
this->incoming_queue_.pop();
|
|
|
|
this->parse_packet(packet);
|
|
}
|
|
}
|
|
|
|
void service_server::parse_packet(const std::string& packet)
|
|
{
|
|
byte_buffer buffer(packet);
|
|
buffer.set_use_data_types(false);
|
|
|
|
try
|
|
{
|
|
while (buffer.has_more_data())
|
|
{
|
|
int size;
|
|
buffer.read_int32(&size);
|
|
|
|
if (size <= 0)
|
|
{
|
|
const std::string zero("\x00\x00\x00\x00", 4);
|
|
|
|
raw_reply reply(zero);
|
|
this->send_reply(&reply);
|
|
return;
|
|
}
|
|
else if (size == 200) // Connection id
|
|
{
|
|
byte_buffer bbufer;
|
|
bbufer.write_uint64(0x00000000000000FD);
|
|
|
|
auto reply = this->create_message(4);
|
|
reply->send(&bbufer, false);
|
|
return;
|
|
}
|
|
|
|
if (buffer.size() < size_t(size)) return;
|
|
|
|
byte_buffer p_buffer;
|
|
p_buffer.set_use_data_types(false);
|
|
p_buffer.get_buffer().resize(size);
|
|
buffer.read(size, p_buffer.get_buffer().data());
|
|
|
|
bool enc;
|
|
p_buffer.read_bool(&enc);
|
|
|
|
if (enc)
|
|
{
|
|
int iv;
|
|
p_buffer.read_int32(&iv);
|
|
|
|
auto iv_hash = utils::cryptography::tiger::compute(std::string(reinterpret_cast<char*>(&iv), 4));
|
|
|
|
const std::string key(reinterpret_cast<char*>(dw::get_key(false)), 24);
|
|
p_buffer = byte_buffer{utils::cryptography::des3::decrypt(p_buffer.get_remaining(), iv_hash, key)};
|
|
p_buffer.set_use_data_types(false);
|
|
|
|
int checksum;
|
|
p_buffer.read_int32(&checksum);
|
|
}
|
|
|
|
uint8_t type;
|
|
p_buffer.read_byte(&type);
|
|
printf("DW: Handling message of type %d (encrypted: %d)\n", type, enc);
|
|
|
|
this->reply_sent_ = false;
|
|
this->call_handler(type, p_buffer.get_remaining());
|
|
|
|
if (!this->reply_sent_ && type != 7)
|
|
{
|
|
this->create_reply(type)->send();
|
|
}
|
|
}
|
|
}
|
|
catch (...)
|
|
{
|
|
}
|
|
}
|
|
}
|