diff options
Diffstat (limited to 'source3/lib')
| -rw-r--r-- | source3/lib/smbldap.c | 112 | 
1 files changed, 91 insertions, 21 deletions
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   | 
