fix login commands in tests
This commit is contained in:
@@ -41,6 +41,8 @@ string License::str() const {
|
||||
|
||||
|
||||
|
||||
LicenseManager::LicenseManager() : filename(""), autosave(false) { }
|
||||
|
||||
LicenseManager::LicenseManager(const string& filename)
|
||||
: filename(filename), autosave(true) {
|
||||
try {
|
||||
@@ -65,6 +67,9 @@ LicenseManager::LicenseManager(const string& filename)
|
||||
}
|
||||
|
||||
void LicenseManager::save() const {
|
||||
if (this->filename.empty()) {
|
||||
throw logic_error("license manager has no filename; cannot save");
|
||||
}
|
||||
auto f = fopen_unique(this->filename, "wb");
|
||||
for (const auto& it : this->serial_number_to_license) {
|
||||
if (it.second->privileges & Privilege::TEMPORARY) {
|
||||
|
||||
+2
-1
@@ -46,7 +46,8 @@ struct License {
|
||||
|
||||
class LicenseManager {
|
||||
public:
|
||||
LicenseManager(const std::string& filename);
|
||||
LicenseManager();
|
||||
explicit LicenseManager(const std::string& filename);
|
||||
~LicenseManager() = default;
|
||||
|
||||
void save() const;
|
||||
|
||||
+14
-3
@@ -288,6 +288,8 @@ int main(int argc, char** argv) {
|
||||
bool parse_data = false;
|
||||
bool byteswap_data = false;
|
||||
const char* replay_log_filename = nullptr;
|
||||
const char* replay_required_access_key = "";
|
||||
const char* replay_required_password = "";
|
||||
struct sockaddr_storage cat_client_remote;
|
||||
for (int x = 1; x < argc; x++) {
|
||||
if (!strcmp(argv[x], "--help")) {
|
||||
@@ -337,6 +339,10 @@ int main(int argc, char** argv) {
|
||||
} else if (!strncmp(argv[x], "--replay-log=", 13)) {
|
||||
behavior = Behavior::REPLAY_LOG;
|
||||
replay_log_filename = &argv[x][13];
|
||||
} else if (!strncmp(argv[x], "--require-password=", 19)) {
|
||||
replay_required_password = &argv[x][19];
|
||||
} else if (!strncmp(argv[x], "--require-access-key=", 21)) {
|
||||
replay_required_access_key = &argv[x][21];
|
||||
} else if (!strncmp(argv[x], "--config=", 9)) {
|
||||
config_filename = &argv[x][9];
|
||||
} else {
|
||||
@@ -461,8 +467,12 @@ int main(int argc, char** argv) {
|
||||
auto config_json = JSONObject::parse(load_file(config_filename));
|
||||
populate_state_from_config(state, config_json);
|
||||
|
||||
config_log.info("Loading license list");
|
||||
state->license_manager.reset(new LicenseManager("system/licenses.nsi"));
|
||||
if (!replay_log_filename) {
|
||||
config_log.info("Loading license list");
|
||||
state->license_manager.reset(new LicenseManager("system/licenses.nsi"));
|
||||
} else {
|
||||
state->license_manager.reset(new LicenseManager());
|
||||
}
|
||||
|
||||
config_log.info("Loading battle parameters");
|
||||
state->battle_params.reset(new BattleParamTable("system/blueburst/BattleParamEntry"));
|
||||
@@ -515,7 +525,8 @@ int main(int argc, char** argv) {
|
||||
state->game_server.reset(new Server(base, state));
|
||||
|
||||
auto f = fopen_unique(replay_log_filename, "rt");
|
||||
replay_session.reset(new ReplaySession(base, f.get(), state));
|
||||
replay_session.reset(new ReplaySession(
|
||||
base, f.get(), state, replay_required_access_key, replay_required_password));
|
||||
replay_session->start();
|
||||
|
||||
} else if (behavior == Behavior::RUN_SERVER) {
|
||||
|
||||
+139
-1
@@ -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;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,9 @@ public:
|
||||
ReplaySession(
|
||||
std::shared_ptr<struct event_base> base,
|
||||
FILE* input_log,
|
||||
std::shared_ptr<ServerState> state);
|
||||
std::shared_ptr<ServerState> state,
|
||||
const std::string& required_access_key = "",
|
||||
const std::string& required_password = "");
|
||||
ReplaySession(const ReplaySession&) = delete;
|
||||
ReplaySession(ReplaySession&&) = delete;
|
||||
ReplaySession& operator=(const ReplaySession&) = delete;
|
||||
@@ -59,6 +61,8 @@ private:
|
||||
};
|
||||
|
||||
std::shared_ptr<ServerState> state;
|
||||
std::string required_access_key;
|
||||
std::string required_password;
|
||||
|
||||
std::unordered_map<uint64_t, std::shared_ptr<Client>> clients;
|
||||
std::unordered_map<Channel*, std::shared_ptr<Client>> channel_to_client;
|
||||
@@ -79,6 +83,7 @@ private:
|
||||
void update_timeout_event();
|
||||
|
||||
void apply_default_mask(std::shared_ptr<Event> ev);
|
||||
void check_for_password(std::shared_ptr<const Event> ev) const;
|
||||
|
||||
static void dispatch_on_timeout(evutil_socket_t fd, short events, void* ctx);
|
||||
static void dispatch_on_command_received(
|
||||
|
||||
Reference in New Issue
Block a user