diff options
| author | Nathan Kinder <nkinder@redhat.com> | 2007-08-30 15:56:36 +0000 |
|---|---|---|
| committer | Nathan Kinder <nkinder@redhat.com> | 2007-08-30 15:56:36 +0000 |
| commit | 40ea59e4c2e81ce665d8c09f0104be1378de901d (patch) | |
| tree | 77a67bb3801da2a53ad2149449124fd2c210e8a6 | |
| parent | 912b102e56a44bafe00fa75ed81fc6fb7d3b6903 (diff) | |
| download | ds-40ea59e4c2e81ce665d8c09f0104be1378de901d.tar.gz ds-40ea59e4c2e81ce665d8c09f0104be1378de901d.tar.xz ds-40ea59e4c2e81ce665d8c09f0104be1378de901d.zip | |
Resolves: 212671
Summary: Handle syncing multi-valued street attribute to AD.
| -rw-r--r-- | ldap/servers/plugins/replication/windows_protocol_util.c | 86 | ||||
| -rw-r--r-- | ldap/servers/slapd/attr.c | 15 | ||||
| -rw-r--r-- | ldap/servers/slapd/slapi-plugin.h | 1 |
3 files changed, 99 insertions, 3 deletions
diff --git a/ldap/servers/plugins/replication/windows_protocol_util.c b/ldap/servers/plugins/replication/windows_protocol_util.c index e1b3d669..573ee587 100644 --- a/ldap/servers/plugins/replication/windows_protocol_util.c +++ b/ldap/servers/plugins/replication/windows_protocol_util.c @@ -1363,7 +1363,41 @@ windows_create_remote_entry(Private_Repl_Protocol *prp,Slapi_Entry *original_ent } } else { - slapi_entry_add_valueset(new_entry,new_type,vs); + Slapi_Attr *new_attr = NULL; + + /* AD treats streetAddress as a single-valued attribute, while we define it + * as a multi-valued attribute as it's defined in rfc 4519. We only + * sync the first value to AD to avoid a constraint violation. + */ + if (0 == slapi_attr_type_cmp(new_type, "streetAddress", SLAPI_TYPE_CMP_SUBTYPE)) { + if (slapi_valueset_count(vs) > 1) { + int i = 0; + const char *street_value = NULL; + Slapi_Value *value = NULL; + Slapi_Value *new_value = NULL; + + i = slapi_valueset_first_value(vs,&value); + if (i >= 0) { + /* Dup the first value, trash the valueset, then copy + * in the dup'd value. */ + new_value = slapi_value_dup(value); + slapi_valueset_done(vs); + /* The below hands off the memory to the valueset */ + slapi_valueset_add_value_ext(vs, new_value, SLAPI_VALUE_FLAG_PASSIN); + } + } + } + + slapi_entry_add_valueset(new_entry,type,vs); + + /* Reset the type to new_type here. This is needed since + * slapi_entry_add_valueset will create the Slapi_Attrs using + * the schema definition, which can reset the type to something + * other than the type you pass into it. To be safe, we just + * create the attributes with the old type, then reset them. */ + if (slapi_entry_attr_find(new_entry, type, &new_attr) == 0) { + slapi_attr_set_type(new_attr, new_type); + } } slapi_ch_free((void**)&new_type); } @@ -1574,6 +1608,29 @@ windows_map_mods_for_replay(Private_Repl_Protocol *prp,LDAPMod **original_mods, slapi_valueset_free(vs); } else { + /* AD treats streetAddress as a single-valued attribute, while we define it + * as a multi-valued attribute as it's defined in rfc 4519. We only + * sync the first value to AD to avoid a constraint violation. + */ + if (0 == slapi_attr_type_cmp(mapped_type, "streetAddress", SLAPI_TYPE_CMP_SUBTYPE)) { + Slapi_Mod smod; + struct berval *new_bval = NULL; + + slapi_mod_init_byref(&smod,mod); + + /* Check if there is more than one value */ + if (slapi_mod_get_num_values(&smod) > 1) { + new_bval = slapi_mod_get_first_value(&smod); + /* Remove all values except for the first */ + while (slapi_mod_get_next_value(&smod)) { + /* This modifies the bvalues in the mod itself */ + slapi_mod_remove_value(&smod); + } + } + + slapi_mod_done(&smod); + } + slapi_mods_add_modbvps(&mapped_smods,mod->mod_op,mapped_type,mod->mod_bvalues); } slapi_ch_free((void**)&mapped_type); @@ -1668,6 +1725,28 @@ attr_compare_equal(Slapi_Attr *a, Slapi_Attr *b, int n) return match; } +/* Returns non-zero if all of the values of attribute a are contained in attribute b. */ +static int +attr_compare_present(Slapi_Attr *a, Slapi_Attr *b) +{ + int match = 1; + int i = 0; + Slapi_Value *va = NULL; + + /* Iterate through values in attr a and search for each in attr b */ + for (i = slapi_attr_first_value(a, &va); va && (i != -1); + i = slapi_attr_next_value(a, i, &va)) { + if (slapi_attr_value_find(b, slapi_value_get_berval(va)) != 0) { + /* This value wasn't found, so stop checking for values */ + match = 0; + break; + } + } + + return match; +} + + /* Helper functions for dirsync result processing */ /* Is this entry a tombstone ? */ @@ -2669,8 +2748,11 @@ windows_generate_update_mods(Private_Repl_Protocol *prp,Slapi_Entry *remote_entr /* AD has a legth contraint on the initials attribute, * so treat is as a special case. */ - if (0 == slapi_attr_type_cmp(type,"initials",SLAPI_TYPE_CMP_SUBTYPE) && !to_windows) { + if (0 == slapi_attr_type_cmp(type, "initials", SLAPI_TYPE_CMP_SUBTYPE) && !to_windows) { values_equal = attr_compare_equal(attr, local_attr, AD_INITIALS_LENGTH); + } else if (0 == slapi_attr_type_cmp(type, FAKE_STREET_ATTR_NAME, SLAPI_TYPE_CMP_SUBTYPE) && !to_windows) { + /* Need to check if attr is present in local_attr */ + values_equal = attr_compare_present(attr, local_attr); } else { /* Compare the entire attribute values */ values_equal = attr_compare_equal(attr, local_attr, 0); diff --git a/ldap/servers/slapd/attr.c b/ldap/servers/slapd/attr.c index 7cd5a2f5..e6b32d42 100644 --- a/ldap/servers/slapd/attr.c +++ b/ldap/servers/slapd/attr.c @@ -699,7 +699,20 @@ slapi_attr_add_value(Slapi_Attr *a, const Slapi_Value *v) return 0; } -/* Make the valuset in SLapi_Attr be *vs--not a copy */ +int +slapi_attr_set_type(Slapi_Attr *a, const char *type) +{ + int rc = 0; + + if((NULL == a) || (NULL == type)) { + rc = -1; + } else { + a->a_type = slapi_ch_strdup(type); + } + return rc; +} + +/* Make the valuset in Slapi_Attr be *vs--not a copy */ int slapi_attr_set_valueset(Slapi_Attr *a, const Slapi_ValueSet *vs) { diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h index c624b38c..30f581b6 100644 --- a/ldap/servers/slapd/slapi-plugin.h +++ b/ldap/servers/slapd/slapi-plugin.h @@ -418,6 +418,7 @@ int slapi_attr_get_numvalues( const Slapi_Attr *a, int *numValues); int slapi_attr_get_valueset(const Slapi_Attr *a, Slapi_ValueSet **vs); /* Make the valuset in Slapi_Attr be *vs--not a copy */ int slapi_attr_set_valueset(Slapi_Attr *a, const Slapi_ValueSet *vs); +int slapi_attr_set_type(Slapi_Attr *a, const char *type); int slapi_attr_get_bervals_copy( Slapi_Attr *a, struct berval ***vals ); char * slapi_attr_syntax_normalize( const char *s ); void slapi_valueset_set_valueset(Slapi_ValueSet *vs1, const Slapi_ValueSet *vs2); |
