return true;
}
return false;
-
}
static int uint32_t_cmp(uint32_t a1, uint32_t a2)
}
}
+/*
+ * Similar to function in repl_meta_data without the extra
+ * dependencies.
+ */
+static WERROR get_parsed_dns_trusted(TALLOC_CTX *mem_ctx, struct ldb_message_element *el,
+ struct parsed_dn **pdn)
+{
+ /* Here we get a list of 'struct parsed_dns' without the parsing */
+ int i;
+ *pdn = talloc_zero_array(mem_ctx, struct parsed_dn,
+ el->num_values);
+ if (!*pdn) {
+ return WERR_DS_DRA_INTERNAL_ERROR;
+ }
+
+ for (i = 0; i < el->num_values; i++) {
+ (*pdn)[i].v = &el->values[i];
+ }
+
+ return WERR_OK;
+}
+
static WERROR getncchanges_update_revealed_list(struct ldb_context *sam_ctx,
TALLOC_CTX *mem_ctx,
struct ldb_message **msg,
struct ldb_dn *object_dn,
+ const struct GUID *object_guid,
const struct dsdb_attribute *sa,
struct replPropertyMetaData1 *meta_data,
struct ldb_message *revealed_users)
{
enum ndr_err_code ndr_err;
int ldb_err;
- unsigned i;
char *attr_str = NULL;
char *attr_hex = NULL;
DATA_BLOB attr_blob;
existing = ldb_msg_find_element(revealed_users, "msDS-RevealedUsers");
if (existing != NULL) {
/* Replace the old value (if one exists) with the current one */
- for (i = 0; i < existing->num_values; i++) {
- struct dsdb_dn *existing_dn = dsdb_dn_parse_trusted(mem_ctx, sam_ctx, &existing->values[i], DSDB_SYNTAX_BINARY_DN);
- if (ldb_dn_compare(object_dn, existing_dn->dn) == 0) {
- struct replPropertyMetaData1 existing_meta_data;
- ndr_err = ndr_pull_struct_blob_all_noalloc(&existing_dn->extra_part,
- &existing_meta_data,
- (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaData1);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ struct parsed_dn *link_dns;
+ struct parsed_dn *exact = NULL, *unused = NULL;
+ WERROR werr;
+ uint8_t attid[4];
+ DATA_BLOB partial_meta;
+
+ werr = get_parsed_dns_trusted(mem_ctx, existing, &link_dns);
+ if (!W_ERROR_IS_OK(werr)) {
+ return werr;
+ }
+
+ /* Construct a partial metadata blob to match on in the DB */
+ SIVAL(attid, 0, sa->attributeID_id);
+ partial_meta.length = 4;
+ partial_meta.data = attid;
+
+ /* Binary search using GUID and attribute id for uniqueness */
+ ldb_err = parsed_dn_find(sam_ctx, link_dns, existing->num_values,
+ object_guid, object_dn,
+ partial_meta, 4,
+ &exact, &unused,
+ DSDB_SYNTAX_BINARY_DN, true);
+
+ if (ldb_err != LDB_SUCCESS) {
+ DEBUG(0,(__location__ ": Failed parsed DN find - %s\n",
+ ldb_errstring(sam_ctx)));
+ return WERR_DS_DRA_INTERNAL_ERROR;
+ }
+
+ if (exact != NULL) {
+ /* Perform some verification of the blob */
+ struct replPropertyMetaData1 existing_meta_data;
+ ndr_err = ndr_pull_struct_blob_all_noalloc(&exact->dsdb_dn->extra_part,
+ &existing_meta_data,
+ (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaData1);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ return WERR_DS_DRA_INTERNAL_ERROR;
+ }
+
+ if (existing_meta_data.attid == sa->attributeID_id) {
+ ldb_err = ldb_msg_add_empty(*msg, "msDS-RevealedUsers", LDB_FLAG_MOD_DELETE, &el_del);
+ if (ldb_err != LDB_SUCCESS) {
return WERR_DS_DRA_INTERNAL_ERROR;
}
- if (existing_meta_data.attid == sa->attributeID_id) {
- ldb_err = ldb_msg_add_empty(*msg, "msDS-RevealedUsers", LDB_FLAG_MOD_DELETE, &el_del);
- if (ldb_err != LDB_SUCCESS) {
- return WERR_DS_DRA_INTERNAL_ERROR;
- }
-
- el_del->values = talloc_array((*msg)->elements, struct ldb_val, 1);
- if (el_del->values == NULL) {
- return WERR_NOT_ENOUGH_MEMORY;
- }
- el_del->values[0] = existing->values[i];
- el_del->num_values = 1;
+ el_del->values = talloc_array((*msg)->elements, struct ldb_val, 1);
+ if (el_del->values == NULL) {
+ return WERR_NOT_ENOUGH_MEMORY;
}
+ el_del->values[0] = *exact->v;
+ el_del->num_values = 1;
+ } else {
+ return WERR_DS_DRA_INTERNAL_ERROR;
}
}
}
struct replPropertyMetaDataBlob md,
struct ldb_context *sam_ctx,
const struct ldb_message *msg,
+ const struct GUID *guid,
uint32_t *count,
uint64_t highest_usn,
const struct dsdb_attribute *rdn_sa,
sa->lDAPDisplayName, ldb_dn_get_linearized(msg->dn)));
werr = getncchanges_update_revealed_list(sam_ctx, obj,
revealed_list_msg,
- msg->dn, sa,
+ msg->dn, guid, sa,
&md.ctr.ctr1.array[i],
existing_revealed_list_msg);
if (!W_ERROR_IS_OK(werr)) {
enum drsuapi_DsExtendedOperation extended_op,
bool force_object_return,
uint32_t *local_pas,
- struct ldb_dn *machine_dn)
+ struct ldb_dn *machine_dn,
+ const struct GUID *guid)
{
const struct ldb_val *md_value;
uint32_t i, n;
return WERR_DS_DRA_INTERNAL_ERROR;
}
- ldb_err = dsdb_search_dn(sam_ctx, obj, &res, machine_dn, machine_attrs, 0);
+ ldb_err = dsdb_search_dn(sam_ctx, obj, &res, machine_dn, machine_attrs, DSDB_SEARCH_SHOW_EXTENDED_DN);
if (ldb_err != LDB_SUCCESS || res->count != 1) {
ldb_transaction_cancel(sam_ctx);
return WERR_DS_DRA_INTERNAL_ERROR;
existing_revealed_list_msg = res->msgs[0];
- werr = get_nc_changes_filter_attrs(obj, md, sam_ctx, msg, &n,
- highest_usn, rdn_sa, schema,
+ werr = get_nc_changes_filter_attrs(obj, md, sam_ctx, msg,
+ guid, &n, highest_usn,
+ rdn_sa, schema,
uptodateness_vector,
partial_attribute_set, local_pas,
attids,
return WERR_DS_DRA_INTERNAL_ERROR;
}
} else {
- werr = get_nc_changes_filter_attrs(obj, md, sam_ctx, msg, &n,
- highest_usn, rdn_sa, schema,
- uptodateness_vector,
+ werr = get_nc_changes_filter_attrs(obj, md, sam_ctx, msg, guid,
+ &n, highest_usn, rdn_sa,
+ schema, uptodateness_vector,
partial_attribute_set, local_pas,
attids,
false,
/*
- return an array of SIDs from a ldb_message given an attribute name
- assumes the SIDs are in NDR form
+ * Return an array of SIDs from a ldb_message given an attribute name assumes
+ * the SIDs are in NDR form (with additional sids applied on the end).
*/
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)
+ const struct dom_sid ***sids,
+ const struct dom_sid **additional_sids,
+ unsigned int num_additional)
{
struct ldb_message_element *el;
- unsigned int i;
+ unsigned int i, j;
el = ldb_msg_find_element(msg, attr);
if (!el) {
return WERR_OK;
}
- (*sids) = talloc_array(mem_ctx, const struct dom_sid *, el->num_values + 1);
+ /* Make array long enough for NULL and additional SID */
+ (*sids) = talloc_array(mem_ctx, const struct dom_sid *,
+ el->num_values + num_additional + 1);
W_ERROR_HAVE_NO_MEMORY(*sids);
for (i=0; i<el->num_values; i++) {
}
(*sids)[i] = sid;
}
+
+ for (j = 0; j < num_additional; j++) {
+ (*sids)[i++] = additional_sids[j];
+ }
+
(*sids)[i] = NULL;
return WERR_OK;
int ret;
const char *rodc_attrs[] = { "msDS-KrbTgtLink", "msDS-NeverRevealGroup", "msDS-RevealOnDemandGroup", "objectGUID", NULL };
const char *obj_attrs[] = { "tokenGroups", "objectSid", "UserAccountControl", "msDS-KrbTgtLinkBL", NULL };
- struct ldb_result *rodc_res, *obj_res;
+ struct ldb_result *rodc_res = NULL, *obj_res = NULL;
const struct dom_sid **never_reveal_sids, **reveal_sids, **token_sids;
+ const struct dom_sid *object_sid = NULL;
WERROR werr;
+ const struct dom_sid *additional_sids[] = { NULL, NULL };
DEBUG(3,(__location__ ": DRSUAPI_EXOP_REPL_SECRET extended op on %s\n",
drs_ObjectIdentifier_to_string(mem_ctx, ncRoot)));
* Which basically means that if you have GET_ALL_CHANGES rights (~== RWDC)
* then you can do EXOP_REPL_SECRETS
*/
+ obj_dn = drs_ObjectIdentifier_to_dn(mem_ctx, b_state->sam_ctx_system, ncRoot);
+ if (!ldb_dn_validate(obj_dn)) goto failed;
+
if (has_get_all_changes) {
goto allowed;
}
- obj_dn = drs_ObjectIdentifier_to_dn(mem_ctx, b_state->sam_ctx_system, ncRoot);
- 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;
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"))) {
+ object_sid = samdb_result_dom_sid(mem_ctx, obj_res->msgs[0], "objectSid");
+ if (dom_sid_equal(user_sid, object_sid)) {
goto allowed;
}
+ additional_sids[0] = object_sid;
+
/*
* Must be an RODC account at this point, verify machine DN matches the
* SID account
goto denied;
}
+ /*
+ * The SID list needs to include itself as well as the tokenGroups.
+ *
+ * TODO determine if sIDHistory is required for this check
+ */
werr = samdb_result_sid_array_ndr(b_state->sam_ctx_system, obj_res->msgs[0],
- mem_ctx, "tokenGroups", &token_sids);
+ mem_ctx, "tokenGroups", &token_sids,
+ additional_sids, 1);
if (!W_ERROR_IS_OK(werr) || token_sids==NULL) {
goto denied;
}
allowed:
DEBUG(2,(__location__ ": Allowed single object with secret replication for %s by %s %s\n",
ldb_dn_get_linearized(obj_dn), has_get_all_changes?"RWDC":"RODC",
- ldb_dn_get_linearized(rodc_res->msgs[0]->dn)));
+ ldb_dn_get_linearized(*machine_dn)));
ctr6->extended_ret = DRSUAPI_EXOP_ERR_SUCCESS;
req10->highwatermark.highest_usn = 0;
return WERR_OK;
req10->uptodateness_vector,
req10->extended_op,
max_wait_reached,
- local_pas, machine_dn);
+ local_pas, machine_dn,
+ &getnc_state->guids[i]);
if (!W_ERROR_IS_OK(werr)) {
return werr;
}
req10->extended_op,
false, /* force_object_return */
local_pas,
- machine_dn);
+ machine_dn,
+ next_anc_guid);
if (!W_ERROR_IS_OK(werr)) {
return werr;
}
to send notifies using the GC SPN */
ureq.options |= (req10->replica_flags & DRSUAPI_DRS_REF_GCSPN);
- werr = drsuapi_UpdateRefs(b_state, mem_ctx, &ureq);
+ werr = drsuapi_UpdateRefs(dce_call->msg_ctx,
+ dce_call->event_ctx, b_state,
+ mem_ctx, &ureq);
if (!W_ERROR_IS_OK(werr)) {
DEBUG(0,(__location__ ": Failed UpdateRefs on %s for %s in DsGetNCChanges - %s\n",
drs_ObjectIdentifier_to_string(mem_ctx, ncRoot), ureq.dest_dsa_dns_name,