From ca00f690fd2042cbe10f71832face09060e490c4 Mon Sep 17 00:00:00 2001 From: WolverinDEV Date: Sat, 9 Nov 2019 18:53:53 +0100 Subject: [PATCH] Fixed a permission bug --- git-teaspeak | 2 +- server/main.cpp | 2 +- server/src/TSServer.cpp | 6 +++ server/src/TSServer.h | 3 ++ .../client/ConnectedClientCommandHandler.cpp | 47 ++++++++++++------- .../client/voice/VoiceClientConnection.cpp | 1 + server/src/server/VoiceServer.cpp | 10 +++- 7 files changed, 49 insertions(+), 22 deletions(-) diff --git a/git-teaspeak b/git-teaspeak index f8b2685..6fa2641 160000 --- a/git-teaspeak +++ b/git-teaspeak @@ -1 +1 @@ -Subproject commit f8b26854fc9eb8fed8ccb30ddcf2379cefaac96c +Subproject commit 6fa26411e7f38d5697269262bab68c307bd159b1 diff --git a/server/main.cpp b/server/main.cpp index 5ecf9dc..bda1114 100644 --- a/server/main.cpp +++ b/server/main.cpp @@ -308,7 +308,7 @@ int main(int argc, char** argv) { logMessage(LOG_GENERAL, "Starting music providers"); terminal::instance()->setPrompt("§aStarting server. §7[§aloading music§7]"); - if(ts::config::music::enabled && !arguments.cmdOptionExists("--valgrind")) { + if(ts::config::music::enabled && !arguments.cmdOptionExists("--no-providers")) { ::music::manager::loadProviders("providers"); ::music::manager::register_provider(::music::provider::ChannelProvider::create_provider()); } diff --git a/server/src/TSServer.cpp b/server/src/TSServer.cpp index 664224c..d8aa491 100644 --- a/server/src/TSServer.cpp +++ b/server/src/TSServer.cpp @@ -1016,6 +1016,12 @@ deque> TSS return result; } +permission::v2::PermissionFlaggedValue TSServer::calculatePermission2(ts::permission::PermissionType permission, ts::ClientDbId cldbid, ts::server::ClientType type, ts::ChannelId channel, std::shared_ptr cache) { + auto result = this->calculatePermissions2(cldbid, {permission}, type, channel, false, cache); + if(result.empty()) return {permNotGranted, false}; + return result.front().second; +} + ts::permission::PermissionValue TSServer::calculatePermission(permission::PermissionTestType test, ClientDbId cldbid, permission::PermissionType permission, ClientType client_type, const std::shared_ptr& channel, std::shared_ptr cache) { auto result = this->calculatePermissions(test, cldbid, {permission}, client_type, channel, cache); if(result.empty()) return permNotGranted; diff --git a/server/src/TSServer.h b/server/src/TSServer.h index 14da4ca..5b99a6c 100644 --- a/server/src/TSServer.h +++ b/server/src/TSServer.h @@ -225,6 +225,9 @@ namespace ts { std::shared_ptr cache = nullptr /* calculate cache */); permission::PermissionValue calculatePermission(permission::PermissionTestType, ClientDbId, permission::PermissionType, ClientType type, const std::shared_ptr& channel, std::shared_ptr cache = nullptr); + + permission::v2::PermissionFlaggedValue calculatePermission2(permission::PermissionType, ClientDbId, ClientType type, ChannelId channel, std::shared_ptr cache = nullptr); + permission::PermissionValue calculatePermissionGrant(permission::PermissionTestType, ClientDbId, permission::PermissionType, ClientType type, const std::shared_ptr& channel); bool verifyServerPassword(std::string, bool hashed = false); diff --git a/server/src/client/ConnectedClientCommandHandler.cpp b/server/src/client/ConnectedClientCommandHandler.cpp index 1d2ba81..b6880f0 100644 --- a/server/src/client/ConnectedClientCommandHandler.cpp +++ b/server/src/client/ConnectedClientCommandHandler.cpp @@ -3426,46 +3426,57 @@ CommandResult ConnectedClient::handleCommandSetClientChannelGroup(Command &cmd) CMD_CHK_AND_INC_FLOOD_POINTS(25); auto serverGroup = this->server->groups->findGroup(cmd["cgid"].as()); - if (!serverGroup && cmd["gcid"].as() == 0) + if (!serverGroup && cmd["cgid"].as() == 0) serverGroup = this->server->groups->defaultGroup(GroupTarget::GROUPTARGET_CHANNEL); if (!serverGroup || serverGroup->target() != GROUPTARGET_CHANNEL) return {findError("parameter_invalid"), "invalid channel group id"}; shared_lock server_channel_lock(this->server->channel_tree_lock); /* ensure we dont get moved or somebody could move us */ - std::shared_ptr channel = this->server->channelTree->findChannel(cmd["cid"].as()); + auto channel_id = cmd["cid"].as(); + auto channel = this->server->channelTree->findChannel(channel_id); if (!channel) return {findError("channel_invalid_id"), "Cant resolve channel"}; auto target_cldbid = cmd["cldbid"].as(); { - - if(!serverGroup->permission_granted(permission::i_channel_group_member_add_power, this->calculate_permission_value(permission::i_channel_group_member_add_power, -1), true)) { + auto channel_group_member_add_power = this->calculate_permission_value(permission::i_channel_group_member_add_power, channel_id); + if(!serverGroup->permission_granted(permission::i_channel_group_needed_member_add_power, channel_group_member_add_power, true)) { if(target_cldbid != this->getClientDatabaseId()) return CommandResultPermissionError{permission::i_channel_group_member_add_power}; - if(!serverGroup->permission_granted(permission::i_channel_group_member_add_power, this->calculate_permission_value(permission::i_channel_group_self_add_power, -1), true)) + + auto channel_group_self_add_power = this->calculate_permission_value(permission::i_channel_group_self_add_power, channel_id); + if(!serverGroup->permission_granted(permission::i_channel_group_needed_member_add_power, channel_group_self_add_power, true)) return CommandResultPermissionError{permission::i_channel_group_self_add_power}; } - auto needed_client_permission = this->server->calculatePermission(permission::PERMTEST_ORDERED, target_cldbid, permission::i_client_needed_permission_modify_power, ClientType::CLIENT_TEAMSPEAK,nullptr); - if(needed_client_permission != permNotGranted) { - if(!this->permission_granted(this->permissionValue(permission::i_client_permission_modify_power), needed_client_permission)) - return CommandResultPermissionError{permission::i_client_needed_permission_modify_power}; - } + auto client_permission_modify_power = this->calculate_permission_value(permission::i_client_permission_modify_power, channel_id); + auto client_needed_permission_modify_power = this->server->calculatePermission2( + permission::i_client_needed_permission_modify_power, target_cldbid, ClientType::CLIENT_TEAMSPEAK, channel_id); + + + if(client_needed_permission_modify_power.has_value) { + if(!this->permission_granted(client_permission_modify_power, client_needed_permission_modify_power.value, true)) + return CommandResultPermissionError{permission::i_client_permission_modify_power}; + } } - auto oldGroup = this->server->groups->getChannelGroupExact(target_cldbid, channel, false); - if(oldGroup) { - if(!serverGroup->permission_granted(permission::i_channel_group_member_remove_power, this->calculate_permission_value(permission::i_channel_group_member_remove_power, -1), true)) { - if(target_cldbid != this->getClientDatabaseId()) - return CommandResultPermissionError{permission::i_channel_group_member_remove_power}; - if(!serverGroup->permission_granted(permission::i_channel_group_member_remove_power, this->calculate_permission_value(permission::i_channel_group_self_remove_power, -1), true)) - return CommandResultPermissionError{permission::i_channel_group_self_remove_power}; + { + auto old_group = this->server->groups->getChannelGroupExact(target_cldbid, channel, false); + if(old_group) { + auto channel_group_member_remove_power = this->calculate_permission_value(permission::i_channel_group_member_remove_power, channel_id); + if(!serverGroup->permission_granted(permission::i_channel_group_needed_member_remove_power, channel_group_member_remove_power, true)) { + if(target_cldbid != this->getClientDatabaseId()) + return CommandResultPermissionError{permission::i_channel_group_member_remove_power}; + + auto channel_group_self_remove_power = this->calculate_permission_value(permission::i_channel_group_self_remove_power, channel_id); + if(!serverGroup->permission_granted(permission::i_channel_group_needed_member_remove_power, channel_group_self_remove_power, true)) + return CommandResultPermissionError{permission::i_channel_group_self_remove_power}; + } } } this->server->groups->setChannelGroup(target_cldbid, serverGroup, channel); - for (const auto &targetClient : this->server->findClientsByCldbId(target_cldbid)) { unique_lock client_channel_lock_w(targetClient->channel_lock); auto updates = this->server->groups->update_server_group_property(targetClient, false, targetClient->getChannel()); /* needs a write lock */ diff --git a/server/src/client/voice/VoiceClientConnection.cpp b/server/src/client/voice/VoiceClientConnection.cpp index 5bfd021..a7201f8 100644 --- a/server/src/client/voice/VoiceClientConnection.cpp +++ b/server/src/client/voice/VoiceClientConnection.cpp @@ -603,6 +603,7 @@ bool VoiceClientConnection::preprocess_write_packets() { packet = std::move(category.queue.front()); category.queue.pop_front(); category.has_work = !category.queue.empty(); + flag_more = category.has_work; } if(!this->prepare_packet_for_write(buffers, packet, work_lock)) { diff --git a/server/src/server/VoiceServer.cpp b/server/src/server/VoiceServer.cpp index 98f669c..814312e 100644 --- a/server/src/server/VoiceServer.cpp +++ b/server/src/server/VoiceServer.cpp @@ -546,8 +546,14 @@ void VoiceServer::handleMessageWrite(int fd, short events, void *_event_handle) TIMING_STEP(timings, "retrigger client"); } - if(!more_clients) - break; + if(more_clients) { + /* allow other clients to write as well */ + if(more_to_write) + event_handle->push_voice_write_queue(client); + client.reset(); + continue; + } + if(!more_to_prepare) { /* we're done with this client. Nothing more to prepare */ client.reset();