mirror of
https://github.com/fluencelabs/redis
synced 2025-03-19 17:10:50 +00:00
ACL: AUTH uses users. ACL WHOAMI implemented.
This commit is contained in:
parent
35fe59935e
commit
cca64672f4
55
src/acl.c
55
src/acl.c
@ -103,6 +103,7 @@ int ACLListMatchSds(void *a, void *b) {
|
|||||||
user *ACLCreateUser(const char *name, size_t namelen) {
|
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->flags = 0;
|
u->flags = 0;
|
||||||
u->allowed_subcommands = NULL;
|
u->allowed_subcommands = NULL;
|
||||||
u->passwords = listCreate();
|
u->passwords = listCreate();
|
||||||
@ -119,8 +120,10 @@ user *ACLCreateUser(const char *name, size_t namelen) {
|
|||||||
/* Set user properties according to the string "op". The following
|
/* Set user properties according to the string "op". The following
|
||||||
* is a description of what different strings will do:
|
* is a description of what different strings will do:
|
||||||
*
|
*
|
||||||
* on Enable the user
|
* on Enable the user: it is possible to authenticate as this user.
|
||||||
* off Disable the user
|
* off Disable the user: it's no longer possible to authenticate
|
||||||
|
* with this user, however the already authenticated connections
|
||||||
|
* will still work.
|
||||||
* +<command> Allow the execution of that command
|
* +<command> Allow the execution of that command
|
||||||
* -<command> Disallow the execution of that command
|
* -<command> Disallow the execution of that command
|
||||||
* +@<category> Allow the execution of all the commands in such category
|
* +@<category> Allow the execution of all the commands in such category
|
||||||
@ -140,6 +143,7 @@ user *ACLCreateUser(const char *name, size_t namelen) {
|
|||||||
* It is possible to specify multiple patterns.
|
* It is possible to specify multiple patterns.
|
||||||
* ><password> Add this passowrd to the list of valid password for the user.
|
* ><password> Add this passowrd to the list of valid password for the user.
|
||||||
* For example >mypass will add "mypass" to the list.
|
* For example >mypass will add "mypass" to the list.
|
||||||
|
* This directive clears the "nopass" flag (see later).
|
||||||
* <<password> Remove this password from the list of valid passwords.
|
* <<password> Remove this password from the list of valid passwords.
|
||||||
* nopass All the set passwords of the user are removed, and the user
|
* nopass All the set passwords of the user are removed, and the user
|
||||||
* is flagged as requiring no password: it means that every
|
* is flagged as requiring no password: it means that every
|
||||||
@ -193,6 +197,7 @@ int ACLSetUser(user *u, const char *op, ssize_t oplen) {
|
|||||||
listNode *ln = listSearchKey(u->passwords,newpass);
|
listNode *ln = listSearchKey(u->passwords,newpass);
|
||||||
/* Avoid re-adding the same password multiple times. */
|
/* Avoid re-adding the same password multiple times. */
|
||||||
if (ln == NULL) listAddNodeTail(u->passwords,newpass);
|
if (ln == NULL) listAddNodeTail(u->passwords,newpass);
|
||||||
|
u->flags &= ~USER_FLAG_NOPASS;
|
||||||
} else if (op[0] == '<') {
|
} else if (op[0] == '<') {
|
||||||
sds delpass = sdsnewlen(op+1,oplen-1);
|
sds delpass = sdsnewlen(op+1,oplen-1);
|
||||||
listNode *ln = listSearchKey(u->passwords,delpass);
|
listNode *ln = listSearchKey(u->passwords,delpass);
|
||||||
@ -220,20 +225,35 @@ void ACLInit(void) {
|
|||||||
* ENONENT: if the specified user does not exist at all.
|
* ENONENT: if the specified user does not exist at all.
|
||||||
*/
|
*/
|
||||||
int ACLCheckUserCredentials(robj *username, robj *password) {
|
int ACLCheckUserCredentials(robj *username, robj *password) {
|
||||||
/* For now only the "default" user is allowed. When the RCP1 ACLs
|
user *u = ACLGetUserByName(username->ptr,sdslen(username->ptr));
|
||||||
* will be implemented multiple usernames will be supproted. */
|
if (u == NULL) {
|
||||||
if (username != NULL && strcmp(username->ptr,"default")) {
|
|
||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
return C_ERR;
|
return C_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For now we just compare the password with the system wide one. */
|
/* Disabled users can't login. */
|
||||||
if (!time_independent_strcmp(password->ptr, server.requirepass)) {
|
if ((u->flags & USER_FLAG_ENABLED) == 0) {
|
||||||
return C_OK;
|
|
||||||
} else {
|
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return C_ERR;
|
return C_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If the user is configured to don't require any password, we
|
||||||
|
* are already fine here. */
|
||||||
|
if (u->flags & USER_FLAG_NOPASS) return C_OK;
|
||||||
|
|
||||||
|
/* Check all the user passwords for at least one to match. */
|
||||||
|
listIter li;
|
||||||
|
listNode *ln;
|
||||||
|
listRewind(u->passwords,&li);
|
||||||
|
while((ln = listNext(&li))) {
|
||||||
|
sds thispass = listNodeValue(ln);
|
||||||
|
if (!time_independent_strcmp(password->ptr, thispass))
|
||||||
|
return C_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we reached this point, no password matched. */
|
||||||
|
errno = EINVAL;
|
||||||
|
return C_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For ACL purposes, every user has a bitmap with the commands that such
|
/* For ACL purposes, every user has a bitmap with the commands that such
|
||||||
@ -314,11 +334,11 @@ int ACLCheckCommandPerm(client *c) {
|
|||||||
* ==========================================================================*/
|
* ==========================================================================*/
|
||||||
|
|
||||||
/* ACL -- show and modify the configuration of ACL users.
|
/* ACL -- show and modify the configuration of ACL users.
|
||||||
* ACL help
|
* ACL HELP
|
||||||
* ACL list
|
* ACL LIST
|
||||||
* ACL setuser <username> ... user attribs ...
|
* ACL SETUSER <username> ... user attribs ...
|
||||||
* ACL deluser <username>
|
* ACL DELUSER <username>
|
||||||
* ACL getuser <username>
|
* ACL GETUSER <username>
|
||||||
*/
|
*/
|
||||||
void aclCommand(client *c) {
|
void aclCommand(client *c) {
|
||||||
char *sub = c->argv[1]->ptr;
|
char *sub = c->argv[1]->ptr;
|
||||||
@ -336,12 +356,19 @@ void aclCommand(client *c) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
addReply(c,shared.ok);
|
addReply(c,shared.ok);
|
||||||
|
} else if (!strcasecmp(sub,"whoami")) {
|
||||||
|
if (c->user != NULL) {
|
||||||
|
addReplyBulkCBuffer(c,c->user->name,sdslen(c->user->name));
|
||||||
|
} else {
|
||||||
|
addReplyNull(c);
|
||||||
|
}
|
||||||
} else if (!strcasecmp(sub,"help")) {
|
} else if (!strcasecmp(sub,"help")) {
|
||||||
const char *help[] = {
|
const char *help[] = {
|
||||||
"LIST -- List all the registered users.",
|
"LIST -- List all the registered users.",
|
||||||
"SETUSER <username> [attribs ...] -- Create or modify a user.",
|
"SETUSER <username> [attribs ...] -- Create or modify a user.",
|
||||||
"DELUSER <username> -- Delete a user.",
|
"DELUSER <username> -- Delete a user.",
|
||||||
"GETUSER <username> -- Get the user details.",
|
"GETUSER <username> -- Get the user details.",
|
||||||
|
"WHOAMI -- Return the current username.",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
addReplyHelp(c,help);
|
addReplyHelp(c,help);
|
||||||
|
@ -722,6 +722,7 @@ typedef struct readyList {
|
|||||||
connection is immediately
|
connection is immediately
|
||||||
authenticated. */
|
authenticated. */
|
||||||
typedef struct user {
|
typedef struct user {
|
||||||
|
sds name; /* The username as an SDS string. */
|
||||||
uint64_t flags; /* See USER_FLAG_* */
|
uint64_t flags; /* See USER_FLAG_* */
|
||||||
|
|
||||||
/* The bit in allowed_commands is set if this user has the right to
|
/* The bit in allowed_commands is set if this user has the right to
|
||||||
|
Loading…
x
Reference in New Issue
Block a user