~lefteris-nikoltsios/+junk/samba-lp1016895

« back to all changes in this revision

Viewing changes to source4/dsdb/kcc/kcc_drs_replica_info.c

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2011-12-21 13:18:04 UTC
  • mfrom: (0.39.21 sid)
  • Revision ID: package-import@ubuntu.com-20111221131804-xtlr39wx6njehxxr
Tags: 2:3.6.1-3ubuntu1
* Merge from Debian testing.  Remaining changes:
  + debian/patches/VERSION.patch:
    - set SAMBA_VERSION_SUFFIX to Ubuntu.
  + debian/patches/error-trans.fix-276472:
    - Add the translation of Unix Error code -ENOTSUP to NT Error Code
    - NT_STATUS_NOT_SUPPORTED to prevent the Permission denied error.
  + debian/smb.conf:
    - add "(Samba, Ubuntu)" to server string.
    - comment out the default [homes] share, and add a comment about
      "valid users = %S" to show users how to restrict access to
      \\server\username to only username.
    - Set 'usershare allow guests', so that usershare admins are 
      allowed to create public shares in addition to authenticated
      ones.
    - add map to guest = Bad user, maps bad username to guest access.
  + debian/samba-common.config:
    - Do not change priority to high if dhclient3 is installed.
    - Use priority medium instead of high for the workgroup question.
  + debian/control:
    - Don't build against or suggest ctdb.
    - Add dependency on samba-common-bin to samba.
  + Add ufw integration:
    - Created debian/samba.ufw.profile
    - debian/rules, debian/samba.dirs, debian/samba.files: install
      profile
    - debian/control: have samba suggest ufw
  + Add apport hook:
    - Created debian/source_samba.py.
    - debian/rules, debian/samba.dirs, debian/samba-common-bin.files: install
  + Switch to upstart:
    - Add debian/samba.{nmbd,smbd}.upstart.
  + debian/samba.logrotate, debian/samba-common.dhcp, debian/samba.if-up:
    - Make them upstart compatible
  + debian/samba.postinst: 
    - Avoid scary pdbedit warnings on first import.
  + debian/samba-common.postinst: Add more informative error message for
    the case where smb.conf was manually deleted
  + debian/patches/fix-debuglevel-name-conflict.patch: don't use 'debug_level'
    as a global variable name in an NSS module 
  + Dropped:
    - debian/patches/error-trans.fix-276472
    - debian/patches/fix-debuglevel-name-conflict.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 "smbd/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
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
        struct ldb_result *res;
 
48
        int ret;
 
49
        const char *attrs[2];
 
50
        struct ldb_dn *attr_ext_dn;
 
51
        NTSTATUS ntstatus;
 
52
 
 
53
        attrs[0] = linked_attr_name;
 
54
        attrs[1] = NULL;
 
55
 
 
56
        ret = dsdb_search_dn(samdb, mem_ctx, &res, dn, attrs,
 
57
                             DSDB_SEARCH_SHOW_EXTENDED_DN | DSDB_SEARCH_REVEAL_INTERNALS);
 
58
        if (ret != LDB_SUCCESS) {
 
59
                DEBUG(0, (__location__ ": Failed search for attribute %s on %s",
 
60
                                linked_attr_name, ldb_dn_get_linearized(dn)));
 
61
                return WERR_INTERNAL_ERROR;
 
62
        }
 
63
 
 
64
        attr_ext_dn = ldb_msg_find_attr_as_dn(samdb, mem_ctx, res->msgs[0], linked_attr_name);
 
65
        if (!attr_ext_dn) {
 
66
                DEBUG(0, (__location__ ": Failed search for attribute %s on %s",
 
67
                                linked_attr_name, ldb_dn_get_linearized(dn)));
 
68
                return WERR_INTERNAL_ERROR;
 
69
        }
 
70
 
 
71
        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
        ntstatus = dsdb_get_extended_dn_uint32(attr_ext_dn, attr_version, "RMD_VERSION");
 
75
        if (!NT_STATUS_IS_OK(ntstatus)) {
 
76
                DEBUG(0, (__location__ ": Could not extract component %s from dn \"%s\"",
 
77
                                "RMD_VERSION", ldb_dn_get_extended_linearized(mem_ctx, attr_ext_dn, 1)));
 
78
                return WERR_INTERNAL_ERROR;
 
79
        }
 
80
 
 
81
        ntstatus = dsdb_get_extended_dn_nttime(attr_ext_dn, attr_change_time, "RMD_CHANGETIME");
 
82
        if (!NT_STATUS_IS_OK(ntstatus)) {
 
83
                DEBUG(0, (__location__ ": Could not extract component %s from dn \"%s\"",
 
84
                                "RMD_CHANGETIME", ldb_dn_get_extended_linearized(mem_ctx, attr_ext_dn, 1)));
 
85
                return WERR_INTERNAL_ERROR;
 
86
        }
 
87
 
 
88
        ntstatus = dsdb_get_extended_dn_uint32(attr_ext_dn, attr_version, "RMD_ORIGINATING_USN");
 
89
        if (!NT_STATUS_IS_OK(ntstatus)) {
 
90
                DEBUG(0, (__location__ ": Could not extract component %s from dn \"%s\"",
 
91
                                "RMD_ORIGINATING_USN", ldb_dn_get_extended_linearized(mem_ctx, attr_ext_dn, 1)));
 
92
                return WERR_INTERNAL_ERROR;
 
93
        }
 
94
 
 
95
        return WERR_OK;
 
96
}
 
