summaryrefslogtreecommitdiff
path: root/src/db.c
diff options
context:
space:
mode:
authorBinbin <binloveplay1314@qq.com>2022-01-27 03:03:21 +0800
committerGitHub <noreply@github.com>2022-01-26 21:03:21 +0200
commitd6169258351e58ce1c0cfc01ba9c85e2a5b15ffb (patch)
tree77c06611ffe63757f30a24c83005d627c96116e4 /src/db.c
parent795ea011ba8674a9b5e05e79284f6f20a5d0cc03 (diff)
downloadredis-d6169258351e58ce1c0cfc01ba9c85e2a5b15ffb.tar.gz
Allow SET without GET arg on write-only ACL. Allow BITFIELD GET on read-only ACL (#10148)
SET is a R+W command, because it can also do `GET` on the data. SET without GET is a write-only command. SET with GET is a read+write command. In #9974, we added ACL to let users define write-only access. So when the user uses SET with GET option, and the user doesn't have the READ permission on the key, we need to reject it, but we rather not reject users with write-only permissions from using the SET command when they don't use GET. In this commit, we add a `getkeys_proc` function to control key flags in SET command. We also add a new key spec flag (VARIABLE_FLAGS) means that some keys might have different flags depending on arguments. We also handle BITFIELD command, add a `bitfieldGetKeys` function. BITFIELD GET is a READ ONLY command. BITFIELD SET or BITFIELD INCR are READ WRITE commands. Other changes: 1. SET GET was added in 6.2, add the missing since in set.json 2. Added tests to cover the changes in acl-v2.tcl 3. Fix some typos in server.h and cleanups in acl-v2.tcl Co-authored-by: Madelyn Olson <madelyneolson@gmail.com> Co-authored-by: Oran Agra <oran@redislabs.com>
Diffstat (limited to 'src/db.c')
-rw-r--r--src/db.c50
1 files changed, 49 insertions, 1 deletions
diff --git a/src/db.c b/src/db.c
index 94fbc0227..66d5506d1 100644
--- a/src/db.c
+++ b/src/db.c
@@ -1824,7 +1824,7 @@ int getKeysFromCommandWithSpecs(struct redisCommand *cmd, robj **argv, int argc,
if (cmd->flags & CMD_MODULE_GETKEYS) {
return moduleGetCommandKeysViaAPI(cmd,argv,argc,result);
} else {
- if (!(getAllKeySpecsFlags(cmd, 0) & CMD_KEY_INCOMPLETE)) {
+ if (!(getAllKeySpecsFlags(cmd, 0) & (CMD_KEY_INCOMPLETE|CMD_KEY_VARIABLE_FLAGS))) {
int ret = getKeysUsingKeySpecs(cmd,argv,argc,search_flags,result);
if (ret >= 0)
return ret;
@@ -2210,3 +2210,51 @@ int xreadGetKeys(struct redisCommand *cmd, robj **argv, int argc, getKeysResult
result->numkeys = num;
return num;
}
+
+/* Helper function to extract keys from the SET command, which may have
+ * a read flag if the GET argument is passed in. */
+int setGetKeys(struct redisCommand *cmd, robj **argv, int argc, getKeysResult *result) {
+ keyReference *keys;
+ UNUSED(cmd);
+
+ keys = getKeysPrepareResult(result, 1);
+ keys[0].pos = 1; /* We always know the position */
+ result->numkeys = 1;
+
+ for (int i = 3; i < argc; i++) {
+ char *arg = argv[i]->ptr;
+ if ((arg[0] == 'g' || arg[0] == 'G') &&
+ (arg[1] == 'e' || arg[1] == 'E') &&
+ (arg[2] == 't' || arg[2] == 'T') && arg[3] == '\0')
+ {
+ keys[0].flags = CMD_KEY_RW | CMD_KEY_ACCESS | CMD_KEY_UPDATE;
+ return 1;
+ }
+ }
+
+ keys[0].flags = CMD_KEY_OW | CMD_KEY_UPDATE;
+ return 1;
+}
+
+/* Helper function to extract keys from the BITFIELD command, which may be
+ * read-only if the BITFIELD GET subcommand is used. */
+int bitfieldGetKeys(struct redisCommand *cmd, robj **argv, int argc, getKeysResult *result) {
+ keyReference *keys;
+ UNUSED(cmd);
+
+ keys = getKeysPrepareResult(result, 1);
+ keys[0].pos = 1; /* We always know the position */
+ result->numkeys = 1;
+
+ for (int i = 2; i < argc; i++) {
+ int remargs = argc - i - 1; /* Remaining args other than current. */
+ char *arg = argv[i]->ptr;
+ if (!strcasecmp(arg, "get") && remargs >= 2) {
+ keys[0].flags = CMD_KEY_RO | CMD_KEY_ACCESS;
+ return 1;
+ }
+ }
+
+ keys[0].flags = CMD_KEY_RW | CMD_KEY_ACCESS | CMD_KEY_UPDATE;
+ return 1;
+}