Fix propagation of LDB errors through TDB.
authorAdrian Cochrane <adrianc@catalyst.net.nz>
Thu, 3 Dec 2015 03:30:59 +0000 (16:30 +1300)
committerGarming Sam <garming@samba.org>
Fri, 4 Dec 2015 05:08:29 +0000 (06:08 +0100)
Returning a non-zero value from a tdb_traverse callback indicates that tdb_traverse
should stop traversing the database. This error code IS NOT propagated back to the
caller, so LTDB must record the error otherwise. This patch corrects LTDB for this
misunderstanding.

Naturally exposing these errors changes the behaviour of some tests. This commit fixes
that as well.

Signed-off-by: Adrian Cochrane <adrianc@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
lib/ldb-samba/tests/match_rules.py
lib/ldb/ldb_tdb/ldb_search.c
lib/ldb/ldb_tdb/ldb_tdb.h
selftest/knownfail

index 6b31392df1dcb676ae96832f8cfae27e60ec2f13..1b30e9fbb79737db062f1a2b62d1fc00e9b81238 100755 (executable)
@@ -14,7 +14,7 @@ from samba.dcerpc import security, misc
 from samba.samdb import SamDB
 from samba.auth import system_session
 from samba.ndr import ndr_unpack
-from ldb import Message, MessageElement, Dn
+from ldb import Message, MessageElement, Dn, LdbError
 from ldb import FLAG_MOD_ADD, FLAG_MOD_REPLACE, FLAG_MOD_DELETE
 from ldb import SCOPE_BASE, SCOPE_SUBTREE
 
@@ -301,11 +301,14 @@ class MatchRulesTests(samba.tests.TestCase):
                         expression="memberOf=cn=g4,%s" % self.ou_groups)
         self.assertTrue(len(res1) == 0)
 
-        # Search with transitive match must return 1 results
-        res1 = self.ldb.search("cn=g4,%s" % self.ou_groups,
-                        scope=SCOPE_BASE,
-                        expression="member:1.2.840.113556.1.4.1941:=cn=u1,%s" % self.ou_users)
-        self.assertTrue(len(res1) == 1)
+        try:
+            # Search with transitive match must return 1 results
+            res1 = self.ldb.search("cn=g4,%s" % self.ou_groups,
+                            scope=SCOPE_BASE,
+                            expression="member:1.2.840.113556.1.4.1941:=cn=u1,%s" % self.ou_users)
+            self.assertTrue(len(res1) == 1)
+        except LdbError, err:
+            self.fail(str(err))
 
         res1 = self.ldb.search("cn=u1,%s" % self.ou_users,
                         scope=SCOPE_BASE,
@@ -324,11 +327,14 @@ class MatchRulesTests(samba.tests.TestCase):
                         expression="memberOf=cn=g4,%s" % self.ou_groups)
         self.assertTrue(len(res1) == 0)
 
-        # Search with transitive match must return 1 results
-        res1 = self.ldb.search("cn=g4,%s" % self.ou_groups,
-                        scope=SCOPE_BASE,
-                        expression="member:1.2.840.113556.1.4.1941:=cn=g1,%s" % self.ou_groups)
-        self.assertTrue(len(res1) == 1)
+        try:
+            # Search with transitive match must return 1 results
+            res1 = self.ldb.search("cn=g4,%s" % self.ou_groups,
+                            scope=SCOPE_BASE,
+                            expression="member:1.2.840.113556.1.4.1941:=cn=g1,%s" % self.ou_groups)
+            self.assertTrue(len(res1) == 1)
+        except LdbError, err:
+            self.fail(str(err))
 
         res1 = self.ldb.search("cn=g1,%s" % self.ou_groups,
                         scope=SCOPE_BASE,
@@ -341,10 +347,13 @@ class MatchRulesTests(samba.tests.TestCase):
                         expression="member=cn=u1,%s" % self.ou_users)
         self.assertTrue(len(res1) == 1)
 
-        res1 = self.ldb.search(self.ou_groups,
-                        scope=SCOPE_SUBTREE,
-                        expression="member:1.2.840.113556.1.4.1941:=cn=u1,%s" % self.ou_users)
-        self.assertTrue(len(res1) == 4)
+        try:
+            res1 = self.ldb.search(self.ou_groups,
+                            scope=SCOPE_SUBTREE,
+                            expression="member:1.2.840.113556.1.4.1941:=cn=u1,%s" % self.ou_users)
+            self.assertTrue(len(res1) == 4)
+        except LdbError, err:
+            self.fail(str(err))
 
     def test_u2_groups(self):
         res1 = self.ldb.search(self.ou_groups,
@@ -352,10 +361,13 @@ class MatchRulesTests(samba.tests.TestCase):
                         expression="member=cn=u2,%s" % self.ou_users)
         self.assertTrue(len(res1) == 1)
 
