Revert "s4:api.py - DN tests - test a bit more special DNs and merge the comparison...
[Samba/gebeck_regimport.git] / source4 / torture / ldap / basic.c
blob1efdc06a8ca7efe3168d548d2c9954b8c8136c02
1 /*
2 Unix SMB/CIFS mplementation.
3 LDAP protocol helper functions for SAMBA
5 Copyright (C) Stefan Metzmacher 2004
6 Copyright (C) Simo Sorce 2004
7 Copyright (C) Matthias Dieter Wallnöfer 2009-2010
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
25 #include "ldb_wrap.h"
26 #include "libcli/ldap/ldap_client.h"
27 #include "lib/cmdline/popt_common.h"
29 #include "torture/torture.h"
30 #include "torture/ldap/proto.h"
33 static bool test_bind_simple(struct ldap_connection *conn, const char *userdn, const char *password)
35 NTSTATUS status;
36 bool ret = true;
38 status = torture_ldap_bind(conn, userdn, password);
39 if (!NT_STATUS_IS_OK(status)) {
40 ret = false;
43 return ret;
46 static bool test_bind_sasl(struct torture_context *tctx,
47 struct ldap_connection *conn, struct cli_credentials *creds)
49 NTSTATUS status;
50 bool ret = true;
52 printf("Testing sasl bind as user\n");
54 status = torture_ldap_bind_sasl(conn, creds, tctx->lp_ctx);
55 if (!NT_STATUS_IS_OK(status)) {
56 ret = false;
59 return ret;
62 static bool test_multibind(struct ldap_connection *conn, const char *userdn, const char *password)
64 bool ret = true;
66 printf("Testing multiple binds on a single connnection as anonymous and user\n");
68 ret = test_bind_simple(conn, NULL, NULL);
69 if (!ret) {
70 printf("1st bind as anonymous failed\n");
71 return ret;
74 ret = test_bind_simple(conn, userdn, password);
75 if (!ret) {
76 printf("2nd bind as authenticated user failed\n");
79 return ret;
82 static bool test_search_rootDSE(struct ldap_connection *conn, const char **basedn,
83 const char ***partitions)
85 bool ret = true;
86 struct ldap_message *msg, *result;
87 struct ldap_request *req;
88 int i;
89 struct ldap_SearchResEntry *r;
90 NTSTATUS status;
92 printf("Testing RootDSE Search\n");
94 *basedn = NULL;
96 if (partitions != NULL) {
97 *partitions = const_str_list(str_list_make_empty(conn));
100 msg = new_ldap_message(conn);
101 if (!msg) {
102 return false;
105 msg->type = LDAP_TAG_SearchRequest;
106 msg->r.SearchRequest.basedn = "";
107 msg->r.SearchRequest.scope = LDAP_SEARCH_SCOPE_BASE;
108 msg->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER;
109 msg->r.SearchRequest.timelimit = 0;
110 msg->r.SearchRequest.sizelimit = 0;
111 msg->r.SearchRequest.attributesonly = false;
112 msg->r.SearchRequest.tree = ldb_parse_tree(msg, "(objectclass=*)");
113 msg->r.SearchRequest.num_attributes = 0;
114 msg->r.SearchRequest.attributes = NULL;
116 req = ldap_request_send(conn, msg);
117 if (req == NULL) {
118 printf("Could not setup ldap search\n");
119 return false;
122 status = ldap_result_one(req, &result, LDAP_TAG_SearchResultEntry);
123 if (!NT_STATUS_IS_OK(status)) {
124 printf("search failed - %s\n", nt_errstr(status));
125 return false;
128 printf("received %d replies\n", req->num_replies);
130 r = &result->r.SearchResultEntry;
132 DEBUG(1,("\tdn: %s\n", r->dn));
133 for (i=0; i<r->num_attributes; i++) {
134 int j;
135 for (j=0; j<r->attributes[i].num_values; j++) {
136 DEBUG(1,("\t%s: %d %.*s\n", r->attributes[i].name,
137 (int)r->attributes[i].values[j].length,
138 (int)r->attributes[i].values[j].length,
139 (char *)r->attributes[i].values[j].data));
140 if (!(*basedn) &&
141 strcasecmp("defaultNamingContext",r->attributes[i].name)==0) {
142 *basedn = talloc_asprintf(conn, "%.*s",
143 (int)r->attributes[i].values[j].length,
144 (char *)r->attributes[i].values[j].data);
146 if ((partitions != NULL) &&
147 (strcasecmp("namingContexts", r->attributes[i].name) == 0)) {
148 char *entry = talloc_asprintf(conn, "%.*s",
149 (int)r->attributes[i].values[j].length,
150 (char *)r->attributes[i].values[j].data);
151 *partitions = str_list_add(*partitions, entry);
156 return ret;
159 static bool test_compare_sasl(struct ldap_connection *conn, const char *basedn)
161 struct ldap_message *msg, *rep;
162 struct ldap_request *req;
163 const char *val;
164 NTSTATUS status;
166 printf("Testing SASL Compare: %s\n", basedn);
168 if (!basedn) {
169 return false;
172 msg = new_ldap_message(conn);
173 if (!msg) {
174 return false;
177 msg->type = LDAP_TAG_CompareRequest;
178 msg->r.CompareRequest.dn = basedn;
179 msg->r.CompareRequest.attribute = talloc_strdup(msg, "objectClass");
180 val = "domain";
181 msg->r.CompareRequest.value = data_blob_talloc(msg, val, strlen(val));
183 req = ldap_request_send(conn, msg);
184 if (!req) {
185 return false;
188 status = ldap_result_one(req, &rep, LDAP_TAG_CompareResponse);
189 if (!NT_STATUS_IS_OK(status)) {
190 printf("error in ldap compare request - %s\n", nt_errstr(status));
191 return false;
194 DEBUG(5,("Code: %d DN: [%s] ERROR:[%s] REFERRAL:[%s]\n",
195 rep->r.CompareResponse.resultcode,
196 rep->r.CompareResponse.dn,
197 rep->r.CompareResponse.errormessage,
198 rep->r.CompareResponse.referral));
200 return true;
204 * This takes an AD error message and splits it into the WERROR code
205 * (WERR_DS_GENERIC if none found) and the reason (remaining string).
207 static WERROR ad_error(const char *err_msg, char **reason)
209 WERROR err = W_ERROR(strtol(err_msg, reason, 16));
211 if ((reason != NULL) && (*reason[0] != ':')) {
212 return WERR_DS_GENERIC_ERROR; /* not an AD std error message */
215 if (reason != NULL) {
216 *reason += 2; /* skip ": " */
218 return err;
221 /* This has to be done using the LDAP API since the LDB API does only transmit
222 * the error code and not the error message. */
223 static bool test_error_codes(struct torture_context *tctx,
224 struct ldap_connection *conn, const char *basedn)
226 struct ldap_message *msg, *rep;
227 struct ldap_request *req;
228 const char *err_code_str;
229 char *endptr;
230 WERROR err;
231 NTSTATUS status;
233 printf("Testing the most important error code -> error message conversions!\n");
235 if (!basedn) {
236 return false;
239 msg = new_ldap_message(conn);
240 if (!msg) {
241 return false;
244 printf(" Try a wrong addition\n");
246 msg->type = LDAP_TAG_AddRequest;
247 msg->r.AddRequest.dn = basedn;
248 msg->r.AddRequest.num_attributes = 0;
249 msg->r.AddRequest.attributes = NULL;
251 req = ldap_request_send(conn, msg);
252 if (!req) {
253 return false;
256 status = ldap_result_one(req, &rep, LDAP_TAG_AddResponse);
257 if (!NT_STATUS_IS_OK(status)) {
258 printf("error in ldap add request - %s\n", nt_errstr(status));
259 return false;
262 if ((rep->r.AddResponse.resultcode == 0)
263 || (rep->r.AddResponse.errormessage == NULL)
264 || (strtol(rep->r.AddResponse.errormessage, &endptr,16) <= 0)
265 || (*endptr != ':')) {
266 printf("Invalid error message!\n");
267 return false;
270 err = ad_error(rep->r.AddResponse.errormessage, &endptr);
271 err_code_str = win_errstr(err);
272 printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
273 if ((!W_ERROR_EQUAL(err, WERR_DS_REFERRAL))
274 || (rep->r.AddResponse.resultcode != LDAP_REFERRAL)) {
275 return false;
277 if ((rep->r.AddResponse.referral == NULL)
278 || (strstr(rep->r.AddResponse.referral, basedn) == NULL)) {
279 return false;
282 printf(" Try another wrong addition\n");
284 msg->type = LDAP_TAG_AddRequest;
285 msg->r.AddRequest.dn = "";
286 msg->r.AddRequest.num_attributes = 0;
287 msg->r.AddRequest.attributes = NULL;
289 req = ldap_request_send(conn, msg);
290 if (!req) {
291 return false;
294 status = ldap_result_one(req, &rep, LDAP_TAG_AddResponse);
295 if (!NT_STATUS_IS_OK(status)) {
296 printf("error in ldap add request - %s\n", nt_errstr(status));
297 return false;
300 if ((rep->r.AddResponse.resultcode == 0)
301 || (rep->r.AddResponse.errormessage == NULL)
302 || (strtol(rep->r.AddResponse.errormessage, &endptr,16) <= 0)
303 || (*endptr != ':')) {
304 printf("Invalid error message!\n");
305 return false;
308 err = ad_error(rep->r.AddResponse.errormessage, &endptr);
309 err_code_str = win_errstr(err);
310 printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
311 if ((!W_ERROR_EQUAL(err, WERR_DS_ROOT_MUST_BE_NC) &&
312 !W_ERROR_EQUAL(err, WERR_DS_NAMING_VIOLATION))
313 || (rep->r.AddResponse.resultcode != LDAP_NAMING_VIOLATION)) {
314 return false;
317 printf(" Try a wrong modification\n");
319 msg->type = LDAP_TAG_ModifyRequest;
320 msg->r.ModifyRequest.dn = basedn;
321 msg->r.ModifyRequest.num_mods = 0;
322 msg->r.ModifyRequest.mods = NULL;
324 req = ldap_request_send(conn, msg);
325 if (!req) {
326 return false;
329 status = ldap_result_one(req, &rep, LDAP_TAG_ModifyResponse);
330 if (!NT_STATUS_IS_OK(status)) {
331 printf("error in ldap modifification request - %s\n", nt_errstr(status));
332 return false;
335 if ((rep->r.ModifyResponse.resultcode == 0)
336 || (rep->r.ModifyResponse.errormessage == NULL)
337 || (strtol(rep->r.ModifyResponse.errormessage, &endptr,16) <= 0)
338 || (*endptr != ':')) {
339 printf("Invalid error message!\n");
340 return false;
343 err = ad_error(rep->r.ModifyResponse.errormessage, &endptr);
344 err_code_str = win_errstr(err);
345 printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
346 if ((!W_ERROR_EQUAL(err, WERR_INVALID_PARAM) &&
347 !W_ERROR_EQUAL(err, WERR_DS_UNWILLING_TO_PERFORM))
348 || (rep->r.ModifyResponse.resultcode != LDAP_UNWILLING_TO_PERFORM)) {
349 return false;
352 printf(" Try another wrong modification\n");
354 msg->type = LDAP_TAG_ModifyRequest;
355 msg->r.ModifyRequest.dn = "";
356 msg->r.ModifyRequest.num_mods = 0;
357 msg->r.ModifyRequest.mods = NULL;
359 req = ldap_request_send(conn, msg);
360 if (!req) {
361 return false;
364 status = ldap_result_one(req, &rep, LDAP_TAG_ModifyResponse);
365 if (!NT_STATUS_IS_OK(status)) {
366 printf("error in ldap modifification request - %s\n", nt_errstr(status));
367 return false;
370 if ((rep->r.ModifyResponse.resultcode == 0)
371 || (rep->r.ModifyResponse.errormessage == NULL)
372 || (strtol(rep->r.ModifyResponse.errormessage, &endptr,16) <= 0)
373 || (*endptr != ':')) {
374 printf("Invalid error message!\n");
375 return false;
378 err = ad_error(rep->r.ModifyResponse.errormessage, &endptr);
379 err_code_str = win_errstr(err);
380 printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
381 if ((!W_ERROR_EQUAL(err, WERR_INVALID_PARAM) &&
382 !W_ERROR_EQUAL(err, WERR_DS_UNWILLING_TO_PERFORM))
383 || (rep->r.ModifyResponse.resultcode != LDAP_UNWILLING_TO_PERFORM)) {
384 return false;
387 printf(" Try a wrong removal\n");
389 msg->type = LDAP_TAG_DelRequest;
390 msg->r.DelRequest.dn = basedn;
392 req = ldap_request_send(conn, msg);
393 if (!req) {
394 return false;
397 status = ldap_result_one(req, &rep, LDAP_TAG_DelResponse);
398 if (!NT_STATUS_IS_OK(status)) {
399 printf("error in ldap removal request - %s\n", nt_errstr(status));
400 return false;
403 if ((rep->r.DelResponse.resultcode == 0)
404 || (rep->r.DelResponse.errormessage == NULL)
405 || (strtol(rep->r.DelResponse.errormessage, &endptr,16) <= 0)
406 || (*endptr != ':')) {
407 printf("Invalid error message!\n");
408 return false;
411 err = ad_error(rep->r.DelResponse.errormessage, &endptr);
412 err_code_str = win_errstr(err);
413 printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
414 if ((!W_ERROR_EQUAL(err, WERR_DS_CANT_DELETE) &&
415 !W_ERROR_EQUAL(err, WERR_DS_UNWILLING_TO_PERFORM))
416 || (rep->r.DelResponse.resultcode != LDAP_UNWILLING_TO_PERFORM)) {
417 return false;
420 printf(" Try another wrong removal\n");
422 msg->type = LDAP_TAG_DelRequest;
423 msg->r.DelRequest.dn = "";
425 req = ldap_request_send(conn, msg);
426 if (!req) {
427 return false;
430 status = ldap_result_one(req, &rep, LDAP_TAG_DelResponse);
431 if (!NT_STATUS_IS_OK(status)) {
432 printf("error in ldap removal request - %s\n", nt_errstr(status));
433 return false;
436 if ((rep->r.DelResponse.resultcode == 0)
437 || (rep->r.DelResponse.errormessage == NULL)
438 || (strtol(rep->r.DelResponse.errormessage, &endptr,16) <= 0)
439 || (*endptr != ':')) {
440 printf("Invalid error message!\n");
441 return false;
444 err = ad_error(rep->r.DelResponse.errormessage, &endptr);
445 err_code_str = win_errstr(err);
446 printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
447 if ((!W_ERROR_EQUAL(err, WERR_DS_OBJ_NOT_FOUND) &&
448 !W_ERROR_EQUAL(err, WERR_DS_NO_SUCH_OBJECT))
449 || (rep->r.DelResponse.resultcode != LDAP_NO_SUCH_OBJECT)) {
450 return false;
453 printf(" Try a wrong rename\n");
455 msg->type = LDAP_TAG_ModifyDNRequest;
456 msg->r.ModifyDNRequest.dn = basedn;
457 msg->r.ModifyDNRequest.newrdn = "dc=test";
458 msg->r.ModifyDNRequest.deleteolddn = true;
459 msg->r.ModifyDNRequest.newsuperior = NULL;
461 req = ldap_request_send(conn, msg);
462 if (!req) {
463 return false;
466 status = ldap_result_one(req, &rep, LDAP_TAG_ModifyDNResponse);
467 if (!NT_STATUS_IS_OK(status)) {
468 printf("error in ldap rename request - %s\n", nt_errstr(status));
469 return false;
472 if ((rep->r.ModifyDNResponse.resultcode == 0)
473 || (rep->r.ModifyDNResponse.errormessage == NULL)
474 || (strtol(rep->r.ModifyDNResponse.errormessage, &endptr,16) <= 0)
475 || (*endptr != ':')) {
476 printf("Invalid error message!\n");
477 return false;
480 err = ad_error(rep->r.ModifyDNResponse.errormessage, &endptr);
481 err_code_str = win_errstr(err);
482 printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
483 if ((!W_ERROR_EQUAL(err, WERR_DS_NO_PARENT_OBJECT) &&
484 !W_ERROR_EQUAL(err, WERR_DS_GENERIC_ERROR))
485 || (rep->r.ModifyDNResponse.resultcode != LDAP_OTHER)) {
486 return false;
489 printf(" Try another wrong rename\n");
491 msg->type = LDAP_TAG_ModifyDNRequest;
492 msg->r.ModifyDNRequest.dn = basedn;
493 msg->r.ModifyDNRequest.newrdn = basedn;
494 msg->r.ModifyDNRequest.deleteolddn = true;
495 msg->r.ModifyDNRequest.newsuperior = NULL;
497 req = ldap_request_send(conn, msg);
498 if (!req) {
499 return false;
502 status = ldap_result_one(req, &rep, LDAP_TAG_ModifyDNResponse);
503 if (!NT_STATUS_IS_OK(status)) {
504 printf("error in ldap rename request - %s\n", nt_errstr(status));
505 return false;
508 if ((rep->r.ModifyDNResponse.resultcode == 0)
509 || (rep->r.ModifyDNResponse.errormessage == NULL)
510 || (strtol(rep->r.ModifyDNResponse.errormessage, &endptr,16) <= 0)
511 || (*endptr != ':')) {
512 printf("Invalid error message!\n");
513 return false;
516 err = ad_error(rep->r.ModifyDNResponse.errormessage, &endptr);
517 err_code_str = win_errstr(err);
518 printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
519 if ((!W_ERROR_EQUAL(err, WERR_INVALID_PARAM) &&
520 !W_ERROR_EQUAL(err, WERR_DS_NAMING_VIOLATION))
521 || (rep->r.ModifyDNResponse.resultcode != LDAP_NAMING_VIOLATION)) {
522 return false;
525 printf(" Try another wrong rename\n");
527 msg->type = LDAP_TAG_ModifyDNRequest;
528 msg->r.ModifyDNRequest.dn = basedn;
529 msg->r.ModifyDNRequest.newrdn = "";
530 msg->r.ModifyDNRequest.deleteolddn = true;
531 msg->r.ModifyDNRequest.newsuperior = NULL;
533 req = ldap_request_send(conn, msg);
534 if (!req) {
535 return false;
538 status = ldap_result_one(req, &rep, LDAP_TAG_ModifyDNResponse);
539 if (!NT_STATUS_IS_OK(status)) {
540 printf("error in ldap rename request - %s\n", nt_errstr(status));
541 return false;
544 if ((rep->r.ModifyDNResponse.resultcode == 0)
545 || (rep->r.ModifyDNResponse.errormessage == NULL)
546 || (strtol(rep->r.ModifyDNResponse.errormessage, &endptr,16) <= 0)
547 || (*endptr != ':')) {
548 printf("Invalid error message!\n");
549 return false;
552 err = ad_error(rep->r.ModifyDNResponse.errormessage, &endptr);
553 err_code_str = win_errstr(err);
554 printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
555 if ((!W_ERROR_EQUAL(err, WERR_INVALID_PARAM) &&
556 !W_ERROR_EQUAL(err, WERR_DS_PROTOCOL_ERROR))
557 || (rep->r.ModifyDNResponse.resultcode != LDAP_PROTOCOL_ERROR)) {
558 return false;
561 printf(" Try another wrong rename\n");
563 msg->type = LDAP_TAG_ModifyDNRequest;
564 msg->r.ModifyDNRequest.dn = "";
565 msg->r.ModifyDNRequest.newrdn = "cn=temp";
566 msg->r.ModifyDNRequest.deleteolddn = true;
567 msg->r.ModifyDNRequest.newsuperior = NULL;
569 req = ldap_request_send(conn, msg);
570 if (!req) {
571 return false;
574 status = ldap_result_one(req, &rep, LDAP_TAG_ModifyDNResponse);
575 if (!NT_STATUS_IS_OK(status)) {
576 printf("error in ldap rename request - %s\n", nt_errstr(status));
577 return false;
580 if ((rep->r.ModifyDNResponse.resultcode == 0)
581 || (rep->r.ModifyDNResponse.errormessage == NULL)
582 || (strtol(rep->r.ModifyDNResponse.errormessage, &endptr,16) <= 0)
583 || (*endptr != ':')) {
584 printf("Invalid error message!\n");
585 return false;
588 err = ad_error(rep->r.ModifyDNResponse.errormessage, &endptr);
589 err_code_str = win_errstr(err);
590 printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
591 if ((!W_ERROR_EQUAL(err, WERR_DS_OBJ_NOT_FOUND) &&
592 !W_ERROR_EQUAL(err, WERR_DS_NO_SUCH_OBJECT))
593 || (rep->r.ModifyDNResponse.resultcode != LDAP_NO_SUCH_OBJECT)) {
594 return false;
597 return true;
600 static bool test_referrals(struct torture_context *tctx, TALLOC_CTX *mem_ctx,
601 const char *url, const char *basedn, const char **partitions)
603 struct ldb_context *ldb;
604 struct ldb_result *res;
605 const char * const *attrs = { NULL };
606 struct ldb_dn *dn1, *dn2;
607 int ret;
608 int i, j, k;
609 char *tempstr;
610 bool found, l_found;
612 printf("Testing referrals\n");
614 if (partitions[0] == NULL) {
615 printf("Partitions list empty!\n");
616 return false;
619 if (strcmp(partitions[0], basedn) != 0) {
620 printf("The first (root) partition DN should be the base DN!\n");
621 return false;
624 ldb = ldb_wrap_connect(mem_ctx, tctx->ev, tctx->lp_ctx, url,
625 NULL, cmdline_credentials, 0);
627 /* "partitions[i]" are the partitions for which we search the parents */
628 for (i = 1; partitions[i] != NULL; i++) {
629 dn1 = ldb_dn_new(mem_ctx, ldb, partitions[i]);
630 if (dn1 == NULL) {
631 printf("Out of memory\n");
632 talloc_free(ldb);
633 return false;
636 /* search using base scope */
637 /* "partitions[j]" are the parent candidates */
638 for (j = str_list_length(partitions) - 1; j >= 0; --j) {
639 dn2 = ldb_dn_new(mem_ctx, ldb, partitions[j]);
640 if (dn2 == NULL) {
641 printf("Out of memory\n");
642 talloc_free(ldb);
643 return false;
646 ret = ldb_search(ldb, mem_ctx, &res, dn2,
647 LDB_SCOPE_BASE, attrs,
648 "(foo=bar)");
649 if (ret != LDB_SUCCESS) {
650 printf("%s", ldb_errstring(ldb));
651 talloc_free(ldb);
652 return false;
655 if (res->refs != NULL) {
656 printf("There shouldn't be generated any referrals in the base scope!\n");
657 talloc_free(ldb);
658 return false;
661 talloc_free(res);
662 talloc_free(dn2);
665 /* search using onelevel scope */
666 found = false;
667 /* "partitions[j]" are the parent candidates */
668 for (j = str_list_length(partitions) - 1; j >= 0; --j) {
669 dn2 = ldb_dn_new(mem_ctx, ldb, partitions[j]);
670 if (dn2 == NULL) {
671 printf("Out of memory\n");
672 talloc_free(ldb);
673 return false;
676 ret = ldb_search(ldb, mem_ctx, &res, dn2,
677 LDB_SCOPE_ONELEVEL, attrs,
678 "(foo=bar)");
679 if (ret != LDB_SUCCESS) {
680 printf("%s", ldb_errstring(ldb));
681 talloc_free(ldb);
682 return false;
685 tempstr = talloc_asprintf(mem_ctx, "/%s??base",
686 partitions[i]);
687 if (tempstr == NULL) {
688 printf("Out of memory\n");
689 talloc_free(ldb);
690 return false;
693 /* Try to find or find not a matching referral */
694 l_found = false;
695 for (k = 0; (!l_found) && (res->refs != NULL)
696 && (res->refs[k] != NULL); k++) {
697 if (strstr(res->refs[k], tempstr) != NULL) {
698 l_found = true;
702 talloc_free(tempstr);
704 if ((!found) && (ldb_dn_compare_base(dn2, dn1) == 0)
705 && (ldb_dn_compare(dn2, dn1) != 0)) {
706 /* This is a referral candidate */
707 if (!l_found) {
708 printf("A required referral hasn't been found on onelevel scope (%s -> %s)!\n", partitions[j], partitions[i]);
709 talloc_free(ldb);
710 return false;
712 found = true;
713 } else {
714 /* This isn't a referral candidate */
715 if (l_found) {
716 printf("A unrequired referral has been found on onelevel scope (%s -> %s)!\n", partitions[j], partitions[i]);
717 talloc_free(ldb);
718 return false;
722 talloc_free(res);
723 talloc_free(dn2);
726 /* search using subtree scope */
727 found = false;
728 /* "partitions[j]" are the parent candidates */
729 for (j = str_list_length(partitions) - 1; j >= 0; --j) {
730 dn2 = ldb_dn_new(mem_ctx, ldb, partitions[j]);
731 if (dn2 == NULL) {
732 printf("Out of memory\n");
733 talloc_free(ldb);
734 return false;
737 ret = ldb_search(ldb, mem_ctx, &res, dn2,
738 LDB_SCOPE_SUBTREE, attrs,
739 "(foo=bar)");
740 if (ret != LDB_SUCCESS) {
741 printf("%s", ldb_errstring(ldb));
742 talloc_free(ldb);
743 return false;
746 tempstr = talloc_asprintf(mem_ctx, "/%s",
747 partitions[i]);
748 if (tempstr == NULL) {
749 printf("Out of memory\n");
750 talloc_free(ldb);
751 return false;
754 /* Try to find or find not a matching referral */
755 l_found = false;
756 for (k = 0; (!l_found) && (res->refs != NULL)
757 && (res->refs[k] != NULL); k++) {
758 if (strstr(res->refs[k], tempstr) != NULL) {
759 l_found = true;
763 talloc_free(tempstr);
765 if ((!found) && (ldb_dn_compare_base(dn2, dn1) == 0)
766 && (ldb_dn_compare(dn2, dn1) != 0)) {
767 /* This is a referral candidate */
768 if (!l_found) {
769 printf("A required referral hasn't been found on subtree scope (%s -> %s)!\n", partitions[j], partitions[i]);
770 talloc_free(ldb);
771 return false;
773 found = true;
774 } else {
775 /* This isn't a referral candidate */
776 if (l_found) {
777 printf("A unrequired referral has been found on subtree scope (%s -> %s)!\n", partitions[j], partitions[i]);
778 talloc_free(ldb);
779 return false;
783 talloc_free(res);
784 talloc_free(dn2);
787 talloc_free(dn1);
790 talloc_free(ldb);
792 return true;
795 static bool test_abandom_request(struct torture_context *tctx,
796 struct ldap_connection *conn, const char *basedn)
798 struct ldap_message *msg;
799 struct ldap_request *req;
800 NTSTATUS status;
802 printf("Testing the AbandonRequest with an old message id!\n");
804 if (!basedn) {
805 return false;
808 msg = new_ldap_message(conn);
809 if (!msg) {
810 return false;
813 printf(" Try a AbandonRequest for an old message id\n");
815 msg->type = LDAP_TAG_AbandonRequest;
816 msg->r.AbandonRequest.messageid = 1;
818 req = ldap_request_send(conn, msg);
819 if (!req) {
820 return false;
823 status = ldap_request_wait(req);
824 if (!NT_STATUS_IS_OK(status)) {
825 printf("error in ldap abandon request - %s\n", nt_errstr(status));
826 return false;
829 return true;
833 bool torture_ldap_basic(struct torture_context *torture)
835 NTSTATUS status;
836 struct ldap_connection *conn;
837 TALLOC_CTX *mem_ctx;
838 bool ret = true;
839 const char *host = torture_setting_string(torture, "host", NULL);
840 const char *userdn = torture_setting_string(torture, "ldap_userdn", NULL);
841 const char *secret = torture_setting_string(torture, "ldap_secret", NULL);
842 const char *url;
843 const char *basedn;
844 const char **partitions;
846 mem_ctx = talloc_init("torture_ldap_basic");
848 url = talloc_asprintf(mem_ctx, "ldap://%s/", host);
850 status = torture_ldap_connection(torture, &conn, url);
851 if (!NT_STATUS_IS_OK(status)) {
852 return false;
855 if (!test_search_rootDSE(conn, &basedn, &partitions)) {
856 ret = false;
859 /* other bind tests here */
861 if (!test_multibind(conn, userdn, secret)) {
862 ret = false;
865 if (!test_bind_sasl(torture, conn, cmdline_credentials)) {
866 ret = false;
869 if (!test_compare_sasl(conn, basedn)) {
870 ret = false;
873 /* error codes test here */
875 if (!test_error_codes(torture, conn, basedn)) {
876 ret = false;
879 /* referrals test here */
881 if (!test_referrals(torture, mem_ctx, url, basedn, partitions)) {
882 ret = false;
885 if (!test_abandom_request(torture, conn, basedn)) {
886 ret = false;
889 /* if there are no more tests we are closing */
890 torture_ldap_close(conn);
891 talloc_free(mem_ctx);
893 return ret;