[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Fri Aug 18 08:06:04 UTC 2017


The branch, master has been updated
       via  cd813f7 s3:gse_krb5: make use of precalculated krb5 keys in fill_mem_keytab_from_secrets()
       via  37e49a2 s3:secrets: allow secrets_fetch_or_upgrade_domain_info() on an AD DC
       via  0bb4d28 getncchanges.py: Add test for GET_ANC and linked attributes
       via  9f0ae6e getncchanges.py: Add GET_ANC replication test case
       via  4cfc296 getncchanges.py: Add a new test for replication
       via  fae5df8 replmd: Try to add forward-link for unknown cross-partition links
       via  89cf5c3 replmd: Don't fail cycle if we get link for deleted object with GET_TGT
       via  ab12aed replmd: Avoid dropping links if link target is deleted
       via  18ea167 replmd: Move where we store linked attributes
       via  f812c29 drs_utils: Add GET_TGT support to 'samba-tool drs replicate --local'
       via  f87332e replmd: Set GET_ANC if Windows sends a link with unknown source object
       via  cc201c2 drepl: Support GET_TGT on periodic replication client
       via  67617d4 drs: Check target object is known after applying objects
       via  f69596c drs: Fail replication transaction instead of dropping links
       via  04ce638 replmd: Split checking link attr target into new function
       via  d13e7b9 werror: Add WERR_DS_DRA_RECYCLED_TARGET
      from  9fb2562 libcli/smb: debug an error if smb1cli_req_writev_submit() is called for SMB2/3

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit cd813f7fd9ee8e9d82a6bf6c98621c437f6974b2
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Aug 17 17:45:21 2017 +0200

    s3:gse_krb5: make use of precalculated krb5 keys in fill_mem_keytab_from_secrets()
    
    This avoids a lot of cpu cycles, which were wasted for each single smb
    connection, even if the client didn't use kerberos.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12973
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    
    Autobuild-User(master): Andrew Bartlett <abartlet at samba.org>
    Autobuild-Date(master): Fri Aug 18 10:04:57 CEST 2017 on sn-devel-144

commit 37e49a2af5bb1c40c17eab18ff9412f2ce79ef71
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Aug 17 21:42:34 2017 +0200

    s3:secrets: allow secrets_fetch_or_upgrade_domain_info() on an AD DC
    
    The reason for the check is for write access as secrets.ldb is the
    master database.
    
    But secrets_fetch_or_upgrade_domain_info() just syncs the values
    we got from if they got overwritten by secrets_store_machine_pw_sync().
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12973
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 0bb4d28272914736a46dc5cdb0bef766ba7a4ab8
Author: Tim Beale <timbeale at catalyst.net.nz>
Date:   Wed Jul 12 10:16:00 2017 +1200

    getncchanges.py: Add test for GET_ANC and linked attributes
    
    Add a basic test that when we use GET_ANC and the parents have linked
    attributes, then we receive all the expected links and all the expected
    objects by the end of the test.
    
    This extends the test code to track what linked attributes get received
    and check whether they match what's present on the DC.
    
    Also made some minor cleanups to store the received objects/links each
    time we successfully receive a GETNCChanges response (this saves the
    test case having to repeat this code every time).
    
    Note that although this test involves linked attributes, it shouldn't
    exercise the GET_TGT case at all.
    
    Signed-off-by: Tim Beale <timbeale at catalyst.net.nz>
    Reviewed-by: Garming Sam <garming at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12972

commit 9f0ae6e44d0f6def6be7c44067c7fcfdf0d42db2
Author: Tim Beale <timbeale at catalyst.net.nz>
Date:   Tue Jun 6 18:21:40 2017 +1200

    getncchanges.py: Add GET_ANC replication test case
    
    This test:
    - creates blocks of parent/child objects
    - modifies the parents, so the child gets received first in the
      replication (which means the client has to use GET_ANC)
    - checks that we always receive the parent before the child (if not, it
      either retries with GET_ANC, or asserts if GET_ANC is already set)
    - modifies the parent objects to change their USN while the
      replication is in progress
    - checks that all expected objects are received by the end of the
      test
    
    I've added a repl_get_next() function to help simulate a client's
    behaviour - if it encounters an object it doesn't know the parent of,
    then it retries with GET_ANC.
    
    Also added some debug to drs_base.py that developers can turn on to make
    it easier to see what objects we're actually receiving in the
    responses.
    
    Signed-off-by: Tim Beale <timbeale at catalyst.net.nz>
    Reviewed-by: Garming Sam <garming at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12972

commit 4cfc29688584ca69c43abb770d1e721d1eab1480
Author: Tim Beale <timbeale at catalyst.net.nz>
Date:   Tue Jun 6 18:06:22 2017 +1200

    getncchanges.py: Add a new test for replication
    
    This adds a new test to check that if objects are modified during a
    replication, then those objects don't wind up missing from the
    replication data.
    
    Note that when this scenario occurs, samba returns the objects in a
    different order to Windows. This test doesn't care what order the
    replicated objects get returned in, so long as they all have been
    received by the end of the test.
    
    As part of this, I've refactored _check_replication() in drs_base.py so
    it can be reused in new tests. In these cases, the objects are split up
    over multiple different chunks. So asserting that the objects are returned
    in a specific order makes it difficult to run the same test on both Samba
    and Windows.
    
    Signed-off-by: Tim Beale <timbeale at catalyst.net.nz>
    Reviewed-by: Garming Sam <garming at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12972

commit fae5df891c11f642cbede9e4e3d845c49c5f86b8
Author: Tim Beale <timbeale at catalyst.net.nz>
Date:   Mon Jul 24 16:20:58 2017 +1200

    replmd: Try to add forward-link for unknown cross-partition links
    
    Previously Samba would just drop cross-partition links where the link
    target object is unknown. Instead, what we want to do is try to add the
    forward link for the GUID specified. We can't add the backlink because
    we don't know the target, however, dbcheck should be able to fix any
    missing backlinks.
    
    The new behaviour should now mean dbcheck will detect the problem and be
    able to fix it. It's still not ideal, but it's better than dropping the
    link completely.
    
    I've updated the log so that it has higher severity and tells the user
    what they need to do to fix it.
    
    These changes now mean that the selftests now detect an error - instead
    of completely dropping the serverReference, we now have a missing
    backlink. I've updated the selftests to fix up any missing
    serverReference backlinks before running dbcheck.
    
    Signed-off-by: Tim Beale <timbeale at catalyst.net.nz>
    Reviewed-by: Garming Sam <garming at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12972

commit 89cf5c3f76e214fbd06ce461470eb64b338c5144
Author: Tim Beale <timbeale at catalyst.net.nz>
Date:   Thu Jul 20 11:14:27 2017 +1200

    replmd: Don't fail cycle if we get link for deleted object with GET_TGT
    
    We are going to end up supporting 2 different server schemes:
    A. the old/default behaviour of sending all the linked attributes last,
       at the end of the replication cycle.
    B. the new/Microsoft way of sending the linked attributes interleaved
       with the source/target objects.
    
    Normally if we're talking to a server using the old scheme-A, we won't
    ever use the GET_TGT flag. However, there are a couple of cases where
    it can happen:
    - A link to a new object was added during the replication cycle.
    - An object was deleted while the replication was in progress (and
    the linked attribute got queued before the object was deleted).
    
    Talking to an Samba DC running the old scheme will just cause it to
    start the replication cycle from scratch again, which is fairly
    harmless. However, there is a chance that the same thing can happen
    again, in which case the replication cycle will fail (because GET_TGT
    was already set).
    
    Even if we're using the new scheme (B), we could still potentially hit
    this case, as we can still queue up linked attributes between requests
    (group memberships can be larger than what can fit into a single
    replication chunk).
    
    If GET_TGT is set in the GetNcChanges request, then the local copy of
    the target object should always be up-to-date when we process the linked
    attribute. So if we still think the target object is deleted/recycled at
    this point, then it's safe to ignore the linked attribute (because we
    know our local copy is up-to-date). This logic matches the MS spec logic
    in ProcessLinkValue().
    
    Not failing the replication cycle may be beneficial if we're trying to
    do a full-sync of a large database. Otherwise it might be time-consuming
    and frustrating to repeat the sync unnecessarily.
    
    Signed-off-by: Tim Beale <timbeale at catalyst.net.nz>
    Reviewed-by: Garming Sam <garming at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12972

