fix login commands in tests

This commit is contained in:
Martin Michelsen
2022-07-27 00:09:14 -07:00
parent 415aa88bd3
commit ea62275f89
10 changed files with 210 additions and 50 deletions
+139 -1
View File
@@ -44,6 +44,133 @@ shared_ptr<ReplaySession::Event> ReplaySession::create_event(
return event;
}
void ReplaySession::check_for_password(shared_ptr<const Event> ev) const {
auto version = this->clients.at(ev->client_id)->version;
auto check_pw = [&](const string& pw) {
if (!this->required_password.empty() && (pw != this->required_password)) {
throw runtime_error("sent password is incorrect");
}
};
auto check_ak = [&](const string& ak) {
if (this->required_access_key.empty()) {
return;
}
string ref_access_key;
if (version == GameVersion::DC || version == GameVersion::PC || version == GameVersion::PATCH) {
ref_access_key = this->required_access_key.substr(0, 8);
} else {
ref_access_key = this->required_access_key;
}
if (ak != ref_access_key) {
throw runtime_error("sent access key is incorrect");
}
};
auto check_either = [&](const string& s) {
try {
check_ak(s);
} catch (const exception&) {
check_pw(s);
}
};
const void* cmd_data = ev->data.data() + ((version == GameVersion::BB) ? 8 : 4);
size_t cmd_size = ev->data.size() - ((version == GameVersion::BB) ? 8 : 4);
switch (version) {
case GameVersion::DC:
// TODO
throw logic_error("sent passwords cannot be checked on DC");
case GameVersion::PATCH: {
const auto& header = check_size_t<PSOCommandHeaderPC>(
ev->data, sizeof(PSOCommandHeaderPC), 0xFFFF);
if (header.command == 0x04) {
check_either(check_size_t<C_Login_Patch_04>(cmd_data, cmd_size).password);
}
break;
}
case GameVersion::PC: {
const auto& header = check_size_t<PSOCommandHeaderPC>(
ev->data, sizeof(PSOCommandHeaderPC), 0xFFFF);
if (header.command == 0x03) {
check_ak(check_size_t<C_LegacyLogin_PC_V3_03>(cmd_data, cmd_size).access_key2);
} else if (header.command == 0x04) {
check_ak(check_size_t<C_LegacyLogin_PC_V3_04>(cmd_data, cmd_size).access_key);
} else if (header.command == 0x9A) {
const auto& cmd = check_size_t<C_Login_DC_PC_V3_9A>(cmd_data, cmd_size);
check_ak(cmd.access_key);
check_ak(cmd.access_key2);
} else if (header.command == 0x9C) {
const auto& cmd = check_size_t<C_Register_DC_PC_V3_9C>(cmd_data, cmd_size);
check_ak(cmd.access_key);
check_pw(cmd.password);
} else if (header.command == 0x9D) {
const auto& cmd = check_size_t<C_Login_PC_9D>(cmd_data, cmd_size,
sizeof(C_Login_PC_9D), sizeof(C_LoginExtended_PC_9D));
check_ak(cmd.access_key);
check_ak(cmd.access_key2);
}
break;
}
case GameVersion::GC:
case GameVersion::XB: {
const auto& header = check_size_t<PSOCommandHeaderDCV3>(
ev->data, sizeof(PSOCommandHeaderDCV3), 0xFFFF);
if (header.command == 0x03) {
check_ak(check_size_t<C_LegacyLogin_PC_V3_03>(cmd_data, cmd_size).access_key2);
} else if (header.command == 0x04) {
check_ak(check_size_t<C_LegacyLogin_PC_V3_04>(cmd_data, cmd_size).access_key);
} else if (header.command == 0x90) {
check_ak(check_size_t<C_LegacyLogin_V3_90>(cmd_data, cmd_size).access_key);
} else if (header.command == 0x9A) {
const auto& cmd = check_size_t<C_Login_DC_PC_V3_9A>(cmd_data, cmd_size);
check_ak(cmd.access_key);
check_ak(cmd.access_key2);
} else if (header.command == 0x9C) {
const auto& cmd = check_size_t<C_Register_DC_PC_V3_9C>(cmd_data, cmd_size);
check_ak(cmd.access_key);
check_pw(cmd.password);
} else if (header.command == 0x9E) {
if (version == GameVersion::GC) {
const auto& cmd = check_size_t<C_Login_GC_9E>(cmd_data, cmd_size,
sizeof(C_Login_GC_9E), sizeof(C_LoginExtended_GC_9E));
check_ak(cmd.access_key);
check_ak(cmd.access_key2);
} else { // XB
const auto& cmd = check_size_t<C_Login_XB_9E>(cmd_data, cmd_size,
sizeof(C_Login_XB_9E), sizeof(C_LoginExtended_XB_9E));
check_ak(cmd.access_key);
check_ak(cmd.access_key2);
}
} else if (header.command == 0xDB) {
const auto& cmd = check_size_t<C_VerifyLicense_V3_DB>(cmd_data, cmd_size);
check_ak(cmd.access_key);
check_ak(cmd.access_key2);
check_pw(cmd.password);
}
break;
}
case GameVersion::BB: {
const auto& header = check_size_t<PSOCommandHeaderBB>(
ev->data, sizeof(PSOCommandHeaderBB), 0xFFFF);
if (header.command == 0x04) {
check_pw(check_size_t<C_LegacyLogin_BB_04>(cmd_data, cmd_size).password);
} else if (header.command == 0x93) {
check_pw(check_size_t<C_Login_BB_93>(cmd_data, cmd_size).password);
} else if (header.command == 0x9C) {
check_pw(check_size_t<C_Register_BB_9C>(cmd_data, cmd_size).password);
} else if (header.command == 0x9E) {
check_pw(check_size_t<C_LoginExtended_BB_9E>(cmd_data, cmd_size).password);
} else if (header.command == 0xDB) {
check_pw(check_size_t<C_VerifyLicense_BB_DB>(cmd_data, cmd_size).password);
}
break;
}
default:
throw logic_error("invalid game version");
}
}
void ReplaySession::apply_default_mask(shared_ptr<Event> ev) {
auto version = this->clients.at(ev->client_id)->version;
@@ -157,8 +284,12 @@ void ReplaySession::apply_default_mask(shared_ptr<Event> ev) {
ReplaySession::ReplaySession(
shared_ptr<struct event_base> base,
FILE* input_log,
shared_ptr<ServerState> state)
shared_ptr<ServerState> state,
const string& required_access_key,
const string& required_password)
: state(state),
required_access_key(required_access_key),
required_password(required_password),
base(base),
commands_sent(0),
bytes_sent(0),
@@ -191,6 +322,13 @@ ReplaySession::ReplaySession(
} else {
if (parsing_command->type == Event::Type::RECEIVE) {
this->apply_default_mask(parsing_command);
} else if (parsing_command->type == Event::Type::SEND) {
try {
this->check_for_password(parsing_command);
} catch (...) {
print_data(stderr, parsing_command->data);
throw;
}
}
parsing_command = nullptr;
}