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
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 2 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, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include "torture/torture.h"
27 #include "librpc/gen_ndr/ndr_drsuapi.h"
28 #include "auth/credentials/credentials.h"
29 #include "torture/rpc/drsuapi.h"
30 #include "torture/rpc/proto.h"
32 BOOL test_DsBind(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
33 struct DsPrivate *priv)
36 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 printf("testing DsBind\n");
47 status = dcerpc_drsuapi_DsBind(p, mem_ctx, &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(mem_ctx, p->last_fault_code);
53 printf("dcerpc_drsuapi_DsBind failed - %s\n", errstr);
55 } else if (!W_ERROR_IS_OK(r.out.result)) {
56 printf("DsBind failed - %s\n", win_errstr(r.out.result));
63 static BOOL test_DsGetDCInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
64 struct DsPrivate *priv)
67 struct drsuapi_DsGetDomainControllerInfo r;
70 r.in.bind_handle = &priv->bind_handle;
73 r.in.req.req1.domain_name = talloc_strdup(mem_ctx, lp_realm());
74 r.in.req.req1.level = 1;
76 printf("testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
77 r.in.req.req1.level, r.in.req.req1.domain_name);
79 status = dcerpc_drsuapi_DsGetDomainControllerInfo(p, mem_ctx, &r);
80 if (!NT_STATUS_IS_OK(status)) {
81 const char *errstr = nt_errstr(status);
82 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
83 errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
85 printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d\n"
86 " with dns domain failed - %s\n",
87 r.in.req.req1.level, errstr);
89 } else if (!W_ERROR_IS_OK(r.out.result)) {
90 printf("DsGetDomainControllerInfo level %d\n"
91 " with dns domain failed - %s\n",
92 r.in.req.req1.level, win_errstr(r.out.result));
96 r.in.req.req1.level = 2;
98 printf("testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
99 r.in.req.req1.level, r.in.req.req1.domain_name);
101 status = dcerpc_drsuapi_DsGetDomainControllerInfo(p, mem_ctx, &r);
102 if (!NT_STATUS_IS_OK(status)) {
103 const char *errstr = nt_errstr(status);
104 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
105 errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
107 printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d\n"
108 " with dns domain failed - %s\n",
109 r.in.req.req1.level, errstr);
111 } else if (!W_ERROR_IS_OK(r.out.result)) {
112 printf("DsGetDomainControllerInfo level %d\n"
113 " with dns domain failed - %s\n",
114 r.in.req.req1.level, win_errstr(r.out.result));
117 if (r.out.ctr.ctr2.count > 0) {
118 priv->dcinfo = r.out.ctr.ctr2.array[0];
122 r.in.req.req1.level = -1;
124 printf("testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
125 r.in.req.req1.level, r.in.req.req1.domain_name);
127 status = dcerpc_drsuapi_DsGetDomainControllerInfo(p, mem_ctx, &r);
128 if (!NT_STATUS_IS_OK(status)) {
129 const char *errstr = nt_errstr(status);
130 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
131 errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
133 printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d\n"
134 " with dns domain failed - %s\n",
135 r.in.req.req1.level, errstr);
137 } else if (!W_ERROR_IS_OK(r.out.result)) {
138 printf("DsGetDomainControllerInfo level %d\n"
139 " with dns domain failed - %s\n",
140 r.in.req.req1.level, win_errstr(r.out.result));
144 r.in.req.req1.domain_name = talloc_strdup(mem_ctx, lp_workgroup());
145 r.in.req.req1.level = 2;
147 printf("testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
148 r.in.req.req1.level, r.in.req.req1.domain_name);
150 status = dcerpc_drsuapi_DsGetDomainControllerInfo(p, mem_ctx, &r);
151 if (!NT_STATUS_IS_OK(status)) {
152 const char *errstr = nt_errstr(status);
153 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
154 errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
156 printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d\n"
157 " with netbios domain failed - %s\n",
158 r.in.req.req1.level, errstr);
160 } else if (!W_ERROR_IS_OK(r.out.result)) {
161 printf("DsGetDomainControllerInfo level %d\n"
162 " with netbios domain failed - %s\n",
163 r.in.req.req1.level, win_errstr(r.out.result));
167 r.in.req.req1.domain_name = "__UNKNOWN_DOMAIN__";
168 r.in.req.req1.level = 2;
170 printf("testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
171 r.in.req.req1.level, r.in.req.req1.domain_name);
173 status = dcerpc_drsuapi_DsGetDomainControllerInfo(p, mem_ctx, &r);
174 if (!NT_STATUS_IS_OK(status)) {
175 const char *errstr = nt_errstr(status);
176 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
177 errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
179 printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d\n"
180 " with invalid domain failed - %s\n",
181 r.in.req.req1.level, errstr);
183 } else if (!W_ERROR_EQUAL(r.out.result, WERR_DS_OBJ_NOT_FOUND)) {
184 printf("DsGetDomainControllerInfo level %d\n"
185 " with invalid domain not expected error (WERR_DS_OBJ_NOT_FOUND) - %s\n",
186 r.in.req.req1.level, win_errstr(r.out.result));
193 static BOOL test_DsWriteAccountSpn(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
194 struct DsPrivate *priv)
197 struct drsuapi_DsWriteAccountSpn r;
198 struct drsuapi_DsNameString names[2];
201 r.in.bind_handle = &priv->bind_handle;
204 printf("testing DsWriteAccountSpn\n");
206 r.in.req.req1.operation = DRSUAPI_DS_SPN_OPERATION_ADD;
207 r.in.req.req1.unknown1 = 0;
208 r.in.req.req1.object_dn = priv->dcinfo.computer_dn;
209 r.in.req.req1.count = 2;
210 r.in.req.req1.spn_names = names;
211 names[0].str = talloc_asprintf(mem_ctx, "smbtortureSPN/%s",priv->dcinfo.netbios_name);
212 names[1].str = talloc_asprintf(mem_ctx, "smbtortureSPN/%s",priv->dcinfo.dns_name);
214 status = dcerpc_drsuapi_DsWriteAccountSpn(p, mem_ctx, &r);
215 if (!NT_STATUS_IS_OK(status)) {
216 const char *errstr = nt_errstr(status);
217 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
218 errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
220 printf("dcerpc_drsuapi_DsWriteAccountSpn failed - %s\n", errstr);
222 } else if (!W_ERROR_IS_OK(r.out.result)) {
223 printf("DsWriteAccountSpn failed - %s\n", win_errstr(r.out.result));
227 r.in.req.req1.operation = DRSUAPI_DS_SPN_OPERATION_DELETE;
228 r.in.req.req1.unknown1 = 0;
230 status = dcerpc_drsuapi_DsWriteAccountSpn(p, mem_ctx, &r);
231 if (!NT_STATUS_IS_OK(status)) {
232 const char *errstr = nt_errstr(status);
233 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
234 errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
236 printf("dcerpc_drsuapi_DsWriteAccountSpn failed - %s\n", errstr);
238 } else if (!W_ERROR_IS_OK(r.out.result)) {
239 printf("DsWriteAccountSpn failed - %s\n", win_errstr(r.out.result));
246 static BOOL test_DsReplicaGetInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
247 struct DsPrivate *priv)
250 struct drsuapi_DsReplicaGetInfo r;
259 DRSUAPI_DS_REPLICA_GET_INFO,
260 DRSUAPI_DS_REPLICA_INFO_NEIGHBORS,
263 DRSUAPI_DS_REPLICA_GET_INFO,
264 DRSUAPI_DS_REPLICA_INFO_CURSORS,
267 DRSUAPI_DS_REPLICA_GET_INFO,
268 DRSUAPI_DS_REPLICA_INFO_OBJ_METADATA,
271 DRSUAPI_DS_REPLICA_GET_INFO,
272 DRSUAPI_DS_REPLICA_INFO_KCC_DSA_CONNECT_FAILURES,
275 DRSUAPI_DS_REPLICA_GET_INFO,
276 DRSUAPI_DS_REPLICA_INFO_KCC_DSA_LINK_FAILURES,
279 DRSUAPI_DS_REPLICA_GET_INFO,
280 DRSUAPI_DS_REPLICA_INFO_PENDING_OPS,
283 DRSUAPI_DS_REPLICA_GET_INFO2,
284 DRSUAPI_DS_REPLICA_INFO_ATTRIBUTE_VALUE_METADATA,
287 DRSUAPI_DS_REPLICA_GET_INFO2,
288 DRSUAPI_DS_REPLICA_INFO_CURSORS2,
291 DRSUAPI_DS_REPLICA_GET_INFO2,
292 DRSUAPI_DS_REPLICA_INFO_CURSORS3,
295 DRSUAPI_DS_REPLICA_GET_INFO2,
296 DRSUAPI_DS_REPLICA_INFO_OBJ_METADATA2,
299 DRSUAPI_DS_REPLICA_GET_INFO2,
300 DRSUAPI_DS_REPLICA_INFO_ATTRIBUTE_VALUE_METADATA2,
303 DRSUAPI_DS_REPLICA_GET_INFO2,
304 DRSUAPI_DS_REPLICA_INFO_NEIGHBORS02,
307 DRSUAPI_DS_REPLICA_GET_INFO2,
308 DRSUAPI_DS_REPLICA_INFO_CONNECTIONS04,
311 DRSUAPI_DS_REPLICA_GET_INFO2,
312 DRSUAPI_DS_REPLICA_INFO_CURSURS05,
315 DRSUAPI_DS_REPLICA_GET_INFO2,
316 DRSUAPI_DS_REPLICA_INFO_06,
321 r.in.bind_handle = &priv->bind_handle;
323 for (i=0; i < ARRAY_SIZE(array); i++) {
324 const char *object_dn;
326 printf("testing DsReplicaGetInfo level %d infotype %d\n",
327 array[i].level, array[i].infotype);
329 object_dn = (array[i].obj_dn ? array[i].obj_dn : priv->domain_obj_dn);
331 r.in.level = array[i].level;
333 case DRSUAPI_DS_REPLICA_GET_INFO:
334 r.in.req.req1.info_type = array[i].infotype;
335 r.in.req.req1.object_dn = object_dn;
336 ZERO_STRUCT(r.in.req.req1.guid1);
338 case DRSUAPI_DS_REPLICA_GET_INFO2:
339 r.in.req.req2.info_type = array[i].infotype;
340 r.in.req.req2.object_dn = object_dn;
341 ZERO_STRUCT(r.in.req.req1.guid1);
342 r.in.req.req2.unknown1 = 0;
343 r.in.req.req2.string1 = NULL;
344 r.in.req.req2.string2 = NULL;
345 r.in.req.req2.unknown2 = 0;
349 status = dcerpc_drsuapi_DsReplicaGetInfo(p, mem_ctx, &r);
350 if (!NT_STATUS_IS_OK(status)) {
351 const char *errstr = nt_errstr(status);
352 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
353 errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
355 if (p->last_fault_code != DCERPC_FAULT_INVALID_TAG) {
356 printf("dcerpc_drsuapi_DsReplicaGetInfo failed - %s\n", errstr);
359 printf("DsReplicaGetInfo level %d and/or infotype %d not supported by server\n",
360 array[i].level, array[i].infotype);
362 } else if (!W_ERROR_IS_OK(r.out.result)) {
363 printf("DsReplicaGetInfo failed - %s\n", win_errstr(r.out.result));
371 static BOOL test_DsReplicaSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
372 struct DsPrivate *priv)
377 struct drsuapi_DsReplicaSync r;
378 struct drsuapi_DsReplicaObjectIdentifier nc;
379 struct GUID null_guid;
380 struct dom_sid null_sid;
389 if (!lp_parm_bool(-1, "torture", "dangerous", False)) {
390 printf("DsReplicaSync disabled - enable dangerous tests to use\n");
394 ZERO_STRUCT(null_guid);
395 ZERO_STRUCT(null_sid);
397 r.in.bind_handle = &priv->bind_handle;
399 for (i=0; i < ARRAY_SIZE(array); i++) {
400 printf("testing DsReplicaSync level %d\n",
403 r.in.level = array[i].level;
408 nc.dn = priv->domain_obj_dn?priv->domain_obj_dn:"";
410 r.in.req.req1.naming_context = &nc;
411 r.in.req.req1.guid1 = priv->dcinfo.ntds_guid;
412 r.in.req.req1.string1 = NULL;
413 r.in.req.req1.options = 16;
417 status = dcerpc_drsuapi_DsReplicaSync(p, mem_ctx, &r);
418 if (!NT_STATUS_IS_OK(status)) {
419 const char *errstr = nt_errstr(status);
420 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
421 errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
423 printf("dcerpc_drsuapi_DsReplicaSync failed - %s\n", errstr);
425 } else if (!W_ERROR_IS_OK(r.out.result)) {
426 printf("DsReplicaSync failed - %s\n", win_errstr(r.out.result));
434 static BOOL test_DsReplicaUpdateRefs(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
435 struct DsPrivate *priv)
440 struct drsuapi_DsReplicaUpdateRefs r;
441 struct drsuapi_DsReplicaObjectIdentifier nc;
442 struct GUID null_guid;
443 struct dom_sid null_sid;
452 ZERO_STRUCT(null_guid);
453 ZERO_STRUCT(null_sid);
455 r.in.bind_handle = &priv->bind_handle;
457 for (i=0; i < ARRAY_SIZE(array); i++) {
458 printf("testing DsReplicaUpdateRefs level %d\n",
461 r.in.level = array[i].level;
466 nc.dn = priv->domain_obj_dn?priv->domain_obj_dn:"";
468 r.in.req.req1.naming_context = &nc;
469 r.in.req.req1.dest_dsa_dns_name = talloc_asprintf(mem_ctx, "__some_dest_dsa_guid_string._msdn.%s",
470 priv->domain_dns_name);
471 r.in.req.req1.dest_dsa_guid = null_guid;
472 r.in.req.req1.options = 0;
476 status = dcerpc_drsuapi_DsReplicaUpdateRefs(p, mem_ctx, &r);
477 if (!NT_STATUS_IS_OK(status)) {
478 const char *errstr = nt_errstr(status);
479 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
480 errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
482 printf("dcerpc_drsuapi_DsReplicaUpdateRefs failed - %s\n", errstr);
484 } else if (!W_ERROR_IS_OK(r.out.result)) {
485 printf("DsReplicaUpdateRefs failed - %s\n", win_errstr(r.out.result));
493 static BOOL test_DsGetNCChanges(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
494 struct DsPrivate *priv)
499 struct drsuapi_DsGetNCChanges r;
500 struct drsuapi_DsReplicaObjectIdentifier nc;
501 struct GUID null_guid;
502 struct dom_sid null_sid;
514 ZERO_STRUCT(null_guid);
515 ZERO_STRUCT(null_sid);
517 for (i=0; i < ARRAY_SIZE(array); i++) {
518 printf("testing DsGetNCChanges level %d\n",
521 r.in.bind_handle = &priv->bind_handle;
522 r.in.level = array[i].level;
524 switch (r.in.level) {
528 nc.dn = priv->domain_obj_dn?priv->domain_obj_dn:"";
530 r.in.req.req5.destination_dsa_guid = GUID_random();
531 r.in.req.req5.source_dsa_guid = null_guid;
532 r.in.req.req5.naming_context = &nc;
533 r.in.req.req5.highwatermark.tmp_highest_usn = 0;
534 r.in.req.req5.highwatermark.reserved_usn = 0;
535 r.in.req.req5.highwatermark.highest_usn = 0;
536 r.in.req.req5.uptodateness_vector = NULL;
537 r.in.req.req5.replica_flags = 0;
538 if (lp_parm_bool(-1, "drsuapi","compression", False)) {
539 r.in.req.req5.replica_flags |= DRSUAPI_DS_REPLICA_NEIGHBOUR_COMPRESS_CHANGES;
541 r.in.req.req5.unknown2 = 0;
542 r.in.req.req5.unknown3 = 0;
543 r.in.req.req5.unknown4 = 0;
544 r.in.req.req5.h1 = 0;
550 nc.dn = priv->domain_obj_dn?priv->domain_obj_dn:"";
552 r.in.req.req8.destination_dsa_guid = GUID_random();
553 r.in.req.req8.source_dsa_guid = null_guid;
554 r.in.req.req8.naming_context = &nc;
555 r.in.req.req8.highwatermark.tmp_highest_usn = 0;
556 r.in.req.req8.highwatermark.reserved_usn = 0;
557 r.in.req.req8.highwatermark.highest_usn = 0;
558 r.in.req.req8.uptodateness_vector = NULL;
559 r.in.req.req8.replica_flags = 0;
560 if (lp_parm_bool(-1,"drsuapi","compression",False)) {
561 r.in.req.req8.replica_flags |= DRSUAPI_DS_REPLICA_NEIGHBOUR_COMPRESS_CHANGES;
563 if (lp_parm_bool(-1,"drsuapi","neighbour_writeable",True)) {
564 r.in.req.req8.replica_flags |= DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE;
566 r.in.req.req8.replica_flags |= DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
567 | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS
568 | DRSUAPI_DS_REPLICA_NEIGHBOUR_RETURN_OBJECT_PARENTS
569 | DRSUAPI_DS_REPLICA_NEIGHBOUR_NEVER_SYNCED
571 r.in.req.req8.unknown2 = 402;
572 r.in.req.req8.unknown3 = 402116;
573 r.in.req.req8.unknown4 = 0;
574 r.in.req.req8.h1 = 0;
575 r.in.req.req8.unique_ptr1 = 0;
576 r.in.req.req8.unique_ptr2 = 0;
577 r.in.req.req8.ctr12.count = 0;
578 r.in.req.req8.ctr12.array = NULL;
583 status = dcerpc_drsuapi_DsGetNCChanges(p, mem_ctx, &r);
584 if (!NT_STATUS_IS_OK(status)) {
585 const char *errstr = nt_errstr(status);
586 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
587 errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
589 printf("dcerpc_drsuapi_DsGetNCChanges failed - %s\n", errstr);
591 } else if (!W_ERROR_IS_OK(r.out.result)) {
592 printf("DsGetNCChanges failed - %s\n", win_errstr(r.out.result));
600 BOOL test_DsUnbind(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
601 struct DsPrivate *priv)
604 struct drsuapi_DsUnbind r;
607 r.in.bind_handle = &priv->bind_handle;
608 r.out.bind_handle = &priv->bind_handle;
610 printf("testing DsUnbind\n");
612 status = dcerpc_drsuapi_DsUnbind(p, mem_ctx, &r);
613 if (!NT_STATUS_IS_OK(status)) {
614 const char *errstr = nt_errstr(status);
615 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
616 errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
618 printf("dcerpc_drsuapi_DsUnbind failed - %s\n", errstr);
620 } else if (!W_ERROR_IS_OK(r.out.result)) {
621 printf("DsBind failed - %s\n", win_errstr(r.out.result));
628 BOOL torture_rpc_drsuapi(void)
631 struct dcerpc_pipe *p;
634 struct DsPrivate priv;
636 mem_ctx = talloc_init("torture_rpc_drsuapi");
638 status = torture_rpc_connection(mem_ctx,
640 &dcerpc_table_drsuapi);
641 if (!NT_STATUS_IS_OK(status)) {
642 talloc_free(mem_ctx);
646 printf("Connected to DRAUAPI pipe\n");
650 ret &= test_DsBind(p, mem_ctx, &priv);
652 ret &= test_DsGetDCInfo(p, mem_ctx, &priv);
654 ret &= test_DsCrackNames(p, mem_ctx, &priv, priv.dcinfo.netbios_name);
656 ret &= test_DsWriteAccountSpn(p, mem_ctx, &priv);
658 ret &= test_DsReplicaGetInfo(p, mem_ctx, &priv);
660 ret &= test_DsReplicaSync(p, mem_ctx, &priv);
662 ret &= test_DsReplicaUpdateRefs(p, mem_ctx, &priv);
664 ret &= test_DsGetNCChanges(p, mem_ctx, &priv);
666 ret &= test_DsUnbind(p, mem_ctx, &priv);
668 talloc_free(mem_ctx);