ACL: use a fixed table for command IDs.

This commit is contained in:
antirez 2019-01-09 21:31:29 +01:00
parent 010b24f864
commit 7fc882c578
3 changed files with 27 additions and 2 deletions

View File

@ -93,3 +93,20 @@ int ACLCheckUserCredentials(robj *username, robj *password) {
return C_ERR; return C_ERR;
} }
} }
/* For ACL purposes, every user has a bitmap with the commands that such
* user is allowed to execute. In order to populate the bitmap, every command
* should have an assigned ID (that is used to index the bitmap). This function
* creates such an ID: it uses sequential IDs, reusing the same ID for the same
* command name, so that a command retains the same ID in case of modules that
* are unloaded and later reloaded. */
unsigned long ACLGetCommandID(const char *cmdname) {
static rax *map = NULL;
unsigned long nextid = 0;
if (map == NULL) map = raxNew();
void *id = raxFind(map,(unsigned char*)cmdname,strlen(cmdname));
if (id != raxNotFound) return (unsigned long)id;
raxInsert(map,(unsigned char*)cmdname,strlen(cmdname),(void*)nextid,NULL);
return nextid++;
}

View File

@ -2224,8 +2224,7 @@ void populateCommandTable(void) {
f++; f++;
} }
c->id = j; /* Sequential ID for each command. Used for ACLs. */ c->id = ACLGetCommandID(c->name); /* Assign the ID used for ACL. */
retval1 = dictAdd(server.commands, sdsnew(c->name), c); retval1 = dictAdd(server.commands, sdsnew(c->name), c);
/* Populate an additional dictionary that will be unaffected /* Populate an additional dictionary that will be unaffected
* by rename-command statements in redis.conf. */ * by rename-command statements in redis.conf. */

View File

@ -1352,6 +1352,14 @@ typedef struct {
dictIterator *di; dictIterator *di;
} setTypeIterator; } setTypeIterator;
/* This structure represents a Redis user. This is useful for ACLs, the
* user is associated to the connection after the connection is authenticated.
* If there is no associated user, the connection uses the default user. */
#define USER_MAX_COMMAND_BIT 1024
typedef struct user {
uint64_t allowed_commands[USER_MAX_COMMAND_BIT/64];
} user;
/* Structure to hold hash iteration abstraction. Note that iteration over /* Structure to hold hash iteration abstraction. Note that iteration over
* hashes involves both fields and values. Because it is possible that * hashes involves both fields and values. Because it is possible that
* not both are required, store pointers in the iterator to avoid * not both are required, store pointers in the iterator to avoid
@ -1655,6 +1663,7 @@ void receiveChildInfo(void);
/* acl.c -- Authentication related prototypes. */ /* acl.c -- Authentication related prototypes. */
int ACLCheckUserCredentials(robj *username, robj *password); int ACLCheckUserCredentials(robj *username, robj *password);
unsigned long ACLGetCommandID(const char *cmdname);
/* Sorted sets data type */ /* Sorted sets data type */