fixed query select bug

This commit is contained in:
WolverinDEV 2019-08-13 11:04:00 +02:00
parent 942ea44e90
commit bd43c53db2
2 changed files with 160 additions and 147 deletions

View File

@ -186,7 +186,7 @@ target_link_libraries(PermHelper
SET(CPACK_PACKAGE_VERSION_MAJOR "1") SET(CPACK_PACKAGE_VERSION_MAJOR "1")
SET(CPACK_PACKAGE_VERSION_MINOR "3") SET(CPACK_PACKAGE_VERSION_MINOR "3")
SET(CPACK_PACKAGE_VERSION_PATCH "22") SET(CPACK_PACKAGE_VERSION_PATCH "23")
if(BUILD_TYPE_NAME EQUAL OFF) if(BUILD_TYPE_NAME EQUAL OFF)
SET(CPACK_PACKAGE_VERSION_DATA "beta") SET(CPACK_PACKAGE_VERSION_DATA "beta")
elseif(BUILD_TYPE_NAME STREQUAL "") elseif(BUILD_TYPE_NAME STREQUAL "")

View File

@ -125,170 +125,182 @@ CommandResult QueryClient::handleCommandExit(Command &) {
return CommandResult::Success; return CommandResult::Success;
} }
struct QuerySqlData {
std::string username;
std::string password;
std::string uniqueId;
};
//login client_login_name=andreas client_login_password=meinPW //login client_login_name=andreas client_login_password=meinPW
CommandResult QueryClient::handleCommandLogin(Command& cmd) { CommandResult QueryClient::handleCommandLogin(Command& cmd) {
CMD_RESET_IDLE; CMD_RESET_IDLE;
std::string username, password; std::string username, password;
if(cmd[0].has("client_login_name") && cmd[0].has("client_login_password")){ if(cmd[0].has("client_login_name") && cmd[0].has("client_login_password")){
username = cmd["client_login_name"].string(); username = cmd["client_login_name"].string();
password = cmd["client_login_password"].string(); password = cmd["client_login_password"].string();
} else { } else {
username = cmd[0][0].key(); username = cmd[0][0].key();
password = cmd[0][1].key(); password = cmd[0][1].key();
} }
debugMessage("Attempted query login with " + username + " - " + password); 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; auto account = _account ? serverInstance->getQueryServer()->load_password(_account) : nullptr;
{ {
threads::MutexLock lock(this->handle->loginLock); threads::MutexLock lock(this->handle->loginLock);
if(!account) if(!account)
return {findError("client_invalid_password"), "username or password dose not match"}; return {findError("client_invalid_password"), "username or password dose not match"};
if (account->password != password) { if (account->password != password) {
if(!this->whitelisted) { if(!this->whitelisted) {
this->handle->loginAttempts[this->getPeerIp()]++; this->handle->loginAttempts[this->getPeerIp()]++;
if(this->handle->loginAttempts[this->getPeerIp()] > 3) { if(this->handle->loginAttempts[this->getPeerIp()] > 3) {
this->handle->queryBann[this->getPeerIp()] = system_clock::now() + seconds(serverInstance->properties()[property::SERVERINSTANCE_SERVERQUERY_BAN_TIME].as<uint64_t>()); //TODO configurable | Disconnect all others? this->handle->queryBann[this->getPeerIp()] = system_clock::now() + seconds(serverInstance->properties()[property::SERVERINSTANCE_SERVERQUERY_BAN_TIME].as<uint64_t>()); //TODO configurable | Disconnect all others?
this->postCommandHandler.emplace_back([&](){ this->postCommandHandler.emplace_back([&](){
this->closeConnection(system_clock::now() + seconds(1)); this->closeConnection(system_clock::now() + seconds(1));
}); });
return {findError("ban_flooding"), ""}; return {findError("ban_flooding"), ""};
} }
} }
return {findError("client_invalid_password"), "username or password dose not match"}; return {findError("client_invalid_password"), "username or password dose not match"};
} }
} }
if(!this->properties()[property::CLIENT_LOGIN_NAME].as<string>().empty()) { if(!this->properties()[property::CLIENT_LOGIN_NAME].as<string>().empty()) {
Command log("logout"); Command log("logout");
if(!this->handleCommandLogout(log)) return {ErrorType::VSError, "Failed to logout!"}; if(!this->handleCommandLogout(log)) return {ErrorType::VSError, "Failed to logout!"};
} }
this->query_account = account; this->query_account = account;
auto joined = this->currentChannel; auto joined_channel = this->currentChannel;
if(this->server) { if(this->server) {
{ {
unique_lock tree_lock(this->server->channel_tree_lock); unique_lock tree_lock(this->server->channel_tree_lock);
if(joined) if(joined_channel)
this->server->client_move(this->ref(), nullptr, nullptr, "", ViewReasonId::VREASON_USER_ACTION, false, tree_lock); 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->unregisterClient(_this.lock(), "login", tree_lock);
} }
this->server->groups->disableCache(_this.lock()); this->server->groups->disableCache(_this.lock());
} else serverInstance->getGroupManager()->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_LOGIN_NAME] = username;
this->properties()[property::CLIENT_UNIQUE_IDENTIFIER] = account->unique_id; //TODO load from table this->properties()[property::CLIENT_UNIQUE_IDENTIFIER] = account->unique_id; //TODO load from table
this->properties()[property::CLIENT_NICKNAME] = username; this->properties()[property::CLIENT_NICKNAME] = username;
auto target_server = this->server; /* keep the server alive 'ill we've joined the server */ auto target_server = this->server; /* keep the server alive 'ill we've joined the server */
if(account->bound_server) { if(account->bound_server) {
target_server = serverInstance->getVoiceServerManager()->findServerById(account->bound_server); target_server = serverInstance->getVoiceServerManager()->findServerById(account->bound_server);
if(!target_server) if(target_server != this->server)
return {findError("server_invalid_id"), "server does not exists anymore"}; joined_channel = nullptr;
} if(!target_server)
return {findError("server_invalid_id"), "server does not exists anymore"};
}
this->server = target_server; this->server = target_server;
DatabaseHelper::assignDatabaseId(this->sql, static_cast<ServerId>(target_server ? target_server->getServerId() : 0), _this.lock()); DatabaseHelper::assignDatabaseId(this->sql, static_cast<ServerId>(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::ClientProperties>{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();
}
if(target_server) { if(target_server) {
unique_lock tree_lock(target_server->channel_tree_lock); target_server->groups->enableCache(_this.lock());
if(joined) target_server->registerClient(_this.lock());
this->server->client_move(this->ref(), joined, nullptr, "", ViewReasonId::VREASON_USER_ACTION, false, tree_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::ClientProperties>{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); this->updateChannelClientProperties(true, true);
return CommandResult::Success; return CommandResult::Success;
} }
CommandResult QueryClient::handleCommandLogout(Command &) { CommandResult QueryClient::handleCommandLogout(Command &) {
CMD_RESET_IDLE; CMD_RESET_IDLE;
if(this->properties()[property::CLIENT_LOGIN_NAME].as<string>().empty()) return {findError("client_not_logged_in"), "not logged in"}; if(this->properties()[property::CLIENT_LOGIN_NAME].as<string>().empty()) return {findError("client_not_logged_in"), "not logged in"};
this->properties()[property::CLIENT_LOGIN_NAME] = ""; this->properties()[property::CLIENT_LOGIN_NAME] = "";
this->query_account = nullptr; this->query_account = nullptr;
auto joined = this->currentChannel; auto joined = this->currentChannel;
if(this->server){ if(this->server){
{ {
unique_lock tree_lock(this->server->channel_tree_lock); unique_lock tree_lock(this->server->channel_tree_lock);
if(joined) if(joined)
this->server->client_move(this->ref(), nullptr, nullptr, "", ViewReasonId::VREASON_USER_ACTION, false, tree_lock); 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->unregisterClient(_this.lock(), "logout", tree_lock);
} }
this->server->groups->disableCache(_this.lock()); this->server->groups->disableCache(_this.lock());
} else serverInstance->getGroupManager()->disableCache(_this.lock()); } else serverInstance->getGroupManager()->disableCache(_this.lock());
this->properties()[property::CLIENT_UNIQUE_IDENTIFIER] = "UnknownQuery"; //TODO load from table 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())); this->properties()[property::CLIENT_NICKNAME] = string() + "ServerQuery#" + this->getLoggingPeerIp() + "/" + to_string(ntohs(this->getPeerPort()));
DatabaseHelper::assignDatabaseId(this->sql, static_cast<ServerId>(this->server ? this->server->getServerId() : 0), _this.lock()); DatabaseHelper::assignDatabaseId(this->sql, static_cast<ServerId>(this->server ? this->server->getServerId() : 0), _this.lock());
if(this->server){ if(this->server){
this->server->groups->enableCache(_this.lock()); this->server->groups->enableCache(_this.lock());
this->server->registerClient(this->ref()); 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->reset();
this->channels->insert_channels(this->server->channelTree->tree_head(), true, false); this->channels->insert_channels(this->server->channelTree->tree_head(), true, false);
client_channel_lock.unlock(); this->subscribeChannel(this->server->channelTree->channels(), false, false);
server_channel_r_lock.unlock(); }
if(joined) {
unique_lock server_channel_w_lock(this->server->channel_tree_lock, defer_lock); if(joined) {
this->server->client_move(this->ref(), joined, nullptr, "", ViewReasonId::VREASON_USER_ACTION, false, server_channel_w_lock); 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 { } else if(!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_virtualserver_select_godmode, 1)) {
serverInstance->getGroupManager()->enableCache(_this.lock()); 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); this->updateChannelClientProperties(true, true);
return CommandResult::Success; return CommandResult::Success;
} }
CommandResult QueryClient::handleCommandServerSelect(Command &cmd) { CommandResult QueryClient::handleCommandServerSelect(Command &cmd) {
CMD_RESET_IDLE; CMD_RESET_IDLE;
shared_ptr<TSServer> target; shared_ptr<TSServer> target;
if(cmd[0].has("port")){ if(cmd[0].has("port")){
target = serverInstance->getVoiceServerManager()->findServerByPort(cmd["port"].as<uint16_t>()); target = serverInstance->getVoiceServerManager()->findServerByPort(cmd["port"].as<uint16_t>());
} else if(cmd[0].has("sid")) { } else if(cmd[0].has("sid")) {
target = serverInstance->getVoiceServerManager()->findServerById(cmd["sid"].as<ServerId>()); target = serverInstance->getVoiceServerManager()->findServerById(cmd["sid"].as<ServerId>());
} }
for(auto& parm : cmd[0].keys()) for(auto& parm : cmd[0].keys())
if(parm.find_first_not_of("0123456789") == string::npos) if(parm.find_first_not_of("0123456789") == string::npos)
target = serverInstance->getVoiceServerManager()->findServerById(static_cast<ServerId>(stol(parm))); target = serverInstance->getVoiceServerManager()->findServerById(static_cast<ServerId>(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(target) {
if(this->query_account && this->query_account->bound_server > 0) { 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()); server_locked->groups->disableCache(_this.lock());
this->channels->reset(); 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); //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 */ /* 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")) if(cmd[0].has("client_nickname"))
this->properties()[property::CLIENT_NICKNAME] = cmd["client_nickname"].string(); this->properties()[property::CLIENT_NICKNAME] = cmd["client_nickname"].string();
DatabaseHelper::assignDatabaseId(this->sql, static_cast<ServerId>(this->server ? this->server->getServerId() : 0), _this.lock()); DatabaseHelper::assignDatabaseId(this->sql, static_cast<ServerId>(this->server ? this->server->getServerId() : 0), _this.lock());
if(this->server) { if(this->server) {
this->server->groups->enableCache(_this.lock()); this->server->groups->enableCache(_this.lock());
this->server->registerClient(_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->subscribeToAll = true; this->channels->insert_channels(this->server->channelTree->tree_head(), true, false);
this->channels->insert_channels(this->server->channelTree->tree_head(), true, false); this->subscribeChannel(this->server->channelTree->channels(), false, false);
this->subscribeChannel(this->server->channelTree->channels(), false, true); }
}
auto negated_enforce_join = this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_virtualserver_select_godmode, 1); auto negated_enforce_join = this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_virtualserver_select_godmode, 1);
if(!negated_enforce_join) if(!negated_enforce_join)
this->server->assignDefaultChannel(this->ref(), true); this->server->assignDefaultChannel(this->ref(), true);
else else
this->update_cached_permissions(); this->update_cached_permissions();
} else { } else {
serverInstance->getGroupManager()->enableCache(_this.lock()); serverInstance->getGroupManager()->enableCache(_this.lock());
this->update_cached_permissions(); this->update_cached_permissions();
} }
this->updateChannelClientProperties(true, true); this->updateChannelClientProperties(true, true);
return CommandResult::Success; return CommandResult::Success;
} }
CommandResult QueryClient::handleCommandJoin(Command &) { CommandResult QueryClient::handleCommandJoin(Command &) {