From c4974eec01d32f2c777aa3fca02210bb6c255d79 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 29 Oct 2009 23:36:14 +0100 Subject: s3-smbldap: support storing octet_strings/DATA_BLOBs. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner --- source3/lib/smbldap.c | 112 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 91 insertions(+), 21 deletions(-) (limited to 'source3/lib/smbldap.c') diff --git a/source3/lib/smbldap.c b/source3/lib/smbldap.c index 207f435d284..4c11ced0c2d 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 -- cgit