-        res1 = self.ldb.search(self.ou_groups,
-                        scope=SCOPE_SUBTREE,
-                        expression="member:1.2.840.113556.1.4.1941:=cn=u2,%s" % self.ou_users)
-        self.assertTrue(len(res1) == 3)
+        try:
+            res1 = self.ldb.search(self.ou_groups,
+                            scope=SCOPE_SUBTREE,
+                            expression="member:1.2.840.113556.1.4.1941:=cn=u2,%s" % self.ou_users)
+            self.assertTrue(len(res1) == 3)
+        except LdbError, err:
+            self.fail(str(err))
 
     def test_u3_groups(self):
         res1 = self.ldb.search(self.ou_groups,
@@ -363,10 +375,13 @@ class MatchRulesTests(samba.tests.TestCase):
                         expression="member=cn=u3,%s" % self.ou_users)
         self.assertTrue(len(res1) == 1)
 
-        res1 = self.ldb.search(self.ou_groups,
-                        scope=SCOPE_SUBTREE,
-                        expression="member:1.2.840.113556.1.4.1941:=cn=u3,%s" % self.ou_users)
-        self.assertTrue(len(res1) == 2)
+        try:
+            res1 = self.ldb.search(self.ou_groups,
+                            scope=SCOPE_SUBTREE,
+                            expression="member:1.2.840.113556.1.4.1941:=cn=u3,%s" % self.ou_users)
+            self.assertTrue(len(res1) == 2)
+        except LdbError, err:
+            self.fail(str(err))
 
     def test_u4_groups(self):
         res1 = self.ldb.search(self.ou_groups,
@@ -374,10 +389,13 @@ class MatchRulesTests(samba.tests.TestCase):
                         expression="member=cn=u4,%s" % self.ou_users)
         self.assertTrue(len(res1) == 1)
 
-        res1 = self.ldb.search(self.ou_groups,
-                        scope=SCOPE_SUBTREE,
-                        expression="member:1.2.840.113556.1.4.1941:=cn=u4,%s" % self.ou_users)
-        self.assertTrue(len(res1) == 1)
+        try:
+            res1 = self.ldb.search(self.ou_groups,
+                            scope=SCOPE_SUBTREE,
+                            expression="member:1.2.840.113556.1.4.1941:=cn=u4,%s" % self.ou_users)
+            self.assertTrue(len(res1) == 1)
+        except LdbError, err:
+            self.fail(str(err))
 
     def test_extended_dn(self):
         res1 = self.ldb.search("cn=u1,%s" % self.ou_users,
@@ -399,10 +417,13 @@ class MatchRulesTests(samba.tests.TestCase):
                         expression="member=<GUID=%s>" % guid)
         self.assertTrue(len(res1) == 1)
 
-        res1 = self.ldb.search(self.ou_groups,
-                        scope=SCOPE_SUBTREE,
-                        expression="member:1.2.840.113556.1.4.1941:=<SID=%s>" % sid)
-        self.assertTrue(len(res1) == 4)
+        try:
+            res1 = self.ldb.search(self.ou_groups,
+                            scope=SCOPE_SUBTREE,
+                            expression="member:1.2.840.113556.1.4.1941:=<SID=%s>" % sid)
+            self.assertTrue(len(res1) == 4)
+        except LdbError, err:
+            self.fail(str(err))
 
         res1 = self.ldb.search(self.ou_groups,
                         scope=SCOPE_SUBTREE,
@@ -415,10 +436,13 @@ class MatchRulesTests(samba.tests.TestCase):
                         expression="msDS-RevealedUsers=B:8:01010101:cn=c3,%s" % self.ou_computers)
         self.assertTrue(len(res1) == 1)
 
-        res1 = self.ldb.search(self.ou_computers,
-                        scope=SCOPE_SUBTREE,
-                        expression="msDS-RevealedUsers:1.2.840.113556.1.4.1941:=B:8:01010101:cn=c3,%s" % self.ou_computers)
-        self.assertTrue(len(res1) == 2)
+        try:
+            res1 = self.ldb.search(self.ou_computers,
+                            scope=SCOPE_SUBTREE,
+                            expression="msDS-RevealedUsers:1.2.840.113556.1.4.1941:=B:8:01010101:cn=c3,%s" % self.ou_computers)
+            self.assertTrue(len(res1) == 2)
+        except LdbError, err:
+            self.fail(str(err))
 
     def test_one_way_links(self):
         res1 = self.ldb.search(self.ou,
@@ -426,10 +450,13 @@ class MatchRulesTests(samba.tests.TestCase):
                         expression="addressBookRoots2=cn=c1,%s" % self.ou_computers)
         self.assertTrue(len(res1) == 1)
 
