lib/replace: define HAVE_WORKING_STRPTIME instead of REPLACE_STRPTIME
[Samba/gebeck_regimport.git] / source4 / torture / ldap / schema.c
blob66284f1ef0e2ae961ad7beda1749863345a9f988
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 WERROR status;
216 status = dsdb_set_attribute_from_ldb(ldb, schema, msg);
217 if (!W_ERROR_IS_OK(status)) {
218 goto failed;
221 return LDB_SUCCESS;
222 failed:
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 WERROR status;
231 status = dsdb_set_class_from_ldb(schema, msg);
232 if (!W_ERROR_IS_OK(status)) {
233 goto failed;
236 return LDB_SUCCESS;
237 failed:
238 return LDB_ERR_OTHER;
241 static bool test_create_schema(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema **_schema)
243 bool ret = true;
244 struct dsdb_schema *schema;
246 schema = talloc_zero(ldb, struct dsdb_schema);
248 d_printf("Fetching attributes...\n");
249 ret &= test_create_schema_type(ldb, root, "(objectClass=attributeSchema)",
250 test_add_attribute, schema);
251 d_printf("Fetching objectClasses...\n");
252 ret &= test_create_schema_type(ldb, root, "(objectClass=classSchema)",
253 test_add_class, schema);
255 if (ret == true) {
256 *_schema = schema;
258 return ret;
261 static bool test_dump_not_replicated(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema *schema)
263 struct dsdb_attribute *a;
264 uint32_t a_i = 1;
266 d_printf("Dumping not replicated attributes\n");
268 for (a=schema->attributes; a; a = a->next) {
269 if (!(a->systemFlags & 0x00000001)) continue;
270 d_printf("attr[%4u]: '%s'\n", a_i++,
271 a->lDAPDisplayName);
274 return true;
277 static bool test_dump_partial(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema *schema)
279 struct dsdb_attribute *a;
280 uint32_t a_i = 1;
282 d_printf("Dumping attributes which are provided by the global catalog\n");
284 for (a=schema->attributes; a; a = a->next) {
285 if (!(a->systemFlags & 0x00000002) && !a->isMemberOfPartialAttributeSet) continue;
286 d_printf("attr[%4u]: %u %u '%s'\n", a_i++,
287 a->systemFlags & 0x00000002, a->isMemberOfPartialAttributeSet,
288 a->lDAPDisplayName);
291 return true;
294 static bool test_dump_contructed(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema *schema)
296 struct dsdb_attribute *a;
297 uint32_t a_i = 1;
299 d_printf("Dumping constructed attributes\n");
301 for (a=schema->attributes; a; a = a->next) {
302 if (!(a->systemFlags & 0x00000004)) continue;
303 d_printf("attr[%4u]: '%s'\n", a_i++,
304 a->lDAPDisplayName);
307 return true;
310 static bool test_dump_sorted_syntax(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema *schema)
312 struct dsdb_attribute *a;
313 uint32_t a_i = 1;
314 uint32_t i;
315 const char *syntaxes[] = {
316 "2.5.5.0",
317 "2.5.5.1",
318 "2.5.5.2",
319 "2.5.5.3",
320 "2.5.5.4",
321 "2.5.5.5",
322 "2.5.5.6",
323 "2.5.5.7",
324 "2.5.5.8",
325 "2.5.5.9",
326 "2.5.5.10",
327 "2.5.5.11",
328 "2.5.5.12",
329 "2.5.5.13",
330 "2.5.5.14",
331 "2.5.5.15",
332 "2.5.5.16",
333 "2.5.5.17"
336 d_printf("Dumping attribute syntaxes\n");
338 for (i=0; i < ARRAY_SIZE(syntaxes); i++) {
339 for (a=schema->attributes; a; a = a->next) {
340 char *om_hex;
342 if (strcmp(syntaxes[i], a->attributeSyntax_oid) != 0) continue;
344 om_hex = data_blob_hex_string_upper(ldb, &a->oMObjectClass);
345 if (!om_hex) {
346 return false;
349 d_printf("attr[%4u]: %s %u '%s' '%s'\n", a_i++,
350 a->attributeSyntax_oid, a->oMSyntax,
351 om_hex, a->lDAPDisplayName);
352 talloc_free(om_hex);
356 return true;
359 static bool test_dump_not_in_filtered_replica(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema *schema)
361 struct dsdb_attribute *a;
362 uint32_t a_i = 1;
364 d_printf("Dumping attributes not in filtered replica\n");
366 for (a=schema->attributes; a; a = a->next) {
367 if (!dsdb_attribute_is_attr_in_filtered_replica(a)) {
368 d_printf("attr[%4u]: '%s'\n", a_i++,
369 a->lDAPDisplayName);
372 return true;
375 bool torture_ldap_schema(struct torture_context *torture)
377 struct ldb_context *ldb;
378 bool ret = true;
379 const char *host = torture_setting_string(torture, "host", NULL);
380 char *url;
381 struct test_rootDSE rootDSE;
382 struct dsdb_schema *schema = NULL;
384 ZERO_STRUCT(rootDSE);
386 url = talloc_asprintf(torture, "ldap://%s/", host);
388 ldb = ldb_wrap_connect(torture, torture->ev, torture->lp_ctx, url,
389 NULL,
390 cmdline_credentials,
392 if (!ldb) goto failed;
394 ret &= test_search_rootDSE(ldb, &rootDSE);
395 if (!ret) goto failed;
396 ret &= test_create_schema(ldb, &rootDSE, &schema);
397 if (!ret) goto failed;
399 ret &= test_dump_not_replicated(ldb, &rootDSE, schema);
400 ret &= test_dump_partial(ldb, &rootDSE, schema);
401 ret &= test_dump_contructed(ldb, &rootDSE, schema);
402 ret &= test_dump_sorted_syntax(ldb, &rootDSE, schema);
403 ret &= test_dump_not_in_filtered_replica(ldb, &rootDSE, schema);
405 failed:
406 return ret;