diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/acl.c | 45 | ||||
-rw-r--r-- | src/module.c | 5 | ||||
-rw-r--r-- | src/script.c | 4 | ||||
-rw-r--r-- | src/server.c | 25 | ||||
-rw-r--r-- | src/server.h | 2 |
5 files changed, 32 insertions, 49 deletions
@@ -1766,7 +1766,11 @@ int ACLUserCheckChannelPerm(user *u, sds channel, int is_pattern) { return ACL_DENIED_CHANNEL; } -/* Lower level API that checks if a specified user is able to execute a given command. */ +/* Lower level API that checks if a specified user is able to execute a given command. + * + * If the command fails an ACL check, idxptr will be to set to the first argv entry that + * causes the failure, either 0 if the command itself fails or the idx of the key/channel + * that causes the failure */ int ACLCheckAllUserCommandPerm(user *u, struct redisCommand *cmd, robj **argv, int argc, int *idxptr) { listIter li; listNode *ln; @@ -2581,18 +2585,25 @@ void addACLLogEntry(client *c, int reason, int context, int argpos, sds username } } -const char* getAclErrorMessage(int acl_res) { - /* Notice that a variant of this code also exists on aclCommand so - * it also need to be updated on changed. */ +sds getAclErrorMessage(int acl_res, user *user, struct redisCommand *cmd, sds errored_val, int verbose) { switch (acl_res) { case ACL_DENIED_CMD: - return "can't run this command or subcommand"; + return sdscatfmt(sdsempty(), "User %S has no permissions to run " + "the '%S' command", user->name, cmd->fullname); case ACL_DENIED_KEY: - return "can't access at least one of the keys mentioned in the command arguments"; + if (verbose) { + return sdscatfmt(sdsempty(), "User %S has no permissions to access " + "the '%S' key", user->name, errored_val); + } else { + return sdsnew("No permissions to access a key"); + } case ACL_DENIED_CHANNEL: - return "can't publish to the channel mentioned in the command"; - default: - return "lacking the permissions for the command"; + if (verbose) { + return sdscatfmt(sdsempty(), "User %S has no permissions to access " + "the '%S' channel", user->name, errored_val); + } else { + return sdsnew("No permissions to access a channel"); + } } serverPanic("Reached deadcode on getAclErrorMessage"); } @@ -2956,22 +2967,8 @@ void aclCommand(client *c) { int idx; int result = ACLCheckAllUserCommandPerm(u, cmd, c->argv + 3, c->argc - 3, &idx); - /* Notice that a variant of this code also exists on getAclErrorMessage so - * it also need to be updated on changed. */ if (result != ACL_OK) { - sds err = sdsempty(); - if (result == ACL_DENIED_CMD) { - err = sdscatfmt(err, "This user has no permissions to run " - "the '%s' command", cmd->fullname); - } else if (result == ACL_DENIED_KEY) { - err = sdscatfmt(err, "This user has no permissions to access " - "the '%s' key", c->argv[idx + 3]->ptr); - } else if (result == ACL_DENIED_CHANNEL) { - err = sdscatfmt(err, "This user has no permissions to access " - "the '%s' channel", c->argv[idx + 3]->ptr); - } else { - serverPanic("Invalid permission result"); - } + sds err = getAclErrorMessage(result, u, cmd, c->argv[idx+3]->ptr, 1); addReplyBulkSds(c, err); return; } diff --git a/src/module.c b/src/module.c index 6d9425baf..11b47d99f 100644 --- a/src/module.c +++ b/src/module.c @@ -6003,7 +6003,10 @@ RedisModuleCallReply *RM_Call(RedisModuleCtx *ctx, const char *cmdname, const ch sds object = (acl_retval == ACL_DENIED_CMD) ? sdsdup(c->cmd->fullname) : sdsdup(c->argv[acl_errpos]->ptr); addACLLogEntry(ctx->client, acl_retval, ACL_LOG_CTX_MODULE, -1, ctx->client->user->name, object); if (error_as_call_replies) { - sds msg = sdscatfmt(sdsempty(), "acl verification failed, %s.", getAclErrorMessage(acl_retval)); + /* verbosity should be same as processCommand() in server.c */ + sds acl_msg = getAclErrorMessage(acl_retval, ctx->client->user, c->cmd, c->argv[acl_errpos]->ptr, 0); + sds msg = sdscatfmt(sdsempty(), "-NOPERM %S\r\n", acl_msg); + sdsfree(acl_msg); reply = callReplyCreateError(msg, ctx); } errno = EACCES; diff --git a/src/script.c b/src/script.c index 12d87322d..3d9785312 100644 --- a/src/script.c +++ b/src/script.c @@ -335,7 +335,9 @@ static int scriptVerifyACL(client *c, sds *err) { int acl_retval = ACLCheckAllPerm(c, &acl_errpos); if (acl_retval != ACL_OK) { addACLLogEntry(c,acl_retval,ACL_LOG_CTX_LUA,acl_errpos,NULL,NULL); - *err = sdscatfmt(sdsempty(), "The user executing the script %s", getAclErrorMessage(acl_retval)); + sds msg = getAclErrorMessage(acl_retval, c->user, c->cmd, c->argv[acl_errpos]->ptr, 0); + *err = sdscatsds(sdsnew("ACL failure in script: "), msg); + sdsfree(msg); return C_ERR; } return C_OK; diff --git a/src/server.c b/src/server.c index 2c65aac66..4962b4fba 100644 --- a/src/server.c +++ b/src/server.c @@ -3752,28 +3752,9 @@ int processCommand(client *c) { int acl_retval = ACLCheckAllPerm(c,&acl_errpos); if (acl_retval != ACL_OK) { addACLLogEntry(c,acl_retval,(c->flags & CLIENT_MULTI) ? ACL_LOG_CTX_MULTI : ACL_LOG_CTX_TOPLEVEL,acl_errpos,NULL,NULL); - switch (acl_retval) { - case ACL_DENIED_CMD: - { - rejectCommandFormat(c, - "-NOPERM this user has no permissions to run " - "the '%s' command", c->cmd->fullname); - break; - } - case ACL_DENIED_KEY: - rejectCommandFormat(c, - "-NOPERM this user has no permissions to access " - "one of the keys used as arguments"); - break; - case ACL_DENIED_CHANNEL: - rejectCommandFormat(c, - "-NOPERM this user has no permissions to access " - "one of the channels used as arguments"); - break; - default: - rejectCommandFormat(c, "no permission"); - break; - } + sds msg = getAclErrorMessage(acl_retval, c->user, c->cmd, c->argv[acl_errpos]->ptr, 0); + rejectCommandFormat(c, "-NOPERM %s", msg); + sdsfree(msg); return C_OK; } diff --git a/src/server.h b/src/server.h index 2ec7dc7ea..4d6eb47ba 100644 --- a/src/server.h +++ b/src/server.h @@ -2805,7 +2805,7 @@ void addReplyCommandCategories(client *c, struct redisCommand *cmd); user *ACLCreateUnlinkedUser(); void ACLFreeUserAndKillClients(user *u); void addACLLogEntry(client *c, int reason, int context, int argpos, sds username, sds object); -const char* getAclErrorMessage(int acl_res); +sds getAclErrorMessage(int acl_res, user *user, struct redisCommand *cmd, sds errored_val, int verbose); void ACLUpdateDefaultUserPassword(sds password); sds genRedisInfoStringACLStats(sds info); |