commit ab12aed7e13a9c9663ba04b6dd4f02acb7bff380
Author: Tim Beale <timbeale at catalyst.net.nz>
Date:   Wed Jul 19 16:18:20 2017 +1200

    replmd: Avoid dropping links if link target is deleted
    
    The server-side can potentially send the linked attribute before the
    target-object. This happens on Microsoft, and will happen on Samba once
    server-side GET_TGT support is added. In these cases there is a hole
    where the Samba client can silently drop the linked attribute.
    
    If the old copy of the target object was deleted/recycled, then the
    client can receive the new linked attribute before it realizes the target
    has now been reincarnated. It silently ignores the linked attribute,
    thinking its receiving out of date information, when really it's the
    client's copy of the target object that's out of date.
    
    In this case we want to retry with the GET_TGT flag set, which will
    force the updated version of the target object to be sent along with the
    linked attribute. This deleted/recycled target case is the main reason
    that Windows added the GET_TGT flag.
    
    If the server sends all the links at the end, instead of along with the
    source object, then this case can still be hit. If so, it will cause the
    server to restart the replication from the beginning again. This is
    probably preferential to silently dropping links.
    
    Signed-off-by: Tim Beale <timbeale at catalyst.net.nz>
    Reviewed-by: Garming Sam <garming at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12972

