LCOV - code coverage report
Current view: top level - source4/torture/ldap - basic.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 427 620 68.9 %
Date: 2024-04-21 15:09:00 Functions: 11 11 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS Implementation.
       3             :    LDAP protocol helper functions for SAMBA
       4             :    
       5             :    Copyright (C) Stefan Metzmacher 2004
       6             :    Copyright (C) Simo Sorce 2004
       7             :    Copyright (C) Matthias Dieter Wallnöfer 2009-2010
       8             :     
       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.
      13             :    
      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.
      18             :    
      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/>.
      21             :    
      22             : */
      23             : 
      24             : #include "includes.h"
      25             : #include "ldb_wrap.h"
      26             : #include "libcli/ldap/ldap_client.h"
      27             : #include "lib/cmdline/cmdline.h"
      28             : 
      29             : #include "torture/torture.h"
      30             : #include "torture/ldap/proto.h"
      31             : 
      32             : #undef strcasecmp
      33             : 
      34           1 : static bool test_bind_sasl(struct torture_context *tctx,
      35             :                            struct ldap_connection *conn, struct cli_credentials *creds)
      36             : {
      37           0 :         NTSTATUS status;
      38           1 :         bool ret = true;
      39             : 
      40           1 :         printf("Testing sasl bind as user\n");
      41             : 
      42           1 :         status = torture_ldap_bind_sasl(conn, creds, tctx->lp_ctx);
      43           1 :         if (!NT_STATUS_IS_OK(status)) {
      44           0 :                 ret = false;
      45             :         }
      46             : 
      47           1 :         return ret;
      48             : }
      49             : 
      50           1 : static bool test_multibind(struct ldap_connection *conn, const char *userdn, const char *password)
      51             : {
      52           0 :         NTSTATUS status, expected;
      53           0 :         bool ok;
      54             : 
      55           1 :         printf("Testing multiple binds on a single connection as anonymous and user\n");
      56             : 
      57           1 :         status = torture_ldap_bind(conn, NULL, NULL);
      58           1 :         if (!NT_STATUS_IS_OK(status)) {
      59           0 :                 printf("1st bind as anonymous failed with %s\n",
      60             :                        nt_errstr(status));
      61           0 :                 return false;
      62             :         }
      63             : 
      64           1 :         expected = NT_STATUS_LDAP(LDAP_STRONG_AUTH_REQUIRED);
      65           1 :         status = torture_ldap_bind(conn, userdn, password);
      66             : 
      67           1 :         ok = NT_STATUS_EQUAL(status, expected);
      68           1 :         if (!ok) {
      69           0 :                 printf("2nd bind as authenticated user should have "
      70             :                        "failed with: %s, got %s\n",
      71             :                        nt_errstr(expected),
      72             :                        nt_errstr(status));
      73           0 :                 return false;
      74             :         }
      75             : 
      76           1 :         return true;
      77             : }
      78             : 
      79           1 : static bool test_search_rootDSE(struct ldap_connection *conn, const char **basedn,
      80             :         const char ***partitions)
      81             : {
      82           1 :         bool ret = true;
      83           0 :         struct ldap_message *msg, *result;
      84           0 :         struct ldap_request *req;
      85           0 :         int i;
      86           0 :         struct ldap_SearchResEntry *r;
      87           0 :         NTSTATUS status;
      88             : 
      89           1 :         printf("Testing RootDSE Search\n");
      90             : 
      91           1 :         *basedn = NULL;
      92             : 
      93           1 :         if (partitions != NULL) {
      94           1 :                 *partitions = const_str_list(str_list_make_empty(conn));
      95             :         }
      96             : 
      97           1 :         msg = new_ldap_message(conn);
      98           1 :         if (!msg) {
      99           0 :                 return false;
     100             :         }
     101             : 
     102           1 :         msg->type = LDAP_TAG_SearchRequest;
     103           1 :         msg->r.SearchRequest.basedn = "";
     104           1 :         msg->r.SearchRequest.scope = LDAP_SEARCH_SCOPE_BASE;
     105           1 :         msg->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER;
     106           1 :         msg->r.SearchRequest.timelimit = 0;
     107           1 :         msg->r.SearchRequest.sizelimit = 0;
     108           1 :         msg->r.SearchRequest.attributesonly = false;
     109           1 :         msg->r.SearchRequest.tree = ldb_parse_tree(msg, "(objectclass=*)");
     110           1 :         msg->r.SearchRequest.num_attributes = 0;
     111           1 :         msg->r.SearchRequest.attributes = NULL;
     112             : 
     113           1 :         req = ldap_request_send(conn, msg);
     114           1 :         if (req == NULL) {
     115           0 :                 printf("Could not setup ldap search\n");
     116           0 :                 return false;
     117             :         }
     118             : 
     119           1 :         status = ldap_result_one(req, &result, LDAP_TAG_SearchResultEntry);
     120           1 :         if (!NT_STATUS_IS_OK(status)) {
     121           0 :                 printf("search failed - %s\n", nt_errstr(status));
     122           0 :                 return false;
     123             :         }
     124             : 
     125           1 :         printf("received %d replies\n", req->num_replies);
     126             : 
     127           1 :         r = &result->r.SearchResultEntry;
     128             :                 
     129           1 :         DEBUG(1,("\tdn: %s\n", r->dn));
     130          23 :         for (i=0; i<r->num_attributes; i++) {
     131             :                 unsigned int j;
     132          77 :                 for (j=0; j<r->attributes[i].num_values; j++) {
     133          55 :                         DEBUG(1,("\t%s: %d %.*s\n", r->attributes[i].name,
     134             :                                  (int)r->attributes[i].values[j].length,
     135             :                                  (int)r->attributes[i].values[j].length,
     136             :                                  (char *)r->attributes[i].values[j].data));
     137          55 :                         if (!(*basedn) && 
     138           2 :                             strcasecmp("defaultNamingContext",r->attributes[i].name)==0) {
     139           1 :                                 *basedn = talloc_asprintf(conn, "%.*s",
     140           1 :                                                           (int)r->attributes[i].values[j].length,
     141           1 :                                                           (char *)r->attributes[i].values[j].data);
     142             :                         }
     143          55 :                         if ((partitions != NULL) &&
     144          55 :                             (strcasecmp("namingContexts", r->attributes[i].name) == 0)) {
     145           5 :                                 char *entry = talloc_asprintf(conn, "%.*s",
     146           5 :                                                               (int)r->attributes[i].values[j].length,
     147           5 :                                                               (char *)r->attributes[i].values[j].data);
     148           5 :                                 *partitions = str_list_add(*partitions, entry);
     149             :                         }
     150             :                 }
     151             :         }
     152             : 
     153           1 :         return ret;
     154             : }
     155             : 
     156           1 : static bool test_search_rootDSE_empty_substring(struct ldap_connection *conn)
     157             : {
     158           1 :         bool ret = true;
     159           0 :         struct ldap_message *msg, *result;
     160           0 :         struct ldap_request *req;
     161           0 :         NTSTATUS status;
     162             : 
     163           1 :         printf("Testing RootDSE Search with objectclass= substring filter\n");
     164             : 
     165           1 :         msg = new_ldap_message(conn);
     166           1 :         if (!msg) {
     167           0 :                 return false;
     168             :         }
     169             : 
     170           1 :         msg->type = LDAP_TAG_SearchRequest;
     171           1 :         msg->r.SearchRequest.basedn = "";
     172           1 :         msg->r.SearchRequest.scope = LDAP_SEARCH_SCOPE_BASE;
     173           1 :         msg->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER;
     174           1 :         msg->r.SearchRequest.timelimit = 0;
     175           1 :         msg->r.SearchRequest.sizelimit = 0;
     176           1 :         msg->r.SearchRequest.attributesonly = false;
     177           1 :         msg->r.SearchRequest.tree = ldb_parse_tree(msg, "(objectclass=*)");
     178           1 :         msg->r.SearchRequest.tree->operation = LDB_OP_SUBSTRING;
     179           1 :         msg->r.SearchRequest.tree->u.substring.attr = "objectclass";
     180           1 :         msg->r.SearchRequest.tree->u.substring.start_with_wildcard = 1;
     181           1 :         msg->r.SearchRequest.tree->u.substring.end_with_wildcard = 1;
     182           1 :         msg->r.SearchRequest.tree->u.substring.chunks = NULL;
     183           1 :         msg->r.SearchRequest.num_attributes = 0;
     184           1 :         msg->r.SearchRequest.attributes = NULL;
     185             : 
     186           1 :         req = ldap_request_send(conn, msg);
     187           1 :         if (req == NULL) {
     188           0 :                 printf("Could not setup ldap search\n");
     189           0 :                 return false;
     190             :         }
     191             : 
     192           1 :         status = ldap_result_one(req, &result, LDAP_TAG_SearchResultEntry);
     193           1 :         if (!NT_STATUS_IS_OK(status)) {
     194           0 :                 printf("looking for search result reply failed - %s\n", nt_errstr(status));
     195           0 :                 return false;
     196             :         }
     197             : 
     198           1 :         printf("received %d replies\n", req->num_replies);
     199             : 
     200           1 :         return ret;
     201             : }
     202             : 
     203           1 : static bool test_search_auth_empty_substring(struct ldap_connection *conn, const char *basedn)
     204             : {
     205           1 :         bool ret = true;
     206           0 :         struct ldap_message *msg, *result;
     207           0 :         struct ldap_request *req;
     208           0 :         NTSTATUS status;
     209           0 :         struct ldap_Result *r;
     210             : 
     211           1 :         printf("Testing authenticated base Search with objectclass= substring filter\n");
     212             : 
     213           1 :         msg = new_ldap_message(conn);
     214           1 :         if (!msg) {
     215           0 :                 return false;
     216             :         }
     217             : 
     218           1 :         msg->type = LDAP_TAG_SearchRequest;
     219           1 :         msg->r.SearchRequest.basedn = basedn;
     220           1 :         msg->r.SearchRequest.scope = LDAP_SEARCH_SCOPE_BASE;
     221           1 :         msg->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER;
     222           1 :         msg->r.SearchRequest.timelimit = 0;
     223           1 :         msg->r.SearchRequest.sizelimit = 0;
     224           1 :         msg->r.SearchRequest.attributesonly = false;
     225           1 :         msg->r.SearchRequest.tree = ldb_parse_tree(msg, "(objectclass=*)");
     226           1 :         msg->r.SearchRequest.tree->operation = LDB_OP_SUBSTRING;
     227           1 :         msg->r.SearchRequest.tree->u.substring.attr = "objectclass";
     228           1 :         msg->r.SearchRequest.tree->u.substring.start_with_wildcard = 1;
     229           1 :         msg->r.SearchRequest.tree->u.substring.end_with_wildcard = 1;
     230           1 :         msg->r.SearchRequest.tree->u.substring.chunks = NULL;
     231           1 :         msg->r.SearchRequest.num_attributes = 0;
     232           1 :         msg->r.SearchRequest.attributes = NULL;
     233             : 
     234           1 :         req = ldap_request_send(conn, msg);
     235           1 :         if (req == NULL) {
     236           0 :                 printf("Could not setup ldap search\n");
     237           0 :                 return false;
     238             :         }
     239             : 
     240           1 :         status = ldap_result_one(req, &result, LDAP_TAG_SearchResultDone);
     241           1 :         if (!NT_STATUS_IS_OK(status)) {
     242           0 :                 printf("looking for search result done failed - %s\n", nt_errstr(status));
     243           0 :                 return false;
     244             :         }
     245             : 
     246           1 :         printf("received %d replies\n", req->num_replies);
     247             : 
     248           1 :         r = &result->r.SearchResultDone;
     249             : 
     250           1 :         if (r->resultcode != LDAP_SUCCESS) {
     251           0 :                 printf("search result done gave error - %s\n", ldb_strerror(r->resultcode));
     252           0 :                 return false;
     253             :         }
     254             : 
     255           1 :         return ret;
     256             : }
     257             : 
     258           1 : static bool test_compare_sasl(struct ldap_connection *conn, const char *basedn)
     259             : {
     260           0 :         struct ldap_message *msg, *rep;
     261           0 :         struct ldap_request *req;
     262           0 :         const char *val;
     263           0 :         NTSTATUS status;
     264             : 
     265           1 :         printf("Testing SASL Compare: %s\n", basedn);
     266             : 
     267           1 :         if (!basedn) {
     268           0 :                 return false;
     269             :         }
     270             : 
     271           1 :         msg = new_ldap_message(conn);
     272           1 :         if (!msg) {
     273           0 :                 return false;
     274             :         }
     275             : 
     276           1 :         msg->type = LDAP_TAG_CompareRequest;
     277           1 :         msg->r.CompareRequest.dn = basedn;
     278           1 :         msg->r.CompareRequest.attribute = talloc_strdup(msg, "objectClass");
     279           1 :         val = "domain";
     280           1 :         msg->r.CompareRequest.value = data_blob_talloc(msg, val, strlen(val));
     281             : 
     282           1 :         req = ldap_request_send(conn, msg);
     283           1 :         if (!req) {
     284           0 :                 return false;
     285             :         }
     286             : 
     287           1 :         status = ldap_result_one(req, &rep, LDAP_TAG_CompareResponse);
     288           1 :         if (!NT_STATUS_IS_OK(status)) {
     289           0 :                 printf("error in ldap compare request - %s\n", nt_errstr(status));
     290           0 :                 return false;
     291             :         }
     292             : 
     293           1 :         DEBUG(5,("Code: %d DN: [%s] ERROR:[%s] REFERRAL:[%s]\n",
     294             :                 rep->r.CompareResponse.resultcode,
     295             :                 rep->r.CompareResponse.dn,
     296             :                 rep->r.CompareResponse.errormessage,
     297             :                 rep->r.CompareResponse.referral));
     298             : 
     299           1 :         return true;
     300             : }
     301             : 
     302             : /*
     303             :  * This takes an AD error message and splits it into the WERROR code
     304             :  * (WERR_DS_GENERIC if none found) and the reason (remaining string).
     305             :  */
     306          10 : static WERROR ad_error(const char *err_msg, char **reason)
     307             : {
     308          10 :         WERROR err = W_ERROR(strtol(err_msg, reason, 16));
     309             : 
     310          10 :         if ((reason != NULL) && (*reason[0] != ':')) {
     311           0 :                 return WERR_DS_GENERIC_ERROR; /* not an AD std error message */
     312             :         }
     313             :                 
     314          10 :         if (reason != NULL) {
     315          10 :                 *reason += 2; /* skip ": " */
     316             :         }
     317          10 :         return err;
     318             : }
     319             : 
     320             : /* This has to be done using the LDAP API since the LDB API does only transmit
     321             :  * the error code and not the error message. */
     322           1 : static bool test_error_codes(struct torture_context *tctx,
     323             :         struct ldap_connection *conn, const char *basedn)
     324             : {
     325           0 :         struct ldap_message *msg, *rep;
     326           0 :         struct ldap_request *req;
     327           0 :         const char *err_code_str;
     328           0 :         char *endptr;
     329           0 :         WERROR err;
     330           0 :         NTSTATUS status;
     331             : 
     332           1 :         printf("Testing the most important error code -> error message conversions!\n");
     333             : 
     334           1 :         if (!basedn) {
     335           0 :                 return false;
     336             :         }
     337             : 
     338           1 :         msg = new_ldap_message(conn);
     339           1 :         if (!msg) {
     340           0 :                 return false;
     341             :         }
     342             : 
     343           1 :         printf(" Try a wrong addition\n");
     344             : 
     345           1 :         msg->type = LDAP_TAG_AddRequest;
     346           1 :         msg->r.AddRequest.dn = basedn;
     347           1 :         msg->r.AddRequest.num_attributes = 0;
     348           1 :         msg->r.AddRequest.attributes = NULL;
     349             : 
     350           1 :         req = ldap_request_send(conn, msg);
     351           1 :         if (!req) {
     352           0 :                 return false;
     353             :         }
     354             : 
     355           1 :         status = ldap_result_one(req, &rep, LDAP_TAG_AddResponse);
     356           1 :         if (!NT_STATUS_IS_OK(status)) {
     357           0 :                 printf("error in ldap add request - %s\n", nt_errstr(status));
     358           0 :                 return false;
     359             :         }
     360             : 
     361           1 :         if ((rep->r.AddResponse.resultcode == 0)
     362           1 :                 || (rep->r.AddResponse.errormessage == NULL)
     363           1 :                 || (strtol(rep->r.AddResponse.errormessage, &endptr,16) <= 0)
     364           1 :                 || (*endptr != ':')) {
     365           0 :                 printf("Invalid error message!\n");
     366           0 :                 return false;
     367             :         }
     368             : 
     369           1 :         err = ad_error(rep->r.AddResponse.errormessage, &endptr);
     370           1 :         err_code_str = win_errstr(err);
     371           1 :         printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
     372           1 :         if ((!W_ERROR_EQUAL(err, WERR_DS_REFERRAL))
     373           1 :                         || (rep->r.AddResponse.resultcode != LDAP_REFERRAL)) {
     374           0 :                         return false;
     375             :         }
     376           1 :         if ((rep->r.AddResponse.referral == NULL)
     377           1 :                         || (strstr(rep->r.AddResponse.referral, basedn) == NULL)) {
     378           0 :                         return false;
     379             :         }
     380             : 
     381           1 :         printf(" Try another wrong addition\n");
     382             : 
     383           1 :         msg->type = LDAP_TAG_AddRequest;
     384           1 :         msg->r.AddRequest.dn = "";
     385           1 :         msg->r.AddRequest.num_attributes = 0;
     386           1 :         msg->r.AddRequest.attributes = NULL;
     387             : 
     388           1 :         req = ldap_request_send(conn, msg);
     389           1 :         if (!req) {
     390           0 :                 return false;
     391             :         }
     392             : 
     393           1 :         status = ldap_result_one(req, &rep, LDAP_TAG_AddResponse);
     394           1 :         if (!NT_STATUS_IS_OK(status)) {
     395           0 :                 printf("error in ldap add request - %s\n", nt_errstr(status));
     396           0 :                 return false;
     397             :         }
     398             : 
     399           1 :         if ((rep->r.AddResponse.resultcode == 0)
     400           1 :                 || (rep->r.AddResponse.errormessage == NULL)
     401           1 :                 || (strtol(rep->r.AddResponse.errormessage, &endptr,16) <= 0)
     402           1 :                 || (*endptr != ':')) {
     403           0 :                 printf("Invalid error message!\n");
     404           0 :                 return false;
     405             :         }
     406             : 
     407           1 :         err = ad_error(rep->r.AddResponse.errormessage, &endptr);
     408           1 :         err_code_str = win_errstr(err);
     409           1 :         printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
     410           1 :         if ((!W_ERROR_EQUAL(err, WERR_DS_ROOT_MUST_BE_NC) &&
     411           1 :              !W_ERROR_EQUAL(err, WERR_DS_NAMING_VIOLATION))
     412           1 :                 || (rep->r.AddResponse.resultcode != LDAP_NAMING_VIOLATION)) {
     413           0 :                 return false;
     414             :         }
     415             : 
     416           1 :         printf(" Try a wrong modification\n");
     417             : 
     418           1 :         msg->type = LDAP_TAG_ModifyRequest;
     419           1 :         msg->r.ModifyRequest.dn = basedn;
     420           1 :         msg->r.ModifyRequest.num_mods = 0;
     421           1 :         msg->r.ModifyRequest.mods = NULL;
     422             : 
     423           1 :         req = ldap_request_send(conn, msg);
     424           1 :         if (!req) {
     425           0 :                 return false;
     426             :         }
     427             : 
     428           1 :         status = ldap_result_one(req, &rep, LDAP_TAG_ModifyResponse);
     429           1 :         if (!NT_STATUS_IS_OK(status)) {
     430           0 :                 printf("error in ldap modifification request - %s\n", nt_errstr(status));
     431           0 :                 return false;
     432             :         }
     433             : 
     434           1 :         if ((rep->r.ModifyResponse.resultcode == 0)
     435           1 :                 || (rep->r.ModifyResponse.errormessage == NULL)
     436           1 :                 || (strtol(rep->r.ModifyResponse.errormessage, &endptr,16) <= 0)
     437           1 :                 || (*endptr != ':')) {
     438           0 :                 printf("Invalid error message!\n");
     439           0 :                 return false;
     440             :         }
     441             : 
     442           1 :         err = ad_error(rep->r.ModifyResponse.errormessage, &endptr);
     443           1 :         err_code_str = win_errstr(err);
     444           1 :         printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
     445           1 :         if ((!W_ERROR_EQUAL(err, WERR_INVALID_PARAMETER) &&
     446           1 :              !W_ERROR_EQUAL(err, WERR_DS_UNWILLING_TO_PERFORM))
     447           1 :                 || (rep->r.ModifyResponse.resultcode != LDAP_UNWILLING_TO_PERFORM)) {
     448           0 :                 return false;
     449             :         }
     450             : 
     451           1 :         printf(" Try another wrong modification\n");
     452             : 
     453           1 :         msg->type = LDAP_TAG_ModifyRequest;
     454           1 :         msg->r.ModifyRequest.dn = "";
     455           1 :         msg->r.ModifyRequest.num_mods = 0;
     456           1 :         msg->r.ModifyRequest.mods = NULL;
     457             : 
     458           1 :         req = ldap_request_send(conn, msg);
     459           1 :         if (!req) {
     460           0 :                 return false;
     461             :         }
     462             : 
     463           1 :         status = ldap_result_one(req, &rep, LDAP_TAG_ModifyResponse);
     464           1 :         if (!NT_STATUS_IS_OK(status)) {
     465           0 :                 printf("error in ldap modifification request - %s\n", nt_errstr(status));
     466           0 :                 return false;
     467             :         }
     468             : 
     469           1 :         if ((rep->r.ModifyResponse.resultcode == 0)
     470           1 :                 || (rep->r.ModifyResponse.errormessage == NULL)
     471           1 :                 || (strtol(rep->r.ModifyResponse.errormessage, &endptr,16) <= 0)
     472           1 :                 || (*endptr != ':')) {
     473           0 :                 printf("Invalid error message!\n");
     474           0 :                 return false;
     475             :         }
     476             : 
     477           1 :         err = ad_error(rep->r.ModifyResponse.errormessage, &endptr);
     478           1 :         err_code_str = win_errstr(err);
     479           1 :         printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
     480           1 :         if ((!W_ERROR_EQUAL(err, WERR_INVALID_PARAMETER) &&
     481           1 :              !W_ERROR_EQUAL(err, WERR_DS_UNWILLING_TO_PERFORM))
     482           1 :                 || (rep->r.ModifyResponse.resultcode != LDAP_UNWILLING_TO_PERFORM)) {
     483           0 :                 return false;
     484             :         }
     485             : 
     486           1 :         printf(" Try a wrong removal\n");
     487             : 
     488           1 :         msg->type = LDAP_TAG_DelRequest;
     489           1 :         msg->r.DelRequest.dn = basedn;
     490             : 
     491           1 :         req = ldap_request_send(conn, msg);
     492           1 :         if (!req) {
     493           0 :                 return false;
     494             :         }
     495             : 
     496           1 :         status = ldap_result_one(req, &rep, LDAP_TAG_DelResponse);
     497           1 :         if (!NT_STATUS_IS_OK(status)) {
     498           0 :                 printf("error in ldap removal request - %s\n", nt_errstr(status));
     499           0 :                 return false;
     500             :         }
     501             : 
     502           1 :         if ((rep->r.DelResponse.resultcode == 0)
     503           1 :                 || (rep->r.DelResponse.errormessage == NULL)
     504           1 :                 || (strtol(rep->r.DelResponse.errormessage, &endptr,16) <= 0)
     505           1 :                 || (*endptr != ':')) {
     506           0 :                 printf("Invalid error message!\n");
     507           0 :                 return false;
     508             :         }
     509             : 
     510           1 :         err = ad_error(rep->r.DelResponse.errormessage, &endptr);
     511           1 :         err_code_str = win_errstr(err);
     512           1 :         printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
     513           1 :         if ((!W_ERROR_EQUAL(err, WERR_DS_CANT_DELETE) &&
     514           1 :              !W_ERROR_EQUAL(err, WERR_DS_UNWILLING_TO_PERFORM))
     515           1 :                 || (rep->r.DelResponse.resultcode != LDAP_UNWILLING_TO_PERFORM)) {
     516           0 :                 return false;
     517             :         }
     518             : 
     519           1 :         printf(" Try another wrong removal\n");
     520             : 
     521           1 :         msg->type = LDAP_TAG_DelRequest;
     522           1 :         msg->r.DelRequest.dn = "";
     523             : 
     524           1 :         req = ldap_request_send(conn, msg);
     525           1 :         if (!req) {
     526           0 :                 return false;
     527             :         }
     528             : 
     529           1 :         status = ldap_result_one(req, &rep, LDAP_TAG_DelResponse);
     530           1 :         if (!NT_STATUS_IS_OK(status)) {
     531           0 :                 printf("error in ldap removal request - %s\n", nt_errstr(status));
     532           0 :                 return false;
     533             :         }
     534             : 
     535           1 :         if ((rep->r.DelResponse.resultcode == 0)
     536           1 :                 || (rep->r.DelResponse.errormessage == NULL)
     537           1 :                 || (strtol(rep->r.DelResponse.errormessage, &endptr,16) <= 0)
     538           1 :                 || (*endptr != ':')) {
     539           0 :                 printf("Invalid error message!\n");
     540           0 :                 return false;
     541             :         }
     542             :         
     543           1 :         err = ad_error(rep->r.DelResponse.errormessage, &endptr);
     544           1 :         err_code_str = win_errstr(err);
     545           1 :         printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
     546           1 :         if ((!W_ERROR_EQUAL(err, WERR_DS_OBJ_NOT_FOUND) &&
     547           1 :              !W_ERROR_EQUAL(err, WERR_DS_NO_SUCH_OBJECT))
     548           1 :                 || (rep->r.DelResponse.resultcode != LDAP_NO_SUCH_OBJECT)) {
     549           0 :                 return false;
     550             :         }
     551             : 
     552           1 :         printf(" Try a wrong rename\n");
     553             : 
     554           1 :         msg->type = LDAP_TAG_ModifyDNRequest;
     555           1 :         msg->r.ModifyDNRequest.dn = basedn;
     556           1 :         msg->r.ModifyDNRequest.newrdn = "dc=test";
     557           1 :         msg->r.ModifyDNRequest.deleteolddn = true;
     558           1 :         msg->r.ModifyDNRequest.newsuperior = NULL;
     559             : 
     560           1 :         req = ldap_request_send(conn, msg);
     561           1 :         if (!req) {
     562           0 :                 return false;
     563             :         }
     564             : 
     565           1 :         status = ldap_result_one(req, &rep, LDAP_TAG_ModifyDNResponse);
     566           1 :         if (!NT_STATUS_IS_OK(status)) {
     567           0 :                 printf("error in ldap rename request - %s\n", nt_errstr(status));
     568           0 :                 return false;
     569             :         }
     570             : 
     571           1 :         if ((rep->r.ModifyDNResponse.resultcode == 0)
     572           1 :                 || (rep->r.ModifyDNResponse.errormessage == NULL)
     573           1 :                 || (strtol(rep->r.ModifyDNResponse.errormessage, &endptr,16) <= 0)
     574           1 :                 || (*endptr != ':')) {
     575           0 :                 printf("Invalid error message!\n");
     576           0 :                 return false;
     577             :         }
     578             : 
     579           1 :         err = ad_error(rep->r.ModifyDNResponse.errormessage, &endptr);
     580           1 :         err_code_str = win_errstr(err);
     581           1 :         printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
     582           1 :         if ((!W_ERROR_EQUAL(err, WERR_DS_NO_PARENT_OBJECT) &&
     583           1 :              !W_ERROR_EQUAL(err, WERR_DS_GENERIC_ERROR))
     584           1 :                 || (rep->r.ModifyDNResponse.resultcode != LDAP_OTHER)) {
     585           0 :                 return false;
     586             :         }
     587             : 
     588           1 :         printf(" Try another wrong rename\n");
     589             : 
     590           1 :         msg->type = LDAP_TAG_ModifyDNRequest;
     591           1 :         msg->r.ModifyDNRequest.dn = basedn;
     592           1 :         msg->r.ModifyDNRequest.newrdn = basedn;
     593           1 :         msg->r.ModifyDNRequest.deleteolddn = true;
     594           1 :         msg->r.ModifyDNRequest.newsuperior = NULL;
     595             : 
     596           1 :         req = ldap_request_send(conn, msg);
     597           1 :         if (!req) {
     598           0 :                 return false;
     599             :         }
     600             : 
     601           1 :         status = ldap_result_one(req, &rep, LDAP_TAG_ModifyDNResponse);
     602           1 :         if (!NT_STATUS_IS_OK(status)) {
     603           0 :                 printf("error in ldap rename request - %s\n", nt_errstr(status));
     604           0 :                 return false;
     605             :         }
     606             : 
     607           1 :         if ((rep->r.ModifyDNResponse.resultcode == 0)
     608           1 :                 || (rep->r.ModifyDNResponse.errormessage == NULL)
     609           1 :                 || (strtol(rep->r.ModifyDNResponse.errormessage, &endptr,16) <= 0)
     610           1 :                 || (*endptr != ':')) {
     611           0 :                 printf("Invalid error message!\n");
     612           0 :                 return false;
     613             :         }
     614             : 
     615           1 :         err = ad_error(rep->r.ModifyDNResponse.errormessage, &endptr);
     616           1 :         err_code_str = win_errstr(err);
     617           1 :         printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
     618           1 :         if ((!W_ERROR_EQUAL(err, WERR_INVALID_PARAMETER) &&
     619           1 :              !W_ERROR_EQUAL(err, WERR_DS_NAMING_VIOLATION))
     620           1 :                 || (rep->r.ModifyDNResponse.resultcode != LDAP_NAMING_VIOLATION)) {
     621           0 :                 return false;
     622             :         }
     623             : 
     624           1 :         printf(" Try another wrong rename\n");
     625             : 
     626           1 :         msg->type = LDAP_TAG_ModifyDNRequest;
     627           1 :         msg->r.ModifyDNRequest.dn = basedn;
     628           1 :         msg->r.ModifyDNRequest.newrdn = "";
     629           1 :         msg->r.ModifyDNRequest.deleteolddn = true;
     630           1 :         msg->r.ModifyDNRequest.newsuperior = NULL;
     631             : 
     632           1 :         req = ldap_request_send(conn, msg);
     633           1 :         if (!req) {
     634           0 :                 return false;
     635             :         }
     636             : 
     637           1 :         status = ldap_result_one(req, &rep, LDAP_TAG_ModifyDNResponse);
     638           1 :         if (!NT_STATUS_IS_OK(status)) {
     639           0 :                 printf("error in ldap rename request - %s\n", nt_errstr(status));
     640           0 :                 return false;
     641             :         }
     642             : 
     643           1 :         if ((rep->r.ModifyDNResponse.resultcode == 0)
     644           1 :                 || (rep->r.ModifyDNResponse.errormessage == NULL)
     645           1 :                 || (strtol(rep->r.ModifyDNResponse.errormessage, &endptr,16) <= 0)
     646           1 :                 || (*endptr != ':')) {
     647           0 :                 printf("Invalid error message!\n");
     648           0 :                 return false;
     649             :         }
     650             : 
     651           1 :         err = ad_error(rep->r.ModifyDNResponse.errormessage, &endptr);
     652           1 :         err_code_str = win_errstr(err);
     653           1 :         printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
     654           1 :         if ((!W_ERROR_EQUAL(err, WERR_INVALID_PARAMETER) &&
     655           1 :              !W_ERROR_EQUAL(err, WERR_DS_PROTOCOL_ERROR))
     656           1 :                 || (rep->r.ModifyDNResponse.resultcode != LDAP_PROTOCOL_ERROR)) {
     657           0 :                 return false;
     658             :         }
     659             : 
     660           1 :         printf(" Try another wrong rename\n");
     661             : 
     662           1 :         msg->type = LDAP_TAG_ModifyDNRequest;
     663           1 :         msg->r.ModifyDNRequest.dn = "";
     664           1 :         msg->r.ModifyDNRequest.newrdn = "cn=temp";
     665           1 :         msg->r.ModifyDNRequest.deleteolddn = true;
     666           1 :         msg->r.ModifyDNRequest.newsuperior = NULL;
     667             : 
     668           1 :         req = ldap_request_send(conn, msg);
     669           1 :         if (!req) {
     670           0 :                 return false;
     671             :         }
     672             : 
     673           1 :         status = ldap_result_one(req, &rep, LDAP_TAG_ModifyDNResponse);
     674           1 :         if (!NT_STATUS_IS_OK(status)) {
     675           0 :                 printf("error in ldap rename request - %s\n", nt_errstr(status));
     676           0 :                 return false;
     677             :         }
     678             : 
     679           1 :         if ((rep->r.ModifyDNResponse.resultcode == 0)
     680           1 :                 || (rep->r.ModifyDNResponse.errormessage == NULL)
     681           1 :                 || (strtol(rep->r.ModifyDNResponse.errormessage, &endptr,16) <= 0)
     682           1 :                 || (*endptr != ':')) {
     683           0 :                 printf("Invalid error message!\n");
     684           0 :                 return false;
     685             :         }
     686             : 
     687           1 :         err = ad_error(rep->r.ModifyDNResponse.errormessage, &endptr);
     688           1 :         err_code_str = win_errstr(err);
     689           1 :         printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
     690           1 :         if ((!W_ERROR_EQUAL(err, WERR_DS_OBJ_NOT_FOUND) &&
     691           1 :              !W_ERROR_EQUAL(err, WERR_DS_NO_SUCH_OBJECT))
     692           1 :                 || (rep->r.ModifyDNResponse.resultcode != LDAP_NO_SUCH_OBJECT)) {
     693           0 :                 return false;
     694             :         }
     695             : 
     696           1 :         return true;
     697             : }
     698             : 
     699           1 : static bool test_referrals(struct torture_context *tctx, TALLOC_CTX *mem_ctx,
     700             :         const char *url, const char *basedn, const char **partitions)
     701             : {
     702           0 :         struct ldb_context *ldb;
     703           0 :         struct ldb_result *res;
     704           1 :         const char * const *attrs = { NULL };
     705           0 :         struct ldb_dn *dn1, *dn2;
     706           0 :         int ret;
     707           0 :         int i, j, k;
     708           0 :         char *tempstr;
     709           0 :         bool found, l_found;
     710             : 
     711           1 :         printf("Testing referrals\n");
     712             : 
     713           1 :         if (partitions[0] == NULL) {
     714           0 :                 printf("Partitions list empty!\n");
     715           0 :                 return false;
     716             :         }
     717             : 
     718           1 :         if (strcmp(partitions[0], basedn) != 0) {
     719           0 :                 printf("The first (root) partition DN should be the base DN!\n");
     720           0 :                 return false;
     721             :         }
     722             : 
     723           1 :         ldb = ldb_wrap_connect(mem_ctx, tctx->ev, tctx->lp_ctx, url,
     724             :                                NULL, samba_cmdline_get_creds(), 0);
     725             : 
     726             :         /* "partitions[i]" are the partitions for which we search the parents */
     727           5 :         for (i = 1; partitions[i] != NULL; i++) {
     728           4 :                 dn1 = ldb_dn_new(mem_ctx, ldb, partitions[i]);
     729           4 :                 if (dn1 == NULL) {
     730           0 :                         printf("Out of memory\n");
     731           0 :                         talloc_free(ldb);
     732           0 :                         return false;
     733             :                 }
     734             : 
     735             :                 /* search using base scope */
     736             :                 /* "partitions[j]" are the parent candidates */
     737          24 :                 for (j = str_list_length(partitions) - 1; j >= 0; --j) {
     738          20 :                         dn2 = ldb_dn_new(mem_ctx, ldb, partitions[j]);
     739          20 :                         if (dn2 == NULL) {
     740           0 :                                 printf("Out of memory\n");
     741           0 :                                 talloc_free(ldb);
     742           0 :                                 return false;
     743             :                         }
     744             : 
     745          20 :                         ret = ldb_search(ldb, mem_ctx, &res, dn2,
     746             :                                          LDB_SCOPE_BASE, attrs,
     747             :                                          "(foo=bar)");
     748          20 :                         if (ret != LDB_SUCCESS) {
     749           0 :                                 printf("%s", ldb_errstring(ldb));
     750           0 :                                 talloc_free(ldb);
     751           0 :                                 return false;
     752             :                         }
     753             : 
     754          20 :                         if (res->refs != NULL) {
     755           0 :                                 printf("There shouldn't be generated any referrals in the base scope!\n");
     756           0 :                                 talloc_free(ldb);
     757           0 :                                 return false;
     758             :                         }
     759             : 
     760          20 :                         talloc_free(res);
     761          20 :                         talloc_free(dn2);
     762             :                 }
     763             : 
     764             :                 /* search using onelevel scope */
     765           4 :                 found = false;
     766             :                 /* "partitions[j]" are the parent candidates */
     767          24 :                 for (j = str_list_length(partitions) - 1; j >= 0; --j) {
     768          20 :                         dn2 = ldb_dn_new(mem_ctx, ldb, partitions[j]);
     769          20 :                         if (dn2 == NULL) {
     770           0 :                                 printf("Out of memory\n");
     771           0 :                                 talloc_free(ldb);
     772           0 :                                 return false;
     773             :                         }
     774             : 
     775          20 :                         ret = ldb_search(ldb, mem_ctx, &res, dn2,
     776             :                                          LDB_SCOPE_ONELEVEL, attrs,
     777             :                                          "(foo=bar)");
     778          20 :                         if (ret != LDB_SUCCESS) {
     779           0 :                                 printf("%s", ldb_errstring(ldb));
     780           0 :                                 talloc_free(ldb);
     781           0 :                                 return false;
     782             :                         }
     783             : 
     784          20 :                         tempstr = talloc_asprintf(mem_ctx, "/%s??base",
     785          20 :                                                   partitions[i]);
     786          20 :                         if (tempstr == NULL) {
     787           0 :                                 printf("Out of memory\n");
     788           0 :                                 talloc_free(ldb);
     789           0 :                                 return false;
     790             :                         }
     791             : 
     792             :                         /* Try to find or find not a matching referral */
     793          20 :                         l_found = false;
     794          49 :                         for (k = 0; (!l_found) && (res->refs != NULL)
     795          50 :                             && (res->refs[k] != NULL); k++) {
     796          13 :                                 if (strstr(res->refs[k], tempstr) != NULL) {
     797           4 :                                         l_found = true;
     798             :                                 }
     799             :                         }
     800             : 
     801          20 :                         talloc_free(tempstr);
     802             : 
     803          20 :                         if ((!found) && (ldb_dn_compare_base(dn2, dn1) == 0)
     804           8 :                             && (ldb_dn_compare(dn2, dn1) != 0)) {
     805             :                                 /* This is a referral candidate */
     806           4 :                                 if (!l_found) {
     807           0 :                                         printf("A required referral hasn't been found on onelevel scope (%s -> %s)!\n", partitions[j], partitions[i]);
     808           0 :                                         talloc_free(ldb);
     809           0 :                                         return false;
     810             :                                 }
     811           4 :                                 found = true;
     812             :                         } else {
     813             :                                 /* This isn't a referral candidate */
     814          16 :                                 if (l_found) {
     815           0 :                                         printf("A unrequired referral has been found on onelevel scope (%s -> %s)!\n", partitions[j], partitions[i]);
     816           0 :                                         talloc_free(ldb);
     817           0 :                                         return false;
     818             :                                 }
     819             :                         }
     820             : 
     821          20 :                         talloc_free(res);
     822          20 :                         talloc_free(dn2);
     823             :                 }
     824             : 
     825             :                 /* search using subtree scope */
     826           4 :                 found = false;
     827             :                 /* "partitions[j]" are the parent candidates */
     828          24 :                 for (j = str_list_length(partitions) - 1; j >= 0; --j) {
     829          20 :                         dn2 = ldb_dn_new(mem_ctx, ldb, partitions[j]);
     830          20 :                         if (dn2 == NULL) {
     831           0 :                                 printf("Out of memory\n");
     832           0 :                                 talloc_free(ldb);
     833           0 :                                 return false;
     834             :                         }
     835             : 
     836          20 :                         ret = ldb_search(ldb, mem_ctx, &res, dn2,
     837             :                                          LDB_SCOPE_SUBTREE, attrs,
     838             :                                          "(foo=bar)");
     839          20 :                         if (ret != LDB_SUCCESS) {
     840           0 :                                 printf("%s", ldb_errstring(ldb));
     841           0 :                                 talloc_free(ldb);
     842           0 :                                 return false;
     843             :                         }
     844             : 
     845          20 :                         tempstr = talloc_asprintf(mem_ctx, "/%s",
     846          20 :                                                   partitions[i]);
     847          20 :                         if (tempstr == NULL) {
     848           0 :                                 printf("Out of memory\n");
     849           0 :                                 talloc_free(ldb);
     850           0 :                                 return false;
     851             :                         }
     852             : 
     853             :                         /* Try to find or find not a matching referral */
     854          20 :                         l_found = false;
     855          49 :                         for (k = 0; (!l_found) && (res->refs != NULL)
     856          50 :                             && (res->refs[k] != NULL); k++) {
     857          13 :                                 if (strstr(res->refs[k], tempstr) != NULL) {
     858           4 :                                         l_found = true;
     859             :                                 }
     860             :                         }
     861             : 
     862          20 :                         talloc_free(tempstr);
     863             : 
     864          20 :                         if ((!found) && (ldb_dn_compare_base(dn2, dn1) == 0)
     865           8 :                             && (ldb_dn_compare(dn2, dn1) != 0)) {
     866             :                                 /* This is a referral candidate */
     867           4 :                                 if (!l_found) {
     868           0 :                                         printf("A required referral hasn't been found on subtree scope (%s -> %s)!\n", partitions[j], partitions[i]);
     869           0 :                                         talloc_free(ldb);
     870           0 :                                         return false;
     871             :                                 }
     872           4 :                                 found = true;
     873             :                         } else {
     874             :                                 /* This isn't a referral candidate */
     875          16 :                                 if (l_found) {
     876           0 :                                         printf("A unrequired referral has been found on subtree scope (%s -> %s)!\n", partitions[j], partitions[i]);
     877           0 :                                         talloc_free(ldb);
     878           0 :                                         return false;
     879             :                                 }
     880             :                         }
     881             : 
     882          20 :                         talloc_free(res);
     883          20 :                         talloc_free(dn2);
     884             :                 }
     885             : 
     886           4 :                 talloc_free(dn1);
     887             :         }
     888             : 
     889           1 :         talloc_free(ldb);
     890             : 
     891           1 :         return true;
     892             : }
     893             : 
     894           1 : static bool test_abandon_request(struct torture_context *tctx,
     895             :         struct ldap_connection *conn, const char *basedn)
     896             : {
     897           0 :         struct ldap_message *msg;
     898           0 :         struct ldap_request *req;
     899           0 :         NTSTATUS status;
     900             : 
     901           1 :         printf("Testing the AbandonRequest with an old message id!\n");
     902             : 
     903           1 :         if (!basedn) {
     904           0 :                 return false;
     905             :         }
     906             : 
     907           1 :         msg = new_ldap_message(conn);
     908           1 :         if (!msg) {
     909           0 :                 return false;
     910             :         }
     911             : 
     912           1 :         printf(" Try a AbandonRequest for an old message id\n");
     913             : 
     914           1 :         msg->type = LDAP_TAG_AbandonRequest;
     915           1 :         msg->r.AbandonRequest.messageid = 1;
     916             : 
     917           1 :         req = ldap_request_send(conn, msg);
     918           1 :         if (!req) {
     919           0 :                 return false;
     920             :         }
     921             : 
     922           1 :         status = ldap_request_wait(req);
     923           1 :         if (!NT_STATUS_IS_OK(status)) {
     924           0 :                 printf("error in ldap abandon request - %s\n", nt_errstr(status));
     925           0 :                 return false;
     926             :         }
     927             : 
     928           1 :         return true;
     929             : }
     930             : 
     931             : 
     932           1 : bool torture_ldap_basic(struct torture_context *torture)
     933             : {
     934           0 :         NTSTATUS status;
     935           0 :         struct ldap_connection *conn;
     936           0 :         TALLOC_CTX *mem_ctx;
     937           1 :         bool ret = true;
     938           1 :         const char *host = torture_setting_string(torture, "host", NULL);
     939           1 :         const char *userdn = torture_setting_string(torture, "ldap_userdn", NULL);
     940           1 :         const char *secret = torture_setting_string(torture, "ldap_secret", NULL);
     941           0 :         const char *url;
     942           0 :         const char *basedn;
     943           0 :         const char **partitions;
     944             : 
     945           1 :         mem_ctx = talloc_init("torture_ldap_basic");
     946             : 
     947           1 :         url = talloc_asprintf(mem_ctx, "ldap://%s/", host);
     948             : 
     949           1 :         status = torture_ldap_connection(torture, &conn, url);
     950           1 :         if (!NT_STATUS_IS_OK(status)) {
     951           0 :                 return false;
     952             :         }
     953             : 
     954           1 :         if (!test_search_rootDSE(conn, &basedn, &partitions)) {
     955           0 :                 ret = false;
     956             :         }
     957             : 
     958           1 :         if (!test_search_rootDSE_empty_substring(conn)) {
     959           0 :                 ret = false;
     960             :         }
     961             : 
     962             :         /* other bind tests here */
     963             : 
     964           1 :         if (!test_multibind(conn, userdn, secret)) {
     965           0 :                 ret = false;
     966             :         }
     967             : 
     968           1 :         if (!test_bind_sasl(torture, conn, samba_cmdline_get_creds())) {
     969           0 :                 ret = false;
     970             :         }
     971             : 
     972           1 :         if (!test_search_auth_empty_substring(conn, basedn)) {
     973           0 :                 ret = false;
     974             :         }
     975             : 
     976           1 :         if (!test_compare_sasl(conn, basedn)) {
     977           0 :                 ret = false;
     978             :         }
     979             : 
     980             :         /* error codes test here */
     981             : 
     982           1 :         if (!test_error_codes(torture, conn, basedn)) {
     983           0 :                 ret = false;
     984             :         }
     985             : 
     986             :         /* referrals test here */
     987             : 
     988           1 :         if (!test_referrals(torture, mem_ctx, url, basedn, partitions)) {
     989           0 :                 ret = false;
     990             :         }
     991             : 
     992           1 :         if (!test_abandon_request(torture, conn, basedn)) {
     993           0 :                 ret = false;
     994             :         }
     995             : 
     996             :         /* if there are no more tests we are closing */
     997           1 :         torture_ldap_close(conn);
     998           1 :         talloc_free(mem_ctx);
     999             : 
    1000           1 :         torture_assert(torture, ret, "torture_ldap_basic failed");
    1001             : 
    1002           1 :         return ret;
    1003             : }
    1004             : 

Generated by: LCOV version 1.14