Merge ldb_search() and ldb_search_exp_fmt() into a simgle function.
[Samba.git] / source4 / torture / ldap / schema.c
blobdd1d2de33163b367753e310c951742e2a8d58ced
1 /*
2 Unix SMB/CIFS mplementation.
3 LDAP schema tests
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/>.
22 #include "includes.h"
23 #include "libcli/ldap/ldap_client.h"
24 #include "lib/cmdline/popt_common.h"
25 #include "ldb_wrap.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"
36 struct test_rootDSE {
37 const char *defaultdn;
38 const char *rootdn;
39 const char *configdn;
40 const char *schemadn;
43 struct test_schema_ctx {
44 struct ldb_paged_control *ctrl;
45 uint32_t count;
46 bool pending;
48 int (*callback)(void *, struct ldb_context *ldb, struct ldb_message *);
49 void *private_data;
52 static bool test_search_rootDSE(struct ldb_context *ldb, struct test_rootDSE *root)
54 int ret;
55 struct ldb_message *msg;
56 struct ldb_result *r;
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) {
63 return false;
64 } else if (r->count != 1) {
65 talloc_free(r);
66 return false;
69 msg = r->msgs[0];
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);
80 talloc_free(r);
82 return true;
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;
90 switch (ares->type) {
91 case LDB_REPLY_ENTRY:
92 actx->count++;
93 ret = actx->callback(actx->private_data, ldb, ares->message);
94 break;
96 case LDB_REPLY_REFERRAL:
97 break;
99 case LDB_REPLY_DONE:
100 if (ares->controls) {
101 struct ldb_paged_control *ctrl = NULL;
102 int i;
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);
107 break;
111 if (!ctrl) break;
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;
121 break;
123 default:
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");
130 actx->pending = 0;
131 return LDB_ERR_OPERATIONS_ERROR;
134 if (ret) {
135 return LDB_ERR_OPERATIONS_ERROR;
138 return LDB_SUCCESS;
141 static bool test_create_schema_type(struct ldb_context *ldb, struct test_rootDSE *root,
142 const char *filter,
143 int (*callback)(void *, struct ldb_context *ldb, struct ldb_message *),
144 void *private_data)
146 struct ldb_control **ctrl;
147 struct ldb_paged_control *control;
148 struct ldb_request *req;
149 int ret;
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;
164 ctrl[1] = NULL;
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;
173 req->context = actx;
174 req->callback = test_schema_search_callback;
175 ldb_set_timeout(ldb, req, 0);
177 actx->count = 0;
178 actx->ctrl = control;
179 actx->callback = callback;
180 actx->private_data = private_data;
181 again:
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));
187 return false;
190 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
191 if (ret != LDB_SUCCESS) {
192 d_printf("search error - %s\n", ldb_errstring(ldb));
193 return false;
196 if (actx->pending)
197 goto again;
199 d_printf("filter[%s] count[%u]\n", filter, actx->count);
200 return true;
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;
207 WERROR status;
209 attr = talloc_zero(schema, struct dsdb_attribute);
210 if (!attr) {
211 goto failed;
214 status = dsdb_attribute_from_ldb(schema, msg, attr, attr);
215 if (!W_ERROR_IS_OK(status)) {
216 goto failed;
219 DLIST_ADD_END(schema->attributes, attr, struct dsdb_attribute *);
220 return LDB_SUCCESS;
221 failed:
222 talloc_free(attr);
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;
230 WERROR status;
232 obj = talloc_zero(schema, struct dsdb_class);
233 if (!obj) {
234 goto failed;
237 status = dsdb_class_from_ldb(schema, msg, obj, obj);
238 if (!W_ERROR_IS_OK(status)) {
239 goto failed;
242 DLIST_ADD_END(schema->classes, obj, struct dsdb_class *);
243 return LDB_SUCCESS;
244 failed:
245 return LDB_ERR_OTHER;
248 static bool test_create_schema(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema **_schema)
250 bool ret = true;
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);
262 if (ret == true) {
263 *_schema = schema;
265 return ret;
268 static bool test_dump_not_replicated(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema *schema)
270 struct dsdb_attribute *a;
271 uint32_t a_i = 1;
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++,
278 a->lDAPDisplayName);
281 return true;
284 static bool test_dump_partial(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema *schema)
286 struct dsdb_attribute *a;
287 uint32_t a_i = 1;
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,
295 a->lDAPDisplayName);
298 return true;
301 static bool test_dump_contructed(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema *schema)
303 struct dsdb_attribute *a;
304 uint32_t a_i = 1;
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++,
311 a->lDAPDisplayName);
314 return true;
317 static bool test_dump_sorted_syntax(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema *schema)
319 struct dsdb_attribute *a;
320 uint32_t a_i = 1;
321 uint32_t i;
322 const char *syntaxes[] = {
323 "2.5.5.0",
324 "2.5.5.1",
325 "2.5.5.2",
326 "2.5.5.3",
327 "2.5.5.4",
328 "2.5.5.5",
329 "2.5.5.6",
330 "2.5.5.7",
331 "2.5.5.8",
332 "2.5.5.9",
333 "2.5.5.10",
334 "2.5.5.11",
335 "2.5.5.12",
336 "2.5.5.13",
337 "2.5.5.14",
338 "2.5.5.15",
339 "2.5.5.16",
340 "2.5.5.17"
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) {
347 char *om_hex;
349 if (strcmp(syntaxes[i], a->attributeSyntax_oid) != 0) continue;
351 om_hex = data_blob_hex_string(ldb, &a->oMObjectClass);
352 if (!om_hex) {
353 return false;
356 d_printf("attr[%4u]: %s %u '%s' '%s'\n", a_i++,
357 a->attributeSyntax_oid, a->oMSyntax,
358 om_hex, a->lDAPDisplayName);
359 talloc_free(om_hex);
363 return true;
366 bool torture_ldap_schema(struct torture_context *torture)
368 struct ldb_context *ldb;
369 bool ret = true;
370 const char *host = torture_setting_string(torture, "host", NULL);
371 char *url;
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,
380 NULL,
381 cmdline_credentials,
382 0, NULL);
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);
395 failed:
396 return ret;