commit 18ea167adef59b80982f13135947e58cb56a4f16
Author: Tim Beale <timbeale at catalyst.net.nz>
Date:   Thu Jun 22 10:43:31 2017 +1200

    replmd: Move where we store linked attributes
    
    There was a bug in my previous patch where the code would verify
    *all* links in the list, rather than just the ones that are new. And it
    would do this for every replication chunk it received, regardless of
    whether there were actually any links in that chunk.
    
    The problem is by the time we want to verify the attributes, we don't
    actually know which attributes are new. We can fix this by moving where
    we store the linked attributes from the start of processing the
    replication chunk to the end of processing the chunk. We can then verify
    the new linked attributes at the same time we store them.
    
    Longer-term we may want to try to apply the linked attribute at this
    point. This would save looking up the source/target objects twice, but
    it makes things a bit more complicated (attributes will usually apply at
    this point *most* of the time, but not *all* the time).
    
    Signed-off-by: Tim Beale <timbeale at catalyst.net.nz>
    Reviewed-by: Garming Sam <garming at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12972

commit f812c29d4000ef35fa5d7f6007606ca53c5ed37a
Author: Tim Beale <timbeale at catalyst.net.nz>
Date:   Fri Jun 16 12:54:32 2017 +1200

    drs_utils: Add GET_TGT support to 'samba-tool drs replicate --local'
    
    Update drs_Replicate.replicate() so it handles being passed the GET_TGT
    flag (more_flags). To do this, we need to always use a v10 GetNCChanges
    request (v8 and v10 are essentially the same except for the more_flags).
    
    If the replicate_chunk() call into the C bindings throws an error, check
    to see whether the error could be fixed by setting the GET_TGT flag, and
    re-send the request if so.
    
    Unfortunately because WERR_DS_DRA_RECYCLED_TARGET isn't documented with
    the other AD error codes, I've left it hardcoded for now (Microsoft
    should be fixing up their Docs).
    
    Signed-off-by: Tim Beale <timbeale at catalyst.net.nz>
    Reviewed-by: Garming Sam <garming at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12972

commit f87332eb35638cc38f83c580d4623ab978088601
Author: Tim Beale <timbeale at catalyst.net.nz>
Date:   Fri Jun 16 09:49:16 2017 +1200

    replmd: Set GET_ANC if Windows sends a link with unknown source object
    
    Windows replication can send the linked attribute before it sends the
    source object. The MS-DRSR spec says that in this case the client should
    resend the GetNCChanges request with the GET_ANC flag set. In my testing
    this resolves the problem - Windows will include the source object for the
    linked attribute in the same replication chunk.
    
    This problem doesn't happen with Samba-to-Samba replication, because the
    source object for the linked attribute is guaranteed to have already been
    sent.
    
    Signed-off-by: Tim Beale <timbeale at catalyst.net.nz>
    Reviewed-by: Garming Sam <garming at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12972

commit cc201c2c4f5d2dfd18f68143d001c5ba02c00b32
Author: Tim Beale <timbeale at catalyst.net.nz>
Date:   Thu Jun 15 16:52:33 2017 +1200

    drepl: Support GET_TGT on periodic replication client
    
    - Update IDL comments to include Microsoft reference doc
    - Add support for sending v10 GetNCChanges request (needed for the
      GET_TGT flag, which is in the new 'more_flags' field)
    - Update to also set the GET_TGT flag in the same place we were setting
      GET_ANC (I split this logic out into a separate function).
    - The state struct now needs to hold a 'more_flags' field as well (this
      flag is different to the GET_ANC replica flag)
    
    Note that using the GET_TGT when replicating from a Windows DC could be
    highly inefficient. Because Samba keeps the GET_TGT flag set throughout
    the replication cycle, it will basically receive a repeated object from
    Windows for every single linked attribute that it receives.
    
    I believe Windows behaviour only expects the client to set the GET_TGT
    flag when it actually needs to (i.e. when it receives a target object it
    doesn't know about), rather than throughout the replication cycle.
    However, this approach won't work with Samba-to-Samba replication,
    because when the server receives the GET_TGT flag it restarts the
    replication cycle from scratch. So if we only set the GET_TGT flag when
    the client encountered an unknown target then Samba-to-Samba could
    potentially get into an endless replication loop.
    
    Signed-off-by: Tim Beale <timbeale at catalyst.net.nz>
    Reviewed-by: Garming Sam <garming at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12972

commit 67617d470028b45c722c598944a17591cab1e6ba
Author: Tim Beale <timbeale at catalyst.net.nz>
Date:   Thu Jun 15 14:09:27 2017 +1200

    drs: Check target object is known after applying objects
    
    Currently we only check that the target object is known at the end of
    the transaction (i.e. the .prepare_commit hook). It's too late at this
    point to resend the request with GET_TGT. Move this processing earlier
    on, after we've applied all the objects (i.e. off the .extended hook).
    
    In reality, we need to perform the checks at both points. I've
    split the common code that gets the source/target details out of the
    la_entry into a helper function. It's not the greatest function ever,
    but seemed to make more sense than duplicating the code.
    
    Signed-off-by: Tim Beale <timbeale at catalyst.net.nz>
    Reviewed-by: Garming Sam <garming at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12972

commit f69596cd21d8106afdf494f39d1fcebea2b0f5dd
Author: Tim Beale <timbeale at catalyst.net.nz>
Date:   Wed Jun 14 11:35:36 2017 +1200

    drs: Fail replication transaction instead of dropping links
    
    If the DRS client received a linked attribute that it couldn't resolve
    the target for, then it would just ignore that link and keep going. That
    link would then be lost forever (although a full-sync would resolve
    this). Instead of silently ignoring the link, fail the transaction.
    
    This *can* happen on Samba, but it is unusual. The target object and
    linked-attribute would need to be added while a replication is still in
    progress. It can also happen fairly easily when talking to a Windows DC.
    
    There are two import exceptions to this:
    
    1). Linked attributes that span partitions. We can never guarantee that
    we will have received the target object, because it may be in a partition
    we haven't replicated yet. Samba doesn't have a great way of handling
    this currently, but we shouldn't fail the replication (because that breaks
    basic join tests). Just skip that linked attribute and hope that a
    subsequent full-sync will fix it.
    (I queried Microsoft and they said resolving cross-partition linked
    attributes is a implementation-specific problem to solve. GET_TGT won't
    resolve it)
    
    2). When the replication involves a subset of objects, e.g.
    critical-only. In these cases, we don't increase the highwater-mark, so
    it is probably not such a dire problem if we don't add the link. In the
    case of critical-only, we will do a subsequent full sync which will then
    add the links.
    
    Signed-off-by: Tim Beale <timbeale at catalyst.net.nz>
    Reviewed-by: Garming Sam <garming at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12972