97
 
 
98
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
        int ret;
 
104
        struct ldb_result *res;
 
105
        const char *attrs[] = { "replPropertyMetaData", NULL };
 
106
        const struct ldb_val *omd_value;
 
107
        enum ndr_err_code ndr_err;
 
108
 
 
109
        ret = ldb_search(samdb, mem_ctx, &res, dn, LDB_SCOPE_BASE, attrs, NULL);
 
110
        if (ret != LDB_SUCCESS || res->count != 1) {
 
111
                DEBUG(0, (__location__ ": Failed search for replPropertyMetaData attribute on %s",
 
112
                          ldb_dn_get_linearized(dn)));
 
113
                return WERR_INTERNAL_ERROR;
 
114
        }
 
115
 
 
116
        omd_value = ldb_msg_find_ldb_val(res->msgs[0], "replPropertyMetaData");
 
117
        if (!omd_value) {
 
118
                DEBUG(0,(__location__ ": Object %s does not have a replPropertyMetaData attribute\n",
 
119
                         ldb_dn_get_linearized(dn)));
 
120
                talloc_free(res);
 
121
                return WERR_INTERNAL_ERROR;
 
122
        }
 
123
 
 
124
        ndr_err = ndr_pull_struct_blob(omd_value, mem_ctx,
 
125
                                        obj_metadata_ctr,
 
126
                                       (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob);
 
127
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 
128
                DEBUG(0,(__location__ ": Failed to parse replPropertyMetaData for %s\n",
 
129
                         ldb_dn_get_linearized(dn)));
 
130
                talloc_free(res);
 
131
                return WERR_INTERNAL_ERROR;
 
132
        }
 
133
 
 
134
        talloc_free(res);
 
135
        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
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
        char *invocation_id_str;
 
149
        const char *attrs_invocation[] = { NULL };
 
150
        struct ldb_message *msg;
 
151
        int ret;
 
152
 
 
153
        invocation_id_str = GUID_string(mem_ctx, invocation_id);
 
154
        W_ERROR_HAVE_NO_MEMORY(invocation_id_str);
 
155
 
 
156
        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
        if (ret != LDB_SUCCESS) {
 
159
                DEBUG(0, (__location__ ": Failed search for the object DN under %s whose invocationId is %s",
 
160
                          invocation_id_str, ldb_dn_get_linearized(ldb_get_config_basedn(samdb))));
 
161
                talloc_free(invocation_id_str);
 
162
                return WERR_INTERNAL_ERROR;
 
163
        }
 
164
 
 
165
        *dn_str = ldb_dn_alloc_linearized(mem_ctx, msg->dn);
 
166
        talloc_free(invocation_id_str);
 
167
        return WERR_OK;
 
168
}
 
169
 
 
170
/*
 
171
  get metadata version 2 info for a specified object DN
 
172
*/
 
173
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
        WERROR status;
 
181
        struct replPropertyMetaDataBlob omd_ctr;
 
182
        struct replPropertyMetaData1 *attr;
 
183
        struct drsuapi_DsReplicaObjMetaData2Ctr *metadata2;
 
184
        const struct dsdb_schema *schema;
 
185
 
 
186
        uint32_t i, j;
 
187
 
 
188
        DEBUG(0, ("kccdrs_replica_get_info_obj_metadata2() called\n"));
 
189
 
 
190
        if (!dn) {
 
191
                return WERR_INVALID_PARAMETER;
 
192
        }
 
193
 
 
194
        if (!ldb_dn_validate(dn)) {
 
195
                return WERR_DS_DRA_BAD_DN;
 
196
        }
 
197
 
 
198
        status = get_repl_prop_metadata_ctr(mem_ctx, samdb, dn, &omd_ctr);
 
199
        W_ERROR_NOT_OK_RETURN(status);
 
200
 
 
201
        schema = dsdb_get_schema(samdb, reply);
 
202
        if (!schema) {
 
203
                DEBUG(0,(__location__": Failed to get the schema\n"));
 
204
                return WERR_INTERNAL_ERROR;
 
205
        }
 
206
 
 
207
        reply->objmetadata2 = talloc_zero(mem_ctx, struct drsuapi_DsReplicaObjMetaData2Ctr);
 
208
        W_ERROR_HAVE_NO_MEMORY(reply->objmetadata2);
 
209
        metadata2 = reply->objmetadata2;
 
210
        metadata2->enumeration_context = 0;
 
211
 
 
212
        /* For each replicated attribute of the object */
 
