]> git.samba.org - obnox/samba/samba-obnox.git/commitdiff
s4-drs: samdb_is_rodc() function and new samdb_rodc() function
authorFernando J V da Silva <fernandojvsilva@yahoo.com.br>
Thu, 15 Apr 2010 20:37:40 +0000 (17:37 -0300)
committerAndrew Tridgell <tridge@samba.org>
Thu, 22 Apr 2010 09:36:15 +0000 (19:36 +1000)
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>
source4/dsdb/common/util.c
source4/dsdb/kcc/kcc_topology.c
source4/dsdb/repl/drepl_out_helpers.c
source4/dsdb/repl/drepl_service.c
source4/rpc_server/drsuapi/getncchanges.c
source4/rpc_server/lsa/dcesrv_lsa.c

index 30cb5c5c99cdde898277b4fef47f33baad4ff3f9..842f56b3ed6b25ed78fa699375c6f348986ddd92 100644 (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 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 
 
index 72eb5e1137b4050be06e89ad8db272a1215e42f1..215cc4d47e6f4529012e087d261123a3cfc8808f 100644 (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;
index a12481b8972515ef335ec5aa61d4b900136eb86a..07fb0b3d6273cb1caee82de2bef9842d5a795c5b 100644 (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;
        }
 
index 4196f942340a8424dd7c937a33555d87bbd8fba7..59436d6c0c30645385f01e591e4f0ab3d90cd1b0 100644 (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);
index e70e863c368004796788d9a1c38ab7bb2e35faf2..56c061d2e8e2ec473792020ccefe8f2cf75dcaf6 100644 (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*/
index 792b016e93c385dab38ece0edbfb2a83b40fdcb7..e683348140beaf0eac8fca19a4daa84666d3a290 100644 (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;
                }