LCOV - code coverage report
Current view: top level - lib/ldb-samba - ldb_ildap.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 453 566 80.0 %
Date: 2024-04-21 15:09:00 Functions: 20 20 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      567890 : static void ildb_request_done(struct ildb_context *ctx,
      75             :                               struct ldb_control **ctrls, int error)
      76             : {
      77         465 :         struct ldb_context *ldb;
      78         465 :         struct ldb_reply *ares;
      79             : 
      80      567890 :         ldb = ldb_module_get_ctx(ctx->module);
      81             : 
      82      567890 :         ctx->done = true;
      83             : 
      84      567890 :         if (ctx->req == NULL) {
      85             :                 /* if the req has been freed already just return */
      86           0 :                 return;
      87             :         }
      88             : 
      89      567890 :         ares = talloc_zero(ctx->req, struct ldb_reply);
      90      567890 :         if (!ares) {
      91           0 :                 ldb_oom(ldb);
      92           0 :                 ctx->req->callback(ctx->req, NULL);
      93           0 :                 return;
      94             :         }
      95      567890 :         ares->type = LDB_REPLY_DONE;
      96      567890 :         ares->controls = talloc_steal(ares, ctrls);
      97      567890 :         ares->error = error;
      98             : 
      99      567890 :         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           0 :         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      154297 : 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         180 :         struct ldap_mod **mods;
     122         180 :         unsigned int i;
     123      154297 :         unsigned int n = 0;
     124             : 
     125             :         /* allocate maximum number of elements needed */
     126      154297 :         mods = talloc_array(mem_ctx, struct ldap_mod *, msg->num_elements+1);
     127      154297 :         if (!mods) {
     128           0 :                 errno = ENOMEM;
     129           0 :                 return NULL;
     130             :         }
     131      154297 :         mods[0] = NULL;
     132             : 
     133      453711 :         for (i = 0; i < msg->num_elements; i++) {
     134      299414 :                 const struct ldb_message_element *el = &msg->elements[i];
     135             : 
     136      299414 :                 mods[n] = talloc(mods, struct ldap_mod);
     137      299414 :                 if (!mods[n]) {
     138           0 :                         goto failed;
     139             :                 }
     140      299414 :                 mods[n + 1] = NULL;
     141      299414 :                 mods[n]->type = 0;
     142      299414 :                 mods[n]->attrib = *el;
     143      299414 :                 if (use_flags) {
     144      113235 :                         switch (el->flags & LDB_FLAG_MOD_MASK) {
     145       31686 :                         case LDB_FLAG_MOD_ADD:
     146       31686 :                                 mods[n]->type = LDAP_MODIFY_ADD;
     147       31686 :                                 break;
     148       21509 :                         case LDB_FLAG_MOD_DELETE:
     149       21509 :                                 mods[n]->type = LDAP_MODIFY_DELETE;
     150       21509 :                                 break;
     151       60026 :                         case LDB_FLAG_MOD_REPLACE:
     152       60026 :                                 mods[n]->type = LDAP_MODIFY_REPLACE;
     153       60026 :                                 break;
     154             :                         }
     155             :                 }
     156      299090 :                 n++;
     157             :         }
     158             : 
     159      154297 :         *num_mods = n;
     160      154297 :         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      238290 : static int ildb_map_error(struct ldb_module *module, NTSTATUS status)
     172             : {
     173         216 :         struct ildb_private *ildb;
     174         216 :         struct ldb_context *ldb;
     175         216 :         TALLOC_CTX *mem_ctx;
     176             : 
     177      238290 :         ildb = talloc_get_type(ldb_module_get_private(module), struct ildb_private);
     178      238290 :         ldb = ldb_module_get_ctx(module);
     179             : 
     180      238290 :         if (NT_STATUS_IS_OK(status)) {
     181      186396 :                 return LDB_SUCCESS;
     182             :         }
     183             : 
     184       51678 :         mem_ctx = talloc_new(ildb);
     185       51678 :         if (!mem_ctx) {
     186           0 :                 ldb_oom(ldb);
     187           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     188             :         }
     189       51678 :         ldb_set_errstring(ldb,
     190             :                           ldap_errstr(ildb->ldap, mem_ctx, status));
     191       51678 :         talloc_free(mem_ctx);
     192       51678 :         if (NT_STATUS_IS_LDAP(status)) {
     193       51678 :                 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     1307246 : static void ildb_callback(struct ldap_request *req)
     211             : {
     212         750 :         struct ldb_context *ldb;
     213         750 :         struct ildb_context *ac;
     214         750 :         NTSTATUS status;
     215         750 :         struct ldap_SearchResEntry *search;
     216         750 :         struct ldap_message *msg;
     217         750 :         struct ldb_control **controls;
     218         750 :         struct ldb_message *ldbmsg;
     219         750 :         char *referral;
     220         750 :         bool callback_failed;
     221         750 :         bool request_done;
     222         750 :         int ret;
     223         750 :         int i;
     224             : 
     225     1307246 :         ac = talloc_get_type(req->async.private_data, struct ildb_context);
     226     1307246 :         ldb = ldb_module_get_ctx(ac->module);
     227     1307246 :         callback_failed = false;
     228     1307246 :         request_done = false;
     229     1307246 :         controls = NULL;
     230             : 
     231             :         /* check if we are already processing this request */
     232     1307246 :         if (ac->in_ildb_callback) {
     233           1 :                 return;
     234             :         }
     235             :         /* mark the request as being in process */
     236     1307245 :         ac->in_ildb_callback = true;
     237             : 
     238     1307245 :         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     1307245 :         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     1307245 :         switch (req->type) {
     251             : 
     252       86586 :         case LDAP_TAG_ModifyRequest:
     253       86586 :                 if (req->replies[0]->type != LDAP_TAG_ModifyResponse) {
     254           0 :                         ret = LDB_ERR_PROTOCOL_ERROR;
     255           0 :                         break;
     256             :                 }
     257       86586 :                 status = ldap_check_response(ac->ireq->conn, &req->replies[0]->r.GeneralResult);
     258       86586 :                 ret = ildb_map_error(ac->module, status);
     259       86586 :                 request_done = true;
     260       86586 :                 break;
     261             : 
     262       67711 :         case LDAP_TAG_AddRequest:
     263       67711 :                 if (req->replies[0]->type != LDAP_TAG_AddResponse) {
     264         750 :                         ret = LDB_ERR_PROTOCOL_ERROR;
     265           0 :                         return;
     266             :                 }
     267       67711 :                 status = ldap_check_response(ac->ireq->conn, &req->replies[0]->r.GeneralResult);
     268       67711 :                 ret = ildb_map_error(ac->module, status);
     269       67711 :                 request_done = true;
     270       67711 :                 break;
     271             : 
     272       75000 :         case LDAP_TAG_DelRequest:
     273       75000 :                 if (req->replies[0]->type != LDAP_TAG_DelResponse) {
     274         750 :                         ret = LDB_ERR_PROTOCOL_ERROR;
     275           0 :                         return;
     276             :                 }
     277       75000 :                 status = ldap_check_response(ac->ireq->conn, &req->replies[0]->r.GeneralResult);
     278       75000 :                 ret = ildb_map_error(ac->module, status);
     279       75000 :                 request_done = true;
     280       75000 :                 break;
     281             : 
     282         384 :         case LDAP_TAG_ModifyDNRequest:
     283         384 :                 if (req->replies[0]->type != LDAP_TAG_ModifyDNResponse) {
     284         750 :                         ret = LDB_ERR_PROTOCOL_ERROR;
     285           0 :                         return;
     286             :                 }
     287         384 :                 status = ldap_check_response(ac->ireq->conn, &req->replies[0]->r.GeneralResult);
     288         384 :                 ret = ildb_map_error(ac->module, status);
     289         384 :                 request_done = true;
     290         384 :                 break;
     291             : 
     292     1076714 :         case LDAP_TAG_SearchRequest:
     293             :                 /* loop over all messages */
     294     1076714 :                 ret = LDB_SUCCESS;
     295     2146202 :                 for (i = 0; i < req->num_replies; i++) {
     296             : 
     297     1077249 :                         msg = req->replies[i];
     298     1077249 :                         switch (msg->type) {
     299             : 
     300      337855 :                         case LDAP_TAG_SearchResultDone:
     301             : 
     302      337855 :                                 status = ldap_check_response(ac->ireq->conn, &msg->r.GeneralResult);
     303      337855 :                                 if (!NT_STATUS_IS_OK(status)) {
     304        8294 :                                         ret = ildb_map_error(ac->module, status);
     305        8294 :                                         break;
     306             :                                 }
     307             : 
     308      329561 :                                 controls = talloc_steal(ac, msg->controls);
     309      329561 :                                 if (msg->r.SearchResultDone.resultcode) {
     310           0 :                                         if (msg->r.SearchResultDone.errormessage) {
     311           0 :                                                 ldb_set_errstring(ldb, msg->r.SearchResultDone.errormessage);
     312             :                                         }
     313             :                                 }
     314             : 
     315      329561 :                                 ret = msg->r.SearchResultDone.resultcode;
     316      329561 :                                 request_done = true;
     317      329561 :                                 break;
     318             : 
     319      606225 :                         case LDAP_TAG_SearchResultEntry:
     320             : 
     321      606225 :                                 ldbmsg = ldb_msg_new(ac);
     322      606225 :                                 if (!ldbmsg) {
     323           0 :                                         ret = LDB_ERR_OPERATIONS_ERROR;
     324           0 :                                         break;
     325             :                                 }
     326             : 
     327      606225 :                                 search = &(msg->r.SearchResultEntry);
     328             : 
     329      606225 :                                 ldbmsg->dn = ldb_dn_new(ldbmsg, ldb, search->dn);
     330      606225 :                                 if ( ! ldb_dn_validate(ldbmsg->dn)) {
     331           0 :                                         ret = LDB_ERR_OPERATIONS_ERROR;
     332           0 :                                         break;
     333             :                                 }
     334      606225 :                                 ldbmsg->num_elements = search->num_attributes;
     335      606225 :                                 ldbmsg->elements = talloc_move(ldbmsg, &search->attributes);
     336             : 
     337      606225 :                                 controls = talloc_steal(ac, msg->controls);
     338             : 
     339      606225 :                                 ret = ldb_module_send_entry(ac->req, ldbmsg, controls);
     340      606225 :                                 if (ret != LDB_SUCCESS) {
     341           0 :                                         callback_failed = true;
     342             :                                 }
     343             : 
     344      605976 :                                 break;
     345             : 
     346      133168 :                         case LDAP_TAG_SearchResultReference:
     347             : 
     348      133168 :                                 referral = talloc_strdup(ac, msg->r.SearchResultReference.referral);
     349             : 
     350      133168 :                                 ret = ldb_module_send_referral(ac->req, referral);
     351      133168 :                                 if (ret != LDB_SUCCESS) {
     352           0 :                                         callback_failed = true;
     353             :                                 }
     354             : 
     355      133132 :                                 break;
     356             : 
     357           1 :                         default:
     358             :                                 /* TAG not handled, fail ! */
     359           1 :                                 ret = LDB_ERR_PROTOCOL_ERROR;
     360           1 :                                 break;
     361             :                         }
     362             : 
     363     1077249 :                         if (ret != LDB_SUCCESS) {
     364        8295 :                                 break;
     365             :                         }
     366             :                 }
     367             : 
     368     1077248 :                 talloc_free(req->replies);
     369     1077248 :                 req->replies = NULL;
     370     1077248 :                 req->num_replies = 0;
     371             : 
     372     1077248 :                 break;
     373             : 
     374         316 :         case LDAP_TAG_ExtendedRequest: {
     375             : 
     376         316 :                 struct ldap_ExtendedResponse *ext_response = NULL;
     377         316 :                 struct ldb_reply *ares = NULL;
     378             : 
     379         316 :                 if (req->replies[0]->type != LDAP_TAG_ExtendedResponse) {
     380         750 :                         ret = LDB_ERR_PROTOCOL_ERROR;
     381           0 :                         return;
     382             :                 }
     383         316 :                 ext_response = &req->replies[0]->r.ExtendedResponse;
     384             : 
     385         316 :                 status = ldap_check_response(ac->ireq->conn,
     386         316 :                                              &req->replies[0]->r.GeneralResult);
     387         316 :                 if (!NT_STATUS_IS_OK(status)) {
     388         315 :                         ret = ildb_map_error(ac->module, status);
     389         315 :                         request_done = true;
     390         315 :                         break;
     391             :                 }
     392             : 
     393           1 :                 ares = talloc_zero(req, struct ldb_reply);
     394           1 :                 if (ares == NULL) {
     395           0 :                         ret = LDB_ERR_OPERATIONS_ERROR;
     396           0 :                         request_done = true;
     397           0 :                         break;
     398             :                 }
     399             : 
     400           1 :                 ares->type = LDB_REPLY_DONE;
     401             : 
     402           1 :                 ares->response = talloc_zero(ares, struct ldb_extended);
     403           1 :                 if (ares->response == NULL) {
     404           0 :                         ret = LDB_ERR_OPERATIONS_ERROR;
     405           0 :                         request_done = true;
     406           0 :                         break;
     407             :                 }
     408             : 
     409           2 :                 ares->response->oid =
     410           1 :                         talloc_strdup(ares->response, ext_response->oid);
     411           1 :                 if (ares->response->oid == NULL) {
     412           0 :                         ret = LDB_ERR_OPERATIONS_ERROR;
     413           0 :                         request_done = true;
     414           0 :                         break;
     415             :                 }
     416             : 
     417           1 :                 if (ext_response->value != NULL) {
     418           2 :                         ares->response->data =
     419           1 :                                 talloc_memdup(ares->response,
     420             :                                               ext_response->value->data,
     421             :                                               ext_response->value->length);
     422           1 :                         if (ares->response->data == NULL) {
     423           0 :                                 ret = LDB_ERR_OPERATIONS_ERROR;
     424           0 :                                 request_done = true;
     425           0 :                                 break;
     426             :                         }
     427             :                 }
     428             : 
     429           1 :                 ares->controls = talloc_move(ares, &req->replies[0]->controls);
     430             : 
     431           1 :                 ac->req->callback(ac->req, ares);
     432           1 :                 return;
     433             :         }
     434             : 
     435           0 :         default:
     436           0 :                 ret = LDB_ERR_PROTOCOL_ERROR;
     437           0 :                 break;
     438             :         }
     439             : 
     440     1307244 :         if (ret != LDB_SUCCESS) {
     441             : 
     442             :                 /* if the callback failed the caller will have freed the
     443             :                  * request. Just return and don't try to use it */
     444       51679 :                 if ( ! callback_failed) {
     445       51679 :                         request_done = true;
     446             :                 }
     447             :         }
     448             : 
     449             :         /* mark the request as not being in progress */
     450     1307244 :         ac->in_ildb_callback = false;
     451             : 
     452     1307244 :         if (request_done) {
     453      567852 :                 ildb_request_done(ac, controls, ret);
     454             :         }
     455             : 
     456     1306494 :         return;
     457             : }
     458             : 
     459      567932 : static int ildb_request_send(struct ildb_context *ac, struct ldap_message *msg)
     460             : {
     461         465 :         struct ldb_context *ldb;
     462         465 :         struct ldap_request *req;
     463             : 
     464      567932 :         if (!ac) {
     465           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     466             :         }
     467             : 
     468      567932 :         ldb = ldb_module_get_ctx(ac->module);
     469             : 
     470      567932 :         ldb_request_set_state(ac->req, LDB_ASYNC_PENDING);
     471             : 
     472      567932 :         req = ldap_request_send(ac->ildb->ldap, msg);
     473      567932 :         if (req == NULL) {
     474           0 :                 ldb_set_errstring(ldb, "async send request failed");
     475           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     476             :         }
     477      567932 :         ac->ireq = talloc_reparent(ac->ildb->ldap, ac, req);
     478             : 
     479      567932 :         if (!ac->ireq->conn) {
     480           0 :                 ldb_set_errstring(ldb, "connection to remote LDAP server dropped?");
     481           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     482             :         }
     483             : 
     484      567932 :         TALLOC_FREE(req->time_event);
     485      567932 :         if (ac->req->timeout > 0) {
     486      567867 :                 struct timeval tv = {
     487      567867 :                         .tv_sec = ac->req->starttime + ac->req->timeout,
     488             :                 };
     489             : 
     490      567867 :                 req->time_event = tevent_add_timer(ac->ildb->event_ctx, ac, tv,
     491             :                                                    ildb_request_timeout, ac);
     492             :         }
     493             : 
     494      567932 :         req->async.fn = ildb_callback;
     495      567932 :         req->async.private_data = ac;
     496             : 
     497      567932 :         return LDB_SUCCESS;
     498             : }
     499             : 
     500             : /*
     501             :   search for matching records using an asynchronous function
     502             :  */
     503      337935 : static int ildb_search(struct ildb_context *ac)
     504             : {
     505         249 :         struct ldb_context *ldb;
     506      337935 :         struct ldb_request *req = ac->req;
     507         249 :         struct ldap_message *msg;
     508         249 :         int n;
     509             : 
     510      337935 :         ldb = ldb_module_get_ctx(ac->module);
     511             : 
     512      337935 :         if (!req->callback || !req->context) {
     513           0 :                 ldb_set_errstring(ldb, "Async interface called with NULL callback function or NULL context");
     514           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     515             :         }
     516             : 
     517      337935 :         if (req->op.search.tree == NULL) {
     518           0 :                 ldb_set_errstring(ldb, "Invalid expression parse tree");
     519           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     520             :         }
     521             : 
     522      337935 :         msg = new_ldap_message(req);
     523      337935 :         if (msg == NULL) {
     524           0 :                 ldb_set_errstring(ldb, "Out of Memory");
     525           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     526             :         }
     527             : 
     528      337935 :         msg->type = LDAP_TAG_SearchRequest;
     529             : 
     530      337935 :         if (req->op.search.base == NULL) {
     531           0 :                 msg->r.SearchRequest.basedn = talloc_strdup(msg, "");
     532             :         } else {
     533      337935 :                 msg->r.SearchRequest.basedn  = ldb_dn_get_extended_linearized(msg, req->op.search.base, 0);
     534             :         }
     535      337935 :         if (msg->r.SearchRequest.basedn == NULL) {
     536           0 :                 ldb_set_errstring(ldb, "Unable to determine baseDN");
     537           0 :                 talloc_free(msg);
     538           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     539             :         }
     540             : 
     541      337935 :         switch (req->op.search.scope) {
     542       88220 :         case LDB_SCOPE_DEFAULT:
     543             :         case LDB_SCOPE_SUBTREE:
     544       88220 :                 msg->r.SearchRequest.scope = LDAP_SEARCH_SCOPE_SUB;
     545       88220 :                 break;
     546      171420 :         case LDB_SCOPE_BASE:
     547      171420 :                 msg->r.SearchRequest.scope = LDAP_SEARCH_SCOPE_BASE;
     548      171420 :                 break;
     549       78295 :         case LDB_SCOPE_ONELEVEL:
     550       78295 :                 msg->r.SearchRequest.scope = LDAP_SEARCH_SCOPE_SINGLE;
     551       78295 :                 break;
     552             :         }
     553             : 
     554      337935 :         msg->r.SearchRequest.deref  = LDAP_DEREFERENCE_NEVER;
     555      337935 :         msg->r.SearchRequest.timelimit = 0;
     556      337935 :         msg->r.SearchRequest.sizelimit = 0;
     557      337935 :         msg->r.SearchRequest.attributesonly = 0;
     558      337935 :         msg->r.SearchRequest.tree = discard_const(req->op.search.tree);
     559             : 
     560      931988 :         for (n = 0; req->op.search.attrs && req->op.search.attrs[n]; n++) /* noop */ ;
     561      337935 :         msg->r.SearchRequest.num_attributes = n;
     562      337935 :         msg->r.SearchRequest.attributes = req->op.search.attrs;
     563      337935 :         msg->controls = req->controls;
     564             : 
     565      337935 :         return ildb_request_send(ac, msg);
     566             : }
     567             : 
     568             : /*
     569             :   add a record
     570             : */
     571       67711 : static int ildb_add(struct ildb_context *ac)
     572             : {
     573       67711 :         struct ldb_request *req = ac->req;
     574          36 :         struct ldap_message *msg;
     575          36 :         struct ldap_mod **mods;
     576          36 :         unsigned int i,n;
     577             : 
     578       67711 :         msg = new_ldap_message(req);
     579       67711 :         if (msg == NULL) {
     580           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     581             :         }
     582             : 
     583       67711 :         msg->type = LDAP_TAG_AddRequest;
     584             : 
     585       67711 :         msg->r.AddRequest.dn = ldb_dn_get_extended_linearized(msg, req->op.add.message->dn, 0);
     586       67711 :         if (msg->r.AddRequest.dn == NULL) {
     587           0 :                 talloc_free(msg);
     588           0 :                 return LDB_ERR_INVALID_DN_SYNTAX;
     589             :         }
     590             : 
     591       67711 :         mods = ildb_msg_to_mods(msg, &n, req->op.add.message, 0);
     592       67711 :         if (mods == NULL) {
     593           0 :                 talloc_free(msg);
     594           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     595             :         }
     596             : 
     597       67711 :         msg->r.AddRequest.num_attributes = n;
     598       67711 :         msg->r.AddRequest.attributes = talloc_array(msg, struct ldb_message_element, n);
     599       67711 :         if (msg->r.AddRequest.attributes == NULL) {
     600           0 :                 talloc_free(msg);
     601           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     602             :         }
     603             : 
     604      253890 :         for (i = 0; i < n; i++) {
     605      186179 :                 msg->r.AddRequest.attributes[i] = mods[i]->attrib;
     606             :         }
     607       67711 :         msg->controls = req->controls;
     608             : 
     609       67711 :         return ildb_request_send(ac, msg);
     610             : }
     611             : 
     612             : /*
     613             :   modify a record
     614             : */
     615       86586 : static int ildb_modify(struct ildb_context *ac)
     616             : {
     617       86586 :         struct ldb_request *req = ac->req;
     618         144 :         struct ldap_message *msg;
     619         144 :         struct ldap_mod **mods;
     620         144 :         unsigned int i,n;
     621             : 
     622       86586 :         msg = new_ldap_message(req);
     623       86586 :         if (msg == NULL) {
     624           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     625             :         }
     626             : 
     627       86586 :         msg->type = LDAP_TAG_ModifyRequest;
     628             : 
     629       86586 :         msg->r.ModifyRequest.dn = ldb_dn_get_extended_linearized(msg, req->op.mod.message->dn, 0);
     630       86586 :         if (msg->r.ModifyRequest.dn == NULL) {
     631           0 :                 talloc_free(msg);
     632           0 :                 return LDB_ERR_INVALID_DN_SYNTAX;
     633             :         }
     634             : 
     635       86586 :         mods = ildb_msg_to_mods(msg, &n, req->op.mod.message, 1);
     636       86586 :         if (mods == NULL) {
     637           0 :                 talloc_free(msg);
     638           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     639             :         }
     640             : 
     641       86586 :         msg->r.ModifyRequest.num_mods = n;
     642       86586 :         msg->r.ModifyRequest.mods = talloc_array(msg, struct ldap_mod, n);
     643       86586 :         if (msg->r.ModifyRequest.mods == NULL) {
     644           0 :                 talloc_free(msg);
     645           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     646             :         }
     647             : 
     648      199821 :         for (i = 0; i < n; i++) {
     649      113235 :                 msg->r.ModifyRequest.mods[i] = *mods[i];
     650             :         }
     651       86586 :         msg->controls = req->controls;
     652       86586 :         return ildb_request_send(ac, msg);
     653             : }
     654             : 
     655             : /*
     656             :   delete a record
     657             : */
     658       75000 : static int ildb_delete(struct ildb_context *ac)
     659             : {
     660       75000 :         struct ldb_request *req = ac->req;
     661          36 :         struct ldap_message *msg;
     662             : 
     663       75000 :         msg = new_ldap_message(req);
     664       75000 :         if (msg == NULL) {
     665           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     666             :         }
     667             : 
     668       75000 :         msg->type = LDAP_TAG_DelRequest;
     669             : 
     670       75000 :         msg->r.DelRequest.dn = ldb_dn_get_extended_linearized(msg, req->op.del.dn, 0);
     671       75000 :         if (msg->r.DelRequest.dn == NULL) {
     672           0 :                 talloc_free(msg);
     673           0 :                 return LDB_ERR_INVALID_DN_SYNTAX;
     674             :         }
     675       75000 :         msg->controls = req->controls;
     676             : 
     677       75000 :         return ildb_request_send(ac, msg);
     678             : }
     679             : 
     680             : /*
     681             :   rename a record
     682             : */
     683         384 : static int ildb_rename(struct ildb_context *ac)
     684             : {
     685         384 :         struct ldb_request *req = ac->req;
     686           0 :         struct ldap_message *msg;
     687           0 :         const char *rdn_name;
     688           0 :         const struct ldb_val *rdn_val;
     689             : 
     690         384 :         msg = new_ldap_message(req);
     691         384 :         if (msg == NULL) {
     692           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     693             :         }
     694             : 
     695         384 :         msg->type = LDAP_TAG_ModifyDNRequest;
     696         384 :         msg->r.ModifyDNRequest.dn = ldb_dn_get_extended_linearized(msg, req->op.rename.olddn, 0);
     697         384 :         if (msg->r.ModifyDNRequest.dn == NULL) {
     698           0 :                 talloc_free(msg);
     699           0 :                 return LDB_ERR_INVALID_DN_SYNTAX;
     700             :         }
     701             : 
     702         384 :         rdn_name = ldb_dn_get_rdn_name(req->op.rename.newdn);
     703         384 :         rdn_val = ldb_dn_get_rdn_val(req->op.rename.newdn);
     704             : 
     705         384 :         if ((rdn_name != NULL) && (rdn_val != NULL)) {
     706         384 :                 msg->r.ModifyDNRequest.newrdn =
     707         384 :                         talloc_asprintf(msg, "%s=%s", rdn_name,
     708         384 :                                         rdn_val->length > 0 ? ldb_dn_escape_value(msg, *rdn_val) : "");
     709             :         } else {
     710           0 :                 msg->r.ModifyDNRequest.newrdn = talloc_strdup(msg, "");
     711             :         }
     712         384 :         if (msg->r.ModifyDNRequest.newrdn == NULL) {
     713           0 :                 talloc_free(msg);
     714           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     715             :         }
     716             : 
     717         384 :         msg->r.ModifyDNRequest.newsuperior =
     718         384 :                 ldb_dn_alloc_linearized(msg, ldb_dn_get_parent(msg, req->op.rename.newdn));
     719         384 :         if (msg->r.ModifyDNRequest.newsuperior == NULL) {
     720           0 :                 talloc_free(msg);
     721           0 :                 return LDB_ERR_INVALID_DN_SYNTAX;
     722             :         }
     723             : 
     724         384 :         msg->r.ModifyDNRequest.deleteolddn = true;
     725         384 :         msg->controls = req->controls;
     726             : 
     727         384 :         return ildb_request_send(ac, msg);
     728             : }
     729             : 
     730             : /*
     731             :  * Issue an extended operation
     732             :  */
     733         316 : static int ildb_extended(struct ildb_context *ac)
     734             : {
     735         316 :         struct ldb_request *req = ac->req;
     736         316 :         struct ldb_extended *extended_req = NULL;
     737         316 :         struct ldap_message *msg = NULL;
     738         316 :         DATA_BLOB *value = NULL;
     739             : 
     740         316 :         if (req->operation != LDB_EXTENDED) {
     741           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     742             :         }
     743         316 :         extended_req = &req->op.extended;
     744             : 
     745         316 :         msg = new_ldap_message(req);
     746         316 :         if (msg == NULL) {
     747           0 :                 goto nomem;
     748             :         }
     749             : 
     750         316 :         if (extended_req->data != NULL) {
     751         315 :                 value = talloc(req, DATA_BLOB);
     752         315 :                 if (value == NULL) {
     753           0 :                         goto nomem;
     754             :                 }
     755         315 :                 *value = data_blob_talloc(value,
     756             :                                           extended_req->data,
     757             :                                           talloc_get_size(extended_req->data));
     758         315 :                 if (value->data == NULL) {
     759           0 :                         goto nomem;
     760             :                 }
     761             :         }
     762             : 
     763         316 :         *msg = (struct ldap_message){
     764             :                 .type = LDAP_TAG_ExtendedRequest,
     765         316 :                 .r.ExtendedRequest.oid = extended_req->oid,
     766             :                 .r.ExtendedRequest.value = value,
     767         316 :                 .controls = req->controls,
     768             :         };
     769             : 
     770         316 :         return ildb_request_send(ac, msg);
     771           0 : nomem:
     772           0 :         TALLOC_FREE(msg);
     773           0 :         return LDB_ERR_OPERATIONS_ERROR;
     774             : }
     775             : 
     776      197141 : static int ildb_start_trans(struct ldb_module *module)
     777             : {
     778             :         /* TODO implement a local locking mechanism here */
     779             : 
     780      197141 :         return LDB_SUCCESS;
     781             : }
     782             : 
     783      154188 : static int ildb_end_trans(struct ldb_module *module)
     784             : {
     785             :         /* TODO implement a local transaction mechanism here */
     786             : 
     787      154188 :         return LDB_SUCCESS;
     788             : }
     789             : 
     790       42951 : static int ildb_del_trans(struct ldb_module *module)
     791             : {
     792             :         /* TODO implement a local locking mechanism here */
     793             : 
     794       42951 :         return LDB_SUCCESS;
     795             : }
     796             : 
     797      567956 : static bool ildb_dn_is_special(struct ldb_request *req)
     798             : {
     799      567956 :         struct ldb_dn *dn = NULL;
     800             : 
     801      567956 :         switch (req->operation) {
     802      337947 :         case LDB_SEARCH:
     803      337947 :                 dn = req->op.search.base;
     804      337947 :                 break;
     805       67723 :         case LDB_ADD:
     806       67723 :                 dn = req->op.add.message->dn;
     807       67723 :                 break;
     808       86586 :         case LDB_MODIFY:
     809       86586 :                 dn = req->op.mod.message->dn;
     810       86586 :                 break;
     811       75000 :         case LDB_DELETE:
     812       75000 :                 dn = req->op.del.dn;
     813       75000 :                 break;
     814         384 :         case LDB_RENAME:
     815         384 :                 dn = req->op.rename.olddn;
     816         384 :                 break;
     817         316 :         default:
     818         316 :                 break;
     819             :         }
     820             : 
     821      567956 :         if (dn && ldb_dn_is_special(dn)) {
     822          24 :                 return true;
     823             :         }
     824      567467 :         return false;
     825             : }
     826             : 
     827      567956 : static int ildb_handle_request(struct ldb_module *module, struct ldb_request *req)
     828             : {
     829         465 :         struct ldb_context *ldb;
     830         465 :         struct ildb_private *ildb;
     831         465 :         struct ildb_context *ac;
     832         465 :         struct tevent_timer *te;
     833         465 :         int ret;
     834             : 
     835      567956 :         ildb = talloc_get_type(ldb_module_get_private(module), struct ildb_private);
     836      567956 :         ldb = ldb_module_get_ctx(module);
     837             : 
     838      567956 :         if (req->starttime == 0 || req->timeout == 0) {
     839           0 :                 ldb_set_errstring(ldb, "Invalid timeout settings");
     840           0 :                 return LDB_ERR_TIME_LIMIT_EXCEEDED;
     841             :         }
     842             : 
     843      567956 :         ac = talloc_zero(req, struct ildb_context);
     844      567956 :         if (ac == NULL) {
     845           0 :                 ldb_set_errstring(ldb, "Out of Memory");
     846           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     847             :         }
     848             : 
     849      567956 :         ac->module = module;
     850      567956 :         ac->req = req;
     851      567956 :         ac->ildb = ildb;
     852             : 
     853      567956 :         if (ildb_dn_is_special(req)) {
     854             : 
     855          24 :                 te = tevent_add_timer(ac->ildb->event_ctx,
     856             :                                       ac, timeval_zero(),
     857             :                                       ildb_auto_done_callback, ac);
     858          24 :                 if (NULL == te) {
     859           0 :                         return LDB_ERR_OPERATIONS_ERROR;
     860             :                 }
     861             : 
     862          24 :                 return LDB_SUCCESS;
     863             :         }
     864             : 
     865      567932 :         switch (ac->req->operation) {
     866      337935 :         case LDB_SEARCH:
     867      337935 :                 ret = ildb_search(ac);
     868      337935 :                 break;
     869       67711 :         case LDB_ADD:
     870       67711 :                 ret = ildb_add(ac);
     871       67711 :                 break;
     872       86586 :         case LDB_MODIFY:
     873       86586 :                 ret = ildb_modify(ac);
     874       86586 :                 break;
     875       75000 :         case LDB_DELETE:
     876       75000 :                 ret = ildb_delete(ac);
     877       75000 :                 break;
     878         384 :         case LDB_RENAME:
     879         384 :                 ret = ildb_rename(ac);
     880         384 :                 break;
     881         316 :         case LDB_EXTENDED:
     882         316 :                 ret = ildb_extended(ac);
     883         316 :                 break;
     884           0 :         default:
     885             :                 /* no other op supported */
     886           0 :                 ret = LDB_ERR_PROTOCOL_ERROR;
     887           0 :                 break;
     888             :         }
     889             : 
     890      567467 :         return ret;
     891             : }
     892             : 
     893             : static const struct ldb_module_ops ildb_ops = {
     894             :         .name              = "ldap",
     895             :         .search            = ildb_handle_request,
     896             :         .add               = ildb_handle_request,
     897             :         .modify            = ildb_handle_request,
     898             :         .del               = ildb_handle_request,
     899             :         .rename            = ildb_handle_request,
     900             :         .extended          = ildb_handle_request,
     901             : /*      .request           = ildb_handle_request, */
     902             :         .start_transaction = ildb_start_trans,
     903             :         .end_transaction   = ildb_end_trans,
     904             :         .del_transaction   = ildb_del_trans,
     905             : };
     906             : 
     907             : /*
     908             :   connect to the database
     909             : */
     910       26714 : static int ildb_connect(struct ldb_context *ldb, const char *url,
     911             :                         unsigned int flags, const char *options[],
     912             :                         struct ldb_module **_module)
     913             : {
     914         122 :         struct ldb_module *module;
     915         122 :         struct ildb_private *ildb;
     916       26714 :         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
     917         122 :         struct cli_credentials *creds;
     918         122 :         struct loadparm_context *lp_ctx;
     919             : 
     920       26714 :         module = ldb_module_new(ldb, ldb, "ldb_ildap backend", &ildb_ops);
     921       26714 :         if (!module) return LDB_ERR_OPERATIONS_ERROR;
     922             : 
     923       26714 :         ildb = talloc(module, struct ildb_private);
     924       26714 :         if (!ildb) {
     925           0 :                 ldb_oom(ldb);
     926           0 :                 goto failed;
     927             :         }
     928       26714 :         ldb_module_set_private(module, ildb);
     929             : 
     930       26714 :         ildb->event_ctx = ldb_get_event_context(ldb);
     931             : 
     932       26714 :         lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
     933             :                                  struct loadparm_context);
     934             : 
     935       26714 :         ildb->ldap = ldap4_new_connection(ildb, lp_ctx,
     936             :                                           ildb->event_ctx);
     937       26714 :         if (!ildb->ldap) {
     938           0 :                 ldb_oom(ldb);
     939           0 :                 goto failed;
     940             :         }
     941             : 
     942       26714 :         if (flags & LDB_FLG_RECONNECT) {
     943           0 :                 ldap_set_reconn_params(ildb->ldap, 10);
     944             :         }
     945             : 
     946       26714 :         status = ldap_connect(ildb->ldap, url);
     947       26714 :         if (!NT_STATUS_IS_OK(status)) {
     948          19 :                 ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to connect to ldap URL '%s' - %s",
     949             :                           url, ldap_errstr(ildb->ldap, module, status));
     950          19 :                 goto failed;
     951             :         }
     952             : 
     953             :         /* caller can optionally setup credentials using the opaque token 'credentials' */
     954       26695 :         creds = talloc_get_type(ldb_get_opaque(ldb, "credentials"), struct cli_credentials);
     955       26695 :         if (creds == NULL) {
     956          11 :                 struct auth_session_info *session_info = talloc_get_type(
     957             :                         ldb_get_opaque(ldb, DSDB_SESSION_INFO),
     958             :                         struct auth_session_info);
     959          11 :                 if (session_info) {
     960           8 :                         creds = session_info->credentials;
     961             :                 }
     962             :         }
     963             : 
     964       26695 :         if (creds != NULL && cli_credentials_authentication_requested(creds)) {
     965       26543 :                 const char *bind_dn = cli_credentials_get_bind_dn(creds);
     966       26543 :                 if (bind_dn) {
     967         442 :                         const char *password = cli_credentials_get_password(creds);
     968         442 :                         status = ldap_bind_simple(ildb->ldap, bind_dn, password);
     969         442 :                         if (!NT_STATUS_IS_OK(status)) {
     970         124 :                                 ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to bind - %s",
     971             :                                           ldap_errstr(ildb->ldap, module, status));
     972         124 :                                 goto failed;
     973             :                         }
     974             :                 } else {
     975       26101 :                         status = ldap_bind_sasl(ildb->ldap, creds, lp_ctx);
     976       26101 :                         if (!NT_STATUS_IS_OK(status)) {
     977         471 :                                 ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to bind - %s",
     978             :                                           ldap_errstr(ildb->ldap, module, status));
     979         471 :                                 goto failed;
     980             :                         }
     981             :                 }
     982             :         }
     983             : 
     984       26100 :         *_module = module;
     985       26100 :         return LDB_SUCCESS;
     986             : 
     987         614 : failed:
     988         614 :         if (ildb != NULL && ildb->ldap != NULL) {
     989         614 :                 ldb_set_errstring(ldb, ldap_errstr(ildb->ldap, module, status));
     990             :         }
     991         614 :         talloc_free(module);
     992         614 :         if (NT_STATUS_IS_LDAP(status)) {
     993         323 :                 return NT_STATUS_LDAP_CODE(status);
     994             :         }
     995         291 :         if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)
     996         291 :                    || NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)
     997         291 :                    || NT_STATUS_EQUAL(status, NT_STATUS_LOGON_FAILURE)
     998         136 :                    || NT_STATUS_EQUAL(status, NT_STATUS_ACCOUNT_LOCKED_OUT)) {
     999         176 :                 return LDB_ERR_INVALID_CREDENTIALS;
    1000             :         }
    1001         115 :         return LDB_ERR_OPERATIONS_ERROR;
    1002             : }
    1003             : 
    1004             : /*
    1005             :   initialise the module
    1006             :  */
    1007        6091 : _PUBLIC_ int ldb_ildap_init(const char *ldb_version)
    1008             : {
    1009         444 :         int ret, i;
    1010        6091 :         const char *names[] = { "ldap", "ldaps", "ldapi", NULL };
    1011       24364 :         for (i=0; names[i]; i++) {
    1012       18273 :                 ret = ldb_register_backend(names[i], ildb_connect, true);
    1013       18273 :                 if (ret != LDB_SUCCESS) {
    1014           0 :                         return ret;
    1015             :                 }
    1016             :         }
    1017        5647 :         return LDB_SUCCESS;
    1018             : }

Generated by: LCOV version 1.14