213
        for (i = 0, j = 0; i < omd_ctr.ctr.ctr1.count; i++) {
 
214
                const struct dsdb_attribute *schema_attr;
 
215
                uint32_t attr_version;
 
216
                NTTIME attr_change_time;
 
217
                uint32_t attr_originating_usn;
 
218
 
 
219
                /*
 
220
                  attr := attrsSeq[i]
 
221
                  s := AttrStamp(object, attr)
 
222
                */
 
223
                /* get a reference to the attribute on 'omd_ctr' */
 
224
                attr = &omd_ctr.ctr.ctr1.array[j];
 
225
 
 
226
                schema_attr = dsdb_attribute_by_attributeID_id(schema, attr->attid);
 
227
 
 
228
                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
                if (schema_attr &&
 
235
                    schema_attr->linkID != 0 && /* Checks if attribute is a linked attribute */
 
236
                    (schema_attr->linkID % 2) == 0 && /* is it a forward link? only forward links have the LinkValueStamp */
 
237
                    r->in.level == 2 &&
 
238
                    (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
                        status = get_linked_attribute_value_stamp(mem_ctx, samdb, dn, schema_attr->lDAPDisplayName,
 
245
                                                                  &attr_version, &attr_change_time, &attr_originating_usn);
 
246
                        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
                        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
                                attr->version = attr_version;
 
264
                                attr->originating_change_time = attr_change_time;
 
265
                                attr->originating_invocation_id = GUID_zero();
 
266
                                attr->originating_usn = attr_originating_usn;
 
267
                        }
 
268
                }
 
269
 
 
270
                if (i < base_index) {
 
271
                        continue;
 
272
                }
 
273
 
 
274
                metadata2->array = talloc_realloc(mem_ctx, metadata2->array,
 
275
                                                  struct drsuapi_DsReplicaObjMetaData2, j + 1);
 
276
                W_ERROR_HAVE_NO_MEMORY(metadata2->array);
 
277
                metadata2->array[j].attribute_name = schema_attr->lDAPDisplayName;
 
278
                metadata2->array[j].local_usn = attr->local_usn;
 
279
                metadata2->array[j].originating_change_time = attr->originating_change_time;
 
280
                metadata2->array[j].originating_invocation_id = attr->originating_invocation_id;
 
281
                metadata2->array[j].originating_usn = attr->originating_usn;
 
282
                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
                status = get_dn_from_invocation_id(mem_ctx, samdb,
 
290
                                                   &attr->originating_invocation_id,
 
291
                                                   &metadata2->array[j].originating_dsa_dn);
 
292
                W_ERROR_NOT_OK_RETURN(status);
 
293
                j++;
 
294
                metadata2->count = j;
 
295
 
 
296
        }
 
297
 
 
298
        return WERR_OK;
 
299
}
 
300
 
 
301
/*
 
302
  get cursors info for a specified DN
 
303
*/
 
304
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
        int ret;
 
311
 
 
312
        if (!ldb_dn_validate(dn)) {
 
313
                return WERR_INVALID_PARAMETER;
 
314
        }
 
315
        reply->cursors = talloc(mem_ctx, struct drsuapi_DsReplicaCursorCtr);
 
316
        W_ERROR_HAVE_NO_MEMORY(reply->cursors);
 
317
 
 
318
        reply->cursors->reserved = 0;
 
319
 
 
320
        ret = dsdb_load_udv_v1(samdb, dn, reply->cursors, &reply->cursors->array, &reply->cursors->count);
 
321
        if (ret != LDB_SUCCESS) {
 
322
                return WERR_DS_DRA_BAD_NC;
 
323
        }
 
324
        return WERR_OK;
 
325
}
 
326
 
 
327
/*
 
328
  get cursors2 info for a specified DN
 
329
*/
 
330
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
        int ret;
 
337
 
 
338
        if (!ldb_dn_validate(dn)) {
 
339
                return WERR_INVALID_PARAMETER;
 
340
        }
 
341
        reply->cursors2 = talloc(mem_ctx, struct drsuapi_DsReplicaCursor2Ctr);
 
342
        W_ERROR_HAVE_NO_MEMORY(reply->cursors2);
 
343
 
 
344
        ret = dsdb_load_udv_v2(samdb, dn, reply->cursors2, &reply->cursors2->array, &reply->cursors2->count);
 
345
        if (ret != LDB_SUCCESS) {
 
346
                return WERR_DS_DRA_BAD_NC;
 
347
        }
 
348
 
 
349
        reply->cursors2->enumeration_context = reply->cursors2->count;
 
350
        return WERR_OK;
 
351
}
 
352
 
 
353
/*
 
354
  get pending ops info for a specified DN
 
355
*/
 
356
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
        struct timeval now = timeval_current();
 
363
 
 
364
        if (!ldb_dn_validate(dn)) {
 
365
                return WERR_INVALID_PARAMETER;
 
366
        }
 
367
        reply->pendingops = talloc(mem_ctx, struct drsuapi_DsReplicaOpCtr);
 
368
        W_ERROR_HAVE_NO_MEMORY(reply->pendingops);
 
369
 
 
370
        /* claim no pending ops for now */
 
371
        reply->pendingops->time = timeval_to_nttime(&now);
 
372
        reply->pendingops->count = 0;
 
373
        reply->pendingops->array = NULL;
 
374
 
 
375
        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
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
        const char *attrs[] = { "hasMasterNCs", NULL };
 
390
        struct ldb_result *res;
 
391
        struct ncList *nc_list = NULL;
 
392
        struct ncList *nc_list_elem;
 
393
        int ret;
 
394
        unsigned int i;
 
395
        char *nc_str;
 
396
 
 
397
        ret = ldb_search(samdb, mem_ctx, &res, ldb_get_config_basedn(samdb),
 
398
                        LDB_SCOPE_DEFAULT, attrs, "(objectguid=%s)", ntds_guid_str);
 
399
 
 
400
        if (ret != LDB_SUCCESS) {
 
401
                DEBUG(0,(__location__ ": Failed objectguid search - %s\n", ldb_errstring(samdb)));
 
402
                return WERR_INTERNAL_ERROR;
 
403
        }
 
404
 
 
405
        if (res->count == 0) {
 
406
                DEBUG(0,(__location__ ": Failed: objectguid=%s not found\n", ntds_guid_str));
 
407
                return WERR_INTERNAL_ERROR;
 
408
        }
 
