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 "librpc/gen_ndr/ndr_drsuapi.h"
27 #include "torture/rpc/drsupai.h"
29 static BOOL test_DsBind(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
30 struct DsPrivate *priv)
33 struct drsuapi_DsBind r;
36 GUID_from_string(DRSUAPI_DS_BIND_GUID, &priv->bind_guid);
38 r.in.bind_guid = &priv->bind_guid;
39 r.in.bind_info = NULL;
40 r.out.bind_handle = &priv->bind_handle;
42 printf("testing DsBind\n");
44 status = dcerpc_drsuapi_DsBind(p, mem_ctx, &r);
45 if (!NT_STATUS_IS_OK(status)) {
46 const char *errstr = nt_errstr(status);
47 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
48 errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
50 printf("dcerpc_drsuapi_DsBind failed - %s\n", errstr);
52 } else if (!W_ERROR_IS_OK(r.out.result)) {
53 printf("DsBind failed - %s\n", win_errstr(r.out.result));
60 static BOOL test_DsGetDCInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
61 struct DsPrivate *priv)
64 struct drsuapi_DsGetDomainControllerInfo r;
67 r.in.bind_handle = &priv->bind_handle;
70 r.in.req.req1.domain_name = talloc_strdup(mem_ctx, lp_realm());
71 r.in.req.req1.level = 1;
73 printf("testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
74 r.in.req.req1.level, r.in.req.req1.domain_name);
76 status = dcerpc_drsuapi_DsGetDomainControllerInfo(p, mem_ctx, &r);
77 if (!NT_STATUS_IS_OK(status)) {
78 const char *errstr = nt_errstr(status);
79 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
80 errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
82 printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d\n"
83 " with dns domain failed - %s\n",
84 r.in.req.req1.level, errstr);
86 } else if (!W_ERROR_IS_OK(r.out.result)) {
87 printf("DsGetDomainControllerInfo level %d\n"
88 " with dns domain failed - %s\n",
89 r.in.req.req1.level, win_errstr(r.out.result));
93 r.in.req.req1.level = 2;
95 printf("testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
96 r.in.req.req1.level, r.in.req.req1.domain_name);
98 status = dcerpc_drsuapi_DsGetDomainControllerInfo(p, mem_ctx, &r);
99 if (!NT_STATUS_IS_OK(status)) {
100 const char *errstr = nt_errstr(status);
101 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
102 errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
104 printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d\n"
105 " with dns domain failed - %s\n",
106 r.in.req.req1.level, errstr);
108 } else if (!W_ERROR_IS_OK(r.out.result)) {
109 printf("DsGetDomainControllerInfo level %d\n"
110 " with dns domain failed - %s\n",
111 r.in.req.req1.level, win_errstr(r.out.result));
114 if (r.out.ctr.ctr2.count > 0) {
115 priv->dcinfo = r.out.ctr.ctr2.array[0];
119 r.in.req.req1.level = -1;
121 printf("testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
122 r.in.req.req1.level, r.in.req.req1.domain_name);
124 status = dcerpc_drsuapi_DsGetDomainControllerInfo(p, mem_ctx, &r);
125 if (!NT_STATUS_IS_OK(status)) {
126 const char *errstr = nt_errstr(status);
127 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
128 errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
130 printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d\n"
131 " with dns domain failed - %s\n",
132 r.in.req.req1.level, errstr);
134 } else if (!W_ERROR_IS_OK(r.out.result)) {
135 printf("DsGetDomainControllerInfo level %d\n"
136 " with dns domain failed - %s\n",
137 r.in.req.req1.level, win_errstr(r.out.result));
141 r.in.req.req1.domain_name = talloc_strdup(mem_ctx, lp_workgroup());
142 r.in.req.req1.level = 2;
144 printf("testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
145 r.in.req.req1.level, r.in.req.req1.domain_name);
147 status = dcerpc_drsuapi_DsGetDomainControllerInfo(p, mem_ctx, &r);
148 if (!NT_STATUS_IS_OK(status)) {
149 const char *errstr = nt_errstr(status);
150 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
151 errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
153 printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d\n"
154 " with netbios domain failed - %s\n",
155 r.in.req.req1.level, errstr);
157 } else if (!W_ERROR_IS_OK(r.out.result)) {
158 printf("DsGetDomainControllerInfo level %d\n"
159 " with netbios domain failed - %s\n",
160 r.in.req.req1.level, win_errstr(r.out.result));
164 r.in.req.req1.domain_name = "__UNKNOWN_DOMAIN__";
165 r.in.req.req1.level = 2;
167 printf("testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
168 r.in.req.req1.level, r.in.req.req1.domain_name);
170 status = dcerpc_drsuapi_DsGetDomainControllerInfo(p, mem_ctx, &r);
171 if (!NT_STATUS_IS_OK(status)) {
172 const char *errstr = nt_errstr(status);
173 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
174 errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
176 printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d\n"
177 " with invalid domain failed - %s\n",
178 r.in.req.req1.level, errstr);
180 } else if (!W_ERROR_EQUAL(r.out.result, WERR_DS_OBJ_NOT_FOUND)) {
181 printf("DsGetDomainControllerInfo level %d\n"
182 " with invalid domain not expected error (WERR_DS_OBJ_NOT_FOUND) - %s\n",
183 r.in.req.req1.level, win_errstr(r.out.result));
190 static BOOL test_DsWriteAccountSpn(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
191 struct DsPrivate *priv)
194 struct drsuapi_DsWriteAccountSpn r;
195 struct drsuapi_DsNameString names[2];
198 r.in.bind_handle = &priv->bind_handle;
201 printf("testing DsWriteAccountSpn\n");
203 r.in.req.req1.operation = DRSUAPI_DS_SPN_OPERATION_ADD;
204 r.in.req.req1.unknown1 = 0;
205 r.in.req.req1.object_dn = priv->dcinfo.computer_dn;
206 r.in.req.req1.count = 2;
207 r.in.req.req1.spn_names = names;
208 names[0].str = talloc_asprintf(mem_ctx, "smbtortureSPN/%s",priv->dcinfo.netbios_name);
209 names[1].str = talloc_asprintf(mem_ctx, "smbtortureSPN/%s",priv->dcinfo.dns_name);
211 status = dcerpc_drsuapi_DsWriteAccountSpn(p, mem_ctx, &r);
212 if (!NT_STATUS_IS_OK(status)) {
213 const char *errstr = nt_errstr(status);
214 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
215 errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
217 printf("dcerpc_drsuapi_DsWriteAccountSpn failed - %s\n", errstr);
219 } else if (!W_ERROR_IS_OK(r.out.result)) {
220 printf("DsWriteAccountSpn failed - %s\n", win_errstr(r.out.result));
224 r.in.req.req1.operation = DRSUAPI_DS_SPN_OPERATION_DELETE;
225 r.in.req.req1.unknown1 = 0;
227 status = dcerpc_drsuapi_DsWriteAccountSpn(p, mem_ctx, &r);
228 if (!NT_STATUS_IS_OK(status)) {
229 const char *errstr = nt_errstr(status);
230 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
231 errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
233 printf("dcerpc_drsuapi_DsWriteAccountSpn failed - %s\n", errstr);
235 } else if (!W_ERROR_IS_OK(r.out.result)) {
236 printf("DsWriteAccountSpn failed - %s\n", win_errstr(r.out.result));
243 static BOOL test_DsReplicaGetInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
244 struct DsPrivate *priv)
247 struct drsuapi_DsReplicaGetInfo r;
256 DRSUAPI_DS_REPLICA_GET_INFO,
257 DRSUAPI_DS_REPLICA_INFO_NEIGHBORS,
260 DRSUAPI_DS_REPLICA_GET_INFO,
261 DRSUAPI_DS_REPLICA_INFO_CURSORS,
264 DRSUAPI_DS_REPLICA_GET_INFO,
265 DRSUAPI_DS_REPLICA_INFO_OBJ_METADATA,
268 DRSUAPI_DS_REPLICA_GET_INFO,
269 DRSUAPI_DS_REPLICA_INFO_KCC_DSA_CONNECT_FAILURES,
272 DRSUAPI_DS_REPLICA_GET_INFO,
273 DRSUAPI_DS_REPLICA_INFO_KCC_DSA_LINK_FAILURES,
276 DRSUAPI_DS_REPLICA_GET_INFO,
277 DRSUAPI_DS_REPLICA_INFO_PENDING_OPS,
280 DRSUAPI_DS_REPLICA_GET_INFO2,
281 DRSUAPI_DS_REPLICA_INFO_ATTRIBUTE_VALUE_METADATA,
284 DRSUAPI_DS_REPLICA_GET_INFO2,
285 DRSUAPI_DS_REPLICA_INFO_CURSORS2,
288 DRSUAPI_DS_REPLICA_GET_INFO2,
289 DRSUAPI_DS_REPLICA_INFO_CURSORS3,
292 DRSUAPI_DS_REPLICA_GET_INFO2,
293 DRSUAPI_DS_REPLICA_INFO_OBJ_METADATA2,
296 DRSUAPI_DS_REPLICA_GET_INFO2,
297 DRSUAPI_DS_REPLICA_INFO_ATTRIBUTE_VALUE_METADATA2,
300 DRSUAPI_DS_REPLICA_GET_INFO2,
301 DRSUAPI_DS_REPLICA_INFO_NEIGHBORS02,
304 DRSUAPI_DS_REPLICA_GET_INFO2,
305 DRSUAPI_DS_REPLICA_INFO_CONNECTIONS04,
308 DRSUAPI_DS_REPLICA_GET_INFO2,
309 DRSUAPI_DS_REPLICA_INFO_CURSURS05,
312 DRSUAPI_DS_REPLICA_GET_INFO2,
313 DRSUAPI_DS_REPLICA_INFO_06,
318 r.in.bind_handle = &priv->bind_handle;
320 for (i=0; i < ARRAY_SIZE(array); i++) {
321 const char *object_dn;
323 printf("testing DsReplicaGetInfo level %d infotype %d\n",
324 array[i].level, array[i].infotype);
326 object_dn = (array[i].obj_dn ? array[i].obj_dn : priv->domain_obj_dn);
328 r.in.level = array[i].level;
330 case DRSUAPI_DS_REPLICA_GET_INFO:
331 r.in.req.req1.info_type = array[i].infotype;
332 r.in.req.req1.object_dn = object_dn;
333 ZERO_STRUCT(r.in.req.req1.guid1);
335 case DRSUAPI_DS_REPLICA_GET_INFO2:
336 r.in.req.req2.info_type = array[i].infotype;
337 r.in.req.req2.object_dn = object_dn;
338 ZERO_STRUCT(r.in.req.req1.guid1);
339 r.in.req.req2.unknown1 = 0;
340 r.in.req.req2.string1 = NULL;
341 r.in.req.req2.string2 = NULL;
342 r.in.req.req2.unknown2 = 0;
346 status = dcerpc_drsuapi_DsReplicaGetInfo(p, mem_ctx, &r);
347 if (!NT_STATUS_IS_OK(status)) {
348 const char *errstr = nt_errstr(status);
349 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
350 errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
352 if (p->last_fault_code != DCERPC_FAULT_INVALID_TAG) {
353 printf("dcerpc_drsuapi_DsReplicaGetInfo failed - %s\n", errstr);
356 printf("DsReplicaGetInfo level %d and/or infotype %d not supported by server\n",
357 array[i].level, array[i].infotype);
359 } else if (!W_ERROR_IS_OK(r.out.result)) {
360 printf("DsReplicaGetInfo failed - %s\n", win_errstr(r.out.result));
368 static BOOL test_DsReplicaSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
369 struct DsPrivate *priv)
374 struct drsuapi_DsReplicaSync r;
375 struct drsuapi_DsReplicaObjectIdentifier nc;
376 struct GUID null_guid;
377 struct dom_sid null_sid;
386 if (!lp_parm_bool(-1, "torture", "dangerous", False)) {
387 printf("DsReplicaSync disabled - enable dangerous tests to use\n");
391 ZERO_STRUCT(null_guid);
392 ZERO_STRUCT(null_sid);
394 r.in.bind_handle = &priv->bind_handle;
396 for (i=0; i < ARRAY_SIZE(array); i++) {
397 printf("testing DsReplicaSync level %d\n",
400 r.in.level = array[i].level;
405 nc.dn = priv->domain_obj_dn?priv->domain_obj_dn:"";
407 r.in.req.req1.naming_context = &nc;
408 r.in.req.req1.guid1 = priv->dcinfo.ntds_guid;
409 r.in.req.req1.string1 = NULL;
410 r.in.req.req1.options = 16;
414 status = dcerpc_drsuapi_DsReplicaSync(p, mem_ctx, &r);
415 if (!NT_STATUS_IS_OK(status)) {
416 const char *errstr = nt_errstr(status);
417 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
418 errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
420 printf("dcerpc_drsuapi_DsReplicaSync failed - %s\n", errstr);
422 } else if (!W_ERROR_IS_OK(r.out.result)) {
423 printf("DsReplicaSync failed - %s\n", win_errstr(r.out.result));
431 static BOOL test_DsReplicaUpdateRefs(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
432 struct DsPrivate *priv)
437 struct drsuapi_DsReplicaUpdateRefs r;
438 struct drsuapi_DsReplicaObjectIdentifier nc;
439 struct GUID null_guid;
440 struct dom_sid null_sid;
449 ZERO_STRUCT(null_guid);
450 ZERO_STRUCT(null_sid);
452 r.in.bind_handle = &priv->bind_handle;
454 for (i=0; i < ARRAY_SIZE(array); i++) {
455 printf("testing DsReplicaUpdateRefs level %d\n",
458 r.in.level = array[i].level;
463 nc.dn = priv->domain_obj_dn?priv->domain_obj_dn:"";
465 r.in.req.req1.naming_context = &nc;
466 r.in.req.req1.dest_dsa_dns_name = talloc_asprintf(mem_ctx, "__some_dest_dsa_guid_string._msdn.%s",
467 priv->domain_dns_name);
468 r.in.req.req1.dest_dsa_guid = null_guid;
469 r.in.req.req1.options = 0;
473 status = dcerpc_drsuapi_DsReplicaUpdateRefs(p, mem_ctx, &r);
474 if (!NT_STATUS_IS_OK(status)) {
475 const char *errstr = nt_errstr(status);
476 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
477 errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
479 printf("dcerpc_drsuapi_DsReplicaUpdateRefs failed - %s\n", errstr);
481 } else if (!W_ERROR_IS_OK(r.out.result)) {
482 printf("DsReplicaUpdateRefs failed - %s\n", win_errstr(r.out.result));
490 static BOOL test_DsGetNCChanges(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
491 struct DsPrivate *priv)
496 struct drsuapi_DsGetNCChanges r;
497 struct drsuapi_DsReplicaObjectIdentifier nc;
498 struct GUID null_guid;
499 struct dom_sid null_sid;
511 ZERO_STRUCT(null_guid);
512 ZERO_STRUCT(null_sid);
514 for (i=0; i < ARRAY_SIZE(array); i++) {
515 printf("testing DsGetNCChanges level %d\n",
518 r.in.bind_handle = &priv->bind_handle;
519 r.in.level = array[i].level;
521 switch (r.in.level) {
525 nc.dn = priv->domain_obj_dn?priv->domain_obj_dn:"";
527 r.in.req.req5.destination_dsa_guid = GUID_random();
528 r.in.req.req5.source_dsa_guid = null_guid;
529 r.in.req.req5.naming_context = &nc;
530 r.in.req.req5.highwatermark.tmp_highest_usn = 0;
531 r.in.req.req5.highwatermark.reserved_usn = 0;
532 r.in.req.req5.highwatermark.highest_usn = 0;
533 r.in.req.req5.uptodateness_vector = NULL;
534 r.in.req.req5.replica_flags = 0;
535 if (lp_parm_bool(-1, "drsuapi","compression", False)) {
536 r.in.req.req5.replica_flags |= DRSUAPI_DS_REPLICA_NEIGHBOUR_COMPRESS_CHANGES;
538 r.in.req.req5.unknown2 = 0;
539 r.in.req.req5.unknown3 = 0;
540 r.in.req.req5.unknown4 = 0;
541 r.in.req.req5.h1 = 0;
547 nc.dn = priv->domain_obj_dn?priv->domain_obj_dn:"";
549 r.in.req.req8.destination_dsa_guid = GUID_random();
550 r.in.req.req8.source_dsa_guid = null_guid;
551 r.in.req.req8.naming_context = &nc;
552 r.in.req.req8.highwatermark.tmp_highest_usn = 0;
553 r.in.req.req8.highwatermark.reserved_usn = 0;
554 r.in.req.req8.highwatermark.highest_usn = 0;
555 r.in.req.req8.uptodateness_vector = NULL;
556 r.in.req.req8.replica_flags = 0
557 | DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
558 | DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
559 | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS
560 | DRSUAPI_DS_REPLICA_NEIGHBOUR_RETURN_OBJECT_PARENTS
561 | DRSUAPI_DS_REPLICA_NEIGHBOUR_NEVER_SYNCED
562 | DRSUAPI_DS_REPLICA_NEIGHBOUR_COMPRESS_CHANGES
564 r.in.req.req8.unknown2 = 402;
565 r.in.req.req8.unknown3 = 402116;
566 r.in.req.req8.unknown4 = 0;
567 r.in.req.req8.h1 = 0;
568 r.in.req.req8.unique_ptr1 = 0;
569 r.in.req.req8.unique_ptr2 = 0;
570 r.in.req.req8.ctr12.count = 0;
571 r.in.req.req8.ctr12.array = NULL;
576 status = dcerpc_drsuapi_DsGetNCChanges(p, mem_ctx, &r);
577 if (!NT_STATUS_IS_OK(status)) {
578 const char *errstr = nt_errstr(status);
579 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
580 errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
582 printf("dcerpc_drsuapi_DsGetNCChanges failed - %s\n", errstr);
584 } else if (!W_ERROR_IS_OK(r.out.result)) {
585 printf("DsGetNCChanges failed - %s\n", win_errstr(r.out.result));
593 static BOOL test_DsUnbind(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
594 struct DsPrivate *priv)
597 struct drsuapi_DsUnbind r;
600 r.in.bind_handle = &priv->bind_handle;
601 r.out.bind_handle = &priv->bind_handle;
603 printf("testing DsUnbind\n");
605 status = dcerpc_drsuapi_DsUnbind(p, mem_ctx, &r);
606 if (!NT_STATUS_IS_OK(status)) {
607 const char *errstr = nt_errstr(status);
608 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
609 errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
611 printf("dcerpc_drsuapi_DsUnbind failed - %s\n", errstr);
613 } else if (!W_ERROR_IS_OK(r.out.result)) {
614 printf("DsBind failed - %s\n", win_errstr(r.out.result));
621 BOOL torture_rpc_drsuapi(void)
624 struct dcerpc_pipe *p;
627 struct DsPrivate priv;
629 mem_ctx = talloc_init("torture_rpc_drsuapi");
631 status = torture_rpc_connection(mem_ctx,
635 DCERPC_DRSUAPI_VERSION);
636 if (!NT_STATUS_IS_OK(status)) {
637 talloc_free(mem_ctx);
641 printf("Connected to DRAUAPI pipe\n");
645 ret &= test_DsBind(p, mem_ctx, &priv);
647 ret &= test_DsGetDCInfo(p, mem_ctx, &priv);
649 ret &= test_DsCrackNames(p, mem_ctx, &priv, priv.dcinfo.netbios_name);
651 ret &= test_DsWriteAccountSpn(p, mem_ctx, &priv);
653 ret &= test_DsReplicaGetInfo(p, mem_ctx, &priv);
655 ret &= test_DsReplicaSync(p, mem_ctx, &priv);
657 ret &= test_DsReplicaUpdateRefs(p, mem_ctx, &priv);
659 ret &= test_DsGetNCChanges(p, mem_ctx, &priv);
661 ret &= test_DsUnbind(p, mem_ctx, &priv);
663 talloc_free(mem_ctx);