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