409
 
 
410
        for (i = 0; i < res->count; i++) {
 
411
                struct ldb_message_element *msg_elem = ldb_msg_find_element(res->msgs[i], "hasMasterNCs");
 
412
                unsigned int k;
 
413
 
 
414
                if (!msg_elem || msg_elem->num_values == 0) {
 
415
                        DEBUG(0,(__location__ ": Failed: Attribute hasMasterNCs not found - %s\n",
 
416
                              ldb_errstring(samdb)));
 
417
                        return WERR_INTERNAL_ERROR;
 
418
                }
 
419
 
 
420
                for (k = 0; k < msg_elem->num_values; k++) {
 
421
                        /* copy the string on msg_elem->values[k]->data to nc_str */
 
422
                        nc_str = talloc_strndup(mem_ctx, (char *)msg_elem->values[k].data, msg_elem->values[k].length);
 
423
                        W_ERROR_HAVE_NO_MEMORY(nc_str);
 
424
 
 
425
                        nc_list_elem = talloc_zero(mem_ctx, struct ncList);
 
426
                        W_ERROR_HAVE_NO_MEMORY(nc_list_elem);
 
427
                        nc_list_elem->dn = ldb_dn_new(mem_ctx, samdb, nc_str);
 
428
                        W_ERROR_HAVE_NO_MEMORY(nc_list_elem);
 
429
                        DLIST_ADD(nc_list, nc_list_elem);
 
430
                }
 
431
 
 
432
        }
 
433
 
 
434
        *master_nc_list = nc_list;
 
435
        return WERR_OK;
 
436
}
 
437
 
 
438
/*
 
439
  Fill 'nc_list' with the ncs list. (MS-DRSR 4.1.13.3)
 
440
  if the object dn is specified, fill 'nc_list' only with this dn
 
441
  otherwise, fill 'nc_list' with all master ncs hosted by this server
 
442
*/
 
443
static WERROR get_ncs_list(TALLOC_CTX *mem_ctx,
 
444
                struct ldb_context *samdb,
 
445
                struct kccsrv_service *service,
 
446
                const char *object_dn_str,
 
447
                struct ncList **nc_list)
 
448
{
 
449
        WERROR status;
 
450
        struct ncList *nc_list_elem;
 
451
        struct ldb_dn *nc_dn;
 
452
 
 
453
        if (object_dn_str != NULL) {
 
454
                /* ncs := { object_dn } */
 
455
                *nc_list = NULL;
 
456
                nc_dn = ldb_dn_new(mem_ctx, samdb, object_dn_str);
 
457
                nc_list_elem = talloc_zero(mem_ctx, struct ncList);
 
458
                W_ERROR_HAVE_NO_MEMORY(nc_list_elem);
 
459
                nc_list_elem->dn = nc_dn;
 
460
                DLIST_ADD_END(*nc_list, nc_list_elem, struct ncList*);
 
461
        } else {
 
462
                /* ncs := getNCs() from ldb database.
 
463
                 * getNCs() must return an array containing
 
464
                 * the DSNames of all NCs hosted by this
 
465
                 * server.
 
466
                 */
 
467
                char *ntds_guid_str = GUID_string(mem_ctx, &service->ntds_guid);
 
468
                W_ERROR_HAVE_NO_MEMORY(ntds_guid_str);
 
469
                status = get_master_ncs(mem_ctx, samdb, ntds_guid_str, nc_list);
 
470
                W_ERROR_NOT_OK_RETURN(status);
 
471
        }
 
472
 
 
473
        return WERR_OK;
 
474
}
 
475
 
 
476
/*
 
477
  Copy the fields from 'reps1' to 'reps2', leaving zeroed the fields on
 
478
  'reps2' that aren't available on 'reps1'.
 
479
*/
 
480
static WERROR copy_repsfrom_1_to_2(TALLOC_CTX *mem_ctx,
 
481
                                 struct repsFromTo2 **reps2,
 
482
                                 struct repsFromTo1 *reps1)
 
483
{
 
484
        struct repsFromTo2* reps;
 
485
 
 
486
        reps = talloc_zero(mem_ctx, struct repsFromTo2);
 
487
        W_ERROR_HAVE_NO_MEMORY(reps);
 
488
 
 
489
        reps->blobsize = reps1->blobsize;
 
490
        reps->consecutive_sync_failures = reps1->consecutive_sync_failures;
 
491
        reps->last_attempt = reps1->last_attempt;
 
492
        reps->last_success = reps1->last_success;
 
493
        reps->result_last_attempt = reps1->result_last_attempt;
 
494
        reps->other_info = talloc_zero(mem_ctx, struct repsFromTo2OtherInfo);
 
495
        W_ERROR_HAVE_NO_MEMORY(reps->other_info);
 
496
        reps->other_info->dns_name1 = reps1->other_info->dns_name;
 
497
        reps->replica_flags = reps1->replica_flags;
 
498
        memcpy(reps->schedule, reps1->schedule, sizeof(reps1->schedule));
 
499
        reps->reserved = reps1->reserved;
 
500
        reps->highwatermark = reps1->highwatermark;
 
501
        reps->source_dsa_obj_guid = reps1->source_dsa_obj_guid;
 
502
        reps->source_dsa_invocation_id = reps1->source_dsa_invocation_id;
 
503
        reps->transport_guid = reps1->transport_guid;
 
504
 
 
505
        *reps2 = reps;
 
506
        return WERR_OK;
 
507
}
 
508
 
 
509
static WERROR fill_neighbor_from_repsFrom(TALLOC_CTX *mem_ctx,
 
510
                                          struct ldb_context *samdb,
 
511
                                          struct ldb_dn *nc_dn,
 
512
                                          struct drsuapi_DsReplicaNeighbour *neigh,
 
513
                                          struct repsFromTo2 *reps_from)
 
