1
0
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:
Fernando J V da Silva 2010-04-15 17:37:40 -03:00 committed by Andrew Tridgell
parent c023fc217e
commit 57bcdf008f
6 changed files with 85 additions and 44 deletions

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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*/

View File

@ -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;
}