s4: popt: Global replace of cmdline_credentials -> popt_get_cmdline_credentials().
[Samba.git] / source4 / torture / ldap / schema.c
blobb6da873e7fc605ce28896af63bf230e9d354c2c0
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"
30 #include "torture/ldap/proto.h"
33 struct test_rootDSE {
34 const char *defaultdn;
35 const char *rootdn;
36 const char *configdn;
37 const char *schemadn;
40 struct test_schema_ctx {
41 struct ldb_context *ldb;
43 struct ldb_paged_control *ctrl;
44 uint32_t count;
45 bool pending;
47 int (*callback)(void *, struct ldb_context *ldb, struct ldb_message *);
48 void *private_data;
51 static bool test_search_rootDSE(struct ldb_context *ldb, struct test_rootDSE *root)
53 int ret;
54 struct ldb_message *msg;
55 struct ldb_result *r;
57 d_printf("Testing RootDSE Search\n");
59 ret = ldb_search(ldb, ldb, &r, ldb_dn_new(ldb, ldb, NULL),
60 LDB_SCOPE_BASE, NULL, NULL);
61 if (ret != LDB_SUCCESS) {
62 return false;
63 } else if (r->count != 1) {
64 talloc_free(r);
65 return false;
68 msg = r->msgs[0];
70 root->defaultdn = ldb_msg_find_attr_as_string(msg, "defaultNamingContext", NULL);
71 talloc_steal(ldb, root->defaultdn);
72 root->rootdn = ldb_msg_find_attr_as_string(msg, "rootDomainNamingContext", NULL);
73 talloc_steal(ldb, root->rootdn);
74 root->configdn = ldb_msg_find_attr_as_string(msg, "configurationNamingContext", NULL);
75 talloc_steal(ldb, root->configdn);
76 root->schemadn = ldb_msg_find_attr_as_string(msg, "schemaNamingContext", NULL);
77 talloc_steal(ldb, root->schemadn);
79 talloc_free(r);
81 return true;
84 static int test_schema_search_callback(struct ldb_request *req, struct ldb_reply *ares)
86 struct test_schema_ctx *actx;
87 int ret = LDB_SUCCESS;
89 actx = talloc_get_type(req->context, struct test_schema_ctx);
91 if (!ares) {
92 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
94 if (ares->error != LDB_SUCCESS) {
95 return ldb_request_done(req, ares->error);
98 switch (ares->type) {
99 case LDB_REPLY_ENTRY:
100 actx->count++;
101 ret = actx->callback(actx->private_data, actx->ldb, ares->message);
102 break;
104 case LDB_REPLY_REFERRAL:
105 break;
107 case LDB_REPLY_DONE:
108 if (ares->controls) {
109 struct ldb_paged_control *ctrl = NULL;
110 int i;
112 for (i=0; ares->controls[i]; i++) {
113 if (strcmp(LDB_CONTROL_PAGED_RESULTS_OID, ares->controls[i]->oid) == 0) {
114 ctrl = talloc_get_type(ares->controls[i]->data, struct ldb_paged_control);
115 break;
119 if (!ctrl) break;
121 talloc_free(actx->ctrl->cookie);
122 actx->ctrl->cookie = talloc_steal(actx->ctrl->cookie, ctrl->cookie);
123 actx->ctrl->cookie_len = ctrl->cookie_len;
125 if (actx->ctrl->cookie_len > 0) {
126 actx->pending = true;
129 talloc_free(ares);
130 return ldb_request_done(req, LDB_SUCCESS);
132 default:
133 d_printf("%s: unknown Reply Type %u\n", __location__, ares->type);
134 return ldb_request_done(req, LDB_ERR_OTHER);
137 if (talloc_free(ares) == -1) {
138 d_printf("talloc_free failed\n");
139 actx->pending = 0;
140 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
143 if (ret) {
144 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
147 return LDB_SUCCESS;
150 static bool test_create_schema_type(struct ldb_context *ldb, struct test_rootDSE *root,
151 const char *filter,
152 int (*callback)(void *, struct ldb_context *ldb, struct ldb_message *),
153 void *private_data)
155 struct ldb_control **ctrl;
156 struct ldb_paged_control *control;
157 struct ldb_request *req;
158 int ret;
159 struct test_schema_ctx *actx;
161 actx = talloc(ldb, struct test_schema_ctx);
162 actx->ldb = ldb;
163 actx->private_data = private_data;
164 actx->callback= callback;
166 ctrl = talloc_array(actx, struct ldb_control *, 2);
167 ctrl[0] = talloc(ctrl, struct ldb_control);
168 ctrl[0]->oid = LDB_CONTROL_PAGED_RESULTS_OID;
169 ctrl[0]->critical = true;
170 control = talloc(ctrl[0], struct ldb_paged_control);
171 control->size = 1000;
172 control->cookie = NULL;
173 control->cookie_len = 0;
174 ctrl[0]->data = control;
175 ctrl[1] = NULL;
177 ret = ldb_build_search_req(&req, ldb, actx,
178 ldb_dn_new(actx, ldb, root->schemadn),
179 LDB_SCOPE_SUBTREE,
180 filter, NULL,
181 ctrl,
182 actx, test_schema_search_callback,
183 NULL);
185 actx->ctrl = control;
186 actx->count = 0;
187 again:
188 actx->pending = false;
190 ret = ldb_request(ldb, req);
191 if (ret != LDB_SUCCESS) {
192 d_printf("search failed - %s\n", ldb_errstring(ldb));
193 talloc_free(actx);
194 return false;
197 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
198 if (ret != LDB_SUCCESS) {
199 d_printf("search error - %s\n", ldb_errstring(ldb));
200 talloc_free(actx);
201 return false;
204 if (actx->pending)
205 goto again;
207 d_printf("filter[%s] count[%u]\n", filter, actx->count);
208 talloc_free(actx);
209 return true;
212 static int test_add_attribute(void *ptr, struct ldb_context *ldb, struct ldb_message *msg)
214 struct dsdb_schema *schema = talloc_get_type(ptr, struct dsdb_schema);
215 WERROR status;
217 status = dsdb_set_attribute_from_ldb(ldb, schema, msg);
218 if (!W_ERROR_IS_OK(status)) {
219 goto failed;
222 return LDB_SUCCESS;
223 failed:
224 return LDB_ERR_OTHER;
227 static int test_add_class(void *ptr, struct ldb_context *ldb, struct ldb_message *msg)
229 struct dsdb_schema *schema = talloc_get_type(ptr, struct dsdb_schema);
230 WERROR status;
232 status = dsdb_set_class_from_ldb(schema, msg);
233 if (!W_ERROR_IS_OK(status)) {
234 goto failed;
237 return LDB_SUCCESS;
238 failed:
239 return LDB_ERR_OTHER;
242 static bool test_create_schema(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema **_schema)
244 bool ret = true;
245 struct dsdb_schema *schema;
247 schema = talloc_zero(ldb, struct dsdb_schema);
249 d_printf("Fetching attributes...\n");
250 ret &= test_create_schema_type(ldb, root, "(objectClass=attributeSchema)",
251 test_add_attribute, schema);
252 d_printf("Fetching objectClasses...\n");
253 ret &= test_create_schema_type(ldb, root, "(objectClass=classSchema)",
254 test_add_class, schema);
256 if (ret == true) {
257 *_schema = schema;
259 return ret;
262 static bool test_dump_not_replicated(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema *schema)
264 struct dsdb_attribute *a;
265 uint32_t a_i = 1;
267 d_printf("Dumping not replicated attributes\n");
269 for (a=schema->attributes; a; a = a->next) {
270 if (!(a->systemFlags & 0x00000001)) continue;
271 d_printf("attr[%4u]: '%s'\n", a_i++,
272 a->lDAPDisplayName);
275 return true;
278 static bool test_dump_partial(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema *schema)
280 struct dsdb_attribute *a;
281 uint32_t a_i = 1;
283 d_printf("Dumping attributes which are provided by the global catalog\n");
285 for (a=schema->attributes; a; a = a->next) {
286 if (!(a->systemFlags & 0x00000002) && !a->isMemberOfPartialAttributeSet) continue;
287 d_printf("attr[%4u]: %u %u '%s'\n", a_i++,
288 a->systemFlags & 0x00000002, a->isMemberOfPartialAttributeSet,
289 a->lDAPDisplayName);
292 return true;
295 static bool test_dump_contructed(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema *schema)
297 struct dsdb_attribute *a;
298 uint32_t a_i = 1;
300 d_printf("Dumping constructed attributes\n");
302 for (a=schema->attributes; a; a = a->next) {
303 if (!(a->systemFlags & 0x00000004)) continue;
304 d_printf("attr[%4u]: '%s'\n", a_i++,
305 a->lDAPDisplayName);
308 return true;
311 static bool test_dump_sorted_syntax(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema *schema)
313 struct dsdb_attribute *a;
314 uint32_t a_i = 1;
315 uint32_t i;
316 const char *syntaxes[] = {
317 "2.5.5.0",
318 "2.5.5.1",
319 "2.5.5.2",
320 "2.5.5.3",
321 "2.5.5.4",
322 "2.5.5.5",
323 "2.5.5.6",
324 "2.5.5.7",
325 "2.5.5.8",
326 "2.5.5.9",
327 "2.5.5.10",
328 "2.5.5.11",
329 "2.5.5.12",
330 "2.5.5.13",
331 "2.5.5.14",
332 "2.5.5.15",
333 "2.5.5.16",
334 "2.5.5.17"
337 d_printf("Dumping attribute syntaxes\n");
339 for (i=0; i < ARRAY_SIZE(syntaxes); i++) {
340 for (a=schema->attributes; a; a = a->next) {
341 char *om_hex;
343 if (strcmp(syntaxes[i], a->attributeSyntax_oid) != 0) continue;
345 om_hex = data_blob_hex_string_upper(ldb, &a->oMObjectClass);
346 if (!om_hex) {
347 return false;
350 d_printf("attr[%4u]: %s %u '%s' '%s'\n", a_i++,
351 a->attributeSyntax_oid, a->oMSyntax,
352 om_hex, a->lDAPDisplayName);
353 talloc_free(om_hex);
357 return true;
360 static bool test_dump_not_in_filtered_replica(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema *schema)
362 struct dsdb_attribute *a;
363 uint32_t a_i = 1;
365 d_printf("Dumping attributes not in filtered replica\n");
367 for (a=schema->attributes; a; a = a->next) {
368 if (!dsdb_attribute_is_attr_in_filtered_replica(a)) {
369 d_printf("attr[%4u]: '%s'\n", a_i++,
370 a->lDAPDisplayName);
373 return true;
376 bool torture_ldap_schema(struct torture_context *torture)
378 struct ldb_context *ldb;
379 bool ret = true;
380 const char *host = torture_setting_string(torture, "host", NULL);
381 char *url;
382 struct test_rootDSE rootDSE;
383 struct dsdb_schema *schema = NULL;
385 ZERO_STRUCT(rootDSE);
387 url = talloc_asprintf(torture, "ldap://%s/", host);
389 ldb = ldb_wrap_connect(torture, torture->ev, torture->lp_ctx, url,
390 NULL,
391 popt_get_cmdline_credentials(),
393 if (!ldb) goto failed;
395 ret &= test_search_rootDSE(ldb, &rootDSE);
396 if (!ret) goto failed;
397 ret &= test_create_schema(ldb, &rootDSE, &schema);
398 if (!ret) goto failed;
400 ret &= test_dump_not_replicated(ldb, &rootDSE, schema);
401 ret &= test_dump_partial(ldb, &rootDSE, schema);
402 ret &= test_dump_contructed(ldb, &rootDSE, schema);
403 ret &= test_dump_sorted_syntax(ldb, &rootDSE, schema);
404 ret &= test_dump_not_in_filtered_replica(ldb, &rootDSE, schema);
406 failed:
407 return ret;