2 Unix SMB/CIFS mplementation.
5 Copyright (C) Stefan Metzmacher 2006
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "libcli/ldap/ldap_client.h"
24 #include "lib/cmdline/popt_common.h"
26 #include "dsdb/samdb/samdb.h"
27 #include "../lib/util/dlinklist.h"
29 #include "torture/torture.h"
33 const char *defaultdn
;
39 struct test_schema_ctx
{
40 struct ldb_context
*ldb
;
42 struct ldb_paged_control
*ctrl
;
46 int (*callback
)(void *, struct ldb_context
*ldb
, struct ldb_message
*);
50 static bool test_search_rootDSE(struct ldb_context
*ldb
, struct test_rootDSE
*root
)
53 struct ldb_message
*msg
;
56 d_printf("Testing RootDSE Search\n");
58 ret
= ldb_search(ldb
, ldb
, &r
, ldb_dn_new(ldb
, ldb
, NULL
),
59 LDB_SCOPE_BASE
, NULL
, NULL
);
60 if (ret
!= LDB_SUCCESS
) {
62 } else if (r
->count
!= 1) {
69 root
->defaultdn
= ldb_msg_find_attr_as_string(msg
, "defaultNamingContext", NULL
);
70 talloc_steal(ldb
, root
->defaultdn
);
71 root
->rootdn
= ldb_msg_find_attr_as_string(msg
, "rootDomainNamingContext", NULL
);
72 talloc_steal(ldb
, root
->rootdn
);
73 root
->configdn
= ldb_msg_find_attr_as_string(msg
, "configurationNamingContext", NULL
);
74 talloc_steal(ldb
, root
->configdn
);
75 root
->schemadn
= ldb_msg_find_attr_as_string(msg
, "schemaNamingContext", NULL
);
76 talloc_steal(ldb
, root
->schemadn
);
83 static int test_schema_search_callback(struct ldb_request
*req
, struct ldb_reply
*ares
)
85 struct test_schema_ctx
*actx
;
86 int ret
= LDB_SUCCESS
;
88 actx
= talloc_get_type(req
->context
, struct test_schema_ctx
);
91 return ldb_request_done(req
, LDB_ERR_OPERATIONS_ERROR
);
93 if (ares
->error
!= LDB_SUCCESS
) {
94 return ldb_request_done(req
, ares
->error
);
100 ret
= actx
->callback(actx
->private_data
, actx
->ldb
, ares
->message
);
103 case LDB_REPLY_REFERRAL
:
107 if (ares
->controls
) {
108 struct ldb_paged_control
*ctrl
= NULL
;
111 for (i
=0; ares
->controls
[i
]; i
++) {
112 if (strcmp(LDB_CONTROL_PAGED_RESULTS_OID
, ares
->controls
[i
]->oid
) == 0) {
113 ctrl
= talloc_get_type(ares
->controls
[i
]->data
, struct ldb_paged_control
);
120 talloc_free(actx
->ctrl
->cookie
);
121 actx
->ctrl
->cookie
= talloc_steal(actx
->ctrl
->cookie
, ctrl
->cookie
);
122 actx
->ctrl
->cookie_len
= ctrl
->cookie_len
;
124 if (actx
->ctrl
->cookie_len
> 0) {
125 actx
->pending
= true;
129 return ldb_request_done(req
, LDB_SUCCESS
);
132 d_printf("%s: unknown Reply Type %u\n", __location__
, ares
->type
);
133 return ldb_request_done(req
, LDB_ERR_OTHER
);
136 if (talloc_free(ares
) == -1) {
137 d_printf("talloc_free failed\n");
139 return ldb_request_done(req
, LDB_ERR_OPERATIONS_ERROR
);
143 return ldb_request_done(req
, LDB_ERR_OPERATIONS_ERROR
);
149 static bool test_create_schema_type(struct ldb_context
*ldb
, struct test_rootDSE
*root
,
151 int (*callback
)(void *, struct ldb_context
*ldb
, struct ldb_message
*),
154 struct ldb_control
**ctrl
;
155 struct ldb_paged_control
*control
;
156 struct ldb_request
*req
;
158 struct test_schema_ctx
*actx
;
160 actx
= talloc(ldb
, struct test_schema_ctx
);
162 actx
->private_data
= private_data
;
163 actx
->callback
= callback
;
165 ctrl
= talloc_array(actx
, struct ldb_control
*, 2);
166 ctrl
[0] = talloc(ctrl
, struct ldb_control
);
167 ctrl
[0]->oid
= LDB_CONTROL_PAGED_RESULTS_OID
;
168 ctrl
[0]->critical
= true;
169 control
= talloc(ctrl
[0], struct ldb_paged_control
);
170 control
->size
= 1000;
171 control
->cookie
= NULL
;
172 control
->cookie_len
= 0;
173 ctrl
[0]->data
= control
;
176 ret
= ldb_build_search_req(&req
, ldb
, actx
,
177 ldb_dn_new(actx
, ldb
, root
->schemadn
),
181 actx
, test_schema_search_callback
,
184 actx
->ctrl
= control
;
187 actx
->pending
= false;
189 ret
= ldb_request(ldb
, req
);
190 if (ret
!= LDB_SUCCESS
) {
191 d_printf("search failed - %s\n", ldb_errstring(ldb
));
196 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
197 if (ret
!= LDB_SUCCESS
) {
198 d_printf("search error - %s\n", ldb_errstring(ldb
));
206 d_printf("filter[%s] count[%u]\n", filter
, actx
->count
);
211 static int test_add_attribute(void *ptr
, struct ldb_context
*ldb
, struct ldb_message
*msg
)
213 struct dsdb_schema
*schema
= talloc_get_type(ptr
, struct dsdb_schema
);
214 struct dsdb_attribute
*attr
= NULL
;
217 attr
= talloc_zero(schema
, struct dsdb_attribute
);
222 status
= dsdb_attribute_from_ldb(ldb
, schema
, msg
, attr
, attr
);
223 if (!W_ERROR_IS_OK(status
)) {
227 DLIST_ADD_END(schema
->attributes
, attr
, struct dsdb_attribute
*);
231 return LDB_ERR_OTHER
;
234 static int test_add_class(void *ptr
, struct ldb_context
*ldb
, struct ldb_message
*msg
)
236 struct dsdb_schema
*schema
= talloc_get_type(ptr
, struct dsdb_schema
);
237 struct dsdb_class
*obj
;
240 obj
= talloc_zero(schema
, struct dsdb_class
);
245 status
= dsdb_class_from_ldb(schema
, msg
, obj
, obj
);
246 if (!W_ERROR_IS_OK(status
)) {
250 DLIST_ADD_END(schema
->classes
, obj
, struct dsdb_class
*);
253 return LDB_ERR_OTHER
;
256 static bool test_create_schema(struct ldb_context
*ldb
, struct test_rootDSE
*root
, struct dsdb_schema
**_schema
)
259 struct dsdb_schema
*schema
;
261 schema
= talloc_zero(ldb
, struct dsdb_schema
);
263 d_printf("Fetching attributes...\n");
264 ret
&= test_create_schema_type(ldb
, root
, "(objectClass=attributeSchema)",
265 test_add_attribute
, schema
);
266 d_printf("Fetching objectClasses...\n");
267 ret
&= test_create_schema_type(ldb
, root
, "(objectClass=classSchema)",
268 test_add_class
, schema
);
276 static bool test_dump_not_replicated(struct ldb_context
*ldb
, struct test_rootDSE
*root
, struct dsdb_schema
*schema
)
278 struct dsdb_attribute
*a
;
281 d_printf("Dumping not replicated attributes\n");
283 for (a
=schema
->attributes
; a
; a
= a
->next
) {
284 if (!(a
->systemFlags
& 0x00000001)) continue;
285 d_printf("attr[%4u]: '%s'\n", a_i
++,
292 static bool test_dump_partial(struct ldb_context
*ldb
, struct test_rootDSE
*root
, struct dsdb_schema
*schema
)
294 struct dsdb_attribute
*a
;
297 d_printf("Dumping attributes which are provided by the global catalog\n");
299 for (a
=schema
->attributes
; a
; a
= a
->next
) {
300 if (!(a
->systemFlags
& 0x00000002) && !a
->isMemberOfPartialAttributeSet
) continue;
301 d_printf("attr[%4u]: %u %u '%s'\n", a_i
++,
302 a
->systemFlags
& 0x00000002, a
->isMemberOfPartialAttributeSet
,
309 static bool test_dump_contructed(struct ldb_context
*ldb
, struct test_rootDSE
*root
, struct dsdb_schema
*schema
)
311 struct dsdb_attribute
*a
;
314 d_printf("Dumping constructed attributes\n");
316 for (a
=schema
->attributes
; a
; a
= a
->next
) {
317 if (!(a
->systemFlags
& 0x00000004)) continue;
318 d_printf("attr[%4u]: '%s'\n", a_i
++,
325 static bool test_dump_sorted_syntax(struct ldb_context
*ldb
, struct test_rootDSE
*root
, struct dsdb_schema
*schema
)
327 struct dsdb_attribute
*a
;
330 const char *syntaxes
[] = {
351 d_printf("Dumping attribute syntaxes\n");
353 for (i
=0; i
< ARRAY_SIZE(syntaxes
); i
++) {
354 for (a
=schema
->attributes
; a
; a
= a
->next
) {
357 if (strcmp(syntaxes
[i
], a
->attributeSyntax_oid
) != 0) continue;
359 om_hex
= data_blob_hex_string_upper(ldb
, &a
->oMObjectClass
);
364 d_printf("attr[%4u]: %s %u '%s' '%s'\n", a_i
++,
365 a
->attributeSyntax_oid
, a
->oMSyntax
,
366 om_hex
, a
->lDAPDisplayName
);
374 bool torture_ldap_schema(struct torture_context
*torture
)
376 struct ldb_context
*ldb
;
378 const char *host
= torture_setting_string(torture
, "host", NULL
);
380 struct test_rootDSE rootDSE
;
381 struct dsdb_schema
*schema
= NULL
;
383 ZERO_STRUCT(rootDSE
);
385 url
= talloc_asprintf(torture
, "ldap://%s/", host
);
387 ldb
= ldb_wrap_connect(torture
, torture
->ev
, torture
->lp_ctx
, url
,
391 if (!ldb
) goto failed
;
393 ret
&= test_search_rootDSE(ldb
, &rootDSE
);
394 if (!ret
) goto failed
;
395 ret
&= test_create_schema(ldb
, &rootDSE
, &schema
);
396 if (!ret
) goto failed
;
398 ret
&= test_dump_not_replicated(ldb
, &rootDSE
, schema
);
399 ret
&= test_dump_partial(ldb
, &rootDSE
, schema
);
400 ret
&= test_dump_contructed(ldb
, &rootDSE
, schema
);
401 ret
&= test_dump_sorted_syntax(ldb
, &rootDSE
, schema
);