r23737: Validate that we object to duplicate values in an add or replace.
authorAndrew Bartlett <abartlet@samba.org>
Sat, 7 Jul 2007 04:34:36 +0000 (04:34 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 19:59:09 +0000 (14:59 -0500)
We can't ever allow duplicates, even if the client sends them

Andrew Bartlett
(This used to be commit 10277f27246b9e16ed36fb72eb4c318b43cb9395)

source4/lib/ldb/ldb_tdb/ldb_tdb.c
testprogs/ejs/ldap.js

index b8e2ec6191d70716810088dc040e2afce9170dc0..6dff3942a87f5f56d39f68f2d7e3d503a37c6f66 100644 (file)
@@ -591,7 +591,7 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms
        TDB_DATA tdb_key, tdb_data;
        struct ldb_message *msg2;
        unsigned i, j;
-       int ret;
+       int ret, idx;
 
        tdb_key = ltdb_key(module, msg->dn);
        if (!tdb_key.dptr) {
@@ -631,9 +631,9 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms
                case LDB_FLAG_MOD_ADD:
                        /* add this element to the message. fail if it
                           already exists */
-                       ret = find_element(msg2, el->name);
+                       idx = find_element(msg2, el->name);
 
-                       if (ret == -1) {
+                       if (idx == -1) {
                                if (msg_add_element(ldb, msg2, el) != 0) {
                                        ret = LDB_ERR_OTHER;
                                        goto failed;
@@ -641,14 +641,21 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms
                                continue;
                        }
 
-                       el2 = &msg2->elements[ret];
+                       el2 = &msg2->elements[idx];
 
-                       /* An attribute with this name already exists, add all
-                        * values if they don't already exist. */
+                       /* An attribute with this name already exists,
+                        * add all values if they don't already exist
+                        * (check both the other elements to be added,
+                        * and those already in the db). */
 
                        for (j=0;j<el->num_values;j++) {
                                if (ldb_msg_find_val(el2, &el->values[j])) {
-                                       ldb_set_errstring(module->ldb, "Type or value exists");
+                                       ldb_asprintf_errstring(module->ldb, "%s: value #%d already exists", el->name, j);
+                                       ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
+                                       goto failed;
+                               }
+                               if (ldb_msg_find_val(el, &el->values[j]) != &el->values[j]) {
+                                       ldb_asprintf_errstring(module->ldb, "%s: value #%d provided more than once", el->name, j);
                                        ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
                                        goto failed;
                                }
@@ -675,11 +682,19 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms
                case LDB_FLAG_MOD_REPLACE:
                        /* replace all elements of this attribute name with the elements
                           listed. The attribute not existing is not an error */
-                       msg_delete_attribute(module, ldb, msg2, msg->elements[i].name);
+                       msg_delete_attribute(module, ldb, msg2, el->name);
+
+                       for (j=0;j<el->num_values;j++) {
+                               if (ldb_msg_find_val(el, &el->values[j]) != &el->values[j]) {
+                                       ldb_asprintf_errstring(module->ldb, "%s: value #%d provided more than once", el->name, j);
+                                       ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
+                                       goto failed;
+                               }
+                       }
 
                        /* add the replacement element, if not empty */
-                       if (msg->elements[i].num_values != 0 &&
-                           msg_add_element(ldb, msg2, &msg->elements[i]) != 0) {
+                       if (el->num_values != 0 &&
+                           msg_add_element(ldb, msg2, el) != 0) {
                                ret = LDB_ERR_OTHER;
                                goto failed;
                        }
index 6cb7f2ce7f6cf199103a20bcf315dffe9a3c74e1..72d8c9acf8785ec81ae2eae272deaaa6554e626d 100755 (executable)
@@ -101,6 +101,21 @@ userAccountControl: 4096
                }
        }
 
+           ok = ldb.modify("
+dn: cn=ldaptest2computer,cn=computers," + base_dn + "
+changetype: modify
+replace: servicePrincipalName
+servicePrincipalName: host/ldaptest2computer
+servicePrincipalName: host/ldaptest2computer
+servicePrincipalName: cifs/ldaptest2computer
+");
+
+//LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS
+               if (ok.error != 20) {
+                       println("Expected error LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS, got :" + ok.errstr);
+                       assert(ok.error == 20);
+               }
+
        ok = ldb.add("
 dn: cn=ldaptestuser2,cn=users," + base_dn + "
 objectClass: person