s3-nmbd: Fix bug #7875
[Samba.git] / source4 / torture / ldap / schema.c
blob7ea7b39d5cdeafd0edafbdf7a409c75d057cbf5d
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_context *ldb;
46 struct ldb_paged_control *ctrl;
47 uint32_t count;
48 bool pending;
50 int (*callback)(void *, struct ldb_context *ldb, struct ldb_message *);
51 void *private_data;
54 static bool test_search_rootDSE(struct ldb_context *ldb, struct test_rootDSE *root)
56 int ret;
57 struct ldb_message *msg;
58 struct ldb_result *r;
60 d_printf("Testing RootDSE Search\n");
62 ret = ldb_search(ldb, ldb, &r, ldb_dn_new(ldb, ldb, NULL),
63 LDB_SCOPE_BASE, NULL, NULL);
64 if (ret != LDB_SUCCESS) {
65 return false;
66 } else if (r->count != 1) {
67 talloc_free(r);
68 return false;
71 msg = r->msgs[0];
73 root->defaultdn = ldb_msg_find_attr_as_string(msg, "defaultNamingContext", NULL);
74 talloc_steal(ldb, root->defaultdn);
75 root->rootdn = ldb_msg_find_attr_as_string(msg, "rootDomainNamingContext", NULL);
76 talloc_steal(ldb, root->rootdn);
77 root->configdn = ldb_msg_find_attr_as_string(msg, "configurationNamingContext", NULL);
78 talloc_steal(ldb, root->configdn);
79 root->schemadn = ldb_msg_find_attr_as_string(msg, "schemaNamingContext", NULL);
80 talloc_steal(ldb, root->schemadn);
82 talloc_free(r);
84 return true;
87 static int test_schema_search_callback(struct ldb_request *req, struct ldb_reply *ares)
89 struct test_schema_ctx *actx;
90 int ret = LDB_SUCCESS;
92 actx = talloc_get_type(req->context, struct test_schema_ctx);
94 if (!ares) {
95 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
97 if (ares->error != LDB_SUCCESS) {
98 return ldb_request_done(req, ares->error);
101 switch (ares->type) {
102 case LDB_REPLY_ENTRY:
103 actx->count++;
104 ret = actx->callback(actx->private_data, actx->ldb, ares->message);
105 break;
107 case LDB_REPLY_REFERRAL:
108 break;
110 case LDB_REPLY_DONE:
111 if (ares->controls) {
112 struct ldb_paged_control *ctrl = NULL;
113 int i;
115 for (i=0; ares->controls[i]; i++) {
116 if (strcmp(LDB_CONTROL_PAGED_RESULTS_OID, ares->controls[i]->oid) == 0) {
117 ctrl = talloc_get_type(ares->controls[i]->data, struct ldb_paged_control);
118 break;
122 if (!ctrl) break;
124 talloc_free(actx->ctrl->cookie);
125 actx->ctrl->cookie = talloc_steal(actx->ctrl->cookie, ctrl->cookie);
126 actx->ctrl->cookie_len = ctrl->cookie_len;
128 if (actx->ctrl->cookie_len > 0) {
129 actx->pending = true;
132 talloc_free(ares);
133 return ldb_request_done(req, LDB_SUCCESS);
135 default:
136 d_printf("%s: unknown Reply Type %u\n", __location__, ares->type);
137 return ldb_request_done(req, LDB_ERR_OTHER);
140 if (talloc_free(ares) == -1) {
141 d_printf("talloc_free failed\n");
142 actx->pending = 0;
143 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
146 if (ret) {
147 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
150 return LDB_SUCCESS;
153 static bool test_create_schema_type(struct ldb_context *ldb, struct test_rootDSE *root,
154 const char *filter,
155 int (*callback)(void *, struct ldb_context *ldb, struct ldb_message *),
156 void *private_data)
158 struct ldb_control **ctrl;
159 struct ldb_paged_control *control;
160 struct ldb_request *req;
161 int ret;
162 struct test_schema_ctx *actx;
164 actx = talloc(ldb, struct test_schema_ctx);
165 actx->ldb = ldb;
166 actx->private_data = private_data;
167 actx->callback= callback;
169 ctrl = talloc_array(actx, struct ldb_control *, 2);
170 ctrl[0] = talloc(ctrl, struct ldb_control);
171 ctrl[0]->oid = LDB_CONTROL_PAGED_RESULTS_OID;
172 ctrl[0]->critical = true;
173 control = talloc(ctrl[0], struct ldb_paged_control);
174 control->size = 1000;
175 control->cookie = NULL;
176 control->cookie_len = 0;
177 ctrl[0]->data = control;
178 ctrl[1] = NULL;
180 ret = ldb_build_search_req(&req, ldb, actx,
181 ldb_dn_new(actx, ldb, root->schemadn),
182 LDB_SCOPE_SUBTREE,
183 filter, NULL,
184 ctrl,
185 actx, test_schema_search_callback,
186 NULL);
188 actx->ctrl = control;
189 actx->count = 0;
190 again:
191 actx->pending = false;
193 ret = ldb_request(ldb, req);
194 if (ret != LDB_SUCCESS) {
195 d_printf("search failed - %s\n", ldb_errstring(ldb));
196 talloc_free(actx);
197 return false;
200 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
201 if (ret != LDB_SUCCESS) {
202 d_printf("search error - %s\n", ldb_errstring(ldb));
203 talloc_free(actx);
204 return false;
207 if (actx->pending)
208 goto again;
210 d_printf("filter[%s] count[%u]\n", filter, actx->count);
211 talloc_free(actx);
212 return true;
215 static int test_add_attribute(void *ptr, struct ldb_context *ldb, struct ldb_message *msg)
217 struct dsdb_schema *schema = talloc_get_type(ptr, struct dsdb_schema);
218 struct dsdb_attribute *attr = NULL;
219 WERROR status;
221 attr = talloc_zero(schema, struct dsdb_attribute);
222 if (!attr) {
223 goto failed;
226 status = dsdb_attribute_from_ldb(ldb, schema, msg, attr, attr);
227 if (!W_ERROR_IS_OK(status)) {
228 goto failed;
231 DLIST_ADD_END(schema->attributes, attr, struct dsdb_attribute *);
232 return LDB_SUCCESS;
233 failed:
234 talloc_free(attr);
235 return LDB_ERR_OTHER;
238 static int test_add_class(void *ptr, struct ldb_context *ldb, struct ldb_message *msg)
240 struct dsdb_schema *schema = talloc_get_type(ptr, struct dsdb_schema);
241 struct dsdb_class *obj;
242 WERROR status;
244 obj = talloc_zero(schema, struct dsdb_class);
245 if (!obj) {
246 goto failed;
249 status = dsdb_class_from_ldb(schema, msg, obj, obj);
250 if (!W_ERROR_IS_OK(status)) {
251 goto failed;
254 DLIST_ADD_END(schema->classes, obj, struct dsdb_class *);
255 return LDB_SUCCESS;
256 failed:
257 return LDB_ERR_OTHER;
260 static bool test_create_schema(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema **_schema)
262 bool ret = true;
263 struct dsdb_schema *schema;
265 schema = talloc_zero(ldb, struct dsdb_schema);
267 d_printf("Fetching attributes...\n");
268 ret &= test_create_schema_type(ldb, root, "(objectClass=attributeSchema)",
269 test_add_attribute, schema);
270 d_printf("Fetching objectClasses...\n");
271 ret &= test_create_schema_type(ldb, root, "(objectClass=classSchema)",
272 test_add_class, schema);
274 if (ret == true) {
275 *_schema = schema;
277 return ret;
280 static bool test_dump_not_replicated(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema *schema)
282 struct dsdb_attribute *a;
283 uint32_t a_i = 1;
285 d_printf("Dumping not replicated attributes\n");
287 for (a=schema->attributes; a; a = a->next) {
288 if (!(a->systemFlags & 0x00000001)) continue;
289 d_printf("attr[%4u]: '%s'\n", a_i++,
290 a->lDAPDisplayName);
293 return true;
296 static bool test_dump_partial(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema *schema)
298 struct dsdb_attribute *a;
299 uint32_t a_i = 1;
301 d_printf("Dumping attributes which are provided by the global catalog\n");
303 for (a=schema->attributes; a; a = a->next) {
304 if (!(a->systemFlags & 0x00000002) && !a->isMemberOfPartialAttributeSet) continue;
305 d_printf("attr[%4u]: %u %u '%s'\n", a_i++,
306 a->systemFlags & 0x00000002, a->isMemberOfPartialAttributeSet,
307 a->lDAPDisplayName);
310 return true;
313 static bool test_dump_contructed(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema *schema)
315 struct dsdb_attribute *a;
316 uint32_t a_i = 1;
318 d_printf("Dumping constructed attributes\n");
320 for (a=schema->attributes; a; a = a->next) {
321 if (!(a->systemFlags & 0x00000004)) continue;
322 d_printf("attr[%4u]: '%s'\n", a_i++,
323 a->lDAPDisplayName);
326 return true;
329 static bool test_dump_sorted_syntax(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema *schema)
331 struct dsdb_attribute *a;
332 uint32_t a_i = 1;
333 uint32_t i;
334 const char *syntaxes[] = {
335 "2.5.5.0",
336 "2.5.5.1",
337 "2.5.5.2",
338 "2.5.5.3",
339 "2.5.5.4",
340 "2.5.5.5",
341 "2.5.5.6",
342 "2.5.5.7",
343 "2.5.5.8",
344 "2.5.5.9",
345 "2.5.5.10",
346 "2.5.5.11",
347 "2.5.5.12",
348 "2.5.5.13",
349 "2.5.5.14",
350 "2.5.5.15",
351 "2.5.5.16",
352 "2.5.5.17"
355 d_printf("Dumping attribute syntaxes\n");
357 for (i=0; i < ARRAY_SIZE(syntaxes); i++) {
358 for (a=schema->attributes; a; a = a->next) {
359 char *om_hex;
361 if (strcmp(syntaxes[i], a->attributeSyntax_oid) != 0) continue;
363 om_hex = data_blob_hex_string(ldb, &a->oMObjectClass);
364 if (!om_hex) {
365 return false;
368 d_printf("attr[%4u]: %s %u '%s' '%s'\n", a_i++,
369 a->attributeSyntax_oid, a->oMSyntax,
370 om_hex, a->lDAPDisplayName);
371 talloc_free(om_hex);
375 return true;
378 bool torture_ldap_schema(struct torture_context *torture)
380 struct ldb_context *ldb;
381 bool ret = true;
382 const char *host = torture_setting_string(torture, "host", NULL);
383 char *url;
384 struct test_rootDSE rootDSE;
385 struct dsdb_schema *schema = NULL;
387 ZERO_STRUCT(rootDSE);
389 url = talloc_asprintf(torture, "ldap://%s/", host);
391 ldb = ldb_wrap_connect(torture, torture->ev, torture->lp_ctx, url,
392 NULL,
393 cmdline_credentials,
394 0, NULL);
395 if (!ldb) goto failed;
397 ret &= test_search_rootDSE(ldb, &rootDSE);
398 if (!ret) goto failed;
399 ret &= test_create_schema(ldb, &rootDSE, &schema);
400 if (!ret) goto failed;
402 ret &= test_dump_not_replicated(ldb, &rootDSE, schema);
403 ret &= test_dump_partial(ldb, &rootDSE, schema);
404 ret &= test_dump_contructed(ldb, &rootDSE, schema);
405 ret &= test_dump_sorted_syntax(ldb, &rootDSE, schema);
407 failed:
408 return ret;