LCOV - code coverage report
Current view: top level - source4/ldap_server - ldap_backend.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 769 935 82.2 %
Date: 2024-04-21 15:09:00 Functions: 20 21 95.2 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    LDAP server
       4             :    Copyright (C) Stefan Metzmacher 2004
       5             :    Copyright (C) Matthias Dieter Wallnöfer 2009
       6             : 
       7             :    This program is free software; you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation; either version 3 of the License, or
      10             :    (at your option) any later version.
      11             : 
      12             :    This program is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include "includes.h"
      22             : #include "ldap_server/ldap_server.h"
      23             : #include "../lib/util/dlinklist.h"
      24             : #include "auth/credentials/credentials.h"
      25             : #include "auth/gensec/gensec.h"
      26             : #include "auth/gensec/gensec_internal.h" /* TODO: remove this */
      27             : #include "auth/common_auth.h"
      28             : #include "param/param.h"
      29             : #include "samba/service_stream.h"
      30             : #include "dsdb/samdb/samdb.h"
      31             : #include <ldb_errors.h>
      32             : #include <ldb_module.h>
      33             : #include "ldb_wrap.h"
      34             : #include "lib/tsocket/tsocket.h"
      35             : #include "libcli/ldap/ldap_proto.h"
      36             : #include "source4/auth/auth.h"
      37             : 
      38      238247 : static int map_ldb_error(TALLOC_CTX *mem_ctx, int ldb_err,
      39             :         const char *add_err_string, const char **errstring)
      40             : {
      41         216 :         WERROR err;
      42             : 
      43             :         /* Certain LDB modules need to return very special WERROR codes. Proof
      44             :          * for them here and if they exist skip the rest of the mapping. */
      45      238247 :         if (add_err_string != NULL) {
      46           0 :                 char *endptr;
      47       51386 :                 strtol(add_err_string, &endptr, 16);
      48       51386 :                 if (endptr != add_err_string) {
      49       11005 :                         *errstring = add_err_string;
      50       11005 :                         return ldb_err;
      51             :                 }
      52             :         }
      53             : 
      54             :         /* Otherwise we calculate here a generic, but appropriate WERROR. */
      55             : 
      56      227242 :         switch (ldb_err) {
      57      186634 :         case LDB_SUCCESS:
      58      186634 :                 err = WERR_OK;
      59      186634 :         break;
      60          88 :         case LDB_ERR_OPERATIONS_ERROR:
      61          88 :                 err = WERR_DS_OPERATIONS_ERROR;
      62          88 :         break;
      63           1 :         case LDB_ERR_PROTOCOL_ERROR:
      64           1 :                 err = WERR_DS_PROTOCOL_ERROR;
      65           1 :         break;
      66           5 :         case LDB_ERR_TIME_LIMIT_EXCEEDED:
      67           5 :                 err = WERR_DS_TIMELIMIT_EXCEEDED;
      68           5 :         break;
      69          10 :         case LDB_ERR_SIZE_LIMIT_EXCEEDED:
      70          10 :                 err = WERR_DS_SIZELIMIT_EXCEEDED;
      71          10 :         break;
      72           0 :         case LDB_ERR_COMPARE_FALSE:
      73           0 :                 err = WERR_DS_COMPARE_FALSE;
      74           0 :         break;
      75           0 :         case LDB_ERR_COMPARE_TRUE:
      76           0 :                 err = WERR_DS_COMPARE_TRUE;
      77           0 :         break;
      78           0 :         case LDB_ERR_AUTH_METHOD_NOT_SUPPORTED:
      79           0 :                 err = WERR_DS_AUTH_METHOD_NOT_SUPPORTED;
      80           0 :         break;
      81           0 :         case LDB_ERR_STRONG_AUTH_REQUIRED:
      82           0 :                 err = WERR_DS_STRONG_AUTH_REQUIRED;
      83           0 :         break;
      84           8 :         case LDB_ERR_REFERRAL:
      85           8 :                 err = WERR_DS_REFERRAL;
      86           8 :         break;
      87           1 :         case LDB_ERR_ADMIN_LIMIT_EXCEEDED:
      88           1 :                 err = WERR_DS_ADMIN_LIMIT_EXCEEDED;
      89           1 :         break;
      90           0 :         case LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION:
      91           0 :                 err = WERR_DS_UNAVAILABLE_CRIT_EXTENSION;
      92           0 :         break;
      93           0 :         case LDB_ERR_CONFIDENTIALITY_REQUIRED:
      94           0 :                 err = WERR_DS_CONFIDENTIALITY_REQUIRED;
      95           0 :         break;
      96           0 :         case LDB_ERR_SASL_BIND_IN_PROGRESS:
      97           0 :                 err = WERR_DS_BUSY;
      98           0 :         break;
      99           5 :         case LDB_ERR_NO_SUCH_ATTRIBUTE:
     100           5 :                 err = WERR_DS_NO_ATTRIBUTE_OR_VALUE;
     101           5 :         break;
     102           3 :         case LDB_ERR_UNDEFINED_ATTRIBUTE_TYPE:
     103           3 :                 err = WERR_DS_ATTRIBUTE_TYPE_UNDEFINED;
     104           3 :         break;
     105           0 :         case LDB_ERR_INAPPROPRIATE_MATCHING:
     106           0 :                 err = WERR_DS_INAPPROPRIATE_MATCHING;
     107           0 :         break;
     108         541 :         case LDB_ERR_CONSTRAINT_VIOLATION:
     109         541 :                 err = WERR_DS_CONSTRAINT_VIOLATION;
     110         541 :         break;
     111         137 :         case LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS:
     112         137 :                 err = WERR_DS_ATTRIBUTE_OR_VALUE_EXISTS;
     113         137 :         break;
     114          15 :         case LDB_ERR_INVALID_ATTRIBUTE_SYNTAX:
     115          15 :                 err = WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
     116          15 :         break;
     117       37573 :         case LDB_ERR_NO_SUCH_OBJECT:
     118       37573 :                 err = WERR_DS_NO_SUCH_OBJECT;
     119       37573 :         break;
     120           0 :         case LDB_ERR_ALIAS_PROBLEM:
     121           0 :                 err = WERR_DS_ALIAS_PROBLEM;
     122           0 :         break;
     123         102 :         case LDB_ERR_INVALID_DN_SYNTAX:
     124         102 :                 err = WERR_DS_INVALID_DN_SYNTAX;
     125         102 :         break;
     126           0 :         case LDB_ERR_ALIAS_DEREFERENCING_PROBLEM:
     127           0 :                 err = WERR_DS_ALIAS_DEREF_PROBLEM;
     128           0 :         break;
     129           0 :         case LDB_ERR_INAPPROPRIATE_AUTHENTICATION:
     130           0 :                 err = WERR_DS_INAPPROPRIATE_AUTH;
     131           0 :         break;
     132           0 :         case LDB_ERR_INVALID_CREDENTIALS:
     133           0 :                 err = WERR_ACCESS_DENIED;
     134           0 :         break;
     135        1193 :         case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
     136        1193 :                 err = WERR_DS_INSUFF_ACCESS_RIGHTS;
     137        1193 :         break;
     138           0 :         case LDB_ERR_BUSY:
     139           0 :                 err = WERR_DS_BUSY;
     140           0 :         break;
     141           0 :         case LDB_ERR_UNAVAILABLE:
     142           0 :                 err = WERR_DS_UNAVAILABLE;
     143           0 :         break;
     144         420 :         case LDB_ERR_UNWILLING_TO_PERFORM:
     145         420 :                 err = WERR_DS_UNWILLING_TO_PERFORM;
     146         420 :         break;
     147           0 :         case LDB_ERR_LOOP_DETECT:
     148           0 :                 err = WERR_DS_LOOP_DETECT;
     149           0 :         break;
     150           8 :         case LDB_ERR_NAMING_VIOLATION:
     151           8 :                 err = WERR_DS_NAMING_VIOLATION;
     152           8 :         break;
     153         241 :         case LDB_ERR_OBJECT_CLASS_VIOLATION:
     154         241 :                 err = WERR_DS_OBJ_CLASS_VIOLATION;
     155         241 :         break;
     156          11 :         case LDB_ERR_NOT_ALLOWED_ON_NON_LEAF:
     157          11 :                 err = WERR_DS_CANT_ON_NON_LEAF;
     158          11 :         break;
     159           2 :         case LDB_ERR_NOT_ALLOWED_ON_RDN:
     160           2 :                 err = WERR_DS_CANT_ON_RDN;
     161           2 :         break;
     162          24 :         case LDB_ERR_ENTRY_ALREADY_EXISTS:
     163          24 :                 err = WERR_DS_OBJ_STRING_NAME_EXISTS;
     164          24 :         break;
     165           0 :         case LDB_ERR_OBJECT_CLASS_MODS_PROHIBITED:
     166           0 :                 err = WERR_DS_CANT_MOD_OBJ_CLASS;
     167           0 :         break;
     168           0 :         case LDB_ERR_AFFECTS_MULTIPLE_DSAS:
     169           0 :                 err = WERR_DS_AFFECTS_MULTIPLE_DSAS;
     170           0 :         break;
     171           4 :         default:
     172           4 :                 err = WERR_DS_GENERIC_ERROR;
     173           4 :         break;
     174             :         }
     175             : 
     176      414103 :         *errstring = talloc_asprintf(mem_ctx, "%08X: %s", W_ERROR_V(err),
     177      186861 :                 add_err_string != NULL ? add_err_string : ldb_strerror(ldb_err));
     178             : 
     179             :         /* result is 1:1 for now */
     180      227242 :         return ldb_err;
     181             : }
     182             : 
     183             : /*
     184             :   connect to the sam database
     185             : */
     186       53623 : int ldapsrv_backend_Init(struct ldapsrv_connection *conn,
     187             :                               char **errstring)
     188             : {
     189       53623 :         bool using_tls = conn->sockets.active == conn->sockets.tls;
     190       53623 :         bool using_seal = conn->gensec != NULL && gensec_have_feature(conn->gensec,
     191             :                                                                       GENSEC_FEATURE_SEAL);
     192       53623 :         struct dsdb_encrypted_connection_state *opaque_connection_state = NULL;
     193             : 
     194       53867 :         int ret = samdb_connect_url(conn,
     195       53379 :                                     conn->connection->event.ctx,
     196             :                                     conn->lp_ctx,
     197             :                                     conn->session_info,
     198       53623 :                                     conn->global_catalog ? LDB_FLG_RDONLY : 0,
     199             :                                     "sam.ldb",
     200       53623 :                                     conn->connection->remote_address,
     201             :                                     &conn->ldb,
     202             :                                     errstring);
     203       53623 :         if (ret != LDB_SUCCESS) {
     204           0 :                 return ret;
     205             :         }
     206             : 
     207             :         /*
     208             :          * We can safely call ldb_set_opaque() on this ldb as we have
     209             :          * set remote_address above which avoids the ldb handle cache
     210             :          */
     211       53623 :         opaque_connection_state = talloc_zero(conn, struct dsdb_encrypted_connection_state);
     212       53623 :         if (opaque_connection_state == NULL) {
     213           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     214             :         }
     215       53623 :         opaque_connection_state->using_encrypted_connection = using_tls || using_seal || conn->is_ldapi;
     216       53623 :         ret = ldb_set_opaque(conn->ldb,
     217             :                              DSDB_OPAQUE_ENCRYPTED_CONNECTION_STATE_NAME,
     218             :                              opaque_connection_state);
     219       53623 :         if (ret != LDB_SUCCESS) {
     220           0 :                 DBG_ERR("ldb_set_opaque() failed to store our "
     221             :                         "encrypted connection state!\n");
     222           0 :                 return ret;
     223             :         }
     224             : 
     225       53623 :         if (conn->server_credentials) {
     226       53623 :                 struct gensec_security *gensec_security = NULL;
     227       53623 :                 const char **sasl_mechs = NULL;
     228         244 :                 NTSTATUS status;
     229             : 
     230       53623 :                 status = samba_server_gensec_start(conn,
     231       53379 :                                                    conn->connection->event.ctx,
     232       53623 :                                                    conn->connection->msg_ctx,
     233             :                                                    conn->lp_ctx,
     234             :                                                    conn->server_credentials,
     235             :                                                    "ldap",
     236             :                                                    &gensec_security);
     237       53623 :                 if (!NT_STATUS_IS_OK(status)) {
     238           0 :                         DBG_ERR("samba_server_gensec_start failed: %s\n",
     239             :                                 nt_errstr(status));
     240           0 :                         return LDB_ERR_OPERATIONS_ERROR;
     241             :                 }
     242             : 
     243             :                 /* ldb can have a different lifetime to conn, so we
     244             :                    need to ensure that sasl_mechs lives as long as the
     245             :                    ldb does */
     246       53867 :                 sasl_mechs = gensec_security_sasl_names(gensec_security,
     247       53623 :                                                         conn->ldb);
     248       53623 :                 TALLOC_FREE(gensec_security);
     249       53623 :                 if (sasl_mechs == NULL) {
     250           0 :                         DBG_ERR("Failed to get sasl mechs!\n");
     251           0 :                         return LDB_ERR_OPERATIONS_ERROR;
     252             :                 }
     253             : 
     254       53623 :                 ldb_set_opaque(conn->ldb, "supportedSASLMechanisms", sasl_mechs);
     255             :         }
     256             : 
     257       53379 :         return LDB_SUCCESS;
     258             : }
     259             : 
     260     1404715 : struct ldapsrv_reply *ldapsrv_init_reply(struct ldapsrv_call *call, uint8_t type)
     261             : {
     262        1116 :         struct ldapsrv_reply *reply;
     263             : 
     264     1404715 :         reply = talloc_zero(call, struct ldapsrv_reply);
     265     1404715 :         if (!reply) {
     266           0 :                 return NULL;
     267             :         }
     268     1404715 :         reply->msg = talloc_zero(reply, struct ldap_message);
     269     1404715 :         if (reply->msg == NULL) {
     270           0 :                 talloc_free(reply);
     271           0 :                 return NULL;
     272             :         }
     273             : 
     274     1404715 :         reply->msg->messageid = call->request->messageid;
     275     1404715 :         reply->msg->type = type;
     276     1404715 :         reply->msg->controls = NULL;
     277             : 
     278     1404715 :         return reply;
     279             : }
     280             : 
     281             : /*
     282             :  * Encode a reply to an LDAP client as ASN.1, free the original memory
     283             :  */
     284     1404715 : static NTSTATUS ldapsrv_encode(TALLOC_CTX *mem_ctx,
     285             :                                struct ldapsrv_reply *reply)
     286             : {
     287     1404715 :         bool bret = ldap_encode(reply->msg,
     288             :                                 samba_ldap_control_handlers(),
     289             :                                 &reply->blob,
     290             :                                 mem_ctx);
     291     1404715 :         if (!bret) {
     292           0 :                 DBG_ERR("Failed to encode ldap reply of type %d: "
     293             :                          "ldap_encode() failed\n",
     294             :                          reply->msg->type);
     295           0 :                 TALLOC_FREE(reply->msg);
     296           0 :                 return NT_STATUS_NO_MEMORY;
     297             :         }
     298             : 
     299     1404715 :         TALLOC_FREE(reply->msg);
     300     1404715 :         talloc_set_name_const(reply->blob.data,
     301             :                               "Outgoing, encoded single LDAP reply");
     302             : 
     303     1404715 :         return NT_STATUS_OK;
     304             : }
     305             : 
     306             : /*
     307             :  * Queue a reply (encoding it also), even if it would exceed the
     308             :  * limit.  This allows the error packet with LDAP_SIZE_LIMIT_EXCEEDED
     309             :  * to be sent
     310             :  */
     311      366746 : static NTSTATUS ldapsrv_queue_reply_forced(struct ldapsrv_call *call,
     312             :                                            struct ldapsrv_reply *reply)
     313             : {
     314      366746 :         NTSTATUS status = ldapsrv_encode(call, reply);
     315             : 
     316      366746 :         if (NT_STATUS_IS_OK(status)) {
     317      366746 :                 DLIST_ADD_END(call->replies, reply);
     318             :         }
     319      366746 :         return status;
     320             : }
     321             : 
     322             : /*
     323             :  * Queue a reply (encoding it also) but check we do not send more than
     324             :  * LDAP_SERVER_MAX_REPLY_SIZE of responses as a way to limit the
     325             :  * amount of data a client can make us allocate.
     326             :  */
     327     1037969 : NTSTATUS ldapsrv_queue_reply(struct ldapsrv_call *call, struct ldapsrv_reply *reply)
     328             : {
     329     1037969 :         NTSTATUS status = ldapsrv_encode(call, reply);
     330             : 
     331     1037969 :         if (!NT_STATUS_IS_OK(status)) {
     332           0 :                 return status;
     333             :         }
     334             : 
     335     1037969 :         if (call->reply_size > call->reply_size + reply->blob.length
     336     1037969 :             || call->reply_size + reply->blob.length > LDAP_SERVER_MAX_REPLY_SIZE) {
     337          10 :                 DBG_WARNING("Refusing to queue LDAP search response size "
     338             :                             "of more than %zu bytes\n",
     339             :                             LDAP_SERVER_MAX_REPLY_SIZE);
     340          10 :                 TALLOC_FREE(reply->blob.data);
     341          10 :                 return NT_STATUS_FILE_TOO_LARGE;
     342             :         }
     343             : 
     344     1037959 :         call->reply_size += reply->blob.length;
     345             : 
     346     1037959 :         DLIST_ADD_END(call->replies, reply);
     347             : 
     348     1037959 :         return status;
     349             : }
     350             : 
     351           0 : static NTSTATUS ldapsrv_unwilling(struct ldapsrv_call *call, int error)
     352             : {
     353           0 :         struct ldapsrv_reply *reply;
     354           0 :         struct ldap_ExtendedResponse *r;
     355             : 
     356           0 :         DBG_DEBUG("type[%d] id[%d]\n", call->request->type, call->request->messageid);
     357             : 
     358           0 :         reply = ldapsrv_init_reply(call, LDAP_TAG_ExtendedResponse);
     359           0 :         if (!reply) {
     360           0 :                 return NT_STATUS_NO_MEMORY;
     361             :         }
     362             : 
     363           0 :         r = &reply->msg->r.ExtendedResponse;
     364           0 :         r->response.resultcode = error;
     365           0 :         r->response.dn = NULL;
     366           0 :         r->response.errormessage = NULL;
     367           0 :         r->response.referral = NULL;
     368           0 :         r->oid = NULL;
     369           0 :         r->value = NULL;
     370             : 
     371           0 :         ldapsrv_queue_reply(call, reply);
     372           0 :         return NT_STATUS_OK;
     373             : }
     374             : 
     375       67773 : static int ldapsrv_add_with_controls(struct ldapsrv_call *call,
     376             :                                      const struct ldb_message *message,
     377             :                                      struct ldb_control **controls,
     378             :                                      struct ldb_result *res)
     379             : {
     380       67773 :         struct ldb_context *ldb = call->conn->ldb;
     381          36 :         struct ldb_request *req;
     382          36 :         int ret;
     383             : 
     384       67773 :         ret = ldb_msg_sanity_check(ldb, message);
     385       67773 :         if (ret != LDB_SUCCESS) {
     386           0 :                 return ret;
     387             :         }
     388             : 
     389       67773 :         ret = ldb_build_add_req(&req, ldb, ldb,
     390             :                                         message,
     391             :                                         controls,
     392             :                                         res,
     393             :                                         ldb_modify_default_callback,
     394             :                                         NULL);
     395             : 
     396       67773 :         if (ret != LDB_SUCCESS) return ret;
     397             : 
     398       67773 :         if (call->conn->global_catalog) {
     399           0 :                 return ldb_error(ldb, LDB_ERR_UNWILLING_TO_PERFORM, "modify forbidden on global catalog port");
     400             :         }
     401       67773 :         ldb_request_add_control(req, DSDB_CONTROL_NO_GLOBAL_CATALOG, false, NULL);
     402             : 
     403       67773 :         ret = ldb_transaction_start(ldb);
     404       67773 :         if (ret != LDB_SUCCESS) {
     405           0 :                 return ret;
     406             :         }
     407             : 
     408       67773 :         if (!call->conn->is_privileged) {
     409       67773 :                 ldb_req_mark_untrusted(req);
     410             :         }
     411             : 
     412       67773 :         LDB_REQ_SET_LOCATION(req);
     413             : 
     414       67773 :         ret = ldb_request(ldb, req);
     415       67773 :         if (ret == LDB_SUCCESS) {
     416       67772 :                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
     417             :         }
     418             : 
     419       67773 :         if (ret == LDB_SUCCESS) {
     420       66810 :                 ret = ldb_transaction_commit(ldb);
     421             :         }
     422             :         else {
     423         963 :                 ldb_transaction_cancel(ldb);
     424             :         }
     425             : 
     426       67773 :         talloc_free(req);
     427       67773 :         return ret;
     428             : }
     429             : 
     430             : /* create and execute a modify request */
     431       86740 : static int ldapsrv_mod_with_controls(struct ldapsrv_call *call,
     432             :                                      const struct ldb_message *message,
     433             :                                      struct ldb_control **controls,
     434             :                                      struct ldb_result *res)
     435             : {
     436       86740 :         struct ldb_context *ldb = call->conn->ldb;
     437         144 :         struct ldb_request *req;
     438         144 :         int ret;
     439             : 
     440       86740 :         ret = ldb_msg_sanity_check(ldb, message);
     441       86740 :         if (ret != LDB_SUCCESS) {
     442           0 :                 return ret;
     443             :         }
     444             : 
     445       86740 :         ret = ldb_build_mod_req(&req, ldb, ldb,
     446             :                                         message,
     447             :                                         controls,
     448             :                                         res,
     449             :                                         ldb_modify_default_callback,
     450             :                                         NULL);
     451             : 
     452       86740 :         if (ret != LDB_SUCCESS) {
     453           0 :                 return ret;
     454             :         }
     455             : 
     456       86740 :         if (call->conn->global_catalog) {
     457           0 :                 return ldb_error(ldb, LDB_ERR_UNWILLING_TO_PERFORM, "modify forbidden on global catalog port");
     458             :         }
     459       86740 :         ldb_request_add_control(req, DSDB_CONTROL_NO_GLOBAL_CATALOG, false, NULL);
     460             : 
     461       86740 :         ret = ldb_transaction_start(ldb);
     462       86740 :         if (ret != LDB_SUCCESS) {
     463           0 :                 return ret;
     464             :         }
     465             : 
     466       86740 :         if (!call->conn->is_privileged) {
     467       86740 :                 ldb_req_mark_untrusted(req);
     468             :         }
     469             : 
     470       86740 :         LDB_REQ_SET_LOCATION(req);
     471             : 
     472       86740 :         ret = ldb_request(ldb, req);
     473       86740 :         if (ret == LDB_SUCCESS) {
     474       84065 :                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
     475             :         }
     476             : 
     477       86740 :         if (ret == LDB_SUCCESS) {
     478       82261 :                 ret = ldb_transaction_commit(ldb);
     479             :         }
     480             :         else {
     481        4479 :                 ldb_transaction_cancel(ldb);
     482             :         }
     483             : 
     484       86740 :         talloc_free(req);
     485       86740 :         return ret;
     486             : }
     487             : 
     488             : /* create and execute a delete request */
     489       75042 : static int ldapsrv_del_with_controls(struct ldapsrv_call *call,
     490             :                                      struct ldb_dn *dn,
     491             :                                      struct ldb_control **controls,
     492             :                                      struct ldb_result *res)
     493             : {
     494       75042 :         struct ldb_context *ldb = call->conn->ldb;
     495          36 :         struct ldb_request *req;
     496          36 :         int ret;
     497             : 
     498       75042 :         ret = ldb_build_del_req(&req, ldb, ldb,
     499             :                                         dn,
     500             :                                         controls,
     501             :                                         res,
     502             :                                         ldb_modify_default_callback,
     503             :                                         NULL);
     504             : 
     505       75042 :         if (ret != LDB_SUCCESS) return ret;
     506             : 
     507       75042 :         if (call->conn->global_catalog) {
     508           0 :                 return ldb_error(ldb, LDB_ERR_UNWILLING_TO_PERFORM, "modify forbidden on global catalog port");
     509             :         }
     510       75042 :         ldb_request_add_control(req, DSDB_CONTROL_NO_GLOBAL_CATALOG, false, NULL);
     511             : 
     512       75042 :         ret = ldb_transaction_start(ldb);
     513       75042 :         if (ret != LDB_SUCCESS) {
     514           0 :                 return ret;
     515             :         }
     516             : 
     517       75042 :         if (!call->conn->is_privileged) {
     518       75042 :                 ldb_req_mark_untrusted(req);
     519             :         }
     520             : 
     521       75042 :         LDB_REQ_SET_LOCATION(req);
     522             : 
     523       75042 :         ret = ldb_request(ldb, req);
     524       75042 :         if (ret == LDB_SUCCESS) {
     525       75027 :                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
     526             :         }
     527             : 
     528       75042 :         if (ret == LDB_SUCCESS) {
     529       37446 :                 ret = ldb_transaction_commit(ldb);
     530             :         }
     531             :         else {
     532       37596 :                 ldb_transaction_cancel(ldb);
     533             :         }
     534             : 
     535       75042 :         talloc_free(req);
     536       75042 :         return ret;
     537             : }
     538             : 
     539         385 : static int ldapsrv_rename_with_controls(struct ldapsrv_call *call,
     540             :                                         struct ldb_dn *olddn,
     541             :                                         struct ldb_dn *newdn,
     542             :                                         struct ldb_control **controls,
     543             :                                         struct ldb_result *res)
     544             : {
     545         385 :         struct ldb_context *ldb = call->conn->ldb;
     546           0 :         struct ldb_request *req;
     547           0 :         int ret;
     548             : 
     549         385 :         ret = ldb_build_rename_req(&req, ldb, ldb,
     550             :                                         olddn,
     551             :                                         newdn,
     552             :                                         controls,
     553             :                                         res,
     554             :                                         ldb_modify_default_callback,
     555             :                                         NULL);
     556             : 
     557         385 :         if (ret != LDB_SUCCESS) return ret;
     558             : 
     559         385 :         if (call->conn->global_catalog) {
     560           0 :                 return ldb_error(ldb, LDB_ERR_UNWILLING_TO_PERFORM, "modify forbidden on global catalog port");
     561             :         }
     562         385 :         ldb_request_add_control(req, DSDB_CONTROL_NO_GLOBAL_CATALOG, false, NULL);
     563             : 
     564         385 :         ret = ldb_transaction_start(ldb);
     565         385 :         if (ret != LDB_SUCCESS) {
     566           0 :                 return ret;
     567             :         }
     568             : 
     569         385 :         if (!call->conn->is_privileged) {
     570         385 :                 ldb_req_mark_untrusted(req);
     571             :         }
     572             : 
     573         385 :         LDB_REQ_SET_LOCATION(req);
     574             : 
     575         385 :         ret = ldb_request(ldb, req);
     576         385 :         if (ret == LDB_SUCCESS) {
     577         385 :                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
     578             :         }
     579             : 
     580         385 :         if (ret == LDB_SUCCESS) {
     581         333 :                 ret = ldb_transaction_commit(ldb);
     582             :         }
     583             :         else {
     584          52 :                 ldb_transaction_cancel(ldb);
     585             :         }
     586             : 
     587         385 :         talloc_free(req);
     588         385 :         return ret;
     589             : }
     590             : 
     591             : 
     592             : 
     593             : struct ldapsrv_context {
     594             :         struct ldapsrv_call *call;
     595             :         int extended_type;
     596             :         bool attributesonly;
     597             :         struct ldb_control **controls;
     598             :         size_t count; /* For notification only */
     599             : };
     600             : 
     601     1138168 : static int ldap_server_search_callback(struct ldb_request *req, struct ldb_reply *ares)
     602             : {
     603     1138168 :         struct ldapsrv_context *ctx = talloc_get_type(req->context, struct ldapsrv_context);
     604     1138168 :         struct ldapsrv_call *call = ctx->call;
     605     1138168 :         struct ldb_context *ldb = call->conn->ldb;
     606         778 :         unsigned int j;
     607     1138168 :         struct ldapsrv_reply *ent_r = NULL;
     608         778 :         struct ldap_SearchResEntry *ent;
     609         778 :         int ret;
     610         778 :         NTSTATUS status;
     611             : 
     612     1138168 :         if (!ares) {
     613           0 :                 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
     614             :         }
     615     1138168 :         if (ares->error != LDB_SUCCESS) {
     616        8285 :                 return ldb_request_done(req, ares->error);
     617             :         }
     618             : 
     619     1129883 :         switch (ares->type) {
     620      635831 :         case LDB_REPLY_ENTRY:
     621             :         {
     622      635831 :                 struct ldb_message *msg = ares->message;
     623      635831 :                 ent_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultEntry);
     624      635831 :                 if (ent_r == NULL) {
     625           0 :                         return ldb_oom(ldb);
     626             :                 }
     627             : 
     628      635831 :                 ctx->count++;
     629             : 
     630             :                 /*
     631             :                  * Put the LDAP search response data under ent_r->msg
     632             :                  * so we can free that later once encoded
     633             :                  */
     634      635831 :                 talloc_steal(ent_r->msg, msg);
     635             : 
     636      635831 :                 ent = &ent_r->msg->r.SearchResultEntry;
     637      635831 :                 ent->dn = ldb_dn_get_extended_linearized(ent_r, msg->dn,
     638             :                                                          ctx->extended_type);
     639      635831 :                 ent->num_attributes = 0;
     640      635831 :                 ent->attributes = NULL;
     641      635831 :                 if (msg->num_elements == 0) {
     642       64093 :                         goto queue_reply;
     643             :                 }
     644      571738 :                 ent->num_attributes = msg->num_elements;
     645      571738 :                 ent->attributes = talloc_array(ent_r, struct ldb_message_element, ent->num_attributes);
     646      571738 :                 if (ent->attributes == NULL) {
     647           0 :                         return ldb_oom(ldb);
     648             :                 }
     649             : 
     650     3659456 :                 for (j=0; j < ent->num_attributes; j++) {
     651     3087718 :                         ent->attributes[j].name = msg->elements[j].name;
     652     3087718 :                         ent->attributes[j].num_values = 0;
     653     3087718 :                         ent->attributes[j].values = NULL;
     654     3087718 :                         if (ctx->attributesonly && (msg->elements[j].num_values == 0)) {
     655           0 :                                 continue;
     656             :                         }
     657     3087718 :                         ent->attributes[j].num_values = msg->elements[j].num_values;
     658     3087718 :                         ent->attributes[j].values = msg->elements[j].values;
     659             :                 }
     660      571738 : queue_reply:
     661      635831 :                 status = ldapsrv_queue_reply(call, ent_r);
     662      635831 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_TOO_LARGE)) {
     663          10 :                         ret = ldb_request_done(req,
     664             :                                                LDB_ERR_SIZE_LIMIT_EXCEEDED);
     665          10 :                         ldb_asprintf_errstring(ldb,
     666             :                                                "LDAP search response size "
     667             :                                                "limited to %zu bytes\n",
     668             :                                                LDAP_SERVER_MAX_REPLY_SIZE);
     669      635821 :                 } else if (!NT_STATUS_IS_OK(status)) {
     670           0 :                         ret = ldb_request_done(req,
     671             :                                                ldb_operr(ldb));
     672             :                 } else {
     673      635450 :                         ret = LDB_SUCCESS;
     674             :                 }
     675      635460 :                 break;
     676             :         }
     677      135521 :         case LDB_REPLY_REFERRAL:
     678             :         {
     679          36 :                 struct ldap_SearchResRef *ent_ref;
     680             : 
     681             :                 /*
     682             :                  * TODO: This should be handled by the notification
     683             :                  * module not here
     684             :                  */
     685      135521 :                 if (call->notification.busy) {
     686           6 :                         ret = LDB_SUCCESS;
     687           6 :                         break;
     688             :                 }
     689             : 
     690      135515 :                 ent_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultReference);
     691      135515 :                 if (ent_r == NULL) {
     692           0 :                         return ldb_oom(ldb);
     693             :                 }
     694             : 
     695             :                 /*
     696             :                  * Put the LDAP referral data under ent_r->msg
     697             :                  * so we can free that later once encoded
     698             :                  */
     699      135515 :                 talloc_steal(ent_r->msg, ares->referral);
     700             : 
     701      135515 :                 ent_ref = &ent_r->msg->r.SearchResultReference;
     702      135515 :                 ent_ref->referral = ares->referral;
     703             : 
     704      135515 :                 status = ldapsrv_queue_reply(call, ent_r);
     705      135515 :                 if (!NT_STATUS_IS_OK(status)) {
     706           0 :                         ret = LDB_ERR_OPERATIONS_ERROR;
     707             :                 } else {
     708      135515 :                         ret = LDB_SUCCESS;
     709             :                 }
     710      135479 :                 break;
     711             :         }
     712      358531 :         case LDB_REPLY_DONE:
     713             :         {
     714             :                 /*
     715             :                  * We don't queue the reply for this one, we let that
     716             :                  * happen outside
     717             :                  */
     718      358531 :                 ctx->controls = talloc_move(ctx, &ares->controls);
     719             : 
     720      358531 :                 TALLOC_FREE(ares);
     721      358531 :                 return ldb_request_done(req, LDB_SUCCESS);
     722             :         }
     723           0 :         default:
     724             :                 /* Doesn't happen */
     725           0 :                 ret = LDB_ERR_OPERATIONS_ERROR;
     726             :         }
     727      771352 :         TALLOC_FREE(ares);
     728             : 
     729      771352 :         return ret;
     730             : }
     731             : 
     732             : 
     733      366827 : static NTSTATUS ldapsrv_SearchRequest(struct ldapsrv_call *call)
     734             : {
     735      366827 :         struct ldap_SearchRequest *req = &call->request->r.SearchRequest;
     736         371 :         struct ldap_Result *done;
     737         371 :         struct ldapsrv_reply *done_r;
     738         371 :         TALLOC_CTX *local_ctx;
     739      366827 :         struct ldapsrv_context *callback_ctx = NULL;
     740      366827 :         struct ldb_context *samdb = talloc_get_type(call->conn->ldb, struct ldb_context);
     741         371 :         struct ldb_dn *basedn;
     742         371 :         struct ldb_request *lreq;
     743         371 :         struct ldb_control *search_control;
     744         371 :         struct ldb_search_options_control *search_options;
     745         371 :         struct ldb_control *extended_dn_control;
     746      366827 :         struct ldb_extended_dn_control *extended_dn_decoded = NULL;
     747      366827 :         struct ldb_control *notification_control = NULL;
     748      366827 :         enum ldb_scope scope = LDB_SCOPE_DEFAULT;
     749      366827 :         const char **attrs = NULL;
     750      366827 :         const char *scope_str, *errstr = NULL;
     751      366827 :         int result = -1;
     752      366827 :         int ldb_ret = -1;
     753         371 :         unsigned int i;
     754      366827 :         int extended_type = 1;
     755             : 
     756             :         /*
     757             :          * Warn for searches that are longer than 1/4 of the
     758             :          * search_timeout, being 30sec by default
     759             :          */
     760      366827 :         struct timeval start_time = timeval_current();
     761         371 :         struct timeval warning_time
     762      366827 :                 = timeval_add(&start_time,
     763      366827 :                               call->conn->limits.search_timeout / 4,
     764             :                               0);
     765             : 
     766      366827 :         local_ctx = talloc_new(call);
     767      366827 :         NT_STATUS_HAVE_NO_MEMORY(local_ctx);
     768             : 
     769      366827 :         basedn = ldb_dn_new(local_ctx, samdb, req->basedn);
     770      366827 :         NT_STATUS_HAVE_NO_MEMORY(basedn);
     771             : 
     772      366827 :         switch (req->scope) {
     773      198960 :         case LDAP_SEARCH_SCOPE_BASE:
     774      198960 :                 scope = LDB_SCOPE_BASE;
     775      198960 :                 break;
     776       78295 :         case LDAP_SEARCH_SCOPE_SINGLE:
     777       78295 :                 scope = LDB_SCOPE_ONELEVEL;
     778       78295 :                 break;
     779       89201 :         case LDAP_SEARCH_SCOPE_SUB:
     780       89201 :                 scope = LDB_SCOPE_SUBTREE;
     781       89201 :                 break;
     782           0 :         default:
     783           0 :                 result = LDAP_PROTOCOL_ERROR;
     784           0 :                 map_ldb_error(local_ctx, LDB_ERR_PROTOCOL_ERROR, NULL,
     785             :                               &errstr);
     786           0 :                 scope_str = "<Invalid scope>";
     787           0 :                 errstr = talloc_asprintf(local_ctx,
     788             :                                          "%s. Invalid scope", errstr);
     789           0 :                 goto reply;
     790             :         }
     791      366827 :         scope_str = dsdb_search_scope_as_string(scope);
     792             : 
     793      366827 :         DBG_DEBUG("scope: [%s]\n", scope_str);
     794             : 
     795      366827 :         if (req->num_attributes >= 1) {
     796      294347 :                 attrs = talloc_array(local_ctx, const char *, req->num_attributes+1);
     797      294347 :                 NT_STATUS_HAVE_NO_MEMORY(attrs);
     798             : 
     799      923933 :                 for (i=0; i < req->num_attributes; i++) {
     800      629586 :                         DBG_DEBUG("attrs: [%s]\n",req->attributes[i]);
     801      629586 :                         attrs[i] = req->attributes[i];
     802             :                 }
     803      294347 :                 attrs[i] = NULL;
     804             :         }
     805             : 
     806      366827 :         DBG_INFO("ldb_request %s dn=%s filter=%s\n",
     807             :                  scope_str, req->basedn, ldb_filter_from_tree(call, req->tree));
     808             : 
     809      366827 :         callback_ctx = talloc_zero(local_ctx, struct ldapsrv_context);
     810      366827 :         NT_STATUS_HAVE_NO_MEMORY(callback_ctx);
     811      366827 :         callback_ctx->call = call;
     812      366827 :         callback_ctx->extended_type = extended_type;
     813      366827 :         callback_ctx->attributesonly = req->attributesonly;
     814             : 
     815      367198 :         ldb_ret = ldb_build_search_req_ex(&lreq, samdb, local_ctx,
     816             :                                           basedn, scope,
     817             :                                           req->tree, attrs,
     818      366827 :                                           call->request->controls,
     819             :                                           callback_ctx,
     820             :                                           ldap_server_search_callback,
     821             :                                           NULL);
     822             : 
     823      366827 :         if (ldb_ret != LDB_SUCCESS) {
     824           0 :                 goto reply;
     825             :         }
     826             : 
     827      366827 :         if (call->conn->global_catalog) {
     828          23 :                 search_control = ldb_request_get_control(lreq, LDB_CONTROL_SEARCH_OPTIONS_OID);
     829             : 
     830          23 :                 search_options = NULL;
     831          23 :                 if (search_control) {
     832           2 :                         search_options = talloc_get_type(search_control->data, struct ldb_search_options_control);
     833           2 :                         search_options->search_options |= LDB_SEARCH_OPTION_PHANTOM_ROOT;
     834             :                 } else {
     835          21 :                         search_options = talloc(lreq, struct ldb_search_options_control);
     836          21 :                         NT_STATUS_HAVE_NO_MEMORY(search_options);
     837          21 :                         search_options->search_options = LDB_SEARCH_OPTION_PHANTOM_ROOT;
     838          21 :                         ldb_request_add_control(lreq, LDB_CONTROL_SEARCH_OPTIONS_OID, false, search_options);
     839             :                 }
     840             :         } else {
     841      366804 :                 ldb_request_add_control(lreq, DSDB_CONTROL_NO_GLOBAL_CATALOG, false, NULL);
     842             :         }
     843             : 
     844      366827 :         extended_dn_control = ldb_request_get_control(lreq, LDB_CONTROL_EXTENDED_DN_OID);
     845             : 
     846      366827 :         if (extended_dn_control) {
     847       16263 :                 if (extended_dn_control->data) {
     848       16127 :                         extended_dn_decoded = talloc_get_type(extended_dn_control->data, struct ldb_extended_dn_control);
     849       16127 :                         extended_type = extended_dn_decoded->type;
     850             :                 } else {
     851         136 :                         extended_type = 0;
     852             :                 }
     853       16263 :                 callback_ctx->extended_type = extended_type;
     854             :         }
     855             : 
     856      366827 :         notification_control = ldb_request_get_control(lreq, LDB_CONTROL_NOTIFICATION_OID);
     857      366827 :         if (notification_control != NULL) {
     858        1424 :                 const struct ldapsrv_call *pc = NULL;
     859        1424 :                 size_t count = 0;
     860             : 
     861        1441 :                 for (pc = call->conn->pending_calls; pc != NULL; pc = pc->next) {
     862          17 :                         count += 1;
     863             :                 }
     864             : 
     865        1424 :                 if (count >= call->conn->limits.max_notifications) {
     866           1 :                         DBG_DEBUG("error MaxNotificationPerConn\n");
     867           1 :                         result = map_ldb_error(local_ctx,
     868             :                                                LDB_ERR_ADMIN_LIMIT_EXCEEDED,
     869             :                                                "MaxNotificationPerConn reached",
     870             :                                                &errstr);
     871           1 :                         goto reply;
     872             :                 }
     873             : 
     874             :                 /*
     875             :                  * For now we need to do periodic retries on our own.
     876             :                  * As the dsdb_notification module will return after each run.
     877             :                  */
     878        1423 :                 call->notification.busy = true;
     879             :         }
     880             : 
     881             :         {
     882      366826 :                 const char *scheme = NULL;
     883      366826 :                 switch (call->conn->referral_scheme) {
     884         766 :                 case LDAP_REFERRAL_SCHEME_LDAPS:
     885         766 :                         scheme = "ldaps";
     886         766 :                         break;
     887      366060 :                 default:
     888      366060 :                         scheme = "ldap";
     889             :                 }
     890      366826 :                 ldb_ret = ldb_set_opaque(
     891             :                         samdb,
     892             :                         LDAP_REFERRAL_SCHEME_OPAQUE,
     893             :                         discard_const_p(char *, scheme));
     894      366826 :                 if (ldb_ret != LDB_SUCCESS) {
     895           0 :                         goto reply;
     896             :                 }
     897             :         }
     898             : 
     899             :         {
     900      366826 :                 time_t timeout = call->conn->limits.search_timeout;
     901             : 
     902      366826 :                 if (timeout == 0
     903      366826 :                     || (req->timelimit != 0
     904        1872 :                         && req->timelimit < timeout))
     905             :                 {
     906        1872 :                         timeout = req->timelimit;
     907             :                 }
     908      366826 :                 ldb_set_timeout(samdb, lreq, timeout);
     909             :         }
     910             : 
     911      366826 :         if (!call->conn->is_privileged) {
     912      361929 :                 ldb_req_mark_untrusted(lreq);
     913             :         }
     914             : 
     915      366826 :         LDB_REQ_SET_LOCATION(lreq);
     916             : 
     917      366826 :         ldb_ret = ldb_request(samdb, lreq);
     918             : 
     919      366826 :         if (ldb_ret != LDB_SUCCESS) {
     920        4569 :                 goto reply;
     921             :         }
     922             : 
     923      362257 :         ldb_ret = ldb_wait(lreq->handle, LDB_WAIT_ALL);
     924             : 
     925      362257 :         if (ldb_ret == LDB_SUCCESS) {
     926      358531 :                 if (call->notification.busy) {
     927             :                         /* Move/Add it to the end */
     928          81 :                         DLIST_DEMOTE(call->conn->pending_calls, call);
     929          81 :                         call->notification.generation =
     930          81 :                                 call->conn->service->notification.generation;
     931             : 
     932          81 :                         if (callback_ctx->count != 0) {
     933           1 :                                 call->notification.generation += 1;
     934           1 :                                 ldapsrv_notification_retry_setup(call->conn->service,
     935             :                                                                  true);
     936             :                         }
     937             : 
     938          81 :                         talloc_free(local_ctx);
     939          81 :                         return NT_STATUS_OK;
     940             :                 }
     941             :         }
     942             : 
     943      362176 : reply:
     944             : 
     945             :         /*
     946             :          * This looks like duplicated code - because it is - but
     947             :          * otherwise the work in the parameters will be done
     948             :          * regardless, this way the functions only execute when the
     949             :          * log level is set.
     950             :          *
     951             :          * The basedn is re-obtained as a string to escape it
     952             :          */
     953      366746 :         if ((req->timelimit == 0 || call->conn->limits.search_timeout < req->timelimit)
     954      364879 :             && ldb_ret == LDB_ERR_TIME_LIMIT_EXCEEDED) {
     955           0 :                 struct dom_sid_buf sid_buf;
     956           5 :                 DBG_WARNING("MaxQueryDuration(%d) timeout exceeded "
     957             :                             "in SearchRequest by %s from %s filter: [%s] "
     958             :                             "basedn: [%s] "
     959             :                             "scope: [%s]\n",
     960             :                             call->conn->limits.search_timeout,
     961             :                             dom_sid_str_buf(&call->conn->session_info->security_token->sids[0],
     962             :                                             &sid_buf),
     963             :                             tsocket_address_string(call->conn->connection->remote_address,
     964             :                                                    call),
     965             :                             ldb_filter_from_tree(call, req->tree),
     966             :                             ldb_dn_get_extended_linearized(call, basedn, 1),
     967             :                             scope_str);
     968          10 :                 for (i=0; i < req->num_attributes; i++) {
     969           5 :                         DBG_WARNING("MaxQueryDuration timeout exceeded attrs: [%s]\n",
     970             :                                     req->attributes[i]);
     971             :                 }
     972             : 
     973      366741 :         } else if (timeval_expired(&warning_time)) {
     974           0 :                 struct dom_sid_buf sid_buf;
     975           0 :                 DBG_NOTICE("Long LDAP Query: Duration was %.2fs, "
     976             :                            "MaxQueryDuration(%d)/4 == %d "
     977             :                            "in SearchRequest by %s from %s filter: [%s] "
     978             :                            "basedn: [%s] "
     979             :                            "scope: [%s] "
     980             :                            "result: %s\n",
     981             :                            timeval_elapsed(&start_time),
     982             :                            call->conn->limits.search_timeout,
     983             :                            call->conn->limits.search_timeout / 4,
     984             :                            dom_sid_str_buf(&call->conn->session_info->security_token->sids[0],
     985             :                                            &sid_buf),
     986             :                            tsocket_address_string(call->conn->connection->remote_address,
     987             :                                                   call),
     988             :                            ldb_filter_from_tree(call, req->tree),
     989             :                            ldb_dn_get_extended_linearized(call, basedn, 1),
     990             :                            scope_str,
     991             :                            ldb_strerror(ldb_ret));
     992           0 :                 for (i=0; i < req->num_attributes; i++) {
     993           0 :                         DBG_NOTICE("Long LDAP Query attrs: [%s]\n",
     994             :                                    req->attributes[i]);
     995             :                 }
     996             :         } else {
     997         371 :                 struct dom_sid_buf sid_buf;
     998      366741 :                 DBG_INFO("LDAP Query: Duration was %.2fs, "
     999             :                          "SearchRequest by %s from %s filter: [%s] "
    1000             :                          "basedn: [%s] "
    1001             :                          "scope: [%s] "
    1002             :                          "result: %s\n",
    1003             :                          timeval_elapsed(&start_time),
    1004             :                          dom_sid_str_buf(&call->conn->session_info->security_token->sids[0],
    1005             :                                          &sid_buf),
    1006             :                          tsocket_address_string(call->conn->connection->remote_address,
    1007             :                                                 call),
    1008             :                          ldb_filter_from_tree(call, req->tree),
    1009             :                          ldb_dn_get_extended_linearized(call, basedn, 1),
    1010             :                          scope_str,
    1011             :                          ldb_strerror(ldb_ret));
    1012             :         }
    1013             : 
    1014      366746 :         DLIST_REMOVE(call->conn->pending_calls, call);
    1015      366746 :         call->notification.busy = false;
    1016             : 
    1017      366746 :         done_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultDone);
    1018      366746 :         NT_STATUS_HAVE_NO_MEMORY(done_r);
    1019             : 
    1020      366746 :         done = &done_r->msg->r.SearchResultDone;
    1021      366746 :         done->dn = NULL;
    1022      366746 :         done->referral = NULL;
    1023             : 
    1024      366746 :         if (result != -1) {
    1025      366745 :         } else if (ldb_ret == LDB_SUCCESS) {
    1026      358450 :                 if (callback_ctx->controls) {
    1027      121282 :                         done_r->msg->controls = callback_ctx->controls;
    1028      121282 :                         talloc_steal(done_r->msg, callback_ctx->controls);
    1029             :                 }
    1030      358079 :                 result = LDB_SUCCESS;
    1031             :         } else {
    1032        8295 :                 DBG_DEBUG("error\n");
    1033        8295 :                 result = map_ldb_error(local_ctx, ldb_ret, ldb_errstring(samdb),
    1034             :                                        &errstr);
    1035             :         }
    1036             : 
    1037      366746 :         done->resultcode = result;
    1038      366746 :         done->errormessage = (errstr?talloc_strdup(done_r, errstr):NULL);
    1039             : 
    1040      366746 :         talloc_free(local_ctx);
    1041             : 
    1042      366746 :         return ldapsrv_queue_reply_forced(call, done_r);
    1043             : }
    1044             : 
    1045       86740 : static NTSTATUS ldapsrv_ModifyRequest(struct ldapsrv_call *call)
    1046             : {
    1047       86740 :         struct ldap_ModifyRequest *req = &call->request->r.ModifyRequest;
    1048         144 :         struct ldap_Result *modify_result;
    1049         144 :         struct ldapsrv_reply *modify_reply;
    1050         144 :         TALLOC_CTX *local_ctx;
    1051       86740 :         struct ldb_context *samdb = call->conn->ldb;
    1052       86740 :         struct ldb_message *msg = NULL;
    1053         144 :         struct ldb_dn *dn;
    1054       86740 :         const char *errstr = NULL;
    1055       86740 :         int result = LDAP_SUCCESS;
    1056         144 :         int ldb_ret;
    1057         144 :         unsigned int i,j;
    1058       86740 :         struct ldb_result *res = NULL;
    1059             : 
    1060       86740 :         DBG_DEBUG("dn: %s\n", req->dn);
    1061             : 
    1062       86740 :         local_ctx = talloc_named(call, 0, "ModifyRequest local memory context");
    1063       86740 :         NT_STATUS_HAVE_NO_MEMORY(local_ctx);
    1064             : 
    1065       86740 :         dn = ldb_dn_new(local_ctx, samdb, req->dn);
    1066       86740 :         NT_STATUS_HAVE_NO_MEMORY(dn);
    1067             : 
    1068       86740 :         DBG_DEBUG("dn: [%s]\n", req->dn);
    1069             : 
    1070       86740 :         msg = ldb_msg_new(local_ctx);
    1071       86740 :         NT_STATUS_HAVE_NO_MEMORY(msg);
    1072             : 
    1073       86740 :         msg->dn = dn;
    1074             : 
    1075       86740 :         if (req->num_mods > 0) {
    1076       86733 :                 msg->num_elements = req->num_mods;
    1077       86733 :                 msg->elements = talloc_array(msg, struct ldb_message_element, req->num_mods);
    1078       86733 :                 NT_STATUS_HAVE_NO_MEMORY(msg->elements);
    1079             : 
    1080      200200 :                 for (i=0; i < msg->num_elements; i++) {
    1081      113467 :                         msg->elements[i].name = discard_const_p(char, req->mods[i].attrib.name);
    1082      113467 :                         msg->elements[i].num_values = 0;
    1083      113467 :                         msg->elements[i].values = NULL;
    1084             : 
    1085      113467 :                         switch (req->mods[i].type) {
    1086           0 :                         default:
    1087           0 :                                 result = LDAP_PROTOCOL_ERROR;
    1088           0 :                                 map_ldb_error(local_ctx,
    1089             :                                         LDB_ERR_PROTOCOL_ERROR, NULL, &errstr);
    1090           0 :                                 errstr = talloc_asprintf(local_ctx,
    1091             :                                         "%s. Invalid LDAP_MODIFY_* type", errstr);
    1092           0 :                                 goto reply;
    1093       31722 :                         case LDAP_MODIFY_ADD:
    1094       31722 :                                 msg->elements[i].flags = LDB_FLAG_MOD_ADD;
    1095       31722 :                                 break;
    1096       21527 :                         case LDAP_MODIFY_DELETE:
    1097       21527 :                                 msg->elements[i].flags = LDB_FLAG_MOD_DELETE;
    1098       21527 :                                 break;
    1099       60218 :                         case LDAP_MODIFY_REPLACE:
    1100       60218 :                                 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
    1101       60218 :                                 break;
    1102             :                         }
    1103             : 
    1104      113467 :                         msg->elements[i].num_values = req->mods[i].attrib.num_values;
    1105      113467 :                         if (msg->elements[i].num_values > 0) {
    1106      107352 :                                 msg->elements[i].values = talloc_array(msg->elements, struct ldb_val,
    1107             :                                                                        msg->elements[i].num_values);
    1108      107352 :                                 NT_STATUS_HAVE_NO_MEMORY(msg->elements[i].values);
    1109             : 
    1110      222307 :                                 for (j=0; j < msg->elements[i].num_values; j++) {
    1111      114955 :                                         msg->elements[i].values[j].length = req->mods[i].attrib.values[j].length;
    1112      114955 :                                         msg->elements[i].values[j].data = req->mods[i].attrib.values[j].data;
    1113             :                                 }
    1114             :                         }
    1115             :                 }
    1116             :         }
    1117             : 
    1118       86740 : reply:
    1119       86740 :         modify_reply = ldapsrv_init_reply(call, LDAP_TAG_ModifyResponse);
    1120       86740 :         NT_STATUS_HAVE_NO_MEMORY(modify_reply);
    1121             : 
    1122       86740 :         if (result == LDAP_SUCCESS) {
    1123       86740 :                 res = talloc_zero(local_ctx, struct ldb_result);
    1124       86740 :                 NT_STATUS_HAVE_NO_MEMORY(res);
    1125       86740 :                 ldb_ret = ldapsrv_mod_with_controls(call, msg, call->request->controls, res);
    1126       86740 :                 result = map_ldb_error(local_ctx, ldb_ret, ldb_errstring(samdb),
    1127             :                                        &errstr);
    1128             :         }
    1129             : 
    1130       86740 :         modify_result = &modify_reply->msg->r.ModifyResponse;
    1131       86740 :         modify_result->dn = NULL;
    1132       86740 :         if ((res != NULL) && (res->refs != NULL)) {
    1133           2 :                 modify_result->resultcode = map_ldb_error(local_ctx,
    1134             :                                                           LDB_ERR_REFERRAL,
    1135             :                                                           NULL, &errstr);
    1136           2 :                 modify_result->errormessage = (errstr?talloc_strdup(modify_reply, errstr):NULL);
    1137           2 :                 modify_result->referral = talloc_strdup(call, *res->refs);
    1138             :         } else {
    1139       86738 :                 modify_result->resultcode = result;
    1140       86738 :                 modify_result->errormessage = (errstr?talloc_strdup(modify_reply, errstr):NULL);
    1141       86738 :                 modify_result->referral = NULL;
    1142             :         }
    1143       86740 :         talloc_free(local_ctx);
    1144             : 
    1145       86740 :         return ldapsrv_queue_reply(call, modify_reply);
    1146             : 
    1147             : }
    1148             : 
    1149       67773 : static NTSTATUS ldapsrv_AddRequest(struct ldapsrv_call *call)
    1150             : {
    1151       67773 :         struct ldap_AddRequest *req = &call->request->r.AddRequest;
    1152          36 :         struct ldap_Result *add_result;
    1153          36 :         struct ldapsrv_reply *add_reply;
    1154          36 :         TALLOC_CTX *local_ctx;
    1155       67773 :         struct ldb_context *samdb = call->conn->ldb;
    1156       67773 :         struct ldb_message *msg = NULL;
    1157          36 :         struct ldb_dn *dn;
    1158       67773 :         const char *errstr = NULL;
    1159       67773 :         int result = LDAP_SUCCESS;
    1160          36 :         int ldb_ret;
    1161          36 :         unsigned int i,j;
    1162       67773 :         struct ldb_result *res = NULL;
    1163             : 
    1164       67773 :         DBG_DEBUG("dn: %s\n", req->dn);
    1165             : 
    1166       67773 :         local_ctx = talloc_named(call, 0, "AddRequest local memory context");
    1167       67773 :         NT_STATUS_HAVE_NO_MEMORY(local_ctx);
    1168             : 
    1169       67773 :         dn = ldb_dn_new(local_ctx, samdb, req->dn);
    1170       67773 :         NT_STATUS_HAVE_NO_MEMORY(dn);
    1171             : 
    1172       67773 :         DBG_DEBUG("dn: [%s]\n", req->dn);
    1173             : 
    1174       67773 :         msg = talloc(local_ctx, struct ldb_message);
    1175       67773 :         NT_STATUS_HAVE_NO_MEMORY(msg);
    1176             : 
    1177       67773 :         msg->dn = dn;
    1178       67773 :         msg->num_elements = 0;
    1179       67773 :         msg->elements = NULL;
    1180             : 
    1181       67773 :         if (req->num_attributes > 0) {
    1182       67770 :                 msg->num_elements = req->num_attributes;
    1183       67770 :                 msg->elements = talloc_array(msg, struct ldb_message_element, msg->num_elements);
    1184       67770 :                 NT_STATUS_HAVE_NO_MEMORY(msg->elements);
    1185             : 
    1186      254313 :                 for (i=0; i < msg->num_elements; i++) {
    1187      186543 :                         msg->elements[i].name = discard_const_p(char, req->attributes[i].name);
    1188      186543 :                         msg->elements[i].flags = 0;
    1189      186543 :                         msg->elements[i].num_values = 0;
    1190      186543 :                         msg->elements[i].values = NULL;
    1191             : 
    1192      186543 :                         if (req->attributes[i].num_values > 0) {
    1193      186498 :                                 msg->elements[i].num_values = req->attributes[i].num_values;
    1194      186498 :                                 msg->elements[i].values = talloc_array(msg->elements, struct ldb_val,
    1195             :                                                                        msg->elements[i].num_values);
    1196      186498 :                                 NT_STATUS_HAVE_NO_MEMORY(msg->elements[i].values);
    1197             : 
    1198      378262 :                                 for (j=0; j < msg->elements[i].num_values; j++) {
    1199      191764 :                                         msg->elements[i].values[j].length = req->attributes[i].values[j].length;
    1200      191764 :                                         msg->elements[i].values[j].data = req->attributes[i].values[j].data;
    1201             :                                 }
    1202             :                         }
    1203             :                 }
    1204             :         }
    1205             : 
    1206       67773 :         add_reply = ldapsrv_init_reply(call, LDAP_TAG_AddResponse);
    1207       67773 :         NT_STATUS_HAVE_NO_MEMORY(add_reply);
    1208             : 
    1209       67773 :         if (result == LDAP_SUCCESS) {
    1210       67773 :                 res = talloc_zero(local_ctx, struct ldb_result);
    1211       67773 :                 NT_STATUS_HAVE_NO_MEMORY(res);
    1212       67773 :                 ldb_ret = ldapsrv_add_with_controls(call, msg, call->request->controls, res);
    1213       67773 :                 result = map_ldb_error(local_ctx, ldb_ret, ldb_errstring(samdb),
    1214             :                                        &errstr);
    1215             :         }
    1216             : 
    1217       67773 :         add_result = &add_reply->msg->r.AddResponse;
    1218       67773 :         add_result->dn = NULL;
    1219       67773 :         if ((res != NULL) && (res->refs != NULL)) {
    1220           5 :                 add_result->resultcode =  map_ldb_error(local_ctx,
    1221             :                                                         LDB_ERR_REFERRAL, NULL,
    1222             :                                                         &errstr);
    1223           5 :                 add_result->errormessage = (errstr?talloc_strdup(add_reply,errstr):NULL);
    1224           5 :                 add_result->referral = talloc_strdup(call, *res->refs);
    1225             :         } else {
    1226       67768 :                 add_result->resultcode = result;
    1227       67768 :                 add_result->errormessage = (errstr?talloc_strdup(add_reply,errstr):NULL);
    1228       67768 :                 add_result->referral = NULL;
    1229             :         }
    1230       67773 :         talloc_free(local_ctx);
    1231             : 
    1232       67773 :         return ldapsrv_queue_reply(call, add_reply);
    1233             : 
    1234             : }
    1235             : 
    1236       75042 : static NTSTATUS ldapsrv_DelRequest(struct ldapsrv_call *call)
    1237             : {
    1238       75042 :         struct ldap_DelRequest *req = &call->request->r.DelRequest;
    1239          36 :         struct ldap_Result *del_result;
    1240          36 :         struct ldapsrv_reply *del_reply;
    1241          36 :         TALLOC_CTX *local_ctx;
    1242       75042 :         struct ldb_context *samdb = call->conn->ldb;
    1243          36 :         struct ldb_dn *dn;
    1244       75042 :         const char *errstr = NULL;
    1245       75042 :         int result = LDAP_SUCCESS;
    1246          36 :         int ldb_ret;
    1247       75042 :         struct ldb_result *res = NULL;
    1248             : 
    1249       75042 :         DBG_DEBUG("dn: %s\n", req->dn);
    1250             : 
    1251       75042 :         local_ctx = talloc_named(call, 0, "DelRequest local memory context");
    1252       75042 :         NT_STATUS_HAVE_NO_MEMORY(local_ctx);
    1253             : 
    1254       75042 :         dn = ldb_dn_new(local_ctx, samdb, req->dn);
    1255       75042 :         NT_STATUS_HAVE_NO_MEMORY(dn);
    1256             : 
    1257       75042 :         DBG_DEBUG("dn: [%s]\n", req->dn);
    1258             : 
    1259       75042 :         del_reply = ldapsrv_init_reply(call, LDAP_TAG_DelResponse);
    1260       75042 :         NT_STATUS_HAVE_NO_MEMORY(del_reply);
    1261             : 
    1262       75042 :         if (result == LDAP_SUCCESS) {
    1263       75042 :                 res = talloc_zero(local_ctx, struct ldb_result);
    1264       75042 :                 NT_STATUS_HAVE_NO_MEMORY(res);
    1265       75042 :                 ldb_ret = ldapsrv_del_with_controls(call, dn, call->request->controls, res);
    1266       75042 :                 result = map_ldb_error(local_ctx, ldb_ret, ldb_errstring(samdb),
    1267             :                                        &errstr);
    1268             :         }
    1269             : 
    1270       75042 :         del_result = &del_reply->msg->r.DelResponse;
    1271       75042 :         del_result->dn = NULL;
    1272       75042 :         if ((res != NULL) && (res->refs != NULL)) {
    1273           1 :                 del_result->resultcode = map_ldb_error(local_ctx,
    1274             :                                                        LDB_ERR_REFERRAL, NULL,
    1275             :                                                        &errstr);
    1276           1 :                 del_result->errormessage = (errstr?talloc_strdup(del_reply,errstr):NULL);
    1277           1 :                 del_result->referral = talloc_strdup(call, *res->refs);
    1278             :         } else {
    1279       75041 :                 del_result->resultcode = result;
    1280       75041 :                 del_result->errormessage = (errstr?talloc_strdup(del_reply,errstr):NULL);
    1281       75041 :                 del_result->referral = NULL;
    1282             :         }
    1283             : 
    1284       75042 :         talloc_free(local_ctx);
    1285             : 
    1286       75042 :         return ldapsrv_queue_reply(call, del_reply);
    1287             : }
    1288             : 
    1289         388 : static NTSTATUS ldapsrv_ModifyDNRequest(struct ldapsrv_call *call)
    1290             : {
    1291         388 :         struct ldap_ModifyDNRequest *req = &call->request->r.ModifyDNRequest;
    1292           0 :         struct ldap_Result *modifydn;
    1293           0 :         struct ldapsrv_reply *modifydn_r;
    1294           0 :         TALLOC_CTX *local_ctx;
    1295         388 :         struct ldb_context *samdb = call->conn->ldb;
    1296         388 :         struct ldb_dn *olddn, *newdn=NULL, *newrdn;
    1297         388 :         struct ldb_dn *parentdn = NULL;
    1298         388 :         const char *errstr = NULL;
    1299         388 :         int result = LDAP_SUCCESS;
    1300           0 :         int ldb_ret;
    1301         388 :         struct ldb_result *res = NULL;
    1302             : 
    1303         388 :         DBG_DEBUG("dn: %s newrdn: %s\n",
    1304             :                   req->dn, req->newrdn);
    1305             : 
    1306         388 :         local_ctx = talloc_named(call, 0, "ModifyDNRequest local memory context");
    1307         388 :         NT_STATUS_HAVE_NO_MEMORY(local_ctx);
    1308             : 
    1309         388 :         olddn = ldb_dn_new(local_ctx, samdb, req->dn);
    1310         388 :         NT_STATUS_HAVE_NO_MEMORY(olddn);
    1311             : 
    1312         388 :         newrdn = ldb_dn_new(local_ctx, samdb, req->newrdn);
    1313         388 :         NT_STATUS_HAVE_NO_MEMORY(newrdn);
    1314             : 
    1315         388 :         DBG_DEBUG("olddn: [%s] newrdn: [%s]\n",
    1316             :                   req->dn, req->newrdn);
    1317             : 
    1318         388 :         if (ldb_dn_get_comp_num(newrdn) == 0) {
    1319           1 :                 result = LDAP_PROTOCOL_ERROR;
    1320           1 :                 map_ldb_error(local_ctx, LDB_ERR_PROTOCOL_ERROR, NULL,
    1321             :                               &errstr);
    1322           1 :                 goto reply;
    1323             :         }
    1324             : 
    1325         387 :         if (ldb_dn_get_comp_num(newrdn) > 1) {
    1326           1 :                 result = LDAP_NAMING_VIOLATION;
    1327           1 :                 map_ldb_error(local_ctx, LDB_ERR_NAMING_VIOLATION, NULL,
    1328             :                               &errstr);
    1329           1 :                 goto reply;
    1330             :         }
    1331             : 
    1332             :         /* we can't handle the rename if we should not remove the old dn */
    1333         386 :         if (!req->deleteolddn) {
    1334           0 :                 result = LDAP_UNWILLING_TO_PERFORM;
    1335           0 :                 map_ldb_error(local_ctx, LDB_ERR_UNWILLING_TO_PERFORM, NULL,
    1336             :                               &errstr);
    1337           0 :                 errstr = talloc_asprintf(local_ctx,
    1338             :                         "%s. Old RDN must be deleted", errstr);
    1339           0 :                 goto reply;
    1340             :         }
    1341             : 
    1342         386 :         if (req->newsuperior) {
    1343         384 :                 DBG_DEBUG("newsuperior: [%s]\n", req->newsuperior);
    1344         384 :                 parentdn = ldb_dn_new(local_ctx, samdb, req->newsuperior);
    1345             :         }
    1346             : 
    1347         386 :         if (!parentdn) {
    1348           2 :                 parentdn = ldb_dn_get_parent(local_ctx, olddn);
    1349             :         }
    1350         386 :         if (!parentdn) {
    1351           1 :                 result = LDAP_NO_SUCH_OBJECT;
    1352           1 :                 map_ldb_error(local_ctx, LDB_ERR_NO_SUCH_OBJECT, NULL, &errstr);
    1353           1 :                 goto reply;
    1354             :         }
    1355             : 
    1356         385 :         if ( ! ldb_dn_add_child(parentdn, newrdn)) {
    1357           0 :                 result = LDAP_OTHER;
    1358           0 :                 map_ldb_error(local_ctx, LDB_ERR_OTHER, NULL, &errstr);
    1359           0 :                 goto reply;
    1360             :         }
    1361         385 :         newdn = parentdn;
    1362             : 
    1363         388 : reply:
    1364         388 :         modifydn_r = ldapsrv_init_reply(call, LDAP_TAG_ModifyDNResponse);
    1365         388 :         NT_STATUS_HAVE_NO_MEMORY(modifydn_r);
    1366             : 
    1367         388 :         if (result == LDAP_SUCCESS) {
    1368         385 :                 res = talloc_zero(local_ctx, struct ldb_result);
    1369         385 :                 NT_STATUS_HAVE_NO_MEMORY(res);
    1370         385 :                 ldb_ret = ldapsrv_rename_with_controls(call, olddn, newdn, call->request->controls, res);
    1371         385 :                 result = map_ldb_error(local_ctx, ldb_ret, ldb_errstring(samdb),
    1372             :                                        &errstr);
    1373             :         }
    1374             : 
    1375         388 :         modifydn = &modifydn_r->msg->r.ModifyDNResponse;
    1376         388 :         modifydn->dn = NULL;
    1377         388 :         if ((res != NULL) && (res->refs != NULL)) {
    1378           0 :                 modifydn->resultcode = map_ldb_error(local_ctx,
    1379             :                                                      LDB_ERR_REFERRAL, NULL,
    1380           0 :                                                      &errstr);;
    1381           0 :                 modifydn->errormessage = (errstr?talloc_strdup(modifydn_r,errstr):NULL);
    1382           0 :                 modifydn->referral = talloc_strdup(call, *res->refs);
    1383             :         } else {
    1384         388 :                 modifydn->resultcode = result;
    1385         388 :                 modifydn->errormessage = (errstr?talloc_strdup(modifydn_r,errstr):NULL);
    1386         388 :                 modifydn->referral = NULL;
    1387             :         }
    1388             : 
    1389         388 :         talloc_free(local_ctx);
    1390             : 
    1391         388 :         return ldapsrv_queue_reply(call, modifydn_r);
    1392             : }
    1393             : 
    1394           1 : static NTSTATUS ldapsrv_CompareRequest(struct ldapsrv_call *call)
    1395             : {
    1396           1 :         struct ldap_CompareRequest *req = &call->request->r.CompareRequest;
    1397           0 :         struct ldap_Result *compare;
    1398           0 :         struct ldapsrv_reply *compare_r;
    1399           0 :         TALLOC_CTX *local_ctx;
    1400           1 :         struct ldb_context *samdb = call->conn->ldb;
    1401           1 :         struct ldb_result *res = NULL;
    1402           0 :         struct ldb_dn *dn;
    1403           0 :         const char *attrs[1];
    1404           1 :         const char *errstr = NULL;
    1405           1 :         const char *filter = NULL;
    1406           1 :         int result = LDAP_SUCCESS;
    1407           0 :         int ldb_ret;
    1408             : 
    1409           1 :         DBG_DEBUG("dn: %s\n", req->dn);
    1410             : 
    1411           1 :         local_ctx = talloc_named(call, 0, "CompareRequest local_memory_context");
    1412           1 :         NT_STATUS_HAVE_NO_MEMORY(local_ctx);
    1413             : 
    1414           1 :         dn = ldb_dn_new(local_ctx, samdb, req->dn);
    1415           1 :         NT_STATUS_HAVE_NO_MEMORY(dn);
    1416             : 
    1417           1 :         DBG_DEBUG("dn: [%s]\n", req->dn);
    1418           1 :         filter = talloc_asprintf(local_ctx, "(%s=%*s)", req->attribute,
    1419           1 :                                  (int)req->value.length, req->value.data);
    1420           1 :         NT_STATUS_HAVE_NO_MEMORY(filter);
    1421             : 
    1422           1 :         DBG_DEBUG("attribute: [%s]\n", filter);
    1423             : 
    1424           1 :         attrs[0] = NULL;
    1425             : 
    1426           1 :         compare_r = ldapsrv_init_reply(call, LDAP_TAG_CompareResponse);
    1427           1 :         NT_STATUS_HAVE_NO_MEMORY(compare_r);
    1428             : 
    1429           1 :         if (result == LDAP_SUCCESS) {
    1430           1 :                 ldb_ret = ldb_search(samdb, local_ctx, &res,
    1431             :                                      dn, LDB_SCOPE_BASE, attrs, "%s", filter);
    1432           1 :                 if (ldb_ret != LDB_SUCCESS) {
    1433           0 :                         result = map_ldb_error(local_ctx, ldb_ret,
    1434             :                                                ldb_errstring(samdb), &errstr);
    1435           0 :                         DBG_DEBUG("error: %s\n", errstr);
    1436           1 :                 } else if (res->count == 0) {
    1437           0 :                         DBG_DEBUG("didn't match\n");
    1438           0 :                         result = LDAP_COMPARE_FALSE;
    1439           0 :                         errstr = NULL;
    1440           1 :                 } else if (res->count == 1) {
    1441           1 :                         DBG_DEBUG("matched\n");
    1442           1 :                         result = LDAP_COMPARE_TRUE;
    1443           1 :                         errstr = NULL;
    1444           0 :                 } else if (res->count > 1) {
    1445           0 :                         result = LDAP_OTHER;
    1446           0 :                         map_ldb_error(local_ctx, LDB_ERR_OTHER, NULL, &errstr);
    1447           0 :                         errstr = talloc_asprintf(local_ctx,
    1448             :                                 "%s. Too many objects match!", errstr);
    1449           0 :                         DBG_DEBUG("%u results: %s\n", res->count, errstr);
    1450             :                 }
    1451             :         }
    1452             : 
    1453           1 :         compare = &compare_r->msg->r.CompareResponse;
    1454           1 :         compare->dn = NULL;
    1455           1 :         compare->resultcode = result;
    1456           1 :         compare->errormessage = (errstr?talloc_strdup(compare_r,errstr):NULL);
    1457           1 :         compare->referral = NULL;
    1458             : 
    1459           1 :         talloc_free(local_ctx);
    1460             : 
    1461           1 :         return ldapsrv_queue_reply(call, compare_r);
    1462             : }
    1463             : 
    1464          80 : static NTSTATUS ldapsrv_AbandonRequest(struct ldapsrv_call *call)
    1465             : {
    1466          80 :         struct ldap_AbandonRequest *req = &call->request->r.AbandonRequest;
    1467          80 :         struct ldapsrv_call *c = NULL;
    1468          80 :         struct ldapsrv_call *n = NULL;
    1469             : 
    1470          80 :         DBG_DEBUG("abandoned\n");
    1471             : 
    1472         169 :         for (c = call->conn->pending_calls; c != NULL; c = n) {
    1473          89 :                 n = c->next;
    1474             : 
    1475          89 :                 if (c->request->messageid != req->messageid) {
    1476          10 :                         continue;
    1477             :                 }
    1478             : 
    1479          79 :                 DLIST_REMOVE(call->conn->pending_calls, c);
    1480          79 :                 TALLOC_FREE(c);
    1481             :         }
    1482             : 
    1483          80 :         return NT_STATUS_OK;
    1484             : }
    1485             : 
    1486           4 : static NTSTATUS ldapsrv_expired(struct ldapsrv_call *call)
    1487             : {
    1488           4 :         struct ldapsrv_reply *reply = NULL;
    1489           4 :         struct ldap_ExtendedResponse *r = NULL;
    1490             : 
    1491           4 :         DBG_DEBUG("Sending connection expired message\n");
    1492             : 
    1493           4 :         reply = ldapsrv_init_reply(call, LDAP_TAG_ExtendedResponse);
    1494           4 :         if (reply == NULL) {
    1495           0 :                 return NT_STATUS_NO_MEMORY;
    1496             :         }
    1497             : 
    1498             :         /*
    1499             :          * According to RFC4511 section 4.4.1 this has a msgid of 0
    1500             :          */
    1501           4 :         reply->msg->messageid = 0;
    1502             : 
    1503           4 :         r = &reply->msg->r.ExtendedResponse;
    1504           4 :         r->response.resultcode = LDB_ERR_UNAVAILABLE;
    1505           4 :         r->response.errormessage = "The server has timed out this connection";
    1506           4 :         r->oid = "1.3.6.1.4.1.1466.20036"; /* see rfc4511 section 4.4.1 */
    1507             : 
    1508           4 :         ldapsrv_queue_reply(call, reply);
    1509           4 :         return NT_STATUS_OK;
    1510             : }
    1511             : 
    1512      633551 : NTSTATUS ldapsrv_do_call(struct ldapsrv_call *call)
    1513             : {
    1514         709 :         unsigned int i;
    1515      633551 :         struct ldap_message *msg = call->request;
    1516      633551 :         struct ldapsrv_connection *conn = call->conn;
    1517         709 :         NTSTATUS status;
    1518         709 :         bool expired;
    1519             : 
    1520      633551 :         expired = timeval_expired(&conn->limits.expire_time);
    1521      633551 :         if (expired) {
    1522           4 :                 status = ldapsrv_expired(call);
    1523           4 :                 if (!NT_STATUS_IS_OK(status)) {
    1524           0 :                         return status;
    1525             :                 }
    1526           4 :                 return NT_STATUS_NETWORK_SESSION_EXPIRED;
    1527             :         }
    1528             : 
    1529             :         /* Check for undecoded critical extensions */
    1530      913926 :         for (i=0; msg->controls && msg->controls[i]; i++) {
    1531      280379 :                 if (!msg->controls_decoded[i] &&
    1532           0 :                     msg->controls[i]->critical) {
    1533           0 :                         DBG_NOTICE("Critical extension %s is not known to this server\n",
    1534             :                                   msg->controls[i]->oid);
    1535           0 :                         return ldapsrv_unwilling(call, LDAP_UNAVAILABLE_CRITICAL_EXTENSION);
    1536             :                 }
    1537             :         }
    1538             : 
    1539      633547 :         if (call->conn->authz_logged == false) {
    1540       63939 :                 bool log = true;
    1541             : 
    1542             :                 /*
    1543             :                  * We do not want to log anonymous access if the query
    1544             :                  * is just for the rootDSE, or it is a startTLS or a
    1545             :                  * Bind.
    1546             :                  *
    1547             :                  * A rootDSE search could also be done over
    1548             :                  * CLDAP anonymously for example, so these don't
    1549             :                  * really count.
    1550             :                  * Essentially we want to know about
    1551             :                  * access beyond that normally done prior to a
    1552             :                  * bind.
    1553             :                  */
    1554             : 
    1555       63939 :                 switch(call->request->type) {
    1556       36234 :                 case LDAP_TAG_BindRequest:
    1557             :                 case LDAP_TAG_UnbindRequest:
    1558             :                 case LDAP_TAG_AbandonRequest:
    1559       36234 :                         log = false;
    1560       36234 :                         break;
    1561           0 :                 case LDAP_TAG_ExtendedResponse: {
    1562           0 :                         struct ldap_ExtendedRequest *req = &call->request->r.ExtendedRequest;
    1563           0 :                         if (strcmp(req->oid, LDB_EXTENDED_START_TLS_OID) == 0) {
    1564           0 :                                 log = false;
    1565             :                         }
    1566           0 :                         break;
    1567             :                 }
    1568       27563 :                 case LDAP_TAG_SearchRequest: {
    1569       27563 :                         struct ldap_SearchRequest *req = &call->request->r.SearchRequest;
    1570       27563 :                         if (req->scope == LDAP_SEARCH_SCOPE_BASE) {
    1571       27478 :                                 if (req->basedn[0] == '\0') {
    1572       27329 :                                         log = false;
    1573             :                                 }
    1574             :                         }
    1575       27441 :                         break;
    1576             :                 }
    1577          20 :                 default:
    1578          20 :                         break;
    1579             :                 }
    1580             : 
    1581       63695 :                 if (log) {
    1582         132 :                         const char *transport_protection = AUTHZ_TRANSPORT_PROTECTION_NONE;
    1583         132 :                         if (call->conn->sockets.active == call->conn->sockets.tls) {
    1584           8 :                                 transport_protection = AUTHZ_TRANSPORT_PROTECTION_TLS;
    1585             :                         }
    1586             : 
    1587         132 :                         log_successful_authz_event(call->conn->connection->msg_ctx,
    1588         132 :                                                    call->conn->connection->lp_ctx,
    1589         132 :                                                    call->conn->connection->remote_address,
    1590         132 :                                                    call->conn->connection->local_address,
    1591             :                                                    "LDAP",
    1592             :                                                    "no bind",
    1593             :                                                    transport_protection,
    1594         132 :                                                    call->conn->session_info,
    1595             :                                                    NULL /* client_audit_info */,
    1596             :                                                    NULL /* server_audit_info */);
    1597             : 
    1598         132 :                         call->conn->authz_logged = true;
    1599             :                 }
    1600             :         }
    1601             : 
    1602      633547 :         switch(call->request->type) {
    1603       36359 :         case LDAP_TAG_BindRequest:
    1604       36359 :                 return ldapsrv_BindRequest(call);
    1605          21 :         case LDAP_TAG_UnbindRequest:
    1606          21 :                 return ldapsrv_UnbindRequest(call);
    1607      366827 :         case LDAP_TAG_SearchRequest:
    1608      366827 :                 return ldapsrv_SearchRequest(call);
    1609       86740 :         case LDAP_TAG_ModifyRequest:
    1610       86740 :                 status = ldapsrv_ModifyRequest(call);
    1611       86740 :                 break;
    1612       67773 :         case LDAP_TAG_AddRequest:
    1613       67773 :                 status = ldapsrv_AddRequest(call);
    1614       67773 :                 break;
    1615       75042 :         case LDAP_TAG_DelRequest:
    1616       75042 :                 status = ldapsrv_DelRequest(call);
    1617       75042 :                 break;
    1618         388 :         case LDAP_TAG_ModifyDNRequest:
    1619         388 :                 status = ldapsrv_ModifyDNRequest(call);
    1620         388 :                 break;
    1621           1 :         case LDAP_TAG_CompareRequest:
    1622           1 :                 return ldapsrv_CompareRequest(call);
    1623          80 :         case LDAP_TAG_AbandonRequest:
    1624          80 :                 return ldapsrv_AbandonRequest(call);
    1625         316 :         case LDAP_TAG_ExtendedRequest:
    1626         316 :                 status = ldapsrv_ExtendedRequest(call);
    1627         316 :                 break;
    1628           0 :         default:
    1629           0 :                 return ldapsrv_unwilling(call, LDAP_PROTOCOL_ERROR);
    1630             :         }
    1631             : 
    1632      230259 :         if (NT_STATUS_IS_OK(status)) {
    1633      230259 :                 ldapsrv_notification_retry_setup(call->conn->service, true);
    1634             :         }
    1635             : 
    1636      230259 :         return status;
    1637             : }

Generated by: LCOV version 1.14