diff options
author | Robert Adam <dev@robert-adam.de> | 2019-12-28 14:22:37 +0300 |
---|---|---|
committer | Robert Adam <dev@robert-adam.de> | 2019-12-28 14:22:37 +0300 |
commit | 1c38b53fdff388bbd8cea14dbfdf26e1d1f022be (patch) | |
tree | 8d042d685db8c475a0901d5c4ee4b807a3249e9a /src/murmur/Messages.cpp | |
parent | 61ee9ddf6d425d4da0bbe871280b6764d4409098 (diff) |
AccessTokens: Added support for temporary access tokens in the UserState message
Diffstat (limited to 'src/murmur/Messages.cpp')
-rw-r--r-- | src/murmur/Messages.cpp | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/src/murmur/Messages.cpp b/src/murmur/Messages.cpp index c2ae3e769..1b67b298e 100644 --- a/src/murmur/Messages.cpp +++ b/src/murmur/Messages.cpp @@ -77,6 +77,59 @@ sendMessage(uSource, mppd); \ } +/// A helper class for managing temporary access tokens +/// It will add the tokens in the comstructor and remove them again in the destructor effectively +/// turning the tokens into a scope-based property +class TemporaryAccessTokenHelper { + protected: + ServerUser *affectedUser; + QStringList qslTemporaryTokens; + Server *server; + + public: + TemporaryAccessTokenHelper(ServerUser *affectedUser, const QStringList &tokens, Server *server) : affectedUser(affectedUser), + qslTemporaryTokens(tokens), server(server) { + // Add the temporary tokens + QMutableStringListIterator it(this->qslTemporaryTokens); + + { + QMutexLocker qml(&server->qmCache); + + while (it.hasNext()) { + QString token = it.next(); + if (!this->affectedUser->qslAccessTokens.contains(token)) { + // Add token + this->affectedUser->qslAccessTokens << token; + } else { + // It appears, as if the user already has this token set -> it's not a temporary one or a duplicate + it.remove(); + } + } + } + + if (!this->qslTemporaryTokens.isEmpty()) { + // Clear the cache in order for tokens to take effect + server->clearACLCache(this->affectedUser); + } + } + + ~TemporaryAccessTokenHelper() { + if (!this->qslTemporaryTokens.isEmpty()) { + { + QMutexLocker qml(&server->qmCache); + + // remove the temporary tokens + foreach(QString token, this->qslTemporaryTokens) { + this->affectedUser->qslAccessTokens.removeOne(token); + } + } + + // Clear cache to actually get rid of the temporary tokens + server->clearACLCache(this->affectedUser); + } + } +}; + void Server::msgAuthenticate(ServerUser *uSource, MumbleProto::Authenticate &msg) { if ((msg.tokens_size() > 0) || (uSource->sState == ServerUser::Authenticated)) { QStringList qsl; @@ -501,6 +554,7 @@ void Server::msgUserState(ServerUser *uSource, MumbleProto::UserState &msg) { First check all permissions involved */ if ((pDstServerUser->iId == 0) && (uSource->iId != 0)) { + // Don't allow any action on the SuperUser except initiated directly by the SuperUser himself/herself PERM_DENIED_TYPE(SuperUser); return; } @@ -516,6 +570,13 @@ void Server::msgUserState(ServerUser *uSource, MumbleProto::UserState &msg) { if (uSource == pDstServerUser) { RATELIMIT(uSource); } + + // Handle potential temporary access tokens + QStringList temporaryAccessTokens; + for (int i=0; i < msg.temporary_access_tokens_size(); i++) { + temporaryAccessTokens << u8(msg.temporary_access_tokens(i)); + } + TemporaryAccessTokenHelper tempTokenHelper(uSource, temporaryAccessTokens, this); if (msg.has_channel_id()) { Channel *c = qhChannels.value(msg.channel_id()); |