commit 04ce638a1f7166b3fe75b52efd0a522248196fd4
Author: Tim Beale <timbeale at catalyst.net.nz>
Date:   Wed Jun 14 10:51:59 2017 +1200

    replmd: Split checking link attr target into new function
    
    We want to re-use this code to check that the linked attribute's target
    object exists *before* we try to commit the transaction. This will allow
    us to re-request the block with the GET_TGT flag set.
    
    This splits checking the target object exists into a separate function.
    
    Minor changes of note:
    - the 'parent' argument was passed to replmd_process_linked_attribute()
      as NULL, so I've just replaced where it was used in the refactored code
      with NULL.
    - I've tweaked the "Failed to find GUID" error message slightly to display
      the attribute ID rather than the attribute name (saves repeating
      lookups and/or passing extra arguments).
    - Tweaked the replmd_deletion_state() logic - it only made sense to call
      it in the code block where we actually found the target
    
    Signed-off-by: Tim Beale <timbeale at catalyst.net.nz>
    Reviewed-by: Garming Sam <garming at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12972

commit d13e7b92f85e5623c5cf1309f13d59141dc7d888
Author: Tim Beale <timbeale at catalyst.net.nz>
Date:   Tue May 30 15:08:44 2017 +1200

    werror: Add WERR_DS_DRA_RECYCLED_TARGET
    
    When the DRS client encounters a linked attribute with an unknown target
    object, it should return a RECYCLED_TARGET error, which should result in
    the client resending the GETNCChanges request with the GET_TGT flag set.
    
    This error code is currently documented by Microsoft under System Error
    Codes (8200-8999). I contacted them and they will also add it to the
    MS-ERREF doc in future.
    
    Signed-off-by: Tim Beale <timbeale at catalyst.net.nz>
    Reviewed-by: Garming Sam <garming at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12972

-----------------------------------------------------------------------

Summary of changes:
 libcli/util/werror.h                            |   1 +
 librpc/idl/drsuapi.idl                          |   4 +-
 python/samba/drs_utils.py                       | 101 +++--
 source3/librpc/crypto/gse_krb5.c                | 180 ++++----
 source3/passdb/machine_account_secrets.c        |  15 +-
 source4/dsdb/repl/drepl_out_helpers.c           | 105 ++++-
 source4/dsdb/repl/drepl_out_pull.c              |   1 +
 source4/dsdb/repl/drepl_service.h               |   2 +
 source4/dsdb/repl/replicated_objects.c          |  11 +-
 source4/dsdb/samdb/ldb_modules/repl_meta_data.c | 558 +++++++++++++++++-------
 source4/dsdb/samdb/samdb.h                      |   3 +-
 source4/libnet/libnet_vampire.c                 |   5 +
 source4/selftest/tests.py                       |  10 +
 source4/torture/drs/python/drs_base.py          | 141 ++++--
 source4/torture/drs/python/getncchanges.py      | 428 ++++++++++++++++++
 testprogs/blackbox/dbcheck.sh                   |   8 +
 16 files changed, 1233 insertions(+), 340 deletions(-)
 create mode 100644 source4/torture/drs/python/getncchanges.py


Changeset truncated at 500 lines:

diff --git a/libcli/util/werror.h b/libcli/util/werror.h
index d3d3327..0370a06 100644
--- a/libcli/util/werror.h
+++ b/libcli/util/werror.h
@@ -100,6 +100,7 @@ typedef uint32_t WERROR;
 #define WERR_INVALID_PRIMARY_GROUP      W_ERROR(0x0000051C)
 
 #define WERR_DS_DRA_SECRETS_DENIED			W_ERROR(0x000021B6)
+#define WERR_DS_DRA_RECYCLED_TARGET			W_ERROR(0x000021BF)
 
 #define WERR_DNS_ERROR_KEYMASTER_REQUIRED               W_ERROR(0x0000238D)
 #define WERR_DNS_ERROR_NOT_ALLOWED_ON_SIGNED_ZONE       W_ERROR(0x0000238E)
