smbd: Fix an ancient oplock bug
[Samba.git] / source4 / torture / ldap / basic.c
blob8d964ac80efe2a9194a371f972f4534bcda525ef
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 connection 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_search_rootDSE_empty_substring(struct ldap_connection *conn)
161 bool ret = true;
162 struct ldap_message *msg, *result;
163 struct ldap_request *req;
164 NTSTATUS status;
166 printf("Testing RootDSE Search with objectclass= substring filter\n");
168 msg = new_ldap_message(conn);
169 if (!msg) {
170 return false;
173 msg->type = LDAP_TAG_SearchRequest;
174 msg->r.SearchRequest.basedn = "";
175 msg->r.SearchRequest.scope = LDAP_SEARCH_SCOPE_BASE;
176 msg->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER;
177 msg->r.SearchRequest.timelimit = 0;
178 msg->r.SearchRequest.sizelimit = 0;
179 msg->r.SearchRequest.attributesonly = false;
180 msg->r.SearchRequest.tree = ldb_parse_tree(msg, "(objectclass=*)");
181 msg->r.SearchRequest.tree->operation = LDB_OP_SUBSTRING;
182 msg->r.SearchRequest.tree->u.substring.attr = "objectclass";
183 msg->r.SearchRequest.tree->u.substring.start_with_wildcard = 1;
184 msg->r.SearchRequest.tree->u.substring.end_with_wildcard = 1;
185 msg->r.SearchRequest.tree->u.substring.chunks = NULL;
186 msg->r.SearchRequest.num_attributes = 0;
187 msg->r.SearchRequest.attributes = NULL;
189 req = ldap_request_send(conn, msg);
190 if (req == NULL) {
191 printf("Could not setup ldap search\n");
192 return false;
195 status = ldap_result_one(req, &result, LDAP_TAG_SearchResultEntry);
196 if (!NT_STATUS_IS_OK(status)) {
197 printf("looking for search result reply failed - %s\n", nt_errstr(status));
198 return false;
201 printf("received %d replies\n", req->num_replies);
203 return ret;
206 static bool test_search_auth_empty_substring(struct ldap_connection *conn, const char *basedn)
208 bool ret = true;
209 struct ldap_message *msg, *result;
210 struct ldap_request *req;
211 NTSTATUS status;
212 struct ldap_Result *r;
214 printf("Testing authenticated base Search with objectclass= substring filter\n");
216 msg = new_ldap_message(conn);
217 if (!msg) {
218 return false;
221 msg->type = LDAP_TAG_SearchRequest;
222 msg->r.SearchRequest.basedn = basedn;
223 msg->r.SearchRequest.scope = LDAP_SEARCH_SCOPE_BASE;
224 msg->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER;
225 msg->r.SearchRequest.timelimit = 0;
226 msg->r.SearchRequest.sizelimit = 0;
227 msg->r.SearchRequest.attributesonly = false;
228 msg->r.SearchRequest.tree = ldb_parse_tree(msg, "(objectclass=*)");
229 msg->r.SearchRequest.tree->operation = LDB_OP_SUBSTRING;
230 msg->r.SearchRequest.tree->u.substring.attr = "objectclass";
231 msg->r.SearchRequest.tree->u.substring.start_with_wildcard = 1;
232 msg->r.SearchRequest.tree->u.substring.end_with_wildcard = 1;
233 msg->r.SearchRequest.tree->u.substring.chunks = NULL;
234 msg->r.SearchRequest.num_attributes = 0;
235 msg->r.SearchRequest.attributes = NULL;
237 req = ldap_request_send(conn, msg);
238 if (req == NULL) {
239 printf("Could not setup ldap search\n");
240 return false;
243 status = ldap_result_one(req, &result, LDAP_TAG_SearchResultDone);
244 if (!NT_STATUS_IS_OK(status)) {
245 printf("looking for search result done failed - %s\n", nt_errstr(status));
246 return false;
249 printf("received %d replies\n", req->num_replies);
251 r = &result->r.SearchResultDone;
253 if (r->resultcode != LDAP_SUCCESS) {
254 printf("search result done gave error - %s\n", ldb_strerror(r->resultcode));
255 return false;
258 return ret;
261 static bool test_compare_sasl(struct ldap_connection *conn, const char *basedn)
263 struct ldap_message *msg, *rep;
264 struct ldap_request *req;
265 const char *val;
266 NTSTATUS status;
268 printf("Testing SASL Compare: %s\n", basedn);
270 if (!basedn) {
271 return false;
274 msg = new_ldap_message(conn);
275 if (!msg) {
276 return false;
279 msg->type = LDAP_TAG_CompareRequest;
280 msg->r.CompareRequest.dn = basedn;
281 msg->r.CompareRequest.attribute = talloc_strdup(msg, "objectClass");
282 val = "domain";
283 msg->r.CompareRequest.value = data_blob_talloc(msg, val, strlen(val));
285 req = ldap_request_send(conn, msg);
286 if (!req) {
287 return false;
290 status = ldap_result_one(req, &rep, LDAP_TAG_CompareResponse);
291 if (!NT_STATUS_IS_OK(status)) {
292 printf("error in ldap compare request - %s\n", nt_errstr(status));
293 return false;
296 DEBUG(5,("Code: %d DN: [%s] ERROR:[%s] REFERRAL:[%s]\n",
297 rep->r.CompareResponse.resultcode,
298 rep->r.CompareResponse.dn,
299 rep->r.CompareResponse.errormessage,
300 rep->r.CompareResponse.referral));
302 return true;
306 * This takes an AD error message and splits it into the WERROR code
307 * (WERR_DS_GENERIC if none found) and the reason (remaining string).
309 static WERROR ad_error(const char *err_msg, char **reason)
311 WERROR err = W_ERROR(strtol(err_msg, reason, 16));
313 if ((reason != NULL) && (*reason[0] != ':')) {
314 return WERR_DS_GENERIC_ERROR; /* not an AD std error message */
317 if (reason != NULL) {
318 *reason += 2; /* skip ": " */
320 return err;
323 /* This has to be done using the LDAP API since the LDB API does only transmit
324 * the error code and not the error message. */
325 static bool test_error_codes(struct torture_context *tctx,
326 struct ldap_connection *conn, const char *basedn)
328 struct ldap_message *msg, *rep;
329 struct ldap_request *req;
330 const char *err_code_str;
331 char *endptr;
332 WERROR err;
333 NTSTATUS status;
335 printf("Testing the most important error code -> error message conversions!\n");
337 if (!basedn) {
338 return false;
341 msg = new_ldap_message(conn);
342 if (!msg) {
343 return false;
346 printf(" Try a wrong addition\n");
348 msg->type = LDAP_TAG_AddRequest;
349 msg->r.AddRequest.dn = basedn;
350 msg->r.AddRequest.num_attributes = 0;
351 msg->r.AddRequest.attributes = NULL;
353 req = ldap_request_send(conn, msg);
354 if (!req) {
355 return false;
358 status = ldap_result_one(req, &rep, LDAP_TAG_AddResponse);
359 if (!NT_STATUS_IS_OK(status)) {
360 printf("error in ldap add request - %s\n", nt_errstr(status));
361 return false;
364 if ((rep->r.AddResponse.resultcode == 0)
365 || (rep->r.AddResponse.errormessage == NULL)
366 || (strtol(rep->r.AddResponse.errormessage, &endptr,16) <= 0)
367 || (*endptr != ':')) {
368 printf("Invalid error message!\n");
369 return false;
372 err = ad_error(rep->r.AddResponse.errormessage, &endptr);
373 err_code_str = win_errstr(err);
374 printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
375 if ((!W_ERROR_EQUAL(err, WERR_DS_REFERRAL))
376 || (rep->r.AddResponse.resultcode != LDAP_REFERRAL)) {
377 return false;
379 if ((rep->r.AddResponse.referral == NULL)
380 || (strstr(rep->r.AddResponse.referral, basedn) == NULL)) {
381 return false;
384 printf(" Try another wrong addition\n");
386 msg->type = LDAP_TAG_AddRequest;
387 msg->r.AddRequest.dn = "";
388 msg->r.AddRequest.num_attributes = 0;
389 msg->r.AddRequest.attributes = NULL;
391 req = ldap_request_send(conn, msg);
392 if (!req) {
393 return false;
396 status = ldap_result_one(req, &rep, LDAP_TAG_AddResponse);
397 if (!NT_STATUS_IS_OK(status)) {
398 printf("error in ldap add request - %s\n", nt_errstr(status));
399 return false;
402 if ((rep->r.AddResponse.resultcode == 0)
403 || (rep->r.AddResponse.errormessage == NULL)
404 || (strtol(rep->r.AddResponse.errormessage, &endptr,16) <= 0)
405 || (*endptr != ':')) {
406 printf("Invalid error message!\n");
407 return false;
410 err = ad_error(rep->r.AddResponse.errormessage, &endptr);
411 err_code_str = win_errstr(err);
412 printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
413 if ((!W_ERROR_EQUAL(err, WERR_DS_ROOT_MUST_BE_NC) &&
414 !W_ERROR_EQUAL(err, WERR_DS_NAMING_VIOLATION))
415 || (rep->r.AddResponse.resultcode != LDAP_NAMING_VIOLATION)) {
416 return false;
419 printf(" Try a wrong modification\n");
421 msg->type = LDAP_TAG_ModifyRequest;
422 msg->r.ModifyRequest.dn = basedn;
423 msg->r.ModifyRequest.num_mods = 0;
424 msg->r.ModifyRequest.mods = NULL;
426 req = ldap_request_send(conn, msg);
427 if (!req) {
428 return false;
431 status = ldap_result_one(req, &rep, LDAP_TAG_ModifyResponse);
432 if (!NT_STATUS_IS_OK(status)) {
433 printf("error in ldap modifification request - %s\n", nt_errstr(status));
434 return false;
437 if ((rep->r.ModifyResponse.resultcode == 0)
438 || (rep->r.ModifyResponse.errormessage == NULL)
439 || (strtol(rep->r.ModifyResponse.errormessage, &endptr,16) <= 0)
440 || (*endptr != ':')) {
441 printf("Invalid error message!\n");
442 return false;
445 err = ad_error(rep->r.ModifyResponse.errormessage, &endptr);
446 err_code_str = win_errstr(err);
447 printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
448 if ((!W_ERROR_EQUAL(err, WERR_INVALID_PARAM) &&
449 !W_ERROR_EQUAL(err, WERR_DS_UNWILLING_TO_PERFORM))
450 || (rep->r.ModifyResponse.resultcode != LDAP_UNWILLING_TO_PERFORM)) {
451 return false;
454 printf(" Try another wrong modification\n");
456 msg->type = LDAP_TAG_ModifyRequest;
457 msg->r.ModifyRequest.dn = "";
458 msg->r.ModifyRequest.num_mods = 0;
459 msg->r.ModifyRequest.mods = NULL;
461 req = ldap_request_send(conn, msg);
462 if (!req) {
463 return false;
466 status = ldap_result_one(req, &rep, LDAP_TAG_ModifyResponse);
467 if (!NT_STATUS_IS_OK(status)) {
468 printf("error in ldap modifification request - %s\n", nt_errstr(status));
469 return false;
472 if ((rep->r.ModifyResponse.resultcode == 0)
473 || (rep->r.ModifyResponse.errormessage == NULL)
474 || (strtol(rep->r.ModifyResponse.errormessage, &endptr,16) <= 0)
475 || (*endptr != ':')) {
476 printf("Invalid error message!\n");
477 return false;
480 err = ad_error(rep->r.ModifyResponse.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_INVALID_PARAM) &&
484 !W_ERROR_EQUAL(err, WERR_DS_UNWILLING_TO_PERFORM))
485 || (rep->r.ModifyResponse.resultcode != LDAP_UNWILLING_TO_PERFORM)) {
486 return false;
489 printf(" Try a wrong removal\n");
491 msg->type = LDAP_TAG_DelRequest;
492 msg->r.DelRequest.dn = basedn;
494 req = ldap_request_send(conn, msg);
495 if (!req) {
496 return false;
499 status = ldap_result_one(req, &rep, LDAP_TAG_DelResponse);
500 if (!NT_STATUS_IS_OK(status)) {
501 printf("error in ldap removal request - %s\n", nt_errstr(status));
502 return false;
505 if ((rep->r.DelResponse.resultcode == 0)
506 || (rep->r.DelResponse.errormessage == NULL)
507 || (strtol(rep->r.DelResponse.errormessage, &endptr,16) <= 0)
508 || (*endptr != ':')) {
509 printf("Invalid error message!\n");
510 return false;
513 err = ad_error(rep->r.DelResponse.errormessage, &endptr);
514 err_code_str = win_errstr(err);
515 printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
516 if ((!W_ERROR_EQUAL(err, WERR_DS_CANT_DELETE) &&
517 !W_ERROR_EQUAL(err, WERR_DS_UNWILLING_TO_PERFORM))
518 || (rep->r.DelResponse.resultcode != LDAP_UNWILLING_TO_PERFORM)) {
519 return false;
522 printf(" Try another wrong removal\n");
524 msg->type = LDAP_TAG_DelRequest;
525 msg->r.DelRequest.dn = "";
527 req = ldap_request_send(conn, msg);
528 if (!req) {
529 return false;
532 status = ldap_result_one(req, &rep, LDAP_TAG_DelResponse);
533 if (!NT_STATUS_IS_OK(status)) {
534 printf("error in ldap removal request - %s\n", nt_errstr(status));
535 return false;
538 if ((rep->r.DelResponse.resultcode == 0)
539 || (rep->r.DelResponse.errormessage == NULL)
540 || (strtol(rep->r.DelResponse.errormessage, &endptr,16) <= 0)
541 || (*endptr != ':')) {
542 printf("Invalid error message!\n");
543 return false;
546 err = ad_error(rep->r.DelResponse.errormessage, &endptr);
547 err_code_str = win_errstr(err);
548 printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
549 if ((!W_ERROR_EQUAL(err, WERR_DS_OBJ_NOT_FOUND) &&
550 !W_ERROR_EQUAL(err, WERR_DS_NO_SUCH_OBJECT))
551 || (rep->r.DelResponse.resultcode != LDAP_NO_SUCH_OBJECT)) {
552 return false;
555 printf(" Try a wrong rename\n");
557 msg->type = LDAP_TAG_ModifyDNRequest;
558 msg->r.ModifyDNRequest.dn = basedn;
559 msg->r.ModifyDNRequest.newrdn = "dc=test";
560 msg->r.ModifyDNRequest.deleteolddn = true;
561 msg->r.ModifyDNRequest.newsuperior = NULL;
563 req = ldap_request_send(conn, msg);
564 if (!req) {
565 return false;
568 status = ldap_result_one(req, &rep, LDAP_TAG_ModifyDNResponse);
569 if (!NT_STATUS_IS_OK(status)) {
570 printf("error in ldap rename request - %s\n", nt_errstr(status));
571 return false;
574 if ((rep->r.ModifyDNResponse.resultcode == 0)
575 || (rep->r.ModifyDNResponse.errormessage == NULL)
576 || (strtol(rep->r.ModifyDNResponse.errormessage, &endptr,16) <= 0)
577 || (*endptr != ':')) {
578 printf("Invalid error message!\n");
579 return false;
582 err = ad_error(rep->r.ModifyDNResponse.errormessage, &endptr);
583 err_code_str = win_errstr(err);
584 printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
585 if ((!W_ERROR_EQUAL(err, WERR_DS_NO_PARENT_OBJECT) &&
586 !W_ERROR_EQUAL(err, WERR_DS_GENERIC_ERROR))
587 || (rep->r.ModifyDNResponse.resultcode != LDAP_OTHER)) {
588 return false;
591 printf(" Try another wrong rename\n");
593 msg->type = LDAP_TAG_ModifyDNRequest;
594 msg->r.ModifyDNRequest.dn = basedn;
595 msg->r.ModifyDNRequest.newrdn = basedn;
596 msg->r.ModifyDNRequest.deleteolddn = true;
597 msg->r.ModifyDNRequest.newsuperior = NULL;
599 req = ldap_request_send(conn, msg);
600 if (!req) {
601 return false;
604 status = ldap_result_one(req, &rep, LDAP_TAG_ModifyDNResponse);
605 if (!NT_STATUS_IS_OK(status)) {
606 printf("error in ldap rename request - %s\n", nt_errstr(status));
607 return false;
610 if ((rep->r.ModifyDNResponse.resultcode == 0)
611 || (rep->r.ModifyDNResponse.errormessage == NULL)
612 || (strtol(rep->r.ModifyDNResponse.errormessage, &endptr,16) <= 0)
613 || (*endptr != ':')) {
614 printf("Invalid error message!\n");
615 return false;
618 err = ad_error(rep->r.ModifyDNResponse.errormessage, &endptr);
619 err_code_str = win_errstr(err);
620 printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
621 if ((!W_ERROR_EQUAL(err, WERR_INVALID_PARAM) &&
622 !W_ERROR_EQUAL(err, WERR_DS_NAMING_VIOLATION))
623 || (rep->r.ModifyDNResponse.resultcode != LDAP_NAMING_VIOLATION)) {
624 return false;
627 printf(" Try another wrong rename\n");
629 msg->type = LDAP_TAG_ModifyDNRequest;
630 msg->r.ModifyDNRequest.dn = basedn;
631 msg->r.ModifyDNRequest.newrdn = "";
632 msg->r.ModifyDNRequest.deleteolddn = true;
633 msg->r.ModifyDNRequest.newsuperior = NULL;
635 req = ldap_request_send(conn, msg);
636 if (!req) {
637 return false;
640 status = ldap_result_one(req, &rep, LDAP_TAG_ModifyDNResponse);
641 if (!NT_STATUS_IS_OK(status)) {
642 printf("error in ldap rename request - %s\n", nt_errstr(status));
643 return false;
646 if ((rep->r.ModifyDNResponse.resultcode == 0)
647 || (rep->r.ModifyDNResponse.errormessage == NULL)
648 || (strtol(rep->r.ModifyDNResponse.errormessage, &endptr,16) <= 0)
649 || (*endptr != ':')) {
650 printf("Invalid error message!\n");
651 return false;
654 err = ad_error(rep->r.ModifyDNResponse.errormessage, &endptr);
655 err_code_str = win_errstr(err);
656 printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
657 if ((!W_ERROR_EQUAL(err, WERR_INVALID_PARAM) &&
658 !W_ERROR_EQUAL(err, WERR_DS_PROTOCOL_ERROR))
659 || (rep->r.ModifyDNResponse.resultcode != LDAP_PROTOCOL_ERROR)) {
660 return false;
663 printf(" Try another wrong rename\n");
665 msg->type = LDAP_TAG_ModifyDNRequest;
666 msg->r.ModifyDNRequest.dn = "";
667 msg->r.ModifyDNRequest.newrdn = "cn=temp";
668 msg->r.ModifyDNRequest.deleteolddn = true;
669 msg->r.ModifyDNRequest.newsuperior = NULL;
671 req = ldap_request_send(conn, msg);
672 if (!req) {
673 return false;
676 status = ldap_result_one(req, &rep, LDAP_TAG_ModifyDNResponse);
677 if (!NT_STATUS_IS_OK(status)) {
678 printf("error in ldap rename request - %s\n", nt_errstr(status));
679 return false;
682 if ((rep->r.ModifyDNResponse.resultcode == 0)
683 || (rep->r.ModifyDNResponse.errormessage == NULL)
684 || (strtol(rep->r.ModifyDNResponse.errormessage, &endptr,16) <= 0)
685 || (*endptr != ':')) {
686 printf("Invalid error message!\n");
687 return false;
690 err = ad_error(rep->r.ModifyDNResponse.errormessage, &endptr);
691 err_code_str = win_errstr(err);
692 printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
693 if ((!W_ERROR_EQUAL(err, WERR_DS_OBJ_NOT_FOUND) &&
694 !W_ERROR_EQUAL(err, WERR_DS_NO_SUCH_OBJECT))
695 || (rep->r.ModifyDNResponse.resultcode != LDAP_NO_SUCH_OBJECT)) {
696 return false;
699 return true;
702 static bool test_referrals(struct torture_context *tctx, TALLOC_CTX *mem_ctx,
703 const char *url, const char *basedn, const char **partitions)
705 struct ldb_context *ldb;
706 struct ldb_result *res;
707 const char * const *attrs = { NULL };
708 struct ldb_dn *dn1, *dn2;
709 int ret;
710 int i, j, k;
711 char *tempstr;
712 bool found, l_found;
714 printf("Testing referrals\n");
716 if (partitions[0] == NULL) {
717 printf("Partitions list empty!\n");
718 return false;
721 if (strcmp(partitions[0], basedn) != 0) {
722 printf("The first (root) partition DN should be the base DN!\n");
723 return false;
726 ldb = ldb_wrap_connect(mem_ctx, tctx->ev, tctx->lp_ctx, url,
727 NULL, cmdline_credentials, 0);
729 /* "partitions[i]" are the partitions for which we search the parents */
730 for (i = 1; partitions[i] != NULL; i++) {
731 dn1 = ldb_dn_new(mem_ctx, ldb, partitions[i]);
732 if (dn1 == NULL) {
733 printf("Out of memory\n");
734 talloc_free(ldb);
735 return false;
738 /* search using base scope */
739 /* "partitions[j]" are the parent candidates */
740 for (j = str_list_length(partitions) - 1; j >= 0; --j) {
741 dn2 = ldb_dn_new(mem_ctx, ldb, partitions[j]);
742 if (dn2 == NULL) {
743 printf("Out of memory\n");
744 talloc_free(ldb);
745 return false;
748 ret = ldb_search(ldb, mem_ctx, &res, dn2,
749 LDB_SCOPE_BASE, attrs,
750 "(foo=bar)");
751 if (ret != LDB_SUCCESS) {
752 printf("%s", ldb_errstring(ldb));
753 talloc_free(ldb);
754 return false;
757 if (res->refs != NULL) {
758 printf("There shouldn't be generated any referrals in the base scope!\n");
759 talloc_free(ldb);
760 return false;
763 talloc_free(res);
764 talloc_free(dn2);
767 /* search using onelevel scope */
768 found = false;
769 /* "partitions[j]" are the parent candidates */
770 for (j = str_list_length(partitions) - 1; j >= 0; --j) {
771 dn2 = ldb_dn_new(mem_ctx, ldb, partitions[j]);
772 if (dn2 == NULL) {
773 printf("Out of memory\n");
774 talloc_free(ldb);
775 return false;
778 ret = ldb_search(ldb, mem_ctx, &res, dn2,
779 LDB_SCOPE_ONELEVEL, attrs,
780 "(foo=bar)");
781 if (ret != LDB_SUCCESS) {
782 printf("%s", ldb_errstring(ldb));
783 talloc_free(ldb);
784 return false;
787 tempstr = talloc_asprintf(mem_ctx, "/%s??base",
788 partitions[i]);
789 if (tempstr == NULL) {
790 printf("Out of memory\n");
791 talloc_free(ldb);
792 return false;
795 /* Try to find or find not a matching referral */
796 l_found = false;
797 for (k = 0; (!l_found) && (res->refs != NULL)
798 && (res->refs[k] != NULL); k++) {
799 if (strstr(res->refs[k], tempstr) != NULL) {
800 l_found = true;
804 talloc_free(tempstr);
806 if ((!found) && (ldb_dn_compare_base(dn2, dn1) == 0)
807 && (ldb_dn_compare(dn2, dn1) != 0)) {
808 /* This is a referral candidate */
809 if (!l_found) {
810 printf("A required referral hasn't been found on onelevel scope (%s -> %s)!\n", partitions[j], partitions[i]);
811 talloc_free(ldb);
812 return false;
814 found = true;
815 } else {
816 /* This isn't a referral candidate */
817 if (l_found) {
818 printf("A unrequired referral has been found on onelevel scope (%s -> %s)!\n", partitions[j], partitions[i]);
819 talloc_free(ldb);
820 return false;
824 talloc_free(res);
825 talloc_free(dn2);
828 /* search using subtree scope */
829 found = false;
830 /* "partitions[j]" are the parent candidates */
831 for (j = str_list_length(partitions) - 1; j >= 0; --j) {
832 dn2 = ldb_dn_new(mem_ctx, ldb, partitions[j]);
833 if (dn2 == NULL) {
834 printf("Out of memory\n");
835 talloc_free(ldb);
836 return false;
839 ret = ldb_search(ldb, mem_ctx, &res, dn2,
840 LDB_SCOPE_SUBTREE, attrs,
841 "(foo=bar)");
842 if (ret != LDB_SUCCESS) {
843 printf("%s", ldb_errstring(ldb));
844 talloc_free(ldb);
845 return false;
848 tempstr = talloc_asprintf(mem_ctx, "/%s",
849 partitions[i]);
850 if (tempstr == NULL) {
851 printf("Out of memory\n");
852 talloc_free(ldb);
853 return false;
856 /* Try to find or find not a matching referral */
857 l_found = false;
858 for (k = 0; (!l_found) && (res->refs != NULL)
859 && (res->refs[k] != NULL); k++) {
860 if (strstr(res->refs[k], tempstr) != NULL) {
861 l_found = true;
865 talloc_free(tempstr);
867 if ((!found) && (ldb_dn_compare_base(dn2, dn1) == 0)
868 && (ldb_dn_compare(dn2, dn1) != 0)) {
869 /* This is a referral candidate */
870 if (!l_found) {
871 printf("A required referral hasn't been found on subtree scope (%s -> %s)!\n", partitions[j], partitions[i]);
872 talloc_free(ldb);
873 return false;
875 found = true;
876 } else {
877 /* This isn't a referral candidate */
878 if (l_found) {
879 printf("A unrequired referral has been found on subtree scope (%s -> %s)!\n", partitions[j], partitions[i]);
880 talloc_free(ldb);
881 return false;
885 talloc_free(res);
886 talloc_free(dn2);
889 talloc_free(dn1);
892 talloc_free(ldb);
894 return true;
897 static bool test_abandon_request(struct torture_context *tctx,
898 struct ldap_connection *conn, const char *basedn)
900 struct ldap_message *msg;
901 struct ldap_request *req;
902 NTSTATUS status;
904 printf("Testing the AbandonRequest with an old message id!\n");
906 if (!basedn) {
907 return false;
910 msg = new_ldap_message(conn);
911 if (!msg) {
912 return false;
915 printf(" Try a AbandonRequest for an old message id\n");
917 msg->type = LDAP_TAG_AbandonRequest;
918 msg->r.AbandonRequest.messageid = 1;
920 req = ldap_request_send(conn, msg);
921 if (!req) {
922 return false;
925 status = ldap_request_wait(req);
926 if (!NT_STATUS_IS_OK(status)) {
927 printf("error in ldap abandon request - %s\n", nt_errstr(status));
928 return false;
931 return true;
935 bool torture_ldap_basic(struct torture_context *torture)
937 NTSTATUS status;
938 struct ldap_connection *conn;
939 TALLOC_CTX *mem_ctx;
940 bool ret = true;
941 const char *host = torture_setting_string(torture, "host", NULL);
942 const char *userdn = torture_setting_string(torture, "ldap_userdn", NULL);
943 const char *secret = torture_setting_string(torture, "ldap_secret", NULL);
944 const char *url;
945 const char *basedn;
946 const char **partitions;
948 mem_ctx = talloc_init("torture_ldap_basic");
950 url = talloc_asprintf(mem_ctx, "ldap://%s/", host);
952 status = torture_ldap_connection(torture, &conn, url);
953 if (!NT_STATUS_IS_OK(status)) {
954 return false;
957 if (!test_search_rootDSE(conn, &basedn, &partitions)) {
958 ret = false;
961 if (!test_search_rootDSE_empty_substring(conn)) {
962 ret = false;
965 /* other bind tests here */
967 if (!test_multibind(conn, userdn, secret)) {
968 ret = false;
971 if (!test_bind_sasl(torture, conn, cmdline_credentials)) {
972 ret = false;
975 if (!test_search_auth_empty_substring(conn, basedn)) {
976 ret = false;
979 if (!test_compare_sasl(conn, basedn)) {
980 ret = false;
983 /* error codes test here */
985 if (!test_error_codes(torture, conn, basedn)) {
986 ret = false;
989 /* referrals test here */
991 if (!test_referrals(torture, mem_ctx, url, basedn, partitions)) {
992 ret = false;
995 if (!test_abandon_request(torture, conn, basedn)) {
996 ret = false;
999 /* if there are no more tests we are closing */
1000 torture_ldap_close(conn);
1001 talloc_free(mem_ctx);
1003 return ret;