From db3de3f6ffca405c616ae9f9104e82d5a95f4b3b Mon Sep 17 00:00:00 2001 From: Ludwig Krispenz Date: Dec 17 2013 19:27:27 +0000 Subject: Ticket 47621 - v2 make referential integrity configuration more flexible Bug Description: Request to make entry scope multivalued and to define exclusion scope Fix Description: The fix makes the configuration parameters nsslapd-pluginEntryScope: multivalued and adds nsslapd-pluginExcludeEntryScope: The logic implemented is specified in: http://port389.org/wiki/Configuring_scope_for_referential_integrity_plugin https://fedorahosted.org/389/ticket/47621 Reviewed by: richm, thanks (cherry picked from commit 16dc94f11e644e8829817489e92f814757058b82) --- diff --git a/ldap/servers/plugins/referint/referint.c b/ldap/servers/plugins/referint/referint.c index 252ff16..cd8a967 100644 --- a/ldap/servers/plugins/referint/referint.c +++ b/ldap/servers/plugins/referint/referint.c @@ -91,7 +91,8 @@ static int refint_started = 0; static Slapi_PluginDesc pdesc = { "referint", VENDOR, DS_PACKAGE_VERSION, "referential integrity plugin" }; static int allow_repl = 0; -static Slapi_DN *plugin_EntryScope = NULL; +static Slapi_DN **plugin_EntryScope = NULL; +static Slapi_DN *plugin_ExcludeEntryScope = NULL; static Slapi_DN *plugin_ContainerScope = NULL; static void* referint_plugin_identity = NULL; @@ -158,32 +159,54 @@ referint_postop_init( Slapi_PBlock *pb ) } if(plugin_entry){ char *plugin_attr_value; + char **plugin_attr_values; plugin_attr_value = slapi_entry_attr_get_charptr(plugin_entry, "nsslapd-pluginAllowReplUpdates"); if(plugin_attr_value && strcasecmp(plugin_attr_value,"on")==0){ allow_repl = 1; } slapi_ch_free_string(&plugin_attr_value); - plugin_attr_value = slapi_entry_attr_get_charptr(plugin_entry, "nsslapd-pluginEntryScope"); - if(plugin_attr_value) { - if (slapi_dn_syntax_check(NULL, plugin_attr_value, 1) == 1) { - slapi_log_error(SLAPI_LOG_FATAL, REFERINT_PLUGIN_SUBSYSTEM, - "Error: Ignoring invalid DN used as plugin entry scope: [%s]\n", - plugin_attr_value); - } else { - plugin_EntryScope = slapi_sdn_new_dn_byref(plugin_attr_value); + + plugin_attr_values = slapi_entry_attr_get_charray(plugin_entry, "nsslapd-pluginEntryScope"); + if(plugin_attr_values) { + int i,j=0;; + for (i=0; plugin_attr_values[i];i++); + plugin_EntryScope = (Slapi_DN **)slapi_ch_calloc(sizeof(Slapi_DN *),i+1); + for (i=0; plugin_attr_values[i];i++) { + if (slapi_dn_syntax_check(NULL, plugin_attr_values[i], 1) == 1) { + slapi_log_error(SLAPI_LOG_FATAL, REFERINT_PLUGIN_SUBSYSTEM, + "Error: Ignoring invalid DN used as plugin entry scope: [%s]\n", + plugin_attr_values[i]); + slapi_ch_free_string(&plugin_attr_values[i]); + } else { + plugin_EntryScope[j++] = slapi_sdn_new_dn_passin(plugin_attr_values[i]); + } } - } + slapi_ch_free((void**)&plugin_attr_values); + } + plugin_attr_value = slapi_entry_attr_get_charptr(plugin_entry, "nsslapd-pluginExcludeEntryScope"); + if(plugin_attr_value) { + if (slapi_dn_syntax_check(NULL, plugin_attr_value, 1) == 1) { + slapi_log_error(SLAPI_LOG_FATAL, REFERINT_PLUGIN_SUBSYSTEM, + "Error: Ignoring invalid DN used as plugin exclude entry scope: [%s]\n", + plugin_attr_value); + slapi_ch_free_string(&plugin_attr_value); + } else { + plugin_ExcludeEntryScope = slapi_sdn_new_dn_passin(plugin_attr_value); + } + } + plugin_attr_value = slapi_entry_attr_get_charptr(plugin_entry, "nsslapd-pluginContainerScope"); if(plugin_attr_value) { - if (slapi_dn_syntax_check(NULL, plugin_attr_value, 1) == 1) { - slapi_log_error(SLAPI_LOG_FATAL, REFERINT_PLUGIN_SUBSYSTEM, - "Error: Ignoring invalid DN used as plugin container scope: [%s]\n", - plugin_attr_value); - } else { - plugin_ContainerScope = slapi_sdn_new_dn_byref(plugin_attr_value); - } - } + if (slapi_dn_syntax_check(NULL, plugin_attr_value, 1) == 1) { + slapi_log_error(SLAPI_LOG_FATAL, REFERINT_PLUGIN_SUBSYSTEM, + "Error: Ignoring invalid DN used as plugin container scope: [%s]\n", + plugin_attr_value); + slapi_ch_free_string(&plugin_attr_value); + } else { + plugin_ContainerScope = slapi_sdn_new_dn_passin(plugin_attr_value); + } + } } slapi_ch_free_string(&plugin_type); @@ -203,6 +226,42 @@ referint_postop_init( Slapi_PBlock *pb ) int +referint_sdn_in_container_scope(Slapi_DN *sdn) +{ + if (plugin_ContainerScope == NULL) { + return(1); + } else { + return(slapi_sdn_issuffix(sdn, plugin_ContainerScope)); + } +} + +int +referint_sdn_in_entry_scope(Slapi_DN *sdn) +{ + int rc = 0; + + if (plugin_ExcludeEntryScope && slapi_sdn_issuffix(sdn, plugin_ExcludeEntryScope)) + return (0); + + if (plugin_EntryScope == NULL) { + /* no scope defined, all sdns match */ + return(1); + } else { + int i = 0; + while (plugin_EntryScope[i]) { + if (slapi_sdn_issuffix(sdn, plugin_EntryScope[i]) ) { + rc = 1; + break; + } else { + i++; + } + } + } + + return (rc); +} + +int referint_postop_del( Slapi_PBlock *pb ) { Slapi_DN *sdn = NULL; @@ -264,9 +323,9 @@ referint_postop_del( Slapi_PBlock *pb ) rc = SLAPI_PLUGIN_SUCCESS; } else if(delay == 0){ /* no delay */ /* call function to update references to entry */ - if (plugin_EntryScope && slapi_sdn_issuffix(sdn, plugin_EntryScope)) { - rc = update_integrity(argv, sdn, NULL, NULL, logChanges); - } + if (referint_sdn_in_entry_scope(sdn)) { + rc = update_integrity(argv, sdn, NULL, NULL, logChanges); + } } else { /* write the entry to integrity log */ writeintegritylog(pb, argv[1], sdn, NULL, NULL, NULL /* slapi_get_requestor_sdn(pb) */); @@ -346,22 +405,24 @@ referint_postop_modrdn( Slapi_PBlock *pb ) rc = SLAPI_PLUGIN_SUCCESS; } else if(delay == 0){ /* no delay */ /* call function to update references to entry */ - if (!plugin_EntryScope) { - /* no scope definde, default always process refint */ + if (!plugin_EntryScope && !plugin_ExcludeEntryScope) { + /* no scope defined, default always process referint */ rc = update_integrity(argv, sdn, newrdn, newsuperior, logChanges); - } else { - const char *newsuperiordn = slapi_sdn_get_dn(newsuperior); - if ( (newsuperiordn == NULL && slapi_sdn_issuffix(sdn, plugin_EntryScope)) || - ( newsuperiordn && slapi_sdn_issuffix(newsuperior, plugin_EntryScope))) { - /* it is a modrdn inside the scope or into the scope, + } else { + const char *newsuperiordn = slapi_sdn_get_dn(newsuperior); + if ( (newsuperiordn == NULL && referint_sdn_in_entry_scope(sdn)) || + ( newsuperiordn && referint_sdn_in_entry_scope(newsuperior))) + { + /* + * It is a modrdn inside the scope or into the scope, * process normal modrdn */ rc = update_integrity(argv, sdn, newrdn, newsuperior, logChanges); - } else if (slapi_sdn_issuffix(sdn, plugin_EntryScope)) { - /* the entry is moved out of scope, treat as delete */ + } else if (referint_sdn_in_entry_scope(sdn)) { + /* the entry is moved out of scope, treat as delete */ rc = update_integrity(argv, sdn, NULL, NULL, logChanges); + } } - } } else { /* write the entry to integrity log */ writeintegritylog(pb, argv[1], sdn, newrdn, newsuperior, NULL /* slapi_get_requestor_sdn(pb) */); @@ -1181,9 +1242,8 @@ writeintegritylog(Slapi_PBlock *pb, char *logfilename, Slapi_DN *sdn, const char *newsuperiordn = NULL; size_t reqdn_len = 0; - if (plugin_EntryScope && - !(slapi_sdn_issuffix(sdn, plugin_EntryScope) || - (newsuperior && slapi_sdn_issuffix(newsuperior, plugin_EntryScope)))) { + if (!(referint_sdn_in_entry_scope(sdn) || + (newsuperior && referint_sdn_in_entry_scope(newsuperior)))) { return; } /* @@ -1211,8 +1271,8 @@ writeintegritylog(Slapi_PBlock *pb, char *logfilename, Slapi_DN *sdn, len_to_write = slapi_sdn_get_ndn_len(sdn) + 5; newsuperiordn = slapi_sdn_get_dn(newsuperior); - if (plugin_EntryScope && newsuperiordn && - !slapi_sdn_issuffix(newsuperior, plugin_EntryScope)) { + if (newsuperiordn && + !referint_sdn_in_entry_scope(newsuperior)) { /* this is a modrdn which moves the entry out of scope, handle like a delete */ newsuperiordn = NULL; newrdn = NULL;