diff --git a/librpc/idl/drsuapi.idl b/librpc/idl/drsuapi.idl
index 2eb1d65..51ef567 100644
--- a/librpc/idl/drsuapi.idl
+++ b/librpc/idl/drsuapi.idl
@@ -70,7 +70,9 @@ interface drsuapi
         } drsuapi_DrsUpdate;
 
 	/*****************/
-        /* Function 0x00 */
+        /* Function 0x00 drsuapi_DsBind() */
+
+        /* MS-DRSR 5.39 DRS_EXTENSIONS_INT */
         typedef [bitmap32bit] bitmap {
 		DRSUAPI_SUPPORTED_EXTENSION_BASE			= 0x00000001,
 		DRSUAPI_SUPPORTED_EXTENSION_ASYNC_REPLICATION		= 0x00000002,
diff --git a/python/samba/drs_utils.py b/python/samba/drs_utils.py
index b9ed059..bed8817 100644
--- a/python/samba/drs_utils.py
+++ b/python/samba/drs_utils.py
@@ -21,6 +21,8 @@ from samba.dcerpc import drsuapi, misc, drsblobs
 from samba.net import Net
 from samba.ndr import ndr_unpack
 from samba import dsdb
+from samba import werror
+from samba import WERRORError
 import samba, ldb
 
 
@@ -198,18 +200,37 @@ class drs_Replicate(object):
             raise RuntimeError("Must not set GUID 00000000-0000-0000-0000-000000000000 as invocation_id")
         self.replication_state = self.net.replicate_init(self.samdb, lp, self.drs, invocation_id)
 
+    def _should_retry_with_get_tgt(self, error_code, req):
+
+        # 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)
+
+        # 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.supported_extensions & drsuapi.DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V10)
+
     def replicate(self, dn, source_dsa_invocation_id, destination_dsa_guid,
                   schema=False, exop=drsuapi.DRSUAPI_EXOP_NONE, rodc=False,
-                  replica_flags=None, full_sync=True, sync_forced=False):
+                  replica_flags=None, full_sync=True, sync_forced=False, more_flags=0):
         '''replicate a single DN'''
 
         # setup for a GetNCChanges call
-        req8 = drsuapi.DsGetNCChangesRequest8()
+        if self.supported_extensions & drsuapi.DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V10:
+            req = drsuapi.DsGetNCChangesRequest10()
+            req.more_flags = more_flags
+            req_level = 10
+        else:
+            req_level = 8
+            req = drsuapi.DsGetNCChangesRequest8()
 
-        req8.destination_dsa_guid = destination_dsa_guid
-        req8.source_dsa_invocation_id = source_dsa_invocation_id
-        req8.naming_context = drsuapi.DsReplicaObjectIdentifier()
-        req8.naming_context.dn = dn
+        req.destination_dsa_guid = destination_dsa_guid
+        req.source_dsa_invocation_id = source_dsa_invocation_id
+        req.naming_context = drsuapi.DsReplicaObjectIdentifier()
+        req.naming_context.dn = dn
 
         # Default to a full replication if we don't find an upToDatenessVector
         udv = None
@@ -244,49 +265,46 @@ class drs_Replicate(object):
             udv.cursors = cursors_v1
             udv.count = len(cursors_v1)
 
-        req8.highwatermark = hwm
-        req8.uptodateness_vector = udv
+        req.highwatermark = hwm
+        req.uptodateness_vector = udv
 
         if replica_flags is not None:
-            req8.replica_flags = replica_flags
+            req.replica_flags = replica_flags
         elif exop == drsuapi.DRSUAPI_EXOP_REPL_SECRET:
-            req8.replica_flags = 0
+            req.replica_flags = 0
         else:
-            req8.replica_flags = (drsuapi.DRSUAPI_DRS_INIT_SYNC |
-                                  drsuapi.DRSUAPI_DRS_PER_SYNC |
-                                  drsuapi.DRSUAPI_DRS_GET_ANC |
-                                  drsuapi.DRSUAPI_DRS_NEVER_SYNCED |
-                                  drsuapi.DRSUAPI_DRS_GET_ALL_GROUP_MEMBERSHIP)
+            req.replica_flags = (drsuapi.DRSUAPI_DRS_INIT_SYNC |
+                                 drsuapi.DRSUAPI_DRS_PER_SYNC |
+                                 drsuapi.DRSUAPI_DRS_GET_ANC |
+                                 drsuapi.DRSUAPI_DRS_NEVER_SYNCED |
+                                 drsuapi.DRSUAPI_DRS_GET_ALL_GROUP_MEMBERSHIP)
             if rodc:
-                req8.replica_flags |= (
-                    drsuapi.DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING)
+                req.replica_flags |= (
+                     drsuapi.DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING)
             else:
-                req8.replica_flags |= drsuapi.DRSUAPI_DRS_WRIT_REP
+                req.replica_flags |= drsuapi.DRSUAPI_DRS_WRIT_REP
 
         if sync_forced:
