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 0 : NTSTATUS status;
90 0 : struct DsSyncTest *ctx;
91 0 : struct drsuapi_DsBindInfo28 *our_bind_info28;
92 0 : struct drsuapi_DsBindInfoCtr *our_bind_info_ctr;
93 3 : const char *binding = torture_setting_string(tctx, "binding", NULL);
94 0 : const char *host;
95 0 : 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 0 : NTSTATUS status;
208 6 : bool ret = true;
209 :
210 6 : 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 0 : 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 0 : 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 0 : 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 0 : 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 : }
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 0 : 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 30 : 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 0 : static uint32_t object_id;
355 0 : const char *save_values_dir;
356 0 : const struct drsuapi_DsReplicaObjectListItemEx *cur;
357 30 : struct ldb_context *ldb = ctx->admin.ldap.ldb;
358 0 : struct ldb_dn *deleted_dn;
359 0 : WERROR status;
360 0 : int i, j, ret;
361 0 : struct dsdb_extended_replicated_objects *objs;
362 0 : struct ldb_extended_dn_control *extended_dn_ctrl;
363 0 : struct dsdb_schema *ldap_schema;
364 30 : struct ldb_dn *partition_dn = ldb_dn_new(tctx, ldb, partition);
365 :
366 30 : torture_assert_not_null(tctx, partition_dn, "Failed to parse partition DN as as DN");
367 :
368 : /* load dsdb_schema using remote prefixMap */
369 30 : torture_assert(tctx,
370 : drs_util_dsdb_schema_load_ldb(tctx, ldb, mapping_ctr, false),
371 : "drs_util_dsdb_schema_load_ldb() failed");
372 30 : ldap_schema = dsdb_get_schema(ldb, NULL);
373 :
374 30 : 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 30 : torture_assert_werr_ok(tctx, status, "dsdb_extended_replicated_objects_convert() failed!");
386 :
387 30 : extended_dn_ctrl = talloc(objs, struct ldb_extended_dn_control);
388 30 : extended_dn_ctrl->type = 1;
389 :
390 30 : deleted_dn = ldb_dn_new(objs, ldb, partition);
391 30 : ldb_dn_add_child_fmt(deleted_dn, "CN=Deleted Objects");
392 :
393 10332 : for (i=0; i < objs->num_objects; i++) {
394 0 : struct ldb_request *search_req;
395 0 : struct ldb_result *res;
396 0 : struct ldb_message *new_msg, *drs_msg, *ldap_msg;
397 10302 : size_t num_attrs = objs->objects[i].msg->num_elements+1;
398 10302 : const char **attrs = talloc_array(objs, const char *, num_attrs);
399 164627 : for (j=0; j < objs->objects[i].msg->num_elements; j++) {
400 154325 : attrs[j] = objs->objects[i].msg->elements[j].name;
401 : }
402 10302 : attrs[j] = NULL;
403 10302 : res = talloc_zero(objs, struct ldb_result);
404 10302 : if (!res) {
405 0 : return LDB_ERR_OPERATIONS_ERROR;
406 : }
407 10302 : ret = ldb_build_search_req(&search_req, ldb, objs,
408 10302 : 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 10302 : if (ret != LDB_SUCCESS) {
417 0 : return false;
418 : }
419 10302 : talloc_steal(search_req, res);
420 10302 : ret = ldb_request_add_control(search_req, LDB_CONTROL_SHOW_DELETED_OID, true, NULL);
421 10302 : if (ret != LDB_SUCCESS) {
422 0 : return false;
423 : }
424 :
425 10302 : ret = ldb_request_add_control(search_req, LDB_CONTROL_EXTENDED_DN_OID, true, extended_dn_ctrl);
426 10302 : if (ret != LDB_SUCCESS) {
427 0 : return false;
428 : }
429 :
430 10302 : ret = ldb_request(ldb, search_req);
431 10302 : if (ret == LDB_SUCCESS) {
432 10302 : ret = ldb_wait(search_req->handle, LDB_WAIT_ALL);
433 : }
434 :
435 10302 : 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 10302 : torture_assert_int_equal(tctx, res->count, 1, "Could not re-fetch object just delivered over DRS");
440 10302 : ldap_msg = res->msgs[0];
441 162557 : for (j=0; j < ldap_msg->num_elements; j++) {
442 152255 : 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 162551 : if ((ldb_attr_cmp(ldap_msg->elements[j].name, "nTSecurityDescriptor") == 0) &&
445 10296 : (ldb_dn_compare(ldap_msg->dn, deleted_dn) == 0)) {
446 0 : ldb_msg_remove_element(ldap_msg, &ldap_msg->elements[j]);
447 : /* Don't skip one */
448 0 : j--;
449 : }
450 : }
451 :
452 10302 : ret = ldb_msg_normalize(ldb, search_req,
453 10302 : objs->objects[i].msg, &drs_msg);
454 10302 : torture_assert(tctx, ret == LDB_SUCCESS,
455 : "ldb_msg_normalize() has failed");
456 :
457 164627 : for (j=0; j < drs_msg->num_elements; j++) {
458 154325 : if (drs_msg->elements[j].num_values == 0) {
459 1965 : ldb_msg_remove_element(drs_msg, &drs_msg->elements[j]);
460 : /* Don't skip one */
461 1965 : j--;
462 :
463 : /* For unknown reasons, there is no nTSecurityDescriptor on cn=deleted objects over LDAP, but there is over DRS! */
464 162662 : } else if ((ldb_attr_cmp(drs_msg->elements[j].name, "nTSecurityDescriptor") == 0) &&
465 10302 : (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 152354 : } else if (ldb_attr_cmp(drs_msg->elements[j].name, "unicodePwd") == 0 ||
470 152321 : ldb_attr_cmp(drs_msg->elements[j].name, "dBCSPwd") == 0 ||
471 152321 : ldb_attr_cmp(drs_msg->elements[j].name, "userPassword") == 0 ||
472 152321 : ldb_attr_cmp(drs_msg->elements[j].name, "ntPwdHistory") == 0 ||
473 152288 : ldb_attr_cmp(drs_msg->elements[j].name, "lmPwdHistory") == 0 ||
474 152288 : ldb_attr_cmp(drs_msg->elements[j].name, "supplementalCredentials") == 0 ||
475 152255 : ldb_attr_cmp(drs_msg->elements[j].name, "priorValue") == 0 ||
476 152255 : ldb_attr_cmp(drs_msg->elements[j].name, "currentValue") == 0 ||
477 152255 : ldb_attr_cmp(drs_msg->elements[j].name, "trustAuthOutgoing") == 0 ||
478 152255 : ldb_attr_cmp(drs_msg->elements[j].name, "trustAuthIncoming") == 0 ||
479 152255 : ldb_attr_cmp(drs_msg->elements[j].name, "initialAuthOutgoing") == 0 ||
480 152255 : 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 99 : ldb_msg_remove_element(drs_msg, &drs_msg->elements[j]);
484 : /* Don't skip one */
485 99 : j--;
486 : } else {
487 152255 : drs_msg->elements[j].flags = LDB_FLAG_MOD_ADD;
488 : }
489 : }
490 :
491 :
492 10302 : ret = ldb_msg_difference(ldb, search_req,
493 : drs_msg, ldap_msg, &new_msg);
494 10302 : torture_assert(tctx, ret == LDB_SUCCESS, "ldb_msg_difference() has failed");
495 10302 : if (new_msg->num_elements != 0) {
496 0 : char *s;
497 0 : bool is_warning = true;
498 0 : unsigned int idx;
499 0 : struct ldb_message_element *el;
500 0 : const struct dsdb_attribute * a;
501 0 : 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 (LDB_FLAG_MOD_TYPE(el->flags) != LDB_FLAG_MOD_ADD &&
531 0 : LDB_FLAG_MOD_TYPE(el->flags) != LDB_FLAG_MOD_REPLACE)
532 : {
533 : /* DRS only value */
534 0 : is_warning = false;
535 0 : } else if (a->linkID & 1) {
536 0 : is_warning = false;
537 : }
538 : }
539 0 : if (is_warning) {
540 0 : torture_warning(tctx, "%s", s);
541 : } else {
542 0 : torture_fail(tctx, s);
543 : }
544 : }
545 :
546 : /* search_req is used as a tmp talloc context in the above */
547 10302 : talloc_free(search_req);
548 : }
549 :
550 30 : if (!lpcfg_parm_bool(tctx->lp_ctx, NULL, "dssync", "print_pwd_blobs", false)) {
551 30 : talloc_free(objs);
552 30 : return true;
553 : }
554 :
555 0 : save_values_dir = lpcfg_parm_string(tctx->lp_ctx, NULL, "dssync", "save_pwd_blobs_dir");
556 :
557 0 : for (cur = first_object; cur; cur = cur->next_object) {
558 0 : const char *dn;
559 0 : bool dn_printed = false;
560 :
561 0 : if (!cur->object.identifier) continue;
562 :
563 0 : dn = cur->object.identifier->dn;
564 :
565 0 : for (i=0; i < cur->object.attribute_ctr.num_attributes; i++) {
566 0 : const char *name = NULL;
567 0 : DATA_BLOB plain_data;
568 0 : struct drsuapi_DsReplicaAttribute *attr;
569 0 : ndr_pull_flags_fn_t pull_fn = NULL;
570 0 : ndr_print_fn_t print_fn = NULL;
571 0 : void *ptr = NULL;
572 0 : attr = &cur->object.attribute_ctr.attributes[i];
573 :
574 0 : switch (attr->attid) {
575 0 : case DRSUAPI_ATTID_dBCSPwd:
576 0 : name = "dBCSPwd";
577 0 : break;
578 0 : case DRSUAPI_ATTID_unicodePwd:
579 0 : name = "unicodePwd";
580 0 : break;
581 0 : case DRSUAPI_ATTID_ntPwdHistory:
582 0 : name = "ntPwdHistory";
583 0 : break;
584 0 : case DRSUAPI_ATTID_lmPwdHistory:
585 0 : name = "lmPwdHistory";
586 0 : break;
587 0 : case DRSUAPI_ATTID_supplementalCredentials:
588 0 : name = "supplementalCredentials";
589 0 : pull_fn = (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob;
590 0 : print_fn = (ndr_print_fn_t)ndr_print_supplementalCredentialsBlob;
591 0 : ptr = talloc(ctx, struct supplementalCredentialsBlob);
592 0 : break;
593 0 : case DRSUAPI_ATTID_priorValue:
594 0 : name = "priorValue";
595 0 : break;
596 0 : case DRSUAPI_ATTID_currentValue:
597 0 : name = "currentValue";
598 0 : break;
599 0 : case DRSUAPI_ATTID_trustAuthOutgoing:
600 0 : name = "trustAuthOutgoing";
601 0 : pull_fn = (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob;
602 0 : print_fn = (ndr_print_fn_t)ndr_print_trustAuthInOutBlob;
603 0 : ptr = talloc(ctx, struct trustAuthInOutBlob);
604 0 : break;
605 0 : case DRSUAPI_ATTID_trustAuthIncoming:
606 0 : name = "trustAuthIncoming";
607 0 : pull_fn = (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob;
608 0 : print_fn = (ndr_print_fn_t)ndr_print_trustAuthInOutBlob;
609 0 : ptr = talloc(ctx, struct trustAuthInOutBlob);
610 0 : break;
611 0 : case DRSUAPI_ATTID_initialAuthOutgoing:
612 0 : name = "initialAuthOutgoing";
613 0 : break;
614 0 : case DRSUAPI_ATTID_initialAuthIncoming:
615 0 : name = "initialAuthIncoming";
616 0 : break;
617 0 : default:
618 0 : continue;
619 : }
620 :
621 0 : if (attr->value_ctr.num_values != 1) continue;
622 :
623 0 : if (!attr->value_ctr.values[0].blob) continue;
624 :
625 0 : plain_data = *attr->value_ctr.values[0].blob;
626 :
627 0 : if (!dn_printed) {
628 0 : object_id++;
629 0 : DEBUG(0,("DN[%u] %s\n", object_id, dn));
630 0 : dn_printed = true;
631 : }
632 0 : DEBUGADD(0,("ATTR: %s plain.length=%lu\n",
633 : name, (long)plain_data.length));
634 0 : if (plain_data.length) {
635 0 : enum ndr_err_code ndr_err;
636 0 : dump_data(0, plain_data.data, plain_data.length);
637 0 : if (save_values_dir) {
638 0 : char *fname;
639 0 : fname = talloc_asprintf(ctx, "%s/%s%02d",
640 : save_values_dir,
641 : name, object_id);
642 0 : if (fname) {
643 0 : bool ok;
644 0 : ok = file_save(fname, plain_data.data, plain_data.length);
645 0 : if (!ok) {
646 0 : DEBUGADD(0,("Failed to save '%s'\n", fname));
647 : }
648 : }
649 0 : talloc_free(fname);
650 : }
651 :
652 0 : if (pull_fn) {
653 : /* Can't use '_all' because of PIDL bugs with relative pointers */
654 0 : ndr_err = ndr_pull_struct_blob(&plain_data, ptr,
655 : ptr, pull_fn);
656 0 : if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
657 0 : (void)ndr_print_debug(1, print_fn, name, ptr, __location__, __func__);
658 : } else {
659 0 : DEBUG(0, ("Failed to decode %s\n", name));
660 : }
661 : }
662 : }
663 0 : talloc_free(ptr);
664 : }
665 : }
666 0 : talloc_free(objs);
667 0 : return true;
668 : }
669 :
670 9 : static bool test_GetNCChanges(struct torture_context *tctx,
671 : struct DsSyncTest *ctx,
672 : const char *nc_dn_str)
673 : {
674 0 : NTSTATUS status;
675 9 : bool ret = true;
676 9 : int i, y = 0;
677 9 : uint64_t highest_usn = 0;
678 0 : struct drsuapi_DsGetNCChanges r;
679 0 : union drsuapi_DsGetNCChangesRequest req;
680 0 : struct drsuapi_DsReplicaObjectIdentifier nc;
681 9 : struct drsuapi_DsGetNCChangesCtr1 *ctr1 = NULL;
682 9 : struct drsuapi_DsGetNCChangesCtr6 *ctr6 = NULL;
683 9 : uint32_t out_level = 0;
684 0 : struct dom_sid null_sid;
685 0 : DATA_BLOB gensec_skey;
686 0 : struct {
687 : uint32_t level;
688 9 : } array[] = {
689 : /* {
690 : 5
691 : },
692 : */ {
693 : 8
694 : }
695 : };
696 :
697 9 : ZERO_STRUCT(null_sid);
698 :
699 9 : highest_usn = lpcfg_parm_int(tctx->lp_ctx, NULL, "dssync", "highest_usn", 0);
700 :
701 9 : array[0].level = lpcfg_parm_int(tctx->lp_ctx, NULL, "dssync", "get_nc_changes_level", array[0].level);
702 :
703 9 : if (lpcfg_parm_bool(tctx->lp_ctx, NULL, "dssync", "print_pwd_blobs", false)) {
704 0 : const struct samr_Password *nthash;
705 0 : nthash = cli_credentials_get_nt_hash(ctx->new_dc.credentials, ctx);
706 0 : if (nthash) {
707 0 : dump_data_pw("CREDENTIALS nthash:", nthash->hash, sizeof(nthash->hash));
708 : }
709 : }
710 9 : status = gensec_session_key(ctx->new_dc.drsuapi.drs_pipe->conn->security_state.generic_state,
711 : ctx, &gensec_skey);
712 9 : if (!NT_STATUS_IS_OK(status)) {
713 0 : printf("failed to get gensec session key: %s\n", nt_errstr(status));
714 0 : return false;
715 : }
716 :
717 18 : for (i=0; i < ARRAY_SIZE(array); i++) {
718 9 : printf("Testing DsGetNCChanges level %d\n",
719 : array[i].level);
720 :
721 9 : r.in.bind_handle = &ctx->new_dc.drsuapi.bind_handle;
722 9 : r.in.level = array[i].level;
723 :
724 9 : switch (r.in.level) {
725 0 : case 5:
726 0 : nc.guid = GUID_zero();
727 0 : nc.sid = null_sid;
728 0 : nc.dn = nc_dn_str;
729 :
730 0 : r.in.req = &req;
731 0 : r.in.req->req5.destination_dsa_guid = ctx->new_dc.invocation_id;
732 0 : r.in.req->req5.source_dsa_invocation_id = GUID_zero();
733 0 : r.in.req->req5.naming_context = &nc;
734 0 : r.in.req->req5.highwatermark.tmp_highest_usn = highest_usn;
735 0 : r.in.req->req5.highwatermark.reserved_usn = 0;
736 0 : r.in.req->req5.highwatermark.highest_usn = highest_usn;
737 0 : r.in.req->req5.uptodateness_vector = NULL;
738 0 : r.in.req->req5.replica_flags = 0;
739 0 : if (lpcfg_parm_bool(tctx->lp_ctx, NULL, "dssync", "compression", false)) {
740 0 : r.in.req->req5.replica_flags |= DRSUAPI_DRS_USE_COMPRESSION;
741 : }
742 0 : if (lpcfg_parm_bool(tctx->lp_ctx, NULL, "dssync", "neighbour_writeable", true)) {
743 0 : r.in.req->req5.replica_flags |= DRSUAPI_DRS_WRIT_REP;
744 : }
745 0 : r.in.req->req5.replica_flags |= DRSUAPI_DRS_INIT_SYNC
746 : | DRSUAPI_DRS_PER_SYNC
747 : | DRSUAPI_DRS_GET_ANC
748 : | DRSUAPI_DRS_NEVER_SYNCED
749 : ;
750 0 : r.in.req->req5.max_object_count = 133;
751 0 : r.in.req->req5.max_ndr_size = 1336770;
752 0 : r.in.req->req5.extended_op = DRSUAPI_EXOP_NONE;
753 0 : r.in.req->req5.fsmo_info = 0;
754 :
755 0 : break;
756 9 : case 8:
757 9 : nc.guid = GUID_zero();
758 9 : nc.sid = null_sid;
759 9 : nc.dn = nc_dn_str;
760 : /* nc.dn can be set to any other ad partition */
761 :
762 9 : r.in.req = &req;
763 9 : r.in.req->req8.destination_dsa_guid = ctx->new_dc.invocation_id;
764 9 : r.in.req->req8.source_dsa_invocation_id = GUID_zero();
765 9 : r.in.req->req8.naming_context = &nc;
766 9 : r.in.req->req8.highwatermark.tmp_highest_usn = highest_usn;
767 9 : r.in.req->req8.highwatermark.reserved_usn = 0;
768 9 : r.in.req->req8.highwatermark.highest_usn = highest_usn;
769 9 : r.in.req->req8.uptodateness_vector = NULL;
770 9 : r.in.req->req8.replica_flags = 0;
771 9 : if (lpcfg_parm_bool(tctx->lp_ctx, NULL, "dssync", "compression", false)) {
772 0 : r.in.req->req8.replica_flags |= DRSUAPI_DRS_USE_COMPRESSION;
773 : }
774 9 : if (lpcfg_parm_bool(tctx->lp_ctx, NULL, "dssync", "neighbour_writeable", true)) {
775 9 : r.in.req->req8.replica_flags |= DRSUAPI_DRS_WRIT_REP;
776 : }
777 9 : r.in.req->req8.replica_flags |= DRSUAPI_DRS_INIT_SYNC
778 : | DRSUAPI_DRS_PER_SYNC
779 : | DRSUAPI_DRS_GET_ANC
780 : | DRSUAPI_DRS_NEVER_SYNCED
781 : ;
782 9 : r.in.req->req8.max_object_count = 402;
783 9 : r.in.req->req8.max_ndr_size = 402116;
784 :
785 9 : r.in.req->req8.extended_op = DRSUAPI_EXOP_NONE;
786 9 : r.in.req->req8.fsmo_info = 0;
787 9 : r.in.req->req8.partial_attribute_set = NULL;
788 9 : r.in.req->req8.partial_attribute_set_ex = NULL;
789 9 : r.in.req->req8.mapping_ctr.num_mappings = 0;
790 9 : r.in.req->req8.mapping_ctr.mappings = NULL;
791 :
792 9 : break;
793 : }
794 :
795 9 : for (y=0; ;y++) {
796 30 : uint32_t _level = 0;
797 0 : union drsuapi_DsGetNCChangesCtr ctr;
798 :
799 30 : ZERO_STRUCT(r.out);
800 :
801 30 : r.out.level_out = &_level;
802 30 : r.out.ctr = &ctr;
803 :
804 30 : if (r.in.level == 5) {
805 0 : torture_comment(tctx,
806 : "start[%d] tmp_higest_usn: %llu , highest_usn: %llu\n",
807 : y,
808 0 : (unsigned long long) r.in.req->req5.highwatermark.tmp_highest_usn,
809 0 : (unsigned long long) r.in.req->req5.highwatermark.highest_usn);
810 : }
811 :
812 30 : if (r.in.level == 8) {
813 30 : torture_comment(tctx,
814 : "start[%d] tmp_higest_usn: %llu , highest_usn: %llu\n",
815 : y,
816 30 : (unsigned long long) r.in.req->req8.highwatermark.tmp_highest_usn,
817 30 : (unsigned long long) r.in.req->req8.highwatermark.highest_usn);
818 : }
819 :
820 30 : status = dcerpc_drsuapi_DsGetNCChanges_r(ctx->new_dc.drsuapi.drs_handle, ctx, &r);
821 30 : torture_drsuapi_assert_call(tctx, ctx->new_dc.drsuapi.drs_pipe, status,
822 : &r, "dcerpc_drsuapi_DsGetNCChanges");
823 :
824 30 : if (ret == true && *r.out.level_out == 1) {
825 0 : out_level = 1;
826 0 : ctr1 = &r.out.ctr->ctr1;
827 30 : } else if (ret == true && *r.out.level_out == 2 &&
828 0 : r.out.ctr->ctr2.mszip1.ts) {
829 0 : out_level = 1;
830 0 : ctr1 = &r.out.ctr->ctr2.mszip1.ts->ctr1;
831 : }
832 :
833 30 : if (out_level == 1) {
834 0 : torture_comment(tctx,
835 : "end[%d] tmp_highest_usn: %llu , highest_usn: %llu\n",
836 : y,
837 0 : (unsigned long long) ctr1->new_highwatermark.tmp_highest_usn,
838 0 : (unsigned long long) ctr1->new_highwatermark.highest_usn);
839 :
840 0 : if (!test_analyse_objects(tctx, ctx, nc_dn_str, &ctr1->mapping_ctr, ctr1->object_count,
841 0 : ctr1->first_object, &gensec_skey)) {
842 0 : return false;
843 : }
844 :
845 0 : if (ctr1->more_data) {
846 0 : r.in.req->req5.highwatermark = ctr1->new_highwatermark;
847 21 : continue;
848 : }
849 : }
850 :
851 30 : if (ret == true && *r.out.level_out == 6) {
852 30 : out_level = 6;
853 30 : ctr6 = &r.out.ctr->ctr6;
854 0 : } else if (ret == true && *r.out.level_out == 7
855 0 : && r.out.ctr->ctr7.level == 6
856 0 : && r.out.ctr->ctr7.type == DRSUAPI_COMPRESSION_TYPE_MSZIP
857 0 : && r.out.ctr->ctr7.ctr.mszip6.ts) {
858 0 : out_level = 6;
859 0 : ctr6 = &r.out.ctr->ctr7.ctr.mszip6.ts->ctr6;
860 0 : } else if (ret == true && *r.out.level_out == 7
861 0 : && r.out.ctr->ctr7.level == 6
862 0 : && r.out.ctr->ctr7.type == DRSUAPI_COMPRESSION_TYPE_WIN2K3_LZ77_DIRECT2
863 0 : && r.out.ctr->ctr7.ctr.xpress6.ts) {
864 0 : out_level = 6;
865 0 : ctr6 = &r.out.ctr->ctr7.ctr.xpress6.ts->ctr6;
866 : }
867 :
868 30 : if (out_level == 6) {
869 30 : torture_comment(tctx,
870 : "end[%d] tmp_highest_usn: %llu , highest_usn: %llu\n",
871 : y,
872 30 : (unsigned long long) ctr6->new_highwatermark.tmp_highest_usn,
873 30 : (unsigned long long) ctr6->new_highwatermark.highest_usn);
874 :
875 30 : if (!test_analyse_objects(tctx, ctx, nc_dn_str, &ctr6->mapping_ctr, ctr6->object_count,
876 30 : ctr6->first_object, &gensec_skey)) {
877 0 : return false;
878 : }
879 :
880 30 : if (ctr6->more_data) {
881 21 : r.in.req->req8.highwatermark = ctr6->new_highwatermark;
882 21 : continue;
883 : }
884 : }
885 :
886 9 : break;
887 : }
888 : }
889 :
890 9 : return ret;
891 : }
892 :
893 : /**
894 : * Test DsGetNCChanges() DRSUAPI call against one
895 : * or more Naming Contexts.
896 : * Specific NC to test with may be supplied
897 : * in lp_ctx configuration. If no NC is specified,
898 : * it will test DsGetNCChanges() on all NCs on remote DC
899 : */
900 3 : static bool test_FetchData(struct torture_context *tctx, struct DsSyncTest *ctx)
901 : {
902 3 : bool ret = true;
903 0 : size_t i, count;
904 0 : const char *nc_dn_str;
905 0 : const char **nc_list;
906 :
907 3 : nc_list = const_str_list(str_list_make_empty(ctx));
908 3 : torture_assert(tctx, nc_list, "Not enough memory!");
909 :
910 : /* make a list of partitions to test with */
911 3 : nc_dn_str = lpcfg_parm_string(tctx->lp_ctx, NULL, "dssync", "partition");
912 3 : if (nc_dn_str == NULL) {
913 3 : nc_list = str_list_add_const(nc_list, ctx->domain_dn);
914 3 : nc_list = str_list_add_const(nc_list, ctx->config_dn);
915 3 : nc_list = str_list_add_const(nc_list, ctx->schema_dn);
916 : } else {
917 0 : nc_list = str_list_add_const(nc_list, nc_dn_str);
918 : }
919 :
920 3 : count = str_list_length(nc_list);
921 12 : for (i = 0; i < count && ret; i++) {
922 9 : torture_comment(tctx, "\nNaming Context: %s\n", nc_list[i]);
923 9 : ret = test_GetNCChanges(tctx, ctx, nc_list[i]);
924 : }
925 :
926 3 : talloc_free(nc_list);
927 3 : return ret;
928 : }
929 :
930 :
931 3 : static bool test_FetchNT4Data(struct torture_context *tctx,
932 : struct DsSyncTest *ctx)
933 : {
934 0 : NTSTATUS status;
935 0 : struct drsuapi_DsGetNT4ChangeLog r;
936 0 : union drsuapi_DsGetNT4ChangeLogRequest req;
937 0 : union drsuapi_DsGetNT4ChangeLogInfo info;
938 3 : uint32_t level_out = 0;
939 0 : DATA_BLOB cookie;
940 :
941 3 : ZERO_STRUCT(cookie);
942 :
943 3 : ZERO_STRUCT(r);
944 3 : r.in.bind_handle = &ctx->new_dc.drsuapi.bind_handle;
945 3 : r.in.level = 1;
946 3 : r.out.info = &info;
947 3 : r.out.level_out = &level_out;
948 :
949 3 : req.req1.flags = lpcfg_parm_int(tctx->lp_ctx, NULL,
950 : "dssync", "nt4changelog_flags",
951 : DRSUAPI_NT4_CHANGELOG_GET_CHANGELOG |
952 : DRSUAPI_NT4_CHANGELOG_GET_SERIAL_NUMBERS);
953 3 : req.req1.preferred_maximum_length = lpcfg_parm_int(tctx->lp_ctx, NULL,
954 : "dssync", "nt4changelog_preferred_len",
955 : 0x00004000);
956 :
957 0 : while (1) {
958 3 : req.req1.restart_length = cookie.length;
959 3 : req.req1.restart_data = cookie.data;
960 :
961 3 : r.in.req = &req;
962 :
963 3 : status = dcerpc_drsuapi_DsGetNT4ChangeLog_r(ctx->new_dc.drsuapi.drs_handle, ctx, &r);
964 3 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
965 3 : torture_skip(tctx,
966 : "DsGetNT4ChangeLog not supported: NT_STATUS_NOT_IMPLEMENTED");
967 3 : } else if (!NT_STATUS_IS_OK(status)) {
968 3 : const char *errstr = nt_errstr(status);
969 3 : if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
970 3 : torture_skip(tctx,
971 : "DsGetNT4ChangeLog not supported: NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE");
972 : }
973 0 : torture_fail(tctx,
974 : talloc_asprintf(tctx, "dcerpc_drsuapi_DsGetNT4ChangeLog failed - %s\n",
975 : errstr));
976 0 : } else if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_DOMAIN_ROLE)) {
977 0 : torture_skip(tctx,
978 : "DsGetNT4ChangeLog not supported: WERR_INVALID_DOMAIN_ROLE");
979 0 : } else if (!W_ERROR_IS_OK(r.out.result)) {
980 0 : torture_fail(tctx,
981 : talloc_asprintf(tctx, "DsGetNT4ChangeLog failed - %s\n",
982 : win_errstr(r.out.result)));
983 0 : } else if (*r.out.level_out != 1) {
984 0 : torture_fail(tctx,
985 : talloc_asprintf(tctx, "DsGetNT4ChangeLog unknown level - %u\n",
986 : *r.out.level_out));
987 0 : } else if (NT_STATUS_IS_OK(r.out.info->info1.status)) {
988 0 : } else if (NT_STATUS_EQUAL(r.out.info->info1.status, STATUS_MORE_ENTRIES)) {
989 0 : cookie.length = r.out.info->info1.restart_length;
990 0 : cookie.data = r.out.info->info1.restart_data;
991 0 : continue;
992 : } else {
993 0 : torture_fail(tctx,
994 : talloc_asprintf(tctx, "DsGetNT4ChangeLog failed - %s\n",
995 : nt_errstr(r.out.info->info1.status)));
996 : }
997 :
998 0 : break;
999 : }
1000 :
1001 0 : return true;
1002 : }
1003 :
1004 : /**
1005 : * DSSYNC test case setup
1006 : */
1007 3 : static bool torture_dssync_tcase_setup(struct torture_context *tctx, void **data)
1008 : {
1009 0 : bool bret;
1010 0 : struct DsSyncTest *ctx;
1011 :
1012 3 : *data = ctx = test_create_context(tctx);
1013 3 : torture_assert(tctx, ctx, "test_create_context() failed");
1014 :
1015 3 : bret = _test_DsBind(tctx, ctx, ctx->admin.credentials, &ctx->admin.drsuapi);
1016 3 : torture_assert(tctx, bret, "_test_DsBind() failed");
1017 :
1018 3 : bret = test_LDAPBind(tctx, ctx, ctx->admin.credentials, &ctx->admin.ldap);
1019 3 : torture_assert(tctx, bret, "test_LDAPBind() failed");
1020 :
1021 3 : bret = test_GetInfo(tctx, ctx);
1022 3 : torture_assert(tctx, bret, "test_GetInfo() failed");
1023 :
1024 3 : bret = _test_DsBind(tctx, ctx, ctx->new_dc.credentials, &ctx->new_dc.drsuapi);
1025 3 : torture_assert(tctx, bret, "_test_DsBind() failed");
1026 :
1027 3 : return true;
1028 : }
1029 :
1030 : /**
1031 : * DSSYNC test case cleanup
1032 : */
1033 3 : static bool torture_dssync_tcase_teardown(struct torture_context *tctx, void *data)
1034 : {
1035 0 : struct DsSyncTest *ctx;
1036 0 : struct drsuapi_DsUnbind r;
1037 0 : struct policy_handle bind_handle;
1038 :
1039 3 : ctx = talloc_get_type(data, struct DsSyncTest);
1040 :
1041 3 : ZERO_STRUCT(r);
1042 3 : r.out.bind_handle = &bind_handle;
1043 :
1044 : /* Unbing admin handle */
1045 3 : r.in.bind_handle = &ctx->admin.drsuapi.bind_handle;
1046 3 : dcerpc_drsuapi_DsUnbind_r(ctx->admin.drsuapi.drs_handle, ctx, &r);
1047 :
1048 : /* Unbing new_dc handle */
1049 3 : r.in.bind_handle = &ctx->new_dc.drsuapi.bind_handle;
1050 3 : dcerpc_drsuapi_DsUnbind_r(ctx->new_dc.drsuapi.drs_handle, ctx, &r);
1051 :
1052 3 : talloc_free(ctx);
1053 :
1054 3 : return true;
1055 : }
1056 :
1057 : /**
1058 : * DSSYNC test case implementation
1059 : */
1060 2358 : void torture_drs_rpc_dssync_tcase(struct torture_suite *suite)
1061 : {
1062 125 : typedef bool (*run_func) (struct torture_context *test, void *tcase_data);
1063 2358 : struct torture_tcase *tcase = torture_suite_add_tcase(suite, "dssync");
1064 :
1065 2358 : torture_tcase_set_fixture(tcase,
1066 : torture_dssync_tcase_setup,
1067 : torture_dssync_tcase_teardown);
1068 :
1069 2358 : torture_tcase_add_simple_test(tcase, "DC_FetchData", (run_func)test_FetchData);
1070 2358 : torture_tcase_add_simple_test(tcase, "FetchNT4Data", (run_func)test_FetchNT4Data);
1071 2358 : }
1072 :
|