[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