Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : DsGetNCChanges replication test
5 :
6 : Copyright (C) Stefan (metze) Metzmacher 2005
7 : Copyright (C) Brad Henry 2005
8 :
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.
13 :
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.
18 :
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/>.
21 : */
22 :
23 : #include "includes.h"
24 : #include "lib/cmdline/cmdline.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 "torture/torture.h"
29 : #include "../libcli/drsuapi/drsuapi.h"
30 : #include "auth/gensec/gensec.h"
31 : #include "param/param.h"
32 : #include "dsdb/samdb/samdb.h"
33 : #include "torture/rpc/torture_rpc.h"
34 : #include "torture/drs/proto.h"
35 : #include "lib/tsocket/tsocket.h"
36 : #include "libcli/resolve/resolve.h"
37 : #include "lib/util/util_paths.h"
38 :
39 : #undef strcasecmp
40 :
41 : struct DsSyncBindInfo {
42 : struct dcerpc_pipe *drs_pipe;
43 : struct dcerpc_binding_handle *drs_handle;
44 : struct drsuapi_DsBind req;
45 : struct GUID bind_guid;
46 : struct drsuapi_DsBindInfoCtr our_bind_info_ctr;
47 : struct drsuapi_DsBindInfo28 our_bind_info28;
48 : struct drsuapi_DsBindInfo28 peer_bind_info28;
49 : struct policy_handle bind_handle;
50 : };
51 :
52 : struct DsSyncLDAPInfo {
53 : struct ldb_context *ldb;
54 : };
55 :
56 : struct DsSyncTest {
57 : struct dcerpc_binding *drsuapi_binding;
58 :
59 : const char *ldap_url;
60 : const char *dest_address;
61 : const char *domain_dn;
62 : const char *config_dn;
63 : const char *schema_dn;
64 :
65 : /* what we need to do as 'Administrator' */
66 : struct {
67 : struct cli_credentials *credentials;
68 : struct DsSyncBindInfo drsuapi;
69 : struct DsSyncLDAPInfo ldap;
70 : } admin;
71 :
72 : /* what we need to do as the new dc machine account */
73 : struct {
74 : struct cli_credentials *credentials;
75 : struct DsSyncBindInfo drsuapi;
76 : struct drsuapi_DsGetDCInfo2 dc_info2;
77 : struct GUID invocation_id;
78 : struct GUID object_guid;
79 : } new_dc;
80 :
81 : /* info about the old dc */
82 : struct {
83 : struct drsuapi_DsGetDomainControllerInfo dc_info;
84 : } old_dc;
85 : };
86 :
87 3 : static struct DsSyncTest *test_create_context(struct torture_context *tctx)
88 : {
89 : NTSTATUS status;
90 : struct DsSyncTest *ctx;
91 : struct drsuapi_DsBindInfo28 *our_bind_info28;
92 : struct drsuapi_DsBindInfoCtr *our_bind_info_ctr;
93 3 : const char *binding = torture_setting_string(tctx, "binding", NULL);
94 : const char *host;
95 : struct nbt_name name;
96 :
97 3 : ctx = talloc_zero(tctx, struct DsSyncTest);
98 3 : if (!ctx) return NULL;
99 :
100 3 : status = dcerpc_parse_binding(ctx, binding, &ctx->drsuapi_binding);
101 3 : if (!NT_STATUS_IS_OK(status)) {
102 0 : printf("Bad binding string %s\n", binding);
103 0 : return NULL;
104 : }
105 3 : status = dcerpc_binding_set_flags(ctx->drsuapi_binding,
106 : DCERPC_SIGN | DCERPC_SEAL, 0);
107 3 : if (!NT_STATUS_IS_OK(status)) {
108 0 : printf("dcerpc_binding_set_flags - %s\n", nt_errstr(status));
109 0 : return NULL;
110 : }
111 :
112 3 : host = dcerpc_binding_get_string_option(ctx->drsuapi_binding, "host");
113 :
114 3 : ctx->ldap_url = talloc_asprintf(ctx, "ldap://%s", host);
115 :
116 3 : make_nbt_name_server(&name, host);
117 :
118 : /* do an initial name resolution to find its IP */
119 3 : status = resolve_name_ex(lpcfg_resolve_context(tctx->lp_ctx),
120 : 0, 0, &name, tctx,
121 : &ctx->dest_address, tctx->ev);
122 3 : if (!NT_STATUS_IS_OK(status)) {
123 0 : printf("Failed to resolve %s - %s\n",
124 : name.name, nt_errstr(status));
125 0 : return NULL;
126 : }
127 :
128 : /* ctx->admin ...*/
129 3 : ctx->admin.credentials = samba_cmdline_get_creds();
130 :
131 3 : our_bind_info28 = &ctx->admin.drsuapi.our_bind_info28;
132 3 : our_bind_info28->supported_extensions = 0xFFFFFFFF;
133 3 : our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3;
134 3 : our_bind_info28->site_guid = GUID_zero();
135 3 : our_bind_info28->pid = 0;
136 3 : our_bind_info28->repl_epoch = 1;
137 :
138 3 : our_bind_info_ctr = &ctx->admin.drsuapi.our_bind_info_ctr;
139 3 : our_bind_info_ctr->length = 28;
140 3 : our_bind_info_ctr->info.info28 = *our_bind_info28;
141 :
142 3 : GUID_from_string(DRSUAPI_DS_BIND_GUID, &ctx->admin.drsuapi.bind_guid);
143 :
144 3 : ctx->admin.drsuapi.req.in.bind_guid = &ctx->admin.drsuapi.bind_guid;
145 3 : ctx->admin.drsuapi.req.in.bind_info = our_bind_info_ctr;
146 3 : ctx->admin.drsuapi.req.out.bind_handle = &ctx->admin.drsuapi.bind_handle;
147 :
148 : /* ctx->new_dc ...*/
149 3 : ctx->new_dc.credentials = samba_cmdline_get_creds();
150 :
151 3 : our_bind_info28 = &ctx->new_dc.drsuapi.our_bind_info28;
152 3 : our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_BASE;
153 3 : our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ASYNC_REPLICATION;
154 3 : our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_REMOVEAPI;
155 3 : our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_MOVEREQ_V2;
156 3 : our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHG_COMPRESS;
157 3 : our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V1;
158 3 : our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION;
159 3 : our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE;
160 3 : our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2;
161 3 : our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION;
162 3 : our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2;
163 3 : our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD;
164 3 : our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_CRYPTO_BIND;
165 3 : our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_REPL_INFO;
166 3 : our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION;
167 3 : our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V01;
168 3 : our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_TRANSITIVE_MEMBERSHIP;
169 3 : our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY;
170 3 : our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3;
171 3 : our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2;
172 3 : our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6;
173 3 : our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_NONDOMAIN_NCS;
174 3 : our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8;
175 3 : our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V5;
176 3 : our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6;
177 3 : our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3;
178 3 : our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V7;
179 3 : our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_VERIFY_OBJECT;
180 3 : if (lpcfg_parm_bool(tctx->lp_ctx, NULL, "dssync", "xpress", false)) {
181 0 : our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_XPRESS_COMPRESS;
182 : }
183 3 : our_bind_info28->site_guid = GUID_zero();
184 3 : our_bind_info28->pid = 0;
185 3 : our_bind_info28->repl_epoch = 0;
186 :
187 3 : our_bind_info_ctr = &ctx->new_dc.drsuapi.our_bind_info_ctr;
188 3 : our_bind_info_ctr->length = 28;
189 3 : our_bind_info_ctr->info.info28 = *our_bind_info28;
190 :
191 3 : GUID_from_string(DRSUAPI_DS_BIND_GUID_W2K3, &ctx->new_dc.drsuapi.bind_guid);
192 :
193 3 : ctx->new_dc.drsuapi.req.in.bind_guid = &ctx->new_dc.drsuapi.bind_guid;
194 3 : ctx->new_dc.drsuapi.req.in.bind_info = our_bind_info_ctr;
195 3 : ctx->new_dc.drsuapi.req.out.bind_handle = &ctx->new_dc.drsuapi.bind_handle;
196 :
197 3 : ctx->new_dc.invocation_id = ctx->new_dc.drsuapi.bind_guid;
198 :
199 : /* ctx->old_dc ...*/
200 :
201 3 : return ctx;
202 : }
203 :
204 6 : static bool _test_DsBind(struct torture_context *tctx,
205 : struct DsSyncTest *ctx, struct cli_credentials *credentials, struct DsSyncBindInfo *b)
206 : {
207 : NTSTATUS status;
208 6 : bool ret = true;
209 :
210 12 : status = dcerpc_pipe_connect_b(ctx,
211 6 : &b->drs_pipe, ctx->drsuapi_binding,
212 : &ndr_table_drsuapi,
213 : credentials, tctx->ev, tctx->lp_ctx);
214 :
215 6 : if (!NT_STATUS_IS_OK(status)) {
216 0 : printf("Failed to connect to server as a BDC: %s\n", nt_errstr(status));
217 0 : return false;
218 : }
219 6 : b->drs_handle = b->drs_pipe->binding_handle;
220 :
221 6 : status = dcerpc_drsuapi_DsBind_r(b->drs_handle, ctx, &b->req);
222 6 : if (!NT_STATUS_IS_OK(status)) {
223 0 : const char *errstr = nt_errstr(status);
224 0 : printf("dcerpc_drsuapi_DsBind failed - %s\n", errstr);
225 0 : ret = false;
226 6 : } else if (!W_ERROR_IS_OK(b->req.out.result)) {
227 0 : printf("DsBind failed - %s\n", win_errstr(b->req.out.result));
228 0 : ret = false;
229 : }
230 :
231 6 : ZERO_STRUCT(b->peer_bind_info28);
232 6 : if (b->req.out.bind_info) {
233 6 : switch (b->req.out.bind_info->length) {
234 0 : case 24: {
235 : struct drsuapi_DsBindInfo24 *info24;
236 0 : info24 = &b->req.out.bind_info->info.info24;
237 0 : b->peer_bind_info28.supported_extensions= info24->supported_extensions;
238 0 : b->peer_bind_info28.site_guid = info24->site_guid;
239 0 : b->peer_bind_info28.pid = info24->pid;
240 0 : b->peer_bind_info28.repl_epoch = 0;
241 0 : break;
242 : }
243 6 : case 28: {
244 6 : b->peer_bind_info28 = b->req.out.bind_info->info.info28;
245 6 : break;
246 : }
247 0 : case 32: {
248 : struct drsuapi_DsBindInfo32 *info32;
249 0 : info32 = &b->req.out.bind_info->info.info32;
250 0 : b->peer_bind_info28.supported_extensions= info32->supported_extensions;
251 0 : b->peer_bind_info28.site_guid = info32->site_guid;
252 0 : b->peer_bind_info28.pid = info32->pid;
253 0 : b->peer_bind_info28.repl_epoch = info32->repl_epoch;
254 0 : break;
255 : }
256 0 : case 48: {
257 : struct drsuapi_DsBindInfo48 *info48;
258 0 : info48 = &b->req.out.bind_info->info.info48;
259 0 : b->peer_bind_info28.supported_extensions= info48->supported_extensions;
260 0 : b->peer_bind_info28.site_guid = info48->site_guid;
261 0 : b->peer_bind_info28.pid = info48->pid;
262 0 : b->peer_bind_info28.repl_epoch = info48->repl_epoch;
263 0 : break;
264 : }
265 0 : case 52: {
266 : struct drsuapi_DsBindInfo52 *info52;
267 0 : info52 = &b->req.out.bind_info->info.info52;
268 0 : b->peer_bind_info28.supported_extensions= info52->supported_extensions;
269 0 : b->peer_bind_info28.site_guid = info52->site_guid;
270 0 : b->peer_bind_info28.pid = info52->pid;
271 0 : b->peer_bind_info28.repl_epoch = info52->repl_epoch;
272 0 : break;
273 : }
274 0 : default:
275 0 : printf("DsBind - warning: unknown BindInfo length: %u\n",
276 0 : b->req.out.bind_info->length);
277 : }
278 0 : }
279 :
280 6 : return ret;
281 : }
282 :
283 3 : static bool test_LDAPBind(struct torture_context *tctx, struct DsSyncTest *ctx,
284 : struct cli_credentials *credentials, struct DsSyncLDAPInfo *l)
285 : {
286 3 : bool ret = true;
287 :
288 : struct ldb_context *ldb;
289 :
290 3 : const char *modules_option[] = { "modules:paged_searches", NULL };
291 3 : ctx->admin.ldap.ldb = ldb = ldb_init(ctx, tctx->ev);
292 3 : if (ldb == NULL) {
293 0 : return false;
294 : }
295 :
296 : /* Despite us loading the schema from the AD server, we need
297 : * the samba handlers to get the extended DN syntax stuff */
298 3 : ret = ldb_register_samba_handlers(ldb);
299 3 : if (ret != LDB_SUCCESS) {
300 0 : talloc_free(ldb);
301 0 : return NULL;
302 : }
303 :
304 3 : ldb_set_modules_dir(ldb, modules_path(ldb, "ldb"));
305 :
306 3 : if (ldb_set_opaque(ldb, "credentials", credentials)) {
307 0 : talloc_free(ldb);
308 0 : return NULL;
309 : }
310 :
311 3 : if (ldb_set_opaque(ldb, "loadparm", tctx->lp_ctx)) {
312 0 : talloc_free(ldb);
313 0 : return NULL;
314 : }
315 :
316 3 : ret = ldb_connect(ldb, ctx->ldap_url, 0, modules_option);
317 3 : if (ret != LDB_SUCCESS) {
318 0 : talloc_free(ldb);
319 0 : torture_assert_int_equal(tctx, ret, LDB_SUCCESS, "Failed to make LDB connection to target");
320 : }
321 :
322 3 : printf("connected to LDAP: %s\n", ctx->ldap_url);
323 :
324 3 : return true;
325 : }
326 :
327 3 : static bool test_GetInfo(struct torture_context *tctx, struct DsSyncTest *ctx)
328 : {
329 3 : struct ldb_context *ldb = ctx->admin.ldap.ldb;
330 :
331 : /* We must have LDB connection ready by this time */
332 3 : SMB_ASSERT(ldb != NULL);
333 :
334 3 : ctx->domain_dn = ldb_dn_get_linearized(ldb_get_default_basedn(ldb));
335 3 : torture_assert(tctx, ctx->domain_dn != NULL, "Failed to get Domain DN");
336 :
337 3 : ctx->config_dn = ldb_dn_get_linearized(ldb_get_config_basedn(ldb));
338 3 : torture_assert(tctx, ctx->config_dn != NULL, "Failed to get Domain DN");
339 :
340 3 : ctx->schema_dn = ldb_dn_get_linearized(ldb_get_schema_basedn(ldb));
341 3 : torture_assert(tctx, ctx->schema_dn != NULL, "Failed to get Domain DN");
342 :
343 3 : return true;
344 : }
345 :
346 33 : static bool test_analyse_objects(struct torture_context *tctx,
347 : struct DsSyncTest *ctx,
348 : const char *partition,
349 : const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr,
350 : uint32_t object_count,
351 : const struct drsuapi_DsReplicaObjectListItemEx *first_object,
352 : const DATA_BLOB *gensec_skey)
353 : {
354 : static uint32_t object_id;
355 : const char *save_values_dir;
356 : const struct drsuapi_DsReplicaObjectListItemEx *cur;
357 33 : struct ldb_context *ldb = ctx->admin.ldap.ldb;
358 : struct ldb_dn *deleted_dn;
359 : WERROR status;
360 : int i, j, ret;
361 : struct dsdb_extended_replicated_objects *objs;
362 : struct ldb_extended_dn_control *extended_dn_ctrl;
363 : struct dsdb_schema *ldap_schema;
364 33 : struct ldb_dn *partition_dn = ldb_dn_new(tctx, ldb, partition);
365 :
366 33 : torture_assert_not_null(tctx, partition_dn, "Failed to parse partition DN as as DN");
367 :
368 : /* load dsdb_schema using remote prefixMap */
369 33 : torture_assert(tctx,
370 : drs_util_dsdb_schema_load_ldb(tctx, ldb, mapping_ctr, false),
371 : "drs_util_dsdb_schema_load_ldb() failed");
372 33 : ldap_schema = dsdb_get_schema(ldb, NULL);
373 :
374 33 : status = dsdb_replicated_objects_convert(ldb,
375 : ldap_schema,
376 : partition_dn,
377 : mapping_ctr,
378 : object_count,
379 : first_object,
380 : 0, NULL,
381 : NULL, NULL,
382 : gensec_skey,
383 : 0,
384 : ctx, &objs);
385 33 : torture_assert_werr_ok(tctx, status, "dsdb_extended_replicated_objects_convert() failed!");
386 :
387 33 : extended_dn_ctrl = talloc(objs, struct ldb_extended_dn_control);
388 33 : extended_dn_ctrl->type = 1;
389 :
390 33 : deleted_dn = ldb_dn_new(objs, ldb, partition);
391 33 : ldb_dn_add_child_fmt(deleted_dn, "CN=Deleted Objects");
392 :
393 21846 : for (i=0; i < objs->num_objects; i++) {
394 : struct ldb_request *search_req;
395 : struct ldb_result *res;
396 : struct ldb_message *new_msg, *drs_msg, *ldap_msg;
397 10890 : size_t num_attrs = objs->objects[i].msg->num_elements+1;
398 10890 : const char **attrs = talloc_array(objs, const char *, num_attrs);
399 176651 : for (j=0; j < objs->objects[i].msg->num_elements; j++) {
400 165761 : attrs[j] = objs->objects[i].msg->elements[j].name;
401 : }
402 10890 : attrs[j] = NULL;
403 10890 : res = talloc_zero(objs, struct ldb_result);
404 10890 : if (!res) {
405 0 : return LDB_ERR_OPERATIONS_ERROR;
406 : }
407 10890 : ret = ldb_build_search_req(&search_req, ldb, objs,
408 10890 : objs->objects[i].msg->dn,
409 : LDB_SCOPE_BASE,
410 : NULL,
411 : attrs,
412 : NULL,
413 : res,
414 : ldb_search_default_callback,
415 : NULL);
416 10890 : if (ret != LDB_SUCCESS) {
417 0 : return false;
418 : }
419 10890 : talloc_steal(search_req, res);
420 10890 : ret = ldb_request_add_control(search_req, LDB_CONTROL_SHOW_DELETED_OID, true, NULL);
421 10890 : if (ret != LDB_SUCCESS) {
422 0 : return false;
423 : }
424 :
425 10890 : ret = ldb_request_add_control(search_req, LDB_CONTROL_EXTENDED_DN_OID, true, extended_dn_ctrl);
426 10890 : if (ret != LDB_SUCCESS) {
427 0 : return false;
428 : }
429 :
430 10890 : ret = ldb_request(ldb, search_req);
431 10890 : if (ret == LDB_SUCCESS) {
432 10890 : ret = ldb_wait(search_req->handle, LDB_WAIT_ALL);
433 : }
434 :
435 10890 : torture_assert_int_equal(tctx, ret, LDB_SUCCESS,
436 : talloc_asprintf(tctx,
437 : "Could not re-fetch object just delivered over DRS: %s",
438 : ldb_errstring(ldb)));
439 10890 : torture_assert_int_equal(tctx, res->count, 1, "Could not re-fetch object just delivered over DRS");
440 10890 : ldap_msg = res->msgs[0];
441 174587 : for (j=0; j < ldap_msg->num_elements; j++) {
442 163697 : ldap_msg->elements[j].flags = LDB_FLAG_MOD_ADD;
443 : /* For unknown reasons, there is no nTSecurityDescriptor on cn=deleted objects over LDAP, but there is over DRS! Skip it on both transports for now here so */
444 174587 : if ((ldb_attr_cmp(ldap_msg->elements[j].name, "nTSecurityDescriptor") == 0) &&
445 10890 : (ldb_dn_compare(ldap_msg->dn, deleted_dn) == 0)) {
446 6 : ldb_msg_remove_element(ldap_msg, &ldap_msg->elements[j]);
447 : /* Don't skip one */
448 6 : j--;
449 : }
450 : }
451 :
452 10890 : ret = ldb_msg_normalize(ldb, search_req,
453 10890 : objs->objects[i].msg, &drs_msg);
454 10890 : torture_assert(tctx, ret == LDB_SUCCESS,
455 : "ldb_msg_normalize() has failed");
456 :
457 176651 : for (j=0; j < drs_msg->num_elements; j++) {
458 165761 : if (drs_msg->elements[j].num_values == 0) {
459 1905 : ldb_msg_remove_element(drs_msg, &drs_msg->elements[j]);
460 : /* Don't skip one */
461 1905 : j--;
462 :
463 : /* For unknown reasons, there is no nTSecurityDescriptor on cn=deleted objects over LDAP, but there is over DRS! */
464 174746 : } else if ((ldb_attr_cmp(drs_msg->elements[j].name, "nTSecurityDescriptor") == 0) &&
465 10890 : (ldb_dn_compare(drs_msg->dn, deleted_dn) == 0)) {
466 6 : ldb_msg_remove_element(drs_msg, &drs_msg->elements[j]);
467 : /* Don't skip one */
468 6 : j--;
469 327667 : } else if (ldb_attr_cmp(drs_msg->elements[j].name, "unicodePwd") == 0 ||
470 327607 : ldb_attr_cmp(drs_msg->elements[j].name, "dBCSPwd") == 0 ||
471 327580 : ldb_attr_cmp(drs_msg->elements[j].name, "userPassword") == 0 ||
472 327547 : ldb_attr_cmp(drs_msg->elements[j].name, "ntPwdHistory") == 0 ||
473 327481 : ldb_attr_cmp(drs_msg->elements[j].name, "lmPwdHistory") == 0 ||
474 327415 : ldb_attr_cmp(drs_msg->elements[j].name, "supplementalCredentials") == 0 ||
475 327382 : ldb_attr_cmp(drs_msg->elements[j].name, "priorValue") == 0 ||
476 327382 : ldb_attr_cmp(drs_msg->elements[j].name, "currentValue") == 0 ||
477 327382 : ldb_attr_cmp(drs_msg->elements[j].name, "trustAuthOutgoing") == 0 ||
478 327382 : ldb_attr_cmp(drs_msg->elements[j].name, "trustAuthIncoming") == 0 ||
479 327382 : ldb_attr_cmp(drs_msg->elements[j].name, "initialAuthOutgoing") == 0 ||
480 163691 : ldb_attr_cmp(drs_msg->elements[j].name, "initialAuthIncoming") == 0) {
481 :
482 : /* These are not shown over LDAP, so we need to skip them for the comparison */
483 159 : ldb_msg_remove_element(drs_msg, &drs_msg->elements[j]);
484 : /* Don't skip one */
485 159 : j--;
486 : } else {
487 163691 : drs_msg->elements[j].flags = LDB_FLAG_MOD_ADD;
488 : }
489 : }
490 :
491 :
492 10890 : ret = ldb_msg_difference(ldb, search_req,
493 : drs_msg, ldap_msg, &new_msg);
494 10890 : torture_assert(tctx, ret == LDB_SUCCESS, "ldb_msg_difference() has failed");
495 10890 : if (new_msg->num_elements != 0) {
496 : char *s;
497 0 : bool is_warning = true;
498 : unsigned int idx;
499 : struct ldb_message_element *el;
500 : const struct dsdb_attribute * a;
501 : struct ldb_ldif ldif;
502 0 : ldif.changetype = LDB_CHANGETYPE_MODIFY;
503 0 : ldif.msg = new_msg;
504 0 : s = ldb_ldif_write_string(ldb, new_msg, &ldif);
505 0 : s = talloc_asprintf(tctx, "\n# Difference in between DRS and LDAP objects: \n%s", s);
506 :
507 0 : ret = ldb_msg_difference(ldb, search_req,
508 : ldap_msg, drs_msg, &ldif.msg);
509 0 : torture_assert(tctx, ret == LDB_SUCCESS, "ldb_msg_difference() has failed");
510 0 : s = talloc_asprintf_append(s,
511 : "\n# Difference in between LDAP and DRS objects: \n%s",
512 : ldb_ldif_write_string(ldb, new_msg, &ldif));
513 :
514 0 : s = talloc_asprintf_append(s,
515 : "# Should have no objects in 'difference' message. Diff elements: %d",
516 0 : new_msg->num_elements);
517 :
518 : /*
519 : * In case differences in messages are:
520 : * 1. Attributes with different values, i.e. 'replace'
521 : * 2. Those attributes are forward-link attributes
522 : * then we just warn about those differences.
523 : * It turns out windows doesn't send all of those values
524 : * in replicated_object but in linked_attributes.
525 : */
526 0 : for (idx = 0; idx < new_msg->num_elements && is_warning; idx++) {
527 0 : el = &new_msg->elements[idx];
528 0 : a = dsdb_attribute_by_lDAPDisplayName(ldap_schema,
529 : el->name);
530 0 : if (!(el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE))) {
531 : /* DRS only value */
532 0 : is_warning = false;
533 0 : } else if (a->linkID & 1) {
534 0 : is_warning = false;
535 : }
536 : }
537 0 : if (is_warning) {
538 0 : torture_warning(tctx, "%s", s);
539 : } else {
540 0 : torture_fail(tctx, s);
541 : }
542 : }
543 :
544 : /* search_req is used as a tmp talloc context in the above */
545 10890 : talloc_free(search_req);
546 : }
547 :
548 33 : if (!lpcfg_parm_bool(tctx->lp_ctx, NULL, "dssync", "print_pwd_blobs", false)) {
549 33 : talloc_free(objs);
550 33 : return true;
551 : }
552 :
553 0 : save_values_dir = lpcfg_parm_string(tctx->lp_ctx, NULL, "dssync", "save_pwd_blobs_dir");
554 :
555 0 : for (cur = first_object; cur; cur = cur->next_object) {
556 : const char *dn;
557 0 : bool dn_printed = false;
558 :
559 0 : if (!cur->object.identifier) continue;
560 :
561 0 : dn = cur->object.identifier->dn;
562 :
563 0 : for (i=0; i < cur->object.attribute_ctr.num_attributes; i++) {
564 0 : const char *name = NULL;
565 : DATA_BLOB plain_data;
566 : struct drsuapi_DsReplicaAttribute *attr;
567 0 : ndr_pull_flags_fn_t pull_fn = NULL;
568 0 : ndr_print_fn_t print_fn = NULL;
569 0 : void *ptr = NULL;
570 0 : attr = &cur->object.attribute_ctr.attributes[i];
571 :
572 0 : switch (attr->attid) {
573 0 : case DRSUAPI_ATTID_dBCSPwd:
574 0 : name = "dBCSPwd";
575 0 : break;
576 0 : case DRSUAPI_ATTID_unicodePwd:
577 0 : name = "unicodePwd";
578 0 : break;
579 0 : case DRSUAPI_ATTID_ntPwdHistory:
580 0 : name = "ntPwdHistory";
581 0 : break;
582 0 : case DRSUAPI_ATTID_lmPwdHistory:
583 0 : name = "lmPwdHistory";
584 0 : break;
585 0 : case DRSUAPI_ATTID_supplementalCredentials:
586 0 : name = "supplementalCredentials";
587 0 : pull_fn = (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob;
588 0 : print_fn = (ndr_print_fn_t)ndr_print_supplementalCredentialsBlob;
589 0 : ptr = talloc(ctx, struct supplementalCredentialsBlob);
590 0 : break;
591 0 : case DRSUAPI_ATTID_priorValue:
592 0 : name = "priorValue";
593 0 : break;
594 0 : case DRSUAPI_ATTID_currentValue:
595 0 : name = "currentValue";
596 0 : break;
597 0 : case DRSUAPI_ATTID_trustAuthOutgoing:
598 0 : name = "trustAuthOutgoing";
599 0 : pull_fn = (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob;
600 0 : print_fn = (ndr_print_fn_t)ndr_print_trustAuthInOutBlob;
601 0 : ptr = talloc(ctx, struct trustAuthInOutBlob);
602 0 : break;
603 0 : case DRSUAPI_ATTID_trustAuthIncoming:
604 0 : name = "trustAuthIncoming";
605 0 : pull_fn = (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob;
606 0 : print_fn = (ndr_print_fn_t)ndr_print_trustAuthInOutBlob;
607 0 : ptr = talloc(ctx, struct trustAuthInOutBlob);
608 0 : break;
609 0 : case DRSUAPI_ATTID_initialAuthOutgoing:
610 0 : name = "initialAuthOutgoing";
611 0 : break;
612 0 : case DRSUAPI_ATTID_initialAuthIncoming:
613 0 : name = "initialAuthIncoming";
614 0 : break;
615 0 : default:
616 0 : continue;
617 : }
618 :
619 0 : if (attr->value_ctr.num_values != 1) continue;
620 :
621 0 : if (!attr->value_ctr.values[0].blob) continue;
622 :
623 0 : plain_data = *attr->value_ctr.values[0].blob;
624 :
625 0 : if (!dn_printed) {
626 0 : object_id++;
627 0 : DEBUG(0,("DN[%u] %s\n", object_id, dn));
628 0 : dn_printed = true;
629 : }
630 0 : DEBUGADD(0,("ATTR: %s plain.length=%lu\n",
631 : name, (long)plain_data.length));
632 0 : if (plain_data.length) {
633 : enum ndr_err_code ndr_err;
634 0 : dump_data(0, plain_data.data, plain_data.length);
635 0 : if (save_values_dir) {
636 : char *fname;
637 0 : fname = talloc_asprintf(ctx, "%s/%s%02d",
638 : save_values_dir,
639 : name, object_id);
640 0 : if (fname) {
641 : bool ok;
642 0 : ok = file_save(fname, plain_data.data, plain_data.length);
643 0 : if (!ok) {
644 0 : DEBUGADD(0,("Failed to save '%s'\n", fname));
645 : }
646 : }
647 0 : talloc_free(fname);
648 : }
649 :
650 0 : if (pull_fn) {
651 : /* Can't use '_all' because of PIDL bugs with relative pointers */
652 0 : ndr_err = ndr_pull_struct_blob(&plain_data, ptr,
653 : ptr, pull_fn);
654 0 : if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
655 0 : ndr_print_debug(print_fn, name, ptr);
656 : } else {
657 0 : DEBUG(0, ("Failed to decode %s\n", name));
658 : }
659 : }
660 : }
661 0 : talloc_free(ptr);
662 : }
663 : }
664 0 : talloc_free(objs);
665 0 : return true;
666 : }
667 :
668 9 : static bool test_GetNCChanges(struct torture_context *tctx,
669 : struct DsSyncTest *ctx,
670 : const char *nc_dn_str)
671 : {
672 : NTSTATUS status;
673 9 : bool ret = true;
674 9 : int i, y = 0;
675 9 : uint64_t highest_usn = 0;
676 : struct drsuapi_DsGetNCChanges r;
677 : union drsuapi_DsGetNCChangesRequest req;
678 : struct drsuapi_DsReplicaObjectIdentifier nc;
679 9 : struct drsuapi_DsGetNCChangesCtr1 *ctr1 = NULL;
680 9 : struct drsuapi_DsGetNCChangesCtr6 *ctr6 = NULL;
681 9 : uint32_t out_level = 0;
682 : struct dom_sid null_sid;
683 : DATA_BLOB gensec_skey;
684 : struct {
685 : uint32_t level;
686 9 : } array[] = {
687 : /* {
688 : 5
689 : },
690 : */ {
691 : 8
692 : }
693 : };
694 :
695 9 : ZERO_STRUCT(null_sid);
696 :
697 9 : highest_usn = lpcfg_parm_int(tctx->lp_ctx, NULL, "dssync", "highest_usn", 0);
698 :
699 9 : array[0].level = lpcfg_parm_int(tctx->lp_ctx, NULL, "dssync", "get_nc_changes_level", array[0].level);
700 :
701 9 : if (lpcfg_parm_bool(tctx->lp_ctx, NULL, "dssync", "print_pwd_blobs", false)) {
702 : const struct samr_Password *nthash;
703 0 : nthash = cli_credentials_get_nt_hash(ctx->new_dc.credentials, ctx);
704 0 : if (nthash) {
705 0 : dump_data_pw("CREDENTIALS nthash:", nthash->hash, sizeof(nthash->hash));
706 : }
707 : }
708 9 : status = gensec_session_key(ctx->new_dc.drsuapi.drs_pipe->conn->security_state.generic_state,
709 : ctx, &gensec_skey);
710 9 : if (!NT_STATUS_IS_OK(status)) {
711 0 : printf("failed to get gensec session key: %s\n", nt_errstr(status));
712 0 : return false;
713 : }
714 :
715 36 : for (i=0; i < ARRAY_SIZE(array); i++) {
716 9 : printf("Testing DsGetNCChanges level %d\n",
717 : array[i].level);
718 :
719 9 : r.in.bind_handle = &ctx->new_dc.drsuapi.bind_handle;
720 9 : r.in.level = array[i].level;
721 :
722 9 : switch (r.in.level) {
723 0 : case 5:
724 0 : nc.guid = GUID_zero();
725 0 : nc.sid = null_sid;
726 0 : nc.dn = nc_dn_str;
727 :
728 0 : r.in.req = &req;
729 0 : r.in.req->req5.destination_dsa_guid = ctx->new_dc.invocation_id;
730 0 : r.in.req->req5.source_dsa_invocation_id = GUID_zero();
731 0 : r.in.req->req5.naming_context = &nc;
732 0 : r.in.req->req5.highwatermark.tmp_highest_usn = highest_usn;
733 0 : r.in.req->req5.highwatermark.reserved_usn = 0;
734 0 : r.in.req->req5.highwatermark.highest_usn = highest_usn;
735 0 : r.in.req->req5.uptodateness_vector = NULL;
736 0 : r.in.req->req5.replica_flags = 0;
737 0 : if (lpcfg_parm_bool(tctx->lp_ctx, NULL, "dssync", "compression", false)) {
738 0 : r.in.req->req5.replica_flags |= DRSUAPI_DRS_USE_COMPRESSION;
739 : }
740 0 : if (lpcfg_parm_bool(tctx->lp_ctx, NULL, "dssync", "neighbour_writeable", true)) {
741 0 : r.in.req->req5.replica_flags |= DRSUAPI_DRS_WRIT_REP;
742 : }
743 0 : r.in.req->req5.replica_flags |= DRSUAPI_DRS_INIT_SYNC
744 : | DRSUAPI_DRS_PER_SYNC
745 : | DRSUAPI_DRS_GET_ANC
746 : | DRSUAPI_DRS_NEVER_SYNCED
747 : ;
748 0 : r.in.req->req5.max_object_count = 133;
749 0 : r.in.req->req5.max_ndr_size = 1336770;
750 0 : r.in.req->req5.extended_op = DRSUAPI_EXOP_NONE;
751 0 : r.in.req->req5.fsmo_info = 0;
752 :
753 0 : break;
754 9 : case 8:
755 9 : nc.guid = GUID_zero();
756 9 : nc.sid = null_sid;
757 9 : nc.dn = nc_dn_str;
758 : /* nc.dn can be set to any other ad partition */
759 :
760 9 : r.in.req = &req;
761 9 : r.in.req->req8.destination_dsa_guid = ctx->new_dc.invocation_id;
762 9 : r.in.req->req8.source_dsa_invocation_id = GUID_zero();
763 9 : r.in.req->req8.naming_context = &nc;
764 9 : r.in.req->req8.highwatermark.tmp_highest_usn = highest_usn;
765 9 : r.in.req->req8.highwatermark.reserved_usn = 0;
766 9 : r.in.req->req8.highwatermark.highest_usn = highest_usn;
767 9 : r.in.req->req8.uptodateness_vector = NULL;
768 9 : r.in.req->req8.replica_flags = 0;
769 9 : if (lpcfg_parm_bool(tctx->lp_ctx, NULL, "dssync", "compression", false)) {
770 0 : r.in.req->req8.replica_flags |= DRSUAPI_DRS_USE_COMPRESSION;
771 : }
772 9 : if (lpcfg_parm_bool(tctx->lp_ctx, NULL, "dssync", "neighbour_writeable", true)) {
773 9 : r.in.req->req8.replica_flags |= DRSUAPI_DRS_WRIT_REP;
774 : }
775 9 : r.in.req->req8.replica_flags |= DRSUAPI_DRS_INIT_SYNC
776 : | DRSUAPI_DRS_PER_SYNC
777 : | DRSUAPI_DRS_GET_ANC
778 : | DRSUAPI_DRS_NEVER_SYNCED
779 : ;
780 9 : r.in.req->req8.max_object_count = 402;
781 9 : r.in.req->req8.max_ndr_size = 402116;
782 :
783 9 : r.in.req->req8.extended_op = DRSUAPI_EXOP_NONE;
784 9 : r.in.req->req8.fsmo_info = 0;
785 9 : r.in.req->req8.partial_attribute_set = NULL;
786 9 : r.in.req->req8.partial_attribute_set_ex = NULL;
787 9 : r.in.req->req8.mapping_ctr.num_mappings = 0;
788 9 : r.in.req->req8.mapping_ctr.mappings = NULL;
789 :
790 9 : break;
791 : }
792 :
793 33 : for (y=0; ;y++) {
794 33 : uint32_t _level = 0;
795 : union drsuapi_DsGetNCChangesCtr ctr;
796 :
797 33 : ZERO_STRUCT(r.out);
798 :
799 33 : r.out.level_out = &_level;
800 33 : r.out.ctr = &ctr;
801 :
802 33 : if (r.in.level == 5) {
803 0 : torture_comment(tctx,
804 : "start[%d] tmp_higest_usn: %llu , highest_usn: %llu\n",
805 : y,
806 0 : (unsigned long long) r.in.req->req5.highwatermark.tmp_highest_usn,
807 0 : (unsigned long long) r.in.req->req5.highwatermark.highest_usn);
808 : }
809 :
810 33 : if (r.in.level == 8) {
811 33 : torture_comment(tctx,
812 : "start[%d] tmp_higest_usn: %llu , highest_usn: %llu\n",
813 : y,
814 33 : (unsigned long long) r.in.req->req8.highwatermark.tmp_highest_usn,
815 33 : (unsigned long long) r.in.req->req8.highwatermark.highest_usn);
816 : }
817 :
818 33 : status = dcerpc_drsuapi_DsGetNCChanges_r(ctx->new_dc.drsuapi.drs_handle, ctx, &r);
819 33 : torture_drsuapi_assert_call(tctx, ctx->new_dc.drsuapi.drs_pipe, status,
820 : &r, "dcerpc_drsuapi_DsGetNCChanges");
821 :
822 66 : if (ret == true && *r.out.level_out == 1) {
823 0 : out_level = 1;
824 0 : ctr1 = &r.out.ctr->ctr1;
825 33 : } else if (ret == true && *r.out.level_out == 2 &&
826 0 : r.out.ctr->ctr2.mszip1.ts) {
827 0 : out_level = 1;
828 0 : ctr1 = &r.out.ctr->ctr2.mszip1.ts->ctr1;
829 : }
830 :
831 33 : if (out_level == 1) {
832 0 : torture_comment(tctx,
833 : "end[%d] tmp_highest_usn: %llu , highest_usn: %llu\n",
834 : y,
835 0 : (unsigned long long) ctr1->new_highwatermark.tmp_highest_usn,
836 0 : (unsigned long long) ctr1->new_highwatermark.highest_usn);
837 :
838 0 : if (!test_analyse_objects(tctx, ctx, nc_dn_str, &ctr1->mapping_ctr, ctr1->object_count,
839 0 : ctr1->first_object, &gensec_skey)) {
840 0 : return false;
841 : }
842 :
843 0 : if (ctr1->more_data) {
844 0 : r.in.req->req5.highwatermark = ctr1->new_highwatermark;
845 24 : continue;
846 : }
847 : }
848 :
849 33 : if (ret == true && *r.out.level_out == 6) {
850 33 : out_level = 6;
851 33 : ctr6 = &r.out.ctr->ctr6;
852 0 : } else if (ret == true && *r.out.level_out == 7
853 0 : && r.out.ctr->ctr7.level == 6
854 0 : && r.out.ctr->ctr7.type == DRSUAPI_COMPRESSION_TYPE_MSZIP
855 0 : && r.out.ctr->ctr7.ctr.mszip6.ts) {
856 0 : out_level = 6;
857 0 : ctr6 = &r.out.ctr->ctr7.ctr.mszip6.ts->ctr6;
858 0 : } else if (ret == true && *r.out.level_out == 7
859 0 : && r.out.ctr->ctr7.level == 6
860 0 : && r.out.ctr->ctr7.type == DRSUAPI_COMPRESSION_TYPE_XPRESS
861 0 : && r.out.ctr->ctr7.ctr.xpress6.ts) {
862 0 : out_level = 6;
863 0 : ctr6 = &r.out.ctr->ctr7.ctr.xpress6.ts->ctr6;
864 : }
865 :
866 33 : if (out_level == 6) {
867 33 : torture_comment(tctx,
868 : "end[%d] tmp_highest_usn: %llu , highest_usn: %llu\n",
869 : y,
870 33 : (unsigned long long) ctr6->new_highwatermark.tmp_highest_usn,
871 33 : (unsigned long long) ctr6->new_highwatermark.highest_usn);
872 :
873 33 : if (!test_analyse_objects(tctx, ctx, nc_dn_str, &ctr6->mapping_ctr, ctr6->object_count,
874 33 : ctr6->first_object, &gensec_skey)) {
875 0 : return false;
876 : }
877 :
878 33 : if (ctr6->more_data) {
879 24 : r.in.req->req8.highwatermark = ctr6->new_highwatermark;
880 24 : continue;
881 : }
882 : }
883 :
884 9 : break;
885 : }
886 : }
887 :
888 9 : return ret;
889 : }
890 :
891 : /**
892 : * Test DsGetNCChanges() DRSUAPI call against one
893 : * or more Naming Contexts.
894 : * Specific NC to test with may be supplied
895 : * in lp_ctx configuration. If no NC is specified,
896 : * it will test DsGetNCChanges() on all NCs on remote DC
897 : */
898 3 : static bool test_FetchData(struct torture_context *tctx, struct DsSyncTest *ctx)
899 : {
900 3 : bool ret = true;
901 : size_t i, count;
902 : const char *nc_dn_str;
903 : const char **nc_list;
904 :
905 3 : nc_list = const_str_list(str_list_make_empty(ctx));
906 3 : torture_assert(tctx, nc_list, "Not enough memory!");
907 :
908 : /* make a list of partitions to test with */
909 3 : nc_dn_str = lpcfg_parm_string(tctx->lp_ctx, NULL, "dssync", "partition");
910 3 : if (nc_dn_str == NULL) {
911 3 : nc_list = str_list_add_const(nc_list, ctx->domain_dn);
912 3 : nc_list = str_list_add_const(nc_list, ctx->config_dn);
913 3 : nc_list = str_list_add_const(nc_list, ctx->schema_dn);
914 : } else {
915 0 : nc_list = str_list_add_const(nc_list, nc_dn_str);
916 : }
917 :
918 3 : count = str_list_length(nc_list);
919 12 : for (i = 0; i < count && ret; i++) {
920 9 : torture_comment(tctx, "\nNaming Context: %s\n", nc_list[i]);
921 9 : ret = test_GetNCChanges(tctx, ctx, nc_list[i]);
922 : }
923 :
924 3 : talloc_free(nc_list);
925 3 : return ret;
926 : }
927 :
928 :
929 3 : static bool test_FetchNT4Data(struct torture_context *tctx,
930 : struct DsSyncTest *ctx)
931 : {
932 : NTSTATUS status;
933 : struct drsuapi_DsGetNT4ChangeLog r;
934 : union drsuapi_DsGetNT4ChangeLogRequest req;
935 : union drsuapi_DsGetNT4ChangeLogInfo info;
936 3 : uint32_t level_out = 0;
937 : DATA_BLOB cookie;
938 :
939 3 : ZERO_STRUCT(cookie);
940 :
941 3 : ZERO_STRUCT(r);
942 3 : r.in.bind_handle = &ctx->new_dc.drsuapi.bind_handle;
943 3 : r.in.level = 1;
944 3 : r.out.info = &info;
945 3 : r.out.level_out = &level_out;
946 :
947 3 : req.req1.flags = lpcfg_parm_int(tctx->lp_ctx, NULL,
948 : "dssync", "nt4changelog_flags",
949 : DRSUAPI_NT4_CHANGELOG_GET_CHANGELOG |
950 : DRSUAPI_NT4_CHANGELOG_GET_SERIAL_NUMBERS);
951 3 : req.req1.preferred_maximum_length = lpcfg_parm_int(tctx->lp_ctx, NULL,
952 : "dssync", "nt4changelog_preferred_len",
953 : 0x00004000);
954 :
955 : while (1) {
956 3 : req.req1.restart_length = cookie.length;
957 3 : req.req1.restart_data = cookie.data;
958 :
959 3 : r.in.req = &req;
960 :
961 3 : status = dcerpc_drsuapi_DsGetNT4ChangeLog_r(ctx->new_dc.drsuapi.drs_handle, ctx, &r);
962 3 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
963 0 : torture_skip(tctx,
964 : "DsGetNT4ChangeLog not supported: NT_STATUS_NOT_IMPLEMENTED");
965 3 : } else if (!NT_STATUS_IS_OK(status)) {
966 3 : const char *errstr = nt_errstr(status);
967 3 : if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
968 3 : torture_skip(tctx,
969 : "DsGetNT4ChangeLog not supported: NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE");
970 : }
971 0 : torture_fail(tctx,
972 : talloc_asprintf(tctx, "dcerpc_drsuapi_DsGetNT4ChangeLog failed - %s\n",
973 : errstr));
974 0 : } else if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_DOMAIN_ROLE)) {
975 0 : torture_skip(tctx,
976 : "DsGetNT4ChangeLog not supported: WERR_INVALID_DOMAIN_ROLE");
977 0 : } else if (!W_ERROR_IS_OK(r.out.result)) {
978 0 : torture_fail(tctx,
979 : talloc_asprintf(tctx, "DsGetNT4ChangeLog failed - %s\n",
980 : win_errstr(r.out.result)));
981 0 : } else if (*r.out.level_out != 1) {
982 0 : torture_fail(tctx,
983 : talloc_asprintf(tctx, "DsGetNT4ChangeLog unknown level - %u\n",
984 : *r.out.level_out));
985 0 : } else if (NT_STATUS_IS_OK(r.out.info->info1.status)) {
986 0 : } else if (NT_STATUS_EQUAL(r.out.info->info1.status, STATUS_MORE_ENTRIES)) {
987 0 : cookie.length = r.out.info->info1.restart_length;
988 0 : cookie.data = r.out.info->info1.restart_data;
989 0 : continue;
990 : } else {
991 0 : torture_fail(tctx,
992 : talloc_asprintf(tctx, "DsGetNT4ChangeLog failed - %s\n",
993 : nt_errstr(r.out.info->info1.status)));
994 : }
995 :
996 0 : break;
997 : }
998 :
999 0 : return true;
1000 : }
1001 :
1002 : /**
1003 : * DSSYNC test case setup
1004 : */
1005 3 : static bool torture_dssync_tcase_setup(struct torture_context *tctx, void **data)
1006 : {
1007 : bool bret;
1008 : struct DsSyncTest *ctx;
1009 :
1010 3 : *data = ctx = test_create_context(tctx);
1011 3 : torture_assert(tctx, ctx, "test_create_context() failed");
1012 :
1013 3 : bret = _test_DsBind(tctx, ctx, ctx->admin.credentials, &ctx->admin.drsuapi);
1014 3 : torture_assert(tctx, bret, "_test_DsBind() failed");
1015 :
1016 3 : bret = test_LDAPBind(tctx, ctx, ctx->admin.credentials, &ctx->admin.ldap);
1017 3 : torture_assert(tctx, bret, "test_LDAPBind() failed");
1018 :
1019 3 : bret = test_GetInfo(tctx, ctx);
1020 3 : torture_assert(tctx, bret, "test_GetInfo() failed");
1021 :
1022 3 : bret = _test_DsBind(tctx, ctx, ctx->new_dc.credentials, &ctx->new_dc.drsuapi);
1023 3 : torture_assert(tctx, bret, "_test_DsBind() failed");
1024 :
1025 3 : return true;
1026 : }
1027 :
1028 : /**
1029 : * DSSYNC test case cleanup
1030 : */
1031 3 : static bool torture_dssync_tcase_teardown(struct torture_context *tctx, void *data)
1032 : {
1033 : struct DsSyncTest *ctx;
1034 : struct drsuapi_DsUnbind r;
1035 : struct policy_handle bind_handle;
1036 :
1037 3 : ctx = talloc_get_type(data, struct DsSyncTest);
1038 :
1039 3 : ZERO_STRUCT(r);
1040 3 : r.out.bind_handle = &bind_handle;
1041 :
1042 : /* Unbing admin handle */
1043 3 : r.in.bind_handle = &ctx->admin.drsuapi.bind_handle;
1044 3 : dcerpc_drsuapi_DsUnbind_r(ctx->admin.drsuapi.drs_handle, ctx, &r);
1045 :
1046 : /* Unbing new_dc handle */
1047 3 : r.in.bind_handle = &ctx->new_dc.drsuapi.bind_handle;
1048 3 : dcerpc_drsuapi_DsUnbind_r(ctx->new_dc.drsuapi.drs_handle, ctx, &r);
1049 :
1050 3 : talloc_free(ctx);
1051 :
1052 3 : return true;
1053 : }
1054 :
1055 : /**
1056 : * DSSYNC test case implementation
1057 : */
1058 2355 : void torture_drs_rpc_dssync_tcase(struct torture_suite *suite)
1059 : {
1060 : typedef bool (*run_func) (struct torture_context *test, void *tcase_data);
1061 2355 : struct torture_tcase *tcase = torture_suite_add_tcase(suite, "dssync");
1062 :
1063 2355 : torture_tcase_set_fixture(tcase,
1064 : torture_dssync_tcase_setup,
1065 : torture_dssync_tcase_teardown);
1066 :
1067 2355 : torture_tcase_add_simple_test(tcase, "DC_FetchData", (run_func)test_FetchData);
1068 2355 : torture_tcase_add_simple_test(tcase, "FetchNT4Data", (run_func)test_FetchNT4Data);
1069 2355 : }
1070 :
|