[SCM] Samba Shared Repository - branch master updated

Andrew Tridgell tridge at samba.org
Fri Aug 20 04:34:29 MDT 2010


The branch, master has been updated
       via  0cc3525... s4-dsdb: the RODC_JOIN control also changes samAccountName
       via  3d13c9e... s4-pysamdb: fixed get_domain_sid()
       via  a662bdc... s4-ldb: added support for rodc_control in ldb
       via  f1c6bab... s4-drs: fixed the error code for EXOP_REPL_SECRET getncchanges calls
       via  4cc6b5a... s4-drs: bring us much closer to the docs for DRS secret replication
       via  6eb34e6... s4-dsdb: fixed dsdb_get_extended_dn_sid()
       via  ba079f9... idl: added the RODC allow/deny secrets RIDs
       via  c122939... s4-drs: implement RODC attribute filtering override
       via  dc7cf47... s4-drs: added sam_ctx_system on DRS bind state
      from  34092c1... s3:loadparm: make lp_load_ex static. We have wrappers for external callers.

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


- Log -----------------------------------------------------------------
commit 0cc3525c039e08bee32199109a515fa08933b31d
Author: Andrew Tridgell <tridge at samba.org>
Date:   Fri Aug 20 17:17:23 2010 +1000

    s4-dsdb: the RODC_JOIN control also changes samAccountName
    
    when adding a user with the RODC_JOIN control, the samAccountName is
    automatically set to the krbtgt_NNNNN form
    
    Pair-Programmed-With: Andrew Bartlett <abartlet at samba.org>

commit 3d13c9e53a25a3af73c520a0ecfa35eafc80784c
Author: Andrew Tridgell <tridge at samba.org>
Date:   Fri Aug 20 07:26:53 2010 +1000

    s4-pysamdb: fixed get_domain_sid()
    
    we need to actually return the SID!
    
    Pair-Programmed-With: Andrew Bartlett <abartlet at samba.org>

commit a662bdc0243743f0e6ff7327cca247f1e3e76e84
Author: Andrew Tridgell <tridge at samba.org>
Date:   Fri Aug 20 07:26:09 2010 +1000

    s4-ldb: added support for rodc_control in ldb
    
    this allows you to specify the RODC join control in python ldb calls
    or on the command line
    
    Pair-Programmed-With: Andrew Bartlett <abartlet at samba.org>

commit f1c6bab60e52624f5f3188689eb9452a0fdc9221
Author: Andrew Tridgell <tridge at samba.org>
Date:   Thu Aug 19 13:06:08 2010 +1000

    s4-drs: fixed the error code for EXOP_REPL_SECRET getncchanges calls
    
    when we deny a EXOP_REPL_SECRET call we should set the exop error code
    to NONE, and the main return code to WERR_DS_DRA_ACCESS_DENIED (based
    on observing windows server behaviour)
    
    Pair-Programmed-With: Andrew Bartlett <abartlet at samba.org>

commit 4cc6b5a69b1f94d96a73ac15d58ff71d2e4febfd
Author: Andrew Tridgell <tridge at samba.org>
Date:   Wed Aug 18 18:38:26 2010 +1000

    s4-drs: bring us much closer to the docs for DRS secret replication
    
    The rules for when a RODC can replicate secrets are:
    
     - it can always replicate its own acct
     - it can also replicate its krbtgt acct
     - it can't replicate other krbtgt accts
     - it can't replicate interdomain trust accounts
     - it can't replicate users in the denied group list
     - it can replicate users in the allowed group list
    
    otherwise it can't replicate
    
    Pair-Programmed-With: Andrew Bartlett <abartlet at samba.org>

commit 6eb34e69078630f1795a75d186eccf50e1f3c683
Author: Andrew Tridgell <tridge at samba.org>
Date:   Wed Aug 18 18:36:12 2010 +1000

    s4-dsdb: fixed dsdb_get_extended_dn_sid()
    
    it should honor the component_name
    
    Pair-Programmed-With: Andrew Bartlett <abartlet at samba.org>

