mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
s4-drs: samdb_is_rodc() function and new samdb_rodc() function
This patch creates the samdb_is_rodc() function, which looks for the NTDSDSA object for a DC that has a specific invocationId and if msDS-isRODC is present on such object and it is TRUE, then consider the DC as a RODC. The new samdb_rodc() function uses the samdb_is_rodc() function for the local server. Signed-off-by: Andrew Tridgell <tridge@samba.org>
This commit is contained in:
parent
c023fc217e
commit
57bcdf008f
@ -2618,50 +2618,59 @@ int drsuapi_DsReplicaCursor_compare(const struct drsuapi_DsReplicaCursor *c1,
|
||||
return GUID_compare(&c1->source_dsa_invocation_id, &c2->source_dsa_invocation_id);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
see if a computer identified by its invocationId is a RODC
|
||||
*/
|
||||
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);
|
||||
|
||||
config_dn = samdb_config_dn(sam_ctx);
|
||||
if (!config_dn) {
|
||||
talloc_free(tmp_ctx);
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
ret = ldb_msg_find_attr_as_bool(res->msgs[0], "msDS-isRODC", 0);
|
||||
*is_rodc = (ret == 1);
|
||||
|
||||
talloc_free(tmp_ctx);
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
see if we are a RODC
|
||||
*/
|
||||
bool samdb_rodc(struct ldb_context *sam_ctx)
|
||||
int samdb_rodc(struct ldb_context *sam_ctx, bool *am_rodc)
|
||||
{
|
||||
TALLOC_CTX *tmp_ctx;
|
||||
const char *obj_category;
|
||||
struct ldb_dn *obj_category_dn;
|
||||
const struct ldb_val *obj_category_dn_rdn_val;
|
||||
|
||||
tmp_ctx = talloc_new(sam_ctx);
|
||||
if (tmp_ctx == NULL) {
|
||||
DEBUG(1,("samdb_rodc: Failed to talloc new context.\n"));
|
||||
goto failed;
|
||||
const struct GUID *invocationId;
|
||||
invocationId = samdb_ntds_invocation_id(sam_ctx);
|
||||
if (!invocationId) {
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
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
|
||||
|
||||
|
@ -1155,7 +1155,13 @@ static NTSTATUS kcctpl_get_all_bridgehead_dcs(struct ldb_context *ldb,
|
||||
|
||||
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) {
|
||||
@ -3155,6 +3161,7 @@ static NTSTATUS kcctpl_create_connections(struct ldb_context *ldb,
|
||||
struct ldb_dn *transports_dn;
|
||||
const char * const attrs[] = { "bridgeheadServerListBL", "name",
|
||||
"transportAddressAttribute", NULL };
|
||||
int ret;
|
||||
|
||||
connected = true;
|
||||
|
||||
@ -3223,14 +3230,19 @@ static NTSTATUS kcctpl_create_connections(struct ldb_context *ldb,
|
||||
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;
|
||||
|
@ -542,6 +542,8 @@ static void dreplsrv_update_refs_trigger(struct tevent_req *req)
|
||||
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)) {
|
||||
@ -566,7 +568,8 @@ static void dreplsrv_update_refs_trigger(struct tevent_req *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;
|
||||
}
|
||||
|
||||
|
@ -132,6 +132,8 @@ static void dreplsrv_task_init(struct task_server *task)
|
||||
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:
|
||||
@ -194,7 +196,8 @@ static void dreplsrv_task_init(struct task_server *task)
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
@ -684,6 +684,7 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_
|
||||
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;
|
||||
@ -699,7 +700,8 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_
|
||||
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;
|
||||
}
|
||||
@ -733,6 +735,16 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_
|
||||
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*/
|
||||
|
@ -1636,6 +1636,7 @@ static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
|
||||
bool del_incoming = false;
|
||||
bool in_transaction = false;
|
||||
int ret;
|
||||
bool am_rodc;
|
||||
|
||||
switch (level) {
|
||||
case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
|
||||
@ -1697,7 +1698,8 @@ static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user