root/source4/lib/ldb/ldb_ildap/ldb_ildap.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ildb_request_done
  2. ildb_auto_done_callback
  3. ildb_msg_to_mods
  4. ildb_map_error
  5. ildb_request_timeout
  6. ildb_callback
  7. ildb_request_send
  8. ildb_search
  9. ildb_add
  10. ildb_modify
  11. ildb_delete
  12. ildb_rename
  13. ildb_start_trans
  14. ildb_end_trans
  15. ildb_del_trans
  16. ildb_dn_is_special
  17. ildb_handle_request
  18. ildb_connect

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

/* [<][>][^][v][top][bottom][index][help] */