From a311cc4ec3cecdbaf83ba66985efa82137e37cc0 Mon Sep 17 00:00:00 2001 From: Michael Grunder Date: Wed, 24 Jun 2020 17:00:01 -0700 Subject: Support for Redis 6 ACLs (#1791) Add support for Redis 6 ACLs in the `Redis`, `RedisCluster`, and `RedisArray` classes. On a related note, it adds a mechanism for users to customize how we generate persistent connection IDs such that they can be grouped in different ways depending on the specific use case required (e.g. it would allow connections to be grouped by username, or by user-defined persistent_id, or both). --- cluster_library.c | 67 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 27 deletions(-) (limited to 'cluster_library.c') diff --git a/cluster_library.c b/cluster_library.c index 8d244a43..98ba9c2c 100644 --- a/cluster_library.c +++ b/cluster_library.c @@ -637,9 +637,7 @@ cluster_node_create(redisCluster *c, char *host, size_t host_len, node->sock = redis_sock_create(host, host_len, port, c->timeout, c->read_timeout, c->persistent, NULL, 0); - if (c->flags->auth) { - node->sock->auth = zend_string_copy(c->flags->auth); - } + redis_sock_set_auth(node->sock, c->flags->user, c->flags->pass); return node; } @@ -850,8 +848,8 @@ cluster_free(redisCluster *c, int free_ctx) /* Free any allocated prefix */ if (c->flags->prefix) zend_string_release(c->flags->prefix); - /* Free auth info we've got */ - if (c->flags->auth) zend_string_release(c->flags->auth); + + redis_sock_free_auth(c->flags); efree(c->flags); /* Call hash table destructors */ @@ -1050,10 +1048,8 @@ cluster_init_seeds(redisCluster *cluster, zend_string **seeds, uint32_t nseeds) (unsigned short)atoi(sep+1), cluster->timeout, cluster->read_timeout, cluster->persistent, NULL, 0); - // Set auth information if specified - if (cluster->flags->auth) { - sock->auth = zend_string_copy(cluster->flags->auth); - } + /* Credentials */ + redis_sock_set_auth(sock, cluster->flags->user, cluster->flags->pass); // Index this seed by host/port key_len = snprintf(key, sizeof(key), "%s:%u", ZSTR_VAL(sock->host), @@ -2294,11 +2290,40 @@ cluster_xinfo_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx) add_next_index_zval(&c->multi_resp, &z_ret); } +static void +cluster_acl_custom_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx, + int (*cb)(RedisSock*, zval*, long)) +{ + zval z_ret; + + array_init(&z_ret); + if (cb(c->cmd_sock, &z_ret, c->reply_len) != SUCCESS) { + zval_dtor(&z_ret); + CLUSTER_RETURN_FALSE(c); + } + + if (CLUSTER_IS_ATOMIC(c)) { + RETURN_ZVAL(&z_ret, 0, 1); + } + add_next_index_zval(&c->multi_resp, &z_ret); +} + +PHP_REDIS_API void +cluster_acl_getuser_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx) { + cluster_acl_custom_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, ctx, redis_read_acl_getuser_reply); +} + +PHP_REDIS_API void +cluster_acl_log_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx) { + cluster_acl_custom_resp(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, ctx, redis_read_acl_log_reply); +} + /* MULTI BULK response loop where we might pull the next one */ PHP_REDIS_API zval *cluster_zval_mbulk_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, int pull, mbulk_cb cb, zval *z_ret) { ZVAL_NULL(z_ret); + // Pull our next response if directed if (pull) { if (cluster_check_response(c, &c->reply_type) < 0) @@ -2712,7 +2737,7 @@ void free_seed_array(zend_string **seeds, uint32_t nseeds) { if (seeds == NULL) return; - for (i = 0; i < nseeds; i++) + for (i = 0; i < nseeds; i++) zend_string_release(seeds[i]); efree(seeds); @@ -2771,11 +2796,11 @@ cleanup: /* Validate cluster construction arguments and return a sanitized and validated * array of seeds */ zend_string** -cluster_validate_args(double timeout, double read_timeout, HashTable *seeds, - uint32_t *nseeds, char **errstr) +cluster_validate_args(double timeout, double read_timeout, HashTable *seeds, + uint32_t *nseeds, char **errstr) { zend_string **retval; - + if (timeout < 0L || timeout > INT_MAX) { if (errstr) *errstr = "Invalid timeout"; return NULL; @@ -2862,21 +2887,9 @@ PHP_REDIS_API redisCachedCluster *cluster_cache_load(zend_string *hash) { /* Cache a cluster's slot information in persistent_list if it's enabled */ PHP_REDIS_API int cluster_cache_store(zend_string *hash, HashTable *nodes) { - redisCachedCluster *cc; - - /* Construct our cache */ - cc = cluster_cache_create(hash, nodes); - - /* Set up our resource */ -#if PHP_VERSION_ID < 70300 - zend_resource le; - le.type = le_cluster_slot_cache; - le.ptr = cc; + redisCachedCluster *cc = cluster_cache_create(hash, nodes); - zend_hash_update_mem(&EG(persistent_list), cc->hash, (void*)&le, sizeof(zend_resource)); -#else - zend_register_persistent_resource_ex(cc->hash, cc, le_cluster_slot_cache); -#endif + redis_register_persistent_resource(cc->hash, cc, le_cluster_slot_cache); return SUCCESS; } -- cgit v1.2.3