implement BB encryption in --cat-client

This commit is contained in:
Martin Michelsen
2022-09-02 17:29:19 -07:00
parent 01e4518c8e
commit 3a7c3c0fe9
3 changed files with 28 additions and 12 deletions
+14 -9
View File
@@ -36,7 +36,8 @@ using namespace std;
CatSession::CatSession( CatSession::CatSession(
shared_ptr<struct event_base> base, shared_ptr<struct event_base> base,
const struct sockaddr_storage& remote, const struct sockaddr_storage& remote,
GameVersion version) GameVersion version,
shared_ptr<const PSOBBEncryption::KeyFile> bb_key_file)
: Shell(base), : Shell(base),
log("[CatSession] ", proxy_server_log.min_level), log("[CatSession] ", proxy_server_log.min_level),
channel( channel(
@@ -44,7 +45,8 @@ CatSession::CatSession(
CatSession::dispatch_on_channel_input, CatSession::dispatch_on_channel_input,
CatSession::dispatch_on_channel_error, CatSession::dispatch_on_channel_error,
this, this,
"CatSession") { "CatSession"),
bb_key_file(bb_key_file) {
if (remote.ss_family != AF_INET) { if (remote.ss_family != AF_INET) {
throw runtime_error("remote is not AF_INET"); throw runtime_error("remote is not AF_INET");
} }
@@ -91,13 +93,16 @@ void CatSession::on_channel_input(
} }
} }
} else { // BB } else { // BB
// TODO: This can easily be done; I'm just lazy. We need to have the user if (command == 0x03 || command == 0x9B) {
// pass in a key name, then get that key file from this->state, then create if (!this->bb_key_file) {
// the crypts. throw runtime_error("BB encryption requires a key file");
// TODO: We really should just move encryption handling into the Channel }
// abstraction instead of the above, but this is a bit harder because then const auto& cmd = check_size_t<S_ServerInit_BB_03_9B>(data,
// Channels would have to know about BB key files. offsetof(S_ServerInit_DC_PC_V3_02_17_91_9B, after_message), 0xFFFF);
throw runtime_error("CatSession does not implement BB encryption yet"); this->channel.crypt_in.reset(new PSOBBEncryption(*this->bb_key_file, &cmd.server_key[0], sizeof(cmd.server_key)));
this->channel.crypt_out.reset(new PSOBBEncryption(*this->bb_key_file, &cmd.client_key[0], sizeof(cmd.client_key)));
this->log.info("Enabled BB encryption");
}
} }
string full_cmd = prepend_command_header( string full_cmd = prepend_command_header(
+3 -1
View File
@@ -23,12 +23,14 @@ public:
CatSession( CatSession(
std::shared_ptr<struct event_base> base, std::shared_ptr<struct event_base> base,
const struct sockaddr_storage& remote, const struct sockaddr_storage& remote,
GameVersion version); GameVersion version,
std::shared_ptr<const PSOBBEncryption::KeyFile> bb_key_file);
virtual ~CatSession() = default; virtual ~CatSession() = default;
protected: protected:
PrefixedLogger log; PrefixedLogger log;
Channel channel; Channel channel;
std::shared_ptr<const PSOBBEncryption::KeyFile> bb_key_file;
virtual void print_prompt(); virtual void print_prompt();
virtual void execute_command(const std::string& command); virtual void execute_command(const std::string& command);
+11 -2
View File
@@ -245,7 +245,8 @@ Specifically:\n\
commands to stdout, and forward any commands typed into stdin to the\n\ commands to stdout, and forward any commands typed into stdin to the\n\
remote server. It is assumed that the input and output are terminals, so\n\ remote server. It is assumed that the input and output are terminals, so\n\
all commands are hex-encoded. The --patch, --dc, --pc, --gc, and --bb\n\ all commands are hex-encoded. The --patch, --dc, --pc, --gc, and --bb\n\
options can be used to select the command format end encryption.\n\ options can be used to select the command format and encryption. If --bb\n\
is used, the --key option is also required (as in --decrypt-data above).\n\
--replay-log=FILENAME\n\ --replay-log=FILENAME\n\
This option makes newserv replay terminal log as if it were a client\n\ This option makes newserv replay terminal log as if it were a client\n\
session. This is used for regression testing, to make sure client\n\ session. This is used for regression testing, to make sure client\n\
@@ -438,8 +439,16 @@ int main(int argc, char** argv) {
} }
case Behavior::CAT_CLIENT: { case Behavior::CAT_CLIENT: {
shared_ptr<PSOBBEncryption::KeyFile> key;
if (cli_version == GameVersion::BB) {
if (key_file_name.empty()) {
throw runtime_error("a key filename is required for BB client emulation");
}
key.reset(new PSOBBEncryption::KeyFile(
load_object_file<PSOBBEncryption::KeyFile>("system/blueburst/keys/" + key_file_name + ".nsk")));
}
shared_ptr<struct event_base> base(event_base_new(), event_base_free); shared_ptr<struct event_base> base(event_base_new(), event_base_free);
CatSession session(base, cat_client_remote, cli_version); CatSession session(base, cat_client_remote, cli_version, key);
event_base_dispatch(base.get()); event_base_dispatch(base.get());
break; break;
} }