514
{
 
515
        struct ldb_dn *source_dsa_dn;
 
516
        int ret;
 
517
        struct ldb_dn *transport_obj_dn = NULL;
 
518
 
 
519
        neigh->source_dsa_address = reps_from->other_info->dns_name1;
 
520
        neigh->replica_flags = reps_from->replica_flags;
 
521
        neigh->last_attempt = reps_from->last_attempt;
 
522
        neigh->source_dsa_obj_guid = reps_from->source_dsa_obj_guid;
 
523
 
 
524
        ret = dsdb_find_dn_by_guid(samdb, mem_ctx, &reps_from->source_dsa_obj_guid,
 
525
                                   &source_dsa_dn);
 
526
 
 
527
        if (ret != LDB_SUCCESS) {
 
528
                DEBUG(0,(__location__ ": Failed to find DN for neighbor GUID %s\n",
 
529
                         GUID_string(mem_ctx, &reps_from->source_dsa_obj_guid)));
 
530
                return WERR_DS_DRA_INTERNAL_ERROR;
 
531
        }
 
532
 
 
533
        neigh->source_dsa_obj_dn = ldb_dn_get_linearized(source_dsa_dn);
 
534
        neigh->naming_context_dn = ldb_dn_get_linearized(nc_dn);
 
535
 
 
536
        if (dsdb_find_guid_by_dn(samdb, nc_dn, &neigh->naming_context_obj_guid)
 
537
                        != LDB_SUCCESS) {
 
538
                return WERR_DS_DRA_INTERNAL_ERROR;
 
539
        }
 
540
 
 
541
        if (!GUID_all_zero(&reps_from->transport_guid)) {
 
542
                ret = dsdb_find_dn_by_guid(samdb, mem_ctx, &reps_from->transport_guid,
 
543
                                           &transport_obj_dn);
 
544
                if (ret != LDB_SUCCESS) {
 
545
                        return WERR_DS_DRA_INTERNAL_ERROR;
 
546
                }
 
547
        }
 
548
 
 
549
        neigh->transport_obj_dn = ldb_dn_get_linearized(transport_obj_dn);
 
550
        neigh->source_dsa_invocation_id = reps_from->source_dsa_invocation_id;
 
551
        neigh->transport_obj_guid = reps_from->transport_guid;
 
552
        neigh->highest_usn = reps_from->highwatermark.highest_usn;
 
553
        neigh->tmp_highest_usn = reps_from->highwatermark.tmp_highest_usn;
 
554
        neigh->last_success = reps_from->last_success;
 
555
        neigh->result_last_attempt = reps_from->result_last_attempt;
 
556
        neigh->consecutive_sync_failures = reps_from->consecutive_sync_failures;
 
557
        neigh->reserved = 0; /* Unused. MUST be 0. */
 
558
 
 
559
        return WERR_OK;
 
560
}
 
561
 
 
562
/*
 
563
  Get the inbound neighbours of this DC
 
564
  See details on MS-DRSR 4.1.13.3, for infoType DS_REPL_INFO_NEIGHBORS
 
565
*/
 
566
static WERROR kccdrs_replica_get_info_neighbours(TALLOC_CTX *mem_ctx,
 
567
                                                 struct kccsrv_service *service,
 
568
                                                 struct ldb_context *samdb,
 
569
                                                 struct drsuapi_DsReplicaGetInfo *r,
 
570
                                                 union drsuapi_DsReplicaInfo *reply,
 
571
                                                 uint32_t base_index,
 
572
                                                 struct GUID req_src_dsa_guid,
 
573
                                                 const char *object_dn_str)
 
