ACL: flags refactoring, function to describe user.
This commit is contained in:
parent
2458e62da4
commit
110c8caf8a
91
src/acl.c
91
src/acl.c
@ -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) {
|
|||||||
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) {
|
|||||||
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) {
|
|||||||
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) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 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) {
|
|||||||
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 {
|
|||||||
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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user