return GUID_compare(&c1->source_dsa_invocation_id, &c2->source_dsa_invocation_id);
}
+
/*
- see if we are a RODC
+ see if a computer identified by its invocationId is a RODC
*/
-bool samdb_rodc(struct ldb_context *sam_ctx)
-{
- TALLOC_CTX *tmp_ctx;
- const char *obj_category;
- struct ldb_dn *obj_category_dn;
- const struct ldb_val *obj_category_dn_rdn_val;
+int samdb_is_rodc(struct ldb_context *sam_ctx, const struct GUID *invocationId, bool *is_rodc)
+{
+ /* 1) find the DN for this servers NTDSDSA object
+ 2) search for the msDS-isRODC attribute
+ 3) if not present then not a RODC
+ 4) if present and TRUE then is a RODC
+ */
+ struct ldb_dn *config_dn;
+ const char *attrs[] = { "msDS-isRODC", NULL };
+ int ret;
+ struct ldb_result *res;
+ TALLOC_CTX *tmp_ctx = talloc_new(sam_ctx);
- tmp_ctx = talloc_new(sam_ctx);
- if (tmp_ctx == NULL) {
- DEBUG(1,("samdb_rodc: Failed to talloc new context.\n"));
- goto failed;
+ config_dn = samdb_config_dn(sam_ctx);
+ if (!config_dn) {
+ talloc_free(tmp_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
}
- obj_category = samdb_ntds_object_category(tmp_ctx, sam_ctx);
- if (!obj_category) {
- DEBUG(1,("samdb_rodc: Failed to get object category.\n"));
- goto failed;
+ ret = dsdb_search(sam_ctx, tmp_ctx, &res, config_dn, LDB_SCOPE_SUBTREE, attrs,
+ DSDB_SEARCH_ONE_ONLY, "invocationID=%s", GUID_string(tmp_ctx, invocationId));
+ if (ret != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ return ret;
}
- obj_category_dn = ldb_dn_new(tmp_ctx, sam_ctx, obj_category);
- if (!obj_category_dn) {
- DEBUG(1,("samdb_rodc: Failed to create object category dn.\n"));
- goto failed;
- }
+ ret = ldb_msg_find_attr_as_bool(res->msgs[0], "msDS-isRODC", 0);
+ *is_rodc = (ret == 1);
- obj_category_dn_rdn_val = ldb_dn_get_rdn_val(obj_category_dn);
- if (!obj_category_dn_rdn_val) {
- DEBUG(1, ("samdb_rodc: Failed to get object category dn rdn value.\n"));
- goto failed;
- }
+ talloc_free(tmp_ctx);
+ return LDB_SUCCESS;
+}
- if (strequal((const char*)obj_category_dn_rdn_val->data, "NTDS-DSA-RO")) {
- talloc_free(tmp_ctx);
- return true;
- }
-failed:
- talloc_free(tmp_ctx);
- return false;
+/*
+ see if we are a RODC
+*/
+int samdb_rodc(struct ldb_context *sam_ctx, bool *am_rodc)
+{
+ const struct GUID *invocationId;
+ invocationId = samdb_ntds_invocation_id(sam_ctx);
+ if (!invocationId) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ return samdb_is_rodc(sam_ctx, invocationId, am_rodc);
}
+
+
/*
return NTDS options flags. See MS-ADTS 7.1.1.2.2.1.2.1.1
el = ldb_msg_find_element(transport, "bridgeheadServerListBL");
- rodc = samdb_rodc(ldb);
+ ret = samdb_rodc(ldb, &rodc);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(1, (__location__ ": unable to tell if we are an RODC: %s\n",
+ ldb_strerror(ret)));
+ talloc_free(tmp_ctx);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
transport_name = samdb_result_string(transport, "name", NULL);
if (!transport_name) {
struct ldb_dn *transports_dn;
const char * const attrs[] = { "bridgeheadServerListBL", "name",
"transportAddressAttribute", NULL };
+ int ret;
connected = true;
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- rodc = samdb_rodc(ldb);
+ ret = samdb_rodc(ldb, &rodc);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(1, (__location__ ": Unable to tell if we are an RODC: %s\n",
+ ldb_strerror(ret)));
+ talloc_free(tmp_ctx);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
for (i = 0; i < st_edge_list.count; i++) {
struct kcctpl_multi_edge *edge;
struct GUID other_site_id;
struct kcctpl_vertex *other_site_vertex;
struct ldb_result *res;
- int ret;
struct ldb_message *transport, *r_bridgehead, *l_bridgehead;
uint8_t schedule[84];
uint32_t first_available, j, interval;
char *ntds_guid_str;
char *ntds_dns_name;
struct tevent_req *subreq;
+ bool am_rodc;
+ int ret;
r = talloc(state, struct drsuapi_DsReplicaUpdateRefs);
if (tevent_req_nomem(r, req)) {
r->in.req.req1.dest_dsa_dns_name = ntds_dns_name;
r->in.req.req1.dest_dsa_guid = service->ntds_guid;
r->in.req.req1.options = DRSUAPI_DRS_ADD_REF | DRSUAPI_DRS_DEL_REF;
- if (!samdb_rodc(service->samdb)) {
+ ret = samdb_rodc(service->samdb, &am_rodc);
+ if (ret == LDB_SUCCESS && !am_rodc) {
r->in.req.req1.options |= DRSUAPI_DRS_WRIT_REP;
}
WERROR status;
struct dreplsrv_service *service;
uint32_t periodic_startup_interval;
+ bool am_rodc;
+ int ret;
switch (lp_server_role(task->lp_ctx)) {
case ROLE_STANDALONE:
}
/* if we are a RODC then we do not send DSReplicaSync*/
- if (!samdb_rodc(service->samdb)) {
+ ret = samdb_rodc(service->samdb, &am_rodc);
+ if (ret == LDB_SUCCESS && !am_rodc) {
service->notify.interval = lp_parm_int(task->lp_ctx, NULL, "dreplsrv",
"notify_interval", 5); /* in seconds */
status = dreplsrv_notify_schedule(service, service->notify.interval);
uint32_t options;
uint32_t max_objects;
struct ldb_dn *search_dn = NULL;
+ bool am_rodc;
DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE);
b_state = h->data;
r->out.ctr->ctr6.uptodateness_vector = NULL;
/* a RODC doesn't allow for any replication */
- if (samdb_rodc(b_state->sam_ctx)) {
+ ret = samdb_rodc(b_state->sam_ctx, &am_rodc);
+ if (ret == LDB_SUCCESS && am_rodc) {
DEBUG(0,(__location__ ": DsGetNCChanges attempt on RODC\n"));
return WERR_DS_DRA_SOURCE_DISABLED;
}
return WERR_DS_DRA_SOURCE_DISABLED;
}
+ if (req8->replica_flags & DRSUAPI_DRS_WRIT_REP) {
+ bool is_rodc;
+ ret = samdb_is_rodc(b_state->sam_ctx, &req8->source_dsa_invocation_id, &is_rodc);
+ if (ret != LDB_SUCCESS || is_rodc) {
+ DEBUG(0,(__location__ ": Attempt to do writeable replication by RODC %s\n",
+ GUID_string(mem_ctx, &req8->source_dsa_invocation_id)));
+ return WERR_DS_DRA_INVALID_PARAMETER;
+ }
+ }
+
if (req8->replica_flags & DRSUAPI_DRS_FULL_SYNC_PACKET) {
/* Ignore the _in_ uptpdateness vector*/
bool del_incoming = false;
bool in_transaction = false;
int ret;
+ bool am_rodc;
switch (level) {
case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
}
}
- if (samdb_rodc(p_state->sam_ldb)) {
+ ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
+ if (ret == LDB_SUCCESS && am_rodc) {
return NT_STATUS_NO_SUCH_DOMAIN;
}