ACL: flags refactoring, function to describe user.

This commit is contained in:
antirez 2019-01-31 16:49:22 +01:00
parent 479f7f7af4
commit c7cd10dfe9
2 changed files with 74 additions and 24 deletions

View File

@ -64,7 +64,19 @@ struct ACLCategoryItem {
{"connection", CMD_CATEGORY_CONNECTION},
{"transaction", CMD_CATEGORY_TRANSACTION},
{"scripting", CMD_CATEGORY_SCRIPTING},
{"",0} /* Terminator. */
{NULL,0} /* Terminator. */
};
struct ACLUserFlag {
const char *name;
uint64_t flag;
} ACLUserFlags[] = {
{"on", USER_FLAG_ENABLED},
{"off", USER_FLAG_DISABLED},
{"allkeys", USER_FLAG_ALLKEYS},
{"allcommands", USER_FLAG_ALLCOMMANDS},
{"nopass", USER_FLAG_NOPASS},
{NULL,0} /* Terminator. */
};
void ACLResetSubcommandsForCommand(user *u, unsigned long id);
@ -150,7 +162,7 @@ user *ACLCreateUser(const char *name, size_t namelen) {
if (raxFind(Users,(unsigned char*)name,namelen) != raxNotFound) return NULL;
user *u = zmalloc(sizeof(*u));
u->name = sdsnewlen(name,namelen);
u->flags = 0;
u->flags = USER_FLAG_DISABLED;
u->allowed_subcommands = NULL;
u->passwords = listCreate();
u->patterns = listCreate();
@ -360,6 +372,54 @@ sds ACLDescribeUserCommandRules(user *u) {
return rules;
}
/* This is similar to ACLDescribeUserCommandRules(), however instead of
* describing just the user command rules, everything is described: user
* flags, keys, passwords and finally the command rules obtained via
* the ACLDescribeUserCommandRules() function. This is the function we call
* when we want to rewrite the configuration files describing ACLs and
* in order to show users with ACL LIST. */
sds ACLDescribeUser(user *u) {
sds res = sdsempty();
/* Flags. */
for (int j = 0; ACLUserFlags[j].flag; j++) {
if (u->flags & ACLUserFlags[j].flag) {
res = sdscat(res,ACLUserFlags[j].name);
res = sdscatlen(res," ",1);
}
}
/* Passwords. */
listIter li;
listNode *ln;
listRewind(u->passwords,&li);
while((ln = listNext(&li))) {
sds thispass = listNodeValue(ln);
res = sdscatlen(res,">",1);
res = sdscatsds(res,thispass);
res = sdscatlen(res," ",1);
}
/* Key patterns. */
if (u->flags & USER_FLAG_ALLKEYS) {
res = sdscatlen(res,"~* ",3);
} else {
listRewind(u->patterns,&li);
while((ln = listNext(&li))) {
sds thispat = listNodeValue(ln);
res = sdscatlen(res,"~",1);
res = sdscatsds(res,thispat);
res = sdscatlen(res," ",1);
}
}
/* Command rules. */
sds rules = ACLDescribeUserCommandRules(u);
res = sdscatsds(res,rules);
sdsfree(rules);
return res;
}
/* Get a command from the original command table, that is not affected
* by the command renaming operations: we base all the ACL work from that
* table, so that ACLs are valid regardless of command renaming. */
@ -500,7 +560,9 @@ int ACLSetUser(user *u, const char *op, ssize_t oplen) {
if (oplen == -1) oplen = strlen(op);
if (!strcasecmp(op,"on")) {
u->flags |= USER_FLAG_ENABLED;
u->flags &= ~USER_FLAG_DISABLED;
} else if (!strcasecmp(op,"off")) {
u->flags |= USER_FLAG_DISABLED;
u->flags &= ~USER_FLAG_ENABLED;
} else if (!strcasecmp(op,"allkeys") ||
!strcasecmp(op,"~*"))
@ -679,7 +741,7 @@ int ACLCheckUserCredentials(robj *username, robj *password) {
}
/* Disabled users can't login. */
if ((u->flags & USER_FLAG_ENABLED) == 0) {
if (u->flags & USER_FLAG_DISABLED) {
errno = EINVAL;
return C_ERR;
}
@ -874,24 +936,11 @@ void aclCommand(client *c) {
addReplyBulkCString(c,"flags");
void *deflen = addReplyDeferredLen(c);
int numflags = 0;
if (u->flags & USER_FLAG_ENABLED) {
addReplyBulkCString(c,"on");
numflags++;
} else {
addReplyBulkCString(c,"off");
numflags++;
}
if (u->flags & USER_FLAG_ALLKEYS) {
addReplyBulkCString(c,"allkeys");
numflags++;
}
if (u->flags & USER_FLAG_ALLCOMMANDS) {
addReplyBulkCString(c,"allcommands");
numflags++;
}
if (u->flags & USER_FLAG_NOPASS) {
addReplyBulkCString(c,"nopass");
numflags++;
for (int j = 0; ACLUserFlags[j].flag; j++) {
if (u->flags & ACLUserFlags[j].flag) {
addReplyBulkCString(c,ACLUserFlags[j].name);
numflags++;
}
}
setDeferredSetLen(c,deflen,numflags);

View File

@ -740,9 +740,10 @@ typedef struct readyList {
command ID we can set in the user
is USER_COMMAND_BITS_COUNT-1. */
#define USER_FLAG_ENABLED (1<<0) /* The user is active. */
#define USER_FLAG_ALLKEYS (1<<1) /* The user can mention any key. */
#define USER_FLAG_ALLCOMMANDS (1<<2) /* The user can run all commands. */
#define USER_FLAG_NOPASS (1<<3) /* The user requires no password, any
#define USER_FLAG_DISABLED (1<<1) /* The user is disabled. */
#define USER_FLAG_ALLKEYS (1<<2) /* The user can mention any key. */
#define USER_FLAG_ALLCOMMANDS (1<<3) /* The user can run all commands. */
#define USER_FLAG_NOPASS (1<<4) /* The user requires no password, any
provided password will work. For the
default user, this also means that
no AUTH is needed, and every