-            req8.replica_flags |= drsuapi.DRSUAPI_DRS_SYNC_FORCED
+            req.replica_flags |= drsuapi.DRSUAPI_DRS_SYNC_FORCED
 
-        req8.max_object_count = 402
-        req8.max_ndr_size = 402116
-        req8.extended_op = exop
-        req8.fsmo_info = 0
-        req8.partial_attribute_set = None
-        req8.partial_attribute_set_ex = None
-        req8.mapping_ctr.num_mappings = 0
-        req8.mapping_ctr.mappings = None
+        req.max_object_count = 402
+        req.max_ndr_size = 402116
+        req.extended_op = exop
+        req.fsmo_info = 0
+        req.partial_attribute_set = None
+        req.partial_attribute_set_ex = None
+        req.mapping_ctr.num_mappings = 0
+        req.mapping_ctr.mappings = None
 
         if not schema and rodc:
-            req8.partial_attribute_set = drs_get_rodc_partial_attribute_set(self.samdb)
+            req.partial_attribute_set = drs_get_rodc_partial_attribute_set(self.samdb)
 
-        if self.supported_extensions & drsuapi.DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8:
-            req_level = 8
-            req = req8
-        else:
+        if not self.supported_extensions & drsuapi.DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8:
             req_level = 5
             req5 = drsuapi.DsGetNCChangesRequest5()
             for a in dir(req5):
                 if a[0] != '_':
-                    setattr(req5, a, getattr(req8, a))
+                    setattr(req5, a, getattr(req, a))
             req = req5
 
         num_objects = 0
@@ -295,8 +313,21 @@ class drs_Replicate(object):
             (level, ctr) = self.drs.DsGetNCChanges(self.drs_handle, req_level, req)
             if ctr.first_object is None and ctr.object_count != 0:
                 raise RuntimeError("DsGetNCChanges: NULL first_object with object_count=%u" % (ctr.object_count))
-            self.net.replicate_chunk(self.replication_state, level, ctr,
-                schema=schema, req_level=req_level, req=req)
+
+            try:
+                self.net.replicate_chunk(self.replication_state, level, ctr,
+                    schema=schema, req_level=req_level, req=req)
+            except WERRORError as e:
+                # Check if retrying with the GET_TGT flag set might resolve this error
+                if self._should_retry_with_get_tgt(e[0], req):
+
+                    print("Missing target object - retrying with DRS_GET_TGT")
+                    req.more_flags |= drsuapi.DRSUAPI_DRS_GET_TGT
+
+                    # try sending the request again
+                    continue
+                else:
+                    raise e
 
             num_objects += ctr.object_count
 
diff --git a/source3/librpc/crypto/gse_krb5.c b/source3/librpc/crypto/gse_krb5.c
index 2c9fc03..cc8cb90 100644
--- a/source3/librpc/crypto/gse_krb5.c
+++ b/source3/librpc/crypto/gse_krb5.c
@@ -20,6 +20,7 @@
 #include "includes.h"
 #include "smb_krb5.h"
 #include "secrets.h"
+#include "librpc/gen_ndr/secrets.h"
 #include "gse_krb5.h"
 #include "lib/param/loadparm.h"
 #include "libads/kerberos_proto.h"
@@ -85,45 +86,15 @@ out:
 	return ret;
 }
 
