LCOV - code coverage report
Current view: top level - source4/ldap_server - ldap_backend.c (source / functions) Hit Total Coverage
Test: coverage report for support-claim-type-attributes 6b5c566e Lines: 776 941 82.5 %
Date: 2023-11-21 12:31:41 Functions: 20 21 95.2 %

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

Generated by: LCOV version 1.14