s3-smbldap: make octet_strings/DATA_BLOBs const.
[nivanova/samba-autobuild/.git] / source3 / lib / smbldap.c
index 207f435d284e60f51e53a9c940dc7ec1db769644..fe43237464161095b86e327429047a54a8c63160 100644 (file)
@@ -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, const 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, const 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,
+                                     const 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, const 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