dsdb: Fix dsdb_next_callback to correctly use ldb_module_done() etc
authorAndrew Bartlett <abartlet@samba.org>
Tue, 1 Aug 2017 01:18:33 +0000 (13:18 +1200)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 1 Aug 2017 05:52:38 +0000 (07:52 +0200)
If we do not call ldb_module_done() then we do not know that up_req->callback()
has been called, and ldb_next_request() will call the callback again.

If called twice, the new ldb_lock_backend_callback() in ldb 1.2.0 will segfault.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=12904

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Autobuild-User(master): Andrew Bartlett <abartlet@samba.org>
Autobuild-Date(master): Tue Aug  1 07:52:38 CEST 2017 on sn-devel-144

python/samba/tests/dsdb.py
source4/dsdb/pydsdb.c
source4/dsdb/samdb/ldb_modules/util.c
source4/dsdb/samdb/samdb.h

index ce5f599161555f37b4bb10785e9ada0a7e3c8282..a9f569b6c674958bc38725796f1a4f96fd4220d0 100644 (file)
@@ -23,6 +23,7 @@ from samba.auth import system_session
 from samba.tests import TestCase
 from samba.ndr import ndr_unpack, ndr_pack
 from samba.dcerpc import drsblobs
+from samba import dsdb
 import ldb
 import os
 import samba
@@ -505,3 +506,25 @@ class DsdbTests(TestCase):
                                        backend_filename)
         backend_path = self.lp.private_path(backend_subpath)
         self._test_full_db_lock2(backend_path)
+
+    def test_no_error_on_invalid_control(self):
+        try:
+            res = self.samdb.search(expression="cn=Administrator",
+                                    scope=ldb.SCOPE_SUBTREE,
+                                    attrs=["replPropertyMetaData"],
+                                    controls=["local_oid:%s:0"
+                                              % dsdb.DSDB_CONTROL_INVALID_NOT_IMPLEMENTED])
+        except ldb.LdbError as e:
+            self.fail("Should have not raised an exception")
+
+    def test_error_on_invalid_critical_control(self):
+        try:
+            res = self.samdb.search(expression="cn=Administrator",
+                                    scope=ldb.SCOPE_SUBTREE,
+                                    attrs=["replPropertyMetaData"],
+                                    controls=["local_oid:%s:1"
+                                              % dsdb.DSDB_CONTROL_INVALID_NOT_IMPLEMENTED])
+        except ldb.LdbError as e:
+            if e[0] != ldb.ERR_UNSUPPORTED_CRITICAL_EXTENSION:
+                self.fail("Got %s should have got ERR_UNSUPPORTED_CRITICAL_EXTENSION"
+                          % e[1])
index 47dc9ad903aa32e26fecf21a870d250b8c312314..09623a6d53b7bef4941ec36c9f5a08a354eff605 100644 (file)
@@ -1572,6 +1572,7 @@ void initdsdb(void)
        ADD_DSDB_STRING(DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID);
        ADD_DSDB_STRING(DSDB_CONTROL_SKIP_DUPLICATES_CHECK_OID);
        ADD_DSDB_STRING(DSDB_CONTROL_BYPASS_PASSWORD_HASH_OID);
+       ADD_DSDB_STRING(DSDB_CONTROL_INVALID_NOT_IMPLEMENTED);
 
        ADD_DSDB_STRING(DS_GUID_COMPUTERS_CONTAINER);
        ADD_DSDB_STRING(DS_GUID_DELETED_OBJECTS_CONTAINER);
index 36d35b7094a0c60c68d86a753bf9a082f6332ebb..9e37c085bbadd72c181526847f0ac3aac61cb88c 100644 (file)
@@ -832,8 +832,29 @@ int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
 {
        struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
 
-       talloc_steal(up_req, req);
-       return up_req->callback(up_req, ares);
+       if (!ares) {
+               return ldb_module_done(up_req, NULL, NULL,
+                                      LDB_ERR_OPERATIONS_ERROR);
+       }
+
+       if (ares->error != LDB_SUCCESS || ares->type == LDB_REPLY_DONE) {
+               return ldb_module_done(up_req, ares->controls,
+                                      ares->response, ares->error);
+       }
+
+       /* Otherwise pass on the callback */
+       switch (ares->type) {
+       case LDB_REPLY_ENTRY:
+               return ldb_module_send_entry(up_req, ares->message,
+                                            ares->controls);
+
+       case LDB_REPLY_REFERRAL:
+               return ldb_module_send_referral(up_req,
+                                               ares->referral);
+       default:
+               /* Can't happen */
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
 }
 
 /*
index 5dce37e2e9c96a9ca4ae4c88804e54ca3c512008..c8658dc42fa39a5e32767e2662665cdf7791390c 100644 (file)
@@ -189,6 +189,8 @@ struct dsdb_control_password_user_account_control {
  */
 #define DSDB_CONTROL_FORCE_RODC_LOCAL_CHANGE "1.3.6.1.4.1.7165.4.3.31"
 
+#define DSDB_CONTROL_INVALID_NOT_IMPLEMENTED "1.3.6.1.4.1.7165.4.3.32"
+
 #define DSDB_EXTENDED_REPLICATED_OBJECTS_OID "1.3.6.1.4.1.7165.4.4.1"
 struct dsdb_extended_replicated_object {
        struct ldb_message *msg;