LCOV - code coverage report
Current view: top level - lib/ldb-samba - ldb_ildap.c (source / functions) Hit Total Coverage
Test: coverage report for master 6248eab5 Lines: 350 445 78.7 %
Date: 2021-08-25 13:27:56 Functions: 21 21 100.0 %

          Line data    Source code
       1             : /*
       2             :    ldb database library - ildap backend
       3             : 
       4             :    Copyright (C) Andrew Tridgell  2005
       5             :    Copyright (C) Simo Sorce       2008
       6             : 
       7             :      ** NOTE! The following LGPL license applies to the ldb
       8             :      ** library. This does NOT imply that all of Samba is released
       9             :      ** under the LGPL
      10             : 
      11             :    This library is free software; you can redistribute it and/or
      12             :    modify it under the terms of the GNU Lesser General Public
      13             :    License as published by the Free Software Foundation; either
      14             :    version 3 of the License, or (at your option) any later version.
      15             : 
      16             :    This library is distributed in the hope that it will be useful,
      17             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      18             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      19             :    Lesser General Public License for more details.
      20             : 
      21             :    You should have received a copy of the GNU Lesser General Public
      22             :    License along with this library; if not, see <http://www.gnu.org/licenses/>.
      23             : */
      24             : 
      25             : /*
      26             :  *  Name: ldb_ildap
      27             :  *
      28             :  *  Component: ldb ildap backend
      29             :  *
      30             :  *  Description: This is a ldb backend for the internal ldap
      31             :  *  client library in Samba4. By using this backend we are
      32             :  *  independent of a system ldap library
      33             :  *
      34             :  *  Author: Andrew Tridgell
      35             :  *
      36             :  *  Modifications:
      37             :  *
      38             :  *  - description: make the module use asynchronous calls
      39             :  *    date: Feb 2006
      40             :  *    author: Simo Sorce
      41             :  */
      42             : 
      43             : #include "includes.h"
      44             : #include "ldb_module.h"
      45             : #include "util/dlinklist.h"
      46             : 
      47             : #include "libcli/ldap/libcli_ldap.h"
      48             : #include "libcli/ldap/ldap_client.h"
      49             : #include "auth/auth.h"
      50             : #include "auth/credentials/credentials.h"
      51             : #include "dsdb/common/util.h"
      52             : 
      53             : struct ildb_private {
      54             :         struct ldap_connection *ldap;
      55             :         struct tevent_context *event_ctx;
      56             : };
      57             : 
      58             : struct ildb_context {
      59             :         struct ldb_module *module;
      60             :         struct ldb_request *req;
      61             : 
      62             :         struct ildb_private *ildb;
      63             :         struct ldap_request *ireq;
      64             : 
      65             :         /* indicate we are already processing
      66             :          * the ldap_request in ildb_callback() */
      67             :         bool in_ildb_callback;
      68             : 
      69             :         bool done;
      70             : 
      71             :         struct ildb_destructor_ctx *dc;
      72             : };
      73             : 
      74      405247 : static void ildb_request_done(struct ildb_context *ctx,
      75             :                               struct ldb_control **ctrls, int error)
      76             : {
      77             :         struct ldb_context *ldb;
      78             :         struct ldb_reply *ares;
      79             : 
      80      405247 :         ldb = ldb_module_get_ctx(ctx->module);
      81             : 
      82      405247 :         ctx->done = true;
      83             : 
      84      405247 :         if (ctx->req == NULL) {
      85             :                 /* if the req has been freed already just return */
      86           0 :                 return;
      87             :         }
      88             : 
      89      405247 :         ares = talloc_zero(ctx->req, struct ldb_reply);
      90      405247 :         if (!ares) {
      91           0 :                 ldb_oom(ldb);
      92           0 :                 ctx->req->callback(ctx->req, NULL);
      93           0 :                 return;
      94             :         }
      95      405247 :         ares->type = LDB_REPLY_DONE;
      96      405247 :         ares->controls = talloc_steal(ares, ctrls);
      97      405247 :         ares->error = error;
      98             : 
      99      405247 :         ctx->req->callback(ctx->req, ares);
     100             : }
     101             : 
     102          24 : static void ildb_auto_done_callback(struct tevent_context *ev,
     103             :                                     struct tevent_timer *te,
     104             :                                     struct timeval t,
     105             :                                     void *private_data)
     106             : {
     107             :         struct ildb_context *ac;
     108             : 
     109          24 :         ac = talloc_get_type(private_data, struct ildb_context);
     110          24 :         ildb_request_done(ac, NULL, LDB_SUCCESS);
     111          24 : }
     112             : 
     113             : /*
     114             :   convert a ldb_message structure to a list of ldap_mod structures
     115             :   ready for ildap_add() or ildap_modify()
     116             : */
     117      102454 : static struct ldap_mod **ildb_msg_to_mods(void *mem_ctx, unsigned int *num_mods,
     118             :                                           const struct ldb_message *msg,
     119             :                                           int use_flags)
     120             : {
     121             :         struct ldap_mod **mods;
     122             :         unsigned int i;
     123      102454 :         unsigned int n = 0;
     124             : 
     125             :         /* allocate maximum number of elements needed */
     126      102454 :         mods = talloc_array(mem_ctx, struct ldap_mod *, msg->num_elements+1);
     127      102454 :         if (!mods) {
     128           0 :                 errno = ENOMEM;
     129           0 :                 return NULL;
     130             :         }
     131      102454 :         mods[0] = NULL;
     132             : 
     133      300082 :         for (i = 0; i < msg->num_elements; i++) {
     134      197448 :                 const struct ldb_message_element *el = &msg->elements[i];
     135             : 
     136      197448 :                 mods[n] = talloc(mods, struct ldap_mod);
     137      197448 :                 if (!mods[n]) {
     138           0 :                         goto failed;
     139             :                 }
     140      197448 :                 mods[n + 1] = NULL;
     141      197448 :                 mods[n]->type = 0;
     142      197448 :                 mods[n]->attrib = *el;
     143      197448 :                 if (use_flags) {
     144       76191 :                         switch (el->flags & LDB_FLAG_MOD_MASK) {
     145       23420 :                         case LDB_FLAG_MOD_ADD:
     146       23420 :                                 mods[n]->type = LDAP_MODIFY_ADD;
     147       23420 :                                 break;
     148       13877 :                         case LDB_FLAG_MOD_DELETE:
     149       13877 :                                 mods[n]->type = LDAP_MODIFY_DELETE;
     150       13877 :                                 break;
     151       38879 :                         case LDB_FLAG_MOD_REPLACE:
     152       38879 :                                 mods[n]->type = LDAP_MODIFY_REPLACE;
     153       38663 :                                 break;
     154             :                         }
     155             :                 }
     156      197124 :                 n++;
     157             :         }
     158             : 
     159      102454 :         *num_mods = n;
     160      102274 :         return mods;
     161             : 
     162           0 : failed:
     163           0 :         talloc_free(mods);
     164           0 :         return NULL;
     165             : }
     166             : 
     167             : 
     168             : /*
     169             :   map an ildap NTSTATUS to a ldb error code
     170             : */
     171      156591 : static int ildb_map_error(struct ldb_module *module, NTSTATUS status)
     172             : {
     173             :         struct ildb_private *ildb;
     174             :         struct ldb_context *ldb;
     175             :         TALLOC_CTX *mem_ctx;
     176             : 
     177      156591 :         ildb = talloc_get_type(ldb_module_get_private(module), struct ildb_private);
     178      156591 :         ldb = ldb_module_get_ctx(module);
     179             : 
     180      156591 :         if (NT_STATUS_IS_OK(status)) {
     181      121901 :                 return LDB_SUCCESS;
     182             :         }
     183             : 
     184       34474 :         mem_ctx = talloc_new(ildb);
     185       34474 :         if (!mem_ctx) {
     186           0 :                 ldb_oom(ldb);
     187           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     188             :         }
     189       34474 :         ldb_set_errstring(ldb,
     190             :                           ldap_errstr(ildb->ldap, mem_ctx, status));
     191       34474 :         talloc_free(mem_ctx);
     192       34474 :         if (NT_STATUS_IS_LDAP(status)) {
     193       34474 :                 return NT_STATUS_LDAP_CODE(status);
     194             :         }
     195           0 :         return LDB_ERR_OPERATIONS_ERROR;
     196             : }
     197             : 
     198          14 : static void ildb_request_timeout(struct tevent_context *ev, struct tevent_timer *te,
     199             :                                  struct timeval t, void *private_data)
     200             : {
     201          14 :         struct ildb_context *ac = talloc_get_type(private_data, struct ildb_context);
     202             : 
     203          14 :         if (ac->ireq->state == LDAP_REQUEST_PENDING) {
     204          14 :                 DLIST_REMOVE(ac->ireq->conn->pending, ac->ireq);
     205             :         }
     206             : 
     207          14 :         ildb_request_done(ac, NULL, LDB_ERR_TIME_LIMIT_EXCEEDED);
     208          14 : }
     209             : 
     210     1015846 : static void ildb_callback(struct ldap_request *req)
     211             : {
     212             :         struct ldb_context *ldb;
     213             :         struct ildb_context *ac;
     214             :         NTSTATUS status;
     215             :         struct ldap_SearchResEntry *search;
     216             :         struct ldap_message *msg;
     217             :         struct ldb_control **controls;
     218             :         struct ldb_message *ldbmsg;
     219             :         char *referral;
     220             :         bool callback_failed;
     221             :         bool request_done;
     222             :         int ret;
     223             :         int i;
     224             : 
     225     1015846 :         ac = talloc_get_type(req->async.private_data, struct ildb_context);
     226     1015846 :         ldb = ldb_module_get_ctx(ac->module);
     227     1015846 :         callback_failed = false;
     228     1015846 :         request_done = false;
     229     1015846 :         controls = NULL;
     230             : 
     231             :         /* check if we are already processing this request */
     232     1015846 :         if (ac->in_ildb_callback) {
     233           1 :                 return;
     234             :         }
     235             :         /* mark the request as being in process */
     236     1015845 :         ac->in_ildb_callback = true;
     237             : 
     238     1015845 :         if (!NT_STATUS_IS_OK(req->status)) {
     239           0 :                 ret = ildb_map_error(ac->module, req->status);
     240           0 :                 ildb_request_done(ac, NULL, ret);
     241           0 :                 return;
     242             :         }
     243             : 
     244     1015845 :         if (req->num_replies < 1) {
     245           0 :                 ret = LDB_ERR_OPERATIONS_ERROR;
     246           0 :                 ildb_request_done(ac, NULL, ret);
     247           0 :                 return;
     248             :         }
     249             : 
     250     1015845 :         switch (req->type) {
     251             : 
     252       57348 :         case LDAP_TAG_ModifyRequest:
     253       57348 :                 if (req->replies[0]->type != LDAP_TAG_ModifyResponse) {
     254           0 :                         ret = LDB_ERR_PROTOCOL_ERROR;
     255           0 :                         break;
     256             :                 }
     257       57348 :                 status = ldap_check_response(ac->ireq->conn, &req->replies[0]->r.GeneralResult);
     258       57348 :                 ret = ildb_map_error(ac->module, status);
     259       57348 :                 request_done = true;
     260       57348 :                 break;
     261             : 
     262       45106 :         case LDAP_TAG_AddRequest:
     263       45106 :                 if (req->replies[0]->type != LDAP_TAG_AddResponse) {
     264           0 :                         ret = LDB_ERR_PROTOCOL_ERROR;
     265           0 :                         return;
     266             :                 }
     267       45106 :                 status = ldap_check_response(ac->ireq->conn, &req->replies[0]->r.GeneralResult);
     268       45106 :                 ret = ildb_map_error(ac->module, status);
     269       45106 :                 request_done = true;
     270       45106 :                 break;
     271             : 
     272       45723 :         case LDAP_TAG_DelRequest:
     273       45723 :                 if (req->replies[0]->type != LDAP_TAG_DelResponse) {
     274           0 :                         ret = LDB_ERR_PROTOCOL_ERROR;
     275           0 :                         return;
     276             :                 }
     277       45723 :                 status = ldap_check_response(ac->ireq->conn, &req->replies[0]->r.GeneralResult);
     278       45723 :                 ret = ildb_map_error(ac->module, status);
     279       45723 :                 request_done = true;
     280       45723 :                 break;
     281             : 
     282         314 :         case LDAP_TAG_ModifyDNRequest:
     283         314 :                 if (req->replies[0]->type != LDAP_TAG_ModifyDNResponse) {
     284           0 :                         ret = LDB_ERR_PROTOCOL_ERROR;
     285           0 :                         return;
     286             :                 }
     287         314 :                 status = ldap_check_response(ac->ireq->conn, &req->replies[0]->r.GeneralResult);
     288         314 :                 ret = ildb_map_error(ac->module, status);
     289         314 :                 request_done = true;
     290         314 :                 break;
     291             : 
     292      866820 :         case LDAP_TAG_SearchRequest:
     293             :                 /* loop over all messages */
     294     1726074 :                 for (i = 0; i < req->num_replies; i++) {
     295             : 
     296      867355 :                         msg = req->replies[i];
     297      867355 :                         switch (msg->type) {
     298             : 
     299      256717 :                         case LDAP_TAG_SearchResultDone:
     300             : 
     301      256717 :                                 status = ldap_check_response(ac->ireq->conn, &msg->r.GeneralResult);
     302      256717 :                                 if (!NT_STATUS_IS_OK(status)) {
     303        8100 :                                         ret = ildb_map_error(ac->module, status);
     304        8100 :                                         break;
     305             :                                 }
     306             : 
     307      248617 :                                 controls = talloc_steal(ac, msg->controls);
     308      248617 :                                 if (msg->r.SearchResultDone.resultcode) {
     309           0 :                                         if (msg->r.SearchResultDone.errormessage) {
     310           0 :                                                 ldb_set_errstring(ldb, msg->r.SearchResultDone.errormessage);
     311             :                                         }
     312             :                                 }
     313             : 
     314      248617 :                                 ret = msg->r.SearchResultDone.resultcode;
     315      248617 :                                 request_done = true;
     316      248617 :                                 break;
     317             : 
     318      528458 :                         case LDAP_TAG_SearchResultEntry:
     319             : 
     320      528458 :                                 ldbmsg = ldb_msg_new(ac);
     321      528458 :                                 if (!ldbmsg) {
     322           0 :                                         ret = LDB_ERR_OPERATIONS_ERROR;
     323           0 :                                         break;
     324             :                                 }
     325             : 
     326      528458 :                                 search = &(msg->r.SearchResultEntry);
     327             : 
     328      528458 :                                 ldbmsg->dn = ldb_dn_new(ldbmsg, ldb, search->dn);
     329      528458 :                                 if ( ! ldb_dn_validate(ldbmsg->dn)) {
     330           0 :                                         ret = LDB_ERR_OPERATIONS_ERROR;
     331           0 :                                         break;
     332             :                                 }
     333      528458 :                                 ldbmsg->num_elements = search->num_attributes;
     334      528458 :                                 ldbmsg->elements = talloc_move(ldbmsg, &search->attributes);
     335             : 
     336      528458 :                                 controls = talloc_steal(ac, msg->controls);
     337             : 
     338      528458 :                                 ret = ldb_module_send_entry(ac->req, ldbmsg, controls);
     339      528458 :                                 if (ret != LDB_SUCCESS) {
     340           0 :                                         callback_failed = true;
     341             :                                 }
     342             : 
     343      528209 :                                 break;
     344             : 
     345       82179 :                         case LDAP_TAG_SearchResultReference:
     346             : 
     347       82179 :                                 referral = talloc_strdup(ac, msg->r.SearchResultReference.referral);
     348             : 
     349       82179 :                                 ret = ldb_module_send_referral(ac->req, referral);
     350       82179 :                                 if (ret != LDB_SUCCESS) {
     351           0 :                                         callback_failed = true;
     352             :                                 }
     353             : 
     354       82143 :                                 break;
     355             : 
     356           1 :                         default:
     357             :                                 /* TAG not handled, fail ! */
     358           1 :                                 ret = LDB_ERR_PROTOCOL_ERROR;
     359           1 :                                 break;
     360             :                         }
     361             : 
     362      867355 :                         if (ret != LDB_SUCCESS) {
     363        8101 :                                 break;
     364             :                         }
     365             :                 }
     366             : 
     367      867354 :                 talloc_free(req->replies);
     368      867354 :                 req->replies = NULL;
     369      867354 :                 req->num_replies = 0;
     370             : 
     371      867354 :                 break;
     372             : 
     373           0 :         default:
     374           0 :                 ret = LDB_ERR_PROTOCOL_ERROR;
     375           0 :                 break;
     376             :         }
     377             : 
     378     1015845 :         if (ret != LDB_SUCCESS) {
     379             : 
     380             :                 /* if the callback failed the caller will have freed the
     381             :                  * request. Just return and don't try to use it */
     382       34475 :                 if ( ! callback_failed) {
     383       34475 :                         request_done = true;
     384             :                 }
     385             :         }
     386             : 
     387             :         /* mark the request as not being in progress */
     388     1015095 :         ac->in_ildb_callback = false;
     389             : 
     390     1015845 :         if (request_done) {
     391      405209 :                 ildb_request_done(ac, controls, ret);
     392             :         }
     393             : 
     394     1015095 :         return;
     395             : }
     396             : 
     397      405262 : static int ildb_request_send(struct ildb_context *ac, struct ldap_message *msg)
     398             : {
     399             :         struct ldb_context *ldb;
     400             :         struct ldap_request *req;
     401             : 
     402      405262 :         if (!ac) {
     403           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     404             :         }
     405             : 
     406      405262 :         ldb = ldb_module_get_ctx(ac->module);
     407             : 
     408      405262 :         ldb_request_set_state(ac->req, LDB_ASYNC_PENDING);
     409             : 
     410      405262 :         req = ldap_request_send(ac->ildb->ldap, msg);
     411      405262 :         if (req == NULL) {
     412           0 :                 ldb_set_errstring(ldb, "async send request failed");
     413           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     414             :         }
     415      405262 :         ac->ireq = talloc_reparent(ac->ildb->ldap, ac, req);
     416             : 
     417      405262 :         if (!ac->ireq->conn) {
     418           0 :                 ldb_set_errstring(ldb, "connection to remote LDAP server dropped?");
     419           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     420             :         }
     421             : 
     422      405262 :         TALLOC_FREE(req->time_event);
     423      405262 :         if (ac->req->timeout > 0) {
     424      810446 :                 struct timeval tv = {
     425      405223 :                         .tv_sec = ac->req->starttime + ac->req->timeout,
     426             :                 };
     427             : 
     428      405223 :                 req->time_event = tevent_add_timer(ac->ildb->event_ctx, ac, tv,
     429             :                                                    ildb_request_timeout, ac);
     430             :         }
     431             : 
     432      405262 :         req->async.fn = ildb_callback;
     433      405262 :         req->async.private_data = ac;
     434             : 
     435      405262 :         return LDB_SUCCESS;
     436             : }
     437             : 
     438             : /*
     439             :   search for matching records using an asynchronous function
     440             :  */
     441      256771 : static int ildb_search(struct ildb_context *ac)
     442             : {
     443             :         struct ldb_context *ldb;
     444      256771 :         struct ldb_request *req = ac->req;
     445             :         struct ldap_message *msg;
     446             :         int n;
     447             : 
     448      256771 :         ldb = ldb_module_get_ctx(ac->module);
     449             : 
     450      256771 :         if (!req->callback || !req->context) {
     451           0 :                 ldb_set_errstring(ldb, "Async interface called with NULL callback function or NULL context");
     452           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     453             :         }
     454             : 
     455      256771 :         if (req->op.search.tree == NULL) {
     456           0 :                 ldb_set_errstring(ldb, "Invalid expression parse tree");
     457           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     458             :         }
     459             : 
     460      256771 :         msg = new_ldap_message(req);
     461      256771 :         if (msg == NULL) {
     462           0 :                 ldb_set_errstring(ldb, "Out of Memory");
     463           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     464             :         }
     465             : 
     466      256771 :         msg->type = LDAP_TAG_SearchRequest;
     467             : 
     468      256771 :         if (req->op.search.base == NULL) {
     469           0 :                 msg->r.SearchRequest.basedn = talloc_strdup(msg, "");
     470             :         } else {
     471      256771 :                 msg->r.SearchRequest.basedn  = ldb_dn_get_extended_linearized(msg, req->op.search.base, 0);
     472             :         }
     473      256771 :         if (msg->r.SearchRequest.basedn == NULL) {
     474           0 :                 ldb_set_errstring(ldb, "Unable to determine baseDN");
     475           0 :                 talloc_free(msg);
     476           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     477             :         }
     478             : 
     479      256771 :         if (req->op.search.scope == LDB_SCOPE_DEFAULT) {
     480        8911 :                 msg->r.SearchRequest.scope = LDAP_SEARCH_SCOPE_SUB;
     481             :         } else {
     482      247860 :                 msg->r.SearchRequest.scope = req->op.search.scope;
     483             :         }
     484             : 
     485      256771 :         msg->r.SearchRequest.deref  = LDAP_DEREFERENCE_NEVER;
     486      256771 :         msg->r.SearchRequest.timelimit = 0;
     487      256771 :         msg->r.SearchRequest.sizelimit = 0;
     488      256771 :         msg->r.SearchRequest.attributesonly = 0;
     489      256771 :         msg->r.SearchRequest.tree = discard_const(req->op.search.tree);
     490             : 
     491      256771 :         for (n = 0; req->op.search.attrs && req->op.search.attrs[n]; n++) /* noop */ ;
     492      256771 :         msg->r.SearchRequest.num_attributes = n;
     493      256771 :         msg->r.SearchRequest.attributes = req->op.search.attrs;
     494      256771 :         msg->controls = req->controls;
     495             : 
     496      256771 :         return ildb_request_send(ac, msg);
     497             : }
     498             : 
     499             : /*
     500             :   add a record
     501             : */
     502       45106 : static int ildb_add(struct ildb_context *ac)
     503             : {
     504       45106 :         struct ldb_request *req = ac->req;
     505             :         struct ldap_message *msg;
     506             :         struct ldap_mod **mods;
     507             :         unsigned int i,n;
     508             : 
     509       45106 :         msg = new_ldap_message(req);
     510       45106 :         if (msg == NULL) {
     511           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     512             :         }
     513             : 
     514       45106 :         msg->type = LDAP_TAG_AddRequest;
     515             : 
     516       45106 :         msg->r.AddRequest.dn = ldb_dn_get_extended_linearized(msg, req->op.add.message->dn, 0);
     517       45106 :         if (msg->r.AddRequest.dn == NULL) {
     518           0 :                 talloc_free(msg);
     519           0 :                 return LDB_ERR_INVALID_DN_SYNTAX;
     520             :         }
     521             : 
     522       45106 :         mods = ildb_msg_to_mods(msg, &n, req->op.add.message, 0);
     523       45106 :         if (mods == NULL) {
     524           0 :                 talloc_free(msg);
     525           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     526             :         }
     527             : 
     528       45106 :         msg->r.AddRequest.num_attributes = n;
     529       45106 :         msg->r.AddRequest.attributes = talloc_array(msg, struct ldb_message_element, n);
     530       45106 :         if (msg->r.AddRequest.attributes == NULL) {
     531           0 :                 talloc_free(msg);
     532           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     533             :         }
     534             : 
     535      166327 :         for (i = 0; i < n; i++) {
     536      121257 :                 msg->r.AddRequest.attributes[i] = mods[i]->attrib;
     537             :         }
     538       45106 :         msg->controls = req->controls;
     539             : 
     540       45106 :         return ildb_request_send(ac, msg);
     541             : }
     542             : 
     543             : /*
     544             :   modify a record
     545             : */
     546       57348 : static int ildb_modify(struct ildb_context *ac)
     547             : {
     548       57348 :         struct ldb_request *req = ac->req;
     549             :         struct ldap_message *msg;
     550             :         struct ldap_mod **mods;
     551             :         unsigned int i,n;
     552             : 
     553       57348 :         msg = new_ldap_message(req);
     554       57348 :         if (msg == NULL) {
     555           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     556             :         }
     557             : 
     558       57348 :         msg->type = LDAP_TAG_ModifyRequest;
     559             : 
     560       57348 :         msg->r.ModifyRequest.dn = ldb_dn_get_extended_linearized(msg, req->op.mod.message->dn, 0);
     561       57348 :         if (msg->r.ModifyRequest.dn == NULL) {
     562           0 :                 talloc_free(msg);
     563           0 :                 return LDB_ERR_INVALID_DN_SYNTAX;
     564             :         }
     565             : 
     566       57348 :         mods = ildb_msg_to_mods(msg, &n, req->op.mod.message, 1);
     567       57348 :         if (mods == NULL) {
     568           0 :                 talloc_free(msg);
     569           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     570             :         }
     571             : 
     572       57348 :         msg->r.ModifyRequest.num_mods = n;
     573       57348 :         msg->r.ModifyRequest.mods = talloc_array(msg, struct ldap_mod, n);
     574       57348 :         if (msg->r.ModifyRequest.mods == NULL) {
     575           0 :                 talloc_free(msg);
     576           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     577             :         }
     578             : 
     579      133395 :         for (i = 0; i < n; i++) {
     580       76191 :                 msg->r.ModifyRequest.mods[i] = *mods[i];
     581             :         }
     582       57348 :         msg->controls = req->controls;
     583       57348 :         return ildb_request_send(ac, msg);
     584             : }
     585             : 
     586             : /*
     587             :   delete a record
     588             : */
     589       45723 : static int ildb_delete(struct ildb_context *ac)
     590             : {
     591       45723 :         struct ldb_request *req = ac->req;
     592             :         struct ldap_message *msg;
     593             : 
     594       45723 :         msg = new_ldap_message(req);
     595       45723 :         if (msg == NULL) {
     596           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     597             :         }
     598             : 
     599       45723 :         msg->type = LDAP_TAG_DelRequest;
     600             : 
     601       45723 :         msg->r.DelRequest.dn = ldb_dn_get_extended_linearized(msg, req->op.del.dn, 0);
     602       45723 :         if (msg->r.DelRequest.dn == NULL) {
     603           0 :                 talloc_free(msg);
     604           0 :                 return LDB_ERR_INVALID_DN_SYNTAX;
     605             :         }
     606       45723 :         msg->controls = req->controls;
     607             : 
     608       45723 :         return ildb_request_send(ac, msg);
     609             : }
     610             : 
     611             : /*
     612             :   rename a record
     613             : */
     614         314 : static int ildb_rename(struct ildb_context *ac)
     615             : {
     616         314 :         struct ldb_request *req = ac->req;
     617             :         struct ldap_message *msg;
     618             :         const char *rdn_name;
     619             :         const struct ldb_val *rdn_val;
     620             : 
     621         314 :         msg = new_ldap_message(req);
     622         314 :         if (msg == NULL) {
     623           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     624             :         }
     625             : 
     626         314 :         msg->type = LDAP_TAG_ModifyDNRequest;
     627         314 :         msg->r.ModifyDNRequest.dn = ldb_dn_get_extended_linearized(msg, req->op.rename.olddn, 0);
     628         314 :         if (msg->r.ModifyDNRequest.dn == NULL) {
     629           0 :                 talloc_free(msg);
     630           0 :                 return LDB_ERR_INVALID_DN_SYNTAX;
     631             :         }
     632             : 
     633         314 :         rdn_name = ldb_dn_get_rdn_name(req->op.rename.newdn);
     634         314 :         rdn_val = ldb_dn_get_rdn_val(req->op.rename.newdn);
     635             : 
     636         314 :         if ((rdn_name != NULL) && (rdn_val != NULL)) {
     637         314 :                 msg->r.ModifyDNRequest.newrdn =
     638         314 :                         talloc_asprintf(msg, "%s=%s", rdn_name,
     639         314 :                                         rdn_val->length > 0 ? ldb_dn_escape_value(msg, *rdn_val) : "");
     640             :         } else {
     641           0 :                 msg->r.ModifyDNRequest.newrdn = talloc_strdup(msg, "");
     642             :         }
     643         314 :         if (msg->r.ModifyDNRequest.newrdn == NULL) {
     644           0 :                 talloc_free(msg);
     645           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     646             :         }
     647             : 
     648         314 :         msg->r.ModifyDNRequest.newsuperior =
     649         314 :                 ldb_dn_alloc_linearized(msg, ldb_dn_get_parent(msg, req->op.rename.newdn));
     650         314 :         if (msg->r.ModifyDNRequest.newsuperior == NULL) {
     651           0 :                 talloc_free(msg);
     652           0 :                 return LDB_ERR_INVALID_DN_SYNTAX;
     653             :         }
     654             : 
     655         314 :         msg->r.ModifyDNRequest.deleteolddn = true;
     656         314 :         msg->controls = req->controls;
     657             : 
     658         314 :         return ildb_request_send(ac, msg);
     659             : }
     660             : 
     661      130322 : static int ildb_start_trans(struct ldb_module *module)
     662             : {
     663             :         /* TODO implement a local locking mechanism here */
     664             : 
     665      130322 :         return LDB_SUCCESS;
     666             : }
     667             : 
     668      104042 : static int ildb_end_trans(struct ldb_module *module)
     669             : {
     670             :         /* TODO implement a local transaction mechanism here */
     671             : 
     672      104042 :         return LDB_SUCCESS;
     673             : }
     674             : 
     675       26278 : static int ildb_del_trans(struct ldb_module *module)
     676             : {
     677             :         /* TODO implement a local locking mechanism here */
     678             : 
     679       26278 :         return LDB_SUCCESS;
     680             : }
     681             : 
     682      405286 : static bool ildb_dn_is_special(struct ldb_request *req)
     683             : {
     684      405286 :         struct ldb_dn *dn = NULL;
     685             : 
     686      405286 :         switch (req->operation) {
     687      256783 :         case LDB_SEARCH:
     688      256783 :                 dn = req->op.search.base;
     689      256534 :                 break;
     690       45118 :         case LDB_ADD:
     691       45118 :                 dn = req->op.add.message->dn;
     692       45082 :                 break;
     693       57348 :         case LDB_MODIFY:
     694       57348 :                 dn = req->op.mod.message->dn;
     695       57204 :                 break;
     696       45723 :         case LDB_DELETE:
     697       45723 :                 dn = req->op.del.dn;
     698       45687 :                 break;
     699         314 :         case LDB_RENAME:
     700         314 :                 dn = req->op.rename.olddn;
     701         314 :                 break;
     702           0 :         default:
     703           0 :                 break;
     704             :         }
     705             : 
     706      405286 :         if (dn && ldb_dn_is_special(dn)) {
     707          24 :                 return true;
     708             :         }
     709      404797 :         return false;
     710             : }
     711             : 
     712      405286 : static int ildb_handle_request(struct ldb_module *module, struct ldb_request *req)
     713             : {
     714             :         struct ldb_context *ldb;
     715             :         struct ildb_private *ildb;
     716             :         struct ildb_context *ac;
     717             :         struct tevent_timer *te;
     718             :         int ret;
     719             : 
     720      405286 :         ildb = talloc_get_type(ldb_module_get_private(module), struct ildb_private);
     721      405286 :         ldb = ldb_module_get_ctx(module);
     722             : 
     723      405286 :         if (req->starttime == 0 || req->timeout == 0) {
     724           0 :                 ldb_set_errstring(ldb, "Invalid timeout settings");
     725           0 :                 return LDB_ERR_TIME_LIMIT_EXCEEDED;
     726             :         }
     727             : 
     728      405286 :         ac = talloc_zero(req, struct ildb_context);
     729      405286 :         if (ac == NULL) {
     730           0 :                 ldb_set_errstring(ldb, "Out of Memory");
     731           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     732             :         }
     733             : 
     734      405286 :         ac->module = module;
     735      405286 :         ac->req = req;
     736      405286 :         ac->ildb = ildb;
     737             : 
     738      405286 :         if (ildb_dn_is_special(req)) {
     739             : 
     740          24 :                 te = tevent_add_timer(ac->ildb->event_ctx,
     741             :                                       ac, timeval_zero(),
     742             :                                       ildb_auto_done_callback, ac);
     743          24 :                 if (NULL == te) {
     744           0 :                         return LDB_ERR_OPERATIONS_ERROR;
     745             :                 }
     746             : 
     747          24 :                 return LDB_SUCCESS;
     748             :         }
     749             : 
     750      405262 :         switch (ac->req->operation) {
     751      256771 :         case LDB_SEARCH:
     752      256771 :                 ret = ildb_search(ac);
     753      256771 :                 break;
     754       45106 :         case LDB_ADD:
     755       45106 :                 ret = ildb_add(ac);
     756       45106 :                 break;
     757       57348 :         case LDB_MODIFY:
     758       57348 :                 ret = ildb_modify(ac);
     759       57348 :                 break;
     760       45723 :         case LDB_DELETE:
     761       45723 :                 ret = ildb_delete(ac);
     762       45723 :                 break;
     763         314 :         case LDB_RENAME:
     764         314 :                 ret = ildb_rename(ac);
     765         314 :                 break;
     766           0 :         default:
     767             :                 /* no other op supported */
     768           0 :                 ret = LDB_ERR_PROTOCOL_ERROR;
     769           0 :                 break;
     770             :         }
     771             : 
     772      404797 :         return ret;
     773             : }
     774             : 
     775             : static const struct ldb_module_ops ildb_ops = {
     776             :         .name              = "ldap",
     777             :         .search            = ildb_handle_request,
     778             :         .add               = ildb_handle_request,
     779             :         .modify            = ildb_handle_request,
     780             :         .del               = ildb_handle_request,
     781             :         .rename            = ildb_handle_request,
     782             : /*      .request           = ildb_handle_request, */
     783             :         .start_transaction = ildb_start_trans,
     784             :         .end_transaction   = ildb_end_trans,
     785             :         .del_transaction   = ildb_del_trans,
     786             : };
     787             : 
     788             : /*
     789             :   connect to the database
     790             : */
     791       17998 : static int ildb_connect(struct ldb_context *ldb, const char *url,
     792             :                         unsigned int flags, const char *options[],
     793             :                         struct ldb_module **_module)
     794             : {
     795             :         struct ldb_module *module;
     796             :         struct ildb_private *ildb;
     797       17998 :         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
     798             :         struct cli_credentials *creds;
     799             :         struct loadparm_context *lp_ctx;
     800             : 
     801       17998 :         module = ldb_module_new(ldb, ldb, "ldb_ildap backend", &ildb_ops);
     802       17998 :         if (!module) return LDB_ERR_OPERATIONS_ERROR;
     803             : 
     804       17998 :         ildb = talloc(module, struct ildb_private);
     805       17998 :         if (!ildb) {
     806           0 :                 ldb_oom(ldb);
     807           0 :                 goto failed;
     808             :         }
     809       17998 :         ldb_module_set_private(module, ildb);
     810             : 
     811       17998 :         ildb->event_ctx = ldb_get_event_context(ldb);
     812             : 
     813       17998 :         lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
     814             :                                  struct loadparm_context);
     815             : 
     816       17998 :         ildb->ldap = ldap4_new_connection(ildb, lp_ctx,
     817             :                                           ildb->event_ctx);
     818       17998 :         if (!ildb->ldap) {
     819           0 :                 ldb_oom(ldb);
     820           0 :                 goto failed;
     821             :         }
     822             : 
     823       17998 :         if (flags & LDB_FLG_RECONNECT) {
     824           0 :                 ldap_set_reconn_params(ildb->ldap, 10);
     825             :         }
     826             : 
     827       17998 :         status = ldap_connect(ildb->ldap, url);
     828       17996 :         if (!NT_STATUS_IS_OK(status)) {
     829          13 :                 ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to connect to ldap URL '%s' - %s",
     830             :                           url, ldap_errstr(ildb->ldap, module, status));
     831          13 :                 goto failed;
     832             :         }
     833             : 
     834             :         /* caller can optionally setup credentials using the opaque token 'credentials' */
     835       17983 :         creds = talloc_get_type(ldb_get_opaque(ldb, "credentials"), struct cli_credentials);
     836       17983 :         if (creds == NULL) {
     837           3 :                 struct auth_session_info *session_info = talloc_get_type(
     838             :                         ldb_get_opaque(ldb, DSDB_SESSION_INFO),
     839             :                         struct auth_session_info);
     840           3 :                 if (session_info) {
     841           0 :                         creds = session_info->credentials;
     842             :                 }
     843             :         }
     844             : 
     845       17983 :         if (creds != NULL && cli_credentials_authentication_requested(creds)) {
     846       17867 :                 const char *bind_dn = cli_credentials_get_bind_dn(creds);
     847       17867 :                 if (bind_dn) {
     848          82 :                         const char *password = cli_credentials_get_password(creds);
     849          82 :                         status = ldap_bind_simple(ildb->ldap, bind_dn, password);
     850          82 :                         if (!NT_STATUS_IS_OK(status)) {
     851          14 :                                 ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to bind - %s",
     852             :                                           ldap_errstr(ildb->ldap, module, status));
     853          14 :                                 goto failed;
     854             :                         }
     855             :                 } else {
     856       17785 :                         status = ldap_bind_sasl(ildb->ldap, creds, lp_ctx);
     857       17785 :                         if (!NT_STATUS_IS_OK(status)) {
     858         301 :                                 ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to bind - %s",
     859             :                                           ldap_errstr(ildb->ldap, module, status));
     860         301 :                                 goto failed;
     861             :                         }
     862             :                 }
     863             :         }
     864             : 
     865       17668 :         *_module = module;
     866       17668 :         return LDB_SUCCESS;
     867             : 
     868         328 : failed:
     869         328 :         if (ildb != NULL && ildb->ldap != NULL) {
     870         328 :                 ldb_set_errstring(ldb, ldap_errstr(ildb->ldap, module, status));
     871             :         }
     872         328 :         talloc_free(module);
     873         328 :         if (NT_STATUS_IS_LDAP(status)) {
     874         170 :                 return NT_STATUS_LDAP_CODE(status);
     875         158 :         } else if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)
     876         158 :                    || NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)
     877         158 :                    || NT_STATUS_EQUAL(status, NT_STATUS_LOGON_FAILURE)
     878          31 :                    || NT_STATUS_EQUAL(status, NT_STATUS_ACCOUNT_LOCKED_OUT)) {
     879         145 :                 return LDB_ERR_INVALID_CREDENTIALS;
     880             :         }
     881          13 :         return LDB_ERR_OPERATIONS_ERROR;
     882             : }
     883             : 
     884             : /*
     885             :   initialise the module
     886             :  */
     887        5580 : _PUBLIC_ int ldb_ildap_init(const char *ldb_version)
     888             : {
     889             :         int ret, i;
     890        5580 :         const char *names[] = { "ldap", "ldaps", "ldapi", NULL };
     891       22320 :         for (i=0; names[i]; i++) {
     892       16740 :                 ret = ldb_register_backend(names[i], ildb_connect, true);
     893       16740 :                 if (ret != LDB_SUCCESS) {
     894           0 :                         return ret;
     895             :                 }
     896             :         }
     897        5189 :         return LDB_SUCCESS;
     898             : }

Generated by: LCOV version 1.13