diff options
-rw-r--r-- | source4/dsdb/kcc/kcc_drs_replica_info.c | 146 |
1 files changed, 142 insertions, 4 deletions
diff --git a/source4/dsdb/kcc/kcc_drs_replica_info.c b/source4/dsdb/kcc/kcc_drs_replica_info.c index 8c1829343e..2ae72173a8 100644 --- a/source4/dsdb/kcc/kcc_drs_replica_info.c +++ b/source4/dsdb/kcc/kcc_drs_replica_info.c @@ -321,6 +321,137 @@ DONE: return status; } +static WERROR fill_neighbor_from_repsTo(TALLOC_CTX *mem_ctx, + struct ldb_context *samdb, struct ldb_dn *nc_dn, + struct drsuapi_DsReplicaNeighbour *neigh, + struct repsFromTo2 *reps_to) +{ + WERROR status; + char *dsa_guid_str; + int ret; + struct ldb_dn *source_dsa_dn; + + neigh->source_dsa_address = reps_to->other_info->dns_name1; + neigh->replica_flags = reps_to->replica_flags; + neigh->last_attempt = reps_to->last_attempt; + neigh->source_dsa_obj_guid = reps_to->source_dsa_obj_guid; + + dsa_guid_str = GUID_string(mem_ctx, &reps_to->source_dsa_obj_guid); + W_ERROR_HAVE_NO_MEMORY(dsa_guid_str); + + ret = dsdb_find_dn_by_guid(samdb, mem_ctx, dsa_guid_str, &source_dsa_dn); + if (ret != LDB_SUCCESS) { + DEBUG(0,(__location__ ": Failed to find DN for neighbor GUID %s\n", + dsa_guid_str)); + status = WERR_DS_DRA_INTERNAL_ERROR; + goto DONE; + } + + neigh->source_dsa_obj_dn = ldb_dn_get_linearized(source_dsa_dn); + neigh->naming_context_dn = ldb_dn_get_linearized(nc_dn); + + ret = dsdb_find_guid_by_dn(samdb, nc_dn, + &neigh->naming_context_obj_guid); + if (ret != LDB_SUCCESS) { + DEBUG(0,(__location__ ": Failed to find GUID for DN %s\n", + ldb_dn_get_linearized(nc_dn))); + status = WERR_DS_DRA_INTERNAL_ERROR; + goto DONE; + } + + /* If everything went fine so far, set the status to OK */ + status = WERR_OK; + DONE: return status; +} + +static WERROR kccdrs_replica_get_info_repsto(TALLOC_CTX *mem_ctx, + struct ldb_context *samdb, struct drsuapi_DsReplicaGetInfo *r, + union drsuapi_DsReplicaInfo *reply, int base_index, + struct GUID req_src_dsa_guid, struct ncList *nc_list) +{ + WERROR status; + int i, j, k; + struct ncList *p_nc_list = NULL; + struct ldb_dn *nc_dn = NULL; + struct repsFromToBlob *reps_to_blob; + struct repsFromTo2 *reps_to; + uint32_t c_reps_to; + int i_rep; + struct drsuapi_DsReplicaNeighbour *neigh; + struct neighList *neigh_list = NULL; + struct neighList *neigh_elem = NULL; + + i = j = 0; + + /* foreach nc in ncs */ + for (p_nc_list = nc_list; p_nc_list != NULL; p_nc_list = p_nc_list->next) { + + nc_dn = p_nc_list->dn; + + status = dsdb_loadreps(samdb, mem_ctx, nc_dn, "repsTo", + &reps_to_blob, &c_reps_to); + if (!W_ERROR_IS_OK(status)) { + status = WERR_DS_DRA_INTERNAL_ERROR; + goto DONE; + } + + /* foreach r in nc!repsTo */ + for (i_rep = 0; i_rep < c_reps_to; i_rep++) { + + /* put all info on reps_from */ + if (reps_to_blob[i_rep].version == 1) { + status = copy_repsfrom_1_to_2(mem_ctx, + &reps_to, + &reps_to_blob[i_rep].ctr.ctr1); + if (!W_ERROR_IS_OK(status)) { + goto DONE; + } + } else { /* reps_from->version == 2 */ + reps_to = &reps_to_blob[i_rep].ctr.ctr2; + } + + if (i >= base_index) { + neigh = talloc_zero(mem_ctx, struct drsuapi_DsReplicaNeighbour); + W_ERROR_HAVE_NO_MEMORY(neigh); + + status = fill_neighbor_from_repsTo(mem_ctx, + samdb, nc_dn, + neigh, reps_to); + if (!W_ERROR_IS_OK(status)) { + goto DONE; + } + + /* append the neighbor to neigh_list */ + neigh_elem = talloc_zero(mem_ctx, struct neighList); + W_ERROR_HAVE_NO_MEMORY(neigh_elem); + neigh_elem->neigh = neigh; + DLIST_ADD_END(neigh_list, neigh_elem, struct neighList*); + + j++; + } + + i++; + } + } + + /* put all neighbours on neigh_list on reply->neighbours->array */ + reply->neighbours = talloc_zero(mem_ctx, struct drsuapi_DsReplicaNeighbourCtr); + W_ERROR_HAVE_NO_MEMORY(reply->neighbours); + + reply->neighbours->count = j; + reply->neighbours->reserved = 0; + reply->neighbours->array = talloc_array(mem_ctx, struct drsuapi_DsReplicaNeighbour, j); + W_ERROR_HAVE_NO_MEMORY(reply->neighbours->array); + + for (k = 0; neigh_list != NULL; neigh_list = neigh_list->next, k++) { + reply->neighbours->array[k] = *neigh_list->neigh; + } + + /* If everything went fine so far, set the status to OK */ + status = WERR_OK; + DONE: return status; +} + static WERROR get_master_ncs(TALLOC_CTX *mem_ctx, struct ldb_context *samdb, const char *ntds_guid_str, struct ncList **master_nc_list) { @@ -483,6 +614,7 @@ NTSTATUS kccdrs_replica_get_info(struct irpc_message *msg, switch (info_type) { case DRSUAPI_DS_REPLICA_INFO_NEIGHBORS: + case DRSUAPI_DS_REPLICA_INFO_NEIGHBORS02: /* On MS-DRSR it is DS_REPL_INFO_REPSTO */ if (object_dn != NULL) { /* ncs := { object_dn } */ nc_list = NULL; nc_dn = ldb_dn_new(mem_ctx, samdb, object_dn); @@ -505,9 +637,16 @@ NTSTATUS kccdrs_replica_get_info(struct irpc_message *msg, } } - status = kccdrs_replica_get_info_neighbours(mem_ctx, samdb, req, - reply, base_index, - req_src_dsa_guid, nc_list); + if (info_type == DRSUAPI_DS_REPLICA_INFO_NEIGHBORS) { + status = kccdrs_replica_get_info_neighbours(mem_ctx, samdb, req, + reply, base_index, + req_src_dsa_guid, nc_list); + } else { /* info_type == DRSUAPI_DS_REPLICA_INFO_NEIGHBORS02 */ + status = kccdrs_replica_get_info_repsto(mem_ctx, samdb, req, + reply, base_index, + req_src_dsa_guid, nc_list); + } + break; case DRSUAPI_DS_REPLICA_INFO_CURSORS: /* On MS-DRSR it is DS_REPL_INFO_CURSORS_FOR_NC */ @@ -525,7 +664,6 @@ NTSTATUS kccdrs_replica_get_info(struct irpc_message *msg, case DRSUAPI_DS_REPLICA_INFO_CURSORS3: /* On MS-DRSR it is DS_REPL_INFO_CURSORS_3_FOR_NC */ case DRSUAPI_DS_REPLICA_INFO_CURSORS05: /* On MS-DRSR it is DS_REPL_INFO_UPTODATE_VECTOR_V1 */ - case DRSUAPI_DS_REPLICA_INFO_NEIGHBORS02: /* DS_REPL_INFO_REPSTO */ case DRSUAPI_DS_REPLICA_INFO_OBJ_METADATA: /* On MS-DRSR it is DS_REPL_INFO_METADATA_FOR_OBJ */ case DRSUAPI_DS_REPLICA_INFO_OBJ_METADATA2: /* On MS-DRSR it is DS_REPL_INFO_METADATA_FOR_OBJ */ case DRSUAPI_DS_REPLICA_INFO_ATTRIBUTE_VALUE_METADATA: /* On MS-DRSR it is DS_REPL_INFO_METADATA_FOR_ATTR_VALUE */ |