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/popt_common.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"
37 struct DsSyncBindInfo
{
38 struct dcerpc_pipe
*drs_pipe
;
39 struct dcerpc_binding_handle
*drs_handle
;
40 struct drsuapi_DsBind req
;
41 struct GUID bind_guid
;
42 struct drsuapi_DsBindInfoCtr our_bind_info_ctr
;
43 struct drsuapi_DsBindInfo28 our_bind_info28
;
44 struct drsuapi_DsBindInfo28 peer_bind_info28
;
45 struct policy_handle bind_handle
;
49 struct dcerpc_binding
*server_binding
;
51 struct dcerpc_pipe
*drs_pipe
;
52 struct dcerpc_binding_handle
*drs_handle
;
54 DATA_BLOB gensec_skey
;
55 struct drsuapi_DsBindInfo48 srv_info48
;
56 struct policy_handle rpc_handle
;
59 struct DsIntIdTestCtx
{
61 const char *domain_dn
;
62 const char *config_dn
;
63 const char *schema_dn
;
65 /* what we need to do as 'Administrator' */
66 struct cli_credentials
*creds
;
67 struct DsaBindInfo dsa_bind
;
68 struct ldb_context
*ldb
;
72 /* Format string to create provision LDIF with */
73 #define PROVISION_LDIF_FMT \
74 "###########################################################\n" \
75 "# Format string with positional params:\n" \
76 "# 1 - (int) Unique ID between 1 and 2^16\n" \
77 "# 2 - (string) Domain DN\n" \
78 "###########################################################\n" \
80 "###########################################################\n" \
82 "###########################################################\n" \
83 "dn: CN=msds-intid-%1$d,CN=Schema,CN=Configuration,%2$s\n" \
85 "objectClass: top\n" \
86 "objectClass: attributeSchema\n" \
87 "cn: msds-intid-%1$d\n" \
88 "attributeID: 1.3.6.1.4.1.7165.4.6.1.%1$d.1.5.9940\n" \
89 "attributeSyntax: 2.5.5.10\n" \
92 "isSingleValued: TRUE\n" \
93 "systemOnly: FALSE\n" \
95 "# schemaUpdateNow\n" \
97 "changeType: modify\n" \
98 "add: schemaUpdateNow\n" \
99 "schemaUpdateNow: 1\n" \
102 "###########################################################\n" \
103 "# Update schema (with linked attribute)\n" \
104 "###########################################################\n" \
105 "dn: CN=msds-intid-link-%1$d,CN=Schema,CN=Configuration,%2$s\n" \
106 "changetype: add\n" \
107 "objectClass: top\n" \
108 "objectClass: attributeSchema\n" \
109 "cn: msds-intid-link-%1$d\n" \
110 "attributeID: 1.3.6.1.4.1.7165.4.6.1.%1$d.1.5.9941\n" \
111 "attributeSyntax: 2.5.5.1\n" \
113 "instanceType: 4\n" \
114 "isSingleValued: TRUE\n" \
115 "systemOnly: FALSE\n" \
116 "linkID: 1.2.840.113556.1.2.50\n" \
118 "# schemaUpdateNow\n" \
120 "changeType: modify\n" \
121 "add: schemaUpdateNow\n" \
122 "schemaUpdateNow: 1\n" \
125 "###########################################################\n" \
126 "# Update User class\n" \
127 "###########################################################\n" \
128 "dn: CN=User,CN=Schema,CN=Configuration,%2$s\n" \
129 "changetype: modify\n" \
130 "add: mayContain\n" \
131 "mayContain: msdsIntid%1$d\n" \
132 "mayContain: msdsIntidLink%1$d\n" \
135 "# schemaUpdateNow\n" \
137 "changeType: modify\n" \
138 "add: schemaUpdateNow\n" \
139 "schemaUpdateNow: 1\n" \
142 "###########################################################\n" \
143 "# create user to test with\n" \
144 "###########################################################\n" \
145 "dn: CN=dsIntId_usr_%1$d,CN=Users,%2$s\n" \
146 "changetype: add\n" \
147 "objectClass: user\n" \
148 "cn: dsIntId_usr_%1$d\n" \
149 "name: dsIntId_usr_%1$d\n" \
150 "displayName: dsIntId_usr_%1$d\n" \
151 "sAMAccountName: dsIntId_usr_%1$d\n" \
152 "msdsIntid%1$d: msDS-IntId-%1$d attribute value\n" \
153 "msdsIntidLink%1$d: %2$s\n" \
157 static struct DsIntIdTestCtx
*_dsintid_create_context(struct torture_context
*tctx
)
160 struct DsIntIdTestCtx
*ctx
;
161 struct dcerpc_binding
*server_binding
;
162 const char *binding
= torture_setting_string(tctx
, "binding", NULL
);
164 /* Create test suite context */
165 ctx
= talloc_zero(tctx
, struct DsIntIdTestCtx
);
167 torture_result(tctx
, TORTURE_FAIL
, "Not enough memory!");
171 /* parse binding object */
172 status
= dcerpc_parse_binding(ctx
, binding
, &server_binding
);
173 if (!NT_STATUS_IS_OK(status
)) {
174 torture_result(tctx
, TORTURE_FAIL
,
175 "Bad binding string '%s': %s", binding
, nt_errstr(status
));
179 status
= dcerpc_binding_set_flags(server_binding
,
180 DCERPC_SIGN
| DCERPC_SEAL
, 0);
181 if (!NT_STATUS_IS_OK(status
)) {
182 torture_result(tctx
, TORTURE_FAIL
,
183 "dcerpc_binding_set_flags: %s", nt_errstr(status
));
187 /* populate test suite context */
188 ctx
->creds
= popt_get_cmdline_credentials();
189 ctx
->dsa_bind
.server_binding
= server_binding
;
191 ctx
->ldap_url
= talloc_asprintf(ctx
, "ldap://%s",
192 dcerpc_binding_get_string_option(server_binding
, "host"));
197 static bool _test_DsaBind(struct torture_context
*tctx
,
199 struct cli_credentials
*credentials
,
200 uint32_t req_extensions
,
201 struct DsaBindInfo
*bi
)
204 struct GUID bind_guid
;
205 struct drsuapi_DsBind r
;
206 struct drsuapi_DsBindInfoCtr bind_info_ctr
;
207 uint32_t supported_extensions
;
209 /* make DCE RPC connection */
210 status
= dcerpc_pipe_connect_b(mem_ctx
,
214 credentials
, tctx
->ev
, tctx
->lp_ctx
);
215 torture_assert_ntstatus_ok(tctx
, status
, "Failed to connect to server");
217 bi
->drs_handle
= bi
->drs_pipe
->binding_handle
;
219 status
= gensec_session_key(bi
->drs_pipe
->conn
->security_state
.generic_state
,
220 mem_ctx
, &bi
->gensec_skey
);
221 torture_assert_ntstatus_ok(tctx
, status
, "failed to get gensec session key");
223 /* Bind to DRSUAPI interface */
224 GUID_from_string(DRSUAPI_DS_BIND_GUID_W2K3
, &bind_guid
);
227 * Add flags that should be 1, according to MS docs.
228 * It turns out DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3
229 * is actually required in order for GetNCChanges() to
230 * return schemaInfo entry in the prefixMap returned.
231 * Use DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION so
232 * we are able to fetch sensitive data.
234 supported_extensions
= req_extensions
235 | DRSUAPI_SUPPORTED_EXTENSION_BASE
236 | DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION
237 | DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD
238 | DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3
239 | DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION
;
241 ZERO_STRUCT(bind_info_ctr
);
242 bind_info_ctr
.length
= 28;
243 bind_info_ctr
.info
.info28
.supported_extensions
= supported_extensions
;
245 r
.in
.bind_guid
= &bind_guid
;
246 r
.in
.bind_info
= &bind_info_ctr
;
247 r
.out
.bind_handle
= &bi
->rpc_handle
;
249 status
= dcerpc_drsuapi_DsBind_r(bi
->drs_handle
, mem_ctx
, &r
);
250 torture_drsuapi_assert_call(tctx
, bi
->drs_pipe
, status
,
251 &r
, "dcerpc_drsuapi_DsBind_r");
254 switch (r
.out
.bind_info
->length
) {
256 struct drsuapi_DsBindInfo24
*info24
;
257 info24
= &r
.out
.bind_info
->info
.info24
;
258 bi
->srv_info48
.supported_extensions
= info24
->supported_extensions
;
259 bi
->srv_info48
.site_guid
= info24
->site_guid
;
260 bi
->srv_info48
.pid
= info24
->pid
;
264 struct drsuapi_DsBindInfo28
*info28
;
265 info28
= &r
.out
.bind_info
->info
.info28
;
266 bi
->srv_info48
.supported_extensions
= info28
->supported_extensions
;
267 bi
->srv_info48
.site_guid
= info28
->site_guid
;
268 bi
->srv_info48
.pid
= info28
->pid
;
269 bi
->srv_info48
.repl_epoch
= info28
->repl_epoch
;
273 struct drsuapi_DsBindInfo32
*info32
;
274 info32
= &r
.out
.bind_info
->info
.info32
;
275 bi
->srv_info48
.supported_extensions
= info32
->supported_extensions
;
276 bi
->srv_info48
.site_guid
= info32
->site_guid
;
277 bi
->srv_info48
.pid
= info32
->pid
;
278 bi
->srv_info48
.repl_epoch
= info32
->repl_epoch
;
282 bi
->srv_info48
= r
.out
.bind_info
->info
.info48
;
286 struct drsuapi_DsBindInfo52
*info52
;
287 info52
= &r
.out
.bind_info
->info
.info52
;
288 bi
->srv_info48
.supported_extensions
= info52
->supported_extensions
;
289 bi
->srv_info48
.site_guid
= info52
->site_guid
;
290 bi
->srv_info48
.pid
= info52
->pid
;
291 bi
->srv_info48
.repl_epoch
= info52
->repl_epoch
;
295 torture_result(tctx
, TORTURE_FAIL
,
296 "DsBind: unknown BindInfo length: %u",
297 r
.out
.bind_info
->length
);
301 /* check if server supports extensions we've requested */
302 if ((bi
->srv_info48
.supported_extensions
& req_extensions
) != req_extensions
) {
303 torture_result(tctx
, TORTURE_FAIL
,
304 "Server does not support requested extensions. "
305 "Requested: 0x%08X, Supported: 0x%08X",
306 req_extensions
, bi
->srv_info48
.supported_extensions
);
313 static bool _test_LDAPBind(struct torture_context
*tctx
,
315 struct cli_credentials
*credentials
,
316 const char *ldap_url
,
317 struct ldb_context
**_ldb
)
321 struct ldb_context
*ldb
;
323 const char *modules_option
[] = { "modules:paged_searches", NULL
};
324 ldb
= ldb_init(mem_ctx
, tctx
->ev
);
329 /* Despite us loading the schema from the AD server, we need
330 * the samba handlers to get the extended DN syntax stuff */
331 ret
= ldb_register_samba_handlers(ldb
);
332 if (ret
!= LDB_SUCCESS
) {
337 ldb_set_modules_dir(ldb
, modules_path(ldb
, "ldb"));
339 if (ldb_set_opaque(ldb
, "credentials", credentials
) != LDB_SUCCESS
) {
344 if (ldb_set_opaque(ldb
, "loadparm", tctx
->lp_ctx
) != LDB_SUCCESS
) {
349 ret
= ldb_connect(ldb
, ldap_url
, 0, modules_option
);
350 if (ret
!= LDB_SUCCESS
) {
352 torture_assert_int_equal(tctx
, ret
, LDB_SUCCESS
, "Failed to make LDB connection to target");
360 static bool _test_provision(struct torture_context
*tctx
, struct DsIntIdTestCtx
*ctx
)
365 struct ldb_ldif
*ldif
;
367 struct ldb_context
*ldb
= ctx
->ldb
;
369 /* We must have LDB connection ready by this time */
370 SMB_ASSERT(ldb
!= NULL
);
372 ctx
->domain_dn
= ldb_dn_get_linearized(ldb_get_default_basedn(ldb
));
373 torture_assert(tctx
, ctx
->domain_dn
!= NULL
, "Failed to get Domain DN");
375 ctx
->config_dn
= ldb_dn_get_linearized(ldb_get_config_basedn(ldb
));
376 torture_assert(tctx
, ctx
->config_dn
!= NULL
, "Failed to get Domain DN");
378 ctx
->schema_dn
= ldb_dn_get_linearized(ldb_get_schema_basedn(ldb
));
379 torture_assert(tctx
, ctx
->schema_dn
!= NULL
, "Failed to get Domain DN");
381 /* prepare LDIF to provision with */
382 attr_id
= generate_random() % 0xFFFF;
383 pstr
= ldif_str
= talloc_asprintf(ctx
, PROVISION_LDIF_FMT
,
384 attr_id
, ctx
->domain_dn
);
386 /* Provision test data */
387 while ((ldif
= ldb_ldif_read_string(ldb
, &pstr
)) != NULL
) {
388 switch (ldif
->changetype
) {
389 case LDB_CHANGETYPE_DELETE
:
390 ret
= ldb_delete(ldb
, ldif
->msg
->dn
);
392 case LDB_CHANGETYPE_MODIFY
:
393 ret
= ldb_modify(ldb
, ldif
->msg
);
395 case LDB_CHANGETYPE_ADD
:
397 ret
= ldb_add(ldb
, ldif
->msg
);
400 if (ret
!= LDB_SUCCESS
) {
401 char *msg
= talloc_asprintf(ctx
,
402 "Failed to apply ldif - %s (%s): \n%s",
405 ldb_ldif_write_string(ldb
, ctx
, ldif
));
406 torture_fail(tctx
, msg
);
409 ldb_ldif_read_free(ldb
, ldif
);
416 static bool _test_GetNCChanges(struct torture_context
*tctx
,
417 struct DsaBindInfo
*bi
,
418 const char *nc_dn_str
,
420 struct drsuapi_DsGetNCChangesCtr6
**_ctr6
)
423 struct drsuapi_DsGetNCChanges r
;
424 union drsuapi_DsGetNCChangesRequest req
;
425 struct drsuapi_DsReplicaObjectIdentifier nc
;
426 struct drsuapi_DsGetNCChangesCtr6
*ctr6_chunk
= NULL
;
427 struct drsuapi_DsGetNCChangesCtr6 ctr6
;
429 union drsuapi_DsGetNCChangesCtr ctr
;
431 struct dom_sid null_sid
;
433 ZERO_STRUCT(null_sid
);
435 /* fill-in Naming Context */
436 nc
.guid
= GUID_zero();
440 /* fill-in request fields */
441 req
.req8
.destination_dsa_guid
= GUID_random();
442 req
.req8
.source_dsa_invocation_id
= GUID_zero();
443 req
.req8
.naming_context
= &nc
;
444 req
.req8
.highwatermark
.tmp_highest_usn
= 0;
445 req
.req8
.highwatermark
.reserved_usn
= 0;
446 req
.req8
.highwatermark
.highest_usn
= 0;
447 req
.req8
.uptodateness_vector
= NULL
;
448 req
.req8
.replica_flags
= DRSUAPI_DRS_WRIT_REP
449 | DRSUAPI_DRS_INIT_SYNC
450 | DRSUAPI_DRS_PER_SYNC
451 | DRSUAPI_DRS_GET_ANC
452 | DRSUAPI_DRS_NEVER_SYNCED
454 req
.req8
.max_object_count
= 402;
455 req
.req8
.max_ndr_size
= 402116;
457 req
.req8
.extended_op
= DRSUAPI_EXOP_NONE
;
458 req
.req8
.fsmo_info
= 0;
459 req
.req8
.partial_attribute_set
= NULL
;
460 req
.req8
.partial_attribute_set_ex
= NULL
;
461 req
.req8
.mapping_ctr
.num_mappings
= 0;
462 req
.req8
.mapping_ctr
.mappings
= NULL
;
464 r
.in
.bind_handle
= &bi
->rpc_handle
;
469 r
.out
.level_out
= &_level
;
476 status
= dcerpc_drsuapi_DsGetNCChanges_r(bi
->drs_handle
, mem_ctx
, &r
);
477 torture_drsuapi_assert_call(tctx
, bi
->drs_pipe
, status
,
478 &r
, "dcerpc_drsuapi_DsGetNCChanges_r");
480 /* we expect to get level 6 reply */
481 torture_assert_int_equal(tctx
, _level
, 6, "Expected level 6 reply");
483 /* store this chunk for later use */
484 ctr6_chunk
= &r
.out
.ctr
->ctr6
;
486 if (!ctr6
.first_object
) {
489 struct drsuapi_DsReplicaObjectListItemEx
*cur
;
491 ctr6
.object_count
+= ctr6_chunk
->object_count
;
492 for (cur
= ctr6
.first_object
; cur
->next_object
; cur
= cur
->next_object
) {}
493 cur
->next_object
= ctr6_chunk
->first_object
;
495 if (ctr6_chunk
->linked_attributes_count
!= 0) {
497 ctr6
.linked_attributes
= talloc_realloc(mem_ctx
, ctr6
.linked_attributes
,
498 struct drsuapi_DsReplicaLinkedAttribute
,
499 ctr6
.linked_attributes_count
+ ctr6_chunk
->linked_attributes_count
);
500 for (i
= 0; i
< ctr6_chunk
->linked_attributes_count
; i
++) {
501 ctr6
.linked_attributes
[ctr6
.linked_attributes_count
++] = ctr6_chunk
->linked_attributes
[i
];
506 /* prepare for next request */
507 r
.in
.req
->req8
.highwatermark
= ctr6_chunk
->new_highwatermark
;
509 } while (ctr6_chunk
->more_data
);
511 *_ctr6
= talloc(mem_ctx
, struct drsuapi_DsGetNCChangesCtr6
);
512 torture_assert(mem_ctx
, *_ctr6
, "Not enough memory");
518 static char * _make_error_message(TALLOC_CTX
*mem_ctx
,
519 enum drsuapi_DsAttributeId drs_attid
,
520 const struct dsdb_attribute
*dsdb_attr
,
521 const struct drsuapi_DsReplicaObjectIdentifier
*identifier
)
523 return talloc_asprintf(mem_ctx
, "\nInvalid ATTID for %1$s (%2$s)\n"
524 " drs_attid: %3$11d (0x%3$08X)\n"
525 " msDS_IntId: %4$11d (0x%4$08X)\n"
526 " attributeId_id: %5$11d (0x%5$08X)",
527 dsdb_attr
->lDAPDisplayName
,
530 dsdb_attr
->msDS_IntId
,
531 dsdb_attr
->attributeID_id
);
535 * Fetch Schema NC and check ATTID values returned.
536 * When Schema partition is replicated, ATTID
537 * should always be made using prefixMap
539 static bool test_dsintid_schema(struct torture_context
*tctx
, struct DsIntIdTestCtx
*ctx
)
542 const struct dsdb_schema
*ldap_schema
;
543 struct drsuapi_DsGetNCChangesCtr6
*ctr6
= NULL
;
544 const struct dsdb_attribute
*dsdb_attr
;
545 const struct drsuapi_DsReplicaAttribute
*drs_attr
;
546 const struct drsuapi_DsReplicaAttributeCtr
*attr_ctr
;
547 const struct drsuapi_DsReplicaObjectListItemEx
*cur
;
548 const struct drsuapi_DsReplicaLinkedAttribute
*la
;
551 mem_ctx
= talloc_new(ctx
);
552 torture_assert(tctx
, mem_ctx
, "Not enough memory");
554 /* fetch whole Schema partition */
555 torture_comment(tctx
, "Fetch partition: %s\n", ctx
->schema_dn
);
556 if (!_test_GetNCChanges(tctx
, &ctx
->dsa_bind
, ctx
->schema_dn
, mem_ctx
, &ctr6
)) {
557 torture_fail(tctx
, "_test_GetNCChanges() failed");
560 /* load schema if not loaded yet */
561 torture_comment(tctx
, "Loading schema...\n");
562 if (!drs_util_dsdb_schema_load_ldb(tctx
, ctx
->ldb
, &ctr6
->mapping_ctr
, false)) {
563 torture_fail(tctx
, "drs_util_dsdb_schema_load_ldb() failed");
565 ldap_schema
= dsdb_get_schema(ctx
->ldb
, NULL
);
567 /* verify ATTIDs fetched */
568 torture_comment(tctx
, "Verify ATTIDs fetched\n");
569 for (cur
= ctr6
->first_object
; cur
; cur
= cur
->next_object
) {
570 attr_ctr
= &cur
->object
.attribute_ctr
;
571 for (i
= 0; i
< attr_ctr
->num_attributes
; i
++) {
572 drs_attr
= &attr_ctr
->attributes
[i
];
573 dsdb_attr
= dsdb_attribute_by_attributeID_id(ldap_schema
,
577 drs_attr
->attid
== dsdb_attr
->attributeID_id
,
578 _make_error_message(ctx
, drs_attr
->attid
,
580 cur
->object
.identifier
));
581 if (dsdb_attr
->msDS_IntId
) {
583 drs_attr
->attid
!= dsdb_attr
->msDS_IntId
,
584 _make_error_message(ctx
, drs_attr
->attid
,
586 cur
->object
.identifier
));
591 /* verify ATTIDs for Linked Attributes */
592 torture_comment(tctx
, "Verify ATTIDs for Linked Attributes (%u)\n",
593 ctr6
->linked_attributes_count
);
594 for (i
= 0; i
< ctr6
->linked_attributes_count
; i
++) {
595 la
= &ctr6
->linked_attributes
[i
];
596 dsdb_attr
= dsdb_attribute_by_attributeID_id(ldap_schema
, la
->attid
);
599 la
->attid
== dsdb_attr
->attributeID_id
,
600 _make_error_message(ctx
, la
->attid
,
603 if (dsdb_attr
->msDS_IntId
) {
605 la
->attid
!= dsdb_attr
->msDS_IntId
,
606 _make_error_message(ctx
, la
->attid
,
612 talloc_free(mem_ctx
);
618 * Fetch non-Schema NC and check ATTID values returned.
619 * When non-Schema partition is replicated, ATTID
620 * should be msDS-IntId value for the attribute
621 * if this value exists
623 static bool _test_dsintid(struct torture_context
*tctx
,
624 struct DsIntIdTestCtx
*ctx
,
625 const char *nc_dn_str
)
628 const struct dsdb_schema
*ldap_schema
;
629 struct drsuapi_DsGetNCChangesCtr6
*ctr6
= NULL
;
630 const struct dsdb_attribute
*dsdb_attr
;
631 const struct drsuapi_DsReplicaAttribute
*drs_attr
;
632 const struct drsuapi_DsReplicaAttributeCtr
*attr_ctr
;
633 const struct drsuapi_DsReplicaObjectListItemEx
*cur
;
634 const struct drsuapi_DsReplicaLinkedAttribute
*la
;
637 mem_ctx
= talloc_new(ctx
);
638 torture_assert(tctx
, mem_ctx
, "Not enough memory");
640 /* fetch whole Schema partition */
641 torture_comment(tctx
, "Fetch partition: %s\n", nc_dn_str
);
642 if (!_test_GetNCChanges(tctx
, &ctx
->dsa_bind
, nc_dn_str
, mem_ctx
, &ctr6
)) {
643 torture_fail(tctx
, "_test_GetNCChanges() failed");
646 /* load schema if not loaded yet */
647 torture_comment(tctx
, "Loading schema...\n");
648 if (!drs_util_dsdb_schema_load_ldb(tctx
, ctx
->ldb
, &ctr6
->mapping_ctr
, false)) {
649 torture_fail(tctx
, "drs_util_dsdb_schema_load_ldb() failed");
651 ldap_schema
= dsdb_get_schema(ctx
->ldb
, NULL
);
653 /* verify ATTIDs fetched */
654 torture_comment(tctx
, "Verify ATTIDs fetched\n");
655 for (cur
= ctr6
->first_object
; cur
; cur
= cur
->next_object
) {
656 attr_ctr
= &cur
->object
.attribute_ctr
;
657 for (i
= 0; i
< attr_ctr
->num_attributes
; i
++) {
658 drs_attr
= &attr_ctr
->attributes
[i
];
659 dsdb_attr
= dsdb_attribute_by_attributeID_id(ldap_schema
,
661 if (dsdb_attr
->msDS_IntId
) {
663 drs_attr
->attid
== dsdb_attr
->msDS_IntId
,
664 _make_error_message(ctx
, drs_attr
->attid
,
666 cur
->object
.identifier
));
669 drs_attr
->attid
== dsdb_attr
->attributeID_id
,
670 _make_error_message(ctx
, drs_attr
->attid
,
672 cur
->object
.identifier
));
677 /* verify ATTIDs for Linked Attributes */
678 torture_comment(tctx
, "Verify ATTIDs for Linked Attributes (%u)\n",
679 ctr6
->linked_attributes_count
);
680 for (i
= 0; i
< ctr6
->linked_attributes_count
; i
++) {
681 la
= &ctr6
->linked_attributes
[i
];
682 dsdb_attr
= dsdb_attribute_by_attributeID_id(ldap_schema
, la
->attid
);
684 if (dsdb_attr
->msDS_IntId
) {
686 la
->attid
== dsdb_attr
->msDS_IntId
,
687 _make_error_message(ctx
, la
->attid
,
692 la
->attid
== dsdb_attr
->attributeID_id
,
693 _make_error_message(ctx
, la
->attid
,
699 talloc_free(mem_ctx
);
705 * Fetch Domain NC and check ATTID values returned.
706 * When Domain partition is replicated, ATTID
707 * should be msDS-IntId value for the attribute
708 * if this value exists
710 static bool test_dsintid_configuration(struct torture_context
*tctx
, struct DsIntIdTestCtx
*ctx
)
712 return _test_dsintid(tctx
, ctx
, ctx
->config_dn
);
716 * Fetch Configuration NC and check ATTID values returned.
717 * When Configuration partition is replicated, ATTID
718 * should be msDS-IntId value for the attribute
719 * if this value exists
721 static bool test_dsintid_domain(struct torture_context
*tctx
, struct DsIntIdTestCtx
*ctx
)
723 return _test_dsintid(tctx
, ctx
, ctx
->domain_dn
);
728 * DSSYNC test case setup
730 static bool torture_dsintid_tcase_setup(struct torture_context
*tctx
, void **data
)
733 struct DsIntIdTestCtx
*ctx
;
735 *data
= ctx
= _dsintid_create_context(tctx
);
736 torture_assert(tctx
, ctx
, "test_create_context() failed");
738 bret
= _test_DsaBind(tctx
, ctx
, ctx
->creds
,
739 DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8
|
740 DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6
,
742 torture_assert(tctx
, bret
, "_test_DsaBind() failed");
744 bret
= _test_LDAPBind(tctx
, ctx
, ctx
->creds
, ctx
->ldap_url
, &ctx
->ldb
);
745 torture_assert(tctx
, bret
, "_test_LDAPBind() failed");
747 bret
= _test_provision(tctx
, ctx
);
748 torture_assert(tctx
, bret
, "_test_provision() failed");
754 * DSSYNC test case cleanup
756 static bool torture_dsintid_tcase_teardown(struct torture_context
*tctx
, void *data
)
758 struct DsIntIdTestCtx
*ctx
;
759 struct drsuapi_DsUnbind r
;
760 struct policy_handle bind_handle
;
762 ctx
= talloc_get_type(data
, struct DsIntIdTestCtx
);
765 r
.out
.bind_handle
= &bind_handle
;
767 /* Release DRSUAPI handle */
768 r
.in
.bind_handle
= &ctx
->dsa_bind
.rpc_handle
;
769 dcerpc_drsuapi_DsUnbind_r(ctx
->dsa_bind
.drs_handle
, ctx
, &r
);
777 * DSSYNC test case implementation
779 void torture_drs_rpc_dsintid_tcase(struct torture_suite
*suite
)
781 typedef bool (*run_func
) (struct torture_context
*test
, void *tcase_data
);
782 struct torture_tcase
*tcase
= torture_suite_add_tcase(suite
, "msDSIntId");
784 torture_tcase_set_fixture(tcase
,
785 torture_dsintid_tcase_setup
,
786 torture_dsintid_tcase_teardown
);
788 torture_tcase_add_simple_test(tcase
, "Schema", (run_func
)test_dsintid_schema
);
789 torture_tcase_add_simple_test(tcase
, "Configuration", (run_func
)test_dsintid_configuration
);
790 torture_tcase_add_simple_test(tcase
, "Domain", (run_func
)test_dsintid_domain
);