LCOV - code coverage report
Current view: top level - source4/dsdb/kcc - kcc_drs_replica_info.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 176 450 39.1 %
Date: 2024-04-21 15:09:00 Functions: 8 15 53.3 %

          Line data    Source code
       1             : /*
       2             :  Unix SMB/CIFS implementation.
       3             : 
       4             :  DRS Replica Information
       5             : 
       6             :  Copyright (C) Erick Nogueira do Nascimento 2009-2010
       7             : 
       8             :  This program is free software; you can redistribute it and/or modify
       9             :  it under the terms of the GNU General Public License as published by
      10             :  the Free Software Foundation; either version 3 of the License, or
      11             :  (at your option) any later version.
      12             : 
      13             :  This program is distributed in the hope that it will be useful,
      14             :  but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :  GNU General Public License for more details.
      17             : 
      18             :  You should have received a copy of the GNU General Public License
      19             :  along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : 
      21             :  */
      22             : 
      23             : #include "includes.h"
      24             : #include "dsdb/samdb/samdb.h"
      25             : #include "dsdb/common/proto.h"
      26             : #include "auth/auth.h"
      27             : #include "samba/service.h"
      28             : #include "lib/events/events.h"
      29             : #include "lib/messaging/irpc.h"
      30             : #include "dsdb/kcc/kcc_service.h"
      31             : #include <ldb_errors.h>
      32             : #include "../lib/util/dlinklist.h"
      33             : #include "librpc/gen_ndr/ndr_misc.h"
      34             : #include "librpc/gen_ndr/ndr_drsuapi.h"
      35             : #include "librpc/gen_ndr/ndr_drsblobs.h"
      36             : #include "param/param.h"
      37             : #include "dsdb/common/util.h"
      38             : 
      39             : 
      40             : /*
      41             :    get the stamp values for the linked attribute 'linked_attr_name' of the object 'dn'
      42             : */
      43           0 : static WERROR get_linked_attribute_value_stamp(TALLOC_CTX *mem_ctx, struct ldb_context *samdb,
      44             :                                        struct ldb_dn *dn, const char *linked_attr_name,
      45             :                                        uint32_t *attr_version, NTTIME *attr_change_time, uint32_t *attr_orig_usn)
      46             : {
      47           0 :         struct ldb_result *res;
      48           0 :         int ret;
      49           0 :         const char *attrs[2];
      50           0 :         struct ldb_dn *attr_ext_dn;
      51           0 :         NTSTATUS ntstatus;
      52             : 
      53           0 :         attrs[0] = linked_attr_name;
      54           0 :         attrs[1] = NULL;
      55             : 
      56           0 :         ret = dsdb_search_dn(samdb, mem_ctx, &res, dn, attrs,
      57             :                              DSDB_SEARCH_SHOW_EXTENDED_DN | DSDB_SEARCH_REVEAL_INTERNALS);
      58           0 :         if (ret != LDB_SUCCESS) {
      59           0 :                 DEBUG(0, (__location__ ": Failed search for attribute %s on %s\n",
      60             :                                 linked_attr_name, ldb_dn_get_linearized(dn)));
      61           0 :                 return WERR_INTERNAL_ERROR;
      62             :         }
      63             : 
      64           0 :         attr_ext_dn = ldb_msg_find_attr_as_dn(samdb, mem_ctx, res->msgs[0], linked_attr_name);
      65           0 :         if (!attr_ext_dn) {
      66           0 :                 DEBUG(0, (__location__ ": Failed search for attribute %s on %s\n",
      67             :                                 linked_attr_name, ldb_dn_get_linearized(dn)));
      68           0 :                 return WERR_INTERNAL_ERROR;
      69             :         }
      70             : 
      71           0 :         DEBUG(0, ("linked_attr_name = %s, attr_ext_dn = %s", linked_attr_name,
      72             :                   ldb_dn_get_extended_linearized(mem_ctx, attr_ext_dn, 1)));
      73             : 
      74           0 :         ntstatus = dsdb_get_extended_dn_uint32(attr_ext_dn, attr_version, "RMD_VERSION");
      75           0 :         if (!NT_STATUS_IS_OK(ntstatus)) {
      76           0 :                 DEBUG(0, (__location__ ": Could not extract component %s from dn \"%s\"\n",
      77             :                                 "RMD_VERSION", ldb_dn_get_extended_linearized(mem_ctx, attr_ext_dn, 1)));
      78           0 :                 return WERR_INTERNAL_ERROR;
      79             :         }
      80             : 
      81           0 :         ntstatus = dsdb_get_extended_dn_nttime(attr_ext_dn, attr_change_time, "RMD_CHANGETIME");
      82           0 :         if (!NT_STATUS_IS_OK(ntstatus)) {
      83           0 :                 DEBUG(0, (__location__ ": Could not extract component %s from dn \"%s\"\n",
      84             :                                 "RMD_CHANGETIME", ldb_dn_get_extended_linearized(mem_ctx, attr_ext_dn, 1)));
      85           0 :                 return WERR_INTERNAL_ERROR;
      86             :         }
      87             : 
      88           0 :         ntstatus = dsdb_get_extended_dn_uint32(attr_ext_dn, attr_version, "RMD_ORIGINATING_USN");
      89           0 :         if (!NT_STATUS_IS_OK(ntstatus)) {
      90           0 :                 DEBUG(0, (__location__ ": Could not extract component %s from dn \"%s\"\n",
      91             :                                 "RMD_ORIGINATING_USN", ldb_dn_get_extended_linearized(mem_ctx, attr_ext_dn, 1)));
      92           0 :                 return WERR_INTERNAL_ERROR;
      93             :         }
      94             : 
      95           0 :         return WERR_OK;
      96             : }
      97             : 
      98           0 : static WERROR get_repl_prop_metadata_ctr(TALLOC_CTX *mem_ctx,
      99             :                                          struct ldb_context *samdb,
     100             :                                          struct ldb_dn *dn,
     101             :                                          struct replPropertyMetaDataBlob *obj_metadata_ctr)
     102             : {
     103           0 :         int ret;
     104           0 :         struct ldb_result *res;
     105           0 :         const char *attrs[] = { "replPropertyMetaData", NULL };
     106           0 :         const struct ldb_val *omd_value;
     107           0 :         enum ndr_err_code ndr_err;
     108             : 
     109           0 :         ret = ldb_search(samdb, mem_ctx, &res, dn, LDB_SCOPE_BASE, attrs, NULL);
     110           0 :         if (ret != LDB_SUCCESS || res->count != 1) {
     111           0 :                 DEBUG(0, (__location__ ": Failed search for replPropertyMetaData attribute on %s\n",
     112             :                           ldb_dn_get_linearized(dn)));
     113           0 :                 return WERR_INTERNAL_ERROR;
     114             :         }
     115             : 
     116           0 :         omd_value = ldb_msg_find_ldb_val(res->msgs[0], "replPropertyMetaData");
     117           0 :         if (!omd_value) {
     118           0 :                 DEBUG(0,(__location__ ": Object %s does not have a replPropertyMetaData attribute\n",
     119             :                          ldb_dn_get_linearized(dn)));
     120           0 :                 talloc_free(res);
     121           0 :                 return WERR_INTERNAL_ERROR;
     122             :         }
     123             : 
     124           0 :         ndr_err = ndr_pull_struct_blob(omd_value, mem_ctx,
     125             :                                         obj_metadata_ctr,
     126             :                                        (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob);
     127           0 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     128           0 :                 DEBUG(0,(__location__ ": Failed to parse replPropertyMetaData for %s\n",
     129             :                          ldb_dn_get_linearized(dn)));
     130           0 :                 talloc_free(res);
     131           0 :                 return WERR_INTERNAL_ERROR;
     132             :         }
     133             : 
     134           0 :         talloc_free(res);
     135           0 :         return WERR_OK;
     136             : }
     137             : 
     138             : /*
     139             :   get the DN of the nTDSDSA object from the configuration partition
     140             :   whose invocationId is 'invocation_id'
     141             :   put the value on 'dn_str'
     142             : */
     143           0 : static WERROR get_dn_from_invocation_id(TALLOC_CTX *mem_ctx,
     144             :                                         struct ldb_context *samdb,
     145             :                                         struct GUID *invocation_id,
     146             :                                         const char **dn_str)
     147             : {
     148           0 :         char *invocation_id_str;
     149           0 :         const char *attrs_invocation[] = { NULL };
     150           0 :         struct ldb_message *msg;
     151           0 :         int ret;
     152             : 
     153           0 :         invocation_id_str = GUID_string(mem_ctx, invocation_id);
     154           0 :         W_ERROR_HAVE_NO_MEMORY(invocation_id_str);
     155             : 
     156           0 :         ret = dsdb_search_one(samdb, invocation_id_str, &msg, ldb_get_config_basedn(samdb), LDB_SCOPE_SUBTREE,
     157             :                               attrs_invocation, 0, "(&(objectClass=nTDSDSA)(invocationId=%s))", invocation_id_str);
     158           0 :         if (ret != LDB_SUCCESS) {
     159           0 :                 DEBUG(0, (__location__ ": Failed search for the object DN under %s whose invocationId is %s\n",
     160             :                           invocation_id_str, ldb_dn_get_linearized(ldb_get_config_basedn(samdb))));
     161           0 :                 talloc_free(invocation_id_str);
     162           0 :                 return WERR_INTERNAL_ERROR;
     163             :         }
     164             : 
     165           0 :         *dn_str = ldb_dn_alloc_linearized(mem_ctx, msg->dn);
     166           0 :         talloc_free(invocation_id_str);
     167           0 :         return WERR_OK;
     168             : }
     169             : 
     170             : /*
     171             :   get metadata version 2 info for a specified object DN
     172             : */
     173           0 : static WERROR kccdrs_replica_get_info_obj_metadata2(TALLOC_CTX *mem_ctx,
     174             :                                                     struct ldb_context *samdb,
     175             :                                                     struct drsuapi_DsReplicaGetInfo *r,
     176             :                                                     union drsuapi_DsReplicaInfo *reply,
     177             :                                                     struct ldb_dn *dn,
     178             :                                                     uint32_t base_index)
     179             : {
     180           0 :         WERROR status;
     181           0 :         struct replPropertyMetaDataBlob omd_ctr;
     182           0 :         struct replPropertyMetaData1 *attr;
     183           0 :         struct drsuapi_DsReplicaObjMetaData2Ctr *metadata2;
     184           0 :         const struct dsdb_schema *schema;
     185             : 
     186           0 :         uint32_t i, j;
     187             : 
     188           0 :         DEBUG(0, ("kccdrs_replica_get_info_obj_metadata2() called\n"));
     189             : 
     190           0 :         if (!dn) {
     191           0 :                 return WERR_INVALID_PARAMETER;
     192             :         }
     193             : 
     194           0 :         if (!ldb_dn_validate(dn)) {
     195           0 :                 return WERR_DS_DRA_BAD_DN;
     196             :         }
     197             : 
     198           0 :         status = get_repl_prop_metadata_ctr(mem_ctx, samdb, dn, &omd_ctr);
     199           0 :         W_ERROR_NOT_OK_RETURN(status);
     200             : 
     201           0 :         schema = dsdb_get_schema(samdb, reply);
     202           0 :         if (!schema) {
     203           0 :                 DEBUG(0,(__location__": Failed to get the schema\n"));
     204           0 :                 return WERR_INTERNAL_ERROR;
     205             :         }
     206             : 
     207           0 :         reply->objmetadata2 = talloc_zero(mem_ctx, struct drsuapi_DsReplicaObjMetaData2Ctr);
     208           0 :         W_ERROR_HAVE_NO_MEMORY(reply->objmetadata2);
     209           0 :         metadata2 = reply->objmetadata2;
     210           0 :         metadata2->enumeration_context = 0;
     211             : 
     212             :         /* For each replicated attribute of the object */
     213           0 :         for (i = 0, j = 0; i < omd_ctr.ctr.ctr1.count; i++) {
     214           0 :                 const struct dsdb_attribute *schema_attr;
     215           0 :                 uint32_t attr_version;
     216           0 :                 NTTIME attr_change_time;
     217           0 :                 uint32_t attr_originating_usn = 0;
     218             : 
     219             :                 /*
     220             :                   attr := attrsSeq[i]
     221             :                   s := AttrStamp(object, attr)
     222             :                 */
     223             :                 /* get a reference to the attribute on 'omd_ctr' */
     224           0 :                 attr = &omd_ctr.ctr.ctr1.array[j];
     225             : 
     226           0 :                 schema_attr = dsdb_attribute_by_attributeID_id(schema, attr->attid);
     227             : 
     228           0 :                 DEBUG(0, ("attribute_id = %d, attribute_name: %s\n", attr->attid, schema_attr->lDAPDisplayName));
     229             : 
     230             :                 /*
     231             :                   if (attr in Link Attributes of object and
     232             :                     dwInVersion = 2 and DS_REPL_INFO_FLAG_IMPROVE_LINKED_ATTRS in msgIn.ulFlags)
     233             :                 */
     234           0 :                 if (schema_attr &&
     235           0 :                     schema_attr->linkID != 0 && /* Checks if attribute is a linked attribute */
     236           0 :                     (schema_attr->linkID % 2) == 0 && /* is it a forward link? only forward links have the LinkValueStamp */
     237           0 :                     r->in.level == 2 &&
     238           0 :                     (r->in.req->req2.flags & DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE)) /* on MS-DRSR it is DS_REPL_INFO_FLAG_IMPROVE_LINKED_ATTRS */
     239             :                 {
     240             :                         /*
     241             :                           ls := LinkValueStamp of the most recent
     242             :                                 value change in object!attr
     243             :                         */
     244           0 :                         status = get_linked_attribute_value_stamp(mem_ctx, samdb, dn, schema_attr->lDAPDisplayName,
     245             :                                                                   &attr_version, &attr_change_time, &attr_originating_usn);
     246           0 :                         W_ERROR_NOT_OK_RETURN(status);
     247             : 
     248             :                         /*
     249             :                          Aligning to MS-DRSR 4.1.13.3:
     250             :                          's' on the doc is 'attr->originating_change_time' here
     251             :                          'ls' on the doc is 'attr_change_time' here
     252             :                         */
     253             : 
     254             :                         /* if (ls is more recent than s (based on order in which the change was applied on server)) then */
     255           0 :                         if (attr_change_time > attr->originating_change_time) {
     256             :                                 /*
     257             :                                  Improve the stamp with the link value stamp.
     258             :                                   s.dwVersion := ls.dwVersion
     259             :                                   s.timeChanged := ls.timeChanged
     260             :                                   s.uuidOriginating := NULLGUID
     261             :                                   s.usnOriginating := ls.usnOriginating
     262             :                                 */
     263           0 :                                 attr->version = attr_version;
     264           0 :                                 attr->originating_change_time = attr_change_time;
     265           0 :                                 attr->originating_invocation_id = GUID_zero();
     266           0 :                                 attr->originating_usn = attr_originating_usn;
     267             :                         }
     268             :                 }
     269             : 
     270           0 :                 if (i < base_index) {
     271           0 :                         continue;
     272             :                 }
     273             : 
     274           0 :                 metadata2->array = talloc_realloc(mem_ctx, metadata2->array,
     275             :                                                   struct drsuapi_DsReplicaObjMetaData2, j + 1);
     276           0 :                 W_ERROR_HAVE_NO_MEMORY(metadata2->array);
     277           0 :                 metadata2->array[j].attribute_name = schema_attr->lDAPDisplayName;
     278           0 :                 metadata2->array[j].local_usn = attr->local_usn;
     279           0 :                 metadata2->array[j].originating_change_time = attr->originating_change_time;
     280           0 :                 metadata2->array[j].originating_invocation_id = attr->originating_invocation_id;
     281           0 :                 metadata2->array[j].originating_usn = attr->originating_usn;
     282           0 :                 metadata2->array[j].version = attr->version;
     283             : 
     284             :                 /*
     285             :                   originating_dsa_dn := GetDNFromInvocationID(originating_invocation_id)
     286             :                   GetDNFromInvocationID() should return the DN of the nTDSDSAobject that has the specified invocation ID
     287             :                   See MS-DRSR 4.1.13.3 and 4.1.13.2.1
     288             :                 */
     289           0 :                 status = get_dn_from_invocation_id(mem_ctx, samdb,
     290             :                                                    &attr->originating_invocation_id,
     291           0 :                                                    &metadata2->array[j].originating_dsa_dn);
     292           0 :                 W_ERROR_NOT_OK_RETURN(status);
     293           0 :                 j++;
     294           0 :                 metadata2->count = j;
     295             : 
     296             :         }
     297             : 
     298           0 :         return WERR_OK;
     299             : }
     300             : 
     301             : /*
     302             :   get cursors info for a specified DN
     303             : */
     304           0 : static WERROR kccdrs_replica_get_info_cursors(TALLOC_CTX *mem_ctx,
     305             :                                               struct ldb_context *samdb,
     306             :                                               struct drsuapi_DsReplicaGetInfo *r,
     307             :                                               union drsuapi_DsReplicaInfo *reply,
     308             :                                               struct ldb_dn *dn)
     309             : {
     310           0 :         int ret;
     311             : 
     312           0 :         if (!ldb_dn_validate(dn)) {
     313           0 :                 return WERR_INVALID_PARAMETER;
     314             :         }
     315           0 :         reply->cursors = talloc(mem_ctx, struct drsuapi_DsReplicaCursorCtr);
     316           0 :         W_ERROR_HAVE_NO_MEMORY(reply->cursors);
     317             : 
     318           0 :         reply->cursors->reserved = 0;
     319             : 
     320           0 :         ret = dsdb_load_udv_v1(samdb, dn, reply->cursors, &reply->cursors->array, &reply->cursors->count);
     321           0 :         if (ret != LDB_SUCCESS) {
     322           0 :                 return WERR_DS_DRA_BAD_NC;
     323             :         }
     324           0 :         return WERR_OK;
     325             : }
     326             : 
     327             : /*
     328             :   get cursors2 info for a specified DN
     329             : */
     330           0 : static WERROR kccdrs_replica_get_info_cursors2(TALLOC_CTX *mem_ctx,
     331             :                                                struct ldb_context *samdb,
     332             :                                                struct drsuapi_DsReplicaGetInfo *r,
     333             :                                                union drsuapi_DsReplicaInfo *reply,
     334             :                                                struct ldb_dn *dn)
     335             : {
     336           0 :         int ret;
     337             : 
     338           0 :         if (!ldb_dn_validate(dn)) {
     339           0 :                 return WERR_INVALID_PARAMETER;
     340             :         }
     341           0 :         reply->cursors2 = talloc(mem_ctx, struct drsuapi_DsReplicaCursor2Ctr);
     342           0 :         W_ERROR_HAVE_NO_MEMORY(reply->cursors2);
     343             : 
     344           0 :         ret = dsdb_load_udv_v2(samdb, dn, reply->cursors2, &reply->cursors2->array, &reply->cursors2->count);
     345           0 :         if (ret != LDB_SUCCESS) {
     346           0 :                 return WERR_DS_DRA_BAD_NC;
     347             :         }
     348             : 
     349           0 :         reply->cursors2->enumeration_context = reply->cursors2->count;
     350           0 :         return WERR_OK;
     351             : }
     352             : 
     353             : /*
     354             :   get pending ops info for a specified DN
     355             : */
     356           0 : static WERROR kccdrs_replica_get_info_pending_ops(TALLOC_CTX *mem_ctx,
     357             :                                                   struct ldb_context *samdb,
     358             :                                                   struct drsuapi_DsReplicaGetInfo *r,
     359             :                                                   union drsuapi_DsReplicaInfo *reply,
     360             :                                                   struct ldb_dn *dn)
     361             : {
     362           0 :         struct timeval now = timeval_current();
     363             : 
     364           0 :         if (!ldb_dn_validate(dn)) {
     365           0 :                 return WERR_INVALID_PARAMETER;
     366             :         }
     367           0 :         reply->pendingops = talloc(mem_ctx, struct drsuapi_DsReplicaOpCtr);
     368           0 :         W_ERROR_HAVE_NO_MEMORY(reply->pendingops);
     369             : 
     370             :         /* claim no pending ops for now */
     371           0 :         reply->pendingops->time = timeval_to_nttime(&now);
     372           0 :         reply->pendingops->count = 0;
     373           0 :         reply->pendingops->array = NULL;
     374             : 
     375           0 :         return WERR_OK;
     376             : }
     377             : 
     378             : struct ncList {
     379             :         struct ldb_dn *dn;
     380             :         struct ncList *prev, *next;
     381             : };
     382             : 
     383             : /*
     384             :   Fill 'master_nc_list' with the master ncs hosted by this server
     385             : */
     386          10 : static WERROR get_master_ncs(TALLOC_CTX *mem_ctx, struct ldb_context *samdb,
     387             :                              const char *ntds_guid_str, struct ncList **master_nc_list)
     388             : {
     389          10 :         const char *post_2003_attrs[] = { "msDS-hasMasterNCs", "hasPartialReplicaNCs", NULL };
     390          10 :         const char *pre_2003_attrs[] = { "hasMasterNCs", "hasPartialReplicaNCs", NULL };
     391          10 :         const char **attrs = post_2003_attrs;
     392           0 :         struct ldb_result *res;
     393          10 :         struct ncList *nc_list = NULL;
     394           0 :         struct ncList *nc_list_elem;
     395           0 :         int ret;
     396           0 :         unsigned int i;
     397           0 :         char *nc_str;
     398             : 
     399             :         /* In W2003 and greater, msDS-hasMasterNCs attribute lists the writable NC replicas */
     400          10 :         ret = ldb_search(samdb, mem_ctx, &res, ldb_get_config_basedn(samdb),
     401             :                         LDB_SCOPE_DEFAULT, post_2003_attrs, "(objectguid=%s)", ntds_guid_str);
     402             : 
     403          10 :         if (ret != LDB_SUCCESS) {
     404           0 :                 DEBUG(0,(__location__ ": Failed objectguid search - %s\n", ldb_errstring(samdb)));
     405             : 
     406           0 :                 attrs = post_2003_attrs;
     407           0 :                 ret = ldb_search(samdb, mem_ctx, &res, ldb_get_config_basedn(samdb),
     408             :                         LDB_SCOPE_DEFAULT, pre_2003_attrs, "(objectguid=%s)", ntds_guid_str);
     409             :         }
     410             : 
     411          10 :         if (ret != LDB_SUCCESS) {
     412           0 :                 DEBUG(0,(__location__ ": Failed objectguid search - %s\n", ldb_errstring(samdb)));
     413           0 :                 return WERR_INTERNAL_ERROR;
     414             :         }
     415             : 
     416          10 :         if (res->count == 0) {
     417           0 :                 DEBUG(0,(__location__ ": Failed: objectguid=%s not found\n", ntds_guid_str));
     418           0 :                 return WERR_INTERNAL_ERROR;
     419             :         }
     420             : 
     421          20 :         for (i = 0; i < res->count; i++) {
     422             :                 struct ldb_message_element *msg_elem;
     423             :                 unsigned int k, a;
     424             : 
     425          30 :                 for (a=0; attrs[a]; a++) {
     426          20 :                         msg_elem = ldb_msg_find_element(res->msgs[i], attrs[a]);
     427          20 :                         if (!msg_elem || msg_elem->num_values == 0) {
     428          10 :                                 continue;
     429             :                         }
     430             : 
     431          60 :                         for (k = 0; k < msg_elem->num_values; k++) {
     432             :                                 /* copy the string on msg_elem->values[k]->data to nc_str */
     433          50 :                                 nc_str = talloc_strndup(mem_ctx, (char *)msg_elem->values[k].data, msg_elem->values[k].length);
     434          50 :                                 W_ERROR_HAVE_NO_MEMORY(nc_str);
     435             : 
     436          50 :                                 nc_list_elem = talloc_zero(mem_ctx, struct ncList);
     437          50 :                                 W_ERROR_HAVE_NO_MEMORY(nc_list_elem);
     438          50 :                                 nc_list_elem->dn = ldb_dn_new(mem_ctx, samdb, nc_str);
     439          50 :                                 W_ERROR_HAVE_NO_MEMORY(nc_list_elem);
     440          50 :                                 DLIST_ADD(nc_list, nc_list_elem);
     441             :                         }
     442             :                 }
     443             :         }
     444             : 
     445          10 :         *master_nc_list = nc_list;
     446          10 :         return WERR_OK;
     447             : }
     448             : 
     449             : /*
     450             :   Fill 'nc_list' with the ncs list. (MS-DRSR 4.1.13.3)
     451             :   if the object dn is specified, fill 'nc_list' only with this dn
     452             :   otherwise, fill 'nc_list' with all master ncs hosted by this server
     453             : */
     454          10 : static WERROR get_ncs_list(TALLOC_CTX *mem_ctx,
     455             :                 struct ldb_context *samdb,
     456             :                 struct kccsrv_service *service,
     457             :                 const char *object_dn_str,
     458             :                 struct ncList **nc_list)
     459             : {
     460           0 :         WERROR status;
     461           0 :         struct ncList *nc_list_elem;
     462           0 :         struct ldb_dn *nc_dn;
     463             : 
     464          10 :         if (object_dn_str != NULL) {
     465             :                 /* ncs := { object_dn } */
     466           0 :                 *nc_list = NULL;
     467           0 :                 nc_dn = ldb_dn_new(mem_ctx, samdb, object_dn_str);
     468           0 :                 nc_list_elem = talloc_zero(mem_ctx, struct ncList);
     469           0 :                 W_ERROR_HAVE_NO_MEMORY(nc_list_elem);
     470           0 :                 nc_list_elem->dn = nc_dn;
     471           0 :                 DLIST_ADD_END(*nc_list, nc_list_elem);
     472             :         } else {
     473             :                 /* ncs := getNCs() from ldb database.
     474             :                  * getNCs() must return an array containing
     475             :                  * the DSNames of all NCs hosted by this
     476             :                  * server.
     477             :                  */
     478          10 :                 char *ntds_guid_str = GUID_string(mem_ctx, &service->ntds_guid);
     479          10 :                 W_ERROR_HAVE_NO_MEMORY(ntds_guid_str);
     480          10 :                 status = get_master_ncs(mem_ctx, samdb, ntds_guid_str, nc_list);
     481          10 :                 W_ERROR_NOT_OK_RETURN(status);
     482             :         }
     483             : 
     484          10 :         return WERR_OK;
     485             : }
     486             : 
     487             : /*
     488             :   Copy the fields from 'reps1' to 'reps2', leaving zeroed the fields on
     489             :   'reps2' that aren't available on 'reps1'.
     490             : */
     491          40 : static WERROR copy_repsfrom_1_to_2(TALLOC_CTX *mem_ctx,
     492             :                                  struct repsFromTo2 **reps2,
     493             :                                  struct repsFromTo1 *reps1)
     494             : {
     495           0 :         struct repsFromTo2* reps;
     496             : 
     497          40 :         reps = talloc_zero(mem_ctx, struct repsFromTo2);
     498          40 :         W_ERROR_HAVE_NO_MEMORY(reps);
     499             : 
     500          40 :         reps->blobsize = reps1->blobsize;
     501          40 :         reps->consecutive_sync_failures = reps1->consecutive_sync_failures;
     502          40 :         reps->last_attempt = reps1->last_attempt;
     503          40 :         reps->last_success = reps1->last_success;
     504          40 :         reps->result_last_attempt = reps1->result_last_attempt;
     505          40 :         reps->other_info = talloc_zero(mem_ctx, struct repsFromTo2OtherInfo);
     506          40 :         W_ERROR_HAVE_NO_MEMORY(reps->other_info);
     507          40 :         reps->other_info->dns_name1 = reps1->other_info->dns_name;
     508          40 :         reps->replica_flags = reps1->replica_flags;
     509          40 :         memcpy(reps->schedule, reps1->schedule, sizeof(reps1->schedule));
     510          40 :         reps->reserved = reps1->reserved;
     511          40 :         reps->highwatermark = reps1->highwatermark;
     512          40 :         reps->source_dsa_obj_guid = reps1->source_dsa_obj_guid;
     513          40 :         reps->source_dsa_invocation_id = reps1->source_dsa_invocation_id;
     514          40 :         reps->transport_guid = reps1->transport_guid;
     515             : 
     516          40 :         *reps2 = reps;
     517          40 :         return WERR_OK;
     518             : }
     519             : 
     520          25 : static WERROR fill_neighbor_from_repsFrom(TALLOC_CTX *mem_ctx,
     521             :                                           struct ldb_context *samdb,
     522             :                                           struct ldb_dn *nc_dn,
     523             :                                           struct drsuapi_DsReplicaNeighbour *neigh,
     524             :                                           struct repsFromTo2 *reps_from)
     525             : {
     526           0 :         struct ldb_dn *source_dsa_dn;
     527           0 :         int ret;
     528          25 :         struct ldb_dn *transport_obj_dn = NULL;
     529             : 
     530          25 :         neigh->source_dsa_address = reps_from->other_info->dns_name1;
     531          25 :         neigh->replica_flags = reps_from->replica_flags;
     532          25 :         neigh->last_attempt = reps_from->last_attempt;
     533          25 :         neigh->source_dsa_obj_guid = reps_from->source_dsa_obj_guid;
     534             : 
     535          25 :         ret = dsdb_find_dn_by_guid(samdb, mem_ctx, &reps_from->source_dsa_obj_guid,
     536             :                                    DSDB_SEARCH_SHOW_RECYCLED,
     537             :                                    &source_dsa_dn);
     538             : 
     539          25 :         if (ret != LDB_SUCCESS) {
     540           0 :                 DEBUG(0,(__location__ ": Failed to find DN for neighbor GUID %s\n",
     541             :                          GUID_string(mem_ctx, &reps_from->source_dsa_obj_guid)));
     542           0 :                 return WERR_DS_DRA_INTERNAL_ERROR;
     543             :         }
     544             : 
     545          25 :         neigh->source_dsa_obj_dn = ldb_dn_get_linearized(source_dsa_dn);
     546          25 :         neigh->naming_context_dn = ldb_dn_get_linearized(nc_dn);
     547             : 
     548          25 :         if (dsdb_find_guid_by_dn(samdb, nc_dn,
     549             :                                  &neigh->naming_context_obj_guid)
     550             :                         != LDB_SUCCESS) {
     551           0 :                 return WERR_DS_DRA_INTERNAL_ERROR;
     552             :         }
     553             : 
     554          25 :         if (!GUID_all_zero(&reps_from->transport_guid)) {
     555           0 :                 ret = dsdb_find_dn_by_guid(samdb, mem_ctx, &reps_from->transport_guid,
     556             :                                            DSDB_SEARCH_SHOW_RECYCLED,
     557             :                                            &transport_obj_dn);
     558           0 :                 if (ret != LDB_SUCCESS) {
     559           0 :                         return WERR_DS_DRA_INTERNAL_ERROR;
     560             :                 }
     561             :         }
     562             : 
     563          25 :         neigh->transport_obj_dn = ldb_dn_get_linearized(transport_obj_dn);
     564          25 :         neigh->source_dsa_invocation_id = reps_from->source_dsa_invocation_id;
     565          25 :         neigh->transport_obj_guid = reps_from->transport_guid;
     566          25 :         neigh->highest_usn = reps_from->highwatermark.highest_usn;
     567          25 :         neigh->tmp_highest_usn = reps_from->highwatermark.tmp_highest_usn;
     568          25 :         neigh->last_success = reps_from->last_success;
     569          25 :         neigh->result_last_attempt = reps_from->result_last_attempt;
     570          25 :         neigh->consecutive_sync_failures = reps_from->consecutive_sync_failures;
     571          25 :         neigh->reserved = 0; /* Unused. MUST be 0. */
     572             : 
     573          25 :         return WERR_OK;
     574             : }
     575             : 
     576             : /*
     577             :   Get the inbound neighbours of this DC
     578             :   See details on MS-DRSR 4.1.13.3, for infoType DS_REPL_INFO_NEIGHBORS
     579             : */
     580           5 : static WERROR kccdrs_replica_get_info_neighbours(TALLOC_CTX *mem_ctx,
     581             :                                                  struct kccsrv_service *service,
     582             :                                                  struct ldb_context *samdb,
     583             :                                                  struct drsuapi_DsReplicaGetInfo *r,
     584             :                                                  union drsuapi_DsReplicaInfo *reply,
     585             :                                                  uint32_t base_index,
     586             :                                                  struct GUID req_src_dsa_guid,
     587             :                                                  const char *object_dn_str)
     588             : {
     589           0 :         WERROR status;
     590           0 :         uint32_t i, j;
     591           5 :         struct ldb_dn *nc_dn = NULL;
     592           5 :         struct ncList *p_nc_list = NULL;
     593           5 :         struct repsFromToBlob *reps_from_blob = NULL;
     594           5 :         struct repsFromTo2 *reps_from = NULL;
     595           0 :         uint32_t c_reps_from;
     596           0 :         uint32_t i_rep;
     597           5 :         struct ncList *nc_list = NULL;
     598             : 
     599           5 :         status = get_ncs_list(mem_ctx, samdb, service, object_dn_str, &nc_list);
     600           5 :         W_ERROR_NOT_OK_RETURN(status);
     601             : 
     602           5 :         i = j = 0;
     603             : 
     604           5 :         reply->neighbours = talloc_zero(mem_ctx, struct drsuapi_DsReplicaNeighbourCtr);
     605           5 :         W_ERROR_HAVE_NO_MEMORY(reply->neighbours);
     606           5 :         reply->neighbours->reserved = 0;
     607           5 :         reply->neighbours->count = 0;
     608             : 
     609             :         /* foreach nc in ncs */
     610          30 :         for (p_nc_list = nc_list; p_nc_list != NULL; p_nc_list = p_nc_list->next) {
     611             : 
     612          25 :                 nc_dn = p_nc_list->dn;
     613             : 
     614             :                 /* load the nc's repsFromTo blob */
     615          25 :                 status = dsdb_loadreps(samdb, mem_ctx, nc_dn, "repsFrom",
     616             :                                 &reps_from_blob, &c_reps_from);
     617          25 :                 W_ERROR_NOT_OK_RETURN(status);
     618             : 
     619             :                 /* foreach r in nc!repsFrom */
     620          50 :                 for (i_rep = 0; i_rep < c_reps_from; i_rep++) {
     621             : 
     622             :                         /* put all info on reps_from */
     623          25 :                         if (reps_from_blob[i_rep].version == 1) {
     624          25 :                                 status = copy_repsfrom_1_to_2(mem_ctx, &reps_from,
     625          25 :                                                               &reps_from_blob[i_rep].ctr.ctr1);
     626          25 :                                 W_ERROR_NOT_OK_RETURN(status);
     627             :                         } else { /* reps_from->version == 2 */
     628           0 :                                 reps_from = &reps_from_blob[i_rep].ctr.ctr2;
     629             :                         }
     630             : 
     631          25 :                         if (GUID_all_zero(&req_src_dsa_guid) ||
     632           0 :                             GUID_equal(&req_src_dsa_guid,
     633           0 :                                        &reps_from->source_dsa_obj_guid)) {
     634             : 
     635          25 :                                 if (i >= base_index) {
     636           0 :                                         struct drsuapi_DsReplicaNeighbour neigh;
     637          25 :                                         ZERO_STRUCT(neigh);
     638          25 :                                         status = fill_neighbor_from_repsFrom(mem_ctx, samdb,
     639             :                                                                              nc_dn, &neigh,
     640             :                                                                              reps_from);
     641          25 :                                         W_ERROR_NOT_OK_RETURN(status);
     642             : 
     643             :                                         /* append the neighbour to the neighbours array */
     644          25 :                                         reply->neighbours->array = talloc_realloc(mem_ctx,
     645             :                                                                                   reply->neighbours->array,
     646             :                                                                                   struct drsuapi_DsReplicaNeighbour,
     647             :                                                                                   reply->neighbours->count + 1);
     648          25 :                                         reply->neighbours->array[reply->neighbours->count] = neigh;
     649          25 :                                         reply->neighbours->count++;
     650          25 :                                         j++;
     651             :                                 }
     652             : 
     653          25 :                                 i++;
     654             :                         }
     655             :                 }
     656             :         }
     657             : 
     658           5 :         return WERR_OK;
     659             : }
     660             : 
     661          15 : static WERROR fill_neighbor_from_repsTo(TALLOC_CTX *mem_ctx,
     662             :                                         struct ldb_context *samdb, struct ldb_dn *nc_dn,
     663             :                                         struct drsuapi_DsReplicaNeighbour *neigh,
     664             :                                         struct repsFromTo2 *reps_to)
     665             : {
     666           0 :         int ret;
     667           0 :         struct ldb_dn *source_dsa_dn;
     668             : 
     669          15 :         neigh->source_dsa_address = reps_to->other_info->dns_name1;
     670          15 :         neigh->replica_flags = reps_to->replica_flags;
     671          15 :         neigh->last_attempt = reps_to->last_attempt;
     672          15 :         neigh->source_dsa_obj_guid = reps_to->source_dsa_obj_guid;
     673             : 
     674          15 :         ret = dsdb_find_dn_by_guid(samdb, mem_ctx,
     675          15 :                                    &reps_to->source_dsa_obj_guid,
     676             :                                    DSDB_SEARCH_SHOW_RECYCLED,
     677             :                                    &source_dsa_dn);
     678          15 :         if (ret != LDB_SUCCESS) {
     679           0 :                 DEBUG(0,(__location__ ": Failed to find DN for neighbor GUID %s\n",
     680             :                          GUID_string(mem_ctx, &reps_to->source_dsa_obj_guid)));
     681           0 :                 return WERR_DS_DRA_INTERNAL_ERROR;
     682             :         }
     683             : 
     684          15 :         neigh->source_dsa_obj_dn = ldb_dn_get_linearized(source_dsa_dn);
     685          15 :         neigh->naming_context_dn = ldb_dn_get_linearized(nc_dn);
     686             : 
     687          15 :         ret = dsdb_find_guid_by_dn(samdb, nc_dn,
     688             :                         &neigh->naming_context_obj_guid);
     689          15 :         if (ret != LDB_SUCCESS) {
     690           0 :                 DEBUG(0,(__location__ ": Failed to find GUID for DN %s\n",
     691             :                          ldb_dn_get_linearized(nc_dn)));
     692           0 :                 return WERR_DS_DRA_INTERNAL_ERROR;
     693             :         }
     694             : 
     695          15 :         neigh->last_success = reps_to->last_success;
     696          15 :         neigh->result_last_attempt = reps_to->result_last_attempt;
     697          15 :         neigh->consecutive_sync_failures = reps_to->consecutive_sync_failures;
     698          15 :         return WERR_OK;
     699             : }
     700             : 
     701             : /*
     702             :   Get the outbound neighbours of this DC
     703             :   See details on MS-DRSR 4.1.13.3, for infoType DS_REPL_INFO_REPSTO
     704             : */
     705           5 : static WERROR kccdrs_replica_get_info_repsto(TALLOC_CTX *mem_ctx,
     706             :                                              struct kccsrv_service *service,
     707             :                                              struct ldb_context *samdb,
     708             :                                              struct drsuapi_DsReplicaGetInfo *r,
     709             :                                              union drsuapi_DsReplicaInfo *reply,
     710             :                                              uint32_t base_index,
     711             :                                              struct GUID req_src_dsa_guid,
     712             :                                              const char *object_dn_str)
     713             : {
     714           0 :         WERROR status;
     715           0 :         uint32_t i, j;
     716           5 :         struct ncList *p_nc_list = NULL;
     717           5 :         struct ldb_dn *nc_dn = NULL;
     718           0 :         struct repsFromToBlob *reps_to_blob;
     719           0 :         struct repsFromTo2 *reps_to;
     720           0 :         uint32_t c_reps_to;
     721           0 :         uint32_t i_rep;
     722           5 :         struct ncList *nc_list = NULL;
     723             : 
     724           5 :         status = get_ncs_list(mem_ctx, samdb, service, object_dn_str, &nc_list);
     725           5 :         W_ERROR_NOT_OK_RETURN(status);
     726             : 
     727           5 :         i = j = 0;
     728             : 
     729           5 :         reply->repsto = talloc_zero(mem_ctx, struct drsuapi_DsReplicaNeighbourCtr);
     730           5 :         W_ERROR_HAVE_NO_MEMORY(reply->repsto);
     731           5 :         reply->repsto->reserved = 0;
     732           5 :         reply->repsto->count = 0;
     733             : 
     734             :         /* foreach nc in ncs */
     735          30 :         for (p_nc_list = nc_list; p_nc_list != NULL; p_nc_list = p_nc_list->next) {
     736             : 
     737          25 :                 nc_dn = p_nc_list->dn;
     738             : 
     739          25 :                 status = dsdb_loadreps(samdb, mem_ctx, nc_dn, "repsTo",
     740             :                                 &reps_to_blob, &c_reps_to);
     741          25 :                 W_ERROR_NOT_OK_RETURN(status);
     742             : 
     743             :                 /* foreach r in nc!repsTo */
     744          40 :                 for (i_rep = 0; i_rep < c_reps_to; i_rep++) {
     745           0 :                         struct drsuapi_DsReplicaNeighbour neigh;
     746          15 :                         ZERO_STRUCT(neigh);
     747             : 
     748             :                         /* put all info on reps_to */
     749          15 :                         if (reps_to_blob[i_rep].version == 1) {
     750          15 :                                 status = copy_repsfrom_1_to_2(mem_ctx,
     751             :                                                               &reps_to,
     752          15 :                                                               &reps_to_blob[i_rep].ctr.ctr1);
     753          15 :                                 W_ERROR_NOT_OK_RETURN(status);
     754             :                         } else { /* reps_to->version == 2 */
     755           0 :                                 reps_to = &reps_to_blob[i_rep].ctr.ctr2;
     756             :                         }
     757             : 
     758          15 :                         if (i >= base_index) {
     759          15 :                                 status = fill_neighbor_from_repsTo(mem_ctx,
     760             :                                                                    samdb, nc_dn,
     761             :                                                                    &neigh, reps_to);
     762          15 :                                 W_ERROR_NOT_OK_RETURN(status);
     763             : 
     764             :                                 /* append the neighbour to the neighbours array */
     765          15 :                                 reply->repsto->array = talloc_realloc(mem_ctx,
     766             :                                                                             reply->repsto->array,
     767             :                                                                             struct drsuapi_DsReplicaNeighbour,
     768             :                                                                             reply->repsto->count + 1);
     769          15 :                                 reply->repsto->array[reply->repsto->count++] = neigh;
     770          15 :                                 j++;
     771             :                         }
     772          15 :                         i++;
     773             :                 }
     774             :         }
     775             : 
     776           5 :         return WERR_OK;
     777             : }
     778             : 
     779          10 : NTSTATUS kccdrs_replica_get_info(struct irpc_message *msg,
     780             :                                  struct drsuapi_DsReplicaGetInfo *req)
     781             : {
     782           0 :         WERROR status;
     783           0 :         struct drsuapi_DsReplicaGetInfoRequest1 *req1;
     784           0 :         struct drsuapi_DsReplicaGetInfoRequest2 *req2;
     785           0 :         uint32_t base_index;
     786           0 :         union drsuapi_DsReplicaInfo *reply;
     787           0 :         struct GUID req_src_dsa_guid;
     788          10 :         const char *object_dn_str = NULL;
     789           0 :         struct kccsrv_service *service;
     790           0 :         struct ldb_context *samdb;
     791           0 :         TALLOC_CTX *mem_ctx;
     792           0 :         enum drsuapi_DsReplicaInfoType info_type;
     793             : 
     794          10 :         service = talloc_get_type(msg->private_data, struct kccsrv_service);
     795          10 :         samdb = service->samdb;
     796          10 :         mem_ctx = talloc_new(msg);
     797          10 :         NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
     798             : 
     799             : #if 0
     800             :         NDR_PRINT_IN_DEBUG(drsuapi_DsReplicaGetInfo, req);
     801             : #endif
     802             : 
     803             :         /* check request version */
     804          10 :         if (req->in.level != DRSUAPI_DS_REPLICA_GET_INFO &&
     805           0 :             req->in.level != DRSUAPI_DS_REPLICA_GET_INFO2)
     806             :         {
     807           0 :                 DEBUG(1,(__location__ ": Unsupported DsReplicaGetInfo level %u\n",
     808             :                          req->in.level));
     809           0 :                 status = WERR_REVISION_MISMATCH;
     810           0 :                 goto done;
     811             :         }
     812             : 
     813          10 :         if (req->in.level == DRSUAPI_DS_REPLICA_GET_INFO) {
     814          10 :                 req1 = &req->in.req->req1;
     815          10 :                 base_index = 0;
     816          10 :                 info_type = req1->info_type;
     817          10 :                 object_dn_str = req1->object_dn;
     818          10 :                 req_src_dsa_guid = req1->source_dsa_guid;
     819             :         } else { /* r->in.level == DRSUAPI_DS_REPLICA_GET_INFO2 */
     820           0 :                 req2 = &req->in.req->req2;
     821           0 :                 if (req2->enumeration_context == 0xffffffff) {
     822             :                         /* no more data is available */
     823           0 :                         status = WERR_NO_MORE_ITEMS; /* on MS-DRSR it is ERROR_NO_MORE_ITEMS */
     824           0 :                         goto done;
     825             :                 }
     826             : 
     827           0 :                 base_index = req2->enumeration_context;
     828           0 :                 info_type = req2->info_type;
     829           0 :                 object_dn_str = req2->object_dn;
     830           0 :                 req_src_dsa_guid = req2->source_dsa_guid;
     831             :         }
     832             : 
     833          10 :         reply = req->out.info;
     834          10 :         *req->out.info_type = info_type;
     835             : 
     836             :         /* Based on the infoType requested, retrieve the corresponding
     837             :          * information and construct the response message */
     838          10 :         switch (info_type) {
     839             : 
     840           5 :         case DRSUAPI_DS_REPLICA_INFO_NEIGHBORS:
     841           5 :                 status = kccdrs_replica_get_info_neighbours(mem_ctx, service, samdb, req,
     842             :                                                             reply, base_index, req_src_dsa_guid,
     843             :                                                             object_dn_str);
     844           5 :                 break;
     845           5 :         case DRSUAPI_DS_REPLICA_INFO_REPSTO:
     846           5 :                 status = kccdrs_replica_get_info_repsto(mem_ctx, service, samdb, req,
     847             :                                                         reply, base_index, req_src_dsa_guid,
     848             :                                                         object_dn_str);
     849           5 :                 break;
     850           0 :         case DRSUAPI_DS_REPLICA_INFO_CURSORS: /* On MS-DRSR it is DS_REPL_INFO_CURSORS_FOR_NC */
     851           0 :                 status = kccdrs_replica_get_info_cursors(mem_ctx, samdb, req, reply,
     852             :                                                          ldb_dn_new(mem_ctx, samdb, object_dn_str));
     853           0 :                 break;
     854           0 :         case DRSUAPI_DS_REPLICA_INFO_CURSORS2: /* On MS-DRSR it is DS_REPL_INFO_CURSORS_2_FOR_NC */
     855           0 :                 status = kccdrs_replica_get_info_cursors2(mem_ctx, samdb, req, reply,
     856             :                                                           ldb_dn_new(mem_ctx, samdb, object_dn_str));
     857           0 :                 break;
     858           0 :         case DRSUAPI_DS_REPLICA_INFO_PENDING_OPS:
     859           0 :                 status = kccdrs_replica_get_info_pending_ops(mem_ctx, samdb, req, reply,
     860             :                                                              ldb_dn_new(mem_ctx, samdb, object_dn_str));
     861           0 :                 break;
     862           0 :         case DRSUAPI_DS_REPLICA_INFO_CURSORS3: /* On MS-DRSR it is DS_REPL_INFO_CURSORS_3_FOR_NC */
     863           0 :                 status = WERR_NOT_SUPPORTED;
     864           0 :                 break;
     865           0 :         case DRSUAPI_DS_REPLICA_INFO_UPTODATE_VECTOR_V1: /* On MS-DRSR it is DS_REPL_INFO_UPTODATE_VECTOR_V1 */
     866           0 :                 status = WERR_NOT_SUPPORTED;
     867           0 :                 break;
     868           0 :         case DRSUAPI_DS_REPLICA_INFO_OBJ_METADATA: /* On MS-DRSR it is DS_REPL_INFO_METADATA_FOR_OBJ */
     869             :                 /*
     870             :                  * It should be too complicated to filter the metadata2 to remove the additional data
     871             :                  * as metadata2 is a superset of metadata
     872             :                  */
     873           0 :                 status = WERR_NOT_SUPPORTED;
     874           0 :                 break;
     875           0 :         case DRSUAPI_DS_REPLICA_INFO_OBJ_METADATA2: /* On MS-DRSR it is DS_REPL_INFO_METADATA_FOR_OBJ */
     876           0 :                 status = kccdrs_replica_get_info_obj_metadata2(mem_ctx, samdb, req, reply,
     877             :                                                                ldb_dn_new(mem_ctx, samdb, object_dn_str), base_index);
     878           0 :                 break;
     879           0 :         case DRSUAPI_DS_REPLICA_INFO_ATTRIBUTE_VALUE_METADATA: /* On MS-DRSR it is DS_REPL_INFO_METADATA_FOR_ATTR_VALUE */
     880           0 :                 status = WERR_NOT_SUPPORTED;
     881           0 :                 break;
     882           0 :         case DRSUAPI_DS_REPLICA_INFO_ATTRIBUTE_VALUE_METADATA2: /* On MS-DRSR it is DS_REPL_INFO_METADATA_2_FOR_ATTR_VALUE */
     883           0 :                 status = WERR_NOT_SUPPORTED;
     884           0 :                 break;
     885           0 :         case DRSUAPI_DS_REPLICA_INFO_KCC_DSA_CONNECT_FAILURES: /* On MS-DRSR it is DS_REPL_INFO_KCC_DSA_CONNECT_FAILURES */
     886           0 :                 status = WERR_NOT_SUPPORTED;
     887           0 :                 break;
     888           0 :         case DRSUAPI_DS_REPLICA_INFO_KCC_DSA_LINK_FAILURES: /* On MS-DRSR it is DS_REPL_INFO_KCC_LINK_FAILURES */
     889           0 :                 status = WERR_NOT_SUPPORTED;
     890           0 :                 break;
     891           0 :         case DRSUAPI_DS_REPLICA_INFO_CLIENT_CONTEXTS: /* On MS-DRSR it is DS_REPL_INFO_CLIENT_CONTEXTS */
     892           0 :                 status = WERR_NOT_SUPPORTED;
     893           0 :                 break;
     894           0 :         case DRSUAPI_DS_REPLICA_INFO_SERVER_OUTGOING_CALLS: /* On MS-DRSR it is DS_REPL_INFO_SERVER_OUTGOING_CALLS */
     895           0 :                 status = WERR_NOT_SUPPORTED;
     896           0 :                 break;
     897           0 :         default:
     898           0 :                 DEBUG(1,(__location__ ": Unsupported DsReplicaGetInfo info_type %u\n",
     899             :                          info_type));
     900           0 :                 status = WERR_INVALID_LEVEL;
     901           0 :                 break;
     902             :         }
     903             : 
     904          10 : done:
     905             :         /* put the status on the result field of the reply */
     906          10 :         req->out.result = status;
     907             : #if 0
     908             :         NDR_PRINT_OUT_DEBUG(drsuapi_DsReplicaGetInfo, req);
     909             : #endif
     910          10 :         return NT_STATUS_OK;
     911             : }

Generated by: LCOV version 1.14