lib/ldb: switch ldb_tdb to schema-based attribute comparison
authorAndrew Bartlett <abartlet@samba.org>
Fri, 11 May 2012 08:00:29 +0000 (10:00 +0200)
committerStefan Metzmacher <metze@samba.org>
Wed, 25 Sep 2013 22:11:43 +0000 (00:11 +0200)
Based on an earlier patch by Matthias Dieter Wallnöfer <mdw@samba.org>

This is necessary to perform correct schema enforcement, becuase we
must enforce uniquiness based on the schema matching rules.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=7485
Bug: https://bugzilla.samba.org/show_bug.cgi?id=8929

Andrew Bartlett

Small fix by Matthias Dieter Wallnöfer <mdw@samba.org>

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Signed-off-by: Matthias Dieter Wallnöfer <mdw@samba.org>
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
lib/ldb/ldb_tdb/ldb_tdb.c

index a8c6e97ec129590a0cf1349bcae5275fbef30a6c..b6c1ced27cb421046f36090a3980fa39491dff91 100644 (file)
@@ -369,7 +369,24 @@ static int ltdb_add_internal(struct ldb_module *module,
 
                /* TODO: This is O(n^2) - replace with more efficient check */
                for (j=0; j<el->num_values; j++) {
-                       if (ldb_msg_find_val(el, &el->values[j]) != &el->values[j]) {
+                       struct ldb_val *matched_val = NULL;
+
+                       ret = ldb_msg_find_val_schema(ldb, a, el,
+                                                     &el->values[j],
+                                                     &matched_val);
+                       if (ret != LDB_SUCCESS) {
+                               return ret;
+                       }
+
+                       if (matched_val == NULL) {
+                               /*
+                                * Something went completely wrong
+                                * This must find the value itself!!!
+                                */
+                               return ldb_operr(ldb);
+                       }
+
+                       if (matched_val != &el->values[j]) {
                                ldb_asprintf_errstring(ldb,
                                                       "attribute '%s': value #%u on '%s' provided more than once",
                                                       el->name, j, ldb_dn_get_linearized(msg->dn));
@@ -634,13 +651,9 @@ static int msg_delete_element(struct ldb_module *module,
 
        for (i=0;i<el->num_values;i++) {
                bool matched;
-               if (a->syntax->operator_fn) {
-                       ret = a->syntax->operator_fn(ldb, LDB_OP_EQUALITY, a,
-                                                    &el->values[i], val, &matched);
-                       if (ret != LDB_SUCCESS) return ret;
-               } else {
-                       matched = (a->syntax->comparison_fn(ldb, ldb,
-                                                           &el->values[i], val) == 0);
+               ret = ldb_val_equal_schema(ldb, a, &el->values[i], val, &matched);
+               if (ret != LDB_SUCCESS) {
+                       return ret;
                }
                if (matched) {
                        if (el->num_values == 1) {
@@ -823,7 +836,16 @@ int ltdb_modify_internal(struct ldb_module *module,
                                   valued attributes or aren't provided twice */
                                /* TODO: This is O(n^2) - replace with more efficient check */
                                for (j = 0; j < el->num_values; j++) {
-                                       if (ldb_msg_find_val(el2, &el->values[j]) != NULL) {
+                                       struct ldb_val *matched_val = NULL;
+
+                                       ret = ldb_msg_find_val_schema(ldb, a, el2,
+                                                                     &el->values[j],
+                                                                     &matched_val);
+                                       if (ret != LDB_SUCCESS) {
+                                               goto done;
+                                       }
+
+                                       if (matched_val != NULL) {
                                                if (control_permissive) {
                                                        /* remove this one as if it was never added */
                                                        el->num_values--;
@@ -841,7 +863,25 @@ int ltdb_modify_internal(struct ldb_module *module,
                                                ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
                                                goto done;
                                        }
-                                       if (ldb_msg_find_val(el, &el->values[j]) != &el->values[j]) {
+
+                                       matched_val = NULL;
+                                       ret = ldb_msg_find_val_schema(ldb, a, el,
+                                                                     &el->values[j],
+                                                                     &matched_val);
+                                       if (ret != LDB_SUCCESS) {
+                                               goto done;
+                                       }
+
+                                       if (matched_val == NULL) {
+                                               /*
+                                                * Something went completely wrong
+                                                * This must find the value itself!!!
+                                                */
+                                               ret = ldb_operr(ldb);
+                                               goto done;
+                                       }
+
+                                       if (matched_val != &el->values[j]) {
                                                ldb_asprintf_errstring(ldb,
                                                                       "attribute '%s': value #%u on '%s' provided more than once",
                                                                       el->name, j, ldb_dn_get_linearized(msg2->dn));
@@ -888,7 +928,25 @@ int ltdb_modify_internal(struct ldb_module *module,
 
                        /* TODO: This is O(n^2) - replace with more efficient check */
                        for (j=0; j<el->num_values; j++) {
-                               if (ldb_msg_find_val(el, &el->values[j]) != &el->values[j]) {
+                               struct ldb_val *matched_val = NULL;
+
+                               ret = ldb_msg_find_val_schema(ldb, a, el,
+                                                             &el->values[j],
+                                                             &matched_val);
+                               if (ret != LDB_SUCCESS) {
+                                       goto done;
+                               }
+
+                               if (matched_val == NULL) {
+                                       /*
+                                        * Something went completely wrong
+                                        * This must find the value itself!!!
+                                        */
+                                       ret = ldb_operr(ldb);
+                                       goto done;
+                               }
+
+                               if (matched_val != &el->values[j]) {
                                        ldb_asprintf_errstring(ldb,
                                                               "attribute '%s': value #%u on '%s' provided more than once",
                                                               el->name, j, ldb_dn_get_linearized(msg2->dn));