574
{
 
575
        WERROR status;
 
576
        uint32_t i, j;
 
577
        struct ldb_dn *nc_dn = NULL;
 
578
        struct ncList *p_nc_list = NULL;
 
579
        struct repsFromToBlob *reps_from_blob = NULL;
 
580
        struct repsFromTo2 *reps_from = NULL;
 
581
        uint32_t c_reps_from;
 
582
        uint32_t i_rep;
 
583
        struct ncList *nc_list = NULL;
 
584
 
 
585
        status = get_ncs_list(mem_ctx, samdb, service, object_dn_str, &nc_list);
 
586
        W_ERROR_NOT_OK_RETURN(status);
 
587
 
 
588
        i = j = 0;
 
589
 
 
590
        reply->neighbours = talloc_zero(mem_ctx, struct drsuapi_DsReplicaNeighbourCtr);
 
591
        W_ERROR_HAVE_NO_MEMORY(reply->neighbours);
 
592
        reply->neighbours->reserved = 0;
 
593
        reply->neighbours->count = 0;
 
594
 
 
595
        /* foreach nc in ncs */
 
596
        for (p_nc_list = nc_list; p_nc_list != NULL; p_nc_list = p_nc_list->next) {
 
597
 
 
598
                nc_dn = p_nc_list->dn;
 
599
 
 
600
                /* load the nc's repsFromTo blob */
 
601
                status = dsdb_loadreps(samdb, mem_ctx, nc_dn, "repsFrom",
 
602
                                &reps_from_blob, &c_reps_from);
 
603
                W_ERROR_NOT_OK_RETURN(status);
 
604
 
 
605
                /* foreach r in nc!repsFrom */
 
606
                for (i_rep = 0; i_rep < c_reps_from; i_rep++) {
 
607
 
 
608
                        /* put all info on reps_from */
 
609
                        if (reps_from_blob[i_rep].version == 1) {
 
610
                                status = copy_repsfrom_1_to_2(mem_ctx, &reps_from,
 
611
                                                              &reps_from_blob[i_rep].ctr.ctr1);
 
612
                                W_ERROR_NOT_OK_RETURN(status);
 
613
                        } else { /* reps_from->version == 2 */
 
614
                                reps_from = &reps_from_blob[i_rep].ctr.ctr2;
 
615
                        }
 
616
 
 
617
                        if (GUID_all_zero(&req_src_dsa_guid) ||
 
618
                            GUID_compare(&req_src_dsa_guid, &reps_from->source_dsa_obj_guid) == 0)
 
619
                        {
 
620
 
 
621
                                if (i >= base_index) {
 
622
                                        struct drsuapi_DsReplicaNeighbour neigh;
 
623
                                        ZERO_STRUCT(neigh);
 
624
                                        status = fill_neighbor_from_repsFrom(mem_ctx, samdb,
 
625
                                                                             nc_dn, &neigh,
 
626
                                                                             reps_from);
 
627
                                        W_ERROR_NOT_OK_RETURN(status);
 
628
 
 
629
                                        /* append the neighbour to the neighbours array */
 
630
                                        reply->neighbours->array = talloc_realloc(mem_ctx,
 
631
                                                                                  reply->neighbours->array,
 
632
                                                                                  struct drsuapi_DsReplicaNeighbour,
 
633
                                                                                  reply->neighbours->count + 1);
 
634
                                        reply->neighbours->array[reply->neighbours->count] = neigh;
 
635
                                        reply->neighbours->count++;
 
636
                                        j++;
 
637
                                }
 
638
 
 
639
                                i++;
 
640
                        }
 
641
                }
 
642
        }
 
643
 
 
644
        return WERR_OK;
 
645
}
 
646
 
 
647
static WERROR fill_neighbor_from_repsTo(TALLOC_CTX *mem_ctx,
 
648
                                        struct ldb_context *samdb, struct ldb_dn *nc_dn,
 
649
                                        struct drsuapi_DsReplicaNeighbour *neigh,
 
650
                                        struct repsFromTo2 *reps_to)
 
651
{
 
652
        int ret;
 
653
        struct ldb_dn *source_dsa_dn;
 
654
 
 
655
        neigh->source_dsa_address = reps_to->other_info->dns_name1;
 
656
        neigh->replica_flags = reps_to->replica_flags;
 
657
        neigh->last_attempt = reps_to->last_attempt;
 
658
        neigh->source_dsa_obj_guid = reps_to->source_dsa_obj_guid;
 
659
 
 
660
        ret = dsdb_find_dn_by_guid(samdb, mem_ctx, &reps_to->source_dsa_obj_guid, &source_dsa_dn);
 
661
        if (ret != LDB_SUCCESS) {
 
662
                DEBUG(0,(__location__ ": Failed to find DN for neighbor GUID %s\n",
 
663
                         GUID_string(mem_ctx, &reps_to->source_dsa_obj_guid)));
 
664
                return WERR_DS_DRA_INTERNAL_ERROR;
 
665
        }
 
666
 
 
667
        neigh->source_dsa_obj_dn = ldb_dn_get_linearized(source_dsa_dn);
 
668
        neigh->naming_context_dn = ldb_dn_get_linearized(nc_dn);
 
669
 
 
670
        ret = dsdb_find_guid_by_dn(samdb, nc_dn,
 
671
                        &neigh->naming_context_obj_guid);
 
672
        if (ret != LDB_SUCCESS) {
 
673
                DEBUG(0,(__location__ ": Failed to find GUID for DN %s\n",
 
674
                         ldb_dn_get_linearized(nc_dn)));
 
675
                return WERR_DS_DRA_INTERNAL_ERROR;
 
676
        }
 
677
 
 
678
        return WERR_OK;
 
679
}
 
680
 
 
681
/*
 
682
  Get the outbound neighbours of this DC
 
683
  See details on MS-DRSR 4.1.13.3, for infoType DS_REPL_INFO_REPSTO
 
684
*/
 
685
static WERROR kccdrs_replica_get_info_repsto(TALLOC_CTX *mem_ctx,
 
686
                                             struct kccsrv_service *service,
 
687
                                             struct ldb_context *samdb,
 
688
                                             struct drsuapi_DsReplicaGetInfo *r,
 
689
                                             union drsuapi_DsReplicaInfo *reply,
 
690
                                             uint32_t base_index,
 
691
                                             struct GUID req_src_dsa_guid,
 
692
                                             const char *object_dn_str)
 
