implement BB client's config scramble logic
This commit is contained in:
+58
-30
@@ -1043,24 +1043,58 @@ static void on_9E_XB(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
|
||||
send_command(c, 0x9F, 0x00);
|
||||
}
|
||||
|
||||
static void scramble_bb_security_data(parray<uint8_t, 0x28>& data, uint8_t which, bool reverse) {
|
||||
static const uint8_t forward_orders[8][5] = {
|
||||
{2, 0, 1, 4, 3},
|
||||
{3, 4, 0, 1, 2},
|
||||
{2, 3, 4, 0, 1},
|
||||
{2, 3, 0, 1, 4},
|
||||
{0, 2, 3, 4, 1},
|
||||
{1, 4, 2, 3, 0},
|
||||
{2, 0, 1, 4, 3},
|
||||
{1, 0, 3, 4, 2},
|
||||
};
|
||||
static const uint8_t reverse_orders[8][5] = {
|
||||
{1, 2, 0, 4, 3},
|
||||
{2, 3, 4, 0, 1},
|
||||
{3, 4, 0, 1, 2},
|
||||
{2, 3, 0, 1, 4},
|
||||
{0, 4, 1, 2, 3},
|
||||
{4, 0, 2, 3, 1},
|
||||
{1, 2, 0, 4, 3},
|
||||
{1, 0, 4, 2, 3},
|
||||
};
|
||||
const auto& order = reverse ? reverse_orders[which & 7] : forward_orders[which & 7];
|
||||
parray<uint8_t, 0x28> scrambled_data;
|
||||
for (size_t z = 0; z < 5; z++) {
|
||||
for (size_t x = 0; x < 8; x++) {
|
||||
scrambled_data[(z * 8) + x] = data[(order[z] * 8) + x];
|
||||
}
|
||||
}
|
||||
data = scrambled_data;
|
||||
}
|
||||
|
||||
static void on_93_BB(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
|
||||
const auto& cmd = check_size_t<C_Login_BB_93>(data, sizeof(C_Login_BB_93) - 8, sizeof(C_Login_BB_93));
|
||||
const auto& base_cmd = check_size_t<C_LoginBase_BB_93>(data, 0xFFFF);
|
||||
auto s = c->require_server_state();
|
||||
|
||||
bool is_old_format;
|
||||
if (data.size() == sizeof(C_Login_BB_93) - 8) {
|
||||
is_old_format = true;
|
||||
} else if (data.size() == sizeof(C_Login_BB_93)) {
|
||||
is_old_format = false;
|
||||
} else {
|
||||
throw runtime_error("invalid size for 93 command");
|
||||
parray<uint8_t, 0x28> config_data = (data.size() == sizeof(C_LoginWithoutHardwareInfo_BB_93))
|
||||
? check_size_t<C_LoginWithoutHardwareInfo_BB_93>(data).client_config
|
||||
: check_size_t<C_LoginWithHardwareInfo_BB_93>(data).client_config;
|
||||
|
||||
// If security_token is zero, the game scrambles the client config data based
|
||||
// on the first character in the username. We undo the scramble here.
|
||||
if (base_cmd.security_token == 0) {
|
||||
scramble_bb_security_data(config_data, base_cmd.username.at(0), true);
|
||||
}
|
||||
|
||||
c->config.set_flags_for_version(c->version(), cmd.sub_version);
|
||||
c->channel.language = cmd.language;
|
||||
c->config.set_flags_for_version(c->version(), base_cmd.sub_version);
|
||||
c->channel.language = base_cmd.language;
|
||||
string username = base_cmd.username.decode();
|
||||
string password = base_cmd.password.decode();
|
||||
|
||||
try {
|
||||
auto l = s->license_index->verify_bb(cmd.username.decode(), cmd.password.decode());
|
||||
auto l = s->license_index->verify_bb(username, password);
|
||||
c->set_license(l);
|
||||
|
||||
} catch (const LicenseIndex::no_username& e) {
|
||||
@@ -1080,9 +1114,9 @@ static void on_93_BB(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
|
||||
return;
|
||||
} else {
|
||||
auto l = s->license_index->create_license();
|
||||
l->serial_number = fnv1a32(cmd.username.decode()) & 0x7FFFFFFF;
|
||||
l->bb_username = cmd.username.decode();
|
||||
l->bb_password = cmd.password.decode();
|
||||
l->serial_number = fnv1a32(username) & 0x7FFFFFFF;
|
||||
l->bb_username = username;
|
||||
l->bb_password = password;
|
||||
s->license_index->add(l);
|
||||
if (!s->is_replay) {
|
||||
l->save();
|
||||
@@ -1093,16 +1127,10 @@ static void on_93_BB(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (is_old_format) {
|
||||
c->config.parse_from(cmd.var.old_client_config);
|
||||
} else {
|
||||
c->config.parse_from(cmd.var.new_clients.client_config);
|
||||
}
|
||||
} catch (const invalid_argument&) {
|
||||
string version_string = is_old_format
|
||||
? cmd.var.old_client_config.as_string()
|
||||
: cmd.var.new_clients.client_config.as_string();
|
||||
if (base_cmd.guild_card_number != 0) {
|
||||
c->config.parse_from(config_data);
|
||||
} else {
|
||||
string version_string = config_data.as_string();
|
||||
strip_trailing_zeroes(version_string);
|
||||
// Note: Tethealla PSOBB is actually Japanese PSOBB, but with most of the
|
||||
// files replaced with English text/graphics/etc. For this reason, it still
|
||||
@@ -1113,17 +1141,17 @@ static void on_93_BB(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
|
||||
c->config.set_flag(Client::Flag::FORCE_ENGLISH_LANGUAGE_BB);
|
||||
}
|
||||
}
|
||||
c->channel.language = c->config.check_flag(Client::Flag::FORCE_ENGLISH_LANGUAGE_BB) ? 1 : cmd.language;
|
||||
c->bb_connection_phase = cmd.connection_phase;
|
||||
c->bb_character_index = cmd.character_slot;
|
||||
c->channel.language = c->config.check_flag(Client::Flag::FORCE_ENGLISH_LANGUAGE_BB) ? 1 : base_cmd.language;
|
||||
c->bb_connection_phase = base_cmd.connection_phase;
|
||||
c->bb_character_index = base_cmd.character_slot;
|
||||
|
||||
if (cmd.menu_id == MenuID::LOBBY) {
|
||||
c->preferred_lobby_id = cmd.preferred_lobby_id;
|
||||
if (base_cmd.menu_id == MenuID::LOBBY) {
|
||||
c->preferred_lobby_id = base_cmd.preferred_lobby_id;
|
||||
}
|
||||
|
||||
send_client_init_bb(c, 0);
|
||||
|
||||
if (cmd.guild_card_number == 0) {
|
||||
if (base_cmd.guild_card_number == 0) {
|
||||
// On first login, send the client to the data server port
|
||||
send_reconnect(c, s->connect_address_for_client(c), s->name_to_port_config.at("bb-data1")->port);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user