commit ba079f9d674417eed26c21d21f0e0ff03a3c5e33
Author: Andrew Tridgell <tridge at samba.org>
Date:   Wed Aug 18 18:35:41 2010 +1000

    idl: added the RODC allow/deny secrets RIDs
    
    Pair-Programmed-With: Andrew Bartlett <abartlet at samba.org>

commit c12293991988bda16ff85135e83c21d23d08abca
Author: Andrew Tridgell <tridge at samba.org>
Date:   Wed Aug 18 14:31:05 2010 +1000

    s4-drs: implement RODC attribute filtering override
    
    When a RODC uses extended getncchanges operation
    DRSUAPI_EXOP_REPL_SECRET it gets an override on the ability to
    replicate the secret attributes.
    
    Pair-Programmed-With: Andrew Bartlett <abartlet at samba.org>

commit dc7cf47371e15a1bfe8c97341773076f00c67aa1
Author: Andrew Tridgell <tridge at samba.org>
Date:   Wed Aug 18 14:27:17 2010 +1000

    s4-drs: added sam_ctx_system on DRS bind state
    
    The getncchanges call needs to be able to access the sam as the system
    user for RODC clients. To do this it needs a sam_ctx connection with
    system credentials
    
    Pair-Programmed-With: Andrew Bartlett <abartlet at samba.org>

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

Summary of changes:
 librpc/idl/security.idl                     |    2 +
 source4/dsdb/common/util.c                  |   46 +++--
 source4/dsdb/samdb/ldb_modules/samldb.c     |   22 +-
 source4/lib/ldb/common/ldb_controls.c       |   27 +++
 source4/rpc_server/drsuapi/dcesrv_drsuapi.c |   19 ++
 source4/rpc_server/drsuapi/dcesrv_drsuapi.h |    1 +
 source4/rpc_server/drsuapi/getncchanges.c   |  318 ++++++++++++++++++++++++---
 source4/scripting/python/samba/samdb.py     |    2 +-
 8 files changed, 380 insertions(+), 57 deletions(-)


Changeset truncated at 500 lines:

diff --git a/librpc/idl/security.idl b/librpc/idl/security.idl
index 68ed485..5594542 100644
--- a/librpc/idl/security.idl
+++ b/librpc/idl/security.idl
@@ -292,6 +292,8 @@ interface security
 	const int DOMAIN_RID_POLICY_ADMINS           = 520;
 	const int DOMAIN_RID_READONLY_DCS            = 521;
 	const int DOMAIN_RID_RAS_SERVERS             = 553;
+	const int DOMAIN_RID_RODC_ALLOW              = 571;
+	const int DOMAIN_RID_RODC_DENY               = 572;
 
 	/* well-known builtin RIDs */
 	const int BUILTIN_RID_ADMINISTRATORS		= 544;
diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c
index cf13b64..fc117b9 100644
--- a/source4/dsdb/common/util.c
+++ b/source4/dsdb/common/util.c
@@ -3112,7 +3112,7 @@ NTSTATUS dsdb_get_extended_dn_sid(struct ldb_dn *dn, struct dom_sid *sid, const
 	struct TALLOC_CTX *tmp_ctx;
 	enum ndr_err_code ndr_err;
 
-	sid_blob = ldb_dn_get_extended_component(dn, "SID");
+	sid_blob = ldb_dn_get_extended_component(dn, component_name);
 	if (!sid_blob) {
 		return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 	}
@@ -3940,29 +3940,43 @@ int dsdb_validate_dsa_guid(struct ldb_context *ldb,
 	return LDB_SUCCESS;
 }
 
-const char *rodc_fas_list[] = {"ms-PKI-DPAPIMasterKeys",
-			       "ms-PKI-AccountCredentials",
-			       "ms-PKI-RoamingTimeStamp",
-			       "ms-FVE-KeyPackage",
-			       "ms-FVE-RecoveryGuid",
-			       "ms-FVE-RecoveryInformation",
-			       "ms-FVE-RecoveryPassword",
-			       "ms-FVE-VolumeGuid",
-			       "ms-TPM-OwnerInformation",
-			       NULL};
+static const char *secret_attributes[] = {
+	"currentValue",
+	"dBCSPwd",
+	"initialAuthIncoming",
+	"initialAuthOutgoing",
+	"lmPwdHistory",
+	"ntPwdHistory",
+	"priorValue",
+	"supplementalCredentials",
+	"trustAuthIncoming",
+	"trustAuthOutgoing",
+	"unicodePwd",
+	NULL
+};
+
 /*
   check if the attribute belongs to the RODC filtered attribute set
+  Note that attributes that are in the filtered attribute set are the
+  ones that _are_ always sent to a RODC
 */
-bool dsdb_attr_in_rodc_fas(uint32_t replica_flags, const struct dsdb_attribute *sa)
+bool dsdb_attr_in_rodc_fas(const struct dsdb_attribute *sa)
 {
-	int rodc_filtered_flags = SEARCH_FLAG_RODC_ATTRIBUTE | SEARCH_FLAG_CONFIDENTIAL;
-	bool drs_write_replica = ((replica_flags & DRSUAPI_DRS_WRIT_REP) == 0);
+	/* they never get secret attributes */
+	if (is_attr_in_list(secret_attributes, sa->lDAPDisplayName)) {
+		return false;
+	}
 
-	if (drs_write_replica && (sa->searchFlags & rodc_filtered_flags)) {
+	/* they do get non-secret critical attributes */
+	if (sa->schemaFlagsEx & SCHEMA_FLAG_ATTR_IS_CRITICAL) {
 		return true;
 	}
-	if (drs_write_replica && is_attr_in_list(rodc_fas_list, sa->cn)) {
+
+	/* they do get non-secret attributes marked as being in the FAS  */
+	if (sa->searchFlags & SEARCH_FLAG_RODC_ATTRIBUTE) {
 		return true;
 	}
+
+	/* other attributes are denied */
 	return false;
 }
diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c
index a12b189..e657381 100644
--- a/source4/dsdb/samdb/ldb_modules/samldb.c
+++ b/source4/dsdb/samdb/ldb_modules/samldb.c
@@ -410,6 +410,11 @@ found:
 		return ldb_operr(ldb);
 	}
 
+	ret = ldb_msg_add_fmt(ac->msg, "samAccountName", "krbtgt_%u", krbtgt_number);
+	if (ret != LDB_SUCCESS) {
+		return ldb_operr(ldb);
+	}
+
 	return samldb_next_step(ac);
 }
 
@@ -986,6 +991,14 @@ static int samldb_fill_object(struct samldb_ctx *ac, const char *type)
 		return LDB_ERR_OPERATIONS_ERROR;
 	}
 
+	rodc_control = ldb_request_get_control(ac->req, LDB_CONTROL_RODC_DCPROMO_OID);
+	if (rodc_control) {
+		/* see [MS-ADTS] 3.1.1.3.4.1.23 LDAP_SERVER_RODC_DCPROMO_OID */
+		rodc_control->critical = false;
+		ret = samldb_add_step(ac, samldb_rodc_add);
+		if (ret != LDB_SUCCESS) return ret;
+	}
+
 	/* check if we have a valid samAccountName */
 	ret = samldb_add_step(ac, samldb_check_samAccountName);
 	if (ret != LDB_SUCCESS) return ret;
@@ -1024,15 +1037,6 @@ static int samldb_fill_object(struct samldb_ctx *ac, const char *type)
 		}
 	}
 
-	rodc_control = ldb_request_get_control(ac->req, LDB_CONTROL_RODC_DCPROMO_OID);
-	if (rodc_control) {
-		/* see [MS-ADTS] 3.1.1.3.4.1.23 LDAP_SERVER_RODC_DCPROMO_OID */
-		rodc_control->critical = false;
-		ret = samldb_add_step(ac, samldb_rodc_add);
-		if (ret != LDB_SUCCESS) return ret;
-	}
-
-
 	/* finally proceed with adding the entry */
 	ret = samldb_add_step(ac, samldb_add_entry);
 	if (ret != LDB_SUCCESS) return ret;
diff --git a/source4/lib/ldb/common/ldb_controls.c b/source4/lib/ldb/common/ldb_controls.c
index d75221e..769761d 100644
--- a/source4/lib/ldb/common/ldb_controls.c
+++ b/source4/lib/ldb/common/ldb_controls.c
@@ -890,6 +890,33 @@ struct ldb_control **ldb_parse_control_strings(struct ldb_context *ldb, TALLOC_C
 			continue;
 		}
 
