Commit c7cd10df authored by antirez's avatar antirez
Browse files

ACL: flags refactoring, function to describe user.

parent 479f7f7a
...@@ -64,7 +64,19 @@ struct ACLCategoryItem { ...@@ -64,7 +64,19 @@ struct ACLCategoryItem {
{"connection", CMD_CATEGORY_CONNECTION}, {"connection", CMD_CATEGORY_CONNECTION},
{"transaction", CMD_CATEGORY_TRANSACTION}, {"transaction", CMD_CATEGORY_TRANSACTION},
{"scripting", CMD_CATEGORY_SCRIPTING}, {"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); void ACLResetSubcommandsForCommand(user *u, unsigned long id);
...@@ -150,7 +162,7 @@ user *ACLCreateUser(const char *name, size_t namelen) { ...@@ -150,7 +162,7 @@ user *ACLCreateUser(const char *name, size_t namelen) {
if (raxFind(Users,(unsigned char*)name,namelen) != raxNotFound) return NULL; if (raxFind(Users,(unsigned char*)name,namelen) != raxNotFound) return NULL;
user *u = zmalloc(sizeof(*u)); user *u = zmalloc(sizeof(*u));
u->name = sdsnewlen(name,namelen); u->name = sdsnewlen(name,namelen);
u->flags = 0; u->flags = USER_FLAG_DISABLED;
u->allowed_subcommands = NULL; u->allowed_subcommands = NULL;
u->passwords = listCreate(); u->passwords = listCreate();
u->patterns = listCreate(); u->patterns = listCreate();
...@@ -360,6 +372,54 @@ sds ACLDescribeUserCommandRules(user *u) { ...@@ -360,6 +372,54 @@ sds ACLDescribeUserCommandRules(user *u) {
return rules; 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 /* 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 * by the command renaming operations: we base all the ACL work from that
* table, so that ACLs are valid regardless of command renaming. */ * table, so that ACLs are valid regardless of command renaming. */
...@@ -500,7 +560,9 @@ int ACLSetUser(user *u, const char *op, ssize_t oplen) { ...@@ -500,7 +560,9 @@ int ACLSetUser(user *u, const char *op, ssize_t oplen) {
if (oplen == -1) oplen = strlen(op); if (oplen == -1) oplen = strlen(op);
if (!strcasecmp(op,"on")) { if (!strcasecmp(op,"on")) {
u->flags |= USER_FLAG_ENABLED; u->flags |= USER_FLAG_ENABLED;
u->flags &= ~USER_FLAG_DISABLED;
} else if (!strcasecmp(op,"off")) { } else if (!strcasecmp(op,"off")) {
u->flags |= USER_FLAG_DISABLED;
u->flags &= ~USER_FLAG_ENABLED; u->flags &= ~USER_FLAG_ENABLED;
} else if (!strcasecmp(op,"allkeys") || } else if (!strcasecmp(op,"allkeys") ||
!strcasecmp(op,"~*")) !strcasecmp(op,"~*"))
...@@ -679,7 +741,7 @@ int ACLCheckUserCredentials(robj *username, robj *password) { ...@@ -679,7 +741,7 @@ int ACLCheckUserCredentials(robj *username, robj *password) {
} }
/* Disabled users can't login. */ /* Disabled users can't login. */
if ((u->flags & USER_FLAG_ENABLED) == 0) { if (u->flags & USER_FLAG_DISABLED) {
errno = EINVAL; errno = EINVAL;
return C_ERR; return C_ERR;
} }
...@@ -874,24 +936,11 @@ void aclCommand(client *c) { ...@@ -874,24 +936,11 @@ void aclCommand(client *c) {
addReplyBulkCString(c,"flags"); addReplyBulkCString(c,"flags");
void *deflen = addReplyDeferredLen(c); void *deflen = addReplyDeferredLen(c);
int numflags = 0; int numflags = 0;
if (u->flags & USER_FLAG_ENABLED) { for (int j = 0; ACLUserFlags[j].flag; j++) {
addReplyBulkCString(c,"on"); if (u->flags & ACLUserFlags[j].flag) {
numflags++; addReplyBulkCString(c,ACLUserFlags[j].name);
} else { numflags++;
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++;
} }
setDeferredSetLen(c,deflen,numflags); setDeferredSetLen(c,deflen,numflags);
......
...@@ -740,9 +740,10 @@ typedef struct readyList { ...@@ -740,9 +740,10 @@ typedef struct readyList {
command ID we can set in the user command ID we can set in the user
is USER_COMMAND_BITS_COUNT-1. */ is USER_COMMAND_BITS_COUNT-1. */
#define USER_FLAG_ENABLED (1<<0) /* The user is active. */ #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_DISABLED (1<<1) /* The user is disabled. */
#define USER_FLAG_ALLCOMMANDS (1<<2) /* The user can run all commands. */ #define USER_FLAG_ALLKEYS (1<<2) /* The user can mention any key. */
#define USER_FLAG_NOPASS (1<<3) /* The user requires no password, any #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 provided password will work. For the
default user, this also means that default user, this also means that
no AUTH is needed, and every no AUTH is needed, and every
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment