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 "lib/ldb/include/ldb.h"
27 #include "lib/ldb/include/ldb_errors.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "lib/util/dlinklist.h"
31 #include "torture/torture.h"
32 #include "torture/ldap/proto.h"
34 #include "param/param.h"
37 const char *defaultdn
;
43 struct test_schema_ctx
{
44 struct ldb_paged_control
*ctrl
;
48 int (*callback
)(void *, struct ldb_context
*ldb
, struct ldb_message
*);
52 static bool test_search_rootDSE(struct ldb_context
*ldb
, struct test_rootDSE
*root
)
55 struct ldb_message
*msg
;
58 d_printf("Testing RootDSE Search\n");
60 ret
= ldb_search(ldb
, ldb
, &r
, ldb_dn_new(ldb
, ldb
, NULL
),
61 LDB_SCOPE_BASE
, NULL
, NULL
);
62 if (ret
!= LDB_SUCCESS
) {
64 } else if (r
->count
!= 1) {
71 root
->defaultdn
= ldb_msg_find_attr_as_string(msg
, "defaultNamingContext", NULL
);
72 talloc_steal(ldb
, root
->defaultdn
);
73 root
->rootdn
= ldb_msg_find_attr_as_string(msg
, "rootDomainNamingContext", NULL
);
74 talloc_steal(ldb
, root
->rootdn
);
75 root
->configdn
= ldb_msg_find_attr_as_string(msg
, "configurationNamingContext", NULL
);
76 talloc_steal(ldb
, root
->configdn
);
77 root
->schemadn
= ldb_msg_find_attr_as_string(msg
, "schemaNamingContext", NULL
);
78 talloc_steal(ldb
, root
->schemadn
);
85 static int test_schema_search_callback(struct ldb_context
*ldb
, void *context
, struct ldb_reply
*ares
)
87 struct test_schema_ctx
*actx
= talloc_get_type(context
, struct test_schema_ctx
);
88 int ret
= LDB_SUCCESS
;
93 ret
= actx
->callback(actx
->private_data
, ldb
, ares
->message
);
96 case LDB_REPLY_REFERRAL
:
100 if (ares
->controls
) {
101 struct ldb_paged_control
*ctrl
= NULL
;
104 for (i
=0; ares
->controls
[i
]; i
++) {
105 if (strcmp(LDB_CONTROL_PAGED_RESULTS_OID
, ares
->controls
[i
]->oid
) == 0) {
106 ctrl
= talloc_get_type(ares
->controls
[i
]->data
, struct ldb_paged_control
);
113 talloc_free(actx
->ctrl
->cookie
);
114 actx
->ctrl
->cookie
= talloc_steal(actx
->ctrl
->cookie
, ctrl
->cookie
);
115 actx
->ctrl
->cookie_len
= ctrl
->cookie_len
;
117 if (actx
->ctrl
->cookie_len
> 0) {
118 actx
->pending
= true;
124 d_printf("%s: unknown Reply Type %u\n", __location__
, ares
->type
);
125 return LDB_ERR_OTHER
;
128 if (talloc_free(ares
) == -1) {
129 d_printf("talloc_free failed\n");
131 return LDB_ERR_OPERATIONS_ERROR
;
135 return LDB_ERR_OPERATIONS_ERROR
;
141 static bool test_create_schema_type(struct ldb_context
*ldb
, struct test_rootDSE
*root
,
143 int (*callback
)(void *, struct ldb_context
*ldb
, struct ldb_message
*),
146 struct ldb_control
**ctrl
;
147 struct ldb_paged_control
*control
;
148 struct ldb_request
*req
;
150 struct test_schema_ctx
*actx
;
152 req
= talloc(ldb
, struct ldb_request
);
153 actx
= talloc(req
, struct test_schema_ctx
);
155 ctrl
= talloc_array(req
, struct ldb_control
*, 2);
156 ctrl
[0] = talloc(ctrl
, struct ldb_control
);
157 ctrl
[0]->oid
= LDB_CONTROL_PAGED_RESULTS_OID
;
158 ctrl
[0]->critical
= true;
159 control
= talloc(ctrl
[0], struct ldb_paged_control
);
160 control
->size
= 1000;
161 control
->cookie
= NULL
;
162 control
->cookie_len
= 0;
163 ctrl
[0]->data
= control
;
166 req
->operation
= LDB_SEARCH
;
167 req
->op
.search
.base
= ldb_dn_new(req
, ldb
, root
->schemadn
);
168 req
->op
.search
.scope
= LDB_SCOPE_SUBTREE
;
169 req
->op
.search
.tree
= ldb_parse_tree(req
, filter
);
170 if (req
->op
.search
.tree
== NULL
) return -1;
171 req
->op
.search
.attrs
= NULL
;
172 req
->controls
= ctrl
;
174 req
->callback
= test_schema_search_callback
;
175 ldb_set_timeout(ldb
, req
, 0);
178 actx
->ctrl
= control
;
179 actx
->callback
= callback
;
180 actx
->private_data
= private_data
;
182 actx
->pending
= false;
184 ret
= ldb_request(ldb
, req
);
185 if (ret
!= LDB_SUCCESS
) {
186 d_printf("search failed - %s\n", ldb_errstring(ldb
));
190 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
191 if (ret
!= LDB_SUCCESS
) {
192 d_printf("search error - %s\n", ldb_errstring(ldb
));
199 d_printf("filter[%s] count[%u]\n", filter
, actx
->count
);
203 static int test_add_attribute(void *ptr
, struct ldb_context
*ldb
, struct ldb_message
*msg
)
205 struct dsdb_schema
*schema
= talloc_get_type(ptr
, struct dsdb_schema
);
206 struct dsdb_attribute
*attr
= NULL
;
209 attr
= talloc_zero(schema
, struct dsdb_attribute
);
214 status
= dsdb_attribute_from_ldb(schema
, msg
, attr
, attr
);
215 if (!W_ERROR_IS_OK(status
)) {
219 DLIST_ADD_END(schema
->attributes
, attr
, struct dsdb_attribute
*);
223 return LDB_ERR_OTHER
;
226 static int test_add_class(void *ptr
, struct ldb_context
*ldb
, struct ldb_message
*msg
)
228 struct dsdb_schema
*schema
= talloc_get_type(ptr
, struct dsdb_schema
);
229 struct dsdb_class
*obj
;
232 obj
= talloc_zero(schema
, struct dsdb_class
);
237 status
= dsdb_class_from_ldb(schema
, msg
, obj
, obj
);
238 if (!W_ERROR_IS_OK(status
)) {
242 DLIST_ADD_END(schema
->classes
, obj
, struct dsdb_class
*);
245 return LDB_ERR_OTHER
;
248 static bool test_create_schema(struct ldb_context
*ldb
, struct test_rootDSE
*root
, struct dsdb_schema
**_schema
)
251 struct dsdb_schema
*schema
;
253 schema
= talloc_zero(ldb
, struct dsdb_schema
);
255 d_printf("Fetching attributes...\n");
256 ret
&= test_create_schema_type(ldb
, root
, "(objectClass=attributeSchema)",
257 test_add_attribute
, schema
);
258 d_printf("Fetching objectClasses...\n");
259 ret
&= test_create_schema_type(ldb
, root
, "(objectClass=classSchema)",
260 test_add_class
, schema
);
268 static bool test_dump_not_replicated(struct ldb_context
*ldb
, struct test_rootDSE
*root
, struct dsdb_schema
*schema
)
270 struct dsdb_attribute
*a
;
273 d_printf("Dumping not replicated attributes\n");
275 for (a
=schema
->attributes
; a
; a
= a
->next
) {
276 if (!(a
->systemFlags
& 0x00000001)) continue;
277 d_printf("attr[%4u]: '%s'\n", a_i
++,
284 static bool test_dump_partial(struct ldb_context
*ldb
, struct test_rootDSE
*root
, struct dsdb_schema
*schema
)
286 struct dsdb_attribute
*a
;
289 d_printf("Dumping attributes which are provided by the global catalog\n");
291 for (a
=schema
->attributes
; a
; a
= a
->next
) {
292 if (!(a
->systemFlags
& 0x00000002) && !a
->isMemberOfPartialAttributeSet
) continue;
293 d_printf("attr[%4u]: %u %u '%s'\n", a_i
++,
294 a
->systemFlags
& 0x00000002, a
->isMemberOfPartialAttributeSet
,
301 static bool test_dump_contructed(struct ldb_context
*ldb
, struct test_rootDSE
*root
, struct dsdb_schema
*schema
)
303 struct dsdb_attribute
*a
;
306 d_printf("Dumping constructed attributes\n");
308 for (a
=schema
->attributes
; a
; a
= a
->next
) {
309 if (!(a
->systemFlags
& 0x00000004)) continue;
310 d_printf("attr[%4u]: '%s'\n", a_i
++,
317 static bool test_dump_sorted_syntax(struct ldb_context
*ldb
, struct test_rootDSE
*root
, struct dsdb_schema
*schema
)
319 struct dsdb_attribute
*a
;
322 const char *syntaxes
[] = {
343 d_printf("Dumping attribute syntaxes\n");
345 for (i
=0; i
< ARRAY_SIZE(syntaxes
); i
++) {
346 for (a
=schema
->attributes
; a
; a
= a
->next
) {
349 if (strcmp(syntaxes
[i
], a
->attributeSyntax_oid
) != 0) continue;
351 om_hex
= data_blob_hex_string(ldb
, &a
->oMObjectClass
);
356 d_printf("attr[%4u]: %s %u '%s' '%s'\n", a_i
++,
357 a
->attributeSyntax_oid
, a
->oMSyntax
,
358 om_hex
, a
->lDAPDisplayName
);
366 bool torture_ldap_schema(struct torture_context
*torture
)
368 struct ldb_context
*ldb
;
370 const char *host
= torture_setting_string(torture
, "host", NULL
);
372 struct test_rootDSE rootDSE
;
373 struct dsdb_schema
*schema
= NULL
;
375 ZERO_STRUCT(rootDSE
);
377 url
= talloc_asprintf(torture
, "ldap://%s/", host
);
379 ldb
= ldb_wrap_connect(torture
, torture
->ev
, torture
->lp_ctx
, url
,
383 if (!ldb
) goto failed
;
385 ret
&= test_search_rootDSE(ldb
, &rootDSE
);
386 if (!ret
) goto failed
;
387 ret
&= test_create_schema(ldb
, &rootDSE
, &schema
);
388 if (!ret
) goto failed
;
390 ret
&= test_dump_not_replicated(ldb
, &rootDSE
, schema
);
391 ret
&= test_dump_partial(ldb
, &rootDSE
, schema
);
392 ret
&= test_dump_contructed(ldb
, &rootDSE
, schema
);
393 ret
&= test_dump_sorted_syntax(ldb
, &rootDSE
, schema
);