diff --git a/src/License.cc b/src/License.cc index 31eb6742..bb208d18 100644 --- a/src/License.cc +++ b/src/License.cc @@ -127,6 +127,14 @@ shared_ptr LicenseIndex::get(uint32_t serial_number) const { } } +shared_ptr LicenseIndex::get_by_bb_username(const string& bb_username) const { + try { + return this->bb_username_to_license.at(bb_username); + } catch (const out_of_range&) { + throw missing_license(); + } +} + vector> LicenseIndex::all() const { vector> ret; ret.reserve(this->serial_number_to_license.size()); diff --git a/src/License.hh b/src/License.hh index 0ad0436f..de6a4ad0 100644 --- a/src/License.hh +++ b/src/License.hh @@ -100,6 +100,7 @@ public: size_t count() const; std::shared_ptr get(uint32_t serial_number) const; + std::shared_ptr get_by_bb_username(const std::string& bb_username) const; std::vector> all() const; void add(std::shared_ptr l); diff --git a/src/ReceiveCommands.cc b/src/ReceiveCommands.cc index b15732f1..ce5b9608 100644 --- a/src/ReceiveCommands.cc +++ b/src/ReceiveCommands.cc @@ -5003,34 +5003,60 @@ static void on_04_P(shared_ptr c, uint16_t, uint32_t, string& data) { const auto& cmd = check_size_t(data); auto s = c->require_server_state(); - try { - auto l = s->license_index->verify_bb(cmd.username.decode(), cmd.password.decode()); - c->set_license(l); + string username = cmd.username.decode(); + string password = cmd.password.decode(); - } catch (const LicenseIndex::incorrect_password& e) { - send_message_box(c, string_printf("Login failed: %s", e.what())); - c->should_disconnect = true; - return; + // There are 3 cases here: + // - No login information at all: just proceed without checking license + // - Username only: check that license exists if allow_unregistered_users is off + // - Username and password: call verify_bb + if (!username.empty() && !password.empty()) { + try { + auto l = s->license_index->verify_bb(username, password); + c->set_license(l); - } catch (const LicenseIndex::missing_license& e) { - if (!s->allow_unregistered_users) { + } catch (const LicenseIndex::incorrect_password& e) { send_message_box(c, string_printf("Login failed: %s", e.what())); c->should_disconnect = true; return; - } else { - 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(); - s->license_index->add(l); - if (!s->is_replay) { - l->save(); + } catch (const LicenseIndex::missing_license& e) { + if (!s->allow_unregistered_users) { + send_message_box(c, string_printf("Login failed: %s", e.what())); + c->should_disconnect = true; + return; + } else { + + 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(); + s->license_index->add(l); + if (!s->is_replay) { + l->save(); + } + c->set_license(l); + string l_str = l->str(); + c->log.info("Created license %s", l_str.c_str()); } - c->set_license(l); - string l_str = l->str(); - c->log.info("Created license %s", l_str.c_str()); } + + } else if (!username.empty() && !s->allow_unregistered_users) { + try { + auto l = s->license_index->get_by_bb_username(username); + c->set_license(l); + } catch (const LicenseIndex::missing_license& e) { + send_message_box(c, string_printf("Login failed: %s", e.what())); + c->should_disconnect = true; + return; + } + + } else { + auto l = s->license_index->create_temporary_license(); + l->serial_number = random_object() & 0x7FFFFFFF; + l->bb_username = "__unknown__"; + l->bb_password = "__unknown__"; + c->set_license(l); } // On BB we can use colors and newlines should be \n; on PC we can't use