1/* 2 ldb database library 3 4 Copyright (C) Andrew Tridgell 2004 5 Copyright (C) Simo Sorce 2005-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 27 * 28 * Component: ldb core API 29 * 30 * Description: core API routines interfacing to ldb backends 31 * 32 * Author: Andrew Tridgell 33 */ 34 35#define TEVENT_DEPRECATED 1 36#include "ldb_private.h" 37 38static int ldb_context_destructor(void *ptr) 39{ 40 struct ldb_context *ldb = talloc_get_type(ptr, struct ldb_context); 41 42 if (ldb->transaction_active) { 43 ldb_debug(ldb, LDB_DEBUG_FATAL, 44 "A transaction is still active in ldb context [%p] on %s", 45 ldb, (const char *)ldb_get_opaque(ldb, "ldb_url")); 46 } 47 48 return 0; 49} 50 51/* 52 this is used to catch debug messages from events 53*/ 54static void ldb_tevent_debug(void *context, enum tevent_debug_level level, 55 const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0); 56 57static void ldb_tevent_debug(void *context, enum tevent_debug_level level, 58 const char *fmt, va_list ap) 59{ 60 struct ldb_context *ldb = talloc_get_type(context, struct ldb_context); 61 enum ldb_debug_level ldb_level = LDB_DEBUG_FATAL; 62 char *s = NULL; 63 64 switch (level) { 65 case TEVENT_DEBUG_FATAL: 66 ldb_level = LDB_DEBUG_FATAL; 67 break; 68 case TEVENT_DEBUG_ERROR: 69 ldb_level = LDB_DEBUG_ERROR; 70 break; 71 case TEVENT_DEBUG_WARNING: 72 ldb_level = LDB_DEBUG_WARNING; 73 break; 74 case TEVENT_DEBUG_TRACE: 75 ldb_level = LDB_DEBUG_TRACE; 76 break; 77 }; 78 79 vasprintf(&s, fmt, ap); 80 if (!s) return; 81 ldb_debug(ldb, ldb_level, "tevent: %s", s); 82 free(s); 83} 84 85/* 86 initialise a ldb context 87 The mem_ctx is required 88 The event_ctx is required 89*/ 90struct ldb_context *ldb_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev_ctx) 91{ 92 struct ldb_context *ldb; 93 int ret; 94 95 ldb = talloc_zero(mem_ctx, struct ldb_context); 96 /* FIXME: Hack a new event context so that CMD line utilities work 97 * until we have them all converted */ 98 if (ev_ctx == NULL) { 99 ev_ctx = tevent_context_init(talloc_autofree_context()); 100 tevent_set_debug(ev_ctx, ldb_tevent_debug, ldb); 101 tevent_loop_allow_nesting(ev_ctx); 102 } 103 104 ret = ldb_setup_wellknown_attributes(ldb); 105 if (ret != 0) { 106 talloc_free(ldb); 107 return NULL; 108 } 109 110 ldb_set_utf8_default(ldb); 111 ldb_set_create_perms(ldb, 0666); 112 ldb_set_modules_dir(ldb, LDB_MODULESDIR); 113 ldb_set_event_context(ldb, ev_ctx); 114 115 /* TODO: get timeout from options if available there */ 116 ldb->default_timeout = 300; /* set default to 5 minutes */ 117 118 talloc_set_destructor((TALLOC_CTX *)ldb, ldb_context_destructor); 119 120 return ldb; 121} 122 123/* 124 try to autodetect a basedn if none specified. This fixes one of my 125 pet hates about ldapsearch, which is that you have to get a long, 126 complex basedn right to make any use of it. 127*/ 128void ldb_set_default_dns(struct ldb_context *ldb) 129{ 130 TALLOC_CTX *tmp_ctx; 131 int ret; 132 struct ldb_result *res; 133 struct ldb_dn *tmp_dn=NULL; 134 static const char *attrs[] = { 135 "rootDomainNamingContext", 136 "configurationNamingContext", 137 "schemaNamingContext", 138 "defaultNamingContext", 139 NULL 140 }; 141 142 tmp_ctx = talloc_new(ldb); 143 ret = ldb_search(ldb, tmp_ctx, &res, ldb_dn_new(tmp_ctx, ldb, NULL), 144 LDB_SCOPE_BASE, attrs, "(objectClass=*)"); 145 if (ret != LDB_SUCCESS) { 146 talloc_free(tmp_ctx); 147 return; 148 } 149 150 if (res->count != 1) { 151 talloc_free(tmp_ctx); 152 return; 153 } 154 155 if (!ldb_get_opaque(ldb, "rootDomainNamingContext")) { 156 tmp_dn = ldb_msg_find_attr_as_dn(ldb, ldb, res->msgs[0], 157 "rootDomainNamingContext"); 158 ldb_set_opaque(ldb, "rootDomainNamingContext", tmp_dn); 159 } 160 161 if (!ldb_get_opaque(ldb, "configurationNamingContext")) { 162 tmp_dn = ldb_msg_find_attr_as_dn(ldb, ldb, res->msgs[0], 163 "configurationNamingContext"); 164 ldb_set_opaque(ldb, "configurationNamingContext", tmp_dn); 165 } 166 167 if (!ldb_get_opaque(ldb, "schemaNamingContext")) { 168 tmp_dn = ldb_msg_find_attr_as_dn(ldb, ldb, res->msgs[0], 169 "schemaNamingContext"); 170 ldb_set_opaque(ldb, "schemaNamingContext", tmp_dn); 171 } 172 173 if (!ldb_get_opaque(ldb, "defaultNamingContext")) { 174 tmp_dn = ldb_msg_find_attr_as_dn(ldb, ldb, res->msgs[0], 175 "defaultNamingContext"); 176 ldb_set_opaque(ldb, "defaultNamingContext", tmp_dn); 177 } 178 179 talloc_free(tmp_ctx); 180} 181 182struct ldb_dn *ldb_get_root_basedn(struct ldb_context *ldb) 183{ 184 void *opaque = ldb_get_opaque(ldb, "rootDomainNamingContext"); 185 return talloc_get_type(opaque, struct ldb_dn); 186} 187 188struct ldb_dn *ldb_get_config_basedn(struct ldb_context *ldb) 189{ 190 void *opaque = ldb_get_opaque(ldb, "configurationNamingContext"); 191 return talloc_get_type(opaque, struct ldb_dn); 192} 193 194struct ldb_dn *ldb_get_schema_basedn(struct ldb_context *ldb) 195{ 196 void *opaque = ldb_get_opaque(ldb, "schemaNamingContext"); 197 return talloc_get_type(opaque, struct ldb_dn); 198} 199 200struct ldb_dn *ldb_get_default_basedn(struct ldb_context *ldb) 201{ 202 void *opaque = ldb_get_opaque(ldb, "defaultNamingContext"); 203 return talloc_get_type(opaque, struct ldb_dn); 204} 205 206/* 207 connect to a database. The URL can either be one of the following forms 208 ldb://path 209 ldapi://path 210 211 flags is made up of LDB_FLG_* 212 213 the options are passed uninterpreted to the backend, and are 214 backend specific 215*/ 216int ldb_connect(struct ldb_context *ldb, const char *url, 217 unsigned int flags, const char *options[]) 218{ 219 int ret; 220 const char *url2; 221 /* We seem to need to do this here, or else some utilities don't 222 * get ldb backends */ 223 224 ldb->flags = flags; 225 226 url2 = talloc_strdup(ldb, url); 227 if (!url2) { 228 ldb_oom(ldb); 229 return LDB_ERR_OPERATIONS_ERROR; 230 } 231 ret = ldb_set_opaque(ldb, "ldb_url", talloc_strdup(ldb, url2)); 232 if (ret != LDB_SUCCESS) { 233 return ret; 234 } 235 236 ret = ldb_connect_backend(ldb, url, options, &ldb->modules); 237 if (ret != LDB_SUCCESS) { 238 return ret; 239 } 240 241 if (ldb_load_modules(ldb, options) != LDB_SUCCESS) { 242 ldb_debug(ldb, LDB_DEBUG_FATAL, 243 "Unable to load modules for %s: %s", 244 url, ldb_errstring(ldb)); 245 return LDB_ERR_OTHER; 246 } 247 248 /* set the default base dn */ 249 ldb_set_default_dns(ldb); 250 251 return LDB_SUCCESS; 252} 253 254void ldb_set_errstring(struct ldb_context *ldb, const char *err_string) 255{ 256 if (ldb->err_string) { 257 talloc_free(ldb->err_string); 258 } 259 ldb->err_string = talloc_strdup(ldb, err_string); 260 if (ldb->flags & LDB_FLG_ENABLE_TRACING) { 261 ldb_debug(ldb, LDB_DEBUG_TRACE, "ldb_set_errstring: %s", ldb->err_string); 262 } 263} 264 265void ldb_asprintf_errstring(struct ldb_context *ldb, const char *format, ...) 266{ 267 va_list ap; 268 char *old_string = NULL; 269 270 if (ldb->err_string) { 271 old_string = ldb->err_string; 272 } 273 274 va_start(ap, format); 275 ldb->err_string = talloc_vasprintf(ldb, format, ap); 276 va_end(ap); 277 talloc_free(old_string); 278} 279 280void ldb_reset_err_string(struct ldb_context *ldb) 281{ 282 if (ldb->err_string) { 283 talloc_free(ldb->err_string); 284 ldb->err_string = NULL; 285 } 286} 287 288#define FIRST_OP_NOERR(ldb, op) do { \ 289 module = ldb->modules; \ 290 while (module && module->ops->op == NULL) module = module->next; \ 291} while (0) 292 293#define FIRST_OP(ldb, op) do { \ 294 FIRST_OP_NOERR(ldb, op); \ 295 if (module == NULL) { \ 296 ldb_asprintf_errstring(ldb, "unable to find module or backend to handle operation: " #op); \ 297 return LDB_ERR_OPERATIONS_ERROR; \ 298 } \ 299} while (0) 300 301 302/* 303 start a transaction 304*/ 305int ldb_transaction_start(struct ldb_context *ldb) 306{ 307 struct ldb_module *module; 308 int status; 309 310 ldb_debug(ldb, LDB_DEBUG_TRACE, 311 "start ldb transaction (nesting: %d)", 312 ldb->transaction_active); 313 314 /* explicit transaction active, count nested requests */ 315 if (ldb->transaction_active) { 316 ldb->transaction_active++; 317 return LDB_SUCCESS; 318 } 319 320 /* start a new transaction */ 321 ldb->transaction_active++; 322 ldb->prepare_commit_done = false; 323 324 FIRST_OP(ldb, start_transaction); 325 326 ldb_reset_err_string(ldb); 327 328 status = module->ops->start_transaction(module); 329 if (status != LDB_SUCCESS) { 330 if (ldb->err_string == NULL) { 331 /* no error string was setup by the backend */ 332 ldb_asprintf_errstring(ldb, 333 "ldb transaction start: %s (%d)", 334 ldb_strerror(status), 335 status); 336 } 337 } 338 return status; 339} 340 341/* 342 prepare for transaction commit (first phase of two phase commit) 343*/ 344int ldb_transaction_prepare_commit(struct ldb_context *ldb) 345{ 346 struct ldb_module *module; 347 int status; 348 349 if (ldb->prepare_commit_done) { 350 return LDB_SUCCESS; 351 } 352 353 /* commit only when all nested transactions are complete */ 354 if (ldb->transaction_active > 1) { 355 return LDB_SUCCESS; 356 } 357 358 ldb->prepare_commit_done = true; 359 360 if (ldb->transaction_active < 0) { 361 ldb_debug(ldb, LDB_DEBUG_FATAL, 362 "prepare commit called but no ldb transactions are active!"); 363 ldb->transaction_active = 0; 364 return LDB_ERR_OPERATIONS_ERROR; 365 } 366 367 /* call prepare transaction if available */ 368 FIRST_OP_NOERR(ldb, prepare_commit); 369 if (module == NULL) { 370 return LDB_SUCCESS; 371 } 372 373 status = module->ops->prepare_commit(module); 374 if (status != LDB_SUCCESS) { 375 /* if a module fails the prepare then we need 376 to call the end transaction for everyone */ 377 FIRST_OP(ldb, end_transaction); 378 module->ops->end_transaction(module); 379 if (ldb->err_string == NULL) { 380 /* no error string was setup by the backend */ 381 ldb_asprintf_errstring(ldb, 382 "ldb transaction prepare commit: %s (%d)", 383 ldb_strerror(status), 384 status); 385 } 386 } 387 388 return status; 389} 390 391 392/* 393 commit a transaction 394*/ 395int ldb_transaction_commit(struct ldb_context *ldb) 396{ 397 struct ldb_module *module; 398 int status; 399 400 status = ldb_transaction_prepare_commit(ldb); 401 if (status != LDB_SUCCESS) { 402 return status; 403 } 404 405 ldb->transaction_active--; 406 407 ldb_debug(ldb, LDB_DEBUG_TRACE, 408 "commit ldb transaction (nesting: %d)", 409 ldb->transaction_active); 410 411 /* commit only when all nested transactions are complete */ 412 if (ldb->transaction_active > 0) { 413 return LDB_SUCCESS; 414 } 415 416 if (ldb->transaction_active < 0) { 417 ldb_debug(ldb, LDB_DEBUG_FATAL, 418 "commit called but no ldb transactions are active!"); 419 ldb->transaction_active = 0; 420 return LDB_ERR_OPERATIONS_ERROR; 421 } 422 423 ldb_reset_err_string(ldb); 424 425 FIRST_OP(ldb, end_transaction); 426 status = module->ops->end_transaction(module); 427 if (status != LDB_SUCCESS) { 428 if (ldb->err_string == NULL) { 429 /* no error string was setup by the backend */ 430 ldb_asprintf_errstring(ldb, 431 "ldb transaction commit: %s (%d)", 432 ldb_strerror(status), 433 status); 434 } 435 /* cancel the transaction */ 436 FIRST_OP(ldb, del_transaction); 437 module->ops->del_transaction(module); 438 } 439 return status; 440} 441 442 443/* 444 cancel a transaction 445*/ 446int ldb_transaction_cancel(struct ldb_context *ldb) 447{ 448 struct ldb_module *module; 449 int status; 450 451 ldb->transaction_active--; 452 453 ldb_debug(ldb, LDB_DEBUG_TRACE, 454 "cancel ldb transaction (nesting: %d)", 455 ldb->transaction_active); 456 457 /* really cancel only if all nested transactions are complete */ 458 if (ldb->transaction_active > 0) { 459 return LDB_SUCCESS; 460 } 461 462 if (ldb->transaction_active < 0) { 463 ldb_debug(ldb, LDB_DEBUG_FATAL, 464 "cancel called but no ldb transactions are active!"); 465 ldb->transaction_active = 0; 466 return LDB_ERR_OPERATIONS_ERROR; 467 } 468 469 FIRST_OP(ldb, del_transaction); 470 471 status = module->ops->del_transaction(module); 472 if (status != LDB_SUCCESS) { 473 if (ldb->err_string == NULL) { 474 /* no error string was setup by the backend */ 475 ldb_asprintf_errstring(ldb, 476 "ldb transaction cancel: %s (%d)", 477 ldb_strerror(status), 478 status); 479 } 480 } 481 return status; 482} 483 484/* autostarts a transacion if none active */ 485static int ldb_autotransaction_request(struct ldb_context *ldb, 486 struct ldb_request *req) 487{ 488 int ret; 489 490 ret = ldb_transaction_start(ldb); 491 if (ret != LDB_SUCCESS) { 492 return ret; 493 } 494 495 ret = ldb_request(ldb, req); 496 if (ret == LDB_SUCCESS) { 497 ret = ldb_wait(req->handle, LDB_WAIT_ALL); 498 } 499 500 if (ret == LDB_SUCCESS) { 501 return ldb_transaction_commit(ldb); 502 } 503 ldb_transaction_cancel(ldb); 504 505 if (ldb->err_string == NULL) { 506 /* no error string was setup by the backend */ 507 ldb_asprintf_errstring(ldb, "%s (%d)", ldb_strerror(ret), ret); 508 } 509 510 return ret; 511} 512 513int ldb_wait(struct ldb_handle *handle, enum ldb_wait_type type) 514{ 515 struct tevent_context *ev; 516 int ret; 517 518 if (!handle) { 519 return LDB_ERR_UNAVAILABLE; 520 } 521 522 if (handle->state == LDB_ASYNC_DONE) { 523 return handle->status; 524 } 525 526 ev = ldb_get_event_context(handle->ldb); 527 if (NULL == ev) { 528 return LDB_ERR_OPERATIONS_ERROR; 529 } 530 531 switch (type) { 532 case LDB_WAIT_NONE: 533 ret = tevent_loop_once(ev); 534 if (ret != 0) { 535 return LDB_ERR_OPERATIONS_ERROR; 536 } 537 if (handle->state == LDB_ASYNC_DONE || 538 handle->status != LDB_SUCCESS) { 539 return handle->status; 540 } 541 break; 542 543 case LDB_WAIT_ALL: 544 while (handle->state != LDB_ASYNC_DONE) { 545 ret = tevent_loop_once(ev); 546 if (ret != 0) { 547 return LDB_ERR_OPERATIONS_ERROR; 548 } 549 if (handle->status != LDB_SUCCESS) { 550 return handle->status; 551 } 552 } 553 return handle->status; 554 } 555 556 return LDB_SUCCESS; 557} 558 559/* set the specified timeout or, if timeout is 0 set the default timeout */ 560int ldb_set_timeout(struct ldb_context *ldb, 561 struct ldb_request *req, 562 int timeout) 563{ 564 if (req == NULL) return LDB_ERR_OPERATIONS_ERROR; 565 566 if (timeout != 0) { 567 req->timeout = timeout; 568 } else { 569 req->timeout = ldb->default_timeout; 570 } 571 req->starttime = time(NULL); 572 573 return LDB_SUCCESS; 574} 575 576/* calculates the new timeout based on the previous starttime and timeout */ 577int ldb_set_timeout_from_prev_req(struct ldb_context *ldb, 578 struct ldb_request *oldreq, 579 struct ldb_request *newreq) 580{ 581 if (newreq == NULL) return LDB_ERR_OPERATIONS_ERROR; 582 583 if (oldreq == NULL) { 584 return ldb_set_timeout(ldb, newreq, 0); 585 } 586 587 newreq->starttime = oldreq->starttime; 588 newreq->timeout = oldreq->timeout; 589 590 return LDB_SUCCESS; 591} 592 593 594/* 595 set the permissions for new files to be passed to open() in 596 backends that use local files 597 */ 598void ldb_set_create_perms(struct ldb_context *ldb, unsigned int perms) 599{ 600 ldb->create_perms = perms; 601} 602 603unsigned int ldb_get_create_perms(struct ldb_context *ldb) 604{ 605 return ldb->create_perms; 606} 607 608void ldb_set_event_context(struct ldb_context *ldb, struct tevent_context *ev) 609{ 610 ldb->ev_ctx = ev; 611} 612 613struct tevent_context * ldb_get_event_context(struct ldb_context *ldb) 614{ 615 return ldb->ev_ctx; 616} 617 618void ldb_request_set_state(struct ldb_request *req, int state) 619{ 620 req->handle->state = state; 621} 622 623int ldb_request_get_status(struct ldb_request *req) 624{ 625 return req->handle->status; 626} 627 628 629/* 630 trace a ldb request 631*/ 632static void ldb_trace_request(struct ldb_context *ldb, struct ldb_request *req) 633{ 634 TALLOC_CTX *tmp_ctx = talloc_new(req); 635 int i; 636 637 switch (req->operation) { 638 case LDB_SEARCH: 639 ldb_debug_add(ldb, "ldb_trace_request: SEARCH\n"); 640 ldb_debug_add(ldb, " dn: %s\n", 641 ldb_dn_is_null(req->op.search.base)?"<rootDSE>": 642 ldb_dn_get_linearized(req->op.search.base)); 643 ldb_debug_add(ldb, " scope: %s\n", 644 req->op.search.scope==LDB_SCOPE_BASE?"base": 645 req->op.search.scope==LDB_SCOPE_ONELEVEL?"one": 646 req->op.search.scope==LDB_SCOPE_SUBTREE?"sub":"UNKNOWN"); 647 ldb_debug_add(ldb, " expr: %s\n", 648 ldb_filter_from_tree(tmp_ctx, req->op.search.tree)); 649 if (req->op.search.attrs == NULL) { 650 ldb_debug_add(ldb, " attr: <ALL>\n"); 651 } else { 652 for (i=0; req->op.search.attrs[i]; i++) { 653 ldb_debug_add(ldb, " attr: %s\n", req->op.search.attrs[i]); 654 } 655 } 656 break; 657 case LDB_DELETE: 658 ldb_debug_add(ldb, "ldb_trace_request: DELETE\n"); 659 ldb_debug_add(ldb, " dn: %s\n", 660 ldb_dn_get_linearized(req->op.del.dn)); 661 break; 662 case LDB_RENAME: 663 ldb_debug_add(ldb, "ldb_trace_request: RENAME\n"); 664 ldb_debug_add(ldb, " olddn: %s\n", 665 ldb_dn_get_linearized(req->op.rename.olddn)); 666 ldb_debug_add(ldb, " newdn: %s\n", 667 ldb_dn_get_linearized(req->op.rename.newdn)); 668 break; 669 case LDB_EXTENDED: 670 ldb_debug_add(ldb, "ldb_trace_request: EXTENDED\n"); 671 ldb_debug_add(ldb, " oid: %s\n", req->op.extended.oid); 672 ldb_debug_add(ldb, " data: %s\n", req->op.extended.data?"yes":"no"); 673 break; 674 case LDB_ADD: 675 ldb_debug_add(ldb, "ldb_trace_request: ADD\n"); 676 ldb_debug_add(req->handle->ldb, "%s\n", 677 ldb_ldif_message_string(req->handle->ldb, tmp_ctx, 678 LDB_CHANGETYPE_ADD, 679 req->op.add.message)); 680 break; 681 case LDB_MODIFY: 682 ldb_debug_add(ldb, "ldb_trace_request: MODIFY\n"); 683 ldb_debug_add(req->handle->ldb, "%s\n", 684 ldb_ldif_message_string(req->handle->ldb, tmp_ctx, 685 LDB_CHANGETYPE_ADD, 686 req->op.mod.message)); 687 break; 688 case LDB_REQ_REGISTER_CONTROL: 689 ldb_debug_add(ldb, "ldb_trace_request: REGISTER_CONTROL\n"); 690 ldb_debug_add(req->handle->ldb, "%s\n", 691 req->op.reg_control.oid); 692 break; 693 case LDB_REQ_REGISTER_PARTITION: 694 ldb_debug_add(ldb, "ldb_trace_request: REGISTER_PARTITION\n"); 695 ldb_debug_add(req->handle->ldb, "%s\n", 696 ldb_dn_get_linearized(req->op.reg_partition.dn)); 697 break; 698 default: 699 ldb_debug_add(ldb, "ldb_trace_request: UNKNOWN(%u)\n", 700 req->operation); 701 break; 702 } 703 704 if (req->controls == NULL) { 705 ldb_debug_add(ldb, " control: <NONE>\n"); 706 } else { 707 for (i=0; req->controls && req->controls[i]; i++) { 708 ldb_debug_add(ldb, " control: %s crit:%u data:%s\n", 709 req->controls[i]->oid, 710 req->controls[i]->critical, 711 req->controls[i]->data?"yes":"no"); 712 } 713 } 714 715 ldb_debug_end(ldb, LDB_DEBUG_TRACE); 716 717 talloc_free(tmp_ctx); 718} 719 720 721/* 722 start an ldb request 723 NOTE: the request must be a talloc context. 724 returns LDB_ERR_* on errors. 725*/ 726int ldb_request(struct ldb_context *ldb, struct ldb_request *req) 727{ 728 struct ldb_module *module; 729 int ret; 730 731 if (req->callback == NULL) { 732 ldb_set_errstring(ldb, "Requests MUST define callbacks"); 733 return LDB_ERR_UNWILLING_TO_PERFORM; 734 } 735 736 ldb_reset_err_string(ldb); 737 738 if (ldb->flags & LDB_FLG_ENABLE_TRACING) { 739 ldb_trace_request(ldb, req); 740 } 741 742 /* call the first module in the chain */ 743 switch (req->operation) { 744 case LDB_SEARCH: 745 FIRST_OP(ldb, search); 746 ret = module->ops->search(module, req); 747 break; 748 case LDB_ADD: 749 FIRST_OP(ldb, add); 750 ret = module->ops->add(module, req); 751 break; 752 case LDB_MODIFY: 753 FIRST_OP(ldb, modify); 754 ret = module->ops->modify(module, req); 755 break; 756 case LDB_DELETE: 757 FIRST_OP(ldb, del); 758 ret = module->ops->del(module, req); 759 break; 760 case LDB_RENAME: 761 FIRST_OP(ldb, rename); 762 ret = module->ops->rename(module, req); 763 break; 764 case LDB_EXTENDED: 765 FIRST_OP(ldb, extended); 766 ret = module->ops->extended(module, req); 767 break; 768 default: 769 FIRST_OP(ldb, request); 770 ret = module->ops->request(module, req); 771 break; 772 } 773 774 return ret; 775} 776 777int ldb_request_done(struct ldb_request *req, int status) 778{ 779 req->handle->state = LDB_ASYNC_DONE; 780 req->handle->status = status; 781 return status; 782} 783 784/* 785 search the database given a LDAP-like search expression 786 787 returns an LDB error code 788 789 Use talloc_free to free the ldb_message returned in 'res', if successful 790 791*/ 792int ldb_search_default_callback(struct ldb_request *req, 793 struct ldb_reply *ares) 794{ 795 struct ldb_result *res; 796 int n; 797 798 res = talloc_get_type(req->context, struct ldb_result); 799 800 if (!ares) { 801 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR); 802 } 803 if (ares->error != LDB_SUCCESS) { 804 return ldb_request_done(req, ares->error); 805 } 806 807 switch (ares->type) { 808 case LDB_REPLY_ENTRY: 809 res->msgs = talloc_realloc(res, res->msgs, 810 struct ldb_message *, res->count + 2); 811 if (! res->msgs) { 812 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR); 813 } 814 815 res->msgs[res->count + 1] = NULL; 816 817 res->msgs[res->count] = talloc_move(res->msgs, &ares->message); 818 res->count++; 819 break; 820 821 case LDB_REPLY_REFERRAL: 822 if (res->refs) { 823 for (n = 0; res->refs[n]; n++) /*noop*/ ; 824 } else { 825 n = 0; 826 } 827 828 res->refs = talloc_realloc(res, res->refs, char *, n + 2); 829 if (! res->refs) { 830 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR); 831 } 832 833 res->refs[n] = talloc_move(res->refs, &ares->referral); 834 res->refs[n + 1] = NULL; 835 break; 836 837 case LDB_REPLY_DONE: 838 /* TODO: we should really support controls on entries 839 * and referrals too! */ 840 res->controls = talloc_move(res, &ares->controls); 841 842 /* this is the last message, and means the request is done */ 843 /* we have to signal and eventual ldb_wait() waiting that the 844 * async request operation was completed */ 845 talloc_free(ares); 846 return ldb_request_done(req, LDB_SUCCESS); 847 } 848 849 talloc_free(ares); 850 851 return LDB_SUCCESS; 852} 853 854int ldb_op_default_callback(struct ldb_request *req, struct ldb_reply *ares) 855{ 856 int ret; 857 858 if (!ares) { 859 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR); 860 } 861 862 if (ares->error != LDB_SUCCESS) { 863 ret = ares->error; 864 talloc_free(ares); 865 return ldb_request_done(req, ret); 866 } 867 868 if (ares->type != LDB_REPLY_DONE) { 869 talloc_free(ares); 870 ldb_set_errstring(req->handle->ldb, "Invalid reply type!"); 871 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR); 872 } 873 874 talloc_free(ares); 875 return ldb_request_done(req, LDB_SUCCESS); 876} 877 878int ldb_build_search_req_ex(struct ldb_request **ret_req, 879 struct ldb_context *ldb, 880 void *mem_ctx, 881 struct ldb_dn *base, 882 enum ldb_scope scope, 883 struct ldb_parse_tree *tree, 884 const char * const *attrs, 885 struct ldb_control **controls, 886 void *context, 887 ldb_request_callback_t callback, 888 struct ldb_request *parent) 889{ 890 struct ldb_request *req; 891 892 *ret_req = NULL; 893 894 req = talloc(mem_ctx, struct ldb_request); 895 if (req == NULL) { 896 ldb_oom(ldb); 897 return LDB_ERR_OPERATIONS_ERROR; 898 } 899 900 req->operation = LDB_SEARCH; 901 if (base == NULL) { 902 req->op.search.base = ldb_dn_new(req, ldb, NULL); 903 } else { 904 req->op.search.base = base; 905 } 906 req->op.search.scope = scope; 907 908 req->op.search.tree = tree; 909 if (req->op.search.tree == NULL) { 910 ldb_set_errstring(ldb, "'tree' can't be NULL"); 911 talloc_free(req); 912 return LDB_ERR_OPERATIONS_ERROR; 913 } 914 915 req->op.search.attrs = attrs; 916 req->controls = controls; 917 req->context = context; 918 req->callback = callback; 919 920 ldb_set_timeout_from_prev_req(ldb, parent, req); 921 922 req->handle = ldb_handle_new(req, ldb); 923 if (req->handle == NULL) { 924 ldb_oom(ldb); 925 return LDB_ERR_OPERATIONS_ERROR; 926 } 927 928 if (parent) { 929 req->handle->nesting++; 930 } 931 932 *ret_req = req; 933 return LDB_SUCCESS; 934} 935 936int ldb_build_search_req(struct ldb_request **ret_req, 937 struct ldb_context *ldb, 938 void *mem_ctx, 939 struct ldb_dn *base, 940 enum ldb_scope scope, 941 const char *expression, 942 const char * const *attrs, 943 struct ldb_control **controls, 944 void *context, 945 ldb_request_callback_t callback, 946 struct ldb_request *parent) 947{ 948 struct ldb_parse_tree *tree; 949 int ret; 950 951 tree = ldb_parse_tree(mem_ctx, expression); 952 if (tree == NULL) { 953 ldb_set_errstring(ldb, "Unable to parse search expression"); 954 return LDB_ERR_OPERATIONS_ERROR; 955 } 956 957 ret = ldb_build_search_req_ex(ret_req, ldb, mem_ctx, base, 958 scope, tree, attrs, controls, 959 context, callback, parent); 960 if (ret == LDB_SUCCESS) { 961 talloc_steal(*ret_req, tree); 962 } 963 return ret; 964} 965 966int ldb_build_add_req(struct ldb_request **ret_req, 967 struct ldb_context *ldb, 968 void *mem_ctx, 969 const struct ldb_message *message, 970 struct ldb_control **controls, 971 void *context, 972 ldb_request_callback_t callback, 973 struct ldb_request *parent) 974{ 975 struct ldb_request *req; 976 977 *ret_req = NULL; 978 979 req = talloc(mem_ctx, struct ldb_request); 980 if (req == NULL) { 981 ldb_set_errstring(ldb, "Out of Memory"); 982 return LDB_ERR_OPERATIONS_ERROR; 983 } 984 985 req->operation = LDB_ADD; 986 req->op.add.message = message; 987 req->controls = controls; 988 req->context = context; 989 req->callback = callback; 990 991 ldb_set_timeout_from_prev_req(ldb, parent, req); 992 993 req->handle = ldb_handle_new(req, ldb); 994 if (req->handle == NULL) { 995 ldb_oom(ldb); 996 return LDB_ERR_OPERATIONS_ERROR; 997 } 998 999 if (parent) { 1000 req->handle->nesting++; 1001 } 1002 1003 *ret_req = req; 1004 1005 return LDB_SUCCESS; 1006} 1007 1008int ldb_build_mod_req(struct ldb_request **ret_req, 1009 struct ldb_context *ldb, 1010 void *mem_ctx, 1011 const struct ldb_message *message, 1012 struct ldb_control **controls, 1013 void *context, 1014 ldb_request_callback_t callback, 1015 struct ldb_request *parent) 1016{ 1017 struct ldb_request *req; 1018 1019 *ret_req = NULL; 1020 1021 req = talloc(mem_ctx, struct ldb_request); 1022 if (req == NULL) { 1023 ldb_set_errstring(ldb, "Out of Memory"); 1024 return LDB_ERR_OPERATIONS_ERROR; 1025 } 1026 1027 req->operation = LDB_MODIFY; 1028 req->op.mod.message = message; 1029 req->controls = controls; 1030 req->context = context; 1031 req->callback = callback; 1032 1033 ldb_set_timeout_from_prev_req(ldb, parent, req); 1034 1035 req->handle = ldb_handle_new(req, ldb); 1036 if (req->handle == NULL) { 1037 ldb_oom(ldb); 1038 return LDB_ERR_OPERATIONS_ERROR; 1039 } 1040 1041 if (parent) { 1042 req->handle->nesting++; 1043 } 1044 1045 *ret_req = req; 1046 1047 return LDB_SUCCESS; 1048} 1049 1050int ldb_build_del_req(struct ldb_request **ret_req, 1051 struct ldb_context *ldb, 1052 void *mem_ctx, 1053 struct ldb_dn *dn, 1054 struct ldb_control **controls, 1055 void *context, 1056 ldb_request_callback_t callback, 1057 struct ldb_request *parent) 1058{ 1059 struct ldb_request *req; 1060 1061 *ret_req = NULL; 1062 1063 req = talloc(mem_ctx, struct ldb_request); 1064 if (req == NULL) { 1065 ldb_set_errstring(ldb, "Out of Memory"); 1066 return LDB_ERR_OPERATIONS_ERROR; 1067 } 1068 1069 req->operation = LDB_DELETE; 1070 req->op.del.dn = dn; 1071 req->controls = controls; 1072 req->context = context; 1073 req->callback = callback; 1074 1075 ldb_set_timeout_from_prev_req(ldb, parent, req); 1076 1077 req->handle = ldb_handle_new(req, ldb); 1078 if (req->handle == NULL) { 1079 ldb_oom(ldb); 1080 return LDB_ERR_OPERATIONS_ERROR; 1081 } 1082 1083 if (parent) { 1084 req->handle->nesting++; 1085 } 1086 1087 *ret_req = req; 1088 1089 return LDB_SUCCESS; 1090} 1091 1092int ldb_build_rename_req(struct ldb_request **ret_req, 1093 struct ldb_context *ldb, 1094 void *mem_ctx, 1095 struct ldb_dn *olddn, 1096 struct ldb_dn *newdn, 1097 struct ldb_control **controls, 1098 void *context, 1099 ldb_request_callback_t callback, 1100 struct ldb_request *parent) 1101{ 1102 struct ldb_request *req; 1103 1104 *ret_req = NULL; 1105 1106 req = talloc(mem_ctx, struct ldb_request); 1107 if (req == NULL) { 1108 ldb_set_errstring(ldb, "Out of Memory"); 1109 return LDB_ERR_OPERATIONS_ERROR; 1110 } 1111 1112 req->operation = LDB_RENAME; 1113 req->op.rename.olddn = olddn; 1114 req->op.rename.newdn = newdn; 1115 req->controls = controls; 1116 req->context = context; 1117 req->callback = callback; 1118 1119 ldb_set_timeout_from_prev_req(ldb, parent, req); 1120 1121 req->handle = ldb_handle_new(req, ldb); 1122 if (req->handle == NULL) { 1123 ldb_oom(ldb); 1124 return LDB_ERR_OPERATIONS_ERROR; 1125 } 1126 1127 if (parent) { 1128 req->handle->nesting++; 1129 } 1130 1131 *ret_req = req; 1132 1133 return LDB_SUCCESS; 1134} 1135 1136int ldb_extended_default_callback(struct ldb_request *req, 1137 struct ldb_reply *ares) 1138{ 1139 struct ldb_result *res; 1140 1141 res = talloc_get_type(req->context, struct ldb_result); 1142 1143 if (!ares) { 1144 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR); 1145 } 1146 if (ares->error != LDB_SUCCESS) { 1147 return ldb_request_done(req, ares->error); 1148 } 1149 1150 if (ares->type == LDB_REPLY_DONE) { 1151 1152 /* TODO: we should really support controls on entries and referrals too! */ 1153 res->extended = talloc_move(res, &ares->response); 1154 res->controls = talloc_move(res, &ares->controls); 1155 1156 talloc_free(ares); 1157 return ldb_request_done(req, LDB_SUCCESS); 1158 } 1159 1160 talloc_free(ares); 1161 ldb_set_errstring(req->handle->ldb, "Invalid reply type!"); 1162 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR); 1163} 1164 1165int ldb_build_extended_req(struct ldb_request **ret_req, 1166 struct ldb_context *ldb, 1167 void *mem_ctx, 1168 const char *oid, 1169 void *data, 1170 struct ldb_control **controls, 1171 void *context, 1172 ldb_request_callback_t callback, 1173 struct ldb_request *parent) 1174{ 1175 struct ldb_request *req; 1176 1177 *ret_req = NULL; 1178 1179 req = talloc(mem_ctx, struct ldb_request); 1180 if (req == NULL) { 1181 ldb_set_errstring(ldb, "Out of Memory"); 1182 return LDB_ERR_OPERATIONS_ERROR; 1183 } 1184 1185 req->operation = LDB_EXTENDED; 1186 req->op.extended.oid = oid; 1187 req->op.extended.data = data; 1188 req->controls = controls; 1189 req->context = context; 1190 req->callback = callback; 1191 1192 ldb_set_timeout_from_prev_req(ldb, parent, req); 1193 1194 req->handle = ldb_handle_new(req, ldb); 1195 if (req->handle == NULL) { 1196 ldb_oom(ldb); 1197 return LDB_ERR_OPERATIONS_ERROR; 1198 } 1199 1200 if (parent) { 1201 req->handle->nesting++; 1202 } 1203 1204 *ret_req = req; 1205 1206 return LDB_SUCCESS; 1207} 1208 1209int ldb_extended(struct ldb_context *ldb, 1210 const char *oid, 1211 void *data, 1212 struct ldb_result **_res) 1213{ 1214 struct ldb_request *req; 1215 int ret; 1216 struct ldb_result *res; 1217 1218 *_res = NULL; 1219 1220 res = talloc_zero(ldb, struct ldb_result); 1221 if (!res) { 1222 return LDB_ERR_OPERATIONS_ERROR; 1223 } 1224 1225 ret = ldb_build_extended_req(&req, ldb, ldb, 1226 oid, data, NULL, 1227 res, ldb_extended_default_callback, 1228 NULL); 1229 if (ret != LDB_SUCCESS) goto done; 1230 1231 ldb_set_timeout(ldb, req, 0); /* use default timeout */ 1232 1233 ret = ldb_request(ldb, req); 1234 1235 if (ret == LDB_SUCCESS) { 1236 ret = ldb_wait(req->handle, LDB_WAIT_ALL); 1237 } 1238 1239 talloc_free(req); 1240 1241done: 1242 if (ret != LDB_SUCCESS) { 1243 talloc_free(res); 1244 } 1245 1246 *_res = res; 1247 return ret; 1248} 1249 1250/* 1251 note that ldb_search() will automatically replace a NULL 'base' value 1252 with the defaultNamingContext from the rootDSE if available. 1253*/ 1254int ldb_search(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, 1255 struct ldb_result **result, struct ldb_dn *base, 1256 enum ldb_scope scope, const char * const *attrs, 1257 const char *exp_fmt, ...) 1258{ 1259 struct ldb_request *req; 1260 struct ldb_result *res; 1261 char *expression; 1262 va_list ap; 1263 int ret; 1264 1265 expression = NULL; 1266 *result = NULL; 1267 req = NULL; 1268 1269 res = talloc_zero(mem_ctx, struct ldb_result); 1270 if (!res) { 1271 return LDB_ERR_OPERATIONS_ERROR; 1272 } 1273 1274 if (exp_fmt) { 1275 va_start(ap, exp_fmt); 1276 expression = talloc_vasprintf(mem_ctx, exp_fmt, ap); 1277 va_end(ap); 1278 1279 if (!expression) { 1280 talloc_free(res); 1281 return LDB_ERR_OPERATIONS_ERROR; 1282 } 1283 } 1284 1285 ret = ldb_build_search_req(&req, ldb, mem_ctx, 1286 base?base:ldb_get_default_basedn(ldb), 1287 scope, 1288 expression, 1289 attrs, 1290 NULL, 1291 res, 1292 ldb_search_default_callback, 1293 NULL); 1294 1295 if (ret != LDB_SUCCESS) goto done; 1296 1297 ret = ldb_request(ldb, req); 1298 1299 if (ret == LDB_SUCCESS) { 1300 ret = ldb_wait(req->handle, LDB_WAIT_ALL); 1301 } 1302 1303done: 1304 if (ret != LDB_SUCCESS) { 1305 talloc_free(res); 1306 res = NULL; 1307 } 1308 1309 talloc_free(expression); 1310 talloc_free(req); 1311 1312 *result = res; 1313 return ret; 1314} 1315 1316/* 1317 add a record to the database. Will fail if a record with the given class 1318 and key already exists 1319*/ 1320int ldb_add(struct ldb_context *ldb, 1321 const struct ldb_message *message) 1322{ 1323 struct ldb_request *req; 1324 int ret; 1325 1326 ret = ldb_msg_sanity_check(ldb, message); 1327 if (ret != LDB_SUCCESS) { 1328 return ret; 1329 } 1330 1331 ret = ldb_build_add_req(&req, ldb, ldb, 1332 message, 1333 NULL, 1334 NULL, 1335 ldb_op_default_callback, 1336 NULL); 1337 1338 if (ret != LDB_SUCCESS) return ret; 1339 1340 /* do request and autostart a transaction */ 1341 ret = ldb_autotransaction_request(ldb, req); 1342 1343 talloc_free(req); 1344 return ret; 1345} 1346 1347/* 1348 modify the specified attributes of a record 1349*/ 1350int ldb_modify(struct ldb_context *ldb, 1351 const struct ldb_message *message) 1352{ 1353 struct ldb_request *req; 1354 int ret; 1355 1356 ret = ldb_msg_sanity_check(ldb, message); 1357 if (ret != LDB_SUCCESS) { 1358 return ret; 1359 } 1360 1361 ret = ldb_build_mod_req(&req, ldb, ldb, 1362 message, 1363 NULL, 1364 NULL, 1365 ldb_op_default_callback, 1366 NULL); 1367 1368 if (ret != LDB_SUCCESS) return ret; 1369 1370 /* do request and autostart a transaction */ 1371 ret = ldb_autotransaction_request(ldb, req); 1372 1373 talloc_free(req); 1374 return ret; 1375} 1376 1377 1378/* 1379 delete a record from the database 1380*/ 1381int ldb_delete(struct ldb_context *ldb, struct ldb_dn *dn) 1382{ 1383 struct ldb_request *req; 1384 int ret; 1385 1386 ret = ldb_build_del_req(&req, ldb, ldb, 1387 dn, 1388 NULL, 1389 NULL, 1390 ldb_op_default_callback, 1391 NULL); 1392 1393 if (ret != LDB_SUCCESS) return ret; 1394 1395 /* do request and autostart a transaction */ 1396 ret = ldb_autotransaction_request(ldb, req); 1397 1398 talloc_free(req); 1399 return ret; 1400} 1401 1402/* 1403 rename a record in the database 1404*/ 1405int ldb_rename(struct ldb_context *ldb, 1406 struct ldb_dn *olddn, struct ldb_dn *newdn) 1407{ 1408 struct ldb_request *req; 1409 int ret; 1410 1411 ret = ldb_build_rename_req(&req, ldb, ldb, 1412 olddn, 1413 newdn, 1414 NULL, 1415 NULL, 1416 ldb_op_default_callback, 1417 NULL); 1418 1419 if (ret != LDB_SUCCESS) return ret; 1420 1421 /* do request and autostart a transaction */ 1422 ret = ldb_autotransaction_request(ldb, req); 1423 1424 talloc_free(req); 1425 return ret; 1426} 1427 1428 1429/* 1430 return the global sequence number 1431*/ 1432int ldb_sequence_number(struct ldb_context *ldb, 1433 enum ldb_sequence_type type, uint64_t *seq_num) 1434{ 1435 struct ldb_seqnum_request *seq; 1436 struct ldb_seqnum_result *seqr; 1437 struct ldb_result *res; 1438 TALLOC_CTX *tmp_ctx; 1439 int ret; 1440 1441 *seq_num = 0; 1442 1443 tmp_ctx = talloc_zero(ldb, struct ldb_request); 1444 if (tmp_ctx == NULL) { 1445 ldb_set_errstring(ldb, "Out of Memory"); 1446 return LDB_ERR_OPERATIONS_ERROR; 1447 } 1448 seq = talloc_zero(tmp_ctx, struct ldb_seqnum_request); 1449 if (seq == NULL) { 1450 ldb_set_errstring(ldb, "Out of Memory"); 1451 ret = LDB_ERR_OPERATIONS_ERROR; 1452 goto done; 1453 } 1454 seq->type = type; 1455 1456 ret = ldb_extended(ldb, LDB_EXTENDED_SEQUENCE_NUMBER, seq, &res); 1457 if (ret != LDB_SUCCESS) { 1458 goto done; 1459 } 1460 talloc_steal(tmp_ctx, res); 1461 1462 if (strcmp(LDB_EXTENDED_SEQUENCE_NUMBER, res->extended->oid) != 0) { 1463 ldb_set_errstring(ldb, "Invalid OID in reply"); 1464 ret = LDB_ERR_OPERATIONS_ERROR; 1465 goto done; 1466 } 1467 seqr = talloc_get_type(res->extended->data, 1468 struct ldb_seqnum_result); 1469 *seq_num = seqr->seq_num; 1470 1471done: 1472 talloc_free(tmp_ctx); 1473 return ret; 1474} 1475 1476/* 1477 return extended error information 1478*/ 1479const char *ldb_errstring(struct ldb_context *ldb) 1480{ 1481 if (ldb->err_string) { 1482 return ldb->err_string; 1483 } 1484 1485 return NULL; 1486} 1487 1488/* 1489 return a string explaining what a ldb error constant meancs 1490*/ 1491const char *ldb_strerror(int ldb_err) 1492{ 1493 switch (ldb_err) { 1494 case LDB_SUCCESS: 1495 return "Success"; 1496 case LDB_ERR_OPERATIONS_ERROR: 1497 return "Operations error"; 1498 case LDB_ERR_PROTOCOL_ERROR: 1499 return "Protocol error"; 1500 case LDB_ERR_TIME_LIMIT_EXCEEDED: 1501 return "Time limit exceeded"; 1502 case LDB_ERR_SIZE_LIMIT_EXCEEDED: 1503 return "Size limit exceeded"; 1504 case LDB_ERR_COMPARE_FALSE: 1505 return "Compare false"; 1506 case LDB_ERR_COMPARE_TRUE: 1507 return "Compare true"; 1508 case LDB_ERR_AUTH_METHOD_NOT_SUPPORTED: 1509 return "Auth method not supported"; 1510 case LDB_ERR_STRONG_AUTH_REQUIRED: 1511 return "Strong auth required"; 1512/* 9 RESERVED */ 1513 case LDB_ERR_REFERRAL: 1514 return "Referral error"; 1515 case LDB_ERR_ADMIN_LIMIT_EXCEEDED: 1516 return "Admin limit exceeded"; 1517 case LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION: 1518 return "Unsupported critical extension"; 1519 case LDB_ERR_CONFIDENTIALITY_REQUIRED: 1520 return "Confidentiality required"; 1521 case LDB_ERR_SASL_BIND_IN_PROGRESS: 1522 return "SASL bind in progress"; 1523 case LDB_ERR_NO_SUCH_ATTRIBUTE: 1524 return "No such attribute"; 1525 case LDB_ERR_UNDEFINED_ATTRIBUTE_TYPE: 1526 return "Undefined attribute type"; 1527 case LDB_ERR_INAPPROPRIATE_MATCHING: 1528 return "Inappropriate matching"; 1529 case LDB_ERR_CONSTRAINT_VIOLATION: 1530 return "Constraint violation"; 1531 case LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS: 1532 return "Attribute or value exists"; 1533 case LDB_ERR_INVALID_ATTRIBUTE_SYNTAX: 1534 return "Invalid attribute syntax"; 1535/* 22-31 unused */ 1536 case LDB_ERR_NO_SUCH_OBJECT: 1537 return "No such object"; 1538 case LDB_ERR_ALIAS_PROBLEM: 1539 return "Alias problem"; 1540 case LDB_ERR_INVALID_DN_SYNTAX: 1541 return "Invalid DN syntax"; 1542/* 35 RESERVED */ 1543 case LDB_ERR_ALIAS_DEREFERENCING_PROBLEM: 1544 return "Alias dereferencing problem"; 1545/* 37-47 unused */ 1546 case LDB_ERR_INAPPROPRIATE_AUTHENTICATION: 1547 return "Inappropriate authentication"; 1548 case LDB_ERR_INVALID_CREDENTIALS: 1549 return "Invalid credentials"; 1550 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS: 1551 return "insufficient access rights"; 1552 case LDB_ERR_BUSY: 1553 return "Busy"; 1554 case LDB_ERR_UNAVAILABLE: 1555 return "Unavailable"; 1556 case LDB_ERR_UNWILLING_TO_PERFORM: 1557 return "Unwilling to perform"; 1558 case LDB_ERR_LOOP_DETECT: 1559 return "Loop detect"; 1560/* 55-63 unused */ 1561 case LDB_ERR_NAMING_VIOLATION: 1562 return "Naming violation"; 1563 case LDB_ERR_OBJECT_CLASS_VIOLATION: 1564 return "Object class violation"; 1565 case LDB_ERR_NOT_ALLOWED_ON_NON_LEAF: 1566 return "Not allowed on non-leaf"; 1567 case LDB_ERR_NOT_ALLOWED_ON_RDN: 1568 return "Not allowed on RDN"; 1569 case LDB_ERR_ENTRY_ALREADY_EXISTS: 1570 return "Entry already exists"; 1571 case LDB_ERR_OBJECT_CLASS_MODS_PROHIBITED: 1572 return "Object class mods prohibited"; 1573/* 70 RESERVED FOR CLDAP */ 1574 case LDB_ERR_AFFECTS_MULTIPLE_DSAS: 1575 return "Affects multiple DSAs"; 1576/* 72-79 unused */ 1577 case LDB_ERR_OTHER: 1578 return "Other"; 1579 } 1580 1581 return "Unknown error"; 1582} 1583 1584/* 1585 set backend specific opaque parameters 1586*/ 1587int ldb_set_opaque(struct ldb_context *ldb, const char *name, void *value) 1588{ 1589 struct ldb_opaque *o; 1590 1591 /* allow updating an existing value */ 1592 for (o=ldb->opaque;o;o=o->next) { 1593 if (strcmp(o->name, name) == 0) { 1594 o->value = value; 1595 return LDB_SUCCESS; 1596 } 1597 } 1598 1599 o = talloc(ldb, struct ldb_opaque); 1600 if (o == NULL) { 1601 ldb_oom(ldb); 1602 return LDB_ERR_OTHER; 1603 } 1604 o->next = ldb->opaque; 1605 o->name = name; 1606 o->value = value; 1607 ldb->opaque = o; 1608 return LDB_SUCCESS; 1609} 1610 1611/* 1612 get a previously set opaque value 1613*/ 1614void *ldb_get_opaque(struct ldb_context *ldb, const char *name) 1615{ 1616 struct ldb_opaque *o; 1617 for (o=ldb->opaque;o;o=o->next) { 1618 if (strcmp(o->name, name) == 0) { 1619 return o->value; 1620 } 1621 } 1622 return NULL; 1623} 1624 1625int ldb_global_init(void) 1626{ 1627 /* Provided for compatibility with some older versions of ldb */ 1628 return 0; 1629} 1630 1631/* return the ldb flags */ 1632unsigned int ldb_get_flags(struct ldb_context *ldb) 1633{ 1634 return ldb->flags; 1635} 1636 1637/* set the ldb flags */ 1638void ldb_set_flags(struct ldb_context *ldb, unsigned flags) 1639{ 1640 ldb->flags = flags; 1641} 1642