2121
2222static EXTENSION_LOGGER_DESCRIPTOR * mc_logger = NULL ;
2323
24+ static const char * zk_root = "/arcus_acl" ;
2425static 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
2831struct 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+
171227static 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 */
0 commit comments