diff options
-rw-r--r-- | source3/include/smbldap.h | 4 | ||||
-rw-r--r-- | source3/lib/smbldap.c | 112 |
2 files changed, 95 insertions, 21 deletions
diff --git a/source3/include/smbldap.h b/source3/include/smbldap.h index 5be9a92bf6..ed1af0b2d9 100644 --- a/source3/include/smbldap.h +++ b/source3/include/smbldap.h @@ -138,9 +138,13 @@ NTSTATUS smbldap_init(TALLOC_CTX *mem_ctx, const char* get_attr_key2string( ATTRIB_MAP_ENTRY table[], int key ); const char** get_attr_list( TALLOC_CTX *mem_ctx, ATTRIB_MAP_ENTRY table[] ); void smbldap_set_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value); +void smbldap_set_mod_blob(LDAPMod *** modlist, int modop, const char *attribute, DATA_BLOB *newblob); void smbldap_make_mod(LDAP *ldap_struct, LDAPMessage *existing, LDAPMod ***mods, const char *attribute, const char *newval); +void smbldap_make_mod_blob(LDAP *ldap_struct, LDAPMessage *existing, + LDAPMod ***mods, + const char *attribute, DATA_BLOB *newblob); bool smbldap_get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry, const char *attribute, char *value, int max_len); diff --git a/source3/lib/smbldap.c b/source3/lib/smbldap.c index 207f435d28..4c11ced0c2 100644 --- a/source3/lib/smbldap.c +++ b/source3/lib/smbldap.c @@ -506,7 +506,7 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = { manage memory used by the array, by each struct, and values ***********************************************************************/ - void smbldap_set_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value) +static void smbldap_set_mod_internal(LDAPMod *** modlist, int modop, const char *attribute, const char *value, DATA_BLOB *blob) { LDAPMod **mods; int i; @@ -557,7 +557,27 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = { mods[i + 1] = NULL; } - if (value != NULL) { + if (blob && (modop & LDAP_MOD_BVALUES)) { + j = 0; + if (mods[i]->mod_bvalues != NULL) { + for (; mods[i]->mod_bvalues[j] != NULL; j++); + } + mods[i]->mod_bvalues = SMB_REALLOC_ARRAY(mods[i]->mod_bvalues, struct berval *, j + 2); + + if (mods[i]->mod_bvalues == NULL) { + smb_panic("smbldap_set_mod: out of memory!"); + /* notreached. */ + } + + mods[i]->mod_bvalues[j] = SMB_MALLOC_P(struct berval); + SMB_ASSERT(mods[i]->mod_bvalues[j] != NULL); + + mods[i]->mod_bvalues[j]->bv_val = (char *)memdup(blob->data, blob->length); + SMB_ASSERT(mods[i]->mod_bvalues[j]->bv_val != NULL); + mods[i]->mod_bvalues[j]->bv_len = blob->length; + + mods[i]->mod_bvalues[j + 1] = NULL; + } else if (value != NULL) { char *utf8_value = NULL; size_t converted_size; @@ -586,17 +606,30 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = { *modlist = mods; } + void smbldap_set_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value) +{ + smbldap_set_mod_internal(modlist, modop, attribute, value, NULL); +} + + void smbldap_set_mod_blob(LDAPMod *** modlist, int modop, const char *attribute, DATA_BLOB *value) +{ + smbldap_set_mod_internal(modlist, modop | LDAP_MOD_BVALUES, attribute, NULL, value); +} + /********************************************************************** Set attribute to newval in LDAP, regardless of what value the attribute had in LDAP before. *********************************************************************/ - void smbldap_make_mod(LDAP *ldap_struct, LDAPMessage *existing, - LDAPMod ***mods, - const char *attribute, const char *newval) +static void smbldap_make_mod_internal(LDAP *ldap_struct, LDAPMessage *existing, + LDAPMod ***mods, + const char *attribute, int op, + const char *newval, + DATA_BLOB *newblob) { char oldval[2048]; /* current largest allowed value is mungeddial */ bool existed; + DATA_BLOB oldblob = data_blob_null; if (attribute == NULL) { /* This can actually happen for ldapsam_compat where we for @@ -605,24 +638,33 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = { } if (existing != NULL) { - existed = smbldap_get_single_attribute(ldap_struct, existing, attribute, oldval, sizeof(oldval)); + if (op & LDAP_MOD_BVALUES) { + existed = smbldap_talloc_single_blob(talloc_tos(), ldap_struct, existing, attribute, &oldblob); + } else { + existed = smbldap_get_single_attribute(ldap_struct, existing, attribute, oldval, sizeof(oldval)); + } } else { existed = False; *oldval = '\0'; } - /* all of our string attributes are case insensitive */ - - if (existed && newval && (StrCaseCmp(oldval, newval) == 0)) { + if (existed) { + bool equal = false; + if (op & LDAP_MOD_BVALUES) { + equal = (newblob && (data_blob_cmp(&oldblob, newblob) == 0)); + } else { + /* all of our string attributes are case insensitive */ + equal = (newval && (StrCaseCmp(oldval, newval) == 0)); + } - /* Believe it or not, but LDAP will deny a delete and - an add at the same time if the values are the - same... */ - DEBUG(10,("smbldap_make_mod: attribute |%s| not changed.\n", attribute)); - return; - } + if (equal) { + /* Believe it or not, but LDAP will deny a delete and + an add at the same time if the values are the + same... */ + DEBUG(10,("smbldap_make_mod: attribute |%s| not changed.\n", attribute)); + return; + } - if (existed) { /* There has been no value before, so don't delete it. * Here's a possible race: We might end up with * duplicate attributes */ @@ -634,20 +676,48 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = { * in Novell NDS. In NDS you have to first remove attribute and then * you could add new value */ - DEBUG(10,("smbldap_make_mod: deleting attribute |%s| values |%s|\n", attribute, oldval)); - smbldap_set_mod(mods, LDAP_MOD_DELETE, attribute, oldval); + if (op & LDAP_MOD_BVALUES) { + DEBUG(10,("smbldap_make_mod: deleting attribute |%s| blob\n", attribute)); + smbldap_set_mod_blob(mods, LDAP_MOD_DELETE, attribute, &oldblob); + } else { + DEBUG(10,("smbldap_make_mod: deleting attribute |%s| values |%s|\n", attribute, oldval)); + smbldap_set_mod(mods, LDAP_MOD_DELETE, attribute, oldval); + } } /* Regardless of the real operation (add or modify) we add the new value here. We rely on deleting the old value, should it exist. */ - if ((newval != NULL) && (strlen(newval) > 0)) { - DEBUG(10,("smbldap_make_mod: adding attribute |%s| value |%s|\n", attribute, newval)); - smbldap_set_mod(mods, LDAP_MOD_ADD, attribute, newval); + if (op & LDAP_MOD_BVALUES) { + if (newblob && newblob->length) { + DEBUG(10,("smbldap_make_mod: adding attribute |%s| blob\n", attribute)); + smbldap_set_mod_blob(mods, LDAP_MOD_ADD, attribute, newblob); + } + } else { + if ((newval != NULL) && (strlen(newval) > 0)) { + DEBUG(10,("smbldap_make_mod: adding attribute |%s| value |%s|\n", attribute, newval)); + smbldap_set_mod(mods, LDAP_MOD_ADD, attribute, newval); + } } } + void smbldap_make_mod(LDAP *ldap_struct, LDAPMessage *existing, + LDAPMod ***mods, + const char *attribute, const char *newval) +{ + smbldap_make_mod_internal(ldap_struct, existing, mods, attribute, + 0, newval, NULL); +} + + void smbldap_make_mod_blob(LDAP *ldap_struct, LDAPMessage *existing, + LDAPMod ***mods, + const char *attribute, DATA_BLOB *newblob) +{ + smbldap_make_mod_internal(ldap_struct, existing, mods, attribute, + LDAP_MOD_BVALUES, NULL, newblob); +} + /********************************************************************** Some varients of the LDAP rebind code do not pass in the third 'arg' pointer to a void*, so we try and work around it by assuming that the |