[PATCH] s4-drs: framework for DsGetReplInfo(), includes the DS_REPL_INFO_NEIGHBORS infoType.

Erick Nogueira do Nascimento erick.nogueira.nascimento at gmail.com
Wed Dec 23 12:51:46 MST 2009


This patch includes the framework for the implementation of all infoTypes of
the DsGetReplInfo() call, and includes the implementation for the first one,
the DS_REPL_INFO_NEIGHBORS.
---
 source4/dsdb/config.mk                      |    4 +-
 source4/dsdb/kcc/kcc_drs_replica_info.c     |  496 +++++++++++++++++++++++++++
 source4/dsdb/kcc/kcc_service.c              |   10 +-
 source4/rpc_server/drsuapi/dcesrv_drsuapi.c |   12 +-
 4 files changed, 518 insertions(+), 4 deletions(-)
 create mode 100644 source4/dsdb/kcc/kcc_drs_replica_info.c

diff --git a/source4/dsdb/config.mk b/source4/dsdb/config.mk
index dfc5def..19dba16 100644
--- a/source4/dsdb/config.mk
+++ b/source4/dsdb/config.mk
@@ -83,6 +83,8 @@ PRIVATE_DEPENDENCIES = \
 KCC_SRV_OBJ_FILES = $(addprefix $(dsdbsrcdir)/kcc/, \
 		kcc_service.o \
 		kcc_connection.o \
-		kcc_periodic.o)
+		kcc_periodic.o \
+		kcc_drs_replica_info.o)
 
 $(eval $(call proto_header_template,$(dsdbsrcdir)/kcc/kcc_service_proto.h,$(KCC_SRV_OBJ_FILES:.o=.c)))
