From 607ba1a2036627d1a90c0ac03265221571dc6899 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 8 Aug 2017 14:34:14 +1200 Subject: [PATCH] s4-drsuapi: Refuse to replicate an NC is that not actually an NC This prevents replication of an OU, you must replicate a whole NC per Windows 2012R2 Signed-off-by: Andrew Bartlett Signed-off-by: Tim Beale Reviewed-by: Garming Sam --- source4/rpc_server/drsuapi/getncchanges.c | 37 ++++++++++++++++++---- source4/torture/drs/python/getnc_unpriv.py | 7 +--- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c index 1f9a35fb0b5..705d0686f34 100644 --- a/source4/rpc_server/drsuapi/getncchanges.c +++ b/source4/rpc_server/drsuapi/getncchanges.c @@ -2241,6 +2241,14 @@ allowed: } if (getnc_state == NULL) { + struct ldb_result *res = NULL; + const char *attrs[] = { + "instanceType", + "objectGuID", + NULL + }; + uint32_t nc_instanceType; + getnc_state = talloc_zero(b_state, struct drsuapi_getncchanges_state); if (getnc_state == NULL) { return WERR_NOT_ENOUGH_MEMORY; @@ -2251,14 +2259,21 @@ allowed: return WERR_NOT_ENOUGH_MEMORY; } - ret = dsdb_find_guid_by_dn(b_state->sam_ctx, - getnc_state->ncRoot_dn, - &getnc_state->ncRoot_guid); + ret = dsdb_search_dn(sam_ctx, mem_ctx, &res, + getnc_state->ncRoot_dn, attrs, + DSDB_SEARCH_SHOW_DELETED | + DSDB_SEARCH_SHOW_RECYCLED); if (ret != LDB_SUCCESS) { - DEBUG(0,(__location__ ": Failed to find GUID of ncRoot_dn %s\n", - ldb_dn_get_linearized(getnc_state->ncRoot_dn))); - return WERR_DS_DRA_INTERNAL_ERROR; + DBG_WARNING("Failed to find ncRoot_dn %s\n", + ldb_dn_get_linearized(getnc_state->ncRoot_dn)); + return WERR_DS_CANT_FIND_EXPECTED_NC; } + getnc_state->ncRoot_guid = samdb_result_guid(res->msgs[0], + "objectGUID"); + nc_instanceType = ldb_msg_find_attr_as_int(res->msgs[0], + "instanceType", + 0); + TALLOC_FREE(res); ncRoot->guid = getnc_state->ncRoot_guid; /* find out if we are to replicate Schema NC */ @@ -2279,6 +2294,16 @@ allowed: */ switch (req10->extended_op) { case DRSUAPI_EXOP_NONE: + if ((nc_instanceType & INSTANCE_TYPE_IS_NC_HEAD) == 0) { + const char *dn_str + = ldb_dn_get_linearized(getnc_state->ncRoot_dn); + + DBG_NOTICE("Rejecting full replication on " + "not NC %s", dn_str); + + return WERR_DS_CANT_FIND_EXPECTED_NC; + } + break; case DRSUAPI_EXOP_FSMO_RID_ALLOC: werr = getncchanges_rid_alloc(b_state, mem_ctx, req10, &r->out.ctr->ctr6, &search_dn); diff --git a/source4/torture/drs/python/getnc_unpriv.py b/source4/torture/drs/python/getnc_unpriv.py index 61ecefa2ea6..dd6142aa816 100644 --- a/source4/torture/drs/python/getnc_unpriv.py +++ b/source4/torture/drs/python/getnc_unpriv.py @@ -102,14 +102,9 @@ class DrsReplicaSyncUnprivTestCase(drs_base.DrsBaseTestCase): user with the correct GET_CHANGES rights """ - ou1 = "OU=single_obj,%s" % self.ou - self.ldb_dc1.add({ - "dn": ou1, - "objectclass": "organizationalUnit" - }) req8 = self._exop_req8(dest_dsa=None, invocation_id=self.ldb_dc1.get_invocation_id(), - nc_dn_str=ou1, + nc_dn_str=self.ldb_dc1.get_default_basedn(), exop=drsuapi.DRSUAPI_EXOP_NONE, replica_flags=drsuapi.DRSUAPI_DRS_WRIT_REP) (level, ctr) = self.user_drs.DsGetNCChanges(self.user_drs_handle, 8, req8)