2
Unix SMB/CIFS implementation.
4
DRS Replica Information
6
Copyright (C) Erick Nogueira do Nascimento 2009-2010
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.
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.
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/>.
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"
41
get the stamp values for the linked attribute 'linked_attr_name' of the object 'dn'
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)
47
struct ldb_result *res;
50
struct ldb_dn *attr_ext_dn;
53
attrs[0] = linked_attr_name;
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;
64
attr_ext_dn = ldb_msg_find_attr_as_dn(samdb, mem_ctx, res->msgs[0], linked_attr_name);
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;
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)));
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;
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;
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;
98
static WERROR get_repl_prop_metadata_ctr(TALLOC_CTX *mem_ctx,
99
struct ldb_context *samdb,
101
struct replPropertyMetaDataBlob *obj_metadata_ctr)
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;
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;
116
omd_value = ldb_msg_find_ldb_val(res->msgs[0], "replPropertyMetaData");
118
DEBUG(0,(__location__ ": Object %s does not have a replPropertyMetaData attribute\n",
119
ldb_dn_get_linearized(dn)));
121
return WERR_INTERNAL_ERROR;
124
ndr_err = ndr_pull_struct_blob(omd_value, mem_ctx,
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)));
131
return WERR_INTERNAL_ERROR;
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'
143
static WERROR get_dn_from_invocation_id(TALLOC_CTX *mem_ctx,
144
struct ldb_context *samdb,
145
struct GUID *invocation_id,
148
char *invocation_id_str;
149
const char *attrs_invocation[] = { NULL };
150
struct ldb_message *msg;
153
invocation_id_str = GUID_string(mem_ctx, invocation_id);
154
W_ERROR_HAVE_NO_MEMORY(invocation_id_str);
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;
165
*dn_str = ldb_dn_alloc_linearized(mem_ctx, msg->dn);
166
talloc_free(invocation_id_str);
171
get metadata version 2 info for a specified object DN
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,
181
struct replPropertyMetaDataBlob omd_ctr;
182
struct replPropertyMetaData1 *attr;
183
struct drsuapi_DsReplicaObjMetaData2Ctr *metadata2;
184
const struct dsdb_schema *schema;
188
DEBUG(0, ("kccdrs_replica_get_info_obj_metadata2() called\n"));
191
return WERR_INVALID_PARAMETER;
194
if (!ldb_dn_validate(dn)) {
195
return WERR_DS_DRA_BAD_DN;
198
status = get_repl_prop_metadata_ctr(mem_ctx, samdb, dn, &omd_ctr);
199
W_ERROR_NOT_OK_RETURN(status);
201
schema = dsdb_get_schema(samdb, reply);
203
DEBUG(0,(__location__": Failed to get the schema\n"));
204
return WERR_INTERNAL_ERROR;
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;
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;
221
s := AttrStamp(object, attr)
223
/* get a reference to the attribute on 'omd_ctr' */
224
attr = &omd_ctr.ctr.ctr1.array[j];
226
schema_attr = dsdb_attribute_by_attributeID_id(schema, attr->attid);
228
DEBUG(0, ("attribute_id = %d, attribute_name: %s\n", attr->attid, schema_attr->lDAPDisplayName));
231
if (attr in Link Attributes of object and
232
dwInVersion = 2 and DS_REPL_INFO_FLAG_IMPROVE_LINKED_ATTRS in msgIn.ulFlags)
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 */
238
(r->in.req->req2.flags & DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE)) /* on MS-DRSR it is DS_REPL_INFO_FLAG_IMPROVE_LINKED_ATTRS */
241
ls := LinkValueStamp of the most recent
242
value change in object!attr
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);
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
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) {
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
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;
270
if (i < base_index) {
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;
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
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);
294
metadata2->count = j;
302
get cursors info for a specified DN
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,
312
if (!ldb_dn_validate(dn)) {
313
return WERR_INVALID_PARAMETER;
315
reply->cursors = talloc(mem_ctx, struct drsuapi_DsReplicaCursorCtr);
316
W_ERROR_HAVE_NO_MEMORY(reply->cursors);
318
reply->cursors->reserved = 0;
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;
328
get cursors2 info for a specified DN
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,
338
if (!ldb_dn_validate(dn)) {
339
return WERR_INVALID_PARAMETER;
341
reply->cursors2 = talloc(mem_ctx, struct drsuapi_DsReplicaCursor2Ctr);
342
W_ERROR_HAVE_NO_MEMORY(reply->cursors2);
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;
349
reply->cursors2->enumeration_context = reply->cursors2->count;
354
get pending ops info for a specified DN
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,
362
struct timeval now = timeval_current();
364
if (!ldb_dn_validate(dn)) {
365
return WERR_INVALID_PARAMETER;
367
reply->pendingops = talloc(mem_ctx, struct drsuapi_DsReplicaOpCtr);
368
W_ERROR_HAVE_NO_MEMORY(reply->pendingops);
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;
380
struct ncList *prev, *next;
384
Fill 'master_nc_list' with the master ncs hosted by this server
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)
389
const char *attrs[] = { "hasMasterNCs", NULL };
390
struct ldb_result *res;
391
struct ncList *nc_list = NULL;
392
struct ncList *nc_list_elem;
397
ret = ldb_search(samdb, mem_ctx, &res, ldb_get_config_basedn(samdb),
398
LDB_SCOPE_DEFAULT, attrs, "(objectguid=%s)", ntds_guid_str);
400
if (ret != LDB_SUCCESS) {
401
DEBUG(0,(__location__ ": Failed objectguid search - %s\n", ldb_errstring(samdb)));
402
return WERR_INTERNAL_ERROR;
405
if (res->count == 0) {
406
DEBUG(0,(__location__ ": Failed: objectguid=%s not found\n", ntds_guid_str));
407
return WERR_INTERNAL_ERROR;
410
for (i = 0; i < res->count; i++) {
411
struct ldb_message_element *msg_elem = ldb_msg_find_element(res->msgs[i], "hasMasterNCs");
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;
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);
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);
434
*master_nc_list = nc_list;
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
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)
450
struct ncList *nc_list_elem;
451
struct ldb_dn *nc_dn;
453
if (object_dn_str != NULL) {
454
/* ncs := { object_dn } */
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*);
462
/* ncs := getNCs() from ldb database.
463
* getNCs() must return an array containing
464
* the DSNames of all NCs hosted by this
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);
477
Copy the fields from 'reps1' to 'reps2', leaving zeroed the fields on
478
'reps2' that aren't available on 'reps1'.
480
static WERROR copy_repsfrom_1_to_2(TALLOC_CTX *mem_ctx,
481
struct repsFromTo2 **reps2,
482
struct repsFromTo1 *reps1)
484
struct repsFromTo2* reps;
486
reps = talloc_zero(mem_ctx, struct repsFromTo2);
487
W_ERROR_HAVE_NO_MEMORY(reps);
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;
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)
515
struct ldb_dn *source_dsa_dn;
517
struct ldb_dn *transport_obj_dn = NULL;
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;
524
ret = dsdb_find_dn_by_guid(samdb, mem_ctx, &reps_from->source_dsa_obj_guid,
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;
533
neigh->source_dsa_obj_dn = ldb_dn_get_linearized(source_dsa_dn);
534
neigh->naming_context_dn = ldb_dn_get_linearized(nc_dn);
536
if (dsdb_find_guid_by_dn(samdb, nc_dn, &neigh->naming_context_obj_guid)
538
return WERR_DS_DRA_INTERNAL_ERROR;
541
if (!GUID_all_zero(&reps_from->transport_guid)) {
542
ret = dsdb_find_dn_by_guid(samdb, mem_ctx, &reps_from->transport_guid,
544
if (ret != LDB_SUCCESS) {
545
return WERR_DS_DRA_INTERNAL_ERROR;
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. */
563
Get the inbound neighbours of this DC
564
See details on MS-DRSR 4.1.13.3, for infoType DS_REPL_INFO_NEIGHBORS
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,
572
struct GUID req_src_dsa_guid,
573
const char *object_dn_str)
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;
583
struct ncList *nc_list = NULL;
585
status = get_ncs_list(mem_ctx, samdb, service, object_dn_str, &nc_list);
586
W_ERROR_NOT_OK_RETURN(status);
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;
595
/* foreach nc in ncs */
596
for (p_nc_list = nc_list; p_nc_list != NULL; p_nc_list = p_nc_list->next) {
598
nc_dn = p_nc_list->dn;
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);
605
/* foreach r in nc!repsFrom */
606
for (i_rep = 0; i_rep < c_reps_from; i_rep++) {
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;
617
if (GUID_all_zero(&req_src_dsa_guid) ||
618
GUID_compare(&req_src_dsa_guid, &reps_from->source_dsa_obj_guid) == 0)
621
if (i >= base_index) {
622
struct drsuapi_DsReplicaNeighbour neigh;
624
status = fill_neighbor_from_repsFrom(mem_ctx, samdb,
627
W_ERROR_NOT_OK_RETURN(status);
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++;
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)
653
struct ldb_dn *source_dsa_dn;
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;
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;
667
neigh->source_dsa_obj_dn = ldb_dn_get_linearized(source_dsa_dn);
668
neigh->naming_context_dn = ldb_dn_get_linearized(nc_dn);
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;
682
Get the outbound neighbours of this DC
683
See details on MS-DRSR 4.1.13.3, for infoType DS_REPL_INFO_REPSTO
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,
691
struct GUID req_src_dsa_guid,
692
const char *object_dn_str)
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;
702
struct ncList *nc_list = NULL;
704
status = get_ncs_list(mem_ctx, samdb, service, object_dn_str, &nc_list);
705
W_ERROR_NOT_OK_RETURN(status);
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;
714
/* foreach nc in ncs */
715
for (p_nc_list = nc_list; p_nc_list != NULL; p_nc_list = p_nc_list->next) {
717
nc_dn = p_nc_list->dn;
719
status = dsdb_loadreps(samdb, mem_ctx, nc_dn, "repsTo",
720
&reps_to_blob, &c_reps_to);
721
W_ERROR_NOT_OK_RETURN(status);
723
/* foreach r in nc!repsTo */
724
for (i_rep = 0; i_rep < c_reps_to; i_rep++) {
725
struct drsuapi_DsReplicaNeighbour neigh;
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,
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;
738
if (i >= base_index) {
739
status = fill_neighbor_from_repsTo(mem_ctx,
742
W_ERROR_NOT_OK_RETURN(status);
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;
759
NTSTATUS kccdrs_replica_get_info(struct irpc_message *msg,
760
struct drsuapi_DsReplicaGetInfo *req)
763
struct drsuapi_DsReplicaGetInfoRequest1 *req1;
764
struct drsuapi_DsReplicaGetInfoRequest2 *req2;
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;
772
enum drsuapi_DsReplicaInfoType info_type;
774
const char *attribute_name, *value_dn;
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);
782
NDR_PRINT_IN_DEBUG(drsuapi_DsReplicaGetInfo, req);
785
/* check request version */
786
if (req->in.level != DRSUAPI_DS_REPLICA_GET_INFO &&
787
req->in.level != DRSUAPI_DS_REPLICA_GET_INFO2)
789
DEBUG(1,(__location__ ": Unsupported DsReplicaGetInfo level %u\n",
791
status = WERR_REVISION_MISMATCH;
795
if (req->in.level == DRSUAPI_DS_REPLICA_GET_INFO) {
796
req1 = &req->in.req->req1;
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 */
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;
814
attribute_name = req2->attribute_name;
815
value_dn = req2->value_dn_str;
818
reply = req->out.info;
819
*req->out.info_type = info_type;
821
/* Based on the infoType requested, retrieve the corresponding
822
* information and construct the response message */
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,
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,
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));
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));
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));
847
case DRSUAPI_DS_REPLICA_INFO_CURSORS3: /* On MS-DRSR it is DS_REPL_INFO_CURSORS_3_FOR_NC */
848
status = WERR_INVALID_LEVEL;
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;
853
case DRSUAPI_DS_REPLICA_INFO_OBJ_METADATA: /* On MS-DRSR it is DS_REPL_INFO_METADATA_FOR_OBJ */
854
status = WERR_INVALID_LEVEL;
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);
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;
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;
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;
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;
872
case DRSUAPI_DS_REPLICA_INFO_CLIENT_CONTEXTS: /* On MS-DRSR it is DS_REPL_INFO_CLIENT_CONTEXTS */
873
status = WERR_INVALID_LEVEL;
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;
879
DEBUG(1,(__location__ ": Unsupported DsReplicaGetInfo info_type %u\n",
881
status = WERR_INVALID_LEVEL;
886
/* put the status on the result field of the reply */
887
req->out.result = status;
889
NDR_PRINT_OUT_DEBUG(drsuapi_DsReplicaGetInfo, req);