don't save licenses for replay sessions

This commit is contained in:
Martin Michelsen
2023-12-07 20:27:46 -08:00
parent 6136f8dfb3
commit e901f5e681
6 changed files with 111 additions and 75 deletions
+68 -55
View File
@@ -53,17 +53,8 @@ JSON License::json() const {
});
}
void License::save() const {
auto json = this->json();
string json_data = json.serialize(JSON::SerializeOption::FORMAT | JSON::SerializeOption::HEX_INTEGERS);
string filename = string_printf("system/licenses/%010" PRIu32 ".json", this->serial_number);
save_file(filename, json_data);
}
void License::delete_file() const {
string filename = string_printf("system/licenses/%010" PRIu32 ".json", this->serial_number);
remove(filename.c_str());
}
void License::save() const {}
void License::delete_file() const {}
string License::str() const {
vector<string> tokens;
@@ -102,53 +93,22 @@ string License::str() const {
return "[License: " + join(tokens, ", ") + "]";
}
struct BinaryLicense {
pstring<TextEncoding::ASCII, 0x14> username; // BB username (max. 16 chars; should technically be Unicode)
pstring<TextEncoding::ASCII, 0x14> bb_password; // BB password (max. 16 chars)
uint32_t serial_number; // PC/GC serial number. MUST BE PRESENT FOR BB LICENSES TOO; this is also the player's guild card number.
pstring<TextEncoding::ASCII, 0x10> access_key; // PC/GC access key. (to log in using PC on a GC license, just enter the first 8 characters of the GC access key)
pstring<TextEncoding::ASCII, 0x0C> gc_password; // GC password
uint32_t privileges; // privilege level
uint64_t ban_end_time; // end time of ban (zero = not banned)
} __attribute__((packed));
DiskLicense::DiskLicense(const JSON& json) : License(json) {}
LicenseIndex::LicenseIndex() {
if (!isdir("system/licenses")) {
mkdir("system/licenses", 0755);
}
void DiskLicense::save() const {
auto json = this->json();
string json_data = json.serialize(JSON::SerializeOption::FORMAT | JSON::SerializeOption::HEX_INTEGERS);
string filename = string_printf("system/licenses/%010" PRIu32 ".json", this->serial_number);
save_file(filename, json_data);
}
// Convert binary licenses to JSON licenses and save them
if (isfile("system/licenses.nsi")) {
auto bin_licenses = load_vector_file<BinaryLicense>("system/licenses.nsi");
for (const auto& bin_license : bin_licenses) {
// Only add licenses from the binary file if there isn't a JSON version of
// the same license
try {
this->get(bin_license.serial_number);
} catch (const missing_license&) {
License license;
license.serial_number = bin_license.serial_number;
license.access_key = bin_license.access_key.decode();
license.gc_password = bin_license.gc_password.decode();
license.bb_username = bin_license.username.decode();
license.bb_password = bin_license.bb_password.decode();
license.flags = bin_license.privileges;
license.ban_end_time = bin_license.ban_end_time;
license.ep3_current_meseta = 0;
license.ep3_total_meseta_earned = 0;
license.save();
}
}
::remove("system/licenses.nsi");
}
void DiskLicense::delete_file() const {
string filename = string_printf("system/licenses/%010" PRIu32 ".json", this->serial_number);
remove(filename.c_str());
}
for (const auto& item : list_directory("system/licenses")) {
if (ends_with(item, ".json")) {
JSON json = JSON::parse(load_file("system/licenses/" + item));
auto license = make_shared<License>(json);
this->add(license);
}
}
shared_ptr<License> LicenseIndex::create_license() const {
return make_shared<License>();
}
size_t LicenseIndex::count() const {
@@ -288,3 +248,56 @@ shared_ptr<License> LicenseIndex::verify_bb(const string& username, const string
throw missing_license();
}
}
DiskLicenseIndex::DiskLicenseIndex() {
struct BinaryLicense {
pstring<TextEncoding::ASCII, 0x14> username; // BB username (max. 16 chars; should technically be Unicode)
pstring<TextEncoding::ASCII, 0x14> bb_password; // BB password (max. 16 chars)
uint32_t serial_number; // PC/GC serial number. MUST BE PRESENT FOR BB LICENSES TOO; this is also the player's guild card number.
pstring<TextEncoding::ASCII, 0x10> access_key; // PC/GC access key. (to log in using PC on a GC license, just enter the first 8 characters of the GC access key)
pstring<TextEncoding::ASCII, 0x0C> gc_password; // GC password
uint32_t privileges; // privilege level
uint64_t ban_end_time; // end time of ban (zero = not banned)
} __attribute__((packed));
if (!isdir("system/licenses")) {
mkdir("system/licenses", 0755);
}
// Convert binary licenses to JSON licenses and save them
if (isfile("system/licenses.nsi")) {
auto bin_licenses = load_vector_file<BinaryLicense>("system/licenses.nsi");
for (const auto& bin_license : bin_licenses) {
// Only add licenses from the binary file if there isn't a JSON version of
// the same license
try {
this->get(bin_license.serial_number);
} catch (const missing_license&) {
License license;
license.serial_number = bin_license.serial_number;
license.access_key = bin_license.access_key.decode();
license.gc_password = bin_license.gc_password.decode();
license.bb_username = bin_license.username.decode();
license.bb_password = bin_license.bb_password.decode();
license.flags = bin_license.privileges;
license.ban_end_time = bin_license.ban_end_time;
license.ep3_current_meseta = 0;
license.ep3_total_meseta_earned = 0;
license.save();
}
}
::remove("system/licenses.nsi");
}
for (const auto& item : list_directory("system/licenses")) {
if (ends_with(item, ".json")) {
JSON json = JSON::parse(load_file("system/licenses/" + item));
auto license = make_shared<DiskLicense>(json);
this->add(license);
}
}
}
shared_ptr<License> DiskLicenseIndex::create_license() const {
return make_shared<DiskLicense>();
}
+27 -5
View File
@@ -10,7 +10,8 @@
class LicenseIndex;
struct License {
class License {
public:
enum Flag : uint32_t {
// clang-format off
KICK_USER = 0x00000001,
@@ -53,14 +54,25 @@ struct License {
License() = default;
explicit License(const JSON& json);
virtual ~License() = default;
JSON json() const;
void save() const;
void delete_file() const;
virtual void save() const;
virtual void delete_file() const;
std::string str() const;
};
class DiskLicense : public License {
public:
DiskLicense() = default;
explicit DiskLicense(const JSON& json);
virtual ~DiskLicense() = default;
virtual void save() const;
virtual void delete_file() const;
};
class LicenseIndex {
public:
class no_username : public std::invalid_argument {
@@ -80,8 +92,10 @@ public:
missing_license() : invalid_argument("missing license") {}
};
LicenseIndex();
~LicenseIndex() = default;
LicenseIndex() = default;
virtual ~LicenseIndex() = default;
virtual std::shared_ptr<License> create_license() const;
size_t count() const;
std::shared_ptr<License> get(uint32_t serial_number) const;
@@ -101,3 +115,11 @@ protected:
std::unordered_map<std::string, std::shared_ptr<License>> xb_gamertag_to_license;
std::unordered_map<uint32_t, std::shared_ptr<License>> serial_number_to_license;
};
class DiskLicenseIndex : public LicenseIndex {
public:
DiskLicenseIndex();
virtual ~DiskLicenseIndex() = default;
virtual std::shared_ptr<License> create_license() const;
};
+1 -1
View File
@@ -377,7 +377,7 @@ void ProxyServer::UnlinkedSession::on_input(Channel& ch, uint16_t command, uint3
if (!s->allow_unregistered_users) {
throw;
}
auto l = make_shared<License>();
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();
+11 -11
View File
@@ -412,7 +412,7 @@ static void on_DB_V3(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
c->should_disconnect = true;
return;
} else {
auto l = make_shared<License>();
auto l = s->license_index->create_license();
l->serial_number = serial_number;
l->access_key = cmd.access_key.decode();
l->gc_password = cmd.password.decode();
@@ -456,7 +456,7 @@ static void on_88_DCNTE(shared_ptr<Client> c, uint16_t, uint32_t, string& data)
send_message_box(c, "Incorrect serial number");
c->should_disconnect = true;
} else {
auto l = make_shared<License>();
auto l = s->license_index->create_license();
l->serial_number = serial_number;
l->access_key = cmd.access_key.decode();
s->license_index->add(l);
@@ -499,7 +499,7 @@ static void on_8B_DCNTE(shared_ptr<Client> c, uint16_t, uint32_t, string& data)
send_message_box(c, "Incorrect serial number");
c->should_disconnect = true;
} else {
auto l = make_shared<License>();
auto l = s->license_index->create_license();
l->serial_number = serial_number;
l->access_key = cmd.access_key.decode();
s->license_index->add(l);
@@ -553,7 +553,7 @@ static void on_90_DC(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
send_command(c, 0x90, 0x03);
c->should_disconnect = true;
} else {
auto l = make_shared<License>();
auto l = s->license_index->create_license();
l->serial_number = serial_number;
l->access_key = cmd.access_key.decode();
s->license_index->add(l);
@@ -610,7 +610,7 @@ static void on_93_DC(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
c->should_disconnect = true;
return;
} else {
auto l = make_shared<License>();
auto l = s->license_index->create_license();
l->serial_number = serial_number;
l->access_key = cmd.access_key.decode();
s->license_index->add(l);
@@ -699,7 +699,7 @@ static void on_9A(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
c->should_disconnect = true;
return;
} else if (is_v1_or_v2(c->version())) {
auto l = make_shared<License>();
auto l = s->license_index->create_license();
l->serial_number = serial_number;
l->access_key = cmd.access_key.decode();
s->license_index->add(l);
@@ -759,7 +759,7 @@ static void on_9C(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
c->should_disconnect = true;
return;
} else {
auto l = make_shared<License>();
auto l = s->license_index->create_license();
l->serial_number = serial_number;
l->access_key = cmd.access_key.decode();
if (is_gc(c->version())) {
@@ -878,7 +878,7 @@ static void on_9D_9E(shared_ptr<Client> c, uint16_t command, uint32_t, string& d
c->should_disconnect = true;
return;
} else if (is_v1_or_v2(c->version())) {
auto l = make_shared<License>();
auto l = s->license_index->create_license();
l->serial_number = serial_number;
l->access_key = base_cmd->access_key.decode();
s->license_index->add(l);
@@ -947,7 +947,7 @@ static void on_9E_XB(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
return;
} catch (const LicenseIndex::missing_license& e) {
auto l = make_shared<License>();
auto l = s->license_index->create_license();
l->serial_number = fnv1a32(xb_gamertag) & 0x7FFFFFFF;
l->xb_gamertag = xb_gamertag;
l->xb_user_id = xb_user_id;
@@ -1004,7 +1004,7 @@ static void on_93_BB(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
c->should_disconnect = true;
return;
} else {
auto l = make_shared<License>();
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();
@@ -4893,7 +4893,7 @@ static void on_04_P(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
return;
} else {
auto l = make_shared<License>();
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();
+3 -2
View File
@@ -321,7 +321,7 @@ Proxy session commands:\n\
}
} else if (command_name == "add-license") {
auto l = make_shared<License>();
auto l = this->state->license_index->create_license();
for (const string& token : split(command_args, ' ')) {
if (starts_with(token, "bb-username=")) {
@@ -376,7 +376,8 @@ Proxy session commands:\n\
uint32_t serial_number = stoul(tokens[0]);
tokens.erase(tokens.begin());
auto orig_l = this->state->license_index->get(serial_number);
auto l = make_shared<License>(*orig_l);
auto l = this->state->license_index->create_license();
*l = *orig_l;
this->state->license_index->remove(orig_l->serial_number);
try {
+1 -1
View File
@@ -973,7 +973,7 @@ void ServerState::load_bb_private_keys() {
void ServerState::load_licenses() {
config_log.info("Indexing licenses");
this->license_index = make_shared<LicenseIndex>();
this->license_index = this->is_replay ? make_shared<LicenseIndex>() : make_shared<DiskLicenseIndex>();
}
void ServerState::load_teams() {