693
{
 
694
        WERROR status;
 
695
        uint32_t i, j;
 
696
        struct ncList *p_nc_list = NULL;
 
697
        struct ldb_dn *nc_dn = NULL;
 
698
        struct repsFromToBlob *reps_to_blob;
 
699
        struct repsFromTo2 *reps_to;
 
700
        uint32_t c_reps_to;
 
701
        uint32_t i_rep;
 
702
        struct ncList *nc_list = NULL;
 
703
 
 
704
        status = get_ncs_list(mem_ctx, samdb, service, object_dn_str, &nc_list);
 
705
        W_ERROR_NOT_OK_RETURN(status);
 
706
 
 
707
        i = j = 0;
 
708
 
 
709
        reply->repsto = talloc_zero(mem_ctx, struct drsuapi_DsReplicaNeighbourCtr);
 
710
        W_ERROR_HAVE_NO_MEMORY(reply->repsto);
 
711
        reply->repsto->reserved = 0;
 
712
        reply->repsto->count = 0;
 
713
 
 
714
        /* foreach nc in ncs */
 
715
        for (p_nc_list = nc_list; p_nc_list != NULL; p_nc_list = p_nc_list->next) {
 
716
 
 
717
                nc_dn = p_nc_list->dn;
 
718
 
 
719
                status = dsdb_loadreps(samdb, mem_ctx, nc_dn, "repsTo",
 
720
                                &reps_to_blob, &c_reps_to);
 
721
                W_ERROR_NOT_OK_RETURN(status);
 
722
 
 
723
                /* foreach r in nc!repsTo */
 
724
                for (i_rep = 0; i_rep < c_reps_to; i_rep++) {
 
725
                        struct drsuapi_DsReplicaNeighbour neigh;
 
726
                        ZERO_STRUCT(neigh);
 
727
 
 
728
                        /* put all info on reps_to */
 
729
                        if (reps_to_blob[i_rep].version == 1) {
 
730
                                status = copy_repsfrom_1_to_2(mem_ctx,
 
731
                                                              &reps_to,
 
732
                                                              &reps_to_blob[i_rep].ctr.ctr1);
 
733
                                W_ERROR_NOT_OK_RETURN(status);
 
734
                        } else { /* reps_to->version == 2 */
 
735
                                reps_to = &reps_to_blob[i_rep].ctr.ctr2;
 
736
                        }
 
737
 
 
738
                        if (i >= base_index) {
 
739
                                status = fill_neighbor_from_repsTo(mem_ctx,
 
740
                                                                   samdb, nc_dn,
 
741
                                                                   &neigh, reps_to);
 
742
                                W_ERROR_NOT_OK_RETURN(status);
 
743
 
 
744
                                /* append the neighbour to the neighbours array */
 
745
                                reply->repsto->array = talloc_realloc(mem_ctx,
 
746
                                                                            reply->repsto->array,
 
747
                                                                            struct drsuapi_DsReplicaNeighbour,
 
748
                                                                            reply->repsto->count + 1);
 
749
                                reply->repsto->array[reply->repsto->count++] = neigh;
 
750
                                j++;
 
751
                        }
 
752
                        i++;
 
753
                }
 
754
        }
 
755
 
 
756
        return WERR_OK;
 
757
}
 
758
 
 
759
NTSTATUS kccdrs_replica_get_info(struct irpc_message *msg,
 
760
                                 struct drsuapi_DsReplicaGetInfo *req)
 