-static krb5_error_code get_host_principal(krb5_context krbctx,
-					  krb5_principal *host_princ)
-{
-	krb5_error_code ret;
-	char *host_princ_s = NULL;
-	int err;
-
-	err = asprintf(&host_princ_s, "%s$@%s", lp_netbios_name(), lp_realm());
-	if (err == -1) {
-		return -1;
-	}
-
-	if (!strlower_m(host_princ_s)) {
-		SAFE_FREE(host_princ_s);
-		return -1;
-	}
-	ret = smb_krb5_parse_name(krbctx, host_princ_s, host_princ);
-	if (ret) {
-		DEBUG(1, (__location__ ": smb_krb5_parse_name(%s) "
-			  "failed (%s)\n",
-			  host_princ_s, error_message(ret)));
-	}
-
-	SAFE_FREE(host_princ_s);
-	return ret;
-}
-
 static krb5_error_code fill_keytab_from_password(krb5_context krbctx,
 						 krb5_keytab keytab,
 						 krb5_principal princ,
 						 krb5_kvno vno,
-						 krb5_data *password)
+						 struct secrets_domain_info1_password *pw)
 {
 	krb5_error_code ret;
 	krb5_enctype *enctypes;
-	krb5_keytab_entry kt_entry;
-	unsigned int i;
-	krb5_principal salt_princ = NULL;
-	char *salt_princ_s = NULL;
+	uint16_t i;
 
 	ret = smb_krb5_get_allowed_etypes(krbctx, &enctypes);
 	if (ret) {
@@ -132,61 +103,47 @@ static krb5_error_code fill_keytab_from_password(krb5_context krbctx,
 		return ret;
 	}
 
-	salt_princ_s = kerberos_secrets_fetch_salt_princ();
-	if (salt_princ_s == NULL) {
-		ret = ENOMEM;
-		goto out;
-	}
-	ret = krb5_parse_name(krbctx, salt_princ_s, &salt_princ);
-	SAFE_FREE(salt_princ_s);
-	if (ret != 0) {
-		goto out;
-	}
-
-	for (i = 0; enctypes[i]; i++) {
+	for (i = 0; i < pw->num_keys; i++) {
+		krb5_keytab_entry kt_entry;
 		krb5_keyblock *key = NULL;
-		int rc;
+		unsigned int ei;
+		bool found_etype = false;
 
-		if (!(key = SMB_MALLOC_P(krb5_keyblock))) {
-			ret = ENOMEM;
-			goto out;
+		for (ei=0; enctypes[ei] != 0; ei++) {
+			if ((uint32_t)enctypes[ei] != pw->keys[i].keytype) {
+				continue;
+			}
+
+			found_etype = true;
+			break;
 		}
 
-		rc = create_kerberos_key_from_string(krbctx,
-						     princ,
-						     salt_princ,
-						     password,
-						     key,
-						     enctypes[i],
-						     false);
-		if (rc != 0) {
-			DEBUG(10, ("Failed to create key for enctype %d "
-				   "(error: %s)\n",
-				   enctypes[i], error_message(ret)));
-			SAFE_FREE(key);
+		if (!found_etype) {
 			continue;
 		}
 
+		ZERO_STRUCT(kt_entry);
 		kt_entry.principal = princ;
 		kt_entry.vno = vno;
-		*(KRB5_KT_KEY(&kt_entry)) = *key;
+
+		key = KRB5_KT_KEY(&kt_entry);
+		KRB5_KEY_TYPE(key) = pw->keys[i].keytype;
+		KRB5_KEY_DATA(key) = pw->keys[i].value.data;
+		KRB5_KEY_LENGTH(key) = pw->keys[i].value.length;
 
 		ret = krb5_kt_add_entry(krbctx, keytab, &kt_entry);
 		if (ret) {
 			DEBUG(1, (__location__ ": Failed to add entry to "
 				  "keytab for enctype %d (error: %s)\n",
-				   enctypes[i], error_message(ret)));
-			krb5_free_keyblock(krbctx, key);
+				  (unsigned)pw->keys[i].keytype,
+				  error_message(ret)));
 			goto out;
 		}
-
-		krb5_free_keyblock(krbctx, key);
 	}
 
 	ret = 0;
 
 out:
-	krb5_free_principal(krbctx, salt_princ);
 	SAFE_FREE(enctypes);
 	return ret;
 }
@@ -197,27 +154,43 @@ out:
 static krb5_error_code fill_mem_keytab_from_secrets(krb5_context krbctx,
 						    krb5_keytab *keytab)
 {
+	TALLOC_CTX *frame = talloc_stackframe();
 	krb5_error_code ret;
-	char *pwd = NULL;
-	size_t pwd_len;
+	const char *domain = lp_workgroup();
+	struct secrets_domain_info1 *info = NULL;
+	const char *realm = NULL;
+	const DATA_BLOB *ct = NULL;
 	krb5_kt_cursor kt_cursor;
 	krb5_keytab_entry kt_entry;
-	krb5_data password;
 	krb5_principal princ = NULL;
 	krb5_kvno kvno = 0; /* FIXME: fetch current vno from KDC ? */
-	char *pwd_old = NULL;
+	NTSTATUS status;
 
 	if (!secrets_init()) {
 		DEBUG(1, (__location__ ": secrets_init failed\n"));
+		TALLOC_FREE(frame);
 		return KRB5_CONFIG_CANTOPEN;
 	}
 
-	pwd = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
-	if (!pwd) {
-		DEBUG(2, (__location__ ": failed to fetch machine password\n"));
+	status = secrets_fetch_or_upgrade_domain_info(domain,
+						      frame,
+						      &info);
+	if (!NT_STATUS_IS_OK(status)) {
+		DBG_WARNING("secrets_fetch_or_upgrade_domain_info(%s) - %s\n",
+			    domain, nt_errstr(status));
+		TALLOC_FREE(frame);
 		return KRB5_LIBOS_CANTREADPWD;
 	}
-	pwd_len = strlen(pwd);
+	ct = &info->password->cleartext_blob;
+
+	if (info->domain_info.dns_domain.string != NULL) {
+		realm = strupper_talloc(frame,
+				info->domain_info.dns_domain.string);
+		if (realm == NULL) {
+			TALLOC_FREE(frame);
+			return ENOMEM;
+		}
+	}
 
 	ZERO_STRUCT(kt_entry);
 	ZERO_STRUCT(kt_cursor);
@@ -249,9 +222,9 @@ static krb5_error_code fill_mem_keytab_from_secrets(krb5_context krbctx,
 			/* found private entry,
 			 * check if keytab is up to date */
 
-			if ((pwd_len == KRB5_KEY_LENGTH(KRB5_KT_KEY(&kt_entry))) &&
+			if ((ct->length == KRB5_KEY_LENGTH(KRB5_KT_KEY(&kt_entry))) &&
 			    (memcmp(KRB5_KEY_DATA(KRB5_KT_KEY(&kt_entry)),
-						pwd, pwd_len) == 0)) {
+						ct->data, ct->length) == 0)) {
 				/* keytab is already up to date, return */
 				smb_krb5_kt_free_entry(krbctx, &kt_entry);
 				goto out;
@@ -277,32 +250,51 @@ static krb5_error_code fill_mem_keytab_from_secrets(krb5_context krbctx,
 
 	/* keytab is not up to date, fill it up */
 
-	ret = get_host_principal(krbctx, &princ);
+	ret = smb_krb5_make_principal(krbctx, &princ, realm,
+				      info->account_name, NULL);
 	if (ret) {
 		DEBUG(1, (__location__ ": Failed to get host principal!\n"));
 		goto out;
 	}
 
-	password.data = pwd;
-	password.length = pwd_len;
 	ret = fill_keytab_from_password(krbctx, *keytab,
-					princ, kvno, &password);
+					princ, kvno,
+					info->password);
 	if (ret) {
-		DEBUG(1, (__location__ ": Failed to fill memory keytab!\n"));
+		DBG_WARNING("fill_keytab_from_password() failed for "
+			    "info->password.\n.");
 		goto out;
 	}
 
-	pwd_old = secrets_fetch_prev_machine_password(lp_workgroup());
-	if (!pwd_old) {
-		DEBUG(10, (__location__ ": no prev machine password\n"));
-	} else {
-		password.data = pwd_old;
-		password.length = strlen(pwd_old);
+	if (info->old_password != NULL) {
+		ret = fill_keytab_from_password(krbctx, *keytab,
+						princ, kvno - 1,
+						info->old_password);
+		if (ret) {
+			DBG_WARNING("fill_keytab_from_password() failed for "
+				    "info->old_password.\n.");
+			goto out;
+		}
+	}
+
+	if (info->older_password != NULL) {
 		ret = fill_keytab_from_password(krbctx, *keytab,
-						princ, kvno -1, &password);
+						princ, kvno - 2,
+						info->older_password);
 		if (ret) {
-			DEBUG(1, (__location__
-				  ": Failed to fill memory keytab!\n"));
+			DBG_WARNING("fill_keytab_from_password() failed for "
+				    "info->older_password.\n.");
+			goto out;
+		}
+	}
+
+	if (info->next_change != NULL) {
+		ret = fill_keytab_from_password(krbctx, *keytab,
+						princ, kvno - 3,
+						info->next_change->password);
+		if (ret) {
+			DBG_WARNING("fill_keytab_from_password() failed for "
+				    "info->next_change->password.\n.");
 			goto out;
 		}
 	}
@@ -314,8 +306,8 @@ static krb5_error_code fill_mem_keytab_from_secrets(krb5_context krbctx,
 	kt_entry.vno = 0;
 
 	KRB5_KEY_TYPE(KRB5_KT_KEY(&kt_entry)) = CLEARTEXT_PRIV_ENCTYPE;
-	KRB5_KEY_LENGTH(KRB5_KT_KEY(&kt_entry)) = pwd_len;
-	KRB5_KEY_DATA(KRB5_KT_KEY(&kt_entry)) = (uint8_t *)pwd;
+	KRB5_KEY_LENGTH(KRB5_KT_KEY(&kt_entry)) = ct->length;
+	KRB5_KEY_DATA(KRB5_KT_KEY(&kt_entry)) = ct->data;
 
 	ret = krb5_kt_add_entry(krbctx, *keytab, &kt_entry);
 	if (ret) {
@@ -328,9 +320,6 @@ static krb5_error_code fill_mem_keytab_from_secrets(krb5_context krbctx,
 	ret = 0;
 
 out:
-	SAFE_FREE(pwd);
-	SAFE_FREE(pwd_old);
-
 	if (!all_zero((uint8_t *)&kt_cursor, sizeof(kt_cursor)) && *keytab) {
 		krb5_kt_end_seq_get(krbctx, *keytab, &kt_cursor);
 	}
@@ -339,6 +328,7 @@ out:
 		krb5_free_principal(krbctx, princ);
 	}
 
+	TALLOC_FREE(frame);
 	return ret;
 }
 
diff --git a/source3/passdb/machine_account_secrets.c b/source3/passdb/machine_account_secrets.c
index 3d1cb5b..5a0f7a8 100644
--- a/source3/passdb/machine_account_secrets.c
+++ b/source3/passdb/machine_account_secrets.c
@@ -832,7 +832,8 @@ static NTSTATUS secrets_store_domain_info1_by_key(const char *key,
 	return NT_STATUS_OK;
 }
 
-static NTSTATUS secrets_store_domain_info(const struct secrets_domain_info1 *info)
+static NTSTATUS secrets_store_domain_info(const struct secrets_domain_info1 *info,
+					  bool upgrade)
 {
 	TALLOC_CTX *frame = talloc_stackframe();
 	const char *domain = info->domain_info.name.string;
@@ -853,7 +854,7 @@ static NTSTATUS secrets_store_domain_info(const struct secrets_domain_info1 *inf
 	switch (info->secure_channel_type) {
 	case SEC_CHAN_WKSTA:


-- 
Samba Shared Repository



More information about the samba-cvs mailing list