2 Unix SMB/CIFS implementation.
4 DsGetNCChanges replication test
6 Copyright (C) Stefan (metze) Metzmacher 2005
7 Copyright (C) Brad Henry 2005
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "lib/cmdline/popt_common.h"
25 #include "librpc/gen_ndr/ndr_drsuapi_c.h"
26 #include "librpc/gen_ndr/ndr_drsblobs.h"
27 #include "libcli/cldap/cldap.h"
28 #include "libcli/ldap/ldap_client.h"
29 #include "torture/torture.h"
30 #include "torture/ldap/proto.h"
31 #include "libcli/auth/libcli_auth.h"
32 #include "../lib/crypto/crypto.h"
33 #include "../libcli/drsuapi/drsuapi.h"
34 #include "auth/credentials/credentials.h"
35 #include "libcli/auth/libcli_auth.h"
36 #include "auth/gensec/gensec.h"
37 #include "param/param.h"
38 #include "dsdb/samdb/samdb.h"
40 struct DsSyncBindInfo
{
41 struct dcerpc_pipe
*pipe
;
42 struct drsuapi_DsBind req
;
43 struct GUID bind_guid
;
44 struct drsuapi_DsBindInfoCtr our_bind_info_ctr
;
45 struct drsuapi_DsBindInfo28 our_bind_info28
;
46 struct drsuapi_DsBindInfo28 peer_bind_info28
;
47 struct policy_handle bind_handle
;
50 struct DsSyncLDAPInfo
{
51 struct ldap_connection
*conn
;
55 struct dcerpc_binding
*drsuapi_binding
;
58 const char *site_name
;
60 const char *domain_dn
;
62 /* what we need to do as 'Administrator' */
64 struct cli_credentials
*credentials
;
65 struct DsSyncBindInfo drsuapi
;
66 struct DsSyncLDAPInfo ldap
;
69 /* what we need to do as the new dc machine account */
71 struct cli_credentials
*credentials
;
72 struct DsSyncBindInfo drsuapi
;
73 struct drsuapi_DsGetDCInfo2 dc_info2
;
74 struct GUID invocation_id
;
75 struct GUID object_guid
;
78 /* info about the old dc */
80 struct drsuapi_DsGetDomainControllerInfo dc_info
;
84 static struct DsSyncTest
*test_create_context(struct torture_context
*tctx
)
87 struct DsSyncTest
*ctx
;
88 struct drsuapi_DsBindInfo28
*our_bind_info28
;
89 struct drsuapi_DsBindInfoCtr
*our_bind_info_ctr
;
90 const char *binding
= torture_setting_string(tctx
, "binding", NULL
);
91 ctx
= talloc_zero(tctx
, struct DsSyncTest
);
92 if (!ctx
) return NULL
;
94 status
= dcerpc_parse_binding(ctx
, binding
, &ctx
->drsuapi_binding
);
95 if (!NT_STATUS_IS_OK(status
)) {
96 printf("Bad binding string %s\n", binding
);
99 ctx
->drsuapi_binding
->flags
|= DCERPC_SIGN
| DCERPC_SEAL
;
101 ctx
->ldap_url
= talloc_asprintf(ctx
, "ldap://%s/", ctx
->drsuapi_binding
->host
);
104 ctx
->admin
.credentials
= cmdline_credentials
;
106 our_bind_info28
= &ctx
->admin
.drsuapi
.our_bind_info28
;
107 our_bind_info28
->supported_extensions
= 0xFFFFFFFF;
108 our_bind_info28
->supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3
;
109 our_bind_info28
->site_guid
= GUID_zero();
110 our_bind_info28
->pid
= 0;
111 our_bind_info28
->repl_epoch
= 1;
113 our_bind_info_ctr
= &ctx
->admin
.drsuapi
.our_bind_info_ctr
;
114 our_bind_info_ctr
->length
= 28;
115 our_bind_info_ctr
->info
.info28
= *our_bind_info28
;
117 GUID_from_string(DRSUAPI_DS_BIND_GUID
, &ctx
->admin
.drsuapi
.bind_guid
);
119 ctx
->admin
.drsuapi
.req
.in
.bind_guid
= &ctx
->admin
.drsuapi
.bind_guid
;
120 ctx
->admin
.drsuapi
.req
.in
.bind_info
= our_bind_info_ctr
;
121 ctx
->admin
.drsuapi
.req
.out
.bind_handle
= &ctx
->admin
.drsuapi
.bind_handle
;
124 ctx
->new_dc
.credentials
= cmdline_credentials
;
126 our_bind_info28
= &ctx
->new_dc
.drsuapi
.our_bind_info28
;
127 our_bind_info28
->supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_BASE
;
128 our_bind_info28
->supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_ASYNC_REPLICATION
;
129 our_bind_info28
->supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_REMOVEAPI
;
130 our_bind_info28
->supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_MOVEREQ_V2
;
131 our_bind_info28
->supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GETCHG_COMPRESS
;
132 our_bind_info28
->supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V1
;
133 our_bind_info28
->supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION
;
134 our_bind_info28
->supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE
;
135 our_bind_info28
->supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2
;
136 our_bind_info28
->supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION
;
137 our_bind_info28
->supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2
;
138 our_bind_info28
->supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD
;
139 our_bind_info28
->supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_CRYPTO_BIND
;
140 our_bind_info28
->supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GET_REPL_INFO
;
141 our_bind_info28
->supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION
;
142 our_bind_info28
->supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V01
;
143 our_bind_info28
->supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_TRANSITIVE_MEMBERSHIP
;
144 our_bind_info28
->supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY
;
145 our_bind_info28
->supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3
;
146 our_bind_info28
->supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2
;
147 our_bind_info28
->supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6
;
148 our_bind_info28
->supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_NONDOMAIN_NCS
;
149 our_bind_info28
->supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8
;
150 our_bind_info28
->supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V5
;
151 our_bind_info28
->supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6
;
152 our_bind_info28
->supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3
;
153 our_bind_info28
->supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V7
;
154 our_bind_info28
->supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_VERIFY_OBJECT
;
155 if (lp_parm_bool(tctx
->lp_ctx
, NULL
, "dssync", "xpress", false)) {
156 our_bind_info28
->supported_extensions
|= DRSUAPI_SUPPORTED_EXTENSION_XPRESS_COMPRESS
;
158 our_bind_info28
->site_guid
= GUID_zero();
159 our_bind_info28
->pid
= 0;
160 our_bind_info28
->repl_epoch
= 0;
162 our_bind_info_ctr
= &ctx
->new_dc
.drsuapi
.our_bind_info_ctr
;
163 our_bind_info_ctr
->length
= 28;
164 our_bind_info_ctr
->info
.info28
= *our_bind_info28
;
166 GUID_from_string(DRSUAPI_DS_BIND_GUID_W2K3
, &ctx
->new_dc
.drsuapi
.bind_guid
);
168 ctx
->new_dc
.drsuapi
.req
.in
.bind_guid
= &ctx
->new_dc
.drsuapi
.bind_guid
;
169 ctx
->new_dc
.drsuapi
.req
.in
.bind_info
= our_bind_info_ctr
;
170 ctx
->new_dc
.drsuapi
.req
.out
.bind_handle
= &ctx
->new_dc
.drsuapi
.bind_handle
;
172 ctx
->new_dc
.invocation_id
= ctx
->new_dc
.drsuapi
.bind_guid
;
179 static bool _test_DsBind(struct torture_context
*tctx
,
180 struct DsSyncTest
*ctx
, struct cli_credentials
*credentials
, struct DsSyncBindInfo
*b
)
185 status
= dcerpc_pipe_connect_b(ctx
,
186 &b
->pipe
, ctx
->drsuapi_binding
,
188 credentials
, tctx
->ev
, tctx
->lp_ctx
);
190 if (!NT_STATUS_IS_OK(status
)) {
191 printf("Failed to connect to server as a BDC: %s\n", nt_errstr(status
));
195 status
= dcerpc_drsuapi_DsBind(b
->pipe
, ctx
, &b
->req
);
196 if (!NT_STATUS_IS_OK(status
)) {
197 const char *errstr
= nt_errstr(status
);
198 if (NT_STATUS_EQUAL(status
, NT_STATUS_NET_WRITE_FAULT
)) {
199 errstr
= dcerpc_errstr(ctx
, b
->pipe
->last_fault_code
);
201 printf("dcerpc_drsuapi_DsBind failed - %s\n", errstr
);
203 } else if (!W_ERROR_IS_OK(b
->req
.out
.result
)) {
204 printf("DsBind failed - %s\n", win_errstr(b
->req
.out
.result
));
208 ZERO_STRUCT(b
->peer_bind_info28
);
209 if (b
->req
.out
.bind_info
) {
210 switch (b
->req
.out
.bind_info
->length
) {
212 struct drsuapi_DsBindInfo24
*info24
;
213 info24
= &b
->req
.out
.bind_info
->info
.info24
;
214 b
->peer_bind_info28
.supported_extensions
= info24
->supported_extensions
;
215 b
->peer_bind_info28
.site_guid
= info24
->site_guid
;
216 b
->peer_bind_info28
.pid
= info24
->pid
;
217 b
->peer_bind_info28
.repl_epoch
= 0;
221 struct drsuapi_DsBindInfo48
*info48
;
222 info48
= &b
->req
.out
.bind_info
->info
.info48
;
223 b
->peer_bind_info28
.supported_extensions
= info48
->supported_extensions
;
224 b
->peer_bind_info28
.site_guid
= info48
->site_guid
;
225 b
->peer_bind_info28
.pid
= info48
->pid
;
226 b
->peer_bind_info28
.repl_epoch
= info48
->repl_epoch
;
230 b
->peer_bind_info28
= b
->req
.out
.bind_info
->info
.info28
;
233 printf("DsBind - warning: unknown BindInfo length: %u\n",
234 b
->req
.out
.bind_info
->length
);
241 static bool test_LDAPBind(struct torture_context
*tctx
, struct DsSyncTest
*ctx
,
242 struct cli_credentials
*credentials
, struct DsSyncLDAPInfo
*l
)
247 status
= torture_ldap_connection(tctx
, &l
->conn
, ctx
->ldap_url
);
248 if (!NT_STATUS_IS_OK(status
)) {
249 printf("failed to connect to LDAP: %s\n", ctx
->ldap_url
);
253 printf("connected to LDAP: %s\n", ctx
->ldap_url
);
255 status
= torture_ldap_bind_sasl(l
->conn
, credentials
, tctx
->lp_ctx
);
256 if (!NT_STATUS_IS_OK(status
)) {
257 printf("failed to bind to LDAP:\n");
260 printf("bound to LDAP.\n");
265 static bool test_GetInfo(struct torture_context
*tctx
, struct DsSyncTest
*ctx
)
268 struct drsuapi_DsCrackNames r
;
269 union drsuapi_DsNameRequest req
;
270 union drsuapi_DsNameCtr ctr
;
271 int32_t level_out
= 0;
272 struct drsuapi_DsNameString names
[1];
274 struct cldap_socket
*cldap
;
275 struct cldap_netlogon search
;
277 status
= cldap_socket_init(ctx
, NULL
, NULL
, NULL
, &cldap
);
278 if (!NT_STATUS_IS_OK(status
)) {
279 printf("failed to setup cldap socket - %s\n",
284 r
.in
.bind_handle
= &ctx
->admin
.drsuapi
.bind_handle
;
287 r
.in
.req
->req1
.codepage
= 1252; /* western european */
288 r
.in
.req
->req1
.language
= 0x00000407; /* german */
289 r
.in
.req
->req1
.count
= 1;
290 r
.in
.req
->req1
.names
= names
;
291 r
.in
.req
->req1
.format_flags
= DRSUAPI_DS_NAME_FLAG_NO_FLAGS
;
292 r
.in
.req
->req1
.format_offered
= DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT
;
293 r
.in
.req
->req1
.format_desired
= DRSUAPI_DS_NAME_FORMAT_FQDN_1779
;
294 names
[0].str
= talloc_asprintf(ctx
, "%s\\", lp_workgroup(tctx
->lp_ctx
));
296 r
.out
.level_out
= &level_out
;
299 status
= dcerpc_drsuapi_DsCrackNames(ctx
->admin
.drsuapi
.pipe
, ctx
, &r
);
300 if (!NT_STATUS_IS_OK(status
)) {
301 const char *errstr
= nt_errstr(status
);
302 if (NT_STATUS_EQUAL(status
, NT_STATUS_NET_WRITE_FAULT
)) {
303 errstr
= dcerpc_errstr(ctx
, ctx
->admin
.drsuapi
.pipe
->last_fault_code
);
305 printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr
);
307 } else if (!W_ERROR_IS_OK(r
.out
.result
)) {
308 printf("DsCrackNames failed - %s\n", win_errstr(r
.out
.result
));
312 ctx
->domain_dn
= r
.out
.ctr
->ctr1
->array
[0].result_name
;
315 search
.in
.dest_address
= ctx
->drsuapi_binding
->host
;
316 search
.in
.dest_port
= lp_cldap_port(tctx
->lp_ctx
);
317 search
.in
.acct_control
= -1;
318 search
.in
.version
= NETLOGON_NT_VERSION_5
| NETLOGON_NT_VERSION_5EX
;
319 search
.in
.map_response
= true;
320 status
= cldap_netlogon(cldap
, lp_iconv_convenience(tctx
->lp_ctx
), ctx
, &search
);
321 if (!NT_STATUS_IS_OK(status
)) {
322 const char *errstr
= nt_errstr(status
);
323 ctx
->site_name
= talloc_asprintf(ctx
, "%s", "Default-First-Site-Name");
324 printf("cldap_netlogon() returned %s. Defaulting to Site-Name: %s\n", errstr
, ctx
->site_name
);
326 ctx
->site_name
= talloc_steal(ctx
, search
.out
.netlogon
.data
.nt5_ex
.client_site
);
327 printf("cldap_netlogon() returned Client Site-Name: %s.\n",ctx
->site_name
);
328 printf("cldap_netlogon() returned Server Site-Name: %s.\n",search
.out
.netlogon
.data
.nt5_ex
.server_site
);
331 if (!ctx
->domain_dn
) {
332 struct ldb_context
*ldb
= ldb_init(ctx
, tctx
->ev
);
333 struct ldb_dn
*dn
= samdb_dns_domain_to_dn(ldb
, ctx
, search
.out
.netlogon
.data
.nt5_ex
.dns_domain
);
334 ctx
->domain_dn
= ldb_dn_alloc_linearized(ctx
, dn
);
342 static void test_analyse_objects(struct torture_context
*tctx
,
343 struct DsSyncTest
*ctx
,
344 const DATA_BLOB
*gensec_skey
,
345 struct drsuapi_DsReplicaObjectListItemEx
*cur
)
347 static uint32_t object_id
;
348 const char *save_values_dir
;
350 if (!lp_parm_bool(tctx
->lp_ctx
, NULL
, "dssync", "print_pwd_blobs", false)) {
354 save_values_dir
= lp_parm_string(tctx
->lp_ctx
, NULL
, "dssync", "save_pwd_blobs_dir");
356 for (; cur
; cur
= cur
->next_object
) {
358 struct dom_sid
*sid
= NULL
;
360 bool dn_printed
= false;
363 if (!cur
->object
.identifier
) continue;
365 dn
= cur
->object
.identifier
->dn
;
366 if (cur
->object
.identifier
->sid
.num_auths
> 0) {
367 sid
= &cur
->object
.identifier
->sid
;
368 rid
= sid
->sub_auths
[sid
->num_auths
- 1];
371 for (i
=0; i
< cur
->object
.attribute_ctr
.num_attributes
; i
++) {
373 const char *name
= NULL
;
375 DATA_BLOB
*enc_data
= NULL
;
376 DATA_BLOB plain_data
;
377 struct drsuapi_DsReplicaAttribute
*attr
;
378 ndr_pull_flags_fn_t pull_fn
= NULL
;
379 ndr_print_fn_t print_fn
= NULL
;
381 attr
= &cur
->object
.attribute_ctr
.attributes
[i
];
383 switch (attr
->attid
) {
384 case DRSUAPI_ATTRIBUTE_dBCSPwd
:
388 case DRSUAPI_ATTRIBUTE_unicodePwd
:
392 case DRSUAPI_ATTRIBUTE_ntPwdHistory
:
393 name
= "ntPwdHistory";
396 case DRSUAPI_ATTRIBUTE_lmPwdHistory
:
397 name
= "lmPwdHistory";
400 case DRSUAPI_ATTRIBUTE_supplementalCredentials
:
401 name
= "supplementalCredentials";
402 pull_fn
= (ndr_pull_flags_fn_t
)ndr_pull_supplementalCredentialsBlob
;
403 print_fn
= (ndr_print_fn_t
)ndr_print_supplementalCredentialsBlob
;
404 ptr
= talloc(ctx
, struct supplementalCredentialsBlob
);
406 case DRSUAPI_ATTRIBUTE_priorValue
:
409 case DRSUAPI_ATTRIBUTE_currentValue
:
410 name
= "currentValue";
412 case DRSUAPI_ATTRIBUTE_trustAuthOutgoing
:
413 name
= "trustAuthOutgoing";
414 pull_fn
= (ndr_pull_flags_fn_t
)ndr_pull_trustAuthInOutBlob
;
415 print_fn
= (ndr_print_fn_t
)ndr_print_trustAuthInOutBlob
;
416 ptr
= talloc(ctx
, struct trustAuthInOutBlob
);
418 case DRSUAPI_ATTRIBUTE_trustAuthIncoming
:
419 name
= "trustAuthIncoming";
420 pull_fn
= (ndr_pull_flags_fn_t
)ndr_pull_trustAuthInOutBlob
;
421 print_fn
= (ndr_print_fn_t
)ndr_print_trustAuthInOutBlob
;
422 ptr
= talloc(ctx
, struct trustAuthInOutBlob
);
424 case DRSUAPI_ATTRIBUTE_initialAuthOutgoing
:
425 name
= "initialAuthOutgoing";
427 case DRSUAPI_ATTRIBUTE_initialAuthIncoming
:
428 name
= "initialAuthIncoming";
434 if (attr
->value_ctr
.num_values
!= 1) continue;
436 if (!attr
->value_ctr
.values
[0].blob
) continue;
438 enc_data
= attr
->value_ctr
.values
[0].blob
;
439 ZERO_STRUCT(plain_data
);
441 werr
= drsuapi_decrypt_attribute_value(ctx
, gensec_skey
, rcrypt
,
443 enc_data
, &plain_data
);
444 if (!W_ERROR_IS_OK(werr
)) {
445 DEBUG(0, ("Failed to decrypt %s\n", name
));
450 DEBUG(0,("DN[%u] %s\n", object_id
, dn
));
453 DEBUGADD(0,("ATTR: %s enc.length=%lu plain.length=%lu\n",
454 name
, (long)enc_data
->length
, (long)plain_data
.length
));
455 if (plain_data
.length
) {
456 enum ndr_err_code ndr_err
;
457 dump_data(0, plain_data
.data
, plain_data
.length
);
458 if (save_values_dir
) {
460 fname
= talloc_asprintf(ctx
, "%s/%s%02d",
465 ok
= file_save(fname
, plain_data
.data
, plain_data
.length
);
467 DEBUGADD(0,("Failed to save '%s'\n", fname
));
474 /* Can't use '_all' because of PIDL bugs with relative pointers */
475 ndr_err
= ndr_pull_struct_blob(&plain_data
, ptr
,
476 lp_iconv_convenience(tctx
->lp_ctx
), ptr
,
478 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
479 ndr_print_debug(print_fn
, name
, ptr
);
481 DEBUG(0, ("Failed to decode %s\n", name
));
485 dump_data(0, enc_data
->data
, enc_data
->length
);
492 static bool test_FetchData(struct torture_context
*tctx
, struct DsSyncTest
*ctx
)
497 uint64_t highest_usn
= 0;
498 const char *partition
= NULL
;
499 struct drsuapi_DsGetNCChanges r
;
500 union drsuapi_DsGetNCChangesRequest req
;
501 struct drsuapi_DsReplicaObjectIdentifier nc
;
502 struct drsuapi_DsGetNCChangesCtr1
*ctr1
= NULL
;
503 struct drsuapi_DsGetNCChangesCtr6
*ctr6
= NULL
;
504 int32_t out_level
= 0;
505 struct GUID null_guid
;
506 struct dom_sid null_sid
;
507 DATA_BLOB gensec_skey
;
519 ZERO_STRUCT(null_guid
);
520 ZERO_STRUCT(null_sid
);
522 partition
= lp_parm_string(tctx
->lp_ctx
, NULL
, "dssync", "partition");
523 if (partition
== NULL
) {
524 partition
= ctx
->domain_dn
;
525 printf("dssync:partition not specified, defaulting to %s.\n", ctx
->domain_dn
);
528 highest_usn
= lp_parm_int(tctx
->lp_ctx
, NULL
, "dssync", "highest_usn", 0);
530 array
[0].level
= lp_parm_int(tctx
->lp_ctx
, NULL
, "dssync", "get_nc_changes_level", array
[0].level
);
532 if (lp_parm_bool(tctx
->lp_ctx
, NULL
, "dssync", "print_pwd_blobs", false)) {
533 const struct samr_Password
*nthash
;
534 nthash
= cli_credentials_get_nt_hash(ctx
->new_dc
.credentials
, ctx
);
536 dump_data_pw("CREDENTIALS nthash:", nthash
->hash
, sizeof(nthash
->hash
));
539 status
= gensec_session_key(ctx
->new_dc
.drsuapi
.pipe
->conn
->security_state
.generic_state
,
541 if (!NT_STATUS_IS_OK(status
)) {
542 printf("failed to get gensec session key: %s\n", nt_errstr(status
));
546 for (i
=0; i
< ARRAY_SIZE(array
); i
++) {
547 printf("testing DsGetNCChanges level %d\n",
550 r
.in
.bind_handle
= &ctx
->new_dc
.drsuapi
.bind_handle
;
551 r
.in
.level
= array
[i
].level
;
553 switch (r
.in
.level
) {
560 r
.in
.req
->req5
.destination_dsa_guid
= ctx
->new_dc
.invocation_id
;
561 r
.in
.req
->req5
.source_dsa_invocation_id
= null_guid
;
562 r
.in
.req
->req5
.naming_context
= &nc
;
563 r
.in
.req
->req5
.highwatermark
.tmp_highest_usn
= highest_usn
;
564 r
.in
.req
->req5
.highwatermark
.reserved_usn
= 0;
565 r
.in
.req
->req5
.highwatermark
.highest_usn
= highest_usn
;
566 r
.in
.req
->req5
.uptodateness_vector
= NULL
;
567 r
.in
.req
->req5
.replica_flags
= 0;
568 if (lp_parm_bool(tctx
->lp_ctx
, NULL
, "dssync", "compression", false)) {
569 r
.in
.req
->req5
.replica_flags
|= DRSUAPI_DS_REPLICA_NEIGHBOUR_COMPRESS_CHANGES
;
571 if (lp_parm_bool(tctx
->lp_ctx
, NULL
, "dssync", "neighbour_writeable", true)) {
572 r
.in
.req
->req5
.replica_flags
|= DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
;
574 r
.in
.req
->req5
.replica_flags
|= DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
575 | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS
576 | DRSUAPI_DS_REPLICA_NEIGHBOUR_RETURN_OBJECT_PARENTS
577 | DRSUAPI_DS_REPLICA_NEIGHBOUR_NEVER_SYNCED
579 r
.in
.req
->req5
.max_object_count
= 133;
580 r
.in
.req
->req5
.max_ndr_size
= 1336770;
581 r
.in
.req
->req5
.extended_op
= DRSUAPI_EXOP_NONE
;
582 r
.in
.req
->req5
.fsmo_info
= 0;
589 /* nc.dn can be set to any other ad partition */
592 r
.in
.req
->req8
.destination_dsa_guid
= ctx
->new_dc
.invocation_id
;
593 r
.in
.req
->req8
.source_dsa_invocation_id
= null_guid
;
594 r
.in
.req
->req8
.naming_context
= &nc
;
595 r
.in
.req
->req8
.highwatermark
.tmp_highest_usn
= highest_usn
;
596 r
.in
.req
->req8
.highwatermark
.reserved_usn
= 0;
597 r
.in
.req
->req8
.highwatermark
.highest_usn
= highest_usn
;
598 r
.in
.req
->req8
.uptodateness_vector
= NULL
;
599 r
.in
.req
->req8
.replica_flags
= 0;
600 if (lp_parm_bool(tctx
->lp_ctx
, NULL
, "dssync", "compression", false)) {
601 r
.in
.req
->req8
.replica_flags
|= DRSUAPI_DS_REPLICA_NEIGHBOUR_COMPRESS_CHANGES
;
603 if (lp_parm_bool(tctx
->lp_ctx
, NULL
, "dssync", "neighbour_writeable", true)) {
604 r
.in
.req
->req8
.replica_flags
|= DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
;
606 r
.in
.req
->req8
.replica_flags
|= DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
607 | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS
608 | DRSUAPI_DS_REPLICA_NEIGHBOUR_RETURN_OBJECT_PARENTS
609 | DRSUAPI_DS_REPLICA_NEIGHBOUR_NEVER_SYNCED
611 r
.in
.req
->req8
.max_object_count
= 402;
612 r
.in
.req
->req8
.max_ndr_size
= 402116;
614 r
.in
.req
->req8
.extended_op
= DRSUAPI_EXOP_NONE
;
615 r
.in
.req
->req8
.fsmo_info
= 0;
616 r
.in
.req
->req8
.partial_attribute_set
= NULL
;
617 r
.in
.req
->req8
.partial_attribute_set_ex
= NULL
;
618 r
.in
.req
->req8
.mapping_ctr
.num_mappings
= 0;
619 r
.in
.req
->req8
.mapping_ctr
.mappings
= NULL
;
624 printf("Dumping AD partition: %s\n", nc
.dn
);
627 union drsuapi_DsGetNCChangesCtr ctr
;
631 r
.out
.level_out
= &_level
;
634 if (r
.in
.level
== 5) {
635 DEBUG(0,("start[%d] tmp_higest_usn: %llu , highest_usn: %llu\n",y
,
636 (long long)r
.in
.req
->req5
.highwatermark
.tmp_highest_usn
,
637 (long long)r
.in
.req
->req5
.highwatermark
.highest_usn
));
640 if (r
.in
.level
== 8) {
641 DEBUG(0,("start[%d] tmp_higest_usn: %llu , highest_usn: %llu\n",y
,
642 (long long)r
.in
.req
->req8
.highwatermark
.tmp_highest_usn
,
643 (long long)r
.in
.req
->req8
.highwatermark
.highest_usn
));
646 status
= dcerpc_drsuapi_DsGetNCChanges(ctx
->new_dc
.drsuapi
.pipe
, ctx
, &r
);
647 if (!NT_STATUS_IS_OK(status
)) {
648 const char *errstr
= nt_errstr(status
);
649 if (NT_STATUS_EQUAL(status
, NT_STATUS_NET_WRITE_FAULT
)) {
650 errstr
= dcerpc_errstr(ctx
, ctx
->new_dc
.drsuapi
.pipe
->last_fault_code
);
652 printf("dcerpc_drsuapi_DsGetNCChanges failed - %s\n", errstr
);
654 } else if (!W_ERROR_IS_OK(r
.out
.result
)) {
655 printf("DsGetNCChanges failed - %s\n", win_errstr(r
.out
.result
));
659 if (ret
== true && *r
.out
.level_out
== 1) {
661 ctr1
= &r
.out
.ctr
->ctr1
;
662 } else if (ret
== true && *r
.out
.level_out
== 2 &&
663 r
.out
.ctr
->ctr2
.mszip1
.ts
) {
665 ctr1
= &r
.out
.ctr
->ctr2
.mszip1
.ts
->ctr1
;
668 if (out_level
== 1) {
669 DEBUG(0,("end[%d] tmp_highest_usn: %llu , highest_usn: %llu\n",y
,
670 (long long)ctr1
->new_highwatermark
.tmp_highest_usn
,
671 (long long)ctr1
->new_highwatermark
.highest_usn
));
673 test_analyse_objects(tctx
, ctx
, &gensec_skey
, ctr1
->first_object
);
675 if (ctr1
->more_data
) {
676 r
.in
.req
->req5
.highwatermark
= ctr1
->new_highwatermark
;
681 if (ret
== true && *r
.out
.level_out
== 6) {
683 ctr6
= &r
.out
.ctr
->ctr6
;
684 } else if (ret
== true && *r
.out
.level_out
== 7
685 && r
.out
.ctr
->ctr7
.level
== 6
686 && r
.out
.ctr
->ctr7
.type
== DRSUAPI_COMPRESSION_TYPE_MSZIP
687 && r
.out
.ctr
->ctr7
.ctr
.mszip6
.ts
) {
689 ctr6
= &r
.out
.ctr
->ctr7
.ctr
.mszip6
.ts
->ctr6
;
690 } else if (ret
== true && *r
.out
.level_out
== 7
691 && r
.out
.ctr
->ctr7
.level
== 6
692 && r
.out
.ctr
->ctr7
.type
== DRSUAPI_COMPRESSION_TYPE_XPRESS
693 && r
.out
.ctr
->ctr7
.ctr
.xpress6
.ts
) {
695 ctr6
= &r
.out
.ctr
->ctr7
.ctr
.xpress6
.ts
->ctr6
;
698 if (out_level
== 6) {
699 DEBUG(0,("end[%d] tmp_highest_usn: %llu , highest_usn: %llu\n",y
,
700 (long long)ctr6
->new_highwatermark
.tmp_highest_usn
,
701 (long long)ctr6
->new_highwatermark
.highest_usn
));
703 test_analyse_objects(tctx
, ctx
, &gensec_skey
, ctr6
->first_object
);
705 if (ctr6
->more_data
) {
706 r
.in
.req
->req8
.highwatermark
= ctr6
->new_highwatermark
;
718 static bool test_FetchNT4Data(struct torture_context
*tctx
,
719 struct DsSyncTest
*ctx
)
723 struct drsuapi_DsGetNT4ChangeLog r
;
724 union drsuapi_DsGetNT4ChangeLogRequest req
;
725 union drsuapi_DsGetNT4ChangeLogInfo info
;
726 uint32_t level_out
= 0;
727 struct GUID null_guid
;
728 struct dom_sid null_sid
;
731 ZERO_STRUCT(null_guid
);
732 ZERO_STRUCT(null_sid
);
736 r
.in
.bind_handle
= &ctx
->new_dc
.drsuapi
.bind_handle
;
739 r
.out
.level_out
= &level_out
;
741 req
.req1
.unknown1
= lp_parm_int(tctx
->lp_ctx
, NULL
, "dssync", "nt4-1", 3);
742 req
.req1
.unknown2
= lp_parm_int(tctx
->lp_ctx
, NULL
, "dssync", "nt4-2", 0x00004000);
745 req
.req1
.length
= cookie
.length
;
746 req
.req1
.data
= cookie
.data
;
750 status
= dcerpc_drsuapi_DsGetNT4ChangeLog(ctx
->new_dc
.drsuapi
.pipe
, ctx
, &r
);
751 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_IMPLEMENTED
)) {
752 printf("DsGetNT4ChangeLog not supported by target server\n");
754 } else if (!NT_STATUS_IS_OK(status
)) {
755 const char *errstr
= nt_errstr(status
);
756 if (NT_STATUS_EQUAL(status
, NT_STATUS_NET_WRITE_FAULT
)) {
757 errstr
= dcerpc_errstr(ctx
, ctx
->new_dc
.drsuapi
.pipe
->last_fault_code
);
759 printf("dcerpc_drsuapi_DsGetNT4ChangeLog failed - %s\n", errstr
);
761 } else if (W_ERROR_EQUAL(r
.out
.result
, WERR_INVALID_DOMAIN_ROLE
)) {
762 printf("DsGetNT4ChangeLog not supported by target server\n");
764 } else if (!W_ERROR_IS_OK(r
.out
.result
)) {
765 printf("DsGetNT4ChangeLog failed - %s\n", win_errstr(r
.out
.result
));
767 } else if (*r
.out
.level_out
!= 1) {
768 printf("DsGetNT4ChangeLog unknown level - %u\n", *r
.out
.level_out
);
770 } else if (NT_STATUS_IS_OK(r
.out
.info
->info1
.status
)) {
771 } else if (NT_STATUS_EQUAL(r
.out
.info
->info1
.status
, STATUS_MORE_ENTRIES
)) {
772 cookie
.length
= r
.out
.info
->info1
.length1
;
773 cookie
.data
= r
.out
.info
->info1
.data1
;
776 printf("DsGetNT4ChangeLog failed - %s\n", nt_errstr(r
.out
.info
->info1
.status
));
786 bool torture_rpc_dssync(struct torture_context
*torture
)
790 struct DsSyncTest
*ctx
;
792 mem_ctx
= talloc_init("torture_rpc_dssync");
793 ctx
= test_create_context(torture
);
795 ret
&= _test_DsBind(torture
, ctx
, ctx
->admin
.credentials
, &ctx
->admin
.drsuapi
);
799 ret
&= test_LDAPBind(torture
, ctx
, ctx
->admin
.credentials
, &ctx
->admin
.ldap
);
803 ret
&= test_GetInfo(torture
, ctx
);
804 ret
&= _test_DsBind(torture
, ctx
, ctx
->new_dc
.credentials
, &ctx
->new_dc
.drsuapi
);
808 ret
&= test_FetchData(torture
, ctx
);
809 ret
&= test_FetchNT4Data(torture
, ctx
);