Skip to content

Commit 3b6d1f5

Browse files
committed
FEATURE: Add config auth_group command
1 parent fed884c commit 3b6d1f5

File tree

5 files changed

+161
-14
lines changed

5 files changed

+161
-14
lines changed

memcached.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9730,6 +9730,30 @@ static void process_config_auth_command(conn *c, token_t *tokens, const size_t n
97309730
out_string(c, "CLIENT_ERROR bad command line format");
97319731
}
97329732
}
9733+
9734+
static void process_config_auth_group_command(conn *c, token_t *tokens, const size_t ntokens)
9735+
{
9736+
assert(c != NULL);
9737+
char *config_val = tokens[SUBCOMMAND_TOKEN+1].value;
9738+
9739+
if (ntokens == 3) {
9740+
char buf[50];
9741+
char *group_name = sasl_get_auth_group();
9742+
if (!group_name) {
9743+
out_string(c, "SERVER_ERROR internal");
9744+
} else {
9745+
sprintf(buf, "auth_group %s\r\nEND", group_name);
9746+
out_string(c, buf);
9747+
free(group_name);
9748+
}
9749+
} else if (ntokens == 4) {
9750+
if (sasl_set_auth_group(config_val) == 0) {
9751+
out_string(c, "END");
9752+
} else {
9753+
out_string(c, "SERVER_ERROR internal");
9754+
}
9755+
}
9756+
}
97339757
#endif
97349758