761
{
 
762
        WERROR status;
 
763
        struct drsuapi_DsReplicaGetInfoRequest1 *req1;
 
764
        struct drsuapi_DsReplicaGetInfoRequest2 *req2;
 
765
        uint32_t base_index;
 
766
        union drsuapi_DsReplicaInfo *reply;
 
767
        struct GUID req_src_dsa_guid;
 
768
        const char *object_dn_str = NULL;
 
769
        struct kccsrv_service *service;
 
770
        struct ldb_context *samdb;
 
771
        TALLOC_CTX *mem_ctx;
 
772
        enum drsuapi_DsReplicaInfoType info_type;
 
773
        uint32_t flags;
 
774
        const char *attribute_name, *value_dn;
 
775
 
 
776
        service = talloc_get_type(msg->private_data, struct kccsrv_service);
 
777
        samdb = service->samdb;
 
778
        mem_ctx = talloc_new(msg);
 
779
        NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
 
780
 
 
781
#if 0
 
782
        NDR_PRINT_IN_DEBUG(drsuapi_DsReplicaGetInfo, req);
 
783
#endif
 
784
 
 
785
        /* check request version */
 
786
        if (req->in.level != DRSUAPI_DS_REPLICA_GET_INFO &&
 
787
            req->in.level != DRSUAPI_DS_REPLICA_GET_INFO2)
 
788
        {
 
789
                DEBUG(1,(__location__ ": Unsupported DsReplicaGetInfo level %u\n",
 
790
                         req->in.level));
 
791
                status = WERR_REVISION_MISMATCH;
 
792
                goto done;
 
793
        }
 
794
 
 
795
        if (req->in.level == DRSUAPI_DS_REPLICA_GET_INFO) {
 
796
                req1 = &req->in.req->req1;
 
797
                base_index = 0;
 
798
                info_type = req1->info_type;
 
799
                object_dn_str = req1->object_dn;
 
800
                req_src_dsa_guid = req1->source_dsa_guid;
 
801
        } else { /* r->in.level == DRSUAPI_DS_REPLICA_GET_INFO2 */
 
802
                req2 = &req->in.req->req2;
 
803
                if (req2->enumeration_context == 0xffffffff) {
 
804
                        /* no more data is available */
 
805
                        status = WERR_NO_MORE_ITEMS; /* on MS-DRSR it is ERROR_NO_MORE_ITEMS */
 
806
                        goto done;
 
807
                }
 
808
 
 
809
                base_index = req2->enumeration_context;
 
810
                info_type = req2->info_type;
 
811
                object_dn_str = req2->object_dn;
 
812
                req_src_dsa_guid = req2->source_dsa_guid;
 
813
                flags = req2->flags;
 
814
                attribute_name = req2->attribute_name;
 
815
                value_dn = req2->value_dn_str;
 
816
        }
 
817
 
 
818
        reply = req->out.info;
 
819
        *req->out.info_type = info_type;
 
820
 
 
821
        /* Based on the infoType requested, retrieve the corresponding
 
822
         * information and construct the response message */
 
823
        switch (info_type) {
 
824
 
 
825
        case DRSUAPI_DS_REPLICA_INFO_NEIGHBORS:
 
826
                status = kccdrs_replica_get_info_neighbours(mem_ctx, service, samdb, req,
 
827
                                                            reply, base_index, req_src_dsa_guid,
 
828
                                                            object_dn_str);
 
829
                break;
 
830
        case DRSUAPI_DS_REPLICA_INFO_REPSTO:
 
831
                status = kccdrs_replica_get_info_repsto(mem_ctx, service, samdb, req,
 
832
                                                        reply, base_index, req_src_dsa_guid,
 
833
                                                        object_dn_str);
 
834
                break;
 
835
        case DRSUAPI_DS_REPLICA_INFO_CURSORS: /* On MS-DRSR it is DS_REPL_INFO_CURSORS_FOR_NC */
 
836
                status = kccdrs_replica_get_info_cursors(mem_ctx, samdb, req, reply,
 
837
                                                         ldb_dn_new(mem_ctx, samdb, object_dn_str));
 
838
                break;
 
839
        case DRSUAPI_DS_REPLICA_INFO_CURSORS2: /* On MS-DRSR it is DS_REPL_INFO_CURSORS_2_FOR_NC */
 
840
                status = kccdrs_replica_get_info_cursors2(mem_ctx, samdb, req, reply,
 
841
                                                          ldb_dn_new(mem_ctx, samdb, object_dn_str));
 
842
                break;
 
843
        case DRSUAPI_DS_REPLICA_INFO_PENDING_OPS:
 
844
                status = kccdrs_replica_get_info_pending_ops(mem_ctx, samdb, req, reply,
 
845
                                                             ldb_dn_new(mem_ctx, samdb, object_dn_str));
 
846
                break;
 
847
        case DRSUAPI_DS_REPLICA_INFO_CURSORS3: /* On MS-DRSR it is DS_REPL_INFO_CURSORS_3_FOR_NC */
 
848
                status = WERR_INVALID_LEVEL;
 
849
                break;
 
850
        case DRSUAPI_DS_REPLICA_INFO_UPTODATE_VECTOR_V1: /* On MS-DRSR it is DS_REPL_INFO_UPTODATE_VECTOR_V1 */
 
851
                status = WERR_INVALID_LEVEL;
 
852
                break;
 
853
        case DRSUAPI_DS_REPLICA_INFO_OBJ_METADATA: /* On MS-DRSR it is DS_REPL_INFO_METADATA_FOR_OBJ */
 
854
                status = WERR_INVALID_LEVEL;
 
855
                break;
 
856
        case DRSUAPI_DS_REPLICA_INFO_OBJ_METADATA2: /* On MS-DRSR it is DS_REPL_INFO_METADATA_FOR_OBJ */
 
857
                status = kccdrs_replica_get_info_obj_metadata2(mem_ctx, samdb, req, reply,
 
858
                                                               ldb_dn_new(mem_ctx, samdb, object_dn_str), base_index);
 
859
                break;
 
860
        case DRSUAPI_DS_REPLICA_INFO_ATTRIBUTE_VALUE_METADATA: /* On MS-DRSR it is DS_REPL_INFO_METADATA_FOR_ATTR_VALUE */
 
861
                status = WERR_INVALID_LEVEL;
 
862
                break;
 
863
        case DRSUAPI_DS_REPLICA_INFO_ATTRIBUTE_VALUE_METADATA2: /* On MS-DRSR it is DS_REPL_INFO_METADATA_2_FOR_ATTR_VALUE */
 
864
                status = WERR_INVALID_LEVEL;
 
865
                break;
 
866
        case DRSUAPI_DS_REPLICA_INFO_KCC_DSA_CONNECT_FAILURES: /* On MS-DRSR it is DS_REPL_INFO_KCC_DSA_CONNECT_FAILURES */
 
867
                status = WERR_INVALID_LEVEL;
 
868
                break;
 
869
        case DRSUAPI_DS_REPLICA_INFO_KCC_DSA_LINK_FAILURES: /* On MS-DRSR it is DS_REPL_INFO_KCC_LINK_FAILURES */
 
870
                status = WERR_INVALID_LEVEL;
 
871
                break;
 
872
        case DRSUAPI_DS_REPLICA_INFO_CLIENT_CONTEXTS: /* On MS-DRSR it is DS_REPL_INFO_CLIENT_CONTEXTS */
 
873
                status = WERR_INVALID_LEVEL;
 
874
                break;
 
875
        case DRSUAPI_DS_REPLICA_INFO_SERVER_OUTGOING_CALLS: /* On MS-DRSR it is DS_REPL_INFO_SERVER_OUTGOING_CALLS */
 
876
                status = WERR_INVALID_LEVEL;
 
877
                break;
 
878
        default:
 
879
                DEBUG(1,(__location__ ": Unsupported DsReplicaGetInfo info_type %u\n",
 
880
                         info_type));
 
881
                status = WERR_INVALID_LEVEL;
 
882
                break;
 
883
        }
 
884
 
 
885
done:
 
886
        /* put the status on the result field of the reply */
 
887
        req->out.result = status;
 
888
#if 0
 
889
        NDR_PRINT_OUT_DEBUG(drsuapi_DsReplicaGetInfo, req);
 
890
#endif
 
891
        return NT_STATUS_OK;
 
892
}