fix BB license check bug; clean up license commands
This commit is contained in:
+47
-31
@@ -85,55 +85,71 @@ void LicenseManager::set_autosave(bool autosave) {
|
||||
|
||||
shared_ptr<const License> LicenseManager::verify_pc(uint32_t serial_number,
|
||||
const string& access_key) const {
|
||||
auto& license = this->serial_number_to_license.at(serial_number);
|
||||
if (!license->access_key.eq_n(access_key, 8)) {
|
||||
throw invalid_argument("incorrect access key");
|
||||
}
|
||||
try {
|
||||
auto& license = this->serial_number_to_license.at(serial_number);
|
||||
if (!license->access_key.eq_n(access_key, 8)) {
|
||||
throw incorrect_access_key();
|
||||
}
|
||||
|
||||
if (license->ban_end_time && (license->ban_end_time >= now())) {
|
||||
throw invalid_argument("user is banned");
|
||||
if (license->ban_end_time && (license->ban_end_time >= now())) {
|
||||
throw invalid_argument("user is banned");
|
||||
}
|
||||
return license;
|
||||
} catch (const out_of_range&) {
|
||||
throw missing_license();
|
||||
}
|
||||
return license;
|
||||
}
|
||||
|
||||
shared_ptr<const License> LicenseManager::verify_gc(uint32_t serial_number,
|
||||
const string& access_key) const {
|
||||
auto& license = this->serial_number_to_license.at(serial_number);
|
||||
if (!license->access_key.eq_n(access_key, 12)) {
|
||||
throw invalid_argument("incorrect access key");
|
||||
try {
|
||||
auto& license = this->serial_number_to_license.at(serial_number);
|
||||
if (!license->access_key.eq_n(access_key, 12)) {
|
||||
throw incorrect_access_key();
|
||||
}
|
||||
if (license->ban_end_time && (license->ban_end_time >= now())) {
|
||||
throw invalid_argument("user is banned");
|
||||
}
|
||||
return license;
|
||||
} catch (const out_of_range&) {
|
||||
throw missing_license();
|
||||
}
|
||||
if (license->ban_end_time && (license->ban_end_time >= now())) {
|
||||
throw invalid_argument("user is banned");
|
||||
}
|
||||
return license;
|
||||
}
|
||||
|
||||
shared_ptr<const License> LicenseManager::verify_gc(uint32_t serial_number,
|
||||
const string& access_key, const string& password) const {
|
||||
auto& license = this->serial_number_to_license.at(serial_number);
|
||||
if (!license->access_key.eq_n(access_key, 12)) {
|
||||
throw invalid_argument("incorrect access key");
|
||||
try {
|
||||
auto& license = this->serial_number_to_license.at(serial_number);
|
||||
if (!license->access_key.eq_n(access_key, 12)) {
|
||||
throw incorrect_access_key();
|
||||
}
|
||||
if (license->gc_password != password) {
|
||||
throw incorrect_password();
|
||||
}
|
||||
if (license->ban_end_time && (license->ban_end_time >= now())) {
|
||||
throw invalid_argument("user is banned");
|
||||
}
|
||||
return license;
|
||||
} catch (const out_of_range&) {
|
||||
throw missing_license();
|
||||
}
|
||||
if (license->gc_password != password) {
|
||||
throw invalid_argument("incorrect password");
|
||||
}
|
||||
if (license->ban_end_time && (license->ban_end_time >= now())) {
|
||||
throw invalid_argument("user is banned");
|
||||
}
|
||||
return license;
|
||||
}
|
||||
|
||||
shared_ptr<const License> LicenseManager::verify_bb(const string& username,
|
||||
const string& password) const {
|
||||
auto& license = this->bb_username_to_license.at(username);
|
||||
if (license->bb_password != password) {
|
||||
throw invalid_argument("incorrect password");
|
||||
}
|
||||
try {
|
||||
auto& license = this->bb_username_to_license.at(username);
|
||||
if (license->bb_password != password) {
|
||||
throw incorrect_password();
|
||||
}
|
||||
|
||||
if (license->ban_end_time && (license->ban_end_time >= now())) {
|
||||
throw invalid_argument("user is banned");
|
||||
if (license->ban_end_time && (license->ban_end_time >= now())) {
|
||||
throw invalid_argument("user is banned");
|
||||
}
|
||||
return license;
|
||||
} catch (const out_of_range&) {
|
||||
throw missing_license();
|
||||
}
|
||||
return license;
|
||||
}
|
||||
|
||||
size_t LicenseManager::count() const {
|
||||
|
||||
@@ -44,6 +44,21 @@ struct License {
|
||||
std::string str() const;
|
||||
} __attribute__((packed));
|
||||
|
||||
class incorrect_password : public std::invalid_argument {
|
||||
public:
|
||||
incorrect_password() : invalid_argument("incorrect password") { }
|
||||
};
|
||||
|
||||
class incorrect_access_key : public std::invalid_argument {
|
||||
public:
|
||||
incorrect_access_key() : invalid_argument("incorrect access key") { }
|
||||
};
|
||||
|
||||
class missing_license : public std::invalid_argument {
|
||||
public:
|
||||
missing_license() : invalid_argument("missing license") { }
|
||||
};
|
||||
|
||||
class LicenseManager {
|
||||
public:
|
||||
LicenseManager();
|
||||
|
||||
+74
-24
@@ -160,16 +160,28 @@ void process_disconnect(shared_ptr<ServerState> s, shared_ptr<Client> c) {
|
||||
void process_verify_license_v3(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
||||
uint16_t, uint32_t, const string& data) { // DB
|
||||
const auto& cmd = check_size_t<C_VerifyLicense_V3_DB>(data);
|
||||
c->flags |= flags_for_version(c->version, cmd.sub_version);
|
||||
|
||||
uint32_t serial_number = stoul(cmd.serial_number, nullptr, 16);
|
||||
try {
|
||||
auto l = s->license_manager->verify_gc(serial_number, cmd.access_key,
|
||||
cmd.password);
|
||||
c->set_license(l);
|
||||
} catch (const exception& e) {
|
||||
send_command(c, 0x9A, 0x02);
|
||||
|
||||
} catch (const incorrect_access_key& e) {
|
||||
send_command(c, 0x9A, 0x03);
|
||||
c->should_disconnect = true;
|
||||
return;
|
||||
|
||||
} catch (const incorrect_password& e) {
|
||||
send_command(c, 0x9A, 0x07);
|
||||
c->should_disconnect = true;
|
||||
return;
|
||||
|
||||
} catch (const missing_license& e) {
|
||||
if (!s->allow_unregistered_users) {
|
||||
u16string message = u"Login failed: " + decode_sjis(e.what());
|
||||
send_message_box(c, message.c_str());
|
||||
send_command(c, 0x9A, 0x04);
|
||||
c->should_disconnect = true;
|
||||
return;
|
||||
} else {
|
||||
@@ -177,11 +189,9 @@ void process_verify_license_v3(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
||||
cmd.password, true);
|
||||
s->license_manager->add(l);
|
||||
c->set_license(l);
|
||||
send_command(c, 0x9A, 0x02);
|
||||
}
|
||||
}
|
||||
|
||||
c->flags |= flags_for_version(c->version, cmd.sub_version);
|
||||
send_command(c, 0x9A, 0x02);
|
||||
}
|
||||
|
||||
void process_login_a_dc_pc_v3(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
||||
@@ -207,28 +217,37 @@ void process_login_a_dc_pc_v3(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
||||
throw logic_error("unsupported versioned command");
|
||||
}
|
||||
c->set_license(l);
|
||||
send_command(c, 0x9A, 0x02);
|
||||
|
||||
} catch (const exception& e) {
|
||||
} catch (const incorrect_access_key& e) {
|
||||
send_command(c, 0x9A, 0x03);
|
||||
c->should_disconnect = true;
|
||||
return;
|
||||
|
||||
} catch (const incorrect_password& e) {
|
||||
send_command(c, 0x9A, 0x07);
|
||||
c->should_disconnect = true;
|
||||
return;
|
||||
|
||||
} catch (const missing_license& e) {
|
||||
// On V3, the client should have sent a different command containing the
|
||||
// password already, which should have created and added a temporary
|
||||
// license. So, if no license exists at this point, disconnect the client
|
||||
// even if unregistered clients are allowed.
|
||||
shared_ptr<License> l;
|
||||
if ((c->version == GameVersion::GC) || (c->version == GameVersion::XB)) {
|
||||
u16string message = u"Login failed: " + decode_sjis(e.what());
|
||||
send_message_box(c, message.c_str());
|
||||
send_command(c, 0x9A, 0x04);
|
||||
c->should_disconnect = true;
|
||||
return;
|
||||
} else if (c->version == GameVersion::PC) {
|
||||
l = LicenseManager::create_license_pc(serial_number, cmd.access_key, true);
|
||||
s->license_manager->add(l);
|
||||
c->set_license(l);
|
||||
send_command(c, 0x9A, 0x02);
|
||||
} else {
|
||||
throw runtime_error("unsupported game version");
|
||||
}
|
||||
s->license_manager->add(l);
|
||||
c->set_license(l);
|
||||
}
|
||||
|
||||
send_command(c, 0x9C, 0x01);
|
||||
}
|
||||
|
||||
void process_login_c_dc_pc_v3(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
||||
@@ -255,11 +274,16 @@ void process_login_c_dc_pc_v3(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
||||
throw logic_error("unsupported versioned command");
|
||||
}
|
||||
c->set_license(l);
|
||||
send_command(c, 0x9C, 0x01);
|
||||
|
||||
} catch (const exception& e) {
|
||||
} catch (const incorrect_password& e) {
|
||||
send_command(c, 0x9C, 0x00);
|
||||
c->should_disconnect = true;
|
||||
return;
|
||||
|
||||
} catch (const missing_license& e) {
|
||||
if (!s->allow_unregistered_users) {
|
||||
u16string message = u"Login failed: " + decode_sjis(e.what());
|
||||
send_message_box(c, message.c_str());
|
||||
send_command(c, 0x9C, 0x00);
|
||||
c->should_disconnect = true;
|
||||
return;
|
||||
} else {
|
||||
@@ -281,10 +305,9 @@ void process_login_c_dc_pc_v3(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
||||
}
|
||||
s->license_manager->add(l);
|
||||
c->set_license(l);
|
||||
send_command(c, 0x9C, 0x01);
|
||||
}
|
||||
}
|
||||
|
||||
send_command(c, 0x9C, 0x01);
|
||||
}
|
||||
|
||||
void process_login_d_e_pc_v3(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
||||
@@ -349,13 +372,33 @@ void process_login_d_e_pc_v3(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
||||
}
|
||||
c->set_license(l);
|
||||
|
||||
} catch (const exception& e) {
|
||||
// See comment in 9A handler about why we do this even if unregistered users
|
||||
// are allowed on the server
|
||||
u16string message = u"Login failed: " + decode_sjis(e.what());
|
||||
send_message_box(c, message.c_str());
|
||||
} catch (const incorrect_access_key& e) {
|
||||
send_command(c, 0x04, 0x03);
|
||||
c->should_disconnect = true;
|
||||
return;
|
||||
|
||||
} catch (const incorrect_password& e) {
|
||||
send_command(c, 0x04, 0x06);
|
||||
c->should_disconnect = true;
|
||||
return;
|
||||
|
||||
} catch (const missing_license& e) {
|
||||
// On V3, the client should have sent a different command containing the
|
||||
// password already, which should have created and added a temporary
|
||||
// license. So, if no license exists at this point, disconnect the client
|
||||
// even if unregistered clients are allowed.
|
||||
shared_ptr<License> l;
|
||||
if ((c->version == GameVersion::GC) || (c->version == GameVersion::XB)) {
|
||||
send_command(c, 0x04, 0x04);
|
||||
c->should_disconnect = true;
|
||||
return;
|
||||
} else if (c->version == GameVersion::PC) {
|
||||
l = LicenseManager::create_license_pc(serial_number, base_cmd->access_key, true);
|
||||
s->license_manager->add(l);
|
||||
c->set_license(l);
|
||||
} else {
|
||||
throw runtime_error("unsupported game version");
|
||||
}
|
||||
}
|
||||
|
||||
if ((c->flags & Client::Flag::EPISODE_3) && (s->ep3_menu_song >= 0)) {
|
||||
@@ -386,7 +429,14 @@ void process_login_bb(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
||||
try {
|
||||
auto l = s->license_manager->verify_bb(cmd.username, cmd.password);
|
||||
c->set_license(l);
|
||||
} catch (const exception& e) {
|
||||
|
||||
} catch (const incorrect_password& e) {
|
||||
u16string message = u"Login failed: " + decode_sjis(e.what());
|
||||
send_message_box(c, message.c_str());
|
||||
c->should_disconnect = true;
|
||||
return;
|
||||
|
||||
} catch (const missing_license& e) {
|
||||
if (!s->allow_unregistered_users) {
|
||||
u16string message = u"Login failed: " + decode_sjis(e.what());
|
||||
send_message_box(c, message.c_str());
|
||||
|
||||
+2
-1
@@ -383,7 +383,8 @@ void ServerState::create_menus(shared_ptr<const JSONObject> config_json) {
|
||||
this->main_menu.emplace_back(MainMenuItemID::DISCONNECT, u"Disconnect",
|
||||
u"Disconnect", 0);
|
||||
this->main_menu.emplace_back(MainMenuItemID::CLEAR_LICENSE, u"Clear license",
|
||||
u"Disconnect with an\ninvalid license error\nso you can enter a\ndifferent serial\nnumber, access key,\nor password", 0);
|
||||
u"Disconnect with an\ninvalid license error\nso you can enter a\ndifferent serial\nnumber, access key,\nor password",
|
||||
MenuItem::Flag::INVISIBLE_ON_BB);
|
||||
|
||||
try {
|
||||
this->welcome_message = decode_sjis(d.at("WelcomeMessage")->as_string());
|
||||
|
||||
@@ -29855,7 +29855,7 @@ I 80350 2022-07-07 23:27:02 - [Commands] Sending to C-7 (version=BB command=00E6
|
||||
0000000000000030 | FF FF FF FF FF FF FF FF 04 00 FF FF FF FF FF FF |
|
||||
0000000000000040 | 02 01 00 00 |
|
||||
I 80350 2022-07-07 23:27:02 - [Commands] Sending to C-7 (version=BB command=0007 flag=00000003)
|
||||
0000000000000000 | B8 00 07 00 03 00 00 00 11 00 00 11 FF FF FF FF |
|
||||
0000000000000000 | 8C 00 07 00 02 00 00 00 11 00 00 11 FF FF FF FF |
|
||||
0000000000000010 | 04 00 41 00 6C 00 65 00 78 00 61 00 6E 00 64 00 | A l e x a n d
|
||||
0000000000000020 | 72 00 69 00 61 00 00 00 00 00 00 00 00 00 00 00 | r i a
|
||||
0000000000000030 | 00 00 00 00 11 00 00 11 11 22 22 11 04 00 47 00 | "" G
|
||||
@@ -29863,10 +29863,7 @@ I 80350 2022-07-07 23:27:02 - [Commands] Sending to C-7 (version=BB command=0007
|
||||
0000000000000050 | 62 00 79 00 00 00 00 00 00 00 00 00 00 00 00 00 | b y
|
||||
0000000000000060 | 11 00 00 11 11 88 88 11 04 00 44 00 69 00 73 00 | D i s
|
||||
0000000000000070 | 63 00 6F 00 6E 00 6E 00 65 00 63 00 74 00 00 00 | c o n n e c t
|
||||
0000000000000080 | 00 00 00 00 00 00 00 00 00 00 00 00 11 00 00 11 |
|
||||
0000000000000090 | 11 99 99 11 04 00 43 00 6C 00 65 00 61 00 72 00 | C l e a r
|
||||
00000000000000A0 | 20 00 6C 00 69 00 63 00 65 00 6E 00 73 00 65 00 | l i c e n s e
|
||||
00000000000000B0 | 00 00 00 00 00 00 00 00 |
|
||||
0000000000000080 | 00 00 00 00 00 00 00 00 00 00 00 00 |
|
||||
I 80350 2022-07-07 23:27:03 - [Commands] Received from C-7 (version=BB command=0010 flag=00000000)
|
||||
0000000000000000 | 10 00 10 00 00 00 00 00 11 00 00 11 11 22 22 11 | ""
|
||||
I 80350 2022-07-07 23:27:03 - [Commands] Sending to C-7 (version=BB command=0019 flag=00000000)
|
||||
@@ -31210,7 +31207,7 @@ I 80350 2022-07-07 23:27:19 - [Commands] Sending to C-9 (version=BB command=00E6
|
||||
0000000000000030 | FF FF FF FF FF FF FF FF 04 00 FF FF FF FF FF FF |
|
||||
0000000000000040 | 02 01 00 00 |
|
||||
I 80350 2022-07-07 23:27:19 - [Commands] Sending to C-9 (version=BB command=0007 flag=00000003)
|
||||
0000000000000000 | B8 00 07 00 03 00 00 00 11 00 00 11 FF FF FF FF |
|
||||
0000000000000000 | 8C 00 07 00 02 00 00 00 11 00 00 11 FF FF FF FF |
|
||||
0000000000000010 | 04 00 41 00 6C 00 65 00 78 00 61 00 6E 00 64 00 | A l e x a n d
|
||||
0000000000000020 | 72 00 69 00 61 00 00 00 00 00 00 00 00 00 00 00 | r i a
|
||||
0000000000000030 | 00 00 00 00 11 00 00 11 11 22 22 11 04 00 47 00 | "" G
|
||||
@@ -31218,10 +31215,7 @@ I 80350 2022-07-07 23:27:19 - [Commands] Sending to C-9 (version=BB command=0007
|
||||
0000000000000050 | 62 00 79 00 00 00 00 00 00 00 00 00 00 00 00 00 | b y
|
||||
0000000000000060 | 11 00 00 11 11 88 88 11 04 00 44 00 69 00 73 00 | D i s
|
||||
0000000000000070 | 63 00 6F 00 6E 00 6E 00 65 00 63 00 74 00 00 00 | c o n n e c t
|
||||
0000000000000080 | 00 00 00 00 00 00 00 00 00 00 00 00 11 00 00 11 |
|
||||
0000000000000090 | 11 99 99 11 04 00 43 00 6C 00 65 00 61 00 72 00 | C l e a r
|
||||
00000000000000A0 | 20 00 6C 00 69 00 63 00 65 00 6E 00 73 00 65 00 | l i c e n s e
|
||||
00000000000000B0 | 00 00 00 00 00 00 00 00 |
|
||||
0000000000000080 | 00 00 00 00 00 00 00 00 00 00 00 00 |
|
||||
I 80350 2022-07-07 23:27:20 - [Commands] Received from C-9 (version=BB command=0010 flag=00000000)
|
||||
0000000000000000 | 10 00 10 00 00 00 00 00 11 00 00 11 11 22 22 11 | ""
|
||||
I 80350 2022-07-07 23:27:20 - [Commands] Sending to C-9 (version=BB command=0019 flag=00000000)
|
||||
@@ -33783,7 +33777,7 @@ I 80350 2022-07-07 23:29:17 - [Commands] Sending to C-B (version=BB command=00E6
|
||||
0000000000000030 | FF FF FF FF FF FF FF FF 04 00 FF FF FF FF FF FF |
|
||||
0000000000000040 | 02 01 00 00 |
|
||||
I 80350 2022-07-07 23:29:17 - [Commands] Sending to C-B (version=BB command=0007 flag=00000003)
|
||||
0000000000000000 | B8 00 07 00 03 00 00 00 11 00 00 11 FF FF FF FF |
|
||||
0000000000000000 | 8C 00 07 00 02 00 00 00 11 00 00 11 FF FF FF FF |
|
||||
0000000000000010 | 04 00 41 00 6C 00 65 00 78 00 61 00 6E 00 64 00 | A l e x a n d
|
||||
0000000000000020 | 72 00 69 00 61 00 00 00 00 00 00 00 00 00 00 00 | r i a
|
||||
0000000000000030 | 00 00 00 00 11 00 00 11 11 22 22 11 04 00 47 00 | "" G
|
||||
@@ -33791,10 +33785,7 @@ I 80350 2022-07-07 23:29:17 - [Commands] Sending to C-B (version=BB command=0007
|
||||
0000000000000050 | 62 00 79 00 00 00 00 00 00 00 00 00 00 00 00 00 | b y
|
||||
0000000000000060 | 11 00 00 11 11 88 88 11 04 00 44 00 69 00 73 00 | D i s
|
||||
0000000000000070 | 63 00 6F 00 6E 00 6E 00 65 00 63 00 74 00 00 00 | c o n n e c t
|
||||
0000000000000080 | 00 00 00 00 00 00 00 00 00 00 00 00 11 00 00 11 |
|
||||
0000000000000090 | 11 99 99 11 04 00 43 00 6C 00 65 00 61 00 72 00 | C l e a r
|
||||
00000000000000A0 | 20 00 6C 00 69 00 63 00 65 00 6E 00 73 00 65 00 | l i c e n s e
|
||||
00000000000000B0 | 00 00 00 00 00 00 00 00 |
|
||||
0000000000000080 | 00 00 00 00 00 00 00 00 00 00 00 00 |
|
||||
I 80350 2022-07-07 23:29:19 - [Commands] Received from C-B (version=BB command=0010 flag=00000000)
|
||||
0000000000000000 | 10 00 10 00 00 00 00 00 11 00 00 11 11 88 88 11 |
|
||||
I 80350 2022-07-07 23:29:19 - [Server] Client disconnected: C-B on fd 29
|
||||
|
||||
@@ -103,7 +103,7 @@ I 80820 2022-07-07 23:34:04 - [Commands] Received from C-2 (version=PC command=9
|
||||
00000000000000C0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
|
||||
00000000000000D0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
|
||||
I 80820 2022-07-07 23:34:04 - [Commands] Sending to C-2 (version=PC command=9C flag=01)
|
||||
0000000000000000 | 04 00 9C 01 |
|
||||
0000000000000000 | 04 00 9A 02 |
|
||||
I 80820 2022-07-07 23:34:04 - [Commands] Received from C-2 (version=PC command=9D flag=01)
|
||||
0000000000000000 | 50 01 9D 01 00 00 FF FF FF FF FF FF 00 00 FF FF | P
|
||||
0000000000000010 | FF FF FF FF 29 00 00 00 00 01 00 00 00 00 00 00 | )
|
||||
@@ -2105,7 +2105,7 @@ I 80820 2022-07-07 23:37:10 - [Commands] Received from C-4 (version=PC command=9
|
||||
00000000000000C0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
|
||||
00000000000000D0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
|
||||
I 80820 2022-07-07 23:37:10 - [Commands] Sending to C-4 (version=PC command=9C flag=01)
|
||||
0000000000000000 | 04 00 9C 01 |
|
||||
0000000000000000 | 04 00 9A 02 |
|
||||
I 80820 2022-07-07 23:37:10 - [Commands] Received from C-4 (version=PC command=9D flag=01)
|
||||
0000000000000000 | 50 01 9D 01 00 00 01 00 78 62 F8 10 00 00 FF FF | P xb
|
||||
0000000000000010 | FF FF FF FF 29 00 00 00 00 01 00 00 00 00 00 00 | )
|
||||
|
||||
Reference in New Issue
Block a user