lib/util Split data_blob_hex_string() into upper and lower
[Samba/ekacnet.git] / source4 / torture / ldap / schema.c
blobb0a4892d7a54650e841ea25ba3d603abe1436cf0
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 "dsdb/samdb/samdb.h"
27 #include "../lib/util/dlinklist.h"
29 #include "torture/torture.h"
32 struct test_rootDSE {
33 const char *defaultdn;
34 const char *rootdn;
35 const char *configdn;
36 const char *schemadn;
39 struct test_schema_ctx {
40 struct ldb_context *ldb;
42 struct ldb_paged_control *ctrl;
43 uint32_t count;
44 bool pending;
46 int (*callback)(void *, struct ldb_context *ldb, struct ldb_message *);
47 void *private_data;
50 static bool test_search_rootDSE(struct ldb_context *ldb, struct test_rootDSE *root)
52 int ret;
53 struct ldb_message *msg;
54 struct ldb_result *r;
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) {
61 return false;
62 } else if (r->count != 1) {
63 talloc_free(r);
64 return false;
67 msg = r->msgs[0];
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);
78 talloc_free(r);
80 return true;
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);
90 if (!ares) {
91 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
93 if (ares->error != LDB_SUCCESS) {
94 return ldb_request_done(req, ares->error);
97 switch (ares->type) {
98 case LDB_REPLY_ENTRY:
99 actx->count++;
100 ret = actx->callback(actx->private_data, actx->ldb, ares->message);
101 break;
103 case LDB_REPLY_REFERRAL:
104 break;
106 case LDB_REPLY_DONE:
107 if (ares->controls) {
108 struct ldb_paged_control *ctrl = NULL;
109 int i;
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);
114 break;
118 if (!ctrl) break;
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;
128 talloc_free(ares);
129 return ldb_request_done(req, LDB_SUCCESS);
131 default:
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");
138 actx->pending = 0;
139 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
142 if (ret) {
143 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
146 return LDB_SUCCESS;
149 static bool test_create_schema_type(struct ldb_context *ldb, struct test_rootDSE *root,
150 const char *filter,
151 int (*callback)(void *, struct ldb_context *ldb, struct ldb_message *),
152 void *private_data)
154 struct ldb_control **ctrl;
155 struct ldb_paged_control *control;
156 struct ldb_request *req;
157 int ret;
158 struct test_schema_ctx *actx;
160 actx = talloc(ldb, struct test_schema_ctx);
161 actx->ldb = ldb;
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;
174 ctrl[1] = NULL;
176 ret = ldb_build_search_req(&req, ldb, actx,
177 ldb_dn_new(actx, ldb, root->schemadn),
178 LDB_SCOPE_SUBTREE,
179 filter, NULL,
180 ctrl,
181 actx, test_schema_search_callback,
182 NULL);
184 actx->ctrl = control;
185 actx->count = 0;
186 again:
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));
192 talloc_free(actx);
193 return false;
196 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
197 if (ret != LDB_SUCCESS) {
198 d_printf("search error - %s\n", ldb_errstring(ldb));
199 talloc_free(actx);
200 return false;
203 if (actx->pending)
204 goto again;
206 d_printf("filter[%s] count[%u]\n", filter, actx->count);
207 talloc_free(actx);
208 return true;
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;
215 WERROR status;
217 attr = talloc_zero(schema, struct dsdb_attribute);
218 if (!attr) {
219 goto failed;
222 status = dsdb_attribute_from_ldb(ldb, schema, msg, attr, attr);
223 if (!W_ERROR_IS_OK(status)) {
224 goto failed;
227 DLIST_ADD_END(schema->attributes, attr, struct dsdb_attribute *);
228 return LDB_SUCCESS;
229 failed:
230 talloc_free(attr);
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;
238 WERROR status;
240 obj = talloc_zero(schema, struct dsdb_class);
241 if (!obj) {
242 goto failed;
245 status = dsdb_class_from_ldb(schema, msg, obj, obj);
246 if (!W_ERROR_IS_OK(status)) {
247 goto failed;
250 DLIST_ADD_END(schema->classes, obj, struct dsdb_class *);
251 return LDB_SUCCESS;
252 failed:
253 return LDB_ERR_OTHER;
256 static bool test_create_schema(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema **_schema)
258 bool ret = true;
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);
270 if (ret == true) {
271 *_schema = schema;
273 return ret;
276 static bool test_dump_not_replicated(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema *schema)
278 struct dsdb_attribute *a;
279 uint32_t a_i = 1;
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++,
286 a->lDAPDisplayName);
289 return true;
292 static bool test_dump_partial(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema *schema)
294 struct dsdb_attribute *a;
295 uint32_t a_i = 1;
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,
303 a->lDAPDisplayName);
306 return true;
309 static bool test_dump_contructed(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema *schema)
311 struct dsdb_attribute *a;
312 uint32_t a_i = 1;
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++,
319 a->lDAPDisplayName);
322 return true;
325 static bool test_dump_sorted_syntax(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema *schema)
327 struct dsdb_attribute *a;
328 uint32_t a_i = 1;
329 uint32_t i;
330 const char *syntaxes[] = {
331 "2.5.5.0",
332 "2.5.5.1",
333 "2.5.5.2",
334 "2.5.5.3",
335 "2.5.5.4",
336 "2.5.5.5",
337 "2.5.5.6",
338 "2.5.5.7",
339 "2.5.5.8",
340 "2.5.5.9",
341 "2.5.5.10",
342 "2.5.5.11",
343 "2.5.5.12",
344 "2.5.5.13",
345 "2.5.5.14",
346 "2.5.5.15",
347 "2.5.5.16",
348 "2.5.5.17"
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) {
355 char *om_hex;
357 if (strcmp(syntaxes[i], a->attributeSyntax_oid) != 0) continue;
359 om_hex = data_blob_hex_string_upper(ldb, &a->oMObjectClass);
360 if (!om_hex) {
361 return false;
364 d_printf("attr[%4u]: %s %u '%s' '%s'\n", a_i++,
365 a->attributeSyntax_oid, a->oMSyntax,
366 om_hex, a->lDAPDisplayName);
367 talloc_free(om_hex);
371 return true;
374 bool torture_ldap_schema(struct torture_context *torture)
376 struct ldb_context *ldb;
377 bool ret = true;
378 const char *host = torture_setting_string(torture, "host", NULL);
379 char *url;
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,
388 NULL,
389 cmdline_credentials,
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);
403 failed:
404 return ret;