+		if (strncmp(control_strings[i], "rodc_join:", 10) == 0) {
+			const char *p;
+			int crit, ret;
+
+			p = &(control_strings[i][10]);
+			ret = sscanf(p, "%d", &crit);
+			if ((ret != 1) || (crit < 0) || (crit > 1)) {
+				error_string = talloc_asprintf(mem_ctx, "invalid rodc_join control syntax\n");
+				error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
+				error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
+				ldb_set_errstring(ldb, error_string);
+				talloc_free(error_string);
+				return NULL;
+			}
+
+			ctrl[i] = talloc(ctrl, struct ldb_control);
+			if (!ctrl[i]) {
+				ldb_oom(ldb);
+				return NULL;
+			}
+			ctrl[i]->oid = LDB_CONTROL_RODC_DCPROMO_OID;
+			ctrl[i]->critical = crit;
+			ctrl[i]->data = NULL;
+
+			continue;
+		}
+
 		/* no controls matched, throw an error */
 		ldb_asprintf_errstring(ldb, "Invalid control name: '%s'", control_strings[i]);
 		return NULL;
diff --git a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c
index a46937b..95113dd 100644
--- a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c
+++ b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c
@@ -57,6 +57,7 @@ static WERROR dcesrv_drsuapi_DsBind(struct dcesrv_call_state *dce_call, TALLOC_C
 	int ret;
 	struct auth_session_info *auth_info;
 	WERROR werr;
+	bool connected_as_system = false;
 
 	r->out.bind_info = NULL;
 	ZERO_STRUCTP(r->out.bind_handle);
@@ -69,6 +70,7 @@ static WERROR dcesrv_drsuapi_DsBind(struct dcesrv_call_state *dce_call, TALLOC_C
 	if (W_ERROR_IS_OK(werr)) {
 		DEBUG(3,(__location__ ": doing DsBind with system_session\n"));
 		auth_info = system_session(dce_call->conn->dce_ctx->lp_ctx);
+		connected_as_system = true;
 	} else {
 		auth_info = dce_call->conn->auth_state.session_info;
 	}
@@ -82,6 +84,23 @@ static WERROR dcesrv_drsuapi_DsBind(struct dcesrv_call_state *dce_call, TALLOC_C
 		return WERR_FOOBAR;
 	}
 
+	if (connected_as_system) {
+		b_state->sam_ctx_system = b_state->sam_ctx;
+	} else {
+		/* an RODC also needs system samdb access for secret
+		   attribute replication */
+		werr = drs_security_level_check(dce_call, NULL, SECURITY_RO_DOMAIN_CONTROLLER,
+						samdb_domain_sid(b_state->sam_ctx));
+		if (W_ERROR_IS_OK(werr)) {
+			b_state->sam_ctx_system = samdb_connect(b_state, dce_call->event_ctx,
+								dce_call->conn->dce_ctx->lp_ctx,
+								system_session(dce_call->conn->dce_ctx->lp_ctx));
+			if (!b_state->sam_ctx_system) {
+				return WERR_FOOBAR;
+			}
+		}
+	}
+
 	/*
 	 * find out the guid of our own site
 	 */
diff --git a/source4/rpc_server/drsuapi/dcesrv_drsuapi.h b/source4/rpc_server/drsuapi/dcesrv_drsuapi.h
index 04bb3db..818813e 100644
--- a/source4/rpc_server/drsuapi/dcesrv_drsuapi.h
+++ b/source4/rpc_server/drsuapi/dcesrv_drsuapi.h
@@ -31,6 +31,7 @@ enum drsuapi_handle {
 */
 struct drsuapi_bind_state {
 	struct ldb_context *sam_ctx;
+	struct ldb_context *sam_ctx_system;
 	struct GUID remote_bind_guid;
 	struct drsuapi_DsBindInfo28 remote_info28;
 	struct drsuapi_DsBindInfo28 local_info28;
diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c
index 23edf6d..8648d5d 100644
--- a/source4/rpc_server/drsuapi/getncchanges.c
+++ b/source4/rpc_server/drsuapi/getncchanges.c
@@ -26,6 +26,7 @@
 #include "param/param.h"
 #include "librpc/gen_ndr/ndr_drsblobs.h"
 #include "librpc/gen_ndr/ndr_drsuapi.h"
+#include "librpc/gen_ndr/ndr_security.h"
 #include "rpc_server/drsuapi/dcesrv_drsuapi.h"
 #include "rpc_server/dcerpc_server_proto.h"
 #include "../libcli/drsuapi/drsuapi.h"
@@ -33,6 +34,7 @@
 #include "lib/util/binsearch.h"
 #include "lib/util/tsort.h"
 #include "auth/session.h"
+#include "dsdb/common/util.h"
 
 /*
   build a DsReplicaObjectIdentifier from a ldb msg
@@ -95,7 +97,8 @@ static WERROR get_nc_changes_build_object(struct drsuapi_DsReplicaObjectListItem
 					  DATA_BLOB *session_key,
 					  uint64_t highest_usn,
 					  uint32_t replica_flags,
-					  struct drsuapi_DsReplicaCursorCtrEx *uptodateness_vector)
+					  struct drsuapi_DsReplicaCursorCtrEx *uptodateness_vector,
+					  enum drsuapi_DsExtendedOperation extended_op)
 {
 	const struct ldb_val *md_value;
 	unsigned int i, n;
@@ -177,9 +180,12 @@ static WERROR get_nc_changes_build_object(struct drsuapi_DsReplicaObjectListItem
 	obj->meta_data_ctr->meta_data = talloc_array(obj, struct drsuapi_DsReplicaMetaData, md.ctr.ctr1.count);
 	for (n=i=0; i<md.ctr.ctr1.count; i++) {
 		const struct dsdb_attribute *sa;
+		bool force_attribute = false;
+
 		/* if the attribute has not changed, and it is not the
 		   instanceType then don't include it */
 		if (md.ctr.ctr1.array[i].local_usn < highest_usn &&
+		    extended_op != DRSUAPI_EXOP_REPL_SECRET &&
 		    md.ctr.ctr1.array[i].attid != DRSUAPI_ATTRIBUTE_instanceType) continue;
 
 		/* don't include the rDN */
@@ -202,8 +208,16 @@ static WERROR get_nc_changes_build_object(struct drsuapi_DsReplicaObjectListItem
 			}
 		}
 
+		if (extended_op == DRSUAPI_EXOP_REPL_SECRET &&
+		    !dsdb_attr_in_rodc_fas(sa)) {
+			force_attribute = true;
+			DEBUG(4,("Forcing attribute %s in %s\n",
+				 sa->lDAPDisplayName, ldb_dn_get_linearized(msg->dn)));
+		}
+
 		/* filter by uptodateness_vector */
 		if (md.ctr.ctr1.array[i].attid != DRSUAPI_ATTRIBUTE_instanceType &&
+		    !force_attribute &&
 		    udv_filter(uptodateness_vector,
 			       &md.ctr.ctr1.array[i].originating_invocation_id, 
 			       md.ctr.ctr1.array[i].originating_usn)) {
@@ -211,15 +225,20 @@ static WERROR get_nc_changes_build_object(struct drsuapi_DsReplicaObjectListItem
 		}
 
 		/*
-		 * If the recipient is a RODC, then we should not add any
-		 * RODC filtered attribute
+		 * If the recipient is a RODC, then we should only give
+		 * attributes from the RODC filtered attribute set
 		 *
 		 * TODO: This is not strictly correct, as it doesn't allow for administrators
 		 * to setup some users to transfer passwords to specific RODCs. To support that
 		 * we would instead remove this check and rely on extended ACL checking in the dsdb
 		 * acl module.
 		 */
-		if (dsdb_attr_in_rodc_fas(replica_flags, sa)) {
+		if (!(replica_flags & DRSUAPI_DRS_WRIT_REP) &&
+		    !force_attribute &&
+		    !dsdb_attr_in_rodc_fas(sa)) {
+			DEBUG(4,("Skipping non-FAS attr %s in %s\n",
+				 sa->lDAPDisplayName,
+				 ldb_dn_get_linearized(msg->dn)));
 			continue;
 		}
 
@@ -660,6 +679,228 @@ static WERROR getncchanges_rid_alloc(struct drsuapi_bind_state *b_state,
 	return WERR_OK;
 }
 
+/*
+  return an array of SIDs from a ldb_message given an attribute name
+  assumes the SIDs are in extended DN format
+ */
+static WERROR samdb_result_sid_array_dn(struct ldb_context *sam_ctx,
+					struct ldb_message *msg,
+					TALLOC_CTX *mem_ctx,
+					const char *attr,
+					const struct dom_sid ***sids)
+{
+	struct ldb_message_element *el;
+	int i;
+
+	el = ldb_msg_find_element(msg, attr);
+	if (!el) {
+		*sids = NULL;
+		return WERR_OK;
+	}
+
+	(*sids) = talloc_array(mem_ctx, const struct dom_sid *, el->num_values + 1);
+	W_ERROR_HAVE_NO_MEMORY(*sids);
+
+	for (i=0; i<el->num_values; i++) {
+		struct ldb_dn *dn = ldb_dn_from_ldb_val(mem_ctx, sam_ctx, &el->values[i]);
+		NTSTATUS status;
+		struct dom_sid *sid;
+
+		sid = talloc(*sids, struct dom_sid);
+		W_ERROR_HAVE_NO_MEMORY(sid);
+		status = dsdb_get_extended_dn_sid(dn, sid, "SID");
+		if (!NT_STATUS_IS_OK(status)) {
+			return WERR_INTERNAL_DB_CORRUPTION;
+		}
+		(*sids)[i] = sid;
+	}
+	(*sids)[i] = NULL;
+
+	return WERR_OK;
+}
+
+
+/*
+  return an array of SIDs from a ldb_message given an attribute name
+  assumes the SIDs are in NDR form
+ */
+static WERROR samdb_result_sid_array_ndr(struct ldb_context *sam_ctx,
+					 struct ldb_message *msg,
+					 TALLOC_CTX *mem_ctx,
+					 const char *attr,
+					 const struct dom_sid ***sids)
+{
+	struct ldb_message_element *el;
+	int i;
+
+	el = ldb_msg_find_element(msg, attr);
+	if (!el) {
+		*sids = NULL;
+		return WERR_OK;
+	}
+
+	(*sids) = talloc_array(mem_ctx, const struct dom_sid *, el->num_values + 1);
+	W_ERROR_HAVE_NO_MEMORY(*sids);
+
+	for (i=0; i<el->num_values; i++) {
+		enum ndr_err_code ndr_err;
+		struct dom_sid *sid;
+
+		sid = talloc(*sids, struct dom_sid);
+		W_ERROR_HAVE_NO_MEMORY(sid);
+
+		ndr_err = ndr_pull_struct_blob(&el->values[i], sid, sid,
+					       (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
+		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+			return WERR_INTERNAL_DB_CORRUPTION;
+		}
+		(*sids)[i] = sid;
+	}
+	(*sids)[i] = NULL;
+
+	return WERR_OK;
+}
+
+/*
+  see if any SIDs in list1 are in list2
+ */
+static bool sid_list_match(const struct dom_sid **list1, const struct dom_sid **list2)
+{
+	int i, j;
+	/* do we ever have enough SIDs here to worry about O(n^2) ? */
+	for (i=0; list1[i]; i++) {
+		for (j=0; list2[j]; j++) {
+			if (dom_sid_equal(list1[i], list2[j])) {
+				return true;
+			}
+		}
+	}
+	return false;
+}
+
+/*
+  handle a DRSUAPI_EXOP_REPL_SECRET call
+ */
+static WERROR getncchanges_repl_secret(struct drsuapi_bind_state *b_state,
+				       TALLOC_CTX *mem_ctx,
+				       struct drsuapi_DsGetNCChangesRequest8 *req8,
+				       struct dom_sid *user_sid,
+				       struct drsuapi_DsGetNCChangesCtr6 *ctr6)
+{
+	struct drsuapi_DsReplicaObjectIdentifier *ncRoot = req8->naming_context;
+	struct ldb_dn *obj_dn, *rodc_dn, *krbtgt_link_dn;
+	int ret;
+	const char *rodc_attrs[] = { "msDS-KrbTgtLink", "msDS-NeverRevealGroup", "msDS-RevealOnDemandGroup", NULL };
+	const char *obj_attrs[] = { "tokenGroups", "objectSid", "UserAccountControl", "msDS-KrbTgtLinkBL", NULL };
+	struct ldb_result *rodc_res, *obj_res;
+	const struct dom_sid **never_reveal_sids, **reveal_sids, **token_sids;
+	WERROR werr;
+
+	DEBUG(3,(__location__ ": DRSUAPI_EXOP_REPL_SECRET extended op on %s\n", ncRoot->dn));
+
+	/*
+	 * we need to work out if we will allow this RODC to
+	 * replicate the secrets for this object
+	 *
+	 * see 4.1.10.5.14 GetRevealSecretsPolicyForUser for details
+	 * of this function
+	 */
+
+	if (b_state->sam_ctx_system == NULL) {
+		/* this operation needs system level access */
+		ctr6->extended_ret = DRSUAPI_EXOP_ERR_ACCESS_DENIED;
+		return WERR_DS_DRA_SOURCE_DISABLED;
+	}
+
+	obj_dn = ldb_dn_new(mem_ctx, b_state->sam_ctx_system, ncRoot->dn);
+	if (!ldb_dn_validate(obj_dn)) goto failed;
+
+	rodc_dn = ldb_dn_new_fmt(mem_ctx, b_state->sam_ctx_system, "<SID=%s>",
+				 dom_sid_string(mem_ctx, user_sid));
+	if (!ldb_dn_validate(rodc_dn)) goto failed;
+
+	/* do the two searches we need */
+	ret = dsdb_search_dn(b_state->sam_ctx_system, mem_ctx, &rodc_res, rodc_dn, rodc_attrs,
+			     DSDB_SEARCH_SHOW_EXTENDED_DN);
+	if (ret != LDB_SUCCESS || rodc_res->count != 1) goto failed;
+
+	ret = dsdb_search_dn(b_state->sam_ctx_system, mem_ctx, &obj_res, obj_dn, obj_attrs, 0);
+	if (ret != LDB_SUCCESS || obj_res->count != 1) goto failed;
+
+	/* if the object SID is equal to the user_sid, allow */
+	if (dom_sid_equal(user_sid,
+			  samdb_result_dom_sid(mem_ctx, obj_res->msgs[0], "objectSid"))) {
+		goto allowed;
+	}
+
+	/* an RODC is allowed to get its own krbtgt account secrets */
+	krbtgt_link_dn = samdb_result_dn(b_state->sam_ctx_system, mem_ctx,
+					 rodc_res->msgs[0], "msDS-KrbTgtLink", NULL);
+	if (krbtgt_link_dn != NULL &&
+	    ldb_dn_compare(obj_dn, krbtgt_link_dn) == 0) {
+		goto allowed;
+	}
+
+	/* but it isn't allowed to get anyone elses krbtgt secrets */
+	if (samdb_result_dn(b_state->sam_ctx_system, mem_ctx,
+			    obj_res->msgs[0], "msDS-KrbTgtLinkBL", NULL)) {
+		goto denied;
+	}
+
+	if (samdb_result_uint(obj_res->msgs[0], "UserAccountControl", 0) &
+	    UF_INTERDOMAIN_TRUST_ACCOUNT) {
+		goto denied;
+	}
+
+	werr = samdb_result_sid_array_dn(b_state->sam_ctx_system, rodc_res->msgs[0],
+					 mem_ctx, "msDS-NeverRevealGroup", &never_reveal_sids);
+	if (!W_ERROR_IS_OK(werr)) {
+		goto denied;
+	}
+
+	werr = samdb_result_sid_array_dn(b_state->sam_ctx_system, rodc_res->msgs[0],
+					 mem_ctx, "msDS-RevealOnDemandGroup", &reveal_sids);
+	if (!W_ERROR_IS_OK(werr)) {
+		goto denied;
+	}
+
+	werr = samdb_result_sid_array_ndr(b_state->sam_ctx_system, obj_res->msgs[0],


-- 
Samba Shared Repository


More information about the samba-cvs mailing list