summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/acl.c45
-rw-r--r--src/module.c5
-rw-r--r--src/script.c4
-rw-r--r--src/server.c25
-rw-r--r--src/server.h2
5 files changed, 32 insertions, 49 deletions
diff --git a/src/acl.c b/src/acl.c
index 8257b59b1..782254eb9 100644
--- a/src/acl.c
+++ b/src/acl.c
@@ -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);