torture: Fix ldap.basic multibind test
[Samba.git] / source4 / torture / ldap / basic.c
blob825ee835c65737ea0936cc1e1dcc7904c254a952
1 /*
2 Unix SMB/CIFS Implementation.
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_sasl(struct torture_context *tctx,
34 struct ldap_connection *conn, struct cli_credentials *creds)
36 NTSTATUS status;
37 bool ret = true;
39 printf("Testing sasl bind as user\n");
41 status = torture_ldap_bind_sasl(conn, creds, tctx->lp_ctx);
42 if (!NT_STATUS_IS_OK(status)) {
43 ret = false;
46 return ret;
49 static bool test_multibind(struct ldap_connection *conn, const char *userdn, const char *password)
51 NTSTATUS status, expected;
52 bool ok;
54 printf("Testing multiple binds on a single connection as anonymous and user\n");
56 status = torture_ldap_bind(conn, NULL, NULL);
57 if (!NT_STATUS_IS_OK(status)) {
58 printf("1st bind as anonymous failed with %s\n",
59 nt_errstr(status));
60 return false;
63 expected = NT_STATUS_LDAP(LDAP_STRONG_AUTH_REQUIRED);
64 status = torture_ldap_bind(conn, userdn, password);
66 ok = NT_STATUS_EQUAL(status, expected);
67 if (!ok) {
68 printf("2nd bind as authenticated user should have "
69 "failed with: %s, got %s\n",
70 nt_errstr(expected),
71 nt_errstr(status));
72 return false;
75 return true;
78 static bool test_search_rootDSE(struct ldap_connection *conn, const char **basedn,
79 const char ***partitions)
81 bool ret = true;
82 struct ldap_message *msg, *result;
83 struct ldap_request *req;
84 int i;
85 struct ldap_SearchResEntry *r;
86 NTSTATUS status;
88 printf("Testing RootDSE Search\n");
90 *basedn = NULL;
92 if (partitions != NULL) {
93 *partitions = const_str_list(str_list_make_empty(conn));
96 msg = new_ldap_message(conn);
97 if (!msg) {
98 return false;
101 msg->type = LDAP_TAG_SearchRequest;
102 msg->r.SearchRequest.basedn = "";
103 msg->r.SearchRequest.scope = LDAP_SEARCH_SCOPE_BASE;
104 msg->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER;
105 msg->r.SearchRequest.timelimit = 0;
106 msg->r.SearchRequest.sizelimit = 0;
107 msg->r.SearchRequest.attributesonly = false;
108 msg->r.SearchRequest.tree = ldb_parse_tree(msg, "(objectclass=*)");
109 msg->r.SearchRequest.num_attributes = 0;
110 msg->r.SearchRequest.attributes = NULL;
112 req = ldap_request_send(conn, msg);
113 if (req == NULL) {
114 printf("Could not setup ldap search\n");
115 return false;
118 status = ldap_result_one(req, &result, LDAP_TAG_SearchResultEntry);
119 if (!NT_STATUS_IS_OK(status)) {
120 printf("search failed - %s\n", nt_errstr(status));
121 return false;
124 printf("received %d replies\n", req->num_replies);
126 r = &result->r.SearchResultEntry;
128 DEBUG(1,("\tdn: %s\n", r->dn));
129 for (i=0; i<r->num_attributes; i++) {
130 unsigned int j;
131 for (j=0; j<r->attributes[i].num_values; j++) {
132 DEBUG(1,("\t%s: %d %.*s\n", r->attributes[i].name,
133 (int)r->attributes[i].values[j].length,
134 (int)r->attributes[i].values[j].length,
135 (char *)r->attributes[i].values[j].data));
136 if (!(*basedn) &&
137 strcasecmp("defaultNamingContext",r->attributes[i].name)==0) {
138 *basedn = talloc_asprintf(conn, "%.*s",
139 (int)r->attributes[i].values[j].length,
140 (char *)r->attributes[i].values[j].data);
142 if ((partitions != NULL) &&
143 (strcasecmp("namingContexts", r->attributes[i].name) == 0)) {
144 char *entry = talloc_asprintf(conn, "%.*s",
145 (int)r->attributes[i].values[j].length,
146 (char *)r->attributes[i].values[j].data);
147 *partitions = str_list_add(*partitions, entry);
152 return ret;
155 static bool test_search_rootDSE_empty_substring(struct ldap_connection *conn)
157 bool ret = true;
158 struct ldap_message *msg, *result;
159 struct ldap_request *req;
160 NTSTATUS status;
162 printf("Testing RootDSE Search with objectclass= substring filter\n");
164 msg = new_ldap_message(conn);
165 if (!msg) {
166 return false;
169 msg->type = LDAP_TAG_SearchRequest;
170 msg->r.SearchRequest.basedn = "";
171 msg->r.SearchRequest.scope = LDAP_SEARCH_SCOPE_BASE;
172 msg->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER;
173 msg->r.SearchRequest.timelimit = 0;
174 msg->r.SearchRequest.sizelimit = 0;
175 msg->r.SearchRequest.attributesonly = false;
176 msg->r.SearchRequest.tree = ldb_parse_tree(msg, "(objectclass=*)");
177 msg->r.SearchRequest.tree->operation = LDB_OP_SUBSTRING;
178 msg->r.SearchRequest.tree->u.substring.attr = "objectclass";
179 msg->r.SearchRequest.tree->u.substring.start_with_wildcard = 1;
180 msg->r.SearchRequest.tree->u.substring.end_with_wildcard = 1;
181 msg->r.SearchRequest.tree->u.substring.chunks = NULL;
182 msg->r.SearchRequest.num_attributes = 0;
183 msg->r.SearchRequest.attributes = NULL;
185 req = ldap_request_send(conn, msg);
186 if (req == NULL) {
187 printf("Could not setup ldap search\n");
188 return false;
191 status = ldap_result_one(req, &result, LDAP_TAG_SearchResultEntry);
192 if (!NT_STATUS_IS_OK(status)) {
193 printf("looking for search result reply failed - %s\n", nt_errstr(status));
194 return false;
197 printf("received %d replies\n", req->num_replies);
199 return ret;
202 static bool test_search_auth_empty_substring(struct ldap_connection *conn, const char *basedn)
204 bool ret = true;
205 struct ldap_message *msg, *result;
206 struct ldap_request *req;
207 NTSTATUS status;
208 struct ldap_Result *r;
210 printf("Testing authenticated base Search with objectclass= substring filter\n");
212 msg = new_ldap_message(conn);
213 if (!msg) {
214 return false;
217 msg->type = LDAP_TAG_SearchRequest;
218 msg->r.SearchRequest.basedn = basedn;
219 msg->r.SearchRequest.scope = LDAP_SEARCH_SCOPE_BASE;
220 msg->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER;
221 msg->r.SearchRequest.timelimit = 0;
222 msg->r.SearchRequest.sizelimit = 0;
223 msg->r.SearchRequest.attributesonly = false;
224 msg->r.SearchRequest.tree = ldb_parse_tree(msg, "(objectclass=*)");
225 msg->r.SearchRequest.tree->operation = LDB_OP_SUBSTRING;
226 msg->r.SearchRequest.tree->u.substring.attr = "objectclass";
227 msg->r.SearchRequest.tree->u.substring.start_with_wildcard = 1;
228 msg->r.SearchRequest.tree->u.substring.end_with_wildcard = 1;
229 msg->r.SearchRequest.tree->u.substring.chunks = NULL;
230 msg->r.SearchRequest.num_attributes = 0;
231 msg->r.SearchRequest.attributes = NULL;
233 req = ldap_request_send(conn, msg);
234 if (req == NULL) {
235 printf("Could not setup ldap search\n");
236 return false;
239 status = ldap_result_one(req, &result, LDAP_TAG_SearchResultDone);
240 if (!NT_STATUS_IS_OK(status)) {
241 printf("looking for search result done failed - %s\n", nt_errstr(status));
242 return false;
245 printf("received %d replies\n", req->num_replies);
247 r = &result->r.SearchResultDone;
249 if (r->resultcode != LDAP_SUCCESS) {
250 printf("search result done gave error - %s\n", ldb_strerror(r->resultcode));
251 return false;
254 return ret;
257 static bool test_compare_sasl(struct ldap_connection *conn, const char *basedn)
259 struct ldap_message *msg, *rep;
260 struct ldap_request *req;
261 const char *val;
262 NTSTATUS status;
264 printf("Testing SASL Compare: %s\n", basedn);
266 if (!basedn) {
267 return false;
270 msg = new_ldap_message(conn);
271 if (!msg) {
272 return false;
275 msg->type = LDAP_TAG_CompareRequest;
276 msg->r.CompareRequest.dn = basedn;
277 msg->r.CompareRequest.attribute = talloc_strdup(msg, "objectClass");
278 val = "domain";
279 msg->r.CompareRequest.value = data_blob_talloc(msg, val, strlen(val));
281 req = ldap_request_send(conn, msg);
282 if (!req) {
283 return false;
286 status = ldap_result_one(req, &rep, LDAP_TAG_CompareResponse);
287 if (!NT_STATUS_IS_OK(status)) {
288 printf("error in ldap compare request - %s\n", nt_errstr(status));
289 return false;
292 DEBUG(5,("Code: %d DN: [%s] ERROR:[%s] REFERRAL:[%s]\n",
293 rep->r.CompareResponse.resultcode,
294 rep->r.CompareResponse.dn,
295 rep->r.CompareResponse.errormessage,
296 rep->r.CompareResponse.referral));
298 return true;
302 * This takes an AD error message and splits it into the WERROR code
303 * (WERR_DS_GENERIC if none found) and the reason (remaining string).
305 static WERROR ad_error(const char *err_msg, char **reason)
307 WERROR err = W_ERROR(strtol(err_msg, reason, 16));
309 if ((reason != NULL) && (*reason[0] != ':')) {
310 return WERR_DS_GENERIC_ERROR; /* not an AD std error message */
313 if (reason != NULL) {
314 *reason += 2; /* skip ": " */
316 return err;
319 /* This has to be done using the LDAP API since the LDB API does only transmit
320 * the error code and not the error message. */
321 static bool test_error_codes(struct torture_context *tctx,
322 struct ldap_connection *conn, const char *basedn)
324 struct ldap_message *msg, *rep;
325 struct ldap_request *req;
326 const char *err_code_str;
327 char *endptr;
328 WERROR err;
329 NTSTATUS status;
331 printf("Testing the most important error code -> error message conversions!\n");
333 if (!basedn) {
334 return false;
337 msg = new_ldap_message(conn);
338 if (!msg) {
339 return false;
342 printf(" Try a wrong addition\n");
344 msg->type = LDAP_TAG_AddRequest;
345 msg->r.AddRequest.dn = basedn;
346 msg->r.AddRequest.num_attributes = 0;
347 msg->r.AddRequest.attributes = NULL;
349 req = ldap_request_send(conn, msg);
350 if (!req) {
351 return false;
354 status = ldap_result_one(req, &rep, LDAP_TAG_AddResponse);
355 if (!NT_STATUS_IS_OK(status)) {
356 printf("error in ldap add request - %s\n", nt_errstr(status));
357 return false;
360 if ((rep->r.AddResponse.resultcode == 0)
361 || (rep->r.AddResponse.errormessage == NULL)
362 || (strtol(rep->r.AddResponse.errormessage, &endptr,16) <= 0)
363 || (*endptr != ':')) {
364 printf("Invalid error message!\n");
365 return false;
368 err = ad_error(rep->r.AddResponse.errormessage, &endptr);
369 err_code_str = win_errstr(err);
370 printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
371 if ((!W_ERROR_EQUAL(err, WERR_DS_REFERRAL))
372 || (rep->r.AddResponse.resultcode != LDAP_REFERRAL)) {
373 return false;
375 if ((rep->r.AddResponse.referral == NULL)
376 || (strstr(rep->r.AddResponse.referral, basedn) == NULL)) {
377 return false;
380 printf(" Try another wrong addition\n");
382 msg->type = LDAP_TAG_AddRequest;
383 msg->r.AddRequest.dn = "";
384 msg->r.AddRequest.num_attributes = 0;
385 msg->r.AddRequest.attributes = NULL;
387 req = ldap_request_send(conn, msg);
388 if (!req) {
389 return false;
392 status = ldap_result_one(req, &rep, LDAP_TAG_AddResponse);
393 if (!NT_STATUS_IS_OK(status)) {
394 printf("error in ldap add request - %s\n", nt_errstr(status));
395 return false;
398 if ((rep->r.AddResponse.resultcode == 0)
399 || (rep->r.AddResponse.errormessage == NULL)
400 || (strtol(rep->r.AddResponse.errormessage, &endptr,16) <= 0)
401 || (*endptr != ':')) {
402 printf("Invalid error message!\n");
403 return false;
406 err = ad_error(rep->r.AddResponse.errormessage, &endptr);
407 err_code_str = win_errstr(err);
408 printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
409 if ((!W_ERROR_EQUAL(err, WERR_DS_ROOT_MUST_BE_NC) &&
410 !W_ERROR_EQUAL(err, WERR_DS_NAMING_VIOLATION))
411 || (rep->r.AddResponse.resultcode != LDAP_NAMING_VIOLATION)) {
412 return false;
415 printf(" Try a wrong modification\n");
417 msg->type = LDAP_TAG_ModifyRequest;
418 msg->r.ModifyRequest.dn = basedn;
419 msg->r.ModifyRequest.num_mods = 0;
420 msg->r.ModifyRequest.mods = NULL;
422 req = ldap_request_send(conn, msg);
423 if (!req) {
424 return false;
427 status = ldap_result_one(req, &rep, LDAP_TAG_ModifyResponse);
428 if (!NT_STATUS_IS_OK(status)) {
429 printf("error in ldap modifification request - %s\n", nt_errstr(status));
430 return false;
433 if ((rep->r.ModifyResponse.resultcode == 0)
434 || (rep->r.ModifyResponse.errormessage == NULL)
435 || (strtol(rep->r.ModifyResponse.errormessage, &endptr,16) <= 0)
436 || (*endptr != ':')) {
437 printf("Invalid error message!\n");
438 return false;
441 err = ad_error(rep->r.ModifyResponse.errormessage, &endptr);
442 err_code_str = win_errstr(err);
443 printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
444 if ((!W_ERROR_EQUAL(err, WERR_INVALID_PARAMETER) &&
445 !W_ERROR_EQUAL(err, WERR_DS_UNWILLING_TO_PERFORM))
446 || (rep->r.ModifyResponse.resultcode != LDAP_UNWILLING_TO_PERFORM)) {
447 return false;
450 printf(" Try another wrong modification\n");
452 msg->type = LDAP_TAG_ModifyRequest;
453 msg->r.ModifyRequest.dn = "";
454 msg->r.ModifyRequest.num_mods = 0;
455 msg->r.ModifyRequest.mods = NULL;
457 req = ldap_request_send(conn, msg);
458 if (!req) {
459 return false;
462 status = ldap_result_one(req, &rep, LDAP_TAG_ModifyResponse);
463 if (!NT_STATUS_IS_OK(status)) {
464 printf("error in ldap modifification request - %s\n", nt_errstr(status));
465 return false;
468 if ((rep->r.ModifyResponse.resultcode == 0)
469 || (rep->r.ModifyResponse.errormessage == NULL)
470 || (strtol(rep->r.ModifyResponse.errormessage, &endptr,16) <= 0)
471 || (*endptr != ':')) {
472 printf("Invalid error message!\n");
473 return false;
476 err = ad_error(rep->r.ModifyResponse.errormessage, &endptr);
477 err_code_str = win_errstr(err);
478 printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
479 if ((!W_ERROR_EQUAL(err, WERR_INVALID_PARAMETER) &&
480 !W_ERROR_EQUAL(err, WERR_DS_UNWILLING_TO_PERFORM))
481 || (rep->r.ModifyResponse.resultcode != LDAP_UNWILLING_TO_PERFORM)) {
482 return false;
485 printf(" Try a wrong removal\n");
487 msg->type = LDAP_TAG_DelRequest;
488 msg->r.DelRequest.dn = basedn;
490 req = ldap_request_send(conn, msg);
491 if (!req) {
492 return false;
495 status = ldap_result_one(req, &rep, LDAP_TAG_DelResponse);
496 if (!NT_STATUS_IS_OK(status)) {
497 printf("error in ldap removal request - %s\n", nt_errstr(status));
498 return false;
501 if ((rep->r.DelResponse.resultcode == 0)
502 || (rep->r.DelResponse.errormessage == NULL)
503 || (strtol(rep->r.DelResponse.errormessage, &endptr,16) <= 0)
504 || (*endptr != ':')) {
505 printf("Invalid error message!\n");
506 return false;
509 err = ad_error(rep->r.DelResponse.errormessage, &endptr);
510 err_code_str = win_errstr(err);
511 printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
512 if ((!W_ERROR_EQUAL(err, WERR_DS_CANT_DELETE) &&
513 !W_ERROR_EQUAL(err, WERR_DS_UNWILLING_TO_PERFORM))
514 || (rep->r.DelResponse.resultcode != LDAP_UNWILLING_TO_PERFORM)) {
515 return false;
518 printf(" Try another wrong removal\n");
520 msg->type = LDAP_TAG_DelRequest;
521 msg->r.DelRequest.dn = "";
523 req = ldap_request_send(conn, msg);
524 if (!req) {
525 return false;
528 status = ldap_result_one(req, &rep, LDAP_TAG_DelResponse);
529 if (!NT_STATUS_IS_OK(status)) {
530 printf("error in ldap removal request - %s\n", nt_errstr(status));
531 return false;
534 if ((rep->r.DelResponse.resultcode == 0)
535 || (rep->r.DelResponse.errormessage == NULL)
536 || (strtol(rep->r.DelResponse.errormessage, &endptr,16) <= 0)
537 || (*endptr != ':')) {
538 printf("Invalid error message!\n");
539 return false;
542 err = ad_error(rep->r.DelResponse.errormessage, &endptr);
543 err_code_str = win_errstr(err);
544 printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
545 if ((!W_ERROR_EQUAL(err, WERR_DS_OBJ_NOT_FOUND) &&
546 !W_ERROR_EQUAL(err, WERR_DS_NO_SUCH_OBJECT))
547 || (rep->r.DelResponse.resultcode != LDAP_NO_SUCH_OBJECT)) {
548 return false;
551 printf(" Try a wrong rename\n");
553 msg->type = LDAP_TAG_ModifyDNRequest;
554 msg->r.ModifyDNRequest.dn = basedn;
555 msg->r.ModifyDNRequest.newrdn = "dc=test";
556 msg->r.ModifyDNRequest.deleteolddn = true;
557 msg->r.ModifyDNRequest.newsuperior = NULL;
559 req = ldap_request_send(conn, msg);
560 if (!req) {
561 return false;
564 status = ldap_result_one(req, &rep, LDAP_TAG_ModifyDNResponse);
565 if (!NT_STATUS_IS_OK(status)) {
566 printf("error in ldap rename request - %s\n", nt_errstr(status));
567 return false;
570 if ((rep->r.ModifyDNResponse.resultcode == 0)
571 || (rep->r.ModifyDNResponse.errormessage == NULL)
572 || (strtol(rep->r.ModifyDNResponse.errormessage, &endptr,16) <= 0)
573 || (*endptr != ':')) {
574 printf("Invalid error message!\n");
575 return false;
578 err = ad_error(rep->r.ModifyDNResponse.errormessage, &endptr);
579 err_code_str = win_errstr(err);
580 printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
581 if ((!W_ERROR_EQUAL(err, WERR_DS_NO_PARENT_OBJECT) &&
582 !W_ERROR_EQUAL(err, WERR_DS_GENERIC_ERROR))
583 || (rep->r.ModifyDNResponse.resultcode != LDAP_OTHER)) {
584 return false;
587 printf(" Try another wrong rename\n");
589 msg->type = LDAP_TAG_ModifyDNRequest;
590 msg->r.ModifyDNRequest.dn = basedn;
591 msg->r.ModifyDNRequest.newrdn = basedn;
592 msg->r.ModifyDNRequest.deleteolddn = true;
593 msg->r.ModifyDNRequest.newsuperior = NULL;
595 req = ldap_request_send(conn, msg);
596 if (!req) {
597 return false;
600 status = ldap_result_one(req, &rep, LDAP_TAG_ModifyDNResponse);
601 if (!NT_STATUS_IS_OK(status)) {
602 printf("error in ldap rename request - %s\n", nt_errstr(status));
603 return false;
606 if ((rep->r.ModifyDNResponse.resultcode == 0)
607 || (rep->r.ModifyDNResponse.errormessage == NULL)
608 || (strtol(rep->r.ModifyDNResponse.errormessage, &endptr,16) <= 0)
609 || (*endptr != ':')) {
610 printf("Invalid error message!\n");
611 return false;
614 err = ad_error(rep->r.ModifyDNResponse.errormessage, &endptr);
615 err_code_str = win_errstr(err);
616 printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
617 if ((!W_ERROR_EQUAL(err, WERR_INVALID_PARAMETER) &&
618 !W_ERROR_EQUAL(err, WERR_DS_NAMING_VIOLATION))
619 || (rep->r.ModifyDNResponse.resultcode != LDAP_NAMING_VIOLATION)) {
620 return false;
623 printf(" Try another wrong rename\n");
625 msg->type = LDAP_TAG_ModifyDNRequest;
626 msg->r.ModifyDNRequest.dn = basedn;
627 msg->r.ModifyDNRequest.newrdn = "";
628 msg->r.ModifyDNRequest.deleteolddn = true;
629 msg->r.ModifyDNRequest.newsuperior = NULL;
631 req = ldap_request_send(conn, msg);
632 if (!req) {
633 return false;
636 status = ldap_result_one(req, &rep, LDAP_TAG_ModifyDNResponse);
637 if (!NT_STATUS_IS_OK(status)) {
638 printf("error in ldap rename request - %s\n", nt_errstr(status));
639 return false;
642 if ((rep->r.ModifyDNResponse.resultcode == 0)
643 || (rep->r.ModifyDNResponse.errormessage == NULL)
644 || (strtol(rep->r.ModifyDNResponse.errormessage, &endptr,16) <= 0)
645 || (*endptr != ':')) {
646 printf("Invalid error message!\n");
647 return false;
650 err = ad_error(rep->r.ModifyDNResponse.errormessage, &endptr);
651 err_code_str = win_errstr(err);
652 printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
653 if ((!W_ERROR_EQUAL(err, WERR_INVALID_PARAMETER) &&
654 !W_ERROR_EQUAL(err, WERR_DS_PROTOCOL_ERROR))
655 || (rep->r.ModifyDNResponse.resultcode != LDAP_PROTOCOL_ERROR)) {
656 return false;
659 printf(" Try another wrong rename\n");
661 msg->type = LDAP_TAG_ModifyDNRequest;
662 msg->r.ModifyDNRequest.dn = "";
663 msg->r.ModifyDNRequest.newrdn = "cn=temp";
664 msg->r.ModifyDNRequest.deleteolddn = true;
665 msg->r.ModifyDNRequest.newsuperior = NULL;
667 req = ldap_request_send(conn, msg);
668 if (!req) {
669 return false;
672 status = ldap_result_one(req, &rep, LDAP_TAG_ModifyDNResponse);
673 if (!NT_STATUS_IS_OK(status)) {
674 printf("error in ldap rename request - %s\n", nt_errstr(status));
675 return false;
678 if ((rep->r.ModifyDNResponse.resultcode == 0)
679 || (rep->r.ModifyDNResponse.errormessage == NULL)
680 || (strtol(rep->r.ModifyDNResponse.errormessage, &endptr,16) <= 0)
681 || (*endptr != ':')) {
682 printf("Invalid error message!\n");
683 return false;
686 err = ad_error(rep->r.ModifyDNResponse.errormessage, &endptr);
687 err_code_str = win_errstr(err);
688 printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
689 if ((!W_ERROR_EQUAL(err, WERR_DS_OBJ_NOT_FOUND) &&
690 !W_ERROR_EQUAL(err, WERR_DS_NO_SUCH_OBJECT))
691 || (rep->r.ModifyDNResponse.resultcode != LDAP_NO_SUCH_OBJECT)) {
692 return false;
695 return true;
698 static bool test_referrals(struct torture_context *tctx, TALLOC_CTX *mem_ctx,
699 const char *url, const char *basedn, const char **partitions)
701 struct ldb_context *ldb;
702 struct ldb_result *res;
703 const char * const *attrs = { NULL };
704 struct ldb_dn *dn1, *dn2;
705 int ret;
706 int i, j, k;
707 char *tempstr;
708 bool found, l_found;
710 printf("Testing referrals\n");
712 if (partitions[0] == NULL) {
713 printf("Partitions list empty!\n");
714 return false;
717 if (strcmp(partitions[0], basedn) != 0) {
718 printf("The first (root) partition DN should be the base DN!\n");
719 return false;
722 ldb = ldb_wrap_connect(mem_ctx, tctx->ev, tctx->lp_ctx, url,
723 NULL, popt_get_cmdline_credentials(), 0);
725 /* "partitions[i]" are the partitions for which we search the parents */
726 for (i = 1; partitions[i] != NULL; i++) {
727 dn1 = ldb_dn_new(mem_ctx, ldb, partitions[i]);
728 if (dn1 == NULL) {
729 printf("Out of memory\n");
730 talloc_free(ldb);
731 return false;
734 /* search using base scope */
735 /* "partitions[j]" are the parent candidates */
736 for (j = str_list_length(partitions) - 1; j >= 0; --j) {
737 dn2 = ldb_dn_new(mem_ctx, ldb, partitions[j]);
738 if (dn2 == NULL) {
739 printf("Out of memory\n");
740 talloc_free(ldb);
741 return false;
744 ret = ldb_search(ldb, mem_ctx, &res, dn2,
745 LDB_SCOPE_BASE, attrs,
746 "(foo=bar)");
747 if (ret != LDB_SUCCESS) {
748 printf("%s", ldb_errstring(ldb));
749 talloc_free(ldb);
750 return false;
753 if (res->refs != NULL) {
754 printf("There shouldn't be generated any referrals in the base scope!\n");
755 talloc_free(ldb);
756 return false;
759 talloc_free(res);
760 talloc_free(dn2);
763 /* search using onelevel scope */
764 found = false;
765 /* "partitions[j]" are the parent candidates */
766 for (j = str_list_length(partitions) - 1; j >= 0; --j) {
767 dn2 = ldb_dn_new(mem_ctx, ldb, partitions[j]);
768 if (dn2 == NULL) {
769 printf("Out of memory\n");
770 talloc_free(ldb);
771 return false;
774 ret = ldb_search(ldb, mem_ctx, &res, dn2,
775 LDB_SCOPE_ONELEVEL, attrs,
776 "(foo=bar)");
777 if (ret != LDB_SUCCESS) {
778 printf("%s", ldb_errstring(ldb));
779 talloc_free(ldb);
780 return false;
783 tempstr = talloc_asprintf(mem_ctx, "/%s??base",
784 partitions[i]);
785 if (tempstr == NULL) {
786 printf("Out of memory\n");
787 talloc_free(ldb);
788 return false;
791 /* Try to find or find not a matching referral */
792 l_found = false;
793 for (k = 0; (!l_found) && (res->refs != NULL)
794 && (res->refs[k] != NULL); k++) {
795 if (strstr(res->refs[k], tempstr) != NULL) {
796 l_found = true;
800 talloc_free(tempstr);
802 if ((!found) && (ldb_dn_compare_base(dn2, dn1) == 0)
803 && (ldb_dn_compare(dn2, dn1) != 0)) {
804 /* This is a referral candidate */
805 if (!l_found) {
806 printf("A required referral hasn't been found on onelevel scope (%s -> %s)!\n", partitions[j], partitions[i]);
807 talloc_free(ldb);
808 return false;
810 found = true;
811 } else {
812 /* This isn't a referral candidate */
813 if (l_found) {
814 printf("A unrequired referral has been found on onelevel scope (%s -> %s)!\n", partitions[j], partitions[i]);
815 talloc_free(ldb);
816 return false;
820 talloc_free(res);
821 talloc_free(dn2);
824 /* search using subtree scope */
825 found = false;
826 /* "partitions[j]" are the parent candidates */
827 for (j = str_list_length(partitions) - 1; j >= 0; --j) {
828 dn2 = ldb_dn_new(mem_ctx, ldb, partitions[j]);
829 if (dn2 == NULL) {
830 printf("Out of memory\n");
831 talloc_free(ldb);
832 return false;
835 ret = ldb_search(ldb, mem_ctx, &res, dn2,
836 LDB_SCOPE_SUBTREE, attrs,
837 "(foo=bar)");
838 if (ret != LDB_SUCCESS) {
839 printf("%s", ldb_errstring(ldb));
840 talloc_free(ldb);
841 return false;
844 tempstr = talloc_asprintf(mem_ctx, "/%s",
845 partitions[i]);
846 if (tempstr == NULL) {
847 printf("Out of memory\n");
848 talloc_free(ldb);
849 return false;
852 /* Try to find or find not a matching referral */
853 l_found = false;
854 for (k = 0; (!l_found) && (res->refs != NULL)
855 && (res->refs[k] != NULL); k++) {
856 if (strstr(res->refs[k], tempstr) != NULL) {
857 l_found = true;
861 talloc_free(tempstr);
863 if ((!found) && (ldb_dn_compare_base(dn2, dn1) == 0)
864 && (ldb_dn_compare(dn2, dn1) != 0)) {
865 /* This is a referral candidate */
866 if (!l_found) {
867 printf("A required referral hasn't been found on subtree scope (%s -> %s)!\n", partitions[j], partitions[i]);
868 talloc_free(ldb);
869 return false;
871 found = true;
872 } else {
873 /* This isn't a referral candidate */
874 if (l_found) {
875 printf("A unrequired referral has been found on subtree scope (%s -> %s)!\n", partitions[j], partitions[i]);
876 talloc_free(ldb);
877 return false;
881 talloc_free(res);
882 talloc_free(dn2);
885 talloc_free(dn1);
888 talloc_free(ldb);
890 return true;
893 static bool test_abandon_request(struct torture_context *tctx,
894 struct ldap_connection *conn, const char *basedn)
896 struct ldap_message *msg;
897 struct ldap_request *req;
898 NTSTATUS status;
900 printf("Testing the AbandonRequest with an old message id!\n");
902 if (!basedn) {
903 return false;
906 msg = new_ldap_message(conn);
907 if (!msg) {
908 return false;
911 printf(" Try a AbandonRequest for an old message id\n");
913 msg->type = LDAP_TAG_AbandonRequest;
914 msg->r.AbandonRequest.messageid = 1;
916 req = ldap_request_send(conn, msg);
917 if (!req) {
918 return false;
921 status = ldap_request_wait(req);
922 if (!NT_STATUS_IS_OK(status)) {
923 printf("error in ldap abandon request - %s\n", nt_errstr(status));
924 return false;
927 return true;
931 bool torture_ldap_basic(struct torture_context *torture)
933 NTSTATUS status;
934 struct ldap_connection *conn;
935 TALLOC_CTX *mem_ctx;
936 bool ret = true;
937 const char *host = torture_setting_string(torture, "host", NULL);
938 const char *userdn = torture_setting_string(torture, "ldap_userdn", NULL);
939 const char *secret = torture_setting_string(torture, "ldap_secret", NULL);
940 const char *url;
941 const char *basedn;
942 const char **partitions;
944 mem_ctx = talloc_init("torture_ldap_basic");
946 url = talloc_asprintf(mem_ctx, "ldap://%s/", host);
948 status = torture_ldap_connection(torture, &conn, url);
949 if (!NT_STATUS_IS_OK(status)) {
950 return false;
953 if (!test_search_rootDSE(conn, &basedn, &partitions)) {
954 ret = false;
957 if (!test_search_rootDSE_empty_substring(conn)) {
958 ret = false;
961 /* other bind tests here */
963 if (!test_multibind(conn, userdn, secret)) {
964 ret = false;
967 if (!test_bind_sasl(torture, conn, popt_get_cmdline_credentials())) {
968 ret = false;
971 if (!test_search_auth_empty_substring(conn, basedn)) {
972 ret = false;
975 if (!test_compare_sasl(conn, basedn)) {
976 ret = false;
979 /* error codes test here */
981 if (!test_error_codes(torture, conn, basedn)) {
982 ret = false;
985 /* referrals test here */
987 if (!test_referrals(torture, mem_ctx, url, basedn, partitions)) {
988 ret = false;
991 if (!test_abandon_request(torture, conn, basedn)) {
992 ret = false;
995 /* if there are no more tests we are closing */
996 torture_ldap_close(conn);
997 talloc_free(mem_ctx);
999 torture_assert(torture, ret, "torture_ldap_basic failed");
1001 return ret;