diff options
author | Robert Adam <dev@robert-adam.de> | 2020-02-08 16:02:29 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-02-08 16:02:29 +0300 |
commit | 8bb5cafcac39f5714e474fac1106ed2610137891 (patch) | |
tree | a9355d6ed7510339f8056a0a47d6c8fab719eb73 /src/murmur/Messages.cpp | |
parent | cdee0b772d698eec853c25451c0f60065d922b22 (diff) | |
parent | 6bc6c9e8225884475f9473a3e5249051144c513c (diff) |
Merge PR #3927: Added support for temporary access tokens
Diffstat (limited to 'src/murmur/Messages.cpp')
-rw-r--r-- | src/murmur/Messages.cpp | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/src/murmur/Messages.cpp b/src/murmur/Messages.cpp index c2a13a4c2..4ab9d22f1 100644 --- a/src/murmur/Messages.cpp +++ b/src/murmur/Messages.cpp @@ -77,6 +77,65 @@ 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 tokens are treated case-insensitively, transform all temp. tokens to lowercase first + if (Group::accessTokenCaseSensitivity == Qt::CaseInsensitive) { + token = token.toLower(); + } + + if (!this->affectedUser->qslAccessTokens.contains(token, Group::accessTokenCaseSensitivity)) { + // 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 +560,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 +576,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()); |