summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
authorFernando J V da Silva <fernandojvsilva@yahoo.com.br>2010-04-15 17:37:40 -0300
committerAndrew Tridgell <tridge@samba.org>2010-04-22 19:36:15 +1000
commit57bcdf008fa44d4c550819cbceada968b11be63c (patch)
treec404018cef84c2e07b26a48f7618cfa31b76c622 /source4
parentc023fc217ed370e5c890c1984da533e0133060d9 (diff)
downloadsamba-57bcdf008fa44d4c550819cbceada968b11be63c.tar.gz
samba-57bcdf008fa44d4c550819cbceada968b11be63c.tar.bz2
samba-57bcdf008fa44d4c550819cbceada968b11be63c.zip
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>
Diffstat (limited to 'source4')
-rw-r--r--source4/dsdb/common/util.c73
-rw-r--r--source4/dsdb/kcc/kcc_topology.c18
-rw-r--r--source4/dsdb/repl/drepl_out_helpers.c5
-rw-r--r--source4/dsdb/repl/drepl_service.c5
-rw-r--r--source4/rpc_server/drsuapi/getncchanges.c14
-rw-r--r--source4/rpc_server/lsa/dcesrv_lsa.c4
6 files changed, 80 insertions, 39 deletions
diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c
index 30cb5c5c99..842f56b3ed 100644
--- a/source4/dsdb/common/util.c
+++ b/source4/dsdb/common/util.c
@@ -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 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
diff --git a/source4/dsdb/kcc/kcc_topology.c b/source4/dsdb/kcc/kcc_topology.c
index 72eb5e1137..215cc4d47e 100644
--- a/source4/dsdb/kcc/kcc_topology.c
+++ b/source4/dsdb/kcc/kcc_topology.c
@@ -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;
diff --git a/source4/dsdb/repl/drepl_out_helpers.c b/source4/dsdb/repl/drepl_out_helpers.c
index a12481b897..07fb0b3d62 100644
--- a/source4/dsdb/repl/drepl_out_helpers.c
+++ b/source4/dsdb/repl/drepl_out_helpers.c
@@ -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;
}
diff --git a/source4/dsdb/repl/drepl_service.c b/source4/dsdb/repl/drepl_service.c
index 4196f94234..59436d6c0c 100644
--- a/source4/dsdb/repl/drepl_service.c
+++ b/source4/dsdb/repl/drepl_service.c
@@ -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);
diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c
index e70e863c36..56c061d2e8 100644
--- a/source4/rpc_server/drsuapi/getncchanges.c
+++ b/source4/rpc_server/drsuapi/getncchanges.c
@@ -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*/
diff --git a/source4/rpc_server/lsa/dcesrv_lsa.c b/source4/rpc_server/lsa/dcesrv_lsa.c
index 792b016e93..e683348140 100644
--- a/source4/rpc_server/lsa/dcesrv_lsa.c
+++ b/source4/rpc_server/lsa/dcesrv_lsa.c
@@ -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;
}