+
diff --git a/source4/dsdb/kcc/kcc_drs_replica_info.c b/source4/dsdb/kcc/kcc_drs_replica_info.c
new file mode 100644
index 0000000..1f8b3d6
--- /dev/null
+++ b/source4/dsdb/kcc/kcc_drs_replica_info.c
@@ -0,0 +1,496 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ DRS Replica Information
+
+ Copyright (C) Erick Nogueira do Nascimento 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+ */
+
+#include "includes.h"
+#include "dsdb/samdb/samdb.h"
+#include "auth/auth.h"
+#include "smbd/service.h"
+#include "lib/events/events.h"
+#include "lib/messaging/irpc.h"
+#include "dsdb/kcc/kcc_service.h"
+#include "lib/ldb/include/ldb_errors.h"
+#include "../lib/util/dlinklist.h"
+#include "librpc/gen_ndr/ndr_misc.h"
+#include "librpc/gen_ndr/ndr_drsuapi.h"
+#include "librpc/gen_ndr/ndr_drsblobs.h"
+#include "param/param.h"
+
+struct ncList {
+	struct ldb_dn *dn;
+	struct ncList *prev, *next;
+};
+
+struct neighList {
+	struct drsuapi_DsReplicaNeighbour *neigh;
+	struct neighList *prev, *next;
+};
+
+static WERROR copy_repsfrom_1_to_2(TALLOC_CTX *mem_ctx,
+				 struct repsFromTo2 **reps2,
+				 struct repsFromTo1 *reps1)
+{
+	struct repsFromTo2* reps;
+
+	reps = talloc_zero(mem_ctx, struct repsFromTo2);
+	W_ERROR_HAVE_NO_MEMORY(reps);
+
+	reps->blobsize = reps1->blobsize;
+	reps->consecutive_sync_failures = reps1->consecutive_sync_failures;
+	reps->last_attempt = reps1->last_attempt;
+	reps->last_success = reps1->last_success;
+	reps->other_info = talloc_zero(mem_ctx, struct repsFromTo2OtherInfo);
+	W_ERROR_HAVE_NO_MEMORY(reps->other_info);
+	reps->other_info->dns_name1 = reps1->other_info->dns_name;
+	reps->replica_flags = reps1->replica_flags;
+	memcpy(reps->schedule, reps1->schedule, sizeof(reps1->schedule));
+	reps->reserved = reps1->reserved;
+	reps->highwatermark = reps1->highwatermark;
+	reps->source_dsa_obj_guid = reps1->source_dsa_obj_guid;
+	reps->source_dsa_invocation_id = reps1->source_dsa_invocation_id;
+	reps->transport_guid = reps1->transport_guid;
+
+	*reps2 = reps;
+	return WERR_OK;
+}
+
+static WERROR fill_neighbor_from_repsFrom(TALLOC_CTX *mem_ctx,
+					  struct ldb_context *samdb,
+					  struct ldb_dn *nc_dn,
+					  struct drsuapi_DsReplicaNeighbour *neigh,
+					  struct repsFromTo2 *reps_from)
+{
+	WERROR status;
+	struct ldb_dn *source_dsa_dn;
+	int ret;
+	char *dsa_guid_str;
+	struct ldb_dn *transport_obj_dn = NULL;
+
+	neigh->source_dsa_address = reps_from->other_info->dns_name1;
+	neigh->replica_flags = reps_from->replica_flags;
+	neigh->last_attempt = reps_from->last_attempt;
+	neigh->source_dsa_obj_guid = reps_from->source_dsa_obj_guid;
+
+	dsa_guid_str = GUID_string(mem_ctx, &reps_from->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);
+
+	if (dsdb_find_guid_by_dn(samdb, nc_dn, &neigh->naming_context_obj_guid)
+			!= LDB_SUCCESS) {
+		status = WERR_DS_DRA_INTERNAL_ERROR;
+		goto DONE;
+	}
+
+	if (!GUID_all_zero(&reps_from->transport_guid)) {
+		char *transp_guid_str = GUID_string(mem_ctx, &reps_from->transport_guid);
+		W_ERROR_HAVE_NO_MEMORY(transp_guid_str);
+		if (dsdb_find_dn_by_guid(samdb, mem_ctx, transp_guid_str,
+					 &transport_obj_dn) != LDB_SUCCESS)
+		{
+			status = WERR_DS_DRA_INTERNAL_ERROR;
+			goto DONE;
+		}
+	}
+
+	neigh->transport_obj_dn = ldb_dn_get_linearized(transport_obj_dn);
+	neigh->source_dsa_invocation_id = reps_from->source_dsa_invocation_id;
+	neigh->transport_obj_guid = reps_from->transport_guid;
+	neigh->highest_usn = reps_from->highwatermark.highest_usn;
+	neigh->tmp_highest_usn = reps_from->highwatermark.tmp_highest_usn;
+	neigh->last_success = reps_from->last_success;
+	neigh->result_last_attempt = reps_from->result_last_attempt;
+	neigh->consecutive_sync_failures = reps_from->consecutive_sync_failures;
+	neigh->reserved = 0; /* Unused. MUST be 0. */
+
+	/* If everything went fine so far, set the status to OK */
+	status = WERR_OK;
+DONE:
+	return status;
+}
+
+/*
+ * See details on MS-DRSR 4.1.13.3, for infoType DS_REPL_INFO_NEIGHBORS
+ * */
+static WERROR kccdrs_replica_get_info_neighbours(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 ldb_dn *nc_dn = NULL;
+	struct ncList *p_nc_list = NULL;
+
+	struct repsFromToBlob *reps_from_blob = NULL;
+	struct repsFromTo2 *reps_from = NULL;
+	uint32_t c_reps_from;
+
+	int i_rep;
+
+	struct neighList *neigh_list = NULL;
+	struct neighList *neigh_elem = NULL;
+
+	struct drsuapi_DsReplicaNeighbour *neigh = NULL;
+
+	i = j = 0;
+	neigh_list = NULL;
+
+	/* 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;
+
+		/* load the nc's repsFromTo blob */
+		status = dsdb_loadreps(samdb, mem_ctx, nc_dn, "repsFrom",
+				&reps_from_blob, &c_reps_from);
+		if (!W_ERROR_IS_OK(status)) {
+			status = WERR_DS_DRA_INTERNAL_ERROR;
+			goto DONE;
+		}
+
+		/* foreach r in nc!repsFrom */
+		for (i_rep = 0; i_rep < c_reps_from; i_rep++) {
+
+			/* put all info on reps_from */
+			if (reps_from_blob[i_rep].version == 1) {
+				status = copy_repsfrom_1_to_2(mem_ctx, &reps_from,
+							      &reps_from_blob[i_rep].ctr.ctr1);
+				if (!W_ERROR_IS_OK(status)) {
+					goto DONE;
+				}
+			} else { /* reps_from->version == 2 */
+				reps_from = &reps_from_blob[i_rep].ctr.ctr2;
+			}
+
+			if (GUID_all_zero(&req_src_dsa_guid) ||
+			    GUID_compare(&req_src_dsa_guid, &reps_from->source_dsa_obj_guid) == 0)
+			{
+
+				if (i >= base_index) {
+					neigh = talloc_zero(mem_ctx, struct drsuapi_DsReplicaNeighbour);
+					W_ERROR_HAVE_NO_MEMORY(neigh);
+
+					status = fill_neighbor_from_repsFrom(mem_ctx, samdb,
+									     nc_dn, neigh,
+									     reps_from);
+					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)
+{
+	WERROR status;
+	const char *attrs[] = { "hasMasterNCs", NULL };
+	struct ldb_result *res;
+	struct ncList *nc_list = NULL;
+	struct ncList *nc_list_elem;
+	int ret;
+	int i;
+	char *nc_str;
+
+	ret = ldb_search(samdb, mem_ctx, &res, ldb_get_config_basedn(samdb),
+			LDB_SCOPE_DEFAULT, attrs, "(objectguid=%s)", ntds_guid_str);
+
+	if (ret != LDB_SUCCESS) {
+		DEBUG(0,(__location__ ": Failed objectguid search - %s\n", ldb_errstring(samdb)));
+		status = WERR_INTERNAL_ERROR;
+		goto DONE;
+	}
+
+	if (res->count == 0) {
+		DEBUG(0,(__location__ ": Failed: objectguid=%s not found\n", ntds_guid_str));
+		status = WERR_INTERNAL_ERROR;
+		goto DONE;
+	}
+
+	for (i = 0; i < res->count; i++) {
+
+		struct ldb_message_element *msg_elem = ldb_msg_find_element(
+				res->msgs[i], "hasMasterNCs");
+		int k;
+
+		if (!msg_elem || msg_elem->num_values == 0) {
+			DEBUG(0,(__location__ ": Failed: Attribute hasMasterNCs not found - %s\n",
+			      ldb_errstring(samdb)));
+			status = WERR_INTERNAL_ERROR;
+			goto DONE;
+		}
+
+		for (k = 0; k < msg_elem->num_values; k++) {
+			int len = msg_elem->values[k].length;
+
+			/* copy the string on msg_elem->values[k]->data to nc_str */
+			nc_str = talloc_array(mem_ctx, char, len);
+			W_ERROR_HAVE_NO_MEMORY(nc_str);
+			memcpy(nc_str, msg_elem->values[k].data, len);
+			nc_str[len] = '\0';
+
+			nc_list_elem = talloc_zero(mem_ctx, struct ncList);
+			W_ERROR_HAVE_NO_MEMORY(nc_list_elem);
+			nc_list_elem->dn = ldb_dn_new(mem_ctx, samdb, nc_str);
+			W_ERROR_HAVE_NO_MEMORY(nc_list_elem);
+			DLIST_ADD(nc_list, nc_list_elem);
+		}
+
+	}
+
+	*master_nc_list = nc_list;
+	/* If everything went fine so far, set the status to OK */
+	status = WERR_OK;
+DONE:
+	return status;
+}
+
+NTSTATUS kccdrs_replica_get_info(struct irpc_message *msg,
+				 struct drsuapi_DsReplicaGetInfo *req)
+{
+	WERROR status;
+
+	struct drsuapi_DsReplicaGetInfoRequest1 *req1;
+	struct drsuapi_DsReplicaGetInfoRequest2 *req2;
+	enum drsuapi_DsReplicaInfoType info_type, *tmp_p_info_type;
+
+	int base_index;
+	union drsuapi_DsReplicaInfo *reply;
+
+	struct GUID req_src_dsa_guid;
+	const char *object_dn = NULL;
+	struct ldb_dn *nc_dn = NULL;
+	struct ncList *nc_list = NULL, *nc_list_elem = NULL;
+
+	struct kccsrv_service *service;
+	struct ldb_context *samdb;
+	TALLOC_CTX *mem_ctx;
+
+	service = talloc_get_type(msg->private_data, struct kccsrv_service);
+	samdb = service->samdb;
+	mem_ctx = talloc_new(msg);
+	NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
+
+	NDR_PRINT_IN_DEBUG(drsuapi_DsReplicaGetInfo, req);
+
+	/* check request version */
+	if (req->in.level != DRSUAPI_DS_REPLICA_GET_INFO &&
+	    req->in.level != DRSUAPI_DS_REPLICA_GET_INFO2)
+	{
+		status = WERR_REVISION_MISMATCH;
+		goto DONE;
+	}
+
+	if (req->in.level == DRSUAPI_DS_REPLICA_GET_INFO) {
+		req1 = &req->in.req->req1;
+		base_index = 0;
+		info_type = req1->info_type;
+		object_dn = req1->object_dn;
+		req_src_dsa_guid = req1->guid1;
+
+	} else { /* r->in.level == DRSUAPI_DS_REPLICA_GET_INFO2 */
+		req2 = &req->in.req->req2;
+		if (req2->unknown2 == 0xffffffff) {
+			/* no more data is available */
+			status = WERR_NO_MORE_ITEMS; /* on MS-DRSR it is ERROR_NO_MORE_ITEMS */
+			goto DONE;
+		}
+
+		base_index = req2->unknown2; /* Note: This is dwEnumerationContext on MS-DRSR 4.1.13.1.3 */
+		info_type = req2->info_type;
+		object_dn = req2->object_dn;
+		req_src_dsa_guid = req2->guid1;
+	}
+
+	/* TODO: Perform the necessary access permission checking here according to the infoType requested */
+
+	switch (info_type) {
+	case DRSUAPI_DS_REPLICA_INFO_NEIGHBORS:
+	case DRSUAPI_DS_REPLICA_INFO_CURSORS:
+	case DRSUAPI_DS_REPLICA_INFO_OBJ_METADATA:
+	case DRSUAPI_DS_REPLICA_INFO_KCC_DSA_CONNECT_FAILURES:
+	case DRSUAPI_DS_REPLICA_INFO_KCC_DSA_LINK_FAILURES:
+	case DRSUAPI_DS_REPLICA_INFO_PENDING_OPS:
+	case DRSUAPI_DS_REPLICA_INFO_ATTRIBUTE_VALUE_METADATA:
+	case DRSUAPI_DS_REPLICA_INFO_CURSORS2:
+	case DRSUAPI_DS_REPLICA_INFO_CURSORS3:
+	case DRSUAPI_DS_REPLICA_INFO_OBJ_METADATA2:
+	case DRSUAPI_DS_REPLICA_INFO_ATTRIBUTE_VALUE_METADATA2:
+	case DRSUAPI_DS_REPLICA_INFO_NEIGHBORS02:
+	case DRSUAPI_DS_REPLICA_INFO_CONNECTIONS04:
+	case DRSUAPI_DS_REPLICA_INFO_CURSORS05:
+	case DRSUAPI_DS_REPLICA_INFO_06:
+		break;
+	default:
+		DEBUG(0,(__location__ ": infoType requested is invalid."));
+		status = WERR_INVALID_PARAMETER; /* infoType is invalid */
+		goto DONE;
+	}
+
+	/* allocate the reply and fill in some fields */
+	reply = talloc_zero(mem_ctx, union drsuapi_DsReplicaInfo);
+	NT_STATUS_HAVE_NO_MEMORY(reply);
+	req->out.info = reply;
+	tmp_p_info_type = talloc(mem_ctx, enum drsuapi_DsReplicaInfoType);
+	NT_STATUS_HAVE_NO_MEMORY(tmp_p_info_type);
+	*tmp_p_info_type = info_type;
+	req->out.info_type = tmp_p_info_type;
+
+	/* Based on the infoType requested, retrieve the corresponding information and construct the response message */
+	switch (info_type) {
+
+	case DRSUAPI_DS_REPLICA_INFO_NEIGHBORS:
+	case DRSUAPI_DS_REPLICA_INFO_NEIGHBORS02: /* DS_REPL_INFO_REPSTO */
+		if (object_dn != NULL) { /* ncs := { object_dn } */
+			nc_list = NULL;
+			nc_dn = ldb_dn_new(mem_ctx, samdb, object_dn);
+			nc_list_elem = talloc_zero(mem_ctx, struct ncList);
+			NT_STATUS_HAVE_NO_MEMORY(nc_list_elem);
+			nc_list_elem->dn = nc_dn;
+			DLIST_ADD_END(nc_list, nc_list_elem, struct ncList*);
+
+		} else {
+			/* ncs := getNCs() from ldb database.
+			 * getNCs() must return an array containing the DSNames of all NCs hosted by this server.
+			 */
+			char *ntds_guid_str = GUID_string(mem_ctx, &service->ntds_guid);
+			NT_STATUS_HAVE_NO_MEMORY(ntds_guid_str);
+			status = get_master_ncs(mem_ctx, samdb, ntds_guid_str, &nc_list);
+			if (!W_ERROR_IS_OK(status)) {
+				goto DONE;
+			}
+		}
+
+		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 = WERR_FOOBAR;
+			goto DONE;
+		}
+
+		break;
+
+	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 */
+		status = WERR_FOOBAR;
+		goto DONE;
+		break;
+
+	case DRSUAPI_DS_REPLICA_INFO_CURSORS: /* On MS-DRSR it is DS_REPL_INFO_CURSORS_FOR_NC */
+		status = WERR_FOOBAR;
+		goto DONE;
+		break;
+
+	case DRSUAPI_DS_REPLICA_INFO_CURSORS2: /* On MS-DRSR it is DS_REPL_INFO_CURSORS_2_FOR_NC */
+	case DRSUAPI_DS_REPLICA_INFO_CURSORS3: /* On MS-DRSR it is DS_REPL_INFO_CURSORS_3_FOR_NC */
+		status = WERR_FOOBAR;
+		goto DONE;
+		break;
+
+	case DRSUAPI_DS_REPLICA_INFO_CURSORS05: /* On MS-DRSR it is DS_REPL_INFO_UPTODATE_VECTOR_V1 */
+		status = WERR_FOOBAR;
+		goto DONE;
+		break;
+
+	case DRSUAPI_DS_REPLICA_INFO_ATTRIBUTE_VALUE_METADATA: /* On MS-DRSR it is DS_REPL_INFO_METADATA_FOR_ATTR_VALUE */
+	case DRSUAPI_DS_REPLICA_INFO_ATTRIBUTE_VALUE_METADATA2: /* On MS-DRSR it is DS_REPL_INFO_METADATA_2_FOR_ATTR_VALUE */
+		status = WERR_FOOBAR;
+		goto DONE;
+		break;
+
+	case DRSUAPI_DS_REPLICA_INFO_KCC_DSA_CONNECT_FAILURES: /* On MS-DRSR it is DS_REPL_INFO_KCC_DSA_CONNECT_FAILURES */
+		status = WERR_FOOBAR;
+		goto DONE;
+		break;
+
+	case DRSUAPI_DS_REPLICA_INFO_KCC_DSA_LINK_FAILURES: /* On MS-DRSR it is DS_REPL_INFO_KCC_LINK_FAILURES */
+		status = WERR_FOOBAR;
+		goto DONE;
+		break;
+
+	case DRSUAPI_DS_REPLICA_INFO_PENDING_OPS: /* On MS-DRSR it is DS_REPL_INFO_PENDING_OPS */
+		status = WERR_FOOBAR;
+		goto DONE;
+		break;
+
+	case DRSUAPI_DS_REPLICA_INFO_CONNECTIONS04: /* On MS-DRSR it is DS_REPL_INFO_CLIENT_CONTEXTS */
+		status = WERR_FOOBAR;
+		goto DONE;
+		break;
+
+	case DRSUAPI_DS_REPLICA_INFO_06: /* On MS-DRSR it is DS_REPL_INFO_SERVER_OUTGOING_CALLS */
+		status = WERR_FOOBAR;
+		goto DONE;
+		break;
+	}
+DONE:
+	/* put the status on the result field of the reply */
+	req->out.result = status;
+	NDR_PRINT_OUT_DEBUG(drsuapi_DsReplicaGetInfo, req);
+	return NT_STATUS_OK;
+}
diff --git a/source4/dsdb/kcc/kcc_service.c b/source4/dsdb/kcc/kcc_service.c
index 4196eb8..a076d20 100644
--- a/source4/dsdb/kcc/kcc_service.c
+++ b/source4/dsdb/kcc/kcc_service.c
@@ -136,8 +136,7 @@ static WERROR kccsrv_load_partitions(struct kccsrv_service *s)
 	return WERR_OK;
 }
 
-static NTSTATUS kccsrv_execute_kcc(struct irpc_message *msg,
-					struct drsuapi_DsExecuteKCC *r)
+static NTSTATUS kccsrv_execute_kcc(struct irpc_message *msg, struct drsuapi_DsExecuteKCC *r)
 {
 	TALLOC_CTX *mem_ctx;
 	NTSTATUS status;
@@ -156,6 +155,11 @@ static NTSTATUS kccsrv_execute_kcc(struct irpc_message *msg,
 	return NT_STATUS_OK;
 }
 
+static NTSTATUS kccsrv_replica_get_info(struct irpc_message *msg, struct drsuapi_DsReplicaGetInfo *r)
+{
+	return kccdrs_replica_get_info(msg, r);
+}
+
 /*
   startup the kcc service task
 */
@@ -227,7 +231,9 @@ static void kccsrv_task_init(struct task_server *task)
 	}
 
 	irpc_add_name(task->msg_ctx, "kccsrv");
+
 	IRPC_REGISTER(task->msg_ctx, drsuapi, DRSUAPI_DSEXECUTEKCC, kccsrv_execute_kcc, service);
+	IRPC_REGISTER(task->msg_ctx, drsuapi, DRSUAPI_DSREPLICAGETINFO, kccsrv_replica_get_info, service);
 }
 
 /*
diff --git a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c
index 3d92880..b1303ca 100644
--- a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c
+++ b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c
@@ -815,7 +815,17 @@ static WERROR dcesrv_drsuapi_DsExecuteKCC(struct dcesrv_call_state *dce_call, TA
 static WERROR dcesrv_drsuapi_DsReplicaGetInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 		       struct drsuapi_DsReplicaGetInfo *r)
 {
-	DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+	WERROR status;
+	status = drs_security_level_check(dce_call, "DsReplicaGetInfo");
+
+	if (!W_ERROR_IS_OK(status)) {
+		return status;
+	}
+
+	dcesrv_irpc_forward_rpc_call(dce_call, mem_ctx, r, NDR_DRSUAPI_DSREPLICAGETINFO,
+								&ndr_table_drsuapi, "kccsrv", "DsReplicaGetInfo");
+
+	return WERR_OK;
 }
 
 
-- 
1.6.0.4


--MP_/iF6jaotBrZqTPP7P4.YVIDb
Content-Type: text/x-patch;
 name=0001-s4-drs-torture-test-for-DsGetReplInfo-RPC-DSGETI.patch
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename=0001-s4-drs-torture-test-for-DsGetReplInfo-RPC-DSGETI.patch



More information about the samba-technical mailing list