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

Generated by: LCOV version 1.14