root/source4/lib/ldb/ldb_ldap/ldb_ldap.c

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

DEFINITIONS

This source file includes following definitions.
  1. lldb_ldap_to_ldb
  2. lldb_msg_to_mods
  3. lldb_add_msg_attr
  4. lldb_search
  5. lldb_add
  6. lldb_modify
  7. lldb_delete
  8. lldb_rename
  9. lldb_start_trans
  10. lldb_end_trans
  11. lldb_del_trans
  12. lldb_request_done
  13. lldb_parse_result
  14. lldb_timeout
  15. lldb_callback
  16. lldb_dn_is_special
  17. lldb_auto_done_callback
  18. lldb_handle_request
  19. lldb_destructor
  20. lldb_connect

   1 /* 
   2    ldb database library
   3 
   4    Copyright (C) Andrew Tridgell  2004
   5    Copyright (C) Simo Sorce       2006
   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_ldap
  27  *
  28  *  Component: ldb ldap backend
  29  *
  30  *  Description: core files for LDAP backend
  31  *
  32  *  Author: Andrew Tridgell
  33  *
  34  *  Modifications:
  35  *
  36  *  - description: make the module use asyncronous calls
  37  *    date: Feb 2006
  38  *    author: Simo Sorce
  39  */
  40 
  41 #include "ldb_includes.h"
  42 #include "ldb_module.h"
  43 
  44 #define LDAP_DEPRECATED 1
  45 #include <ldap.h>
  46 
  47 struct lldb_private {
  48         LDAP *ldap;
  49 };
  50 
  51 struct lldb_context {
  52         struct ldb_module *module;
  53         struct ldb_request *req;
  54 
  55         struct lldb_private *lldb;
  56 
  57         struct ldb_control **controls;
  58         int msgid;
  59 };
  60 
  61 static int lldb_ldap_to_ldb(int err) {
     /* [<][>][^][v][top][bottom][index][help] */
  62         /* Ldap errors and ldb errors are defined to the same values */
  63         return err;
  64 }
  65 
  66 /*
  67   convert a ldb_message structure to a list of LDAPMod structures
  68   ready for ldap_add() or ldap_modify()
  69 */
  70 static LDAPMod **lldb_msg_to_mods(void *mem_ctx, const struct ldb_message *msg, int use_flags)
     /* [<][>][^][v][top][bottom][index][help] */
  71 {
  72         LDAPMod **mods;
  73         unsigned int i, j;
  74         int num_mods = 0;
  75 
  76         /* allocate maximum number of elements needed */
  77         mods = talloc_array(mem_ctx, LDAPMod *, msg->num_elements+1);
  78         if (!mods) {
  79                 errno = ENOMEM;
  80                 return NULL;
  81         }
  82         mods[0] = NULL;
  83 
  84         for (i=0;i<msg->num_elements;i++) {
  85                 const struct ldb_message_element *el = &msg->elements[i];
  86 
  87                 mods[num_mods] = talloc(mods, LDAPMod);
  88                 if (!mods[num_mods]) {
  89                         goto failed;
  90                 }
  91                 mods[num_mods+1] = NULL;
  92                 mods[num_mods]->mod_op = LDAP_MOD_BVALUES;
  93                 if (use_flags) {
  94                         switch (el->flags & LDB_FLAG_MOD_MASK) {
  95                         case LDB_FLAG_MOD_ADD:
  96                                 mods[num_mods]->mod_op |= LDAP_MOD_ADD;
  97                                 break;
  98                         case LDB_FLAG_MOD_DELETE:
  99                                 mods[num_mods]->mod_op |= LDAP_MOD_DELETE;
 100                                 break;
 101                         case LDB_FLAG_MOD_REPLACE:
 102                                 mods[num_mods]->mod_op |= LDAP_MOD_REPLACE;
 103                                 break;
 104                         }
 105                 }
 106                 mods[num_mods]->mod_type = discard_const_p(char, el->name);
 107                 mods[num_mods]->mod_vals.modv_bvals = talloc_array(mods[num_mods], 
 108                                                                    struct berval *,
 109                                                                    1+el->num_values);
 110                 if (!mods[num_mods]->mod_vals.modv_bvals) {
 111                         goto failed;
 112                 }
 113 
 114                 for (j=0;j<el->num_values;j++) {
 115                         mods[num_mods]->mod_vals.modv_bvals[j] = talloc(mods[num_mods]->mod_vals.modv_bvals,
 116                                                                         struct berval);
 117                         if (!mods[num_mods]->mod_vals.modv_bvals[j]) {
 118                                 goto failed;
 119                         }
 120                         mods[num_mods]->mod_vals.modv_bvals[j]->bv_val = el->values[j].data;
 121                         mods[num_mods]->mod_vals.modv_bvals[j]->bv_len = el->values[j].length;
 122                 }
 123                 mods[num_mods]->mod_vals.modv_bvals[j] = NULL;
 124                 num_mods++;
 125         }
 126 
 127         return mods;
 128 
 129 failed:
 130         talloc_free(mods);
 131         return NULL;
 132 }
 133 
 134 /*
 135   add a single set of ldap message values to a ldb_message
 136 */
 137 static int lldb_add_msg_attr(struct ldb_context *ldb,
     /* [<][>][^][v][top][bottom][index][help] */
 138                              struct ldb_message *msg, 
 139                              const char *attr, struct berval **bval)
 140 {
 141         int count, i;
 142         struct ldb_message_element *el;
 143 
 144         count = ldap_count_values_len(bval);
 145 
 146         if (count <= 0) {
 147                 return -1;
 148         }
 149 
 150         el = talloc_realloc(msg, msg->elements, struct ldb_message_element, 
 151                               msg->num_elements + 1);
 152         if (!el) {
 153                 errno = ENOMEM;
 154                 return -1;
 155         }
 156 
 157         msg->elements = el;
 158 
 159         el = &msg->elements[msg->num_elements];
 160 
 161         el->name = talloc_strdup(msg->elements, attr);
 162         if (!el->name) {
 163                 errno = ENOMEM;
 164                 return -1;
 165         }
 166         el->flags = 0;
 167 
 168         el->num_values = 0;
 169         el->values = talloc_array(msg->elements, struct ldb_val, count);
 170         if (!el->values) {
 171                 errno = ENOMEM;
 172                 return -1;
 173         }
 174 
 175         for (i=0;i<count;i++) {
 176                 /* we have to ensure this is null terminated so that
 177                    ldb_msg_find_attr_as_string() can work */
 178                 el->values[i].data = talloc_size(el->values, bval[i]->bv_len+1);
 179                 if (!el->values[i].data) {
 180                         errno = ENOMEM;
 181                         return -1;
 182                 }
 183                 memcpy(el->values[i].data, bval[i]->bv_val, bval[i]->bv_len);
 184                 el->values[i].data[bval[i]->bv_len] = 0;
 185                 el->values[i].length = bval[i]->bv_len;
 186                 el->num_values++;
 187         }
 188 
 189         msg->num_elements++;
 190 
 191         return 0;
 192 }
 193 
 194 /*
 195   search for matching records
 196 */
 197 static int lldb_search(struct lldb_context *lldb_ac)
     /* [<][>][^][v][top][bottom][index][help] */
 198 {
 199         struct ldb_context *ldb;
 200         struct lldb_private *lldb = lldb_ac->lldb;
 201         struct ldb_module *module = lldb_ac->module;
 202         struct ldb_request *req = lldb_ac->req;
 203         struct timeval tv;
 204         int ldap_scope;
 205         char *search_base;
 206         char *expression;
 207         int ret;
 208 
 209         ldb = ldb_module_get_ctx(module);
 210 
 211         if (!req->callback || !req->context) {
 212                 ldb_set_errstring(ldb, "Async interface called with NULL callback function or NULL context");
 213                 return LDB_ERR_OPERATIONS_ERROR;
 214         }
 215 
 216         if (req->op.search.tree == NULL) {
 217                 ldb_set_errstring(ldb, "Invalid expression parse tree");
 218                 return LDB_ERR_OPERATIONS_ERROR;
 219         }
 220 
 221         if (req->controls != NULL) {
 222                 ldb_debug(ldb, LDB_DEBUG_WARNING, "Controls are not yet supported by ldb_ldap backend!\n");
 223         }
 224 
 225         ldb_request_set_state(req, LDB_ASYNC_PENDING);
 226 
 227         search_base = ldb_dn_alloc_linearized(lldb_ac, req->op.search.base);
 228         if (req->op.search.base == NULL) {
 229                 search_base = talloc_strdup(lldb_ac, "");
 230         }
 231         if (search_base == NULL) {
 232                 return LDB_ERR_OPERATIONS_ERROR;
 233         }
 234 
 235         expression = ldb_filter_from_tree(lldb_ac, req->op.search.tree);
 236         if (expression == NULL) {
 237                 return LDB_ERR_OPERATIONS_ERROR;
 238         }
 239 
 240         switch (req->op.search.scope) {
 241         case LDB_SCOPE_BASE:
 242                 ldap_scope = LDAP_SCOPE_BASE;
 243                 break;
 244         case LDB_SCOPE_ONELEVEL:
 245                 ldap_scope = LDAP_SCOPE_ONELEVEL;
 246                 break;
 247         default:
 248                 ldap_scope = LDAP_SCOPE_SUBTREE;
 249                 break;
 250         }
 251 
 252         tv.tv_sec = req->timeout;
 253         tv.tv_usec = 0;
 254 
 255         ret = ldap_search_ext(lldb->ldap, search_base, ldap_scope, 
 256                             expression, 
 257                             discard_const_p(char *, req->op.search.attrs), 
 258                             0,
 259                             NULL,
 260                             NULL,
 261                             &tv,
 262                             LDAP_NO_LIMIT,
 263                             &lldb_ac->msgid);
 264 
 265         if (ret != LDAP_SUCCESS) {
 266                 ldb_set_errstring(ldb, ldap_err2string(ret));
 267         }
 268 
 269         return lldb_ldap_to_ldb(ret);
 270 }
 271 
 272 /*
 273   add a record
 274 */
 275 static int lldb_add(struct lldb_context *lldb_ac)
     /* [<][>][^][v][top][bottom][index][help] */
 276 {
 277         struct ldb_context *ldb;
 278         struct lldb_private *lldb = lldb_ac->lldb;
 279         struct ldb_module *module = lldb_ac->module;
 280         struct ldb_request *req = lldb_ac->req;
 281         LDAPMod **mods;
 282         char *dn;
 283         int ret;
 284 
 285         ldb_module_get_ctx(module);
 286 
 287         ldb_request_set_state(req, LDB_ASYNC_PENDING);
 288 
 289         mods = lldb_msg_to_mods(lldb_ac, req->op.add.message, 0);
 290         if (mods == NULL) {
 291                 return LDB_ERR_OPERATIONS_ERROR;
 292         }
 293 
 294         dn = ldb_dn_alloc_linearized(lldb_ac, req->op.add.message->dn);
 295         if (dn == NULL) {
 296                 return LDB_ERR_OPERATIONS_ERROR;
 297         }
 298 
 299         ret = ldap_add_ext(lldb->ldap, dn, mods,
 300                            NULL,
 301                            NULL,
 302                            &lldb_ac->msgid);
 303 
 304         if (ret != LDAP_SUCCESS) {
 305                 ldb_set_errstring(ldb, ldap_err2string(ret));
 306         }
 307 
 308         return lldb_ldap_to_ldb(ret);
 309 }
 310 
 311 /*
 312   modify a record
 313 */
 314 static int lldb_modify(struct lldb_context *lldb_ac)
     /* [<][>][^][v][top][bottom][index][help] */
 315 {
 316         struct ldb_context *ldb;
 317         struct lldb_private *lldb = lldb_ac->lldb;
 318         struct ldb_module *module = lldb_ac->module;
 319         struct ldb_request *req = lldb_ac->req;
 320         LDAPMod **mods;
 321         char *dn;
 322         int ret;
 323 
 324         ldb_module_get_ctx(module);
 325 
 326         ldb_request_set_state(req, LDB_ASYNC_PENDING);
 327 
 328         mods = lldb_msg_to_mods(lldb_ac, req->op.mod.message, 1);
 329         if (mods == NULL) {
 330                 return LDB_ERR_OPERATIONS_ERROR;
 331         }
 332 
 333         dn = ldb_dn_alloc_linearized(lldb_ac, req->op.mod.message->dn);
 334         if (dn == NULL) {
 335                 return LDB_ERR_OPERATIONS_ERROR;
 336         }
 337 
 338         ret = ldap_modify_ext(lldb->ldap, dn, mods,
 339                               NULL,
 340                               NULL,
 341                               &lldb_ac->msgid);
 342 
 343         if (ret != LDAP_SUCCESS) {
 344                 ldb_set_errstring(ldb, ldap_err2string(ret));
 345         }
 346 
 347         return lldb_ldap_to_ldb(ret);
 348 }
 349 
 350 /*
 351   delete a record
 352 */
 353 static int lldb_delete(struct lldb_context *lldb_ac)
     /* [<][>][^][v][top][bottom][index][help] */
 354 {
 355         struct ldb_context *ldb;
 356         struct lldb_private *lldb = lldb_ac->lldb;
 357         struct ldb_module *module = lldb_ac->module;
 358         struct ldb_request *req = lldb_ac->req;
 359         char *dnstr;
 360         int ret;
 361 
 362         ldb_module_get_ctx(module);
 363 
 364         ldb_request_set_state(req, LDB_ASYNC_PENDING);
 365 
 366         dnstr = ldb_dn_alloc_linearized(lldb_ac, req->op.del.dn);
 367 
 368         ret = ldap_delete_ext(lldb->ldap, dnstr,
 369                               NULL,
 370                               NULL,
 371                               &lldb_ac->msgid);
 372 
 373         if (ret != LDAP_SUCCESS) {
 374                 ldb_set_errstring(ldb, ldap_err2string(ret));
 375         }
 376 
 377         return lldb_ldap_to_ldb(ret);
 378 }
 379 
 380 /*
 381   rename a record
 382 */
 383 static int lldb_rename(struct lldb_context *lldb_ac)
     /* [<][>][^][v][top][bottom][index][help] */
 384 {
 385         struct ldb_context *ldb;
 386         struct lldb_private *lldb = lldb_ac->lldb;
 387         struct ldb_module *module = lldb_ac->module;
 388         struct ldb_request *req = lldb_ac->req;
 389         char *old_dn;
 390         char *newrdn;
 391         char *parentdn;
 392         int ret;
 393 
 394         ldb_module_get_ctx(module);
 395 
 396         ldb_request_set_state(req, LDB_ASYNC_PENDING);
 397 
 398         old_dn = ldb_dn_alloc_linearized(lldb_ac, req->op.rename.olddn);
 399         if (old_dn == NULL) {
 400                 return LDB_ERR_OPERATIONS_ERROR;
 401         }
 402 
 403         newrdn = talloc_asprintf(lldb_ac, "%s=%s",
 404                                  ldb_dn_get_rdn_name(req->op.rename.newdn),
 405                                  ldb_dn_escape_value(lldb, *(ldb_dn_get_rdn_val(req->op.rename.newdn))));
 406         if (!newrdn) {
 407                 return LDB_ERR_OPERATIONS_ERROR;
 408         }
 409 
 410         parentdn = ldb_dn_alloc_linearized(lldb_ac, ldb_dn_get_parent(lldb_ac, req->op.rename.newdn));
 411         if (!parentdn) {
 412                 return LDB_ERR_OPERATIONS_ERROR;
 413         }
 414 
 415         ret = ldap_rename(lldb->ldap, old_dn, newrdn, parentdn,
 416                           1, NULL, NULL,
 417                           &lldb_ac->msgid);
 418 
 419         if (ret != LDAP_SUCCESS) {
 420                 ldb_set_errstring(ldb, ldap_err2string(ret));
 421         }
 422 
 423         return lldb_ldap_to_ldb(ret);
 424 }
 425 
 426 static int lldb_start_trans(struct ldb_module *module)
     /* [<][>][^][v][top][bottom][index][help] */
 427 {
 428         /* TODO implement a local transaction mechanism here */
 429 
 430         return LDB_SUCCESS;
 431 }
 432 
 433 static int lldb_end_trans(struct ldb_module *module)
     /* [<][>][^][v][top][bottom][index][help] */
 434 {
 435         /* TODO implement a local transaction mechanism here */
 436 
 437         return LDB_SUCCESS;
 438 }
 439 
 440 static int lldb_del_trans(struct ldb_module *module)
     /* [<][>][^][v][top][bottom][index][help] */
 441 {
 442         /* TODO implement a local transaction mechanism here */
 443 
 444         return LDB_SUCCESS;
 445 }
 446 
 447 void lldb_request_done(struct lldb_context *ac,
     /* [<][>][^][v][top][bottom][index][help] */
 448                         struct ldb_control **ctrls, int error)
 449 {
 450         struct ldb_request *req;
 451         struct ldb_reply *ares;
 452 
 453         req = ac->req;
 454 
 455         ares = talloc_zero(req, struct ldb_reply);
 456         if (!ares) {
 457                 ldb_oom(ldb_module_get_ctx(ac->module));
 458                 req->callback(req, NULL);
 459                 return;
 460         }
 461         ares->type = LDB_REPLY_DONE;
 462         ares->controls = talloc_steal(ares, ctrls);
 463         ares->error = error;
 464 
 465         req->callback(req, ares);
 466 }
 467 
 468 /* return false if the request is still in progress
 469  * return true if the request is completed
 470  */
 471 static bool lldb_parse_result(struct lldb_context *ac, LDAPMessage *result)
     /* [<][>][^][v][top][bottom][index][help] */
 472 {
 473         struct ldb_context *ldb;
 474         struct lldb_private *lldb = ac->lldb;
 475         LDAPControl **serverctrlsp = NULL;
 476         char **referralsp = NULL;
 477         char *matcheddnp = NULL;
 478         char *errmsgp = NULL;
 479         LDAPMessage *msg;
 480         int type;
 481         struct ldb_message *ldbmsg;
 482         char *referral;
 483         bool callback_failed;
 484         bool request_done;
 485         bool lret;
 486         int ret;
 487         int i;
 488 
 489         ldb = ldb_module_get_ctx(ac->module);
 490 
 491         type = ldap_msgtype(result);
 492         callback_failed = false;
 493         request_done = false;
 494 
 495         switch (type) {
 496         case LDAP_RES_SEARCH_ENTRY:
 497 
 498                 msg = ldap_first_entry(lldb->ldap, result);
 499                 if (msg != NULL) {
 500                         BerElement *berptr = NULL;
 501                         char *attr, *dn;
 502 
 503                         ldbmsg = ldb_msg_new(ac);
 504                         if (!ldbmsg) {
 505                                 ret = LDB_ERR_OPERATIONS_ERROR;
 506                                 break;
 507                         }
 508 
 509                         dn = ldap_get_dn(lldb->ldap, msg);
 510                         if (!dn) {
 511                                 talloc_free(ldbmsg);
 512                                 ret = LDB_ERR_OPERATIONS_ERROR;
 513                                 break;
 514                         }
 515                         ldbmsg->dn = ldb_dn_new(ldbmsg, ldb, dn);
 516                         if ( ! ldb_dn_validate(ldbmsg->dn)) {
 517                                 talloc_free(ldbmsg);
 518                                 ret = LDB_ERR_OPERATIONS_ERROR;
 519                                 break;
 520                         }
 521                         ldap_memfree(dn);
 522 
 523                         ldbmsg->num_elements = 0;
 524                         ldbmsg->elements = NULL;
 525 
 526                         /* loop over all attributes */
 527                         for (attr=ldap_first_attribute(lldb->ldap, msg, &berptr);
 528                              attr;
 529                              attr=ldap_next_attribute(lldb->ldap, msg, berptr)) {
 530                                 struct berval **bval;
 531                                 bval = ldap_get_values_len(lldb->ldap, msg, attr);
 532 
 533                                 if (bval) {
 534                                         lldb_add_msg_attr(ldb, ldbmsg, attr, bval);
 535                                         ldap_value_free_len(bval);
 536                                 }
 537                         }
 538                         if (berptr) ber_free(berptr, 0);
 539 
 540                         ret = ldb_module_send_entry(ac->req, ldbmsg, NULL /* controls not yet supported */);
 541                         if (ret != LDB_SUCCESS) {
 542 
 543                                 callback_failed = true;
 544                         }
 545                 } else {
 546                         ret = LDB_ERR_OPERATIONS_ERROR;
 547                 }
 548                 break;
 549 
 550         case LDAP_RES_SEARCH_REFERENCE:
 551 
 552                 if (ldap_parse_result(lldb->ldap, result, &ret,
 553                                         &matcheddnp, &errmsgp,
 554                                         &referralsp, &serverctrlsp, 0) != LDAP_SUCCESS) {
 555                         ret = LDB_ERR_OPERATIONS_ERROR;
 556                 }
 557                 if (ret != LDB_SUCCESS) {
 558                         break;
 559                 }
 560                 if (referralsp == NULL) {
 561                         ret = LDB_ERR_PROTOCOL_ERROR;
 562                         break;
 563                 }
 564 
 565                 for (i = 0; referralsp[i]; i++) {
 566                         referral = talloc_strdup(ac, referralsp[i]);
 567 
 568                         ret = ldb_module_send_referral(ac->req, referral);
 569                         if (ret != LDB_SUCCESS) {
 570                                 callback_failed = true;
 571                                 break;
 572                         }
 573                 }
 574                 break;
 575 
 576         case LDAP_RES_SEARCH_RESULT:
 577         case LDAP_RES_MODIFY:
 578         case LDAP_RES_ADD:
 579         case LDAP_RES_DELETE:
 580         case LDAP_RES_MODDN:
 581 
 582                 if (ldap_parse_result(lldb->ldap, result, &ret,
 583                                         &matcheddnp, &errmsgp,
 584                                         &referralsp, &serverctrlsp, 0) != LDAP_SUCCESS) {
 585                         ret = LDB_ERR_OPERATIONS_ERROR;
 586                 }
 587                 if (ret != LDB_SUCCESS) {
 588                         break;
 589                 }
 590 
 591                 if (serverctrlsp != NULL) {
 592                         /* FIXME: transform the LDAPControl list into an ldb_control one */
 593                         ac->controls = NULL;
 594                 }
 595 
 596                 request_done = true;
 597                 break;
 598 
 599         default:
 600                 ret = LDB_ERR_PROTOCOL_ERROR;
 601                 break;
 602         }
 603 
 604         if (ret != LDB_SUCCESS) {
 605 
 606                 /* if the callback failed the caller will have freed the
 607                  * request. Just return and don't try to use it */
 608                 if (callback_failed) {
 609 
 610                         /* tell lldb_wait to remove the request from the
 611                          *  queue */
 612                         lret = true;
 613                         goto free_and_return;
 614                 }
 615 
 616                 request_done = true;
 617         }
 618 
 619         if (request_done) {
 620                 lldb_request_done(ac, ac->controls, ret);
 621                 lret = true;
 622                 goto free_and_return;
 623         }
 624 
 625         lret = false;
 626 
 627 free_and_return:
 628 
 629         if (matcheddnp) ldap_memfree(matcheddnp);
 630         if (errmsgp && *errmsgp) {
 631                 ldb_set_errstring(ldb, errmsgp);
 632         }
 633         if (errmsgp) {
 634                 ldap_memfree(errmsgp);
 635         }
 636         if (referralsp) ldap_value_free(referralsp);
 637         if (serverctrlsp) ldap_controls_free(serverctrlsp);
 638 
 639         ldap_msgfree(result);
 640 
 641         return lret;
 642 }
 643 
 644 static void lldb_timeout(struct tevent_context *ev,
     /* [<][>][^][v][top][bottom][index][help] */
 645                          struct tevent_timer *te,
 646                          struct timeval t,
 647                          void *private_data)
 648 {
 649         struct lldb_context *ac;
 650         ac = talloc_get_type(private_data, struct lldb_context);
 651 
 652         lldb_request_done(ac, NULL, LDB_ERR_TIME_LIMIT_EXCEEDED);
 653 }
 654 
 655 static void lldb_callback(struct tevent_context *ev,
     /* [<][>][^][v][top][bottom][index][help] */
 656                           struct tevent_timer *te,
 657                           struct timeval t,
 658                           void *private_data)
 659 {
 660         struct lldb_context *ac;
 661         struct tevent_timer *lte;
 662         struct timeval tv;
 663         LDAPMessage *result;
 664         int lret;
 665 
 666         ac = talloc_get_type(private_data, struct lldb_context);
 667 
 668         if (!ac->msgid) {
 669                 lldb_request_done(ac, NULL, LDB_ERR_OPERATIONS_ERROR);
 670                 return;
 671         }
 672 
 673         tv.tv_sec = 0;
 674         tv.tv_usec = 0;
 675         lret = ldap_result(ac->lldb->ldap, ac->msgid, 0, &tv, &result);
 676         if (lret == 0) {
 677                 goto respin;
 678         }
 679         if (lret == -1) {
 680                 lldb_request_done(ac, NULL, LDB_ERR_OPERATIONS_ERROR);
 681                 return;
 682         }
 683 
 684         if ( ! lldb_parse_result(ac, result)) {
 685                 goto respin;
 686         }
 687 
 688         return;
 689 
 690 respin:
 691         tv.tv_sec = 0;
 692         tv.tv_usec = 100;
 693         lte = tevent_add_timer(ev, ac, tv, lldb_callback, ac);
 694         if (NULL == lte) {
 695                 lldb_request_done(ac, NULL, LDB_ERR_OPERATIONS_ERROR);
 696         }
 697 }
 698 
 699 static bool lldb_dn_is_special(struct ldb_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 700 {
 701         struct ldb_dn *dn = NULL;
 702 
 703         switch (req->operation) {
 704         case LDB_ADD:
 705                 dn = req->op.add.message->dn;
 706                 break;
 707         case LDB_MODIFY:
 708                 dn = req->op.mod.message->dn;
 709                 break;
 710         case LDB_DELETE:
 711                 dn = req->op.del.dn;
 712                 break;
 713         case LDB_RENAME:
 714                 dn = req->op.rename.olddn;
 715                 break;
 716         default:
 717                 break;
 718         }
 719 
 720         if (dn && ldb_dn_is_special(dn)) {
 721                 return true;
 722         }
 723         return false;
 724 }
 725 
 726 static void lldb_auto_done_callback(struct tevent_context *ev,
     /* [<][>][^][v][top][bottom][index][help] */
 727                                     struct tevent_timer *te,
 728                                     struct timeval t,
 729                                     void *private_data)
 730 {
 731         struct lldb_context *ac;
 732 
 733         ac = talloc_get_type(private_data, struct lldb_context);
 734         lldb_request_done(ac, NULL, LDB_SUCCESS);
 735 }
 736 
 737 static int lldb_handle_request(struct ldb_module *module, struct ldb_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 738 {
 739         struct ldb_context *ldb;
 740         struct lldb_private *lldb;
 741         struct lldb_context *ac;
 742         struct tevent_context *ev;
 743         struct tevent_timer *te;
 744         struct timeval tv;
 745         int ret;
 746 
 747         lldb = talloc_get_type(ldb_module_get_private(module), struct lldb_private);
 748         ldb = ldb_module_get_ctx(module);
 749 
 750         if (req->starttime == 0 || req->timeout == 0) {
 751                 ldb_set_errstring(ldb, "Invalid timeout settings");
 752                 return LDB_ERR_TIME_LIMIT_EXCEEDED;
 753         }
 754 
 755         ev = ldb_get_event_context(ldb);
 756         if (NULL == ev) {
 757                 return LDB_ERR_OPERATIONS_ERROR;
 758         }
 759 
 760         ac = talloc_zero(ldb, struct lldb_context);
 761         if (ac == NULL) {
 762                 ldb_set_errstring(ldb, "Out of Memory");
 763                 return LDB_ERR_OPERATIONS_ERROR;
 764         }
 765 
 766         ac->module = module;
 767         ac->req = req;
 768         ac->lldb = lldb;
 769         ac->msgid = 0;
 770 
 771         if (lldb_dn_is_special(req)) {
 772                 tv.tv_sec = 0;
 773                 tv.tv_usec = 0;
 774                 te = tevent_add_timer(ev, ac, tv,
 775                                      lldb_auto_done_callback, ac);
 776                 if (NULL == te) {
 777                         return LDB_ERR_OPERATIONS_ERROR;
 778                 }
 779 
 780                 return LDB_SUCCESS;
 781         }
 782 
 783         switch (ac->req->operation) {
 784         case LDB_SEARCH:
 785                 ret = lldb_search(ac);
 786                 break;
 787         case LDB_ADD:
 788                 ret = lldb_add(ac);
 789                 break;
 790         case LDB_MODIFY:
 791                 ret = lldb_modify(ac);
 792                 break;
 793         case LDB_DELETE:
 794                 ret = lldb_delete(ac);
 795                 break;
 796         case LDB_RENAME:
 797                 ret = lldb_rename(ac);
 798                 break;
 799         default:
 800                 /* no other op supported */
 801                 ret = LDB_ERR_OPERATIONS_ERROR;
 802                 break;
 803         }
 804 
 805         if (ret != LDB_SUCCESS) {
 806                 lldb_request_done(ac, NULL, ret);
 807                 return ret;
 808         }
 809 
 810         tv.tv_sec = 0;
 811         tv.tv_usec = 0;
 812         te = tevent_add_timer(ev, ac, tv, lldb_callback, ac);
 813         if (NULL == te) {
 814                 return LDB_ERR_OPERATIONS_ERROR;
 815         }
 816 
 817 
 818         tv.tv_sec = req->starttime + req->timeout;
 819         tv.tv_usec = 0;
 820         te = tevent_add_timer(ev, ac, tv, lldb_timeout, ac);
 821         if (NULL == te) {
 822                 return LDB_ERR_OPERATIONS_ERROR;
 823         }
 824 
 825         return LDB_SUCCESS;
 826 }
 827 
 828 static const struct ldb_module_ops lldb_ops = {
 829         .name              = "ldap",
 830         .search            = lldb_handle_request,
 831         .add               = lldb_handle_request,
 832         .modify            = lldb_handle_request,
 833         .del               = lldb_handle_request,
 834         .rename            = lldb_handle_request,
 835         .request           = lldb_handle_request,
 836         .start_transaction = lldb_start_trans,
 837         .end_transaction   = lldb_end_trans,
 838         .del_transaction   = lldb_del_trans,
 839 };
 840 
 841 
 842 static int lldb_destructor(struct lldb_private *lldb)
     /* [<][>][^][v][top][bottom][index][help] */
 843 {
 844         ldap_unbind(lldb->ldap);
 845         return 0;
 846 }
 847 
 848 /*
 849   connect to the database
 850 */
 851 static int lldb_connect(struct ldb_context *ldb,
     /* [<][>][^][v][top][bottom][index][help] */
 852                         const char *url,
 853                         unsigned int flags,
 854                         const char *options[],
 855                         struct ldb_module **_module)
 856 {
 857         struct ldb_module *module;
 858         struct lldb_private *lldb;
 859         int version = 3;
 860         int ret;
 861 
 862         module = ldb_module_new(ldb, ldb, "ldb_ldap backend", &lldb_ops);
 863         if (!module) return -1;
 864 
 865         lldb = talloc_zero(module, struct lldb_private);
 866         if (!lldb) {
 867                 ldb_oom(ldb);
 868                 goto failed;
 869         }
 870         ldb_module_set_private(module, lldb);
 871 
 872         ret = ldap_initialize(&lldb->ldap, url);
 873         if (ret != LDAP_SUCCESS) {
 874                 ldb_debug(ldb, LDB_DEBUG_FATAL, "ldap_initialize failed for URL '%s' - %s\n",
 875                           url, ldap_err2string(ret));
 876                 goto failed;
 877         }
 878 
 879         talloc_set_destructor(lldb, lldb_destructor);
 880 
 881         ret = ldap_set_option(lldb->ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
 882         if (ret != LDAP_SUCCESS) {
 883                 ldb_debug(ldb, LDB_DEBUG_FATAL, "ldap_set_option failed - %s\n",
 884                           ldap_err2string(ret));
 885                 goto failed;
 886         }
 887 
 888         *_module = module;
 889         return 0;
 890 
 891 failed:
 892         talloc_free(module);
 893         return -1;
 894 }
 895 
 896 const struct ldb_backend_ops ldb_ldap_backend_ops = {
 897         .name = "ldap",
 898         .connect_fn = lldb_connect
 899 };
 900 
 901 const struct ldb_backend_ops ldb_ldapi_backend_ops = {
 902         .name = "ldapi",
 903         .connect_fn = lldb_connect
 904 };
 905 
 906 const struct ldb_backend_ops ldb_ldaps_backend_ops = {
 907         .name = "ldaps",
 908         .connect_fn = lldb_connect
 909 };

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