mirror of
https://github.com/fluencelabs/redis
synced 2025-03-20 17:40:50 +00:00
ACL: user commands bitmap check refactoring for new features.
This commit is contained in:
parent
dbdc68a658
commit
48eeec5fb4
34
src/acl.c
34
src/acl.c
@ -305,6 +305,32 @@ user *ACLGetUserByName(const char *name, size_t namelen) {
|
|||||||
return myuser;
|
return myuser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Given a command ID, this function set by reference 'word' and 'bit'
|
||||||
|
* so that user->allowed_commands[word] will address the right word
|
||||||
|
* where the corresponding bit for the provided ID is stored, and
|
||||||
|
* so that user->allowed_commands[word]&bit will identify that specific
|
||||||
|
* bit. The function returns C_ERR in case the specified ID overflows
|
||||||
|
* the bitmap in the user representation. */
|
||||||
|
int ACLGetCommandBitCoordinates(unsigned long id, uint64_t *word, uint64_t *bit) {
|
||||||
|
if (id >= USER_MAX_COMMAND_BIT) return C_ERR;
|
||||||
|
*word = id / sizeof(uint64_t) / 8;
|
||||||
|
*bit = 1 << (id % (sizeof(uint64_t) * 8));
|
||||||
|
return C_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the specified command bit is set for the specified user.
|
||||||
|
* The function returns 1 is the bit is set or 0 if it is not.
|
||||||
|
* Note that this function does not check the ALLCOMMANDS flag of the user
|
||||||
|
* but just the lowlevel bitmask.
|
||||||
|
*
|
||||||
|
* If the bit overflows the user internal represetation, zero is returned
|
||||||
|
* in order to disallow the execution of the command in such edge case. */
|
||||||
|
int ACLCheckCommandID(user *u, unsigned long id) {
|
||||||
|
uint64_t word, bit;
|
||||||
|
if (ACLGetCommandBitCoordinates(id,&word,&bit) == C_ERR) return 0;
|
||||||
|
return u->allowed_commands[word] & bit;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if the command ready to be excuted in the client 'c', and already
|
/* Check if the command ready to be excuted in the client 'c', and already
|
||||||
* referenced by c->cmd, can be executed by this client according to the
|
* referenced by c->cmd, can be executed by this client according to the
|
||||||
* ACls associated to the client user c->user.
|
* ACls associated to the client user c->user.
|
||||||
@ -321,19 +347,13 @@ int ACLCheckCommandPerm(client *c) {
|
|||||||
/* If there is no associated user, the connection can run anything. */
|
/* If there is no associated user, the connection can run anything. */
|
||||||
if (u == NULL) return ACL_OK;
|
if (u == NULL) return ACL_OK;
|
||||||
|
|
||||||
/* We have to deny every command with an ID that overflows the Redis
|
|
||||||
* internal structures. Very unlikely to happen. */
|
|
||||||
if (c->cmd->id >= USER_MAX_COMMAND_BIT) return ACL_DENIED_CMD;
|
|
||||||
|
|
||||||
/* Check if the user can execute this command. */
|
/* Check if the user can execute this command. */
|
||||||
if (!(u->flags & USER_FLAG_ALLCOMMANDS) &&
|
if (!(u->flags & USER_FLAG_ALLCOMMANDS) &&
|
||||||
c->cmd->proc != authCommand)
|
c->cmd->proc != authCommand)
|
||||||
{
|
{
|
||||||
uint64_t wordid = id / sizeof(u->allowed_commands[0]) / 8;
|
|
||||||
uint64_t bit = 1 << (id % (sizeof(u->allowed_commands[0] * 8)));
|
|
||||||
/* If the bit is not set we have to check further, in case the
|
/* If the bit is not set we have to check further, in case the
|
||||||
* command is allowed just with that specific subcommand. */
|
* command is allowed just with that specific subcommand. */
|
||||||
if (!(u->allowed_commands[wordid] & bit)) {
|
if (ACLCheckCommandID(u,id) == 0) {
|
||||||
/* Check if the subcommand matches. */
|
/* Check if the subcommand matches. */
|
||||||
if (u->allowed_subcommands == NULL || c->argc < 2)
|
if (u->allowed_subcommands == NULL || c->argc < 2)
|
||||||
return ACL_DENIED_CMD;
|
return ACL_DENIED_CMD;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user