97359759
static void process_config_command(conn *c, token_t *tokens, const size_t ntokens)
@@ -9810,6 +9834,9 @@ static void process_config_command(conn *c, token_t *tokens, const size_t ntoken
98109834
else if (strcmp(config_key, "auth") == 0) {
98119835
process_config_auth_command(c, tokens, ntokens);
98129836
}
9837+
else if (strcmp(config_key, "auth_group") == 0) {
9838+
process_config_auth_group_command(c, tokens, ntokens);
9839+
}
98139840
#endif
98149841
else {
98159842
print_invalid_command(c, tokens, ntokens);

sasl_auxprop.c

Lines changed: 106 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,16 @@
2121

2222
static EXTENSION_LOGGER_DESCRIPTOR *mc_logger = NULL;
2323

24+
static const char *zk_root = "/arcus_acl";
2425
static const char *ensemble_list;
25-
// 16: buffer for "/arcus_acl", "/" separator, "\0" terminator, etc.
26-
static char group_zpath[16 + GROUP_MAXLEN];
26+
static char g_group_name[GROUP_MAXLEN];
27+
static char new_group_name[GROUP_MAXLEN];
28+
// 16: buffer for zk_root, "/" separator, "\0" terminator, etc.
29+
static char g_group_zpath[16 + GROUP_MAXLEN];
2730

2831
struct sasl_entry {
2932
struct sasl_entry *next;
30-
char key[sizeof(group_zpath) + USERNAME_MAXLEN + PROPNAME_MAXLEN];
33+
char key[16 + GROUP_MAXLEN + USERNAME_MAXLEN + PROPNAME_MAXLEN];
3134
size_t value_len;
3235
char value[];
3336
};
@@ -84,13 +87,13 @@ static void _table_free(struct sasl_entry **table)
8487
free(table);
8588
}
8689

87-
static struct sasl_entry** get_arcus_acl_table(void)
90+
static struct sasl_entry** get_arcus_acl_table(char *group_zpath)
8891
{
8992
struct sasl_entry **table = NULL;
9093
zhandle_t *zh = NULL;
9194
struct String_vector users;
9295
struct String_vector props;
93-
char user_zpath[sizeof(group_zpath) + USERNAME_MAXLEN];
96+
char user_zpath[16 + GROUP_MAXLEN + USERNAME_MAXLEN];
9497
char prop_zpath[sizeof(user_zpath) + PROPNAME_MAXLEN];
9598
char value[VALUE_MAXLEN];
9699
int value_len;
@@ -168,6 +171,59 @@ static struct sasl_entry** get_arcus_acl_table(void)
168171
return table;
169172
}
170173

174+
static int validate_group(char *group_name)
175+
{
176+
char candidate_group_zpath[16 + GROUP_MAXLEN];
177+
snprintf(candidate_group_zpath, sizeof(candidate_group_zpath), "%s/%s", zk_root, group_name);
178+
179+
struct sasl_entry **candidate_table = get_arcus_acl_table(candidate_group_zpath);
180+
if (!candidate_table) {
181+
mc_logger->log(EXTENSION_LOG_WARNING, NULL,
182+
"SECURITY_EVENT ACL group change to %s failed: unable to fetch group data\n", group_name);
183+
return -1;
184+
}
185+
186+
pthread_mutex_lock(&g_sasltable_lock);
187+
int origin_group_zpath_len = strlen(zk_root) + strlen(g_group_name) + 2;
188+
for (int i = 0; i < SASL_TABLE_SIZE; i++) {
189+
struct sasl_entry *old_entry = g_sasltable[i];
190+
while (old_entry) {
191+
char new_key[16 + GROUP_MAXLEN + USERNAME_MAXLEN + PROPNAME_MAXLEN];
192+
snprintf(new_key, sizeof(new_key), "%s/%s",
193+
candidate_group_zpath, old_entry->key + origin_group_zpath_len);
194+
struct sasl_entry *new_entry = candidate_table[hash_function(new_key) % SASL_TABLE_SIZE];
195+
bool found = false;
196+
while (new_entry) {
197+
if (strcmp(new_entry->key, new_key) == 0 &&
198+
new_entry->value_len == old_entry->value_len &&
199+
memcmp(new_entry->value, old_entry->value, old_entry->value_len) == 0) {
200+
found = true;
201+
break;
202+
}
203+
new_entry = new_entry->next;
204+
}
205+
if (!found) {
206+
mc_logger->log(EXTENSION_LOG_WARNING, NULL,
207+
"SECURITY_EVENT ACL group change to %s failed: missing key %s\n",
208+
group_name, old_entry->key);
209+
pthread_mutex_unlock(&g_sasltable_lock);
210+
_table_free(candidate_table);
211+
return -1;
212+
}
213+
old_entry = old_entry->next;
214+
}
215+
}
216+
217+
struct sasl_entry **old_table = g_sasltable;
218+
g_sasltable = candidate_table;
219+
snprintf(g_group_name, sizeof(g_group_name), "%s", group_name);
220+
snprintf(g_group_zpath, sizeof(g_group_zpath), "%s", candidate_group_zpath);
221+
pthread_mutex_unlock(&g_sasltable_lock);
222+
223+
_table_free(old_table);
224+
return 0;
225+
}
226+
171227
static void* acl_refresh_thread(void *arg)
172228
{
173229
struct timespec ts;
@@ -193,7 +249,22 @@ static void* acl_refresh_thread(void *arg)
193249
}
194250

195251
mc_logger->log(EXTENSION_LOG_INFO, NULL, "ACL refresh started.\n");
196-
new_table = get_arcus_acl_table();
252+
253+
pthread_mutex_lock(&acl_thread_lock);
254+
bool update_req = new_group_name[0] != '\0';
255+
pthread_mutex_unlock(&acl_thread_lock);
256+
if (update_req) {
257+
int ret = validate_group(new_group_name);
258+
pthread_mutex_lock(&acl_thread_lock);
259+
new_group_name[0] = '\0';
260+
pthread_mutex_unlock(&acl_thread_lock);
261+
if (ret == 0) {
262+
mc_logger->log(EXTENSION_LOG_INFO, NULL, "SECURITY_EVENT ACL group changed to: %s\n", g_group_name);
263+
continue;
264+
}
265+
}
266+
267+
new_table = get_arcus_acl_table(g_group_zpath);
197268
if (new_table != NULL) {
198269
pthread_mutex_lock(&g_sasltable_lock);
199270
old_table = g_sasltable;
@@ -223,18 +294,18 @@ static int _arcus_getdata(const char *user,
223294
char *out, const size_t max_out,
224295
size_t *out_len)
225296
{
226-
char key[sizeof(group_zpath) + USERNAME_MAXLEN + PROPNAME_MAXLEN];
297+
char key[sizeof(g_group_zpath) + USERNAME_MAXLEN + PROPNAME_MAXLEN];
298+
pthread_mutex_lock(&g_sasltable_lock);
227299
if (propName) {
228-
snprintf(key, sizeof(key), "%s/%s/%s", group_zpath, user, propName);
300+
snprintf(key, sizeof(key), "%s/%s/%s", g_group_zpath, user, propName);
229301
} else {
230-
snprintf(key, sizeof(key), "%s/%s", group_zpath, user);
302+
snprintf(key, sizeof(key), "%s/%s", g_group_zpath, user);
231303
}
232304

233305
int ret = SASL_NOUSER;
234306
unsigned long index = hash_function(key) % SASL_TABLE_SIZE;
235307
struct sasl_entry *entry;
236308

237-
pthread_mutex_lock(&g_sasltable_lock);
238309
if (g_sasltable) {
239310
entry = g_sasltable[index];
240311
while (entry) {
@@ -395,9 +466,10 @@ int arcus_auxprop_plug_init(const sasl_utils_t *utils,
395466
mc_logger->log(EXTENSION_LOG_WARNING, NULL, "ARCUS_ACL_GROUP environment is not set\n");
396467
return SASL_FAIL;
397468
}
398-
snprintf(group_zpath, sizeof(group_zpath), "/arcus_acl/%s", acl_group);
469+
snprintf(g_group_name, sizeof(g_group_name), "%s", acl_group);
470+
snprintf(g_group_zpath, sizeof(g_group_zpath), "%s/%s", zk_root, acl_group);
399471

400-
g_sasltable = get_arcus_acl_table();
472+
g_sasltable = get_arcus_acl_table(g_group_zpath);
401473
if (!g_sasltable) {
402474
mc_logger->log(EXTENSION_LOG_WARNING, NULL, "Failed to initialize SASL table\n");
403475
return SASL_FAIL;
@@ -428,5 +500,27 @@ void arcus_auxprop_wakeup(void)
428500
pthread_mutex_unlock(&acl_thread_lock);
429501
}
430502

503+
char *arcus_auxprop_get_group(void)
504+
{
505+
char *ret;
506+
pthread_mutex_lock(&g_sasltable_lock);
507+
ret = strdup(g_group_name);
508+
pthread_mutex_unlock(&g_sasltable_lock);
509+
return ret;
510+
}
511+
512+
int arcus_auxprop_set_group(char *group_name)
513+
{
514+
int ret = -1;
515+
pthread_mutex_lock(&acl_thread_lock);
516+
if (new_group_name[0] == '\0') {
517+
snprintf(new_group_name, sizeof(new_group_name), "%s", group_name);
518+
ret = 0;
519+
}
520+
pthread_cond_signal(&acl_thread_cond);
521+
pthread_mutex_unlock(&acl_thread_lock);
522+
return ret;
523+
}
524+
431525
#endif /* ENABLE_ZK_INTEGRATION */
432526
#endif /* ENABLE_SASL */

sasl_auxprop.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ int arcus_auxprop_plug_init(const sasl_utils_t *utils,
2020
int arcus_getdata(const char *user, char *out, const size_t max_out);
2121

2222
void arcus_auxprop_wakeup(void);
23+
char *arcus_auxprop_get_group(void);
24+
int arcus_auxprop_set_group(char *group_name);
2325

2426
#endif /* ENABLE_ZK_INTEGRATION */
2527
#endif /* ENABLE_SASL */

sasl_defs.c

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
#include <string.h>
88
#include "sasl_auxprop.h"
99

10+
#if defined(ENABLE_SASL) && defined(ENABLE_ZK_INTEGRATION)
11+
static bool use_acl_zookeeper = false;
12+
#endif
13+
1014
const char *sasl_engine_string(void)
1115
{
1216
#if defined(ENABLE_SASL)
@@ -31,10 +35,26 @@ void sasl_get_auth_data(sasl_conn_t *conn, auth_data_t *data)
3135
#endif
3236
}
3337
}
38+
39+
char *sasl_get_auth_group(void)
40+
{
41+
#ifdef ENABLE_ZK_INTEGRATION
42+
if (use_acl_zookeeper) {
43+
return arcus_auxprop_get_group();
44+
}
3445
#endif
46+
return NULL;
47+
}
3548

36-
#if defined(ENABLE_SASL) && defined(ENABLE_ZK_INTEGRATION)
37-
static bool use_acl_zookeeper = false;
49+
int sasl_set_auth_group(char *group_name)
50+
{
51+
#ifdef ENABLE_ZK_INTEGRATION
52+
if (use_acl_zookeeper) {
53+
return arcus_auxprop_set_group(group_name);
54+
}
55+
#endif
56+
return -1;
57+
}
3858
#endif
3959

4060
#ifdef ENABLE_SASL_PWDB

sasl_defs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ int init_sasl(EXTENSION_LOGGER_DESCRIPTOR *logger);
1515
void shutdown_sasl(void);
1616
int reload_sasl(void);
1717
void sasl_get_auth_data(sasl_conn_t *conn, auth_data_t *data);
18+
char *sasl_get_auth_group(void);
19+
int sasl_set_auth_group(char *group_name);
1820

1921

2022
#elif defined(ENABLE_ISASL)
@@ -27,6 +29,8 @@ int init_sasl(EXTENSION_LOGGER_DESCRIPTOR *logger);
2729
void shutdown_sasl(void);
2830
int reload_sasl(void);
2931
void sasl_get_auth_data(sasl_conn_t *conn, auth_data_t *data);
32+
char *sasl_get_auth_group(void);
33+
int sasl_set_auth_group(char *group_name);
3034

3135
#endif /* End of SASL support */
3236

0 commit comments

Comments
 (0)