2 Unix SMB/CIFS implementation.
4 msDS-IntId attribute replication test.
6 Copyright (C) Kamen Mazdrashki <kamenim@samba.org> 2010
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "lib/cmdline/cmdline.h"
24 #include "librpc/gen_ndr/ndr_drsuapi_c.h"
25 #include "librpc/gen_ndr/ndr_drsblobs.h"
26 #include "libcli/cldap/cldap.h"
27 #include "torture/torture.h"
28 #include "../libcli/drsuapi/drsuapi.h"
29 #include "auth/gensec/gensec.h"
30 #include "param/param.h"
31 #include "dsdb/samdb/samdb.h"
32 #include "torture/rpc/torture_rpc.h"
33 #include "torture/drs/proto.h"
34 #include "lib/tsocket/tsocket.h"
35 #include "libcli/resolve/resolve.h"
36 #include "lib/util/util_paths.h"
38 struct DsSyncBindInfo
{
39 struct dcerpc_pipe
*drs_pipe
;
40 struct dcerpc_binding_handle
*drs_handle
;
41 struct drsuapi_DsBind req
;
42 struct GUID bind_guid
;
43 struct drsuapi_DsBindInfoCtr our_bind_info_ctr
;
44 struct drsuapi_DsBindInfo28 our_bind_info28
;
45 struct drsuapi_DsBindInfo28 peer_bind_info28
;
46 struct policy_handle bind_handle
;
50 struct dcerpc_binding
*server_binding
;
52 struct dcerpc_pipe
*drs_pipe
;
53 struct dcerpc_binding_handle
*drs_handle
;
55 DATA_BLOB gensec_skey
;
56 struct drsuapi_DsBindInfo48 srv_info48
;
57 struct policy_handle rpc_handle
;
60 struct DsIntIdTestCtx
{
62 const char *domain_dn
;
63 const char *config_dn
;
64 const char *schema_dn
;
66 /* what we need to do as 'Administrator' */
67 struct cli_credentials
*creds
;
68 struct DsaBindInfo dsa_bind
;
69 struct ldb_context
*ldb
;
73 /* Format string to create provision LDIF with */
74 #define PROVISION_LDIF_FMT \
75 "###########################################################\n" \
76 "# Format string with positional params:\n" \
77 "# 1 - (int) Unique ID between 1 and 2^16\n" \
78 "# 2 - (string) Domain DN\n" \
79 "###########################################################\n" \
81 "###########################################################\n" \
83 "###########################################################\n" \
84 "dn: CN=msds-intid-%1$d,CN=Schema,CN=Configuration,%2$s\n" \
86 "objectClass: top\n" \
87 "objectClass: attributeSchema\n" \
88 "cn: msds-intid-%1$d\n" \
89 "attributeID: 1.3.6.1.4.1.7165.4.6.1.%1$d.1.5.9940\n" \
90 "attributeSyntax: 2.5.5.10\n" \
93 "isSingleValued: TRUE\n" \
94 "systemOnly: FALSE\n" \
96 "# schemaUpdateNow\n" \
98 "changeType: modify\n" \
99 "add: schemaUpdateNow\n" \
100 "schemaUpdateNow: 1\n" \
103 "###########################################################\n" \
104 "# Update schema (with linked attribute)\n" \
105 "###########################################################\n" \
106 "dn: CN=msds-intid-link-%1$d,CN=Schema,CN=Configuration,%2$s\n" \
107 "changetype: add\n" \
108 "objectClass: top\n" \
109 "objectClass: attributeSchema\n" \
110 "cn: msds-intid-link-%1$d\n" \
111 "attributeID: 1.3.6.1.4.1.7165.4.6.1.%1$d.1.5.9941\n" \
112 "attributeSyntax: 2.5.5.1\n" \
114 "instanceType: 4\n" \
115 "isSingleValued: TRUE\n" \
116 "systemOnly: FALSE\n" \
117 "linkID: 1.2.840.113556.1.2.50\n" \
119 "# schemaUpdateNow\n" \
121 "changeType: modify\n" \
122 "add: schemaUpdateNow\n" \
123 "schemaUpdateNow: 1\n" \
126 "###########################################################\n" \
127 "# Update User class\n" \
128 "###########################################################\n" \
129 "dn: CN=User,CN=Schema,CN=Configuration,%2$s\n" \
130 "changetype: modify\n" \
131 "add: mayContain\n" \
132 "mayContain: msdsIntid%1$d\n" \
133 "mayContain: msdsIntidLink%1$d\n" \
136 "# schemaUpdateNow\n" \
138 "changeType: modify\n" \
139 "add: schemaUpdateNow\n" \
140 "schemaUpdateNow: 1\n" \
143 "###########################################################\n" \
144 "# create user to test with\n" \
145 "###########################################################\n" \
146 "dn: CN=dsIntId_usr_%1$d,CN=Users,%2$s\n" \
147 "changetype: add\n" \
148 "objectClass: user\n" \
149 "cn: dsIntId_usr_%1$d\n" \
150 "name: dsIntId_usr_%1$d\n" \
151 "displayName: dsIntId_usr_%1$d\n" \
152 "sAMAccountName: dsIntId_usr_%1$d\n" \
153 "msdsIntid%1$d: msDS-IntId-%1$d attribute value\n" \
154 "msdsIntidLink%1$d: %2$s\n" \
158 static struct DsIntIdTestCtx
*_dsintid_create_context(struct torture_context
*tctx
)
161 struct DsIntIdTestCtx
*ctx
;
162 struct dcerpc_binding
*server_binding
;
163 const char *binding
= torture_setting_string(tctx
, "binding", NULL
);
165 /* Create test suite context */
166 ctx
= talloc_zero(tctx
, struct DsIntIdTestCtx
);
168 torture_result(tctx
, TORTURE_FAIL
, "Not enough memory!");
172 /* parse binding object */
173 status
= dcerpc_parse_binding(ctx
, binding
, &server_binding
);
174 if (!NT_STATUS_IS_OK(status
)) {
175 torture_result(tctx
, TORTURE_FAIL
,
176 "Bad binding string '%s': %s", binding
, nt_errstr(status
));
180 status
= dcerpc_binding_set_flags(server_binding
,
181 DCERPC_SIGN
| DCERPC_SEAL
, 0);
182 if (!NT_STATUS_IS_OK(status
)) {
183 torture_result(tctx
, TORTURE_FAIL
,
184 "dcerpc_binding_set_flags: %s", nt_errstr(status
));
188 /* populate test suite context */
189 ctx
->creds
= samba_cmdline_get_creds();
190 ctx
->dsa_bind
.server_binding
= server_binding
;
192 ctx
->ldap_url
= talloc_asprintf(ctx
, "ldap://%s",
193 dcerpc_binding_get_string_option(server_binding
, "host"));
198 static bool _test_DsaBind(struct torture_context
*tctx
,
200 struct cli_credentials
*credentials
,
201 uint32_t req_extensions
,
202 struct DsaBindInfo
*bi
)
205 struct GUID bind_guid
;
206 struct drsuapi_DsBind r
;
207 struct drsuapi_DsBindInfoCtr bind_info_ctr
;
208 uint32_t supported_extensions
;
210 /* make DCE RPC connection */
211 status
= dcerpc_pipe_connect_b(mem_ctx
,
215 credentials
, tctx
->ev
, tctx
->lp_ctx
);
216 torture_assert_ntstatus_ok(tctx
, status
, "Failed to connect to server");
218 bi
->drs_handle
= bi
->drs_pipe
->binding_handle
;
220 status
= dcerpc_binding_handle_auth_session_key(bi
->drs_handle
,
223 torture_assert_ntstatus_ok(tctx
, status
, "failed to get gensec session key");
225 /* Bind to DRSUAPI interface */
226 GUID_from_string(DRSUAPI_DS_BIND_GUID_W2K3
, &bind_guid
);
229 * Add flags that should be 1, according to MS docs.
230 * It turns out DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3
231 * is actually required in order for GetNCChanges() to
232 * return schemaInfo entry in the prefixMap returned.
233 * Use DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION so
234 * we are able to fetch sensitive data.
236 supported_extensions
= req_extensions
237 | DRSUAPI_SUPPORTED_EXTENSION_BASE
238 | DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION
239 | DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD
240 | DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3
241 | DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION
;
243 ZERO_STRUCT(bind_info_ctr
);
244 bind_info_ctr
.length
= 28;
245 bind_info_ctr
.info
.info28
.supported_extensions
= supported_extensions
;
247 r
.in
.bind_guid
= &bind_guid
;
248 r
.in
.bind_info
= &bind_info_ctr
;
249 r
.out
.bind_handle
= &bi
->rpc_handle
;
251 status
= dcerpc_drsuapi_DsBind_r(bi
->drs_handle
, mem_ctx
, &r
);
252 torture_drsuapi_assert_call(tctx
, bi
->drs_pipe
, status
,
253 &r
, "dcerpc_drsuapi_DsBind_r");
256 switch (r
.out
.bind_info
->length
) {
258 struct drsuapi_DsBindInfo24
*info24
;
259 info24
= &r
.out
.bind_info
->info
.info24
;
260 bi
->srv_info48
.supported_extensions
= info24
->supported_extensions
;
261 bi
->srv_info48
.site_guid
= info24
->site_guid
;
262 bi
->srv_info48
.pid
= info24
->pid
;
266 struct drsuapi_DsBindInfo28
*info28
;
267 info28
= &r
.out
.bind_info
->info
.info28
;
268 bi
->srv_info48
.supported_extensions
= info28
->supported_extensions
;
269 bi
->srv_info48
.site_guid
= info28
->site_guid
;
270 bi
->srv_info48
.pid
= info28
->pid
;
271 bi
->srv_info48
.repl_epoch
= info28
->repl_epoch
;
275 struct drsuapi_DsBindInfo32
*info32
;
276 info32
= &r
.out
.bind_info
->info
.info32
;
277 bi
->srv_info48
.supported_extensions
= info32
->supported_extensions
;
278 bi
->srv_info48
.site_guid
= info32
->site_guid
;
279 bi
->srv_info48
.pid
= info32
->pid
;
280 bi
->srv_info48
.repl_epoch
= info32
->repl_epoch
;
284 bi
->srv_info48
= r
.out
.bind_info
->info
.info48
;
288 struct drsuapi_DsBindInfo52
*info52
;
289 info52
= &r
.out
.bind_info
->info
.info52
;
290 bi
->srv_info48
.supported_extensions
= info52
->supported_extensions
;
291 bi
->srv_info48
.site_guid
= info52
->site_guid
;
292 bi
->srv_info48
.pid
= info52
->pid
;
293 bi
->srv_info48
.repl_epoch
= info52
->repl_epoch
;
297 torture_result(tctx
, TORTURE_FAIL
,
298 "DsBind: unknown BindInfo length: %u",
299 r
.out
.bind_info
->length
);
303 /* check if server supports extensions we've requested */
304 if ((bi
->srv_info48
.supported_extensions
& req_extensions
) != req_extensions
) {
305 torture_result(tctx
, TORTURE_FAIL
,
306 "Server does not support requested extensions. "
307 "Requested: 0x%08X, Supported: 0x%08X",
308 req_extensions
, bi
->srv_info48
.supported_extensions
);
315 static bool _test_LDAPBind(struct torture_context
*tctx
,
317 struct cli_credentials
*credentials
,
318 const char *ldap_url
,
319 struct ldb_context
**_ldb
)
323 struct ldb_context
*ldb
;
325 const char *modules_option
[] = { "modules:paged_searches", NULL
};
326 ldb
= ldb_init(mem_ctx
, tctx
->ev
);
331 /* Despite us loading the schema from the AD server, we need
332 * the samba handlers to get the extended DN syntax stuff */
333 ret
= ldb_register_samba_handlers(ldb
);
334 if (ret
!= LDB_SUCCESS
) {
339 ldb_set_modules_dir(ldb
, modules_path(ldb
, "ldb"));
341 if (ldb_set_opaque(ldb
, "credentials", credentials
) != LDB_SUCCESS
) {
346 if (ldb_set_opaque(ldb
, "loadparm", tctx
->lp_ctx
) != LDB_SUCCESS
) {
351 ret
= ldb_connect(ldb
, ldap_url
, 0, modules_option
);
352 if (ret
!= LDB_SUCCESS
) {
354 torture_assert_int_equal(tctx
, ret
, LDB_SUCCESS
, "Failed to make LDB connection to target");
362 static bool _test_provision(struct torture_context
*tctx
, struct DsIntIdTestCtx
*ctx
)
367 struct ldb_ldif
*ldif
;
369 struct ldb_context
*ldb
= ctx
->ldb
;
371 /* We must have LDB connection ready by this time */
372 SMB_ASSERT(ldb
!= NULL
);
374 ctx
->domain_dn
= ldb_dn_get_linearized(ldb_get_default_basedn(ldb
));
375 torture_assert(tctx
, ctx
->domain_dn
!= NULL
, "Failed to get Domain DN");
377 ctx
->config_dn
= ldb_dn_get_linearized(ldb_get_config_basedn(ldb
));
378 torture_assert(tctx
, ctx
->config_dn
!= NULL
, "Failed to get Domain DN");
380 ctx
->schema_dn
= ldb_dn_get_linearized(ldb_get_schema_basedn(ldb
));
381 torture_assert(tctx
, ctx
->schema_dn
!= NULL
, "Failed to get Domain DN");
383 /* prepare LDIF to provision with */
384 attr_id
= generate_random() % 0xFFFF;
385 pstr
= ldif_str
= talloc_asprintf(ctx
, PROVISION_LDIF_FMT
,
386 attr_id
, ctx
->domain_dn
);
388 /* Provision test data */
389 while ((ldif
= ldb_ldif_read_string(ldb
, &pstr
)) != NULL
) {
390 switch (ldif
->changetype
) {
391 case LDB_CHANGETYPE_DELETE
:
392 ret
= ldb_delete(ldb
, ldif
->msg
->dn
);
394 case LDB_CHANGETYPE_MODIFY
:
395 ret
= ldb_modify(ldb
, ldif
->msg
);
397 case LDB_CHANGETYPE_ADD
:
399 ret
= ldb_add(ldb
, ldif
->msg
);
402 if (ret
!= LDB_SUCCESS
) {
403 char *msg
= talloc_asprintf(ctx
,
404 "Failed to apply ldif - %s (%s): \n%s",
407 ldb_ldif_write_string(ldb
, ctx
, ldif
));
408 torture_fail(tctx
, msg
);
411 ldb_ldif_read_free(ldb
, ldif
);
418 static bool _test_GetNCChanges(struct torture_context
*tctx
,
419 struct DsaBindInfo
*bi
,
420 const char *nc_dn_str
,
422 struct drsuapi_DsGetNCChangesCtr6
**_ctr6
)
425 struct drsuapi_DsGetNCChanges r
;
426 union drsuapi_DsGetNCChangesRequest req
;
427 struct drsuapi_DsReplicaObjectIdentifier nc
;
428 struct drsuapi_DsGetNCChangesCtr6
*ctr6_chunk
= NULL
;
429 struct drsuapi_DsGetNCChangesCtr6 ctr6
;
431 union drsuapi_DsGetNCChangesCtr ctr
;
433 struct dom_sid null_sid
;
435 ZERO_STRUCT(null_sid
);
437 /* fill-in Naming Context */
438 nc
.guid
= GUID_zero();
442 /* fill-in request fields */
443 req
.req8
.destination_dsa_guid
= GUID_random();
444 req
.req8
.source_dsa_invocation_id
= GUID_zero();
445 req
.req8
.naming_context
= &nc
;
446 req
.req8
.highwatermark
.tmp_highest_usn
= 0;
447 req
.req8
.highwatermark
.reserved_usn
= 0;
448 req
.req8
.highwatermark
.highest_usn
= 0;
449 req
.req8
.uptodateness_vector
= NULL
;
450 req
.req8
.replica_flags
= DRSUAPI_DRS_WRIT_REP
451 | DRSUAPI_DRS_INIT_SYNC
452 | DRSUAPI_DRS_PER_SYNC
453 | DRSUAPI_DRS_GET_ANC
454 | DRSUAPI_DRS_NEVER_SYNCED
456 req
.req8
.max_object_count
= 402;
457 req
.req8
.max_ndr_size
= 402116;
459 req
.req8
.extended_op
= DRSUAPI_EXOP_NONE
;
460 req
.req8
.fsmo_info
= 0;
461 req
.req8
.partial_attribute_set
= NULL
;
462 req
.req8
.partial_attribute_set_ex
= NULL
;
463 req
.req8
.mapping_ctr
.num_mappings
= 0;
464 req
.req8
.mapping_ctr
.mappings
= NULL
;
466 r
.in
.bind_handle
= &bi
->rpc_handle
;
471 r
.out
.level_out
= &_level
;
478 status
= dcerpc_drsuapi_DsGetNCChanges_r(bi
->drs_handle
, mem_ctx
, &r
);
479 torture_drsuapi_assert_call(tctx
, bi
->drs_pipe
, status
,
480 &r
, "dcerpc_drsuapi_DsGetNCChanges_r");
482 /* we expect to get level 6 reply */
483 torture_assert_int_equal(tctx
, _level
, 6, "Expected level 6 reply");
485 /* store this chunk for later use */
486 ctr6_chunk
= &r
.out
.ctr
->ctr6
;
488 if (!ctr6
.first_object
) {
491 struct drsuapi_DsReplicaObjectListItemEx
*cur
;
493 ctr6
.object_count
+= ctr6_chunk
->object_count
;
494 for (cur
= ctr6
.first_object
; cur
->next_object
; cur
= cur
->next_object
) {}
495 cur
->next_object
= ctr6_chunk
->first_object
;
497 if (ctr6_chunk
->linked_attributes_count
!= 0) {
499 ctr6
.linked_attributes
= talloc_realloc(mem_ctx
, ctr6
.linked_attributes
,
500 struct drsuapi_DsReplicaLinkedAttribute
,
501 ctr6
.linked_attributes_count
+ ctr6_chunk
->linked_attributes_count
);
502 for (i
= 0; i
< ctr6_chunk
->linked_attributes_count
; i
++) {
503 ctr6
.linked_attributes
[ctr6
.linked_attributes_count
++] = ctr6_chunk
->linked_attributes
[i
];
508 /* prepare for next request */
509 r
.in
.req
->req8
.highwatermark
= ctr6_chunk
->new_highwatermark
;
511 } while (ctr6_chunk
->more_data
);
513 *_ctr6
= talloc(mem_ctx
, struct drsuapi_DsGetNCChangesCtr6
);
514 torture_assert(mem_ctx
, *_ctr6
, "Not enough memory");
520 static char * _make_error_message(TALLOC_CTX
*mem_ctx
,
521 enum drsuapi_DsAttributeId drs_attid
,
522 const struct dsdb_attribute
*dsdb_attr
,
523 const struct drsuapi_DsReplicaObjectIdentifier
*identifier
)
525 return talloc_asprintf(mem_ctx
, "\nInvalid ATTID for %1$s (%2$s)\n"
526 " drs_attid: %3$11d (0x%3$08X)\n"
527 " msDS_IntId: %4$11d (0x%4$08X)\n"
528 " attributeId_id: %5$11d (0x%5$08X)",
529 dsdb_attr
->lDAPDisplayName
,
532 dsdb_attr
->msDS_IntId
,
533 dsdb_attr
->attributeID_id
);
537 * Fetch Schema NC and check ATTID values returned.
538 * When Schema partition is replicated, ATTID
539 * should always be made using prefixMap
541 static bool test_dsintid_schema(struct torture_context
*tctx
, struct DsIntIdTestCtx
*ctx
)
544 const struct dsdb_schema
*ldap_schema
;
545 struct drsuapi_DsGetNCChangesCtr6
*ctr6
= NULL
;
546 const struct dsdb_attribute
*dsdb_attr
;
547 const struct drsuapi_DsReplicaAttribute
*drs_attr
;
548 const struct drsuapi_DsReplicaAttributeCtr
*attr_ctr
;
549 const struct drsuapi_DsReplicaObjectListItemEx
*cur
;
550 const struct drsuapi_DsReplicaLinkedAttribute
*la
;
553 mem_ctx
= talloc_new(ctx
);
554 torture_assert(tctx
, mem_ctx
, "Not enough memory");
556 /* fetch whole Schema partition */
557 torture_comment(tctx
, "Fetch partition: %s\n", ctx
->schema_dn
);
558 if (!_test_GetNCChanges(tctx
, &ctx
->dsa_bind
, ctx
->schema_dn
, mem_ctx
, &ctr6
)) {
559 torture_fail(tctx
, "_test_GetNCChanges() failed");
562 /* load schema if not loaded yet */
563 torture_comment(tctx
, "Loading schema...\n");
564 if (!drs_util_dsdb_schema_load_ldb(tctx
, ctx
->ldb
, &ctr6
->mapping_ctr
, false)) {
565 torture_fail(tctx
, "drs_util_dsdb_schema_load_ldb() failed");
567 ldap_schema
= dsdb_get_schema(ctx
->ldb
, NULL
);
569 /* verify ATTIDs fetched */
570 torture_comment(tctx
, "Verify ATTIDs fetched\n");
571 for (cur
= ctr6
->first_object
; cur
; cur
= cur
->next_object
) {
572 attr_ctr
= &cur
->object
.attribute_ctr
;
573 for (i
= 0; i
< attr_ctr
->num_attributes
; i
++) {
574 drs_attr
= &attr_ctr
->attributes
[i
];
575 dsdb_attr
= dsdb_attribute_by_attributeID_id(ldap_schema
,
579 drs_attr
->attid
== dsdb_attr
->attributeID_id
,
580 _make_error_message(ctx
, drs_attr
->attid
,
582 cur
->object
.identifier
));
583 if (dsdb_attr
->msDS_IntId
) {
585 drs_attr
->attid
!= dsdb_attr
->msDS_IntId
,
586 _make_error_message(ctx
, drs_attr
->attid
,
588 cur
->object
.identifier
));
593 /* verify ATTIDs for Linked Attributes */
594 torture_comment(tctx
, "Verify ATTIDs for Linked Attributes (%u)\n",
595 ctr6
->linked_attributes_count
);
596 for (i
= 0; i
< ctr6
->linked_attributes_count
; i
++) {
597 la
= &ctr6
->linked_attributes
[i
];
598 dsdb_attr
= dsdb_attribute_by_attributeID_id(ldap_schema
, la
->attid
);
601 la
->attid
== dsdb_attr
->attributeID_id
,
602 _make_error_message(ctx
, la
->attid
,
605 if (dsdb_attr
->msDS_IntId
) {
607 la
->attid
!= dsdb_attr
->msDS_IntId
,
608 _make_error_message(ctx
, la
->attid
,
614 talloc_free(mem_ctx
);
620 * Fetch non-Schema NC and check ATTID values returned.
621 * When non-Schema partition is replicated, ATTID
622 * should be msDS-IntId value for the attribute
623 * if this value exists
625 static bool _test_dsintid(struct torture_context
*tctx
,
626 struct DsIntIdTestCtx
*ctx
,
627 const char *nc_dn_str
)
630 const struct dsdb_schema
*ldap_schema
;
631 struct drsuapi_DsGetNCChangesCtr6
*ctr6
= NULL
;
632 const struct dsdb_attribute
*dsdb_attr
;
633 const struct drsuapi_DsReplicaAttribute
*drs_attr
;
634 const struct drsuapi_DsReplicaAttributeCtr
*attr_ctr
;
635 const struct drsuapi_DsReplicaObjectListItemEx
*cur
;
636 const struct drsuapi_DsReplicaLinkedAttribute
*la
;
639 mem_ctx
= talloc_new(ctx
);
640 torture_assert(tctx
, mem_ctx
, "Not enough memory");
642 /* fetch whole Schema partition */
643 torture_comment(tctx
, "Fetch partition: %s\n", nc_dn_str
);
644 if (!_test_GetNCChanges(tctx
, &ctx
->dsa_bind
, nc_dn_str
, mem_ctx
, &ctr6
)) {
645 torture_fail(tctx
, "_test_GetNCChanges() failed");
648 /* load schema if not loaded yet */
649 torture_comment(tctx
, "Loading schema...\n");
650 if (!drs_util_dsdb_schema_load_ldb(tctx
, ctx
->ldb
, &ctr6
->mapping_ctr
, false)) {
651 torture_fail(tctx
, "drs_util_dsdb_schema_load_ldb() failed");
653 ldap_schema
= dsdb_get_schema(ctx
->ldb
, NULL
);
655 /* verify ATTIDs fetched */
656 torture_comment(tctx
, "Verify ATTIDs fetched\n");
657 for (cur
= ctr6
->first_object
; cur
; cur
= cur
->next_object
) {
658 attr_ctr
= &cur
->object
.attribute_ctr
;
659 for (i
= 0; i
< attr_ctr
->num_attributes
; i
++) {
660 drs_attr
= &attr_ctr
->attributes
[i
];
661 dsdb_attr
= dsdb_attribute_by_attributeID_id(ldap_schema
,
663 if (dsdb_attr
->msDS_IntId
) {
665 drs_attr
->attid
== dsdb_attr
->msDS_IntId
,
666 _make_error_message(ctx
, drs_attr
->attid
,
668 cur
->object
.identifier
));
671 drs_attr
->attid
== dsdb_attr
->attributeID_id
,
672 _make_error_message(ctx
, drs_attr
->attid
,
674 cur
->object
.identifier
));
679 /* verify ATTIDs for Linked Attributes */
680 torture_comment(tctx
, "Verify ATTIDs for Linked Attributes (%u)\n",
681 ctr6
->linked_attributes_count
);
682 for (i
= 0; i
< ctr6
->linked_attributes_count
; i
++) {
683 la
= &ctr6
->linked_attributes
[i
];
684 dsdb_attr
= dsdb_attribute_by_attributeID_id(ldap_schema
, la
->attid
);
686 if (dsdb_attr
->msDS_IntId
) {
688 la
->attid
== dsdb_attr
->msDS_IntId
,
689 _make_error_message(ctx
, la
->attid
,
694 la
->attid
== dsdb_attr
->attributeID_id
,
695 _make_error_message(ctx
, la
->attid
,
701 talloc_free(mem_ctx
);
707 * Fetch Domain NC and check ATTID values returned.
708 * When Domain partition is replicated, ATTID
709 * should be msDS-IntId value for the attribute
710 * if this value exists
712 static bool test_dsintid_configuration(struct torture_context
*tctx
, struct DsIntIdTestCtx
*ctx
)
714 return _test_dsintid(tctx
, ctx
, ctx
->config_dn
);
718 * Fetch Configuration NC and check ATTID values returned.
719 * When Configuration partition is replicated, ATTID
720 * should be msDS-IntId value for the attribute
721 * if this value exists
723 static bool test_dsintid_domain(struct torture_context
*tctx
, struct DsIntIdTestCtx
*ctx
)
725 return _test_dsintid(tctx
, ctx
, ctx
->domain_dn
);
730 * DSSYNC test case setup
732 static bool torture_dsintid_tcase_setup(struct torture_context
*tctx
, void **data
)
735 struct DsIntIdTestCtx
*ctx
;
737 *data
= ctx
= _dsintid_create_context(tctx
);
738 torture_assert(tctx
, ctx
, "test_create_context() failed");
740 bret
= _test_DsaBind(tctx
, ctx
, ctx
->creds
,
741 DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8
|
742 DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6
,
744 torture_assert(tctx
, bret
, "_test_DsaBind() failed");
746 bret
= _test_LDAPBind(tctx
, ctx
, ctx
->creds
, ctx
->ldap_url
, &ctx
->ldb
);
747 torture_assert(tctx
, bret
, "_test_LDAPBind() failed");
749 bret
= _test_provision(tctx
, ctx
);
750 torture_assert(tctx
, bret
, "_test_provision() failed");
756 * DSSYNC test case cleanup
758 static bool torture_dsintid_tcase_teardown(struct torture_context
*tctx
, void *data
)
760 struct DsIntIdTestCtx
*ctx
;
761 struct drsuapi_DsUnbind r
;
762 struct policy_handle bind_handle
;
764 ctx
= talloc_get_type(data
, struct DsIntIdTestCtx
);
767 r
.out
.bind_handle
= &bind_handle
;
769 /* Release DRSUAPI handle */
770 r
.in
.bind_handle
= &ctx
->dsa_bind
.rpc_handle
;
771 dcerpc_drsuapi_DsUnbind_r(ctx
->dsa_bind
.drs_handle
, ctx
, &r
);
779 * DSSYNC test case implementation
781 void torture_drs_rpc_dsintid_tcase(struct torture_suite
*suite
)
783 typedef bool (*run_func
) (struct torture_context
*test
, void *tcase_data
);
784 struct torture_tcase
*tcase
= torture_suite_add_tcase(suite
, "msDSIntId");
786 torture_tcase_set_fixture(tcase
,
787 torture_dsintid_tcase_setup
,
788 torture_dsintid_tcase_teardown
);
790 torture_tcase_add_simple_test(tcase
, "Schema", (run_func
)test_dsintid_schema
);
791 torture_tcase_add_simple_test(tcase
, "Configuration", (run_func
)test_dsintid_configuration
);
792 torture_tcase_add_simple_test(tcase
, "Domain", (run_func
)test_dsintid_domain
);