-        res1 = self.ldb.search(self.ou,
-                        scope=SCOPE_SUBTREE,
-                        expression="addressBookRoots2:1.2.840.113556.1.4.1941:=cn=c1,%s" % self.ou_computers)
-        self.assertTrue(len(res1) == 2)
+        try:
+            res1 = self.ldb.search(self.ou,
+                            scope=SCOPE_SUBTREE,
+                            expression="addressBookRoots2:1.2.840.113556.1.4.1941:=cn=c1,%s" % self.ou_computers)
+            self.assertTrue(len(res1) == 2)
+        except LdbError, err:
+            self.fail(str(err))
 
     def test_not_linked_attrs(self):
         res1 = self.ldb.search(self.base_dn,
@@ -437,10 +464,13 @@ class MatchRulesTests(samba.tests.TestCase):
                         expression="wellKnownObjects=B:32:aa312825768811d1aded00c04fd8d5cd:CN=computers,%s" % self.base_dn)
         self.assertTrue(len(res1) == 1)
 
-        res1 = self.ldb.search(self.base_dn,
-                        scope=SCOPE_BASE,
-                        expression="wellKnownObjects:1.2.840.113556.1.4.1941:=B:32:aa312825768811d1aded00c04fd8d5cd:CN=computers,%s" % self.base_dn)
-        self.assertTrue(len(res1) == 0)
+        try:
+            res1 = self.ldb.search(self.base_dn,
+                            scope=SCOPE_BASE,
+                            expression="wellKnownObjects:1.2.840.113556.1.4.1941:=B:32:aa312825768811d1aded00c04fd8d5cd:CN=computers,%s" % self.base_dn)
+            self.assertTrue(len(res1) == 0)
+        except LdbError, err:
+            self.fail(str(err))
 
 
        res1 = self.ldb.search(self.ou,
index c939bcba6b4b82b44fe590e7448f5e11fea48fae..62a36c7c252d46d40fc783416627f840a13b3bc8 100644 (file)
@@ -445,6 +445,7 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi
 
        msg = ldb_msg_new(ac);
        if (!msg) {
+               ac->error = LDB_ERR_OPERATIONS_ERROR;
                return -1;
        }
 
@@ -452,6 +453,7 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi
        ret = ldb_unpack_data(ldb, (struct ldb_val *)&data, msg);
        if (ret == -1) {
                talloc_free(msg);
+               ac->error = LDB_ERR_OPERATIONS_ERROR;
                return -1;
        }
 
@@ -460,6 +462,7 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi
                                     (char *)key.dptr + 3);
                if (msg->dn == NULL) {
                        talloc_free(msg);
+                       ac->error = LDB_ERR_OPERATIONS_ERROR;
                        return -1;
                }
        }
@@ -469,6 +472,7 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi
                                  ac->tree, ac->base, ac->scope, &matched);
        if (ret != LDB_SUCCESS) {
                talloc_free(msg);
+               ac->error = LDB_ERR_OPERATIONS_ERROR;
                return -1;
        }
        if (!matched) {
@@ -481,6 +485,7 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi
 
        if (ret == -1) {
                talloc_free(msg);
+               ac->error = LDB_ERR_OPERATIONS_ERROR;
                return -1;
        }
 
@@ -488,6 +493,7 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi
        if (ret != LDB_SUCCESS) {
                ac->request_terminated = true;
                /* the callback failed, abort the operation */
+               ac->error = LDB_ERR_OPERATIONS_ERROR;
                return -1;
        }
 
@@ -505,6 +511,7 @@ static int ltdb_search_full(struct ltdb_context *ctx)
        struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
        int ret;
 
+       ctx->error = LDB_SUCCESS;
        if (ltdb->in_transaction != 0) {
                ret = tdb_traverse(ltdb->tdb, search_func, ctx);
        } else {
@@ -515,7 +522,7 @@ static int ltdb_search_full(struct ltdb_context *ctx)
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
-       return LDB_SUCCESS;
+       return ctx->error;
 }
 
 /*
index 35218000eb4bb6a5334b9a6701b22ec92a960d52..caa98ebf8efbd0d3b51f95ab5dafb2b789ff801f 100644 (file)
@@ -48,6 +48,9 @@ struct ltdb_context {
        enum ldb_scope scope;
        const char * const *attrs;
        struct tevent_timer *timeout_event;
+
+       /* error handling */
+       int error;
 };
 
 /* special record types */
index d184f4117f5db35e7f21224c477340ad7507bc7a..191d3913776fdf86069481b6a3f6661f8a318b8c 100644 (file)
 #
 ^samba4.ldap.match_rules.python.__main__.MatchRulesTests.test_extended_dn
 ^samba4.ldap.match_rules.python.__main__.MatchRulesTests.test_g1_member_of_g4
+^samba4.ldap.match_rules.python.__main__.MatchRulesTests.test_not_linked_attrs
 ^samba4.ldap.match_rules.python.__main__.MatchRulesTests.test_object_dn_binary
 ^samba4.ldap.match_rules.python.__main__.MatchRulesTests.test_one_way_links
 ^samba4.ldap.match_rules.python.__main__.MatchRulesTests.test_u1_groups