2 Unix SMB/CIFS implementation.
6 Copyright (C) Andrew Tridgell 2003
7 Copyright (C) Stefan (metze) Metzmacher 2004
8 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2006
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "torture/torture.h"
26 #include "librpc/gen_ndr/ndr_drsuapi_c.h"
27 #include "torture/rpc/rpc.h"
28 #include "param/param.h"
30 #define TEST_MACHINE_NAME "torturetest"
32 bool test_DsBind(struct dcerpc_pipe *p,
33 struct torture_context *tctx,
34 struct DsPrivate *priv)
37 struct drsuapi_DsBind r;
39 GUID_from_string(DRSUAPI_DS_BIND_GUID, &priv->bind_guid);
41 r.in.bind_guid = &priv->bind_guid;
42 r.in.bind_info = NULL;
43 r.out.bind_handle = &priv->bind_handle;
45 torture_comment(tctx, "testing DsBind\n");
47 status = dcerpc_drsuapi_DsBind(p, tctx, &r);
48 if (!NT_STATUS_IS_OK(status)) {
49 const char *errstr = nt_errstr(status);
50 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
51 errstr = dcerpc_errstr(tctx, p->last_fault_code);
53 torture_fail(tctx, "dcerpc_drsuapi_DsBind failed");
54 } else if (!W_ERROR_IS_OK(r.out.result)) {
55 torture_fail(tctx, "DsBind failed");
61 static bool test_DsGetDomainControllerInfo(struct dcerpc_pipe *p,
62 struct torture_context *tctx,
63 struct DsPrivate *priv)
66 struct drsuapi_DsGetDomainControllerInfo r;
67 union drsuapi_DsGetDCInfoCtr ctr;
68 int32_t level_out = 0;
77 .name = torture_join_dom_netbios_name(priv->join),
81 .name = torture_join_dom_dns_name(priv->join),
85 .name = "__UNKNOWN_DOMAIN__",
86 .expected = WERR_DS_OBJ_NOT_FOUND
89 .name = "unknown.domain.samba.example.com",
90 .expected = WERR_DS_OBJ_NOT_FOUND
93 int levels[] = {1, 2};
96 for (i=0; i < ARRAY_SIZE(levels); i++) {
97 for (j=0; j < ARRAY_SIZE(names); j++) {
98 union drsuapi_DsGetDCInfoRequest req;
100 r.in.bind_handle = &priv->bind_handle;
104 r.in.req->req1.domain_name = names[j].name;
105 r.in.req->req1.level = level;
108 r.out.level_out = &level_out;
110 torture_comment(tctx,
111 "testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
112 r.in.req->req1.level, r.in.req->req1.domain_name);
114 status = dcerpc_drsuapi_DsGetDomainControllerInfo(p, tctx, &r);
115 torture_assert_ntstatus_ok(tctx, status,
116 "dcerpc_drsuapi_DsGetDomainControllerInfo with dns domain failed");
117 torture_assert_werr_equal(tctx,
118 r.out.result, names[j].expected,
119 "DsGetDomainControllerInfo level with dns domain failed");
121 if (!W_ERROR_IS_OK(r.out.result)) {
122 /* If this was an error, we can't read the result structure */
126 torture_assert_int_equal(tctx,
127 r.in.req->req1.level, *r.out.level_out,
128 "dcerpc_drsuapi_DsGetDomainControllerInfo in/out level differs");
132 for (k=0; k < r.out.ctr->ctr1.count; k++) {
133 if (strcasecmp_m(r.out.ctr->ctr1.array[k].netbios_name,
134 torture_join_netbios_name(priv->join)) == 0) {
141 for (k=0; k < r.out.ctr->ctr2.count; k++) {
142 if (strcasecmp_m(r.out.ctr->ctr2.array[k].netbios_name,
143 torture_join_netbios_name(priv->join)) == 0) {
145 priv->dcinfo = r.out.ctr->ctr2.array[k];
151 torture_assert(tctx, found,
152 "dcerpc_drsuapi_DsGetDomainControllerInfo: Failed to find the domain controller we just created during the join");
156 r.in.bind_handle = &priv->bind_handle;
160 r.out.level_out = &level_out;
162 r.in.req->req1.domain_name = "__UNKNOWN_DOMAIN__"; /* This is clearly ignored for this level */
163 r.in.req->req1.level = -1;
165 torture_comment(tctx, "testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
166 r.in.req->req1.level, r.in.req->req1.domain_name);
168 status = dcerpc_drsuapi_DsGetDomainControllerInfo(p, tctx, &r);
170 torture_assert_ntstatus_ok(tctx, status,
171 "dcerpc_drsuapi_DsGetDomainControllerInfo with dns domain failed");
172 torture_assert_werr_ok(tctx, r.out.result,
173 "DsGetDomainControllerInfo with dns domain failed");
176 const char *dc_account = talloc_asprintf(tctx, "%s\\%s$",
177 torture_join_dom_netbios_name(priv->join),
178 priv->dcinfo.netbios_name);
179 torture_comment(tctx, "%s: Enum active LDAP sessions searching for %s\n", __func__, dc_account);
180 for (k=0; k < r.out.ctr->ctr01.count; k++) {
181 if (strcasecmp_m(r.out.ctr->ctr01.array[k].client_account,
187 torture_assert(tctx, found,
188 "dcerpc_drsuapi_DsGetDomainControllerInfo level: Failed to find the domain controller in last logon records");
195 static bool test_DsWriteAccountSpn(struct dcerpc_pipe *p,
196 struct torture_context *tctx,
197 struct DsPrivate *priv)
200 struct drsuapi_DsWriteAccountSpn r;
201 union drsuapi_DsWriteAccountSpnRequest req;
202 struct drsuapi_DsNameString names[2];
203 union drsuapi_DsWriteAccountSpnResult res;
207 r.in.bind_handle = &priv->bind_handle;
211 torture_comment(tctx, "testing DsWriteAccountSpn\n");
213 r.in.req->req1.operation = DRSUAPI_DS_SPN_OPERATION_ADD;
214 r.in.req->req1.unknown1 = 0;
215 r.in.req->req1.object_dn = priv->dcinfo.computer_dn;
216 r.in.req->req1.count = 2;
217 r.in.req->req1.spn_names = names;
218 names[0].str = talloc_asprintf(tctx, "smbtortureSPN/%s",priv->dcinfo.netbios_name);
219 names[1].str = talloc_asprintf(tctx, "smbtortureSPN/%s",priv->dcinfo.dns_name);
222 r.out.level_out = &level_out;
224 status = dcerpc_drsuapi_DsWriteAccountSpn(p, tctx, &r);
225 if (!NT_STATUS_IS_OK(status)) {
226 const char *errstr = nt_errstr(status);
227 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
228 errstr = dcerpc_errstr(tctx, p->last_fault_code);
230 printf("dcerpc_drsuapi_DsWriteAccountSpn failed - %s\n", errstr);
232 } else if (!W_ERROR_IS_OK(r.out.result)) {
233 printf("DsWriteAccountSpn failed - %s\n", win_errstr(r.out.result));
237 r.in.req->req1.operation = DRSUAPI_DS_SPN_OPERATION_DELETE;
238 r.in.req->req1.unknown1 = 0;
240 status = dcerpc_drsuapi_DsWriteAccountSpn(p, tctx, &r);
241 if (!NT_STATUS_IS_OK(status)) {
242 const char *errstr = nt_errstr(status);
243 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
244 errstr = dcerpc_errstr(tctx, p->last_fault_code);
246 printf("dcerpc_drsuapi_DsWriteAccountSpn failed - %s\n", errstr);
248 } else if (!W_ERROR_IS_OK(r.out.result)) {
249 printf("DsWriteAccountSpn failed - %s\n", win_errstr(r.out.result));
256 static bool test_DsReplicaGetInfo(struct dcerpc_pipe *p,
257 struct torture_context *tctx,
258 struct DsPrivate *priv)
261 struct drsuapi_DsReplicaGetInfo r;
262 union drsuapi_DsReplicaGetInfoRequest req;
263 union drsuapi_DsReplicaInfo info;
264 enum drsuapi_DsReplicaInfoType info_type;
273 DRSUAPI_DS_REPLICA_GET_INFO,
274 DRSUAPI_DS_REPLICA_INFO_NEIGHBORS,
277 DRSUAPI_DS_REPLICA_GET_INFO,
278 DRSUAPI_DS_REPLICA_INFO_CURSORS,
281 DRSUAPI_DS_REPLICA_GET_INFO,
282 DRSUAPI_DS_REPLICA_INFO_OBJ_METADATA,
285 DRSUAPI_DS_REPLICA_GET_INFO,
286 DRSUAPI_DS_REPLICA_INFO_KCC_DSA_CONNECT_FAILURES,
289 DRSUAPI_DS_REPLICA_GET_INFO,
290 DRSUAPI_DS_REPLICA_INFO_KCC_DSA_LINK_FAILURES,
293 DRSUAPI_DS_REPLICA_GET_INFO,
294 DRSUAPI_DS_REPLICA_INFO_PENDING_OPS,
297 DRSUAPI_DS_REPLICA_GET_INFO2,
298 DRSUAPI_DS_REPLICA_INFO_ATTRIBUTE_VALUE_METADATA,
301 DRSUAPI_DS_REPLICA_GET_INFO2,
302 DRSUAPI_DS_REPLICA_INFO_CURSORS2,
305 DRSUAPI_DS_REPLICA_GET_INFO2,
306 DRSUAPI_DS_REPLICA_INFO_CURSORS3,
309 DRSUAPI_DS_REPLICA_GET_INFO2,
310 DRSUAPI_DS_REPLICA_INFO_OBJ_METADATA2,
313 DRSUAPI_DS_REPLICA_GET_INFO2,
314 DRSUAPI_DS_REPLICA_INFO_ATTRIBUTE_VALUE_METADATA2,
317 DRSUAPI_DS_REPLICA_GET_INFO2,
318 DRSUAPI_DS_REPLICA_INFO_NEIGHBORS02,
321 DRSUAPI_DS_REPLICA_GET_INFO2,
322 DRSUAPI_DS_REPLICA_INFO_CONNECTIONS04,
325 DRSUAPI_DS_REPLICA_GET_INFO2,
326 DRSUAPI_DS_REPLICA_INFO_CURSORS05,
329 DRSUAPI_DS_REPLICA_GET_INFO2,
330 DRSUAPI_DS_REPLICA_INFO_06,
335 if (torture_setting_bool(tctx, "samba4", false)) {
336 torture_comment(tctx, "skipping DsReplicaGetInfo test against Samba4\n");
340 r.in.bind_handle = &priv->bind_handle;
343 for (i=0; i < ARRAY_SIZE(array); i++) {
344 const char *object_dn;
346 torture_comment(tctx, "testing DsReplicaGetInfo level %d infotype %d\n",
347 array[i].level, array[i].infotype);
349 object_dn = (array[i].obj_dn ? array[i].obj_dn : priv->domain_obj_dn);
351 r.in.level = array[i].level;
353 case DRSUAPI_DS_REPLICA_GET_INFO:
354 r.in.req->req1.info_type = array[i].infotype;
355 r.in.req->req1.object_dn = object_dn;
356 ZERO_STRUCT(r.in.req->req1.guid1);
358 case DRSUAPI_DS_REPLICA_GET_INFO2:
359 r.in.req->req2.info_type = array[i].infotype;
360 r.in.req->req2.object_dn = object_dn;
361 ZERO_STRUCT(r.in.req->req2.guid1);
362 r.in.req->req2.unknown1 = 0;
363 r.in.req->req2.string1 = NULL;
364 r.in.req->req2.string2 = NULL;
365 r.in.req->req2.unknown2 = 0;
370 r.out.info_type = &info_type;
372 status = dcerpc_drsuapi_DsReplicaGetInfo(p, tctx, &r);
373 torture_drsuapi_assert_call(tctx, p, status, &r, "dcerpc_drsuapi_DsReplicaGetInfo");
374 if (!NT_STATUS_IS_OK(status)) {
375 const char *errstr = nt_errstr(status);
376 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
377 errstr = dcerpc_errstr(tctx, p->last_fault_code);
379 if (p->last_fault_code != DCERPC_FAULT_INVALID_TAG) {
380 printf("dcerpc_drsuapi_DsReplicaGetInfo failed - %s\n", errstr);
383 printf("DsReplicaGetInfo level %d and/or infotype %d not supported by server\n",
384 array[i].level, array[i].infotype);
386 } else if (!W_ERROR_IS_OK(r.out.result)) {
387 printf("DsReplicaGetInfo failed - %s\n", win_errstr(r.out.result));
395 static bool test_DsReplicaSync(struct dcerpc_pipe *p,
396 struct torture_context *tctx,
397 struct DsPrivate *priv)
402 struct drsuapi_DsReplicaSync r;
403 struct drsuapi_DsReplicaObjectIdentifier nc;
404 struct GUID null_guid;
405 struct dom_sid null_sid;
414 if (!torture_setting_bool(tctx, "dangerous", false)) {
415 torture_comment(tctx, "DsReplicaSync disabled - enable dangerous tests to use\n");
419 if (torture_setting_bool(tctx, "samba4", false)) {
420 torture_comment(tctx, "skipping DsReplicaSync test against Samba4\n");
424 ZERO_STRUCT(null_guid);
425 ZERO_STRUCT(null_sid);
427 r.in.bind_handle = &priv->bind_handle;
429 for (i=0; i < ARRAY_SIZE(array); i++) {
430 torture_comment(tctx, "testing DsReplicaSync level %d\n",
433 r.in.level = array[i].level;
438 nc.dn = priv->domain_obj_dn?priv->domain_obj_dn:"";
440 r.in.req.req1.naming_context = &nc;
441 r.in.req.req1.source_dsa_guid = priv->dcinfo.ntds_guid;
442 r.in.req.req1.other_info = NULL;
443 r.in.req.req1.options = 16;
447 status = dcerpc_drsuapi_DsReplicaSync(p, tctx, &r);
448 if (!NT_STATUS_IS_OK(status)) {
449 const char *errstr = nt_errstr(status);
450 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
451 errstr = dcerpc_errstr(tctx, p->last_fault_code);
453 printf("dcerpc_drsuapi_DsReplicaSync failed - %s\n", errstr);
455 } else if (!W_ERROR_IS_OK(r.out.result)) {
456 printf("DsReplicaSync failed - %s\n", win_errstr(r.out.result));
464 static bool test_DsReplicaUpdateRefs(struct dcerpc_pipe *p, struct torture_context *tctx,
465 struct DsPrivate *priv)
470 struct drsuapi_DsReplicaUpdateRefs r;
471 struct drsuapi_DsReplicaObjectIdentifier nc;
472 struct GUID null_guid;
473 struct dom_sid null_sid;
482 if (torture_setting_bool(tctx, "samba4", false)) {
483 torture_comment(tctx, "skipping DsReplicaUpdateRefs test against Samba4\n");
487 ZERO_STRUCT(null_guid);
488 ZERO_STRUCT(null_sid);
490 r.in.bind_handle = &priv->bind_handle;
492 for (i=0; i < ARRAY_SIZE(array); i++) {
493 torture_comment(tctx, "testing DsReplicaUpdateRefs level %d\n",
496 r.in.level = array[i].level;
501 nc.dn = priv->domain_obj_dn ? priv->domain_obj_dn : "";
503 r.in.req.req1.naming_context = &nc;
504 r.in.req.req1.dest_dsa_dns_name = talloc_asprintf(tctx, "__some_dest_dsa_guid_string._msdn.%s",
505 priv->domain_dns_name);
506 r.in.req.req1.dest_dsa_guid = null_guid;
507 r.in.req.req1.options = 0;
511 status = dcerpc_drsuapi_DsReplicaUpdateRefs(p, tctx, &r);
512 if (!NT_STATUS_IS_OK(status)) {
513 const char *errstr = nt_errstr(status);
514 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
515 errstr = dcerpc_errstr(tctx, p->last_fault_code);
517 printf("dcerpc_drsuapi_DsReplicaUpdateRefs failed - %s\n", errstr);
519 } else if (!W_ERROR_IS_OK(r.out.result)) {
520 printf("DsReplicaUpdateRefs failed - %s\n", win_errstr(r.out.result));
528 static bool test_DsGetNCChanges(struct dcerpc_pipe *p,
529 struct torture_context *tctx,
530 struct DsPrivate *priv)
535 struct drsuapi_DsGetNCChanges r;
536 union drsuapi_DsGetNCChangesRequest req;
537 union drsuapi_DsGetNCChangesCtr ctr;
538 struct drsuapi_DsReplicaObjectIdentifier nc;
539 struct GUID null_guid;
540 struct dom_sid null_sid;
553 if (torture_setting_bool(tctx, "samba4", false)) {
554 torture_comment(tctx, "skipping DsGetNCChanges test against Samba4\n");
558 ZERO_STRUCT(null_guid);
559 ZERO_STRUCT(null_sid);
561 for (i=0; i < ARRAY_SIZE(array); i++) {
562 torture_comment(tctx,
563 "testing DsGetNCChanges level %d\n",
566 r.in.bind_handle = &priv->bind_handle;
567 r.in.level = array[i].level;
568 r.out.level_out = &level_out;
571 switch (r.in.level) {
575 nc.dn = priv->domain_obj_dn ? priv->domain_obj_dn : "";
578 r.in.req->req5.destination_dsa_guid = GUID_random();
579 r.in.req->req5.source_dsa_invocation_id = null_guid;
580 r.in.req->req5.naming_context = &nc;
581 r.in.req->req5.highwatermark.tmp_highest_usn = 0;
582 r.in.req->req5.highwatermark.reserved_usn = 0;
583 r.in.req->req5.highwatermark.highest_usn = 0;
584 r.in.req->req5.uptodateness_vector = NULL;
585 r.in.req->req5.replica_flags = 0;
586 if (lp_parm_bool(tctx->lp_ctx, NULL, "drsuapi", "compression", false)) {
587 r.in.req->req5.replica_flags |= DRSUAPI_DS_REPLICA_NEIGHBOUR_COMPRESS_CHANGES;
589 r.in.req->req5.max_object_count = 0;
590 r.in.req->req5.max_ndr_size = 0;
591 r.in.req->req5.extended_op = DRSUAPI_EXOP_NONE;
592 r.in.req->req5.fsmo_info = 0;
598 nc.dn = priv->domain_obj_dn ? priv->domain_obj_dn : "";
601 r.in.req->req8.destination_dsa_guid = GUID_random();
602 r.in.req->req8.source_dsa_invocation_id = null_guid;
603 r.in.req->req8.naming_context = &nc;
604 r.in.req->req8.highwatermark.tmp_highest_usn = 0;
605 r.in.req->req8.highwatermark.reserved_usn = 0;
606 r.in.req->req8.highwatermark.highest_usn = 0;
607 r.in.req->req8.uptodateness_vector = NULL;
608 r.in.req->req8.replica_flags = 0;
609 if (lp_parm_bool(tctx->lp_ctx, NULL, "drsuapi", "compression", false)) {
610 r.in.req->req8.replica_flags |= DRSUAPI_DS_REPLICA_NEIGHBOUR_COMPRESS_CHANGES;
612 if (lp_parm_bool(tctx->lp_ctx, NULL, "drsuapi", "neighbour_writeable", true)) {
613 r.in.req->req8.replica_flags |= DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE;
615 r.in.req->req8.replica_flags |= DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
616 | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS
617 | DRSUAPI_DS_REPLICA_NEIGHBOUR_RETURN_OBJECT_PARENTS
618 | DRSUAPI_DS_REPLICA_NEIGHBOUR_NEVER_SYNCED
620 r.in.req->req8.max_object_count = 402;
621 r.in.req->req8.max_ndr_size = 402116;
622 r.in.req->req8.extended_op = DRSUAPI_EXOP_NONE;
623 r.in.req->req8.fsmo_info = 0;
624 r.in.req->req8.partial_attribute_set = NULL;
625 r.in.req->req8.partial_attribute_set_ex = NULL;
626 r.in.req->req8.mapping_ctr.num_mappings = 0;
627 r.in.req->req8.mapping_ctr.mappings = NULL;
632 status = dcerpc_drsuapi_DsGetNCChanges(p, tctx, &r);
633 if (!NT_STATUS_IS_OK(status)) {
634 const char *errstr = nt_errstr(status);
635 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
636 errstr = dcerpc_errstr(tctx, p->last_fault_code);
638 printf("dcerpc_drsuapi_DsGetNCChanges failed - %s\n", errstr);
640 } else if (!W_ERROR_IS_OK(r.out.result)) {
641 printf("DsGetNCChanges failed - %s\n", win_errstr(r.out.result));
649 bool test_QuerySitesByCost(struct dcerpc_pipe *p,
650 struct torture_context *tctx,
651 struct DsPrivate *priv)
654 struct drsuapi_QuerySitesByCost r;
655 union drsuapi_QuerySitesByCostRequest req;
658 const char *my_site = "Default-First-Site-Name";
659 const char *remote_site1 = "smbtorture-nonexisting-site1";
660 const char *remote_site2 = "smbtorture-nonexisting-site2";
662 req.req1.site_from = talloc_strdup(tctx, my_site);
663 req.req1.num_req = 2;
664 req.req1.site_to = talloc_zero_array(tctx, const char *, 2);
665 req.req1.site_to[0] = talloc_strdup(tctx, remote_site1);
666 req.req1.site_to[1] = talloc_strdup(tctx, remote_site2);
669 r.in.bind_handle = &priv->bind_handle;
673 status = dcerpc_drsuapi_QuerySitesByCost(p, tctx, &r);
674 if (!NT_STATUS_IS_OK(status)) {
675 const char *errstr = nt_errstr(status);
676 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
677 errstr = dcerpc_errstr(tctx, p->last_fault_code);
679 printf("drsuapi_QuerySitesByCost - %s\n", errstr);
681 } else if (!W_ERROR_IS_OK(r.out.result)) {
682 printf("QuerySitesByCost failed - %s\n", win_errstr(r.out.result));
686 if (W_ERROR_IS_OK(r.out.result)) {
688 if (!W_ERROR_EQUAL(r.out.ctr->ctr1.info[0].error_code, WERR_DS_OBJ_NOT_FOUND) ||
689 !W_ERROR_EQUAL(r.out.ctr->ctr1.info[1].error_code, WERR_DS_OBJ_NOT_FOUND)) {
690 torture_comment(tctx,
691 "expected error_code WERR_DS_OBJ_NOT_FOUND, got %s\n",
692 win_errstr(r.out.ctr->ctr1.info[0].error_code));
696 if ((r.out.ctr->ctr1.info[0].site_cost != (uint32_t) -1) ||
697 (r.out.ctr->ctr1.info[1].site_cost != (uint32_t) -1)) {
698 torture_comment(tctx,
699 "expected site_cost %d, got %d\n",
700 (uint32_t)-1, r.out.ctr->ctr1.info[0].site_cost);
710 bool test_DsUnbind(struct dcerpc_pipe *p,
711 struct torture_context *tctx,
712 struct DsPrivate *priv)
715 struct drsuapi_DsUnbind r;
718 r.in.bind_handle = &priv->bind_handle;
719 r.out.bind_handle = &priv->bind_handle;
721 torture_comment(tctx, "testing DsUnbind\n");
723 status = dcerpc_drsuapi_DsUnbind(p, tctx, &r);
724 if (!NT_STATUS_IS_OK(status)) {
725 const char *errstr = nt_errstr(status);
726 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
727 errstr = dcerpc_errstr(tctx, p->last_fault_code);
729 printf("dcerpc_drsuapi_DsUnbind failed - %s\n", errstr);
731 } else if (!W_ERROR_IS_OK(r.out.result)) {
732 printf("DsBind failed - %s\n", win_errstr(r.out.result));
739 bool torture_rpc_drsuapi(struct torture_context *torture)
742 struct dcerpc_pipe *p;
744 struct DsPrivate *priv;
745 struct cli_credentials *machine_credentials;
747 priv = talloc_zero(torture, struct DsPrivate);
749 priv->join = torture_join_domain(torture, TEST_MACHINE_NAME, ACB_SVRTRUST,
750 &machine_credentials);
752 torture_fail(torture, "Failed to join as BDC");
755 status = torture_rpc_connection(torture,
758 if (!NT_STATUS_IS_OK(status)) {
759 torture_leave_domain(torture, priv->join);
760 torture_fail(torture, "Unable to connect to DRSUAPI pipe");
763 /* cache pipe handle */
766 ret &= test_DsBind(p, torture, priv);
768 ret &= test_QuerySitesByCost(p, torture, priv);
770 ret &= test_DsGetDomainControllerInfo(p, torture, priv);
772 ret &= test_DsCrackNames(torture, priv);
774 ret &= test_DsWriteAccountSpn(p, torture, priv);
776 ret &= test_DsReplicaGetInfo(p, torture, priv);
778 ret &= test_DsReplicaSync(p, torture, priv);
780 ret &= test_DsReplicaUpdateRefs(p, torture, priv);
782 ret &= test_DsGetNCChanges(p, torture, priv);
784 ret &= test_DsUnbind(p, torture, priv);
786 torture_leave_domain(torture, priv->join);
794 * Helper func to collect DC information for testing purposes.
795 * This function is almost identical to test_DsGetDomainControllerInfo
797 bool torture_rpc_drsuapi_get_dcinfo(struct torture_context *torture,
798 struct DsPrivate *priv)
801 int32_t level_out = 0;
802 struct drsuapi_DsGetDomainControllerInfo r;
803 union drsuapi_DsGetDCInfoCtr ctr;
805 const char *names[] = {
806 torture_join_dom_netbios_name(priv->join),
807 torture_join_dom_dns_name(priv->join)};
809 for (j=0; j < ARRAY_SIZE(names); j++) {
810 union drsuapi_DsGetDCInfoRequest req;
811 r.in.bind_handle = &priv->bind_handle;
815 r.in.req->req1.domain_name = names[j];
816 r.in.req->req1.level = 2;
819 r.out.level_out = &level_out;
821 status = dcerpc_drsuapi_DsGetDomainControllerInfo(priv->pipe, torture, &r);
822 if (!NT_STATUS_IS_OK(status)) {
825 if (!W_ERROR_IS_OK(r.out.result)) {
826 /* If this was an error, we can't read the result structure */
830 for (k=0; k < r.out.ctr->ctr2.count; k++) {
831 if (strcasecmp_m(r.out.ctr->ctr2.array[k].netbios_name,
832 torture_join_netbios_name(priv->join)) == 0) {
833 priv->dcinfo = r.out.ctr->ctr2.array[k];
843 * Common test case setup function to be used
844 * in DRS suit of test when appropriate
846 bool torture_drsuapi_tcase_setup_common(struct torture_context *tctx, struct DsPrivate *priv)
849 struct cli_credentials *machine_credentials;
851 torture_assert(tctx, priv, "Invalid argument");
853 torture_comment(tctx, "Create DRSUAPI pipe\n");
854 status = torture_rpc_connection(tctx,
857 torture_assert(tctx, NT_STATUS_IS_OK(status), "Unable to connect to DRSUAPI pipe");
859 torture_comment(tctx, "About to join domain\n");
860 priv->join = torture_join_domain(tctx, TEST_MACHINE_NAME, ACB_SVRTRUST,
861 &machine_credentials);
862 torture_assert(tctx, priv->join, "Failed to join as BDC");
864 if (!test_DsBind(priv->pipe, tctx, priv)) {
866 torture_drsuapi_tcase_teardown_common(tctx, priv);
867 torture_fail(tctx, "Failed execute test_DsBind()");
870 /* try collect some information for testing */
871 torture_rpc_drsuapi_get_dcinfo(tctx, priv);
877 * Common test case teardown function to be used
878 * in DRS suit of test when appropriate
880 bool torture_drsuapi_tcase_teardown_common(struct torture_context *tctx, struct DsPrivate *priv)
883 torture_leave_domain(tctx, priv->join);