From 09041b9359dfcdc84cf5570ded44160fbe7e2bfb Mon Sep 17 00:00:00 2001 From: antirez Date: Mon, 30 Sep 2019 18:22:55 +0200 Subject: ACLs: change hashed passwords opcode to also remove them. Related to PR #6405 --- src/acl.c | 32 ++++++++++++++++++++++---------- tests/unit/acl.tcl | 6 ++++++ 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/acl.c b/src/acl.c index 9c5196f48..4c43add14 100644 --- a/src/acl.c +++ b/src/acl.c @@ -95,7 +95,7 @@ void ACLResetSubcommands(user *u); void ACLAddAllowedSubcommand(user *u, unsigned long id, const char *sub); /* The length of the string representation of a hashed password. */ -#define HASH_PASSWORD_LEN SHA256_BLOCK_SIZE*2 +#define HASH_PASSWORD_LEN SHA256_BLOCK_SIZE*2 /* ============================================================================= * Helper functions for the rest of the ACL implementation @@ -652,11 +652,14 @@ void ACLAddAllowedSubcommand(user *u, unsigned long id, const char *sub) { * > Add this password to the list of valid password for the user. * For example >mypass will add "mypass" to the list. * This directive clears the "nopass" flag (see later). - * # Add this password hash to the list of valid hashes for - * the user. This is useful if you have previously computed - * the hash, and don't want to store it in plaintext. - * This directive clears the "nopass" flag (see later). + * # Add this password hash to the list of valid hashes for + * the user. This is useful if you have previously computed + * the hash, and don't want to store it in plaintext. + * This directive clears the "nopass" flag (see later). * < Remove this password from the list of valid passwords. + * ! Remove this hashed password from the list of valid passwords. + * This is useful when you want to remove a password just by + * hash without knowing its plaintext version at all. * nopass All the set passwords of the user are removed, and the user * is flagged as requiring no password: it means that every * password will work against this user. If this directive is @@ -735,12 +738,12 @@ int ACLSetUser(user *u, const char *op, ssize_t oplen) { } else { if (oplen != HASH_PASSWORD_LEN + 1) { errno = EBADMSG; - return C_ERR; + return C_ERR; } /* Password hashes can only be characters that represent - * hexadecimal values, which are numbers and lowercase - * characters 'a' through 'f'. + * hexadecimal values, which are numbers and lowercase + * characters 'a' through 'f'. */ for(int i = 1; i < HASH_PASSWORD_LEN + 1; i++) { char c = op[i]; @@ -759,8 +762,17 @@ int ACLSetUser(user *u, const char *op, ssize_t oplen) { else sdsfree(newpass); u->flags &= ~USER_FLAG_NOPASS; - } else if (op[0] == '<') { - sds delpass = ACLHashPassword((unsigned char*)op+1,oplen-1); + } else if (op[0] == '<' || op[0] == '!') { + sds delpass; + if (op[0] == '<') { + delpass = ACLHashPassword((unsigned char*)op+1,oplen-1); + } else { + if (oplen != HASH_PASSWORD_LEN + 1) { + errno = EBADMSG; + return C_ERR; + } + delpass = sdsnewlen(op+1,oplen-1); + } listNode *ln = listSearchKey(u->passwords,delpass); sdsfree(delpass); if (ln) { diff --git a/tests/unit/acl.tcl b/tests/unit/acl.tcl index d3b721205..2205d2d86 100644 --- a/tests/unit/acl.tcl +++ b/tests/unit/acl.tcl @@ -55,6 +55,12 @@ start_server {tags {"acl"}} { assert_no_match {*passwd4*} $passstr } + test {Test hashed passwords removal} { + r ACL setuser newuser !34344e4d60c2b6d639b7bd22e18f2b0b91bc34bf0ac5f9952744435093cfb4e6 + set passstr [dict get [r ACL getuser newuser] passwords] + assert_no_match {*34344e4d60c2b6d639b7bd22e18f2b0b91bc34bf0ac5f9952744435093cfb4e6*} $passstr + } + test {By default users are not able to access any command} { catch {r SET foo bar} e set e -- cgit v1.2.1