drs_utils: Avoid invalid dereference of v8 requests
authorTim Beale <timbeale@catalyst.net.nz>
Mon, 5 Nov 2018 04:01:55 +0000 (17:01 +1300)
committerTim Beale <timbeale@samba.org>
Tue, 6 Nov 2018 06:15:33 +0000 (07:15 +0100)
req.more_flags only exists for v10 requests, so we throw an exception if
we try to dereference that field on a v8 (or v5) request. Unfortunately,
we were checking that we support v10 *after* we had tried to access the
more_flags. This patch fixes up the order of the checks.

This may be a problem trying to replicate with an older Windows DC
(pre-2008R2), and was reported on the samba mailing-list at one point:
https://lists.samba.org/archive/samba/2018-June/216541.html

Unfortunately this patch doesn't help the overall situation at all (the
join will fail because we can't resolve the link target and we can't use
GET_TGT). But it now gives you a more meaningful error, i.e.

  ERROR(runtime): uncaught exception - (8639, "Failed to process 'chunk'
    of DRS replicated objects: DOS code 0x000021bf"
instead of:
  ERROR(<type 'exceptions.AttributeError'>): uncaught exception -
    'drsuapi.DsGetNCChangesRequest8' object has no attribute 'more_flags'

Signed-off-by: Tim Beale <timbeale@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Autobuild-User(master): Tim Beale <timbeale@samba.org>
Autobuild-Date(master): Tue Nov  6 07:15:33 CET 2018 on sn-devel-144

python/samba/drs_utils.py

index be2b606..43d1b4a 100644 (file)
@@ -221,13 +221,14 @@ class drs_Replicate(object):
         # If the error indicates we fail to resolve a target object for a
         # linked attribute, then we should retry the request with GET_TGT
         # (if we support it and haven't already tried that)
+        supports_ext = self.supports_ext
 
         # TODO fix up the below line when we next update werror_err_table.txt
         # and pull in the new error-code
         # return (error_code == werror.WERR_DS_DRA_RECYCLED_TARGET and
         return (error_code == 0x21bf and
-                (req.more_flags & drsuapi.DRSUAPI_DRS_GET_TGT) == 0 and
-                self.supports_ext & DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V10)
+                supports_ext & DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V10 and
+                (req.more_flags & drsuapi.DRSUAPI_DRS_GET_TGT) == 0)
 
     def process_chunk(self, level, ctr, schema, req_level, req, first_chunk):
         '''Processes a single chunk of received replication data'''