diff options
author | Slava Koyfman <slavak@users.noreply.github.com> | 2023-04-02 16:18:28 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-02 16:18:28 +0300 |
commit | f38aa6bfb7a1bc7a3c5b18fadc513da1152bc7b5 (patch) | |
tree | 02902613299fe40dbfefc9c55527b5b52e34e1fd /src | |
parent | 1f76bb17ddcb2adc484bf82f1b839c45e264524f (diff) | |
download | redis-f38aa6bfb7a1bc7a3c5b18fadc513da1152bc7b5.tar.gz |
Disconnect pub-sub subscribers when revoking `allchannels` permission (#11992)
The existing logic for killing pub-sub clients did not handle the `allchannels`
permission correctly. For example, if you:
ACL SETUSER foo allchannels
Have a client authenticate as the user `foo` and subscribe to a channel, and then:
ACL SETUSER foo resetchannels
The subscribed client would not be disconnected, though new clients under that user
would be blocked from subscribing to any channels.
This was caused by an incomplete optimization in `ACLKillPubsubClientsIfNeeded`
checking whether the new channel permissions were a strict superset of the old ones.
Diffstat (limited to 'src')
-rw-r--r-- | src/acl.c | 7 |
1 files changed, 7 insertions, 0 deletions
@@ -1891,6 +1891,13 @@ void ACLKillPubsubClientsIfNeeded(user *new, user *original) { listRewind(original->selectors,&li); while((ln = listNext(&li)) && match) { aclSelector *s = (aclSelector *) listNodeValue(ln); + /* If any of the original selectors has the all-channels permission, but + * the new ones don't (this is checked earlier in this function), then the + * new list is not a strict superset of the original. */ + if (s->flags & SELECTOR_FLAG_ALLCHANNELS) { + match = 0; + break; + } listRewind(s->channels, &lpi); while((lpn = listNext(&lpi)) && match) { if (!listSearchKey(upcoming, listNodeValue(lpn))) { |