diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 15f484d..55c7655 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -186,7 +186,7 @@ target_link_libraries(PermHelper SET(CPACK_PACKAGE_VERSION_MAJOR "1") SET(CPACK_PACKAGE_VERSION_MINOR "3") -SET(CPACK_PACKAGE_VERSION_PATCH "22") +SET(CPACK_PACKAGE_VERSION_PATCH "23") if(BUILD_TYPE_NAME EQUAL OFF) SET(CPACK_PACKAGE_VERSION_DATA "beta") elseif(BUILD_TYPE_NAME STREQUAL "") diff --git a/server/src/client/query/QueryClientCommands.cpp b/server/src/client/query/QueryClientCommands.cpp index 14019e4..7481b2e 100644 --- a/server/src/client/query/QueryClientCommands.cpp +++ b/server/src/client/query/QueryClientCommands.cpp @@ -125,170 +125,182 @@ CommandResult QueryClient::handleCommandExit(Command &) { return CommandResult::Success; } -struct QuerySqlData { - std::string username; - std::string password; - std::string uniqueId; -}; //login client_login_name=andreas client_login_password=meinPW CommandResult QueryClient::handleCommandLogin(Command& cmd) { - CMD_RESET_IDLE; + CMD_RESET_IDLE; - std::string username, password; - if(cmd[0].has("client_login_name") && cmd[0].has("client_login_password")){ - username = cmd["client_login_name"].string(); - password = cmd["client_login_password"].string(); - } else { - username = cmd[0][0].key(); - password = cmd[0][1].key(); - } - debugMessage("Attempted query login with " + username + " - " + password); + std::string username, password; + if(cmd[0].has("client_login_name") && cmd[0].has("client_login_password")){ + username = cmd["client_login_name"].string(); + password = cmd["client_login_password"].string(); + } else { + username = cmd[0][0].key(); + password = cmd[0][1].key(); + } + debugMessage("Attempted query login with " + username + " - " + password); - auto _account = serverInstance->getQueryServer()->find_query_account_by_name(username); + auto _account = serverInstance->getQueryServer()->find_query_account_by_name(username); auto account = _account ? serverInstance->getQueryServer()->load_password(_account) : nullptr; - { - threads::MutexLock lock(this->handle->loginLock); + { + threads::MutexLock lock(this->handle->loginLock); - if(!account) - return {findError("client_invalid_password"), "username or password dose not match"}; + if(!account) + return {findError("client_invalid_password"), "username or password dose not match"}; - if (account->password != password) { - if(!this->whitelisted) { - this->handle->loginAttempts[this->getPeerIp()]++; - if(this->handle->loginAttempts[this->getPeerIp()] > 3) { - this->handle->queryBann[this->getPeerIp()] = system_clock::now() + seconds(serverInstance->properties()[property::SERVERINSTANCE_SERVERQUERY_BAN_TIME].as()); //TODO configurable | Disconnect all others? - this->postCommandHandler.emplace_back([&](){ - this->closeConnection(system_clock::now() + seconds(1)); - }); - return {findError("ban_flooding"), ""}; - } - } - return {findError("client_invalid_password"), "username or password dose not match"}; - } - } + if (account->password != password) { + if(!this->whitelisted) { + this->handle->loginAttempts[this->getPeerIp()]++; + if(this->handle->loginAttempts[this->getPeerIp()] > 3) { + this->handle->queryBann[this->getPeerIp()] = system_clock::now() + seconds(serverInstance->properties()[property::SERVERINSTANCE_SERVERQUERY_BAN_TIME].as()); //TODO configurable | Disconnect all others? + this->postCommandHandler.emplace_back([&](){ + this->closeConnection(system_clock::now() + seconds(1)); + }); + return {findError("ban_flooding"), ""}; + } + } + return {findError("client_invalid_password"), "username or password dose not match"}; + } + } if(!this->properties()[property::CLIENT_LOGIN_NAME].as().empty()) { Command log("logout"); if(!this->handleCommandLogout(log)) return {ErrorType::VSError, "Failed to logout!"}; } - this->query_account = account; + this->query_account = account; - auto joined = this->currentChannel; - if(this->server) { - { - unique_lock tree_lock(this->server->channel_tree_lock); - if(joined) - this->server->client_move(this->ref(), nullptr, nullptr, "", ViewReasonId::VREASON_USER_ACTION, false, tree_lock); - this->server->unregisterClient(_this.lock(), "login", tree_lock); - } - this->server->groups->disableCache(_this.lock()); - } else serverInstance->getGroupManager()->disableCache(_this.lock()); + auto joined_channel = this->currentChannel; + if(this->server) { + { + unique_lock tree_lock(this->server->channel_tree_lock); + if(joined_channel) + this->server->client_move(this->ref(), nullptr, nullptr, "", ViewReasonId::VREASON_USER_ACTION, false, tree_lock); + this->server->unregisterClient(_this.lock(), "login", tree_lock); + } + this->server->groups->disableCache(_this.lock()); + } else serverInstance->getGroupManager()->disableCache(_this.lock()); - logMessage(LOG_QUERY, "Got new authenticated client. Username: {}, Unique-ID: {}, Bounded Server: {}", account->username, account->unique_id, account->bound_server); + logMessage(LOG_QUERY, "Got new authenticated client. Username: {}, Unique-ID: {}, Bounded Server: {}", account->username, account->unique_id, account->bound_server); - this->properties()[property::CLIENT_LOGIN_NAME] = username; - this->properties()[property::CLIENT_UNIQUE_IDENTIFIER] = account->unique_id; //TODO load from table - this->properties()[property::CLIENT_NICKNAME] = username; + this->properties()[property::CLIENT_LOGIN_NAME] = username; + this->properties()[property::CLIENT_UNIQUE_IDENTIFIER] = account->unique_id; //TODO load from table + this->properties()[property::CLIENT_NICKNAME] = username; - auto target_server = this->server; /* keep the server alive 'ill we've joined the server */ - if(account->bound_server) { - target_server = serverInstance->getVoiceServerManager()->findServerById(account->bound_server); - if(!target_server) - return {findError("server_invalid_id"), "server does not exists anymore"}; - } + auto target_server = this->server; /* keep the server alive 'ill we've joined the server */ + if(account->bound_server) { + target_server = serverInstance->getVoiceServerManager()->findServerById(account->bound_server); + if(target_server != this->server) + joined_channel = nullptr; + if(!target_server) + return {findError("server_invalid_id"), "server does not exists anymore"}; + } this->server = target_server; - DatabaseHelper::assignDatabaseId(this->sql, static_cast(target_server ? target_server->getServerId() : 0), _this.lock()); - if(target_server) { - target_server->groups->enableCache(_this.lock()); - target_server->registerClient(_this.lock()); - - shared_lock server_tree_lock(target_server->channel_tree_lock); - target_server->notifyClientPropertyUpdates(_this.lock(), deque{property::CLIENT_NICKNAME, property::CLIENT_UNIQUE_IDENTIFIER}); - - shared_lock client_tree_lock(this->channel_lock); - this->channels->reset(); - this->channels->insert_channels(target_server->channelTree->tree_head(), true, false); - } else { - serverInstance->getGroupManager()->enableCache(_this.lock()); - this->update_cached_permissions(); - } - + DatabaseHelper::assignDatabaseId(this->sql, static_cast(target_server ? target_server->getServerId() : 0), _this.lock()); if(target_server) { - unique_lock tree_lock(target_server->channel_tree_lock); - if(joined) - this->server->client_move(this->ref(), joined, nullptr, "", ViewReasonId::VREASON_USER_ACTION, false, tree_lock); + target_server->groups->enableCache(_this.lock()); + target_server->registerClient(_this.lock()); + + { + shared_lock server_tree_lock(target_server->channel_tree_lock); + if(joined_channel) /* needs only notify if we were already on that server within a channel */ + target_server->notifyClientPropertyUpdates(_this.lock(), deque{property::CLIENT_NICKNAME, property::CLIENT_UNIQUE_IDENTIFIER}); + + unique_lock client_tree_lock(this->channel_lock); + this->channels->reset(); + this->channels->insert_channels(target_server->channelTree->tree_head(), true, false); + this->subscribeChannel(this->server->channelTree->channels(), false, false); + } + + if(joined_channel) { + unique_lock tree_lock(this->server->channel_tree_lock); + if(joined_channel) + this->server->client_move(this->ref(), joined_channel, nullptr, "", ViewReasonId::VREASON_USER_ACTION, false, tree_lock); + } else if(!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_virtualserver_select_godmode, 1)) + this->server->assignDefaultChannel(this->ref(), true); + else + this->update_cached_permissions(); + } else { + serverInstance->getGroupManager()->enableCache(_this.lock()); + this->update_cached_permissions(); } - this->properties()[property::CLIENT_TOTALCONNECTIONS]++; + + this->properties()[property::CLIENT_TOTALCONNECTIONS]++; this->updateChannelClientProperties(true, true); - return CommandResult::Success; + return CommandResult::Success; } CommandResult QueryClient::handleCommandLogout(Command &) { - CMD_RESET_IDLE; - if(this->properties()[property::CLIENT_LOGIN_NAME].as().empty()) return {findError("client_not_logged_in"), "not logged in"}; - this->properties()[property::CLIENT_LOGIN_NAME] = ""; - this->query_account = nullptr; + CMD_RESET_IDLE; + if(this->properties()[property::CLIENT_LOGIN_NAME].as().empty()) return {findError("client_not_logged_in"), "not logged in"}; + this->properties()[property::CLIENT_LOGIN_NAME] = ""; + this->query_account = nullptr; - auto joined = this->currentChannel; - if(this->server){ - { - unique_lock tree_lock(this->server->channel_tree_lock); - if(joined) - this->server->client_move(this->ref(), nullptr, nullptr, "", ViewReasonId::VREASON_USER_ACTION, false, tree_lock); - this->server->unregisterClient(_this.lock(), "logout", tree_lock); - } - this->server->groups->disableCache(_this.lock()); - } else serverInstance->getGroupManager()->disableCache(_this.lock()); + auto joined = this->currentChannel; + if(this->server){ + { + unique_lock tree_lock(this->server->channel_tree_lock); + if(joined) + this->server->client_move(this->ref(), nullptr, nullptr, "", ViewReasonId::VREASON_USER_ACTION, false, tree_lock); + this->server->unregisterClient(_this.lock(), "logout", tree_lock); + } + this->server->groups->disableCache(_this.lock()); + } else serverInstance->getGroupManager()->disableCache(_this.lock()); - this->properties()[property::CLIENT_UNIQUE_IDENTIFIER] = "UnknownQuery"; //TODO load from table - this->properties()[property::CLIENT_NICKNAME] = string() + "ServerQuery#" + this->getLoggingPeerIp() + "/" + to_string(ntohs(this->getPeerPort())); - DatabaseHelper::assignDatabaseId(this->sql, static_cast(this->server ? this->server->getServerId() : 0), _this.lock()); + this->properties()[property::CLIENT_UNIQUE_IDENTIFIER] = "UnknownQuery"; //TODO load from table + this->properties()[property::CLIENT_NICKNAME] = string() + "ServerQuery#" + this->getLoggingPeerIp() + "/" + to_string(ntohs(this->getPeerPort())); + DatabaseHelper::assignDatabaseId(this->sql, static_cast(this->server ? this->server->getServerId() : 0), _this.lock()); - if(this->server){ - this->server->groups->enableCache(_this.lock()); - this->server->registerClient(this->ref()); + if(this->server){ + this->server->groups->enableCache(_this.lock()); + this->server->registerClient(this->ref()); - shared_lock server_channel_r_lock(this->server->channel_tree_lock); - unique_lock client_channel_lock(this->channel_lock); + { + shared_lock server_channel_r_lock(this->server->channel_tree_lock); + unique_lock client_channel_lock(this->channel_lock); - this->channels->reset(); - this->channels->insert_channels(this->server->channelTree->tree_head(), true, false); - client_channel_lock.unlock(); - server_channel_r_lock.unlock(); - if(joined) { - unique_lock server_channel_w_lock(this->server->channel_tree_lock, defer_lock); - this->server->client_move(this->ref(), joined, nullptr, "", ViewReasonId::VREASON_USER_ACTION, false, server_channel_w_lock); - } - } else { - serverInstance->getGroupManager()->enableCache(_this.lock()); - } + this->channels->reset(); + this->channels->insert_channels(this->server->channelTree->tree_head(), true, false); + this->subscribeChannel(this->server->channelTree->channels(), false, false); + } + + if(joined) { + unique_lock server_channel_w_lock(this->server->channel_tree_lock, defer_lock); + this->server->client_move(this->ref(), joined, nullptr, "", ViewReasonId::VREASON_USER_ACTION, false, server_channel_w_lock); + } else if(!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_virtualserver_select_godmode, 1)) { + this->server->assignDefaultChannel(this->ref(), true); + } else { + this->update_cached_permissions(); + } + } else { + serverInstance->getGroupManager()->enableCache(_this.lock()); + this->update_cached_permissions(); + } this->updateChannelClientProperties(true, true); - return CommandResult::Success; + return CommandResult::Success; } CommandResult QueryClient::handleCommandServerSelect(Command &cmd) { - CMD_RESET_IDLE; - shared_ptr target; + CMD_RESET_IDLE; + shared_ptr target; - if(cmd[0].has("port")){ - target = serverInstance->getVoiceServerManager()->findServerByPort(cmd["port"].as()); - } else if(cmd[0].has("sid")) { - target = serverInstance->getVoiceServerManager()->findServerById(cmd["sid"].as()); - } + if(cmd[0].has("port")){ + target = serverInstance->getVoiceServerManager()->findServerByPort(cmd["port"].as()); + } else if(cmd[0].has("sid")) { + target = serverInstance->getVoiceServerManager()->findServerById(cmd["sid"].as()); + } - for(auto& parm : cmd[0].keys()) - if(parm.find_first_not_of("0123456789") == string::npos) - target = serverInstance->getVoiceServerManager()->findServerById(static_cast(stol(parm))); + for(auto& parm : cmd[0].keys()) + if(parm.find_first_not_of("0123456789") == string::npos) + target = serverInstance->getVoiceServerManager()->findServerById(static_cast(stol(parm))); - if(!target && (!cmd[0].has("0") && (!cmd[0].has("sid") || !cmd["sid"] == 0))) return {findError("server_invalid_id"), "Invalid server id"}; + if(!target && (!cmd[0].has("0") && (!cmd[0].has("sid") || !cmd["sid"] == 0))) return {findError("server_invalid_id"), "Invalid server id"}; - if(target == this->server) return CommandResult::Success; + if(target == this->server) return CommandResult::Success; if(target) { if(this->query_account && this->query_account->bound_server > 0) { @@ -312,11 +324,12 @@ CommandResult QueryClient::handleCommandServerSelect(Command &cmd) { } server_locked->groups->disableCache(_this.lock()); this->channels->reset(); - } else serverInstance->getGroupManager()->disableCache(_this.lock()); + } else + serverInstance->getGroupManager()->disableCache(_this.lock()); } - this->resetEventMask(); + this->resetEventMask(); - //register at current server + //register at current server { //unique_lock server_lock(this->server_lock); /* We dont need to lock the server because only one command can be executed at the time. Everything else should copy the server once and test the copy and use that ref then */ @@ -326,32 +339,32 @@ CommandResult QueryClient::handleCommandServerSelect(Command &cmd) { if(cmd[0].has("client_nickname")) this->properties()[property::CLIENT_NICKNAME] = cmd["client_nickname"].string(); - DatabaseHelper::assignDatabaseId(this->sql, static_cast(this->server ? this->server->getServerId() : 0), _this.lock()); - if(this->server) { - this->server->groups->enableCache(_this.lock()); - this->server->registerClient(_this.lock()); + DatabaseHelper::assignDatabaseId(this->sql, static_cast(this->server ? this->server->getServerId() : 0), _this.lock()); + if(this->server) { + this->server->groups->enableCache(_this.lock()); + this->server->registerClient(_this.lock()); - { - shared_lock server_channel_lock(target->channel_tree_lock); + { + shared_lock server_channel_lock(target->channel_tree_lock); + unique_lock client_channel_lock(this->channel_lock); - unique_lock client_channel_lock(this->channel_lock); - this->subscribeToAll = true; - this->channels->insert_channels(this->server->channelTree->tree_head(), true, false); - this->subscribeChannel(this->server->channelTree->channels(), false, true); - } + this->subscribeToAll = true; + this->channels->insert_channels(this->server->channelTree->tree_head(), true, false); + this->subscribeChannel(this->server->channelTree->channels(), false, false); + } - auto negated_enforce_join = this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_virtualserver_select_godmode, 1); - if(!negated_enforce_join) - this->server->assignDefaultChannel(this->ref(), true); - else - this->update_cached_permissions(); - } else { - serverInstance->getGroupManager()->enableCache(_this.lock()); - this->update_cached_permissions(); - } + auto negated_enforce_join = this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_virtualserver_select_godmode, 1); + if(!negated_enforce_join) + this->server->assignDefaultChannel(this->ref(), true); + else + this->update_cached_permissions(); + } else { + serverInstance->getGroupManager()->enableCache(_this.lock()); + this->update_cached_permissions(); + } this->updateChannelClientProperties(true, true); - return CommandResult::Success; + return CommandResult::Success; } CommandResult QueryClient::handleCommandJoin(Command &) {