s4-drs: DsGetReplInfo() refactoring
authorErick Nogueira do Nascimento <erick.nogueira.nascimento@gmail.com>
Thu, 11 Feb 2010 21:04:00 +0000 (19:04 -0200)
committerAndrew Tridgell <tridge@samba.org>
Mon, 15 Feb 2010 21:34:28 +0000 (08:34 +1100)
source4/dsdb/kcc/kcc_drs_replica_info.c
source4/torture/rpc/dsgetinfo.c

index 2ae72173a8930671f795af3d3120f7193f3ce346..da89a470a34328ed7db6ac753fb2738a5f0089b5 100644 (file)
@@ -112,17 +112,112 @@ static WERROR kccdrs_replica_get_info_pending_ops(TALLOC_CTX *mem_ctx,
        return WERR_OK;
 }
 
        return WERR_OK;
 }
 
-
 struct ncList {
        struct ldb_dn *dn;
        struct ncList *prev, *next;
 };
 
 struct ncList {
        struct ldb_dn *dn;
        struct ncList *prev, *next;
 };
 
-struct neighList {
-       struct drsuapi_DsReplicaNeighbour *neigh;
-       struct neighList *prev, *next;
-};
+/*
+  Fill 'master_nc_list' with the master ncs hosted by this server
+*/
+static WERROR get_master_ncs(TALLOC_CTX *mem_ctx, struct ldb_context *samdb,
+                            const char *ntds_guid_str, struct ncList **master_nc_list)
+{
+       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)));
+               return WERR_INTERNAL_ERROR;
+       }
+
+       if (res->count == 0) {
+               DEBUG(0,(__location__ ": Failed: objectguid=%s not found\n", ntds_guid_str));
+               return WERR_INTERNAL_ERROR;
+       }
+
+       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)));
+                       return WERR_INTERNAL_ERROR;
+               }
+
+               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;
+       return WERR_OK;
+}
+
+/*
+  Fill 'nc_list' with the ncs list. (MS-DRSR 4.1.13.3)
+  if the object dn is specified, fill 'nc_list' only with this dn
+  otherwise, fill 'nc_list' with all master ncs hosted by this server
+*/
+static WERROR get_ncs_list(TALLOC_CTX *mem_ctx,
+               struct ldb_context *samdb,
+               struct kccsrv_service *service,
+               const char *object_dn_str,
+               struct ncList **nc_list)
+{
+       WERROR status;
+       struct ncList *nc_list_elem;
+       struct ldb_dn *nc_dn;
+
+       if (object_dn_str != NULL) {
+               /* ncs := { object_dn } */
+               *nc_list = NULL;
+               nc_dn = ldb_dn_new(mem_ctx, samdb, object_dn_str);
+               nc_list_elem = talloc_zero(mem_ctx, struct ncList);
+               W_ERROR_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);
+               W_ERROR_HAVE_NO_MEMORY(ntds_guid_str);
+               status = get_master_ncs(mem_ctx, samdb, ntds_guid_str, nc_list);
+               W_ERROR_NOT_OK_RETURN(status);
+       }
+
+       return WERR_OK;
+}
 
 
+/*
+  Copy the fields from 'reps1' to 'reps2', leaving zeroed the fields on
+  'reps2' that aren't available on 'reps1'.
+*/
 static WERROR copy_repsfrom_1_to_2(TALLOC_CTX *mem_ctx,
                                 struct repsFromTo2 **reps2,
                                 struct repsFromTo1 *reps1)
 static WERROR copy_repsfrom_1_to_2(TALLOC_CTX *mem_ctx,
                                 struct repsFromTo2 **reps2,
                                 struct repsFromTo1 *reps1)
@@ -157,7 +252,6 @@ static WERROR fill_neighbor_from_repsFrom(TALLOC_CTX *mem_ctx,
                                          struct drsuapi_DsReplicaNeighbour *neigh,
                                          struct repsFromTo2 *reps_from)
 {
                                          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 *source_dsa_dn;
        int ret;
        char *dsa_guid_str;
@@ -175,8 +269,7 @@ static WERROR fill_neighbor_from_repsFrom(TALLOC_CTX *mem_ctx,
        if (ret != LDB_SUCCESS) {
                DEBUG(0,(__location__ ": Failed to find DN for neighbor GUID %s\n",
                      dsa_guid_str));
        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;
+               return WERR_DS_DRA_INTERNAL_ERROR;
        }
 
        neigh->source_dsa_obj_dn = ldb_dn_get_linearized(source_dsa_dn);
        }
 
        neigh->source_dsa_obj_dn = ldb_dn_get_linearized(source_dsa_dn);
@@ -184,8 +277,7 @@ static WERROR fill_neighbor_from_repsFrom(TALLOC_CTX *mem_ctx,
 
        if (dsdb_find_guid_by_dn(samdb, nc_dn, &neigh->naming_context_obj_guid)
                        != LDB_SUCCESS) {
 
        if (dsdb_find_guid_by_dn(samdb, nc_dn, &neigh->naming_context_obj_guid)
                        != LDB_SUCCESS) {
-               status = WERR_DS_DRA_INTERNAL_ERROR;
-               goto DONE;
+               return WERR_DS_DRA_INTERNAL_ERROR;
        }
 
        if (!GUID_all_zero(&reps_from->transport_guid)) {
        }
 
        if (!GUID_all_zero(&reps_from->transport_guid)) {
@@ -194,8 +286,7 @@ static WERROR fill_neighbor_from_repsFrom(TALLOC_CTX *mem_ctx,
                if (dsdb_find_dn_by_guid(samdb, mem_ctx, transp_guid_str,
                                         &transport_obj_dn) != LDB_SUCCESS)
                {
                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;
+                       return WERR_DS_DRA_INTERNAL_ERROR;
                }
        }
 
                }
        }
 
@@ -209,42 +300,42 @@ static WERROR fill_neighbor_from_repsFrom(TALLOC_CTX *mem_ctx,
        neigh->consecutive_sync_failures = reps_from->consecutive_sync_failures;
        neigh->reserved = 0; /* Unused. MUST be 0. */
 
        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;
+       return WERR_OK;
 }
 
 /*
 }
 
 /*
- * See details on MS-DRSR 4.1.13.3, for infoType DS_REPL_INFO_NEIGHBORS
- * */
+  Get the inbound neighbours of this DC
+  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,
 static WERROR kccdrs_replica_get_info_neighbours(TALLOC_CTX *mem_ctx,
+                                                struct kccsrv_service *service,
                                                 struct ldb_context *samdb,
                                                 struct drsuapi_DsReplicaGetInfo *r,
                                                 union drsuapi_DsReplicaInfo *reply,
                                                 int base_index,
                                                 struct GUID req_src_dsa_guid,
                                                 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)
+                                                const char *object_dn_str)
 {
        WERROR status;
 {
        WERROR status;
-
-       int i, j, k;
+       int i, j;
        struct ldb_dn *nc_dn = NULL;
        struct ncList *p_nc_list = NULL;
        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;
        struct repsFromToBlob *reps_from_blob = NULL;
        struct repsFromTo2 *reps_from = NULL;
        uint32_t c_reps_from;
-
        int i_rep;
        int i_rep;
+       struct drsuapi_DsReplicaNeighbour neigh;
+       struct ncList *nc_list = NULL;
 
 
-       struct neighList *neigh_list = NULL;
-       struct neighList *neigh_elem = NULL;
-
-       struct drsuapi_DsReplicaNeighbour *neigh = NULL;
+       status = get_ncs_list(mem_ctx, samdb, service, object_dn_str, &nc_list);
+       W_ERROR_NOT_OK_RETURN(status);
 
        i = j = 0;
 
        i = j = 0;
-       neigh_list = NULL;
+
+       reply->neighbours = talloc_zero(mem_ctx, struct drsuapi_DsReplicaNeighbourCtr);
+       W_ERROR_HAVE_NO_MEMORY(reply->neighbours);
+       reply->neighbours->reserved = 0;
+       reply->neighbours->count = 0;
 
        /* foreach nc in ncs */
        for (p_nc_list = nc_list; p_nc_list != NULL; p_nc_list = p_nc_list->next) {
 
        /* foreach nc in ncs */
        for (p_nc_list = nc_list; p_nc_list != NULL; p_nc_list = p_nc_list->next) {
@@ -254,10 +345,7 @@ static WERROR kccdrs_replica_get_info_neighbours(TALLOC_CTX *mem_ctx,
                /* load the nc's repsFromTo blob */
                status = dsdb_loadreps(samdb, mem_ctx, nc_dn, "repsFrom",
                                &reps_from_blob, &c_reps_from);
                /* 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;
-               }
+               W_ERROR_NOT_OK_RETURN(status);
 
                /* foreach r in nc!repsFrom */
                for (i_rep = 0; i_rep < c_reps_from; i_rep++) {
 
                /* foreach r in nc!repsFrom */
                for (i_rep = 0; i_rep < c_reps_from; i_rep++) {
@@ -266,9 +354,7 @@ static WERROR kccdrs_replica_get_info_neighbours(TALLOC_CTX *mem_ctx,
                        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 (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;
-                               }
+                               W_ERROR_NOT_OK_RETURN(status);
                        } else { /* reps_from->version == 2 */
                                reps_from = &reps_from_blob[i_rep].ctr.ctr2;
                        }
                        } else { /* reps_from->version == 2 */
                                reps_from = &reps_from_blob[i_rep].ctr.ctr2;
                        }
@@ -278,22 +364,17 @@ static WERROR kccdrs_replica_get_info_neighbours(TALLOC_CTX *mem_ctx,
                        {
 
                                if (i >= base_index) {
                        {
 
                                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,
                                        status = fill_neighbor_from_repsFrom(mem_ctx, samdb,
-                                                                            nc_dn, neigh,
+                                                                            nc_dn, &neigh,
                                                                             reps_from);
                                                                             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*);
-
+                                       W_ERROR_NOT_OK_RETURN(status);
+
+                                       /* append the neighbour to the neighbours array */
+                                       reply->neighbours->array = talloc_realloc(mem_ctx,
+                                                                                   reply->neighbours->array,
+                                                                                   struct drsuapi_DsReplicaNeighbour,
+                                                                                   reply->neighbours->count + 1);
+                                       reply->neighbours->array[reply->neighbours->count++] = neigh;
                                        j++;
                                }
 
                                        j++;
                                }
 
@@ -302,23 +383,7 @@ static WERROR kccdrs_replica_get_info_neighbours(TALLOC_CTX *mem_ctx,
                }
        }
 
                }
        }
 
-       /* 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;
+       return WERR_OK;
 }
 
 static WERROR fill_neighbor_from_repsTo(TALLOC_CTX *mem_ctx,
 }
 
 static WERROR fill_neighbor_from_repsTo(TALLOC_CTX *mem_ctx,
@@ -326,7 +391,6 @@ static WERROR fill_neighbor_from_repsTo(TALLOC_CTX *mem_ctx,
                                        struct drsuapi_DsReplicaNeighbour *neigh,
                                        struct repsFromTo2 *reps_to)
 {
                                        struct drsuapi_DsReplicaNeighbour *neigh,
                                        struct repsFromTo2 *reps_to)
 {
-       WERROR status;
        char *dsa_guid_str;
        int ret;
        struct ldb_dn *source_dsa_dn;
        char *dsa_guid_str;
        int ret;
        struct ldb_dn *source_dsa_dn;
@@ -343,8 +407,7 @@ static WERROR fill_neighbor_from_repsTo(TALLOC_CTX *mem_ctx,
        if (ret != LDB_SUCCESS) {
                DEBUG(0,(__location__ ": Failed to find DN for neighbor GUID %s\n",
                         dsa_guid_str));
        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;
+               return WERR_DS_DRA_INTERNAL_ERROR;
        }
 
        neigh->source_dsa_obj_dn = ldb_dn_get_linearized(source_dsa_dn);
        }
 
        neigh->source_dsa_obj_dn = ldb_dn_get_linearized(source_dsa_dn);
@@ -355,34 +418,46 @@ static WERROR fill_neighbor_from_repsTo(TALLOC_CTX *mem_ctx,
        if (ret != LDB_SUCCESS) {
                DEBUG(0,(__location__ ": Failed to find GUID for DN %s\n",
                         ldb_dn_get_linearized(nc_dn)));
        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;
+               return WERR_DS_DRA_INTERNAL_ERROR;
        }
 
        }
 
-       /* If everything went fine so far, set the status to OK */
-       status = WERR_OK;
-       DONE: return status;
+       return WERR_OK;
 }
 
 }
 
+/*
+  Get the outbound neighbours of this DC
+  See details on MS-DRSR 4.1.13.3, for infoType DS_REPL_INFO_REPSTO
+*/
 static WERROR kccdrs_replica_get_info_repsto(TALLOC_CTX *mem_ctx,
 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)
+                                            struct kccsrv_service *service,
+                                            struct ldb_context *samdb,
+                                            struct drsuapi_DsReplicaGetInfo *r,
+                                            union drsuapi_DsReplicaInfo *reply,
+                                            int base_index,
+                                            struct GUID req_src_dsa_guid,
+                                            const char *object_dn_str)
 {
        WERROR status;
 {
        WERROR status;
-       int i, j, k;
+       int i, j;
        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 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;
+       struct drsuapi_DsReplicaNeighbour neigh;
+       struct ncList *nc_list = NULL;
+
+       status = get_ncs_list(mem_ctx, samdb, service, object_dn_str, &nc_list);
+       W_ERROR_NOT_OK_RETURN(status);
 
        i = j = 0;
 
 
        i = j = 0;
 
+       reply->neighbours02 = talloc_zero(mem_ctx, struct drsuapi_DsReplicaNeighbourCtr);
+       W_ERROR_HAVE_NO_MEMORY(reply->neighbours02);
+       reply->neighbours02->reserved = 0;
+       reply->neighbours02->count = 0;
+
        /* foreach nc in ncs */
        for (p_nc_list = nc_list; p_nc_list != NULL; p_nc_list = p_nc_list->next) {
 
        /* foreach nc in ncs */
        for (p_nc_list = nc_list; p_nc_list != NULL; p_nc_list = p_nc_list->next) {
 
@@ -390,153 +465,56 @@ static WERROR kccdrs_replica_get_info_repsto(TALLOC_CTX *mem_ctx,
 
                status = dsdb_loadreps(samdb, mem_ctx, nc_dn, "repsTo",
                                &reps_to_blob, &c_reps_to);
 
                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;
-               }
+               W_ERROR_NOT_OK_RETURN(status);
 
                /* foreach r in nc!repsTo */
                for (i_rep = 0; i_rep < c_reps_to; i_rep++) {
 
 
                /* foreach r in nc!repsTo */
                for (i_rep = 0; i_rep < c_reps_to; i_rep++) {
 
-                       /* put all info on reps_from */
+                       /* put all info on reps_to */
                        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 (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 */
+                               W_ERROR_NOT_OK_RETURN(status);
+                       } else { /* reps_to->version == 2 */
                                reps_to = &reps_to_blob[i_rep].ctr.ctr2;
                        }
 
                        if (i >= base_index) {
                                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,
                                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*);
-
+                                                                  &neigh, reps_to);
+                               W_ERROR_NOT_OK_RETURN(status);
+
+                               /* append the neighbour to the neighbours array */
+                               reply->neighbours02->array = talloc_realloc(mem_ctx,
+                                                                           reply->neighbours02->array,
+                                                                           struct drsuapi_DsReplicaNeighbour,
+                                                                           reply->neighbours02->count + 1);
+                               reply->neighbours02->array[reply->neighbours02->count++] = neigh;
                                j++;
                        }
                                j++;
                        }
-
                        i++;
                }
        }
 
                        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;
+       return WERR_OK;
 }
 
 NTSTATUS kccdrs_replica_get_info(struct irpc_message *msg,
                                 struct drsuapi_DsReplicaGetInfo *req)
 {
        WERROR status;
 }
 
 NTSTATUS kccdrs_replica_get_info(struct irpc_message *msg,
                                 struct drsuapi_DsReplicaGetInfo *req)
 {
        WERROR status;
-
        struct drsuapi_DsReplicaGetInfoRequest1 *req1;
        struct drsuapi_DsReplicaGetInfoRequest2 *req2;
        struct drsuapi_DsReplicaGetInfoRequest1 *req1;
        struct drsuapi_DsReplicaGetInfoRequest2 *req2;
-       enum drsuapi_DsReplicaInfoType info_type, *tmp_p_info_type;
-
        int base_index;
        union drsuapi_DsReplicaInfo *reply;
        int base_index;
        union drsuapi_DsReplicaInfo *reply;
-
        struct GUID req_src_dsa_guid;
        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;
-
+       const char *object_dn_str = NULL;
        struct kccsrv_service *service;
        struct ldb_context *samdb;
        TALLOC_CTX *mem_ctx;
        struct kccsrv_service *service;
        struct ldb_context *samdb;
        TALLOC_CTX *mem_ctx;
+       enum drsuapi_DsReplicaInfoType info_type;
 
        service = talloc_get_type(msg->private_data, struct kccsrv_service);
        samdb = service->samdb;
 
        service = talloc_get_type(msg->private_data, struct kccsrv_service);
        samdb = service->samdb;
@@ -552,14 +530,14 @@ NTSTATUS kccdrs_replica_get_info(struct irpc_message *msg,
                DEBUG(1,(__location__ ": Unsupported DsReplicaGetInfo level %u\n",
                         req->in.level));
                status = WERR_REVISION_MISMATCH;
                DEBUG(1,(__location__ ": Unsupported DsReplicaGetInfo level %u\n",
                         req->in.level));
                status = WERR_REVISION_MISMATCH;
-               goto DONE;
+               goto done;
        }
 
        if (req->in.level == DRSUAPI_DS_REPLICA_GET_INFO) {
                req1 = &req->in.req->req1;
                base_index = 0;
                info_type = req1->info_type;
        }
 
        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;
+               object_dn_str = req1->object_dn;
                req_src_dsa_guid = req1->guid1;
 
        } else { /* r->in.level == DRSUAPI_DS_REPLICA_GET_INFO2 */
                req_src_dsa_guid = req1->guid1;
 
        } else { /* r->in.level == DRSUAPI_DS_REPLICA_GET_INFO2 */
@@ -567,99 +545,48 @@ NTSTATUS kccdrs_replica_get_info(struct irpc_message *msg,
                if (req2->enumeration_context == 0xffffffff) {
                        /* no more data is available */
                        status = WERR_NO_MORE_ITEMS; /* on MS-DRSR it is ERROR_NO_MORE_ITEMS */
                if (req2->enumeration_context == 0xffffffff) {
                        /* no more data is available */
                        status = WERR_NO_MORE_ITEMS; /* on MS-DRSR it is ERROR_NO_MORE_ITEMS */
-                       goto DONE;
+                       goto done;
                }
 
                base_index = req2->enumeration_context;
                info_type = req2->info_type;
                }
 
                base_index = req2->enumeration_context;
                info_type = req2->info_type;
-               object_dn = req2->object_dn;
+               object_dn_str = req2->object_dn;
                req_src_dsa_guid = req2->guid1;
        }
 
                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 %u requested is invalid.", (unsigned)info_type));
-               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;
        /* 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;
+       req->out.info_type = talloc(mem_ctx, enum drsuapi_DsReplicaInfoType);
+       NT_STATUS_HAVE_NO_MEMORY(req->out.info_type);
+       *req->out.info_type = 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:
 
        /* Based on the infoType requested, retrieve the corresponding
         * information and construct the response message */
        switch (info_type) {
 
        case DRSUAPI_DS_REPLICA_INFO_NEIGHBORS:
+               status = kccdrs_replica_get_info_neighbours(mem_ctx, service, samdb, req,
+                                                           reply, base_index, req_src_dsa_guid,
+                                                           object_dn_str);
+               break;
        case DRSUAPI_DS_REPLICA_INFO_NEIGHBORS02: /* On MS-DRSR it is DS_REPL_INFO_REPSTO */
        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);
-                       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 = kccdrs_replica_get_info_repsto(mem_ctx, samdb, req,
-                                                               reply, base_index,
-                                                               req_src_dsa_guid, nc_list);
-               }
-
+               status = kccdrs_replica_get_info_repsto(mem_ctx, service, samdb, req,
+                                                       reply, base_index, req_src_dsa_guid,
+                                                       object_dn_str);
                break;
                break;
-
        case DRSUAPI_DS_REPLICA_INFO_CURSORS: /* On MS-DRSR it is DS_REPL_INFO_CURSORS_FOR_NC */
                status = kccdrs_replica_get_info_cursors(mem_ctx, samdb, req, reply,
        case DRSUAPI_DS_REPLICA_INFO_CURSORS: /* On MS-DRSR it is DS_REPL_INFO_CURSORS_FOR_NC */
                status = kccdrs_replica_get_info_cursors(mem_ctx, samdb, req, reply,
-                                                        ldb_dn_new(mem_ctx, samdb, object_dn));
+                                                        ldb_dn_new(mem_ctx, samdb, object_dn_str));
                break;
        case DRSUAPI_DS_REPLICA_INFO_CURSORS2: /* On MS-DRSR it is DS_REPL_INFO_CURSORS_2_FOR_NC */
                status = kccdrs_replica_get_info_cursors2(mem_ctx, samdb, req, reply,
                break;
        case DRSUAPI_DS_REPLICA_INFO_CURSORS2: /* On MS-DRSR it is DS_REPL_INFO_CURSORS_2_FOR_NC */
                status = kccdrs_replica_get_info_cursors2(mem_ctx, samdb, req, reply,
-                                                         ldb_dn_new(mem_ctx, samdb, object_dn));
+                                                         ldb_dn_new(mem_ctx, samdb, object_dn_str));
                break;
        case DRSUAPI_DS_REPLICA_INFO_PENDING_OPS: /* On MS-DRSR it is DS_REPL_INFO_PENDING_OPS */
                status = kccdrs_replica_get_info_pending_ops(mem_ctx, samdb, req, reply,
                break;
        case DRSUAPI_DS_REPLICA_INFO_PENDING_OPS: /* On MS-DRSR it is DS_REPL_INFO_PENDING_OPS */
                status = kccdrs_replica_get_info_pending_ops(mem_ctx, samdb, req, reply,
-                                                            ldb_dn_new(mem_ctx, samdb, object_dn));
+                                                            ldb_dn_new(mem_ctx, samdb, object_dn_str));
                break;
 
        case DRSUAPI_DS_REPLICA_INFO_CURSORS3: /* On MS-DRSR it is DS_REPL_INFO_CURSORS_3_FOR_NC */
                break;
 
        case DRSUAPI_DS_REPLICA_INFO_CURSORS3: /* On MS-DRSR it is DS_REPL_INFO_CURSORS_3_FOR_NC */
@@ -679,7 +606,7 @@ NTSTATUS kccdrs_replica_get_info(struct irpc_message *msg,
                break;
        }
 
                break;
        }
 
-DONE:
+done:
        /* put the status on the result field of the reply */
        req->out.result = status;
        NDR_PRINT_OUT_DEBUG(drsuapi_DsReplicaGetInfo, req);
        /* put the status on the result field of the reply */
        req->out.result = status;
        NDR_PRINT_OUT_DEBUG(drsuapi_DsReplicaGetInfo, req);
index acad1a09169551fc8a1970043f1ed87dbe68aca9..03bda7e70ed84e133eb9cddd1041208d5e331715 100644 (file)
@@ -172,6 +172,7 @@ static bool test_getinfo(struct torture_context *tctx,
        union drsuapi_DsReplicaInfo info;
        enum drsuapi_DsReplicaInfoType info_type;
        int i;
        union drsuapi_DsReplicaInfo info;
        enum drsuapi_DsReplicaInfoType info_type;
        int i;
+       int invalid_levels = 0;
        struct {
                int32_t level;
                int32_t infotype;
        struct {
                int32_t level;
                int32_t infotype;
@@ -278,14 +279,24 @@ static bool test_getinfo(struct torture_context *tctx,
                r.out.info_type         = &info_type;
 
                status = dcerpc_drsuapi_DsReplicaGetInfo(p, tctx, &r);
                r.out.info_type         = &info_type;
 
                status = dcerpc_drsuapi_DsReplicaGetInfo(p, tctx, &r);
-               torture_drsuapi_assert_call(tctx, p, status, &r, "dcerpc_drsuapi_DsReplicaGetInfo");
-               if (!NT_STATUS_IS_OK(status) && p->last_fault_code == DCERPC_FAULT_INVALID_TAG) {
+
+               if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
+                       /* this is a not yet supported level */
+                       torture_comment(tctx,
+                                       "DsReplicaGetInfo level %d and/or infotype %d not yet supported by server\n",
+                                       array[i].level, array[i].infotype);
+                       invalid_levels++;
+               } else if (!NT_STATUS_IS_OK(status) && p->last_fault_code == DCERPC_FAULT_INVALID_TAG) {
                        torture_comment(tctx,
                                        "DsReplicaGetInfo level %d and/or infotype %d not supported by server\n",
                                        array[i].level, array[i].infotype);
                        torture_comment(tctx,
                                        "DsReplicaGetInfo level %d and/or infotype %d not supported by server\n",
                                        array[i].level, array[i].infotype);
-               } else {
+               }/* else {
                        torture_drsuapi_assert_call(tctx, p, status, &r, "dcerpc_drsuapi_DsReplicaGetInfo");
                        torture_drsuapi_assert_call(tctx, p, status, &r, "dcerpc_drsuapi_DsReplicaGetInfo");
-               }
+               }*/
+       }
+
+       if (invalid_levels > 0) {
+               return false;
        }
 
        return true;
        }
 
        return true;