Line data Source code
1 : /*
2 : Unix SMB/CIFS Implementation.
3 : LDAP schema tests
4 :
5 : Copyright (C) Stefan Metzmacher 2006
6 :
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.
11 :
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.
16 :
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/>.
19 :
20 : */
21 :
22 : #include "includes.h"
23 : #include "libcli/ldap/ldap_client.h"
24 : #include "lib/cmdline/cmdline.h"
25 : #include "ldb_wrap.h"
26 : #include "dsdb/samdb/samdb.h"
27 : #include "../lib/util/dlinklist.h"
28 :
29 : #include "torture/torture.h"
30 : #include "torture/ldap/proto.h"
31 :
32 :
33 : struct test_rootDSE {
34 : const char *defaultdn;
35 : const char *rootdn;
36 : const char *configdn;
37 : const char *schemadn;
38 : };
39 :
40 : struct test_schema_ctx {
41 : struct ldb_context *ldb;
42 :
43 : struct ldb_paged_control *ctrl;
44 : uint32_t count;
45 : bool pending;
46 :
47 : int (*callback)(void *, struct ldb_context *ldb, struct ldb_message *);
48 : void *private_data;
49 : };
50 :
51 1 : static bool test_search_rootDSE(struct ldb_context *ldb, struct test_rootDSE *root)
52 : {
53 0 : int ret;
54 0 : struct ldb_message *msg;
55 0 : struct ldb_result *r;
56 :
57 1 : d_printf("Testing RootDSE Search\n");
58 :
59 1 : ret = ldb_search(ldb, ldb, &r, ldb_dn_new(ldb, ldb, NULL),
60 : LDB_SCOPE_BASE, NULL, NULL);
61 1 : if (ret != LDB_SUCCESS) {
62 0 : return false;
63 1 : } else if (r->count != 1) {
64 0 : talloc_free(r);
65 0 : return false;
66 : }
67 :
68 1 : msg = r->msgs[0];
69 :
70 1 : root->defaultdn = ldb_msg_find_attr_as_string(msg, "defaultNamingContext", NULL);
71 1 : talloc_steal(ldb, root->defaultdn);
72 1 : root->rootdn = ldb_msg_find_attr_as_string(msg, "rootDomainNamingContext", NULL);
73 1 : talloc_steal(ldb, root->rootdn);
74 1 : root->configdn = ldb_msg_find_attr_as_string(msg, "configurationNamingContext", NULL);
75 1 : talloc_steal(ldb, root->configdn);
76 1 : root->schemadn = ldb_msg_find_attr_as_string(msg, "schemaNamingContext", NULL);
77 1 : talloc_steal(ldb, root->schemadn);
78 :
79 1 : talloc_free(r);
80 :
81 1 : return true;
82 : }
83 :
84 1771 : static int test_schema_search_callback(struct ldb_request *req, struct ldb_reply *ares)
85 : {
86 0 : struct test_schema_ctx *actx;
87 1771 : int ret = LDB_SUCCESS;
88 :
89 1771 : actx = talloc_get_type(req->context, struct test_schema_ctx);
90 :
91 1771 : if (!ares) {
92 0 : return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
93 : }
94 1771 : if (ares->error != LDB_SUCCESS) {
95 0 : return ldb_request_done(req, ares->error);
96 : }
97 :
98 1771 : switch (ares->type) {
99 1768 : case LDB_REPLY_ENTRY:
100 1768 : actx->count++;
101 1768 : ret = actx->callback(actx->private_data, actx->ldb, ares->message);
102 1768 : break;
103 :
104 0 : case LDB_REPLY_REFERRAL:
105 0 : break;
106 :
107 3 : case LDB_REPLY_DONE:
108 3 : if (ares->controls) {
109 3 : struct ldb_paged_control *ctrl = NULL;
110 : int i;
111 :
112 3 : for (i=0; ares->controls[i]; i++) {
113 3 : if (strcmp(LDB_CONTROL_PAGED_RESULTS_OID, ares->controls[i]->oid) == 0) {
114 3 : ctrl = talloc_get_type(ares->controls[i]->data, struct ldb_paged_control);
115 3 : break;
116 : }
117 : }
118 :
119 3 : if (!ctrl) break;
120 :
121 3 : talloc_free(actx->ctrl->cookie);
122 3 : actx->ctrl->cookie = talloc_steal(actx->ctrl->cookie, ctrl->cookie);
123 3 : actx->ctrl->cookie_len = ctrl->cookie_len;
124 :
125 3 : if (actx->ctrl->cookie_len > 0) {
126 1 : actx->pending = true;
127 : }
128 : }
129 3 : talloc_free(ares);
130 3 : return ldb_request_done(req, LDB_SUCCESS);
131 :
132 0 : default:
133 0 : d_printf("%s: unknown Reply Type %u\n", __location__, ares->type);
134 0 : return ldb_request_done(req, LDB_ERR_OTHER);
135 : }
136 :
137 1768 : if (talloc_free(ares) == -1) {
138 0 : d_printf("talloc_free failed\n");
139 0 : actx->pending = 0;
140 0 : return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
141 : }
142 :
143 1768 : if (ret) {
144 0 : return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
145 : }
146 :
147 1768 : return LDB_SUCCESS;
148 : }
149 :
150 2 : 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)
154 : {
155 0 : struct ldb_control **ctrl;
156 0 : struct ldb_paged_control *control;
157 0 : struct ldb_request *req;
158 0 : int ret;
159 0 : struct test_schema_ctx *actx;
160 :
161 2 : actx = talloc(ldb, struct test_schema_ctx);
162 2 : actx->ldb = ldb;
163 2 : actx->private_data = private_data;
164 2 : actx->callback= callback;
165 :
166 2 : ctrl = talloc_array(actx, struct ldb_control *, 2);
167 2 : ctrl[0] = talloc(ctrl, struct ldb_control);
168 2 : ctrl[0]->oid = LDB_CONTROL_PAGED_RESULTS_OID;
169 2 : ctrl[0]->critical = true;
170 2 : control = talloc(ctrl[0], struct ldb_paged_control);
171 2 : control->size = 1000;
172 2 : control->cookie = NULL;
173 2 : control->cookie_len = 0;
174 2 : ctrl[0]->data = control;
175 2 : ctrl[1] = NULL;
176 :
177 2 : 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);
184 :
185 2 : actx->ctrl = control;
186 2 : actx->count = 0;
187 3 : again:
188 3 : actx->pending = false;
189 :
190 3 : ret = ldb_request(ldb, req);
191 3 : if (ret != LDB_SUCCESS) {
192 0 : d_printf("search failed - %s\n", ldb_errstring(ldb));
193 0 : talloc_free(actx);
194 0 : return false;
195 : }
196 :
197 3 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
198 3 : if (ret != LDB_SUCCESS) {
199 0 : d_printf("search error - %s\n", ldb_errstring(ldb));
200 0 : talloc_free(actx);
201 0 : return false;
202 : }
203 :
204 3 : if (actx->pending)
205 1 : goto again;
206 :
207 2 : d_printf("filter[%s] count[%u]\n", filter, actx->count);
208 2 : talloc_free(actx);
209 2 : return true;
210 : }
211 :
212 1499 : static int test_add_attribute(void *ptr, struct ldb_context *ldb, struct ldb_message *msg)
213 : {
214 1499 : struct dsdb_schema *schema = talloc_get_type(ptr, struct dsdb_schema);
215 0 : WERROR status;
216 :
217 1499 : status = dsdb_set_attribute_from_ldb(ldb, schema, msg);
218 1499 : if (!W_ERROR_IS_OK(status)) {
219 0 : goto failed;
220 : }
221 :
222 1499 : return LDB_SUCCESS;
223 0 : failed:
224 0 : return LDB_ERR_OTHER;
225 : }
226 :
227 269 : static int test_add_class(void *ptr, struct ldb_context *ldb, struct ldb_message *msg)
228 : {
229 269 : struct dsdb_schema *schema = talloc_get_type(ptr, struct dsdb_schema);
230 0 : WERROR status;
231 :
232 269 : status = dsdb_set_class_from_ldb(schema, msg);
233 269 : if (!W_ERROR_IS_OK(status)) {
234 0 : goto failed;
235 : }
236 :
237 269 : return LDB_SUCCESS;
238 0 : failed:
239 0 : return LDB_ERR_OTHER;
240 : }
241 :
242 1 : static bool test_create_schema(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema **_schema)
243 : {
244 1 : bool ret = true;
245 0 : struct dsdb_schema *schema;
246 :
247 1 : schema = talloc_zero(ldb, struct dsdb_schema);
248 :
249 1 : d_printf("Fetching attributes...\n");
250 1 : ret &= test_create_schema_type(ldb, root, "(objectClass=attributeSchema)",
251 : test_add_attribute, schema);
252 1 : d_printf("Fetching objectClasses...\n");
253 1 : ret &= test_create_schema_type(ldb, root, "(objectClass=classSchema)",
254 : test_add_class, schema);
255 :
256 1 : if (ret == true) {
257 1 : *_schema = schema;
258 : }
259 1 : return ret;
260 : }
261 :
262 1 : static bool test_dump_not_replicated(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema *schema)
263 : {
264 0 : struct dsdb_attribute *a;
265 1 : uint32_t a_i = 1;
266 :
267 1 : d_printf("Dumping not replicated attributes\n");
268 :
269 1500 : for (a=schema->attributes; a; a = a->next) {
270 1499 : if (!(a->systemFlags & 0x00000001)) continue;
271 98 : d_printf("attr[%4u]: '%s'\n", a_i++,
272 : a->lDAPDisplayName);
273 : }
274 :
275 1 : return true;
276 : }
277 :
278 1 : static bool test_dump_partial(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema *schema)
279 : {
280 0 : struct dsdb_attribute *a;
281 1 : uint32_t a_i = 1;
282 :
283 1 : d_printf("Dumping attributes which are provided by the global catalog\n");
284 :
285 1500 : for (a=schema->attributes; a; a = a->next) {
286 1499 : if (!(a->systemFlags & 0x00000002) && !a->isMemberOfPartialAttributeSet) continue;
287 201 : d_printf("attr[%4u]: %u %u '%s'\n", a_i++,
288 201 : a->systemFlags & 0x00000002, a->isMemberOfPartialAttributeSet,
289 : a->lDAPDisplayName);
290 : }
291 :
292 1 : return true;
293 : }
294 :
295 1 : static bool test_dump_contructed(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema *schema)
296 : {
297 0 : struct dsdb_attribute *a;
298 1 : uint32_t a_i = 1;
299 :
300 1 : d_printf("Dumping constructed attributes\n");
301 :
302 1500 : for (a=schema->attributes; a; a = a->next) {
303 1499 : if (!(a->systemFlags & 0x00000004)) continue;
304 55 : d_printf("attr[%4u]: '%s'\n", a_i++,
305 : a->lDAPDisplayName);
306 : }
307 :
308 1 : return true;
309 : }
310 :
311 1 : static bool test_dump_sorted_syntax(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema *schema)
312 : {
313 0 : struct dsdb_attribute *a;
314 1 : uint32_t a_i = 1;
315 0 : uint32_t i;
316 1 : 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"
335 : };
336 :
337 1 : d_printf("Dumping attribute syntaxes\n");
338 :
339 19 : for (i=0; i < ARRAY_SIZE(syntaxes); i++) {
340 27000 : for (a=schema->attributes; a; a = a->next) {
341 0 : char *om_hex;
342 :
343 26982 : if (strcmp(syntaxes[i], a->attributeSyntax_oid) != 0) continue;
344 :
345 1499 : om_hex = data_blob_hex_string_upper(ldb, &a->oMObjectClass);
346 1499 : if (!om_hex) {
347 0 : return false;
348 : }
349 :
350 1499 : d_printf("attr[%4u]: %s %u '%s' '%s'\n", a_i++,
351 : a->attributeSyntax_oid, a->oMSyntax,
352 : om_hex, a->lDAPDisplayName);
353 1499 : talloc_free(om_hex);
354 : }
355 : }
356 :
357 1 : return true;
358 : }
359 :
360 1 : static bool test_dump_not_in_filtered_replica(struct ldb_context *ldb, struct test_rootDSE *root, struct dsdb_schema *schema)
361 : {
362 0 : struct dsdb_attribute *a;
363 1 : uint32_t a_i = 1;
364 :
365 1 : d_printf("Dumping attributes not in filtered replica\n");
366 :
367 1500 : for (a=schema->attributes; a; a = a->next) {
368 1499 : if (!dsdb_attribute_is_attr_in_filtered_replica(a)) {
369 479 : d_printf("attr[%4u]: '%s'\n", a_i++,
370 : a->lDAPDisplayName);
371 : }
372 : }
373 1 : return true;
374 : }
375 :
376 1 : bool torture_ldap_schema(struct torture_context *torture)
377 : {
378 0 : struct ldb_context *ldb;
379 1 : bool ret = true;
380 1 : const char *host = torture_setting_string(torture, "host", NULL);
381 0 : char *url;
382 0 : struct test_rootDSE rootDSE;
383 1 : struct dsdb_schema *schema = NULL;
384 :
385 1 : ZERO_STRUCT(rootDSE);
386 :
387 1 : url = talloc_asprintf(torture, "ldap://%s/", host);
388 :
389 1 : ldb = ldb_wrap_connect(torture, torture->ev, torture->lp_ctx, url,
390 : NULL,
391 : samba_cmdline_get_creds(),
392 : 0);
393 1 : if (!ldb) goto failed;
394 :
395 1 : ret &= test_search_rootDSE(ldb, &rootDSE);
396 1 : if (!ret) goto failed;
397 1 : ret &= test_create_schema(ldb, &rootDSE, &schema);
398 1 : if (!ret) goto failed;
399 :
400 1 : ret &= test_dump_not_replicated(ldb, &rootDSE, schema);
401 1 : ret &= test_dump_partial(ldb, &rootDSE, schema);
402 1 : ret &= test_dump_contructed(ldb, &rootDSE, schema);
403 1 : ret &= test_dump_sorted_syntax(ldb, &rootDSE, schema);
404 1 : ret &= test_dump_not_in_filtered_replica(ldb, &rootDSE, schema);
405 :
406 1 : failed:
407 1 : return ret;
408 : }
|