diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 53e31d3..2b522ec 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -243,7 +243,7 @@ target_link_libraries(PermMapHelper SET(CPACK_PACKAGE_VERSION_MAJOR "1") SET(CPACK_PACKAGE_VERSION_MINOR "4") -SET(CPACK_PACKAGE_VERSION_PATCH "13") +SET(CPACK_PACKAGE_VERSION_PATCH "14") if (BUILD_TYPE_NAME EQUAL OFF) SET(CPACK_PACKAGE_VERSION_DATA "beta") elseif (BUILD_TYPE_NAME STREQUAL "") diff --git a/server/src/Configuration.cpp b/server/src/Configuration.cpp index 0dfeb23..65b4d7f 100644 --- a/server/src/Configuration.cpp +++ b/server/src/Configuration.cpp @@ -63,6 +63,8 @@ bool config::server::clients::teaspeak; std::string config::server::clients::extra_welcome_message_teaspeak; config::server::clients::WelcomeMessageType config::server::clients::extra_welcome_message_type_teaspeak; +bool config::server::clients::ignore_max_clone_permissions; + uint16_t config::voice::default_voice_port; size_t config::voice::DefaultPuzzlePrecomputeSize; bool config::server::delete_missing_icon_permissions; @@ -1384,6 +1386,14 @@ std::deque> config::create_bindings() { ADD_DESCRIPTION(std::to_string(WelcomeMessageType::WELCOME_MESSAGE_TYPE_POKE) + " - Message, pokes the client with the message when he enters the server"); ADD_NOTE_RELOADABLE(); } + + { + CREATE_BINDING("ignore_max_clone_permissions", FLAG_RELOADABLE); + BIND_BOOL(config::server::clients::ignore_max_clone_permissions, false); + ADD_DESCRIPTION("Allows you to disable the permission checks for i_client_max_clones_uid, i_client_max_clones_ip and i_client_max_clones_hwid"); + ADD_SENSITIVE(); + ADD_NOTE_RELOADABLE(); + } } } { diff --git a/server/src/Configuration.h b/server/src/Configuration.h index 7cb7076..3340151 100644 --- a/server/src/Configuration.h +++ b/server/src/Configuration.h @@ -107,6 +107,8 @@ namespace ts::config { extern bool teaweb; extern std::string extra_welcome_message_teaweb; extern WelcomeMessageType extra_welcome_message_type_teaweb; + + extern bool ignore_max_clone_permissions; } extern ssize_t max_virtual_server; diff --git a/server/src/client/ConnectedClient.h b/server/src/client/ConnectedClient.h index 8602d30..3f25858 100644 --- a/server/src/client/ConnectedClient.h +++ b/server/src/client/ConnectedClient.h @@ -633,18 +633,20 @@ namespace ts { template struct ConnectedLockedClient { + ConnectedLockedClient() {} explicit ConnectedLockedClient(std::shared_ptr client) : client{std::move(client)} { if(this->client) this->connection_lock = this->client->require_connected_state(); } + explicit ConnectedLockedClient(ConnectedLockedClient&& client) : client{std::move(client.client)}, connection_lock{std::move(client.connection_lock)} { } - inline ConnectedLockedClient &operator=(const ConnectedLockedClient& other) { + inline ConnectedLockedClient &operator=(const ConnectedLockedClient& other) { this->client = other.client; if(other) this->connection_lock = std::shared_lock{*other.connection_lock.mutex()}; /* if the other is true (state locked & client) than we could easily acquire a shared lock */ } - inline ConnectedLockedClient &operator=(ConnectedLockedClient&& other) { + inline ConnectedLockedClient &operator=(ConnectedLockedClient&& other) { this->client = std::move(other.client); this->connection_lock = std::move(other.connection_lock); } diff --git a/server/src/client/SpeakingClient.cpp b/server/src/client/SpeakingClient.cpp index 0336504..32e81ab 100644 --- a/server/src/client/SpeakingClient.cpp +++ b/server/src/client/SpeakingClient.cpp @@ -532,37 +532,39 @@ command_result SpeakingClient::handleCommandClientInit(Command& cmd) { if(!this->server->verifyServerPassword(cmd["client_server_password"].string(), true)) return command_result{error::server_invalid_password}; - size_t clones_uid = 0; - size_t clones_ip = 0; - size_t clones_hwid = 0; + if(!config::server::clients::ignore_max_clone_permissions) { + size_t clones_uid = 0; + size_t clones_ip = 0; + size_t clones_hwid = 0; - auto _own_hwid = this->getHardwareId(); - this->server->forEachClient([&](const shared_ptr& client) { - if(client->getExternalType() != CLIENT_TEAMSPEAK) return; - if(client->getUid() == this->getUid()) - clones_uid++; - if(client->getPeerIp() == this->getPeerIp()) - clones_ip++; - if(!_own_hwid.empty() && client->getHardwareId() == _own_hwid) - clones_hwid++; - }); + auto _own_hwid = this->getHardwareId(); + this->server->forEachClient([&](const shared_ptr& client) { + if(client->getExternalType() != CLIENT_TEAMSPEAK) return; + if(client->getUid() == this->getUid()) + clones_uid++; + if(client->getPeerIp() == this->getPeerIp()) + clones_ip++; + if(!_own_hwid.empty() && client->getHardwareId() == _own_hwid) + clones_hwid++; + }); - if(clones_uid > 0 && permissions[permission::i_client_max_clones_uid].has_value && !permission::v2::permission_granted(clones_uid, permissions[permission::i_client_max_clones_uid])) { - logMessage(this->getServerId(), "{} Disconnecting because there are already {} uid clones connected. (Allowed: {})", CLIENT_STR_LOG_PREFIX, clones_uid, permissions[permission::i_client_max_clones_uid]); - return command_result{error:: client_too_many_clones_connected, "too many clones connected (uid)"}; + if(clones_uid > 0 && permissions[permission::i_client_max_clones_uid].has_value && !permission::v2::permission_granted(clones_uid, permissions[permission::i_client_max_clones_uid])) { + logMessage(this->getServerId(), "{} Disconnecting because there are already {} uid clones connected. (Allowed: {})", CLIENT_STR_LOG_PREFIX, clones_uid, permissions[permission::i_client_max_clones_uid]); + return command_result{error:: client_too_many_clones_connected, "too many clones connected (uid)"}; + } + + if(clones_ip > 0 && permissions[permission::i_client_max_clones_ip].has_value && !permission::v2::permission_granted(clones_ip, permissions[permission::i_client_max_clones_ip])) { + logMessage(this->getServerId(), "{} Disconnecting because there are already {} ip clones connected. (Allowed: {})", CLIENT_STR_LOG_PREFIX, clones_ip, permissions[permission::i_client_max_clones_ip]); + return command_result{error:: client_too_many_clones_connected, "too many clones connected (ip)"}; + } + + if(clones_hwid > 0 && permissions[permission::i_client_max_clones_hwid].has_value && !permission::v2::permission_granted(clones_hwid, permissions[permission::i_client_max_clones_hwid])) { + logMessage(this->getServerId(), "{} Disconnecting because there are already {} hwid clones connected. (Allowed: {})", CLIENT_STR_LOG_PREFIX, clones_hwid, permissions[permission::i_client_max_clones_hwid]); + return command_result{error:: client_too_many_clones_connected, "too many clones connected (hwid)"}; + } + TIMING_STEP(timings, "max clones "); } - if(clones_ip > 0 && permissions[permission::i_client_max_clones_ip].has_value && !permission::v2::permission_granted(clones_ip, permissions[permission::i_client_max_clones_ip])) { - logMessage(this->getServerId(), "{} Disconnecting because there are already {} ip clones connected. (Allowed: {})", CLIENT_STR_LOG_PREFIX, clones_ip, permissions[permission::i_client_max_clones_ip]); - return command_result{error:: client_too_many_clones_connected, "too many clones connected (ip)"}; - } - - if(clones_hwid > 0 && permissions[permission::i_client_max_clones_hwid].has_value && !permission::v2::permission_granted(clones_hwid, permissions[permission::i_client_max_clones_hwid])) { - logMessage(this->getServerId(), "{} Disconnecting because there are already {} hwid clones connected. (Allowed: {})", CLIENT_STR_LOG_PREFIX, clones_hwid, permissions[permission::i_client_max_clones_hwid]); - return command_result{error:: client_too_many_clones_connected, "too many clones connected (hwid)"}; - } - TIMING_STEP(timings, "max clones "); - auto banEntry = this->resolveActiveBan(this->getPeerIp()); if(banEntry) { logMessage(this->getServerId(), "{} Disconnecting while init because of ban record. Record id {} at server {}", diff --git a/server/src/client/command_handler/channel.cpp b/server/src/client/command_handler/channel.cpp index 8e050d3..0f5906e 100644 --- a/server/src/client/command_handler/channel.cpp +++ b/server/src/client/command_handler/channel.cpp @@ -420,12 +420,12 @@ command_result ConnectedClient::handleCommandChannelGroupAddPerm(Command &cmd) { PARSE_PERMISSION(cmd); auto val = cmd[index]["permvalue"].as(); - if(permission_require_granted_value(permType) && !permission::v2::permission_granted(val, max_value)) { + if(!ignore_granted_values && permission_require_granted_value(permType) && !permission::v2::permission_granted(val, max_value)) { if(conOnError) continue; return command_result{permission::i_permission_modify_power}; } - if(!ignore_granted_values && !permission::v2::permission_granted(1, this->calculate_permission(permType, 0, true))) { + if(!permission::v2::permission_granted(1, this->calculate_permission(permType, 0, true))) { if(conOnError) continue; return command_result{permission::i_permission_modify_power}; } @@ -475,8 +475,6 @@ command_result ConnectedClient::handleCommandChannelGroupDelPerm(Command &cmd) { if (!channelGroup || channelGroup->target() != GROUPTARGET_CHANNEL) return command_result{error::parameter_invalid, "invalid channel group id"}; ACTION_REQUIRES_GROUP_PERMISSION(channelGroup, permission::i_channel_group_needed_modify_power, permission::i_channel_group_modify_power, true); - auto ignore_granted_values = permission::v2::permission_granted(1, this->calculate_permission(permission::b_permission_modify_power_ignore, 0)); - bool updateList = false; bool conOnError = cmd[0].has("continueonerror"); @@ -484,7 +482,7 @@ command_result ConnectedClient::handleCommandChannelGroupDelPerm(Command &cmd) { for (int index = 0; index < cmd.bulkCount(); index++) { PARSE_PERMISSION(cmd) - if(!ignore_granted_values && !permission::v2::permission_granted(0, this->calculate_permission(permType, 0, true))) { + if(!permission::v2::permission_granted(0, this->calculate_permission(permType, 0, true))) { if(conOnError) continue; return command_result{permission::i_permission_modify_power}; } @@ -1494,12 +1492,12 @@ command_result ConnectedClient::handleCommandChannelAddPerm(Command &cmd) { PARSE_PERMISSION(cmd); auto val = cmd[index]["permvalue"].as(); - if(permission_require_granted_value(permType) && !permission::v2::permission_granted(val, max_value)) { + if(!ignore_granted_values && permission_require_granted_value(permType) && !permission::v2::permission_granted(val, max_value)) { if(conOnError) continue; return command_result{permission::i_permission_modify_power}; } - if(!ignore_granted_values && !permission::v2::permission_granted(1, this->calculate_permission(permType, channel_id, true))) { + if(!permission::v2::permission_granted(1, this->calculate_permission(permType, channel_id, true))) { if(conOnError) continue; return command_result{permission::i_permission_modify_power}; } @@ -1595,7 +1593,7 @@ command_result ConnectedClient::handleCommandChannelDelPerm(Command &cmd) { for (int index = 0; index < cmd.bulkCount(); index++) { PARSE_PERMISSION(cmd); - if(!ignore_granted_values && !permission::v2::permission_granted(0, this->calculate_permission(permType, channel_id, true))) { + if(!permission::v2::permission_granted(0, this->calculate_permission(permType, channel_id, true))) { if(conOnError) continue; return command_result{permission::i_permission_modify_power}; } @@ -1730,14 +1728,12 @@ command_result ConnectedClient::handleCommandChannelClientDelPerm(Command &cmd) ACTION_REQUIRES_PERMISSION(permission::i_client_permission_modify_power, required_permissions, channel_id); } - auto ignore_granted_values = permission::v2::permission_granted(1, this->calculate_permission(permission::b_permission_modify_power_ignore, channel_id)); - bool conOnError = cmd[0].has("continueonerror"), update_view = false; auto cll = this->server->findClientsByCldbId(cldbid); for (int index = 0; index < cmd.bulkCount(); index++) { PARSE_PERMISSION(cmd); - if(!ignore_granted_values && !permission::v2::permission_granted(0, this->calculate_permission(permType, channel_id, true))) { + if(!permission::v2::permission_granted(0, this->calculate_permission(permType, channel_id, true))) { if(conOnError) continue; return command_result{permission::i_permission_modify_power}; } @@ -1813,12 +1809,12 @@ command_result ConnectedClient::handleCommandChannelClientAddPerm(Command &cmd) PARSE_PERMISSION(cmd); auto val = cmd[index]["permvalue"].as(); - if(permission_require_granted_value(permType) && !permission::v2::permission_granted(val, max_value)) { + if(!ignore_granted_values && permission_require_granted_value(permType) && !permission::v2::permission_granted(val, max_value)) { if(conOnError) continue; return command_result{permission::i_permission_modify_power}; } - if(!ignore_granted_values && !permission::v2::permission_granted(1, this->calculate_permission(permType, channel_id, true))) { + if(!permission::v2::permission_granted(1, this->calculate_permission(permType, channel_id, true))) { if(conOnError) continue; return command_result{permission::i_permission_modify_power}; } diff --git a/server/src/client/command_handler/client.cpp b/server/src/client/command_handler/client.cpp index 14c0cc6..5b96225 100644 --- a/server/src/client/command_handler/client.cpp +++ b/server/src/client/command_handler/client.cpp @@ -1,5 +1,6 @@ #include +#include #include #include #include "../../build.h" @@ -61,26 +62,56 @@ command_result ConnectedClient::handleCommandClientKick(Command &cmd) { CMD_REQ_SERVER; CMD_CHK_AND_INC_FLOOD_POINTS(25); - ConnectedLockedClient client{this->server->find_client_by_id(cmd["clid"].as())}; - if (!client) return command_result{error::client_invalid_id}; - if (client->getType() == CLIENT_MUSIC) return command_result{error::client_invalid_type, "You cant kick a music bot!"}; - std::shared_ptr targetChannel = nullptr; - auto type = cmd["reasonid"].as(); - if (type == ViewReasonId::VREASON_CHANNEL_KICK) { - auto channel = client->getChannel(); - ACTION_REQUIRES_PERMISSION(permission::i_client_kick_from_channel_power, client->calculate_permission(permission::i_client_needed_kick_from_channel_power, client->getChannelId()), client->getChannelId()); - targetChannel = this->server->channelTree->getDefaultChannel(); - } else if (type == ViewReasonId::VREASON_SERVER_KICK) { - auto channel = client->getChannel(); - ACTION_REQUIRES_GLOBAL_PERMISSION(permission::i_client_kick_from_server_power, client->calculate_permission(permission::i_client_needed_kick_from_server_power, client->getChannelId())); - targetChannel = nullptr; - } else return command_result{error::not_implemented}; + std::vector> clients{}; + clients.reserve(cmd.bulkCount()); - if (targetChannel) { - this->server->notify_client_kick(client.client, this->ref(), cmd["reasonmsg"].as(), targetChannel); - } else { - this->server->notify_client_kick(client.client, this->ref(), cmd["reasonmsg"].as(), nullptr); - client->close_connection(system_clock::now() + seconds(1)); + auto type = cmd["reasonid"].as(); + auto single_client = cmd.bulkCount() == 1; + auto target_channel = type == ViewReasonId::VREASON_CHANNEL_KICK ? this->server->channelTree->getDefaultChannel() : nullptr; + auto kick_power = type == ViewReasonId::VREASON_CHANNEL_KICK ? + this->calculate_permission(permission::i_client_kick_from_channel_power, target_channel->channelId()) : + this->calculate_permission(permission::i_client_kick_from_server_power, 0); + + for(size_t index = 0; index < cmd.bulkCount(); index++) { + ConnectedLockedClient client{this->server->find_client_by_id(cmd[index]["clid"].as())}; + + if (!client) { + if(single_client) + return command_result{error::client_invalid_id}; + continue; + } + if (client->getType() == CLIENT_MUSIC) { + if(single_client) + return command_result{error::client_invalid_type}; + continue; + } + + if(type == ViewReasonId::VREASON_CHANNEL_KICK) { + if(!permission::v2::permission_granted(client->calculate_permission(permission::i_client_needed_kick_from_channel_power, client->getChannelId()), kick_power)) { + if(single_client) + return command_result{permission::i_client_needed_kick_from_channel_power}; + continue; + } + } else { + if(!permission::v2::permission_granted(client->calculate_permission(permission::i_client_needed_kick_from_server_power, client->getChannelId()), kick_power)) { + if(single_client) + return command_result{permission::i_client_needed_kick_from_server_power}; + continue; + } + } + + clients.emplace_back(std::move(client)); + } + if (clients.empty()) + return command_result{error::database_empty_result}; + + for(auto& client : clients) { + if (target_channel) { + this->server->notify_client_kick(client.client, this->ref(), cmd["reasonmsg"].as(), target_channel); + } else { + this->server->notify_client_kick(client.client, this->ref(), cmd["reasonmsg"].as(), nullptr); + client->close_connection(system_clock::now() + seconds(1)); + } } return command_result{error::ok}; @@ -130,16 +161,7 @@ command_result ConnectedClient::handleCommandClientMove(Command &cmd) { CMD_CHK_AND_INC_FLOOD_POINTS(10); shared_lock server_channel_r_lock(this->server->channel_tree_lock); - auto target_client_id = cmd["clid"].as(); - ConnectedLockedClient target_client{target_client_id == 0 ? this->ref() : this->server->find_client_by_id(target_client_id)}; - if(!target_client) { - return command_result{error::client_invalid_id, "Invalid target clid"}; - } - if(!target_client->getChannel()) { - if(target_client.client != this) - return command_result{error::client_invalid_id, "Invalid target clid"}; - } auto channel = this->server->channelTree->findChannel(cmd["cid"].as()); if (!channel) { return command_result{error::channel_invalid_id}; @@ -155,11 +177,43 @@ command_result ConnectedClient::handleCommandClientMove(Command &cmd) { auto permission_error = this->calculate_and_get_join_state(channel); if(permission_error != permission::unknown) return command_result{permission_error}; + std::vector> clients{}; + auto is_single_client = cmd.bulkCount() == 1; + + for(size_t index{0}; index < cmd.bulkCount(); index++) { + auto target_client_id = cmd[index]["clid"].as(); + ConnectedLockedClient target_client{target_client_id == 0 ? this->ref() : this->server->find_client_by_id(target_client_id)}; + if(!target_client) { + if(is_single_client) + return command_result{error::client_invalid_id}; + continue; + } + + if(!target_client->getChannel()) { + if(target_client.client != this) { + if(is_single_client) + return command_result{error::client_invalid_id}; + continue; + } + } + + if(target_client.client != this) { + if(!permission::v2::permission_granted(target_client->calculate_permission(permission::i_client_needed_move_power, 0), this->calculate_permission(permission::i_client_move_power, 0))) { + if(is_single_client) + return command_result{permission::i_client_move_power}; + continue; + } + } + clients.emplace_back(std::move(target_client)); + } + if(clients.empty()) + return command_result{error::database_empty_result}; + if (!channel->properties()[property::CHANNEL_FLAG_MAXCLIENTS_UNLIMITED].as() || !channel->properties()[property::CHANNEL_FLAG_MAXFAMILYCLIENTS_UNLIMITED].as()) { if(!permission::v2::permission_granted(1, this->calculate_permission(permission::b_channel_join_ignore_maxclients, channel->channelId()))) { if(!channel->properties()[property::CHANNEL_FLAG_MAXCLIENTS_UNLIMITED].as()) { auto maxClients = channel->properties()[property::CHANNEL_MAXCLIENTS].as(); - if (maxClients >= 0 && maxClients <= this->server->getClientsByChannel(channel).size()) + if (maxClients >= 0 && maxClients <= this->server->getClientsByChannel(channel).size() + clients.size()) return command_result{error::channel_maxclients_reached}; } if(!channel->properties()[property::CHANNEL_FLAG_MAXFAMILYCLIENTS_UNLIMITED].as()) { @@ -167,36 +221,43 @@ command_result ConnectedClient::handleCommandClientMove(Command &cmd) { if(channel->properties()[property::CHANNEL_FLAG_MAXFAMILYCLIENTS_INHERITED].as()) { family_root = channel; - while(family_root && family_root->properties()[property::CHANNEL_FLAG_MAXFAMILYCLIENTS_INHERITED].as()) family_root = family_root->parent(); + while(family_root && family_root->properties()[property::CHANNEL_FLAG_MAXFAMILYCLIENTS_INHERITED].as()) + family_root = family_root->parent(); } if(family_root && !family_root->properties()[property::CHANNEL_FLAG_MAXFAMILYCLIENTS_UNLIMITED]) { //Could not be CHANNEL_FLAG_MAXFAMILYCLIENTS_INHERITED auto maxClients = family_root->properties()[property::CHANNEL_MAXFAMILYCLIENTS].as(); - auto clients = 0; - for(const auto& entry : this->server->getClientsByChannelRoot(channel, false)) if(entry.get() != this) clients++; //Dont count the client itself - if (maxClients >= 0 && maxClients <= clients) + auto client_count = 0; + for(const auto& entry : this->server->getClientsByChannelRoot(channel, false)) + if(entry.get() != this) client_count++; //Dont count the client itself + + if (maxClients >= 0 && maxClients <= client_count + clients.size()) return command_result{error::channel_maxfamily_reached}; } } } } - if (target_client.client != this) - ACTION_REQUIRES_PERMISSION(permission::i_client_move_power, target_client->calculate_permission(permission::i_client_needed_move_power, target_client->getChannelId()), target_client->getChannelId()); - server_channel_r_lock.unlock(); unique_lock server_channel_w_lock(this->server->channel_tree_lock); - auto oldChannel = target_client->getChannel(); - this->server->client_move( - target_client.client, - channel, - target_client.client == this ? nullptr : _this.lock(), - "", - target_client.client == this ? ViewReasonId::VREASON_USER_ACTION : ViewReasonId::VREASON_MOVED, - true, - server_channel_w_lock - ); + std::vector> channels{}; + channels.reserve(clients.size()); - if(oldChannel) { + for(auto& client : clients) { + auto oldChannel = client->getChannel(); + this->server->client_move( + client.client, + channel, + client.client == this ? nullptr : _this.lock(), + "", + client.client == this ? ViewReasonId::VREASON_USER_ACTION : ViewReasonId::VREASON_MOVED, + true, + server_channel_w_lock + ); + if(std::find_if(channels.begin(), channels.end(), [&](const std::shared_ptr& channel) { return &*channel == &*oldChannel; }) == channels.end()) + channels.push_back(oldChannel); + } + + for(auto oldChannel : channels) { if(!server_channel_w_lock.owns_lock()) server_channel_w_lock.lock(); if(oldChannel->channelType() == ChannelType::temporary && oldChannel->properties()[property::CHANNEL_DELETE_DELAY].as() == 0) @@ -213,12 +274,41 @@ command_result ConnectedClient::handleCommandClientPoke(Command &cmd) { CMD_RESET_IDLE; CMD_CHK_AND_INC_FLOOD_POINTS(25); - ConnectedLockedClient client{ this->server->find_client_by_id(cmd["clid"].as())}; - if (!client) return command_result{error::client_invalid_id}; - if (client->getType() == CLIENT_MUSIC) return command_result{error::client_invalid_type}; - ACTION_REQUIRES_PERMISSION(permission::i_client_poke_power, client->calculate_permission(permission::i_client_needed_poke_power, client->getChannelId()), client->getChannelId()); + std::vector> clients{}; + clients.resize(cmd.bulkCount()); - client->notifyClientPoke(_this.lock(), cmd["msg"]); + bool is_single_poke = cmd.bulkCount() == 1; + for(size_t index{0}; index < cmd.bulkCount(); index++) { + ConnectedLockedClient client{ this->server->find_client_by_id(cmd["clid"].as())}; + if (!client) { + if(is_single_poke) + return command_result{error::client_invalid_id}; + continue; + } + if (client->getType() == CLIENT_MUSIC) { + if(is_single_poke) + return command_result{error::client_invalid_type}; + continue; + } + + auto own_permission = this->calculate_permission(permission::i_client_poke_power, client->getChannelId()); + if(!permission::v2::permission_granted(client->calculate_permission(permission::i_client_needed_poke_power, client->getChannelId()), own_permission)) { + if(is_single_poke) + return command_result{permission::i_client_poke_power}; + continue; + } + + clients.push_back(std::move(client)); + } + if(clients.empty()) + return command_result{error::database_empty_result}; + else if(clients.size() > 1) { + auto max_clients = this->calculate_permission(permission::i_client_poke_max_clients, 0); + if(!permission::v2::permission_granted(clients.size(), max_clients)) + return command_result{permission::i_client_poke_max_clients}; + } + for(auto& client : clients) + client->notifyClientPoke(_this.lock(), cmd["msg"]); return command_result{error::ok}; } @@ -884,12 +974,12 @@ command_result ConnectedClient::handleCommandClientAddPerm(Command &cmd) { PARSE_PERMISSION(cmd); auto val = cmd[index]["permvalue"].as(); - if(permission_require_granted_value(permType) && !permission::v2::permission_granted(val, max_value)) { + if(!ignore_granted_values && permission_require_granted_value(permType) && !permission::v2::permission_granted(val, max_value)) { if(conOnError) continue; return command_result{permission::i_permission_modify_power}; } - if(!ignore_granted_values && !permission::v2::permission_granted(1, this->calculate_permission(permType, 0, true))) { + if(!permission::v2::permission_granted(1, this->calculate_permission(permType, 0, true))) { if(conOnError) continue; return command_result{permission::i_permission_modify_power}; } @@ -926,14 +1016,13 @@ command_result ConnectedClient::handleCommandClientDelPerm(Command &cmd) { auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server, cldbid); ACTION_REQUIRES_GLOBAL_PERMISSION(permission::i_client_permission_modify_power, this->server->calculate_permission(permission::i_client_needed_permission_modify_power, cldbid, ClientType::CLIENT_TEAMSPEAK, 0)); - auto ignore_granted_values = permission::v2::permission_granted(1, this->calculate_permission(permission::b_permission_modify_power_ignore, 0)); bool conOnError = cmd[0].has("continueonerror"); auto onlineClients = this->server->findClientsByCldbId(cmd["cldbid"]); auto update_channel = false; for (int index = 0; index < cmd.bulkCount(); index++) { PARSE_PERMISSION(cmd) - if(!ignore_granted_values && !permission::v2::permission_granted(0, this->calculate_permission(permType, 0, true))) { + if(!permission::v2::permission_granted(0, this->calculate_permission(permType, 0, true))) { if(conOnError) continue; return command_result{permission::i_permission_modify_power}; } diff --git a/server/src/client/command_handler/server.cpp b/server/src/client/command_handler/server.cpp index 967ecba..20519dc 100644 --- a/server/src/client/command_handler/server.cpp +++ b/server/src/client/command_handler/server.cpp @@ -819,12 +819,12 @@ command_result ConnectedClient::handleCommandServerGroupAddPerm(Command &cmd) { //permvalue='1' permnegated='0' permskip='0' auto val = cmd[index]["permvalue"].as(); - if(permission_require_granted_value(permType) && !permission::v2::permission_granted(val, max_value)) { + if(!ignore_granted_values && permission_require_granted_value(permType) && !permission::v2::permission_granted(val, max_value)) { if(conOnError) continue; return command_result{permission::i_permission_modify_power}; } - if(!ignore_granted_values && !permission::v2::permission_granted(1, this->calculate_permission(permType, 0, true))) { + if(!permission::v2::permission_granted(1, this->calculate_permission(permType, 0, true))) { if(conOnError) continue; return command_result{permission::i_permission_modify_power}; } @@ -895,7 +895,7 @@ command_result ConnectedClient::handleCommandServerGroupDelPerm(Command &cmd) { for (int index = 0; index < cmd.bulkCount(); index++) { PARSE_PERMISSION(cmd); - if(!ignore_granted_values && !permission::v2::permission_granted(0, this->calculate_permission(permType, 0, true))) { + if(!permission::v2::permission_granted(0, this->calculate_permission(permType, 0, true))) { if(conOnError) continue; return command_result{permission::i_permission_modify_power}; } diff --git a/server/src/client/voice/VoiceClientConnection.h b/server/src/client/voice/VoiceClientConnection.h index 1135bbf..7607f1a 100644 --- a/server/src/client/voice/VoiceClientConnection.h +++ b/server/src/client/voice/VoiceClientConnection.h @@ -105,7 +105,7 @@ namespace ts { CompressionHandler compress_handler; AcknowledgeManager acknowledge_handler; - std::atomic_bool should_reassembled_reschedule; /* this get checked as soon the command handle lock has been released so trylock will succeed */ + std::atomic_bool should_reassembled_reschedule{}; /* this get checked as soon the command handle lock has been released so trylock will succeed */ //Handle stuff void execute_handle_command_packets(const std::chrono::system_clock::time_point& /* scheduled */); @@ -113,8 +113,8 @@ namespace ts { /* ---------- Write declarations ---------- */ - spin_lock write_queue_lock; /* queue access isn't for long in general */ - std::deque write_queue; + spin_lock write_queue_lock{}; /* queue access isn't for long in general */ + std::deque write_queue{}; struct WritePreprocessCategory { enum value { diff --git a/shared b/shared index 0b06a87..2725c57 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit 0b06a87fa4fb0d45221e073317afc0c503f4c14a +Subproject commit 2725c57f2e8c75a2bd8eae1ff477de3a33241cc9