summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/smbldap.h4
-rw-r--r--source3/lib/smbldap.c112
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