summaryrefslogtreecommitdiff
path: root/ldb/common
diff options
context:
space:
mode:
Diffstat (limited to 'ldb/common')
-rw-r--r--ldb/common/attrib_handlers.c378
-rw-r--r--ldb/common/ldb.c1359
-rw-r--r--ldb/common/ldb_attributes.c274
-rw-r--r--ldb/common/ldb_controls.c597
-rw-r--r--ldb/common/ldb_debug.c103
-rw-r--r--ldb/common/ldb_dn.c1800
-rw-r--r--ldb/common/ldb_ldif.c761
-rw-r--r--ldb/common/ldb_match.c428
-rw-r--r--ldb/common/ldb_modules.c777
-rw-r--r--ldb/common/ldb_msg.c899
-rw-r--r--ldb/common/ldb_parse.c819
-rw-r--r--ldb/common/ldb_utf8.c136
-rw-r--r--ldb/common/qsort.c251
13 files changed, 0 insertions, 8582 deletions
diff --git a/ldb/common/attrib_handlers.c b/ldb/common/attrib_handlers.c
deleted file mode 100644
index 5ec86b5b..00000000
--- a/ldb/common/attrib_handlers.c
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- ldb database library
-
- Copyright (C) Andrew Tridgell 2005
-
- ** NOTE! The following LGPL license applies to the ldb
- ** library. This does NOT imply that all of Samba is released
- ** under the LGPL
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-/*
- attribute handlers for well known attribute types, selected by syntax OID
- see rfc2252
-*/
-
-#include "ldb_includes.h"
-#include "system/locale.h"
-#include "ldb_handlers.h"
-
-/*
- default handler that just copies a ldb_val.
-*/
-int ldb_handler_copy(struct ldb_context *ldb, void *mem_ctx,
- const struct ldb_val *in, struct ldb_val *out)
-{
- *out = ldb_val_dup(mem_ctx, in);
- if (in->length > 0 && out->data == NULL) {
- ldb_oom(ldb);
- return -1;
- }
- return 0;
-}
-
-/*
- a case folding copy handler, removing leading and trailing spaces and
- multiple internal spaces
-
- We exploit the fact that utf8 never uses the space octet except for
- the space itself
-*/
-int ldb_handler_fold(struct ldb_context *ldb, void *mem_ctx,
- const struct ldb_val *in, struct ldb_val *out)
-{
- char *s, *t;
- int l;
-
- if (!in || !out || !(in->data)) {
- return -1;
- }
-
- out->data = (uint8_t *)ldb_casefold(ldb, mem_ctx, (const char *)(in->data), in->length);
- if (out->data == NULL) {
- ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_handler_fold: unable to casefold string [%s]", in->data);
- return -1;
- }
-
- s = (char *)(out->data);
-
- /* remove trailing spaces if any */
- l = strlen(s);
- while (l > 0 && s[l - 1] == ' ') l--;
- s[l] = '\0';
-
- /* remove leading spaces if any */
- if (*s == ' ') {
- for (t = s; *s == ' '; s++) ;
-
- /* remove leading spaces by moving down the string */
- memmove(t, s, l);
-
- s = t;
- }
-
- /* check middle spaces */
- while ((t = strchr(s, ' ')) != NULL) {
- for (s = t; *s == ' '; s++) ;
-
- if ((s - t) > 1) {
- l = strlen(s);
-
- /* remove all spaces but one by moving down the string */
- memmove(t + 1, s, l);
- }
- }
-
- out->length = strlen((char *)out->data);
- return 0;
-}
-
-
-
-/*
- canonicalise a ldap Integer
- rfc2252 specifies it should be in decimal form
-*/
-int ldb_canonicalise_Integer(struct ldb_context *ldb, void *mem_ctx,
- const struct ldb_val *in, struct ldb_val *out)
-{
- char *end;
- long long i = strtoll((char *)in->data, &end, 0);
- if (*end != 0) {
- return -1;
- }
- out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%lld", i);
- if (out->data == NULL) {
- return -1;
- }
- out->length = strlen((char *)out->data);
- return 0;
-}
-
-/*
- compare two Integers
-*/
-int ldb_comparison_Integer(struct ldb_context *ldb, void *mem_ctx,
- const struct ldb_val *v1, const struct ldb_val *v2)
-{
- return strtoll((char *)v1->data, NULL, 0) - strtoll((char *)v2->data, NULL, 0);
-}
-
-/*
- compare two binary blobs
-*/
-int ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx,
- const struct ldb_val *v1, const struct ldb_val *v2)
-{
- if (v1->length != v2->length) {
- return v1->length - v2->length;
- }
- return memcmp(v1->data, v2->data, v1->length);
-}
-
-/*
- compare two case insensitive strings, ignoring multiple whitespaces
- and leading and trailing whitespaces
- see rfc2252 section 8.1
-
- try to optimize for the ascii case,
- but if we find out an utf8 codepoint revert to slower but correct function
-*/
-int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx,
- const struct ldb_val *v1, const struct ldb_val *v2)
-{
- const char *s1=(const char *)v1->data, *s2=(const char *)v2->data;
- size_t n1 = v1->length, n2 = v2->length;
- const char *u1, *u2;
- char *b1, *b2;
- int ret;
- while (*s1 == ' ' && n1) { s1++; n1--; };
- while (*s2 == ' ' && n2) { s2++; n2--; };
- /* TODO: make utf8 safe, possibly with helper function from application */
- while (*s1 && *s2 && n1 && n2) {
- /* the first 127 (0x7F) chars are ascii and utf8 guarantes they
- * never appear in multibyte sequences */
- if (((unsigned char)s1[0]) & 0x80) goto utf8str;
- if (((unsigned char)s2[0]) & 0x80) goto utf8str;
- if (toupper((unsigned char)*s1) != toupper((unsigned char)*s2))
- break;
- if (*s1 == ' ') {
- while (s1[0] == s1[1] && n1) { s1++; n1--; }
- while (s2[0] == s2[1] && n2) { s2++; n2--; }
- }
- s1++; s2++;
- n1--; n2--;
- }
- if (! (*s1 && *s2)) {
- /* check for trailing spaces only if one of the pointers
- * has reached the end of the strings otherwise we
- * can mistakenly match.
- * ex. "domain users" <-> "domainUpdates"
- */
- while (*s1 == ' ') { s1++; n1--; }
- while (*s2 == ' ') { s2++; n2--; }
- }
- if (n1 != n2) {
- return n1 - n2;
- }
- return (int)(toupper(*s1)) - (int)(toupper(*s2));
-
-utf8str:
- /* no need to recheck from the start, just from the first utf8 char found */
- b1 = ldb_casefold(ldb, mem_ctx, s1, n1);
- b2 = ldb_casefold(ldb, mem_ctx, s2, n2);
-
- if (b1 && b2) {
- /* Both strings converted correctly */
-
- u1 = b1;
- u2 = b2;
- } else {
- /* One of the strings was not UTF8, so we have no options but to do a binary compare */
-
- u1 = s1;
- u2 = s2;
- }
-
- while (*u1 & *u2) {
- if (*u1 != *u2)
- break;
- if (*u1 == ' ') {
- while (u1[0] == u1[1]) u1++;
- while (u2[0] == u2[1]) u2++;
- }
- u1++; u2++;
- }
- if (! (*u1 && *u2)) {
- while (*u1 == ' ') u1++;
- while (*u2 == ' ') u2++;
- }
- ret = (int)(*u1 - *u2);
-
- talloc_free(b1);
- talloc_free(b2);
-
- return ret;
-}
-
-
-/*
- canonicalise a attribute in DN format
-*/
-int ldb_canonicalise_dn(struct ldb_context *ldb, void *mem_ctx,
- const struct ldb_val *in, struct ldb_val *out)
-{
- struct ldb_dn *dn;
- int ret = -1;
-
- out->length = 0;
- out->data = NULL;
-
- dn = ldb_dn_from_ldb_val(ldb, mem_ctx, in);
- if ( ! ldb_dn_validate(dn)) {
- return LDB_ERR_INVALID_DN_SYNTAX;
- }
-
- out->data = (uint8_t *)ldb_dn_alloc_casefold(mem_ctx, dn);
- if (out->data == NULL) {
- goto done;
- }
- out->length = strlen((char *)out->data);
-
- ret = 0;
-
-done:
- talloc_free(dn);
-
- return ret;
-}
-
-/*
- compare two dns
-*/
-int ldb_comparison_dn(struct ldb_context *ldb, void *mem_ctx,
- const struct ldb_val *v1, const struct ldb_val *v2)
-{
- struct ldb_dn *dn1 = NULL, *dn2 = NULL;
- int ret;
-
- dn1 = ldb_dn_from_ldb_val(ldb, mem_ctx, v1);
- if ( ! ldb_dn_validate(dn1)) return -1;
-
- dn2 = ldb_dn_from_ldb_val(ldb, mem_ctx, v2);
- if ( ! ldb_dn_validate(dn2)) {
- talloc_free(dn1);
- return -1;
- }
-
- ret = ldb_dn_compare(dn1, dn2);
-
- talloc_free(dn1);
- talloc_free(dn2);
- return ret;
-}
-
-/*
- compare two utc time values. 1 second resolution
-*/
-int ldb_comparison_utctime(struct ldb_context *ldb, void *mem_ctx,
- const struct ldb_val *v1, const struct ldb_val *v2)
-{
- time_t t1, t2;
- t1 = ldb_string_to_time((char *)v1->data);
- t2 = ldb_string_to_time((char *)v2->data);
- return (int)t2 - (int)t1;
-}
-
-/*
- canonicalise a utc time
-*/
-int ldb_canonicalise_utctime(struct ldb_context *ldb, void *mem_ctx,
- const struct ldb_val *in, struct ldb_val *out)
-{
- time_t t = ldb_string_to_time((char *)in->data);
- out->data = (uint8_t *)ldb_timestring(mem_ctx, t);
- if (out->data == NULL) {
- return -1;
- }
- out->length = strlen((char *)out->data);
- return 0;
-}
-
-/*
- table of standard attribute handlers
-*/
-static const struct ldb_schema_syntax ldb_standard_syntaxes[] = {
- {
- .name = LDB_SYNTAX_INTEGER,
- .ldif_read_fn = ldb_handler_copy,
- .ldif_write_fn = ldb_handler_copy,
- .canonicalise_fn = ldb_canonicalise_Integer,
- .comparison_fn = ldb_comparison_Integer
- },
- {
- .name = LDB_SYNTAX_OCTET_STRING,
- .ldif_read_fn = ldb_handler_copy,
- .ldif_write_fn = ldb_handler_copy,
- .canonicalise_fn = ldb_handler_copy,
- .comparison_fn = ldb_comparison_binary
- },
- {
- .name = LDB_SYNTAX_DIRECTORY_STRING,
- .ldif_read_fn = ldb_handler_copy,
- .ldif_write_fn = ldb_handler_copy,
- .canonicalise_fn = ldb_handler_fold,
- .comparison_fn = ldb_comparison_fold
- },
- {
- .name = LDB_SYNTAX_DN,
- .ldif_read_fn = ldb_handler_copy,
- .ldif_write_fn = ldb_handler_copy,
- .canonicalise_fn = ldb_canonicalise_dn,
- .comparison_fn = ldb_comparison_dn
- },
- {
- .name = LDB_SYNTAX_OBJECTCLASS,
- .ldif_read_fn = ldb_handler_copy,
- .ldif_write_fn = ldb_handler_copy,
- .canonicalise_fn = ldb_handler_fold,
- .comparison_fn = ldb_comparison_fold
- },
- {
- .name = LDB_SYNTAX_UTC_TIME,
- .ldif_read_fn = ldb_handler_copy,
- .ldif_write_fn = ldb_handler_copy,
- .canonicalise_fn = ldb_canonicalise_utctime,
- .comparison_fn = ldb_comparison_utctime
- }
-};
-
-
-/*
- return the attribute handlers for a given syntax name
-*/
-const struct ldb_schema_syntax *ldb_standard_syntax_by_name(struct ldb_context *ldb,
- const char *syntax)
-{
- int i;
- unsigned num_handlers = sizeof(ldb_standard_syntaxes)/sizeof(ldb_standard_syntaxes[0]);
- /* TODO: should be replaced with a binary search */
- for (i=0;i<num_handlers;i++) {
- if (strcmp(ldb_standard_syntaxes[i].name, syntax) == 0) {
- return &ldb_standard_syntaxes[i];
- }
- }
- return NULL;
-}
diff --git a/ldb/common/ldb.c b/ldb/common/ldb.c
deleted file mode 100644
index c013565d..00000000
--- a/ldb/common/ldb.c
+++ /dev/null
@@ -1,1359 +0,0 @@
-/*
- ldb database library
-
- Copyright (C) Andrew Tridgell 2004
- Copyright (C) Simo Sorce 2005-2008
-
- ** NOTE! The following LGPL license applies to the ldb
- ** library. This does NOT imply that all of Samba is released
- ** under the LGPL
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-/*
- * Name: ldb
- *
- * Component: ldb core API
- *
- * Description: core API routines interfacing to ldb backends
- *
- * Author: Andrew Tridgell
- */
-
-#include "ldb_includes.h"
-
-/*
- initialise a ldb context
- The mem_ctx is required
- The event_ctx is required
-*/
-struct ldb_context *ldb_init(TALLOC_CTX *mem_ctx, struct event_context *ev_ctx)
-{
- struct ldb_context *ldb;
- int ret;
-
- ldb = talloc_zero(mem_ctx, struct ldb_context);
- /* FIXME: Hack a new event context so that CMD line utilities work
- * until we have them all converted */
- if (ev_ctx == NULL) {
- ev_ctx = event_context_init(talloc_autofree_context());
- }
-
- ret = ldb_setup_wellknown_attributes(ldb);
- if (ret != 0) {
- talloc_free(ldb);
- return NULL;
- }
-
- ldb_set_utf8_default(ldb);
- ldb_set_create_perms(ldb, 0666);
- ldb_set_modules_dir(ldb, LDB_MODULESDIR);
- ldb_set_event_context(ldb, ev_ctx);
-
- /* TODO: get timeout from options if available there */
- ldb->default_timeout = 300; /* set default to 5 minutes */
-
- return ldb;
-}
-
-/*
- try to autodetect a basedn if none specified. This fixes one of my
- pet hates about ldapsearch, which is that you have to get a long,
- complex basedn right to make any use of it.
-*/
-void ldb_set_default_dns(struct ldb_context *ldb)
-{
- TALLOC_CTX *tmp_ctx;
- int ret;
- struct ldb_result *res;
- struct ldb_dn *tmp_dn=NULL;
- static const char *attrs[] = {
- "rootDomainNamingContext",
- "configurationNamingContext",
- "schemaNamingContext",
- "defaultNamingContext",
- NULL
- };
-
- tmp_ctx = talloc_new(ldb);
- ret = ldb_search(ldb, tmp_ctx, &res, ldb_dn_new(tmp_ctx, ldb, NULL),
- LDB_SCOPE_BASE, attrs, "(objectClass=*)");
- if (ret != LDB_SUCCESS) {
- talloc_free(tmp_ctx);
- return;
- }
-
- if (res->count != 1) {
- talloc_free(tmp_ctx);
- return;
- }
-
- if (!ldb_get_opaque(ldb, "rootDomainNamingContext")) {
- tmp_dn = ldb_msg_find_attr_as_dn(ldb, ldb, res->msgs[0],
- "rootDomainNamingContext");
- ldb_set_opaque(ldb, "rootDomainNamingContext", tmp_dn);
- }
-
- if (!ldb_get_opaque(ldb, "configurationNamingContext")) {
- tmp_dn = ldb_msg_find_attr_as_dn(ldb, ldb, res->msgs[0],
- "configurationNamingContext");
- ldb_set_opaque(ldb, "configurationNamingContext", tmp_dn);
- }
-
- if (!ldb_get_opaque(ldb, "schemaNamingContext")) {
- tmp_dn = ldb_msg_find_attr_as_dn(ldb, ldb, res->msgs[0],
- "schemaNamingContext");
- ldb_set_opaque(ldb, "schemaNamingContext", tmp_dn);
- }
-
- if (!ldb_get_opaque(ldb, "defaultNamingContext")) {
- tmp_dn = ldb_msg_find_attr_as_dn(ldb, ldb, res->msgs[0],
- "defaultNamingContext");
- ldb_set_opaque(ldb, "defaultNamingContext", tmp_dn);
- }
-
- talloc_free(tmp_ctx);
-}
-
-struct ldb_dn *ldb_get_root_basedn(struct ldb_context *ldb)
-{
- void *opaque = ldb_get_opaque(ldb, "rootDomainNamingContext");
- return talloc_get_type(opaque, struct ldb_dn);
-}
-
-struct ldb_dn *ldb_get_config_basedn(struct ldb_context *ldb)
-{
- void *opaque = ldb_get_opaque(ldb, "configurationNamingContext");
- return talloc_get_type(opaque, struct ldb_dn);
-}
-
-struct ldb_dn *ldb_get_schema_basedn(struct ldb_context *ldb)
-{
- void *opaque = ldb_get_opaque(ldb, "schemaNamingContext");
- return talloc_get_type(opaque, struct ldb_dn);
-}
-
-struct ldb_dn *ldb_get_default_basedn(struct ldb_context *ldb)
-{
- void *opaque = ldb_get_opaque(ldb, "defaultNamingContext");
- return talloc_get_type(opaque, struct ldb_dn);
-}
-
-/*
- connect to a database. The URL can either be one of the following forms
- ldb://path
- ldapi://path
-
- flags is made up of LDB_FLG_*
-
- the options are passed uninterpreted to the backend, and are
- backend specific
-*/
-int ldb_connect(struct ldb_context *ldb, const char *url,
- unsigned int flags, const char *options[])
-{
- int ret;
- const char *url2;
- /* We seem to need to do this here, or else some utilities don't
- * get ldb backends */
-
- ldb->flags = flags;
-
- url2 = talloc_strdup(ldb, url);
- if (!url2) {
- ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
- }
- ret = ldb_set_opaque(ldb, "ldb_url", talloc_strdup(ldb, url2));
- if (ret != LDB_SUCCESS) {
- return ret;
- }
-
- ret = ldb_connect_backend(ldb, url, options, &ldb->modules);
- if (ret != LDB_SUCCESS) {
- return ret;
- }
-
- if (ldb_load_modules(ldb, options) != LDB_SUCCESS) {
- ldb_debug(ldb, LDB_DEBUG_FATAL,
- "Unable to load modules for %s: %s\n",
- url, ldb_errstring(ldb));
- return LDB_ERR_OTHER;
- }
-
- /* set the default base dn */
- ldb_set_default_dns(ldb);
-
- return LDB_SUCCESS;
-}
-
-void ldb_set_errstring(struct ldb_context *ldb, const char *err_string)
-{
- if (ldb->err_string) {
- talloc_free(ldb->err_string);
- }
- ldb->err_string = talloc_strdup(ldb, err_string);
-}
-
-void ldb_asprintf_errstring(struct ldb_context *ldb, const char *format, ...)
-{
- va_list ap;
- char *old_string = NULL;
-
- if (ldb->err_string) {
- old_string = ldb->err_string;
- }
-
- va_start(ap, format);
- ldb->err_string = talloc_vasprintf(ldb, format, ap);
- va_end(ap);
- talloc_free(old_string);
-}
-
-void ldb_reset_err_string(struct ldb_context *ldb)
-{
- if (ldb->err_string) {
- talloc_free(ldb->err_string);
- ldb->err_string = NULL;
- }
-}
-
-#define FIRST_OP(ldb, op) do { \
- module = ldb->modules; \
- while (module && module->ops->op == NULL) module = module->next; \
- if (module == NULL) { \
- ldb_asprintf_errstring(ldb, "unable to find module or backend to handle operation: " #op); \
- return LDB_ERR_OPERATIONS_ERROR; \
- } \
-} while (0)
-
-/*
- start a transaction
-*/
-static int ldb_transaction_start_internal(struct ldb_context *ldb)
-{
- struct ldb_module *module;
- int status;
- FIRST_OP(ldb, start_transaction);
-
- ldb_reset_err_string(ldb);
-
- status = module->ops->start_transaction(module);
- if (status != LDB_SUCCESS) {
- if (ldb->err_string == NULL) {
- /* no error string was setup by the backend */
- ldb_asprintf_errstring(ldb,
- "ldb transaction start: %s (%d)",
- ldb_strerror(status),
- status);
- }
- }
- return status;
-}
-
-/*
- commit a transaction
-*/
-static int ldb_transaction_commit_internal(struct ldb_context *ldb)
-{
- struct ldb_module *module;
- int status;
- FIRST_OP(ldb, end_transaction);
-
- ldb_reset_err_string(ldb);
-
- status = module->ops->end_transaction(module);
- if (status != LDB_SUCCESS) {
- if (ldb->err_string == NULL) {
- /* no error string was setup by the backend */
- ldb_asprintf_errstring(ldb,
- "ldb transaction commit: %s (%d)",
- ldb_strerror(status),
- status);
- }
- }
- return status;
-}
-
-/*
- cancel a transaction
-*/
-static int ldb_transaction_cancel_internal(struct ldb_context *ldb)
-{
- struct ldb_module *module;
- int status;
- FIRST_OP(ldb, del_transaction);
-
- status = module->ops->del_transaction(module);
- if (status != LDB_SUCCESS) {
- if (ldb->err_string == NULL) {
- /* no error string was setup by the backend */
- ldb_asprintf_errstring(ldb,
- "ldb transaction cancel: %s (%d)",
- ldb_strerror(status),
- status);
- }
- }
- return status;
-}
-
-int ldb_transaction_start(struct ldb_context *ldb)
-{
- /* disable autotransactions */
- ldb->transaction_active++;
-
- return ldb_transaction_start_internal(ldb);
-}
-
-int ldb_transaction_commit(struct ldb_context *ldb)
-{
- /* renable autotransactions (when we reach 0) */
- if (ldb->transaction_active > 0)
- ldb->transaction_active--;
-
- return ldb_transaction_commit_internal(ldb);
-}
-
-int ldb_transaction_cancel(struct ldb_context *ldb)
-{
- /* renable autotransactions (when we reach 0) */
- if (ldb->transaction_active > 0)
- ldb->transaction_active--;
-
- return ldb_transaction_cancel_internal(ldb);
-}
-
-static int ldb_autotransaction_start(struct ldb_context *ldb)
-{
- /* explicit transaction active, ignore autotransaction request */
- if (ldb->transaction_active)
- return LDB_SUCCESS;
-
- return ldb_transaction_start_internal(ldb);
-}
-
-static int ldb_autotransaction_commit(struct ldb_context *ldb)
-{
- /* explicit transaction active, ignore autotransaction request */
- if (ldb->transaction_active)
- return LDB_SUCCESS;
-
- return ldb_transaction_commit_internal(ldb);
-}
-
-static int ldb_autotransaction_cancel(struct ldb_context *ldb)
-{
- /* explicit transaction active, ignore autotransaction request */
- if (ldb->transaction_active)
- return LDB_SUCCESS;
-
- return ldb_transaction_cancel_internal(ldb);
-}
-
-/* autostarts a transacion if none active */
-static int ldb_autotransaction_request(struct ldb_context *ldb,
- struct ldb_request *req)
-{
- int ret;
-
- ret = ldb_autotransaction_start(ldb);
- if (ret != LDB_SUCCESS) {
- return ret;
- }
-
- ret = ldb_request(ldb, req);
- if (ret == LDB_SUCCESS) {
- ret = ldb_wait(req->handle, LDB_WAIT_ALL);
- }
-
- if (ret == LDB_SUCCESS) {
- return ldb_autotransaction_commit(ldb);
- }
- ldb_autotransaction_cancel(ldb);
-
- if (ldb->err_string == NULL) {
- /* no error string was setup by the backend */
- ldb_asprintf_errstring(ldb, "%s (%d)", ldb_strerror(ret), ret);
- }
-
- return ret;
-}
-
-int ldb_wait(struct ldb_handle *handle, enum ldb_wait_type type)
-{
- struct event_context *ev;
-
- if (!handle) {
- return LDB_ERR_UNAVAILABLE;
- }
-
- if (handle->state == LDB_ASYNC_DONE) {
- return handle->status;
- }
-
- ev = ldb_get_event_context(handle->ldb);
- if (NULL == ev) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- switch (type) {
- case LDB_WAIT_NONE:
- event_loop_once(ev);
- if (handle->state == LDB_ASYNC_DONE ||
- handle->status != LDB_SUCCESS) {
- return handle->status;
- }
- break;
-
- case LDB_WAIT_ALL:
- while (handle->state != LDB_ASYNC_DONE) {
- event_loop_once(ev);
- if (handle->status != LDB_SUCCESS) {
- return handle->status;
- }
- }
- return handle->status;
- }
-
- return LDB_SUCCESS;
-}
-
-/* set the specified timeout or, if timeout is 0 set the default timeout */
-int ldb_set_timeout(struct ldb_context *ldb,
- struct ldb_request *req,
- int timeout)
-{
- if (req == NULL) return LDB_ERR_OPERATIONS_ERROR;
-
- if (timeout != 0) {
- req->timeout = timeout;
- } else {
- req->timeout = ldb->default_timeout;
- }
- req->starttime = time(NULL);
-
- return LDB_SUCCESS;
-}
-
-/* calculates the new timeout based on the previous starttime and timeout */
-int ldb_set_timeout_from_prev_req(struct ldb_context *ldb,
- struct ldb_request *oldreq,
- struct ldb_request *newreq)
-{
- if (newreq == NULL) return LDB_ERR_OPERATIONS_ERROR;
-
- if (oldreq == NULL) {
- return ldb_set_timeout(ldb, newreq, 0);
- }
-
- newreq->starttime = oldreq->starttime;
- newreq->timeout = oldreq->timeout;
-
- return LDB_SUCCESS;
-}
-
-
-/*
- set the permissions for new files to be passed to open() in
- backends that use local files
- */
-void ldb_set_create_perms(struct ldb_context *ldb, unsigned int perms)
-{
- ldb->create_perms = perms;
-}
-
-void ldb_set_event_context(struct ldb_context *ldb, struct event_context *ev)
-{
- ldb->ev_ctx = ev;
-}
-
-struct event_context * ldb_get_event_context(struct ldb_context *ldb)
-{
- return ldb->ev_ctx;
-}
-
-/*
- start an ldb request
- NOTE: the request must be a talloc context.
- returns LDB_ERR_* on errors.
-*/
-int ldb_request(struct ldb_context *ldb, struct ldb_request *req)
-{
- struct ldb_module *module;
- int ret;
-
- if (req->callback == NULL) {
- ldb_set_errstring(ldb, "Requests MUST define callbacks");
- return LDB_ERR_UNWILLING_TO_PERFORM;
- }
-
- ldb_reset_err_string(ldb);
-
- /* call the first module in the chain */
- switch (req->operation) {
- case LDB_SEARCH:
- FIRST_OP(ldb, search);
- ret = module->ops->search(module, req);
- break;
- case LDB_ADD:
- FIRST_OP(ldb, add);
- ret = module->ops->add(module, req);
- break;
- case LDB_MODIFY:
- FIRST_OP(ldb, modify);
- ret = module->ops->modify(module, req);
- break;
- case LDB_DELETE:
- FIRST_OP(ldb, del);
- ret = module->ops->del(module, req);
- break;
- case LDB_RENAME:
- FIRST_OP(ldb, rename);
- ret = module->ops->rename(module, req);
- break;
- case LDB_EXTENDED:
- FIRST_OP(ldb, extended);
- ret = module->ops->extended(module, req);
- break;
- default:
- FIRST_OP(ldb, request);
- ret = module->ops->request(module, req);
- break;
- }
-
- return ret;
-}
-
-int ldb_request_done(struct ldb_request *req, int status)
-{
- req->handle->state = LDB_ASYNC_DONE;
- req->handle->status = status;
- return status;
-}
-
-/*
- search the database given a LDAP-like search expression
-
- returns an LDB error code
-
- Use talloc_free to free the ldb_message returned in 'res', if successful
-
-*/
-int ldb_search_default_callback(struct ldb_request *req,
- struct ldb_reply *ares)
-{
- struct ldb_result *res;
- int n;
-
- res = talloc_get_type(req->context, struct ldb_result);
-
- if (!ares) {
- return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
- }
- if (ares->error != LDB_SUCCESS) {
- return ldb_request_done(req, ares->error);
- }
-
- switch (ares->type) {
- case LDB_REPLY_ENTRY:
- res->msgs = talloc_realloc(res, res->msgs,
- struct ldb_message *, res->count + 2);
- if (! res->msgs) {
- return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
- }
-
- res->msgs[res->count + 1] = NULL;
-
- res->msgs[res->count] = talloc_move(res->msgs, &ares->message);
- res->count++;
- break;
-
- case LDB_REPLY_REFERRAL:
- if (res->refs) {
- for (n = 0; res->refs[n]; n++) /*noop*/ ;
- } else {
- n = 0;
- }
-
- res->refs = talloc_realloc(res, res->refs, char *, n + 2);
- if (! res->refs) {
- return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
- }
-
- res->refs[n] = talloc_move(res->refs, &ares->referral);
- res->refs[n + 1] = NULL;
- break;
-
- case LDB_REPLY_DONE:
- /* TODO: we should really support controls on entries
- * and referrals too! */
- res->controls = talloc_move(res, &ares->controls);
-
- /* this is the last message, and means the request is done */
- /* we have to signal and eventual ldb_wait() waiting that the
- * async request operation was completed */
- return ldb_request_done(req, LDB_SUCCESS);
- }
-
- talloc_free(ares);
- return LDB_SUCCESS;
-}
-
-int ldb_op_default_callback(struct ldb_request *req, struct ldb_reply *ares)
-{
- int ret;
-
- if (!ares) {
- return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
- }
-
- if (ares->error != LDB_SUCCESS) {
- ret = ares->error;
- talloc_free(ares);
- return ldb_request_done(req, ret);
- }
-
- if (ares->type != LDB_REPLY_DONE) {
- talloc_free(ares);
- ldb_set_errstring(req->handle->ldb, "Invalid reply type!");
- return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
- }
-
- talloc_free(ares);
- return ldb_request_done(req, LDB_SUCCESS);
-}
-
-int ldb_build_search_req_ex(struct ldb_request **ret_req,
- struct ldb_context *ldb,
- void *mem_ctx,
- struct ldb_dn *base,
- enum ldb_scope scope,
- struct ldb_parse_tree *tree,
- const char * const *attrs,
- struct ldb_control **controls,
- void *context,
- ldb_request_callback_t callback,
- struct ldb_request *parent)
-{
- struct ldb_request *req;
-
- *ret_req = NULL;
-
- req = talloc(mem_ctx, struct ldb_request);
- if (req == NULL) {
- ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- req->operation = LDB_SEARCH;
- if (base == NULL) {
- req->op.search.base = ldb_dn_new(req, ldb, NULL);
- } else {
- req->op.search.base = base;
- }
- req->op.search.scope = scope;
-
- req->op.search.tree = tree;
- if (req->op.search.tree == NULL) {
- ldb_set_errstring(ldb, "'tree' can't be NULL");
- talloc_free(req);
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- req->op.search.attrs = attrs;
- req->controls = controls;
- req->context = context;
- req->callback = callback;
-
- ldb_set_timeout_from_prev_req(ldb, parent, req);
-
- req->handle = ldb_handle_new(req, ldb);
- if (req->handle == NULL) {
- ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- *ret_req = req;
- return LDB_SUCCESS;
-}
-
-int ldb_build_search_req(struct ldb_request **ret_req,
- struct ldb_context *ldb,
- void *mem_ctx,
- struct ldb_dn *base,
- enum ldb_scope scope,
- const char *expression,
- const char * const *attrs,
- struct ldb_control **controls,
- void *context,
- ldb_request_callback_t callback,
- struct ldb_request *parent)
-{
- struct ldb_parse_tree *tree;
- int ret;
-
- tree = ldb_parse_tree(mem_ctx, expression);
- if (tree == NULL) {
- ldb_set_errstring(ldb, "Unable to parse search expression");
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- ret = ldb_build_search_req_ex(ret_req, ldb, mem_ctx, base,
- scope, tree, attrs, controls,
- context, callback, parent);
- if (ret == LDB_SUCCESS) {
- talloc_steal(*ret_req, tree);
- }
- return ret;
-}
-
-int ldb_build_add_req(struct ldb_request **ret_req,
- struct ldb_context *ldb,
- void *mem_ctx,
- const struct ldb_message *message,
- struct ldb_control **controls,
- void *context,
- ldb_request_callback_t callback,
- struct ldb_request *parent)
-{
- struct ldb_request *req;
-
- *ret_req = NULL;
-
- req = talloc(mem_ctx, struct ldb_request);
- if (req == NULL) {
- ldb_set_errstring(ldb, "Out of Memory");
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- req->operation = LDB_ADD;
- req->op.add.message = message;
- req->controls = controls;
- req->context = context;
- req->callback = callback;
-
- ldb_set_timeout_from_prev_req(ldb, parent, req);
-
- req->handle = ldb_handle_new(req, ldb);
- if (req->handle == NULL) {
- ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- *ret_req = req;
-
- return LDB_SUCCESS;
-}
-
-int ldb_build_mod_req(struct ldb_request **ret_req,
- struct ldb_context *ldb,
- void *mem_ctx,
- const struct ldb_message *message,
- struct ldb_control **controls,
- void *context,
- ldb_request_callback_t callback,
- struct ldb_request *parent)
-{
- struct ldb_request *req;
-
- *ret_req = NULL;
-
- req = talloc(mem_ctx, struct ldb_request);
- if (req == NULL) {
- ldb_set_errstring(ldb, "Out of Memory");
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- req->operation = LDB_MODIFY;
- req->op.mod.message = message;
- req->controls = controls;
- req->context = context;
- req->callback = callback;
-
- ldb_set_timeout_from_prev_req(ldb, parent, req);
-
- req->handle = ldb_handle_new(req, ldb);
- if (req->handle == NULL) {
- ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- *ret_req = req;
-
- return LDB_SUCCESS;
-}
-
-int ldb_build_del_req(struct ldb_request **ret_req,
- struct ldb_context *ldb,
- void *mem_ctx,
- struct ldb_dn *dn,
- struct ldb_control **controls,
- void *context,
- ldb_request_callback_t callback,
- struct ldb_request *parent)
-{
- struct ldb_request *req;
-
- *ret_req = NULL;
-
- req = talloc(mem_ctx, struct ldb_request);
- if (req == NULL) {
- ldb_set_errstring(ldb, "Out of Memory");
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- req->operation = LDB_DELETE;
- req->op.del.dn = dn;
- req->controls = controls;
- req->context = context;
- req->callback = callback;
-
- ldb_set_timeout_from_prev_req(ldb, parent, req);
-
- req->handle = ldb_handle_new(req, ldb);
- if (req->handle == NULL) {
- ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- *ret_req = req;
-
- return LDB_SUCCESS;
-}
-
-int ldb_build_rename_req(struct ldb_request **ret_req,
- struct ldb_context *ldb,
- void *mem_ctx,
- struct ldb_dn *olddn,
- struct ldb_dn *newdn,
- struct ldb_control **controls,
- void *context,
- ldb_request_callback_t callback,
- struct ldb_request *parent)
-{
- struct ldb_request *req;
-
- *ret_req = NULL;
-
- req = talloc(mem_ctx, struct ldb_request);
- if (req == NULL) {
- ldb_set_errstring(ldb, "Out of Memory");
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- req->operation = LDB_RENAME;
- req->op.rename.olddn = olddn;
- req->op.rename.newdn = newdn;
- req->controls = controls;
- req->context = context;
- req->callback = callback;
-
- ldb_set_timeout_from_prev_req(ldb, parent, req);
-
- req->handle = ldb_handle_new(req, ldb);
- if (req->handle == NULL) {
- ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- *ret_req = req;
-
- return LDB_SUCCESS;
-}
-
-int ldb_extended_default_callback(struct ldb_request *req,
- struct ldb_reply *ares)
-{
- struct ldb_result *res;
-
- res = talloc_get_type(req->context, struct ldb_result);
-
- if (!ares) {
- return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
- }
- if (ares->error != LDB_SUCCESS) {
- return ldb_request_done(req, ares->error);
- }
-
- if (ares->type == LDB_REPLY_DONE) {
-
- /* TODO: we should really support controls on entries and referrals too! */
- res->extended = talloc_move(res, &ares->response);
- res->controls = talloc_move(res, &ares->controls);
-
- talloc_free(ares);
- return ldb_request_done(req, LDB_SUCCESS);
- }
-
- talloc_free(ares);
- ldb_set_errstring(req->handle->ldb, "Invalid reply type!");
- return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
-}
-
-int ldb_build_extended_req(struct ldb_request **ret_req,
- struct ldb_context *ldb,
- void *mem_ctx,
- const char *oid,
- void *data,
- struct ldb_control **controls,
- void *context,
- ldb_request_callback_t callback,
- struct ldb_request *parent)
-{
- struct ldb_request *req;
-
- *ret_req = NULL;
-
- req = talloc(mem_ctx, struct ldb_request);
- if (req == NULL) {
- ldb_set_errstring(ldb, "Out of Memory");
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- req->operation = LDB_EXTENDED;
- req->op.extended.oid = oid;
- req->op.extended.data = data;
- req->controls = controls;
- req->context = context;
- req->callback = callback;
-
- ldb_set_timeout_from_prev_req(ldb, parent, req);
-
- req->handle = ldb_handle_new(req, ldb);
- if (req->handle == NULL) {
- ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- *ret_req = req;
-
- return LDB_SUCCESS;
-}
-
-int ldb_extended(struct ldb_context *ldb,
- const char *oid,
- void *data,
- struct ldb_result **_res)
-{
- struct ldb_request *req;
- int ret;
- struct ldb_result *res;
-
- *_res = NULL;
-
- res = talloc_zero(ldb, struct ldb_result);
- if (!res) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- ret = ldb_build_extended_req(&req, ldb, ldb,
- oid, data, NULL,
- res, ldb_extended_default_callback,
- NULL);
- if (ret != LDB_SUCCESS) goto done;
-
- ldb_set_timeout(ldb, req, 0); /* use default timeout */
-
- ret = ldb_request(ldb, req);
-
- if (ret == LDB_SUCCESS) {
- ret = ldb_wait(req->handle, LDB_WAIT_ALL);
- }
-
- talloc_free(req);
-
-done:
- if (ret != LDB_SUCCESS) {
- talloc_free(res);
- }
-
- *_res = res;
- return ret;
-}
-
-/*
- note that ldb_search() will automatically replace a NULL 'base' value
- with the defaultNamingContext from the rootDSE if available.
-*/
-int ldb_search(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
- struct ldb_result **result, struct ldb_dn *base,
- enum ldb_scope scope, const char * const *attrs,
- const char *exp_fmt, ...)
-{
- struct ldb_request *req;
- struct ldb_result *res;
- char *expression;
- va_list ap;
- int ret;
-
- expression = NULL;
- *result = NULL;
- req = NULL;
-
- res = talloc_zero(mem_ctx, struct ldb_result);
- if (!res) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- if (exp_fmt) {
- va_start(ap, exp_fmt);
- expression = talloc_vasprintf(mem_ctx, exp_fmt, ap);
- va_end(ap);
-
- if (!expression) {
- talloc_free(res);
- return LDB_ERR_OPERATIONS_ERROR;
- }
- }
-
- ret = ldb_build_search_req(&req, ldb, mem_ctx,
- base?base:ldb_get_default_basedn(ldb),
- scope,
- expression,
- attrs,
- NULL,
- res,
- ldb_search_default_callback,
- NULL);
-
- if (ret != LDB_SUCCESS) goto done;
-
- ret = ldb_request(ldb, req);
-
- if (ret == LDB_SUCCESS) {
- ret = ldb_wait(req->handle, LDB_WAIT_ALL);
- }
-
-done:
- if (ret != LDB_SUCCESS) {
- talloc_free(res);
- res = NULL;
- }
-
- talloc_free(expression);
- talloc_free(req);
-
- *result = res;
- return ret;
-}
-
-/*
- add a record to the database. Will fail if a record with the given class
- and key already exists
-*/
-int ldb_add(struct ldb_context *ldb,
- const struct ldb_message *message)
-{
- struct ldb_request *req;
- int ret;
-
- ret = ldb_msg_sanity_check(ldb, message);
- if (ret != LDB_SUCCESS) {
- return ret;
- }
-
- ret = ldb_build_add_req(&req, ldb, ldb,
- message,
- NULL,
- NULL,
- ldb_op_default_callback,
- NULL);
-
- if (ret != LDB_SUCCESS) return ret;
-
- /* do request and autostart a transaction */
- ret = ldb_autotransaction_request(ldb, req);
-
- talloc_free(req);
- return ret;
-}
-
-/*
- modify the specified attributes of a record
-*/
-int ldb_modify(struct ldb_context *ldb,
- const struct ldb_message *message)
-{
- struct ldb_request *req;
- int ret;
-
- ret = ldb_msg_sanity_check(ldb, message);
- if (ret != LDB_SUCCESS) {
- return ret;
- }
-
- ret = ldb_build_mod_req(&req, ldb, ldb,
- message,
- NULL,
- NULL,
- ldb_op_default_callback,
- NULL);
-
- if (ret != LDB_SUCCESS) return ret;
-
- /* do request and autostart a transaction */
- ret = ldb_autotransaction_request(ldb, req);
-
- talloc_free(req);
- return ret;
-}
-
-
-/*
- delete a record from the database
-*/
-int ldb_delete(struct ldb_context *ldb, struct ldb_dn *dn)
-{
- struct ldb_request *req;
- int ret;
-
- ret = ldb_build_del_req(&req, ldb, ldb,
- dn,
- NULL,
- NULL,
- ldb_op_default_callback,
- NULL);
-
- if (ret != LDB_SUCCESS) return ret;
-
- /* do request and autostart a transaction */
- ret = ldb_autotransaction_request(ldb, req);
-
- talloc_free(req);
- return ret;
-}
-
-/*
- rename a record in the database
-*/
-int ldb_rename(struct ldb_context *ldb,
- struct ldb_dn *olddn, struct ldb_dn *newdn)
-{
- struct ldb_request *req;
- int ret;
-
- ret = ldb_build_rename_req(&req, ldb, ldb,
- olddn,
- newdn,
- NULL,
- NULL,
- ldb_op_default_callback,
- NULL);
-
- if (ret != LDB_SUCCESS) return ret;
-
- /* do request and autostart a transaction */
- ret = ldb_autotransaction_request(ldb, req);
-
- talloc_free(req);
- return ret;
-}
-
-
-/*
- return the global sequence number
-*/
-int ldb_sequence_number(struct ldb_context *ldb,
- enum ldb_sequence_type type, uint64_t *seq_num)
-{
- struct ldb_seqnum_request *seq;
- struct ldb_seqnum_result *seqr;
- struct ldb_result *res;
- TALLOC_CTX *tmp_ctx;
- int ret;
-
- *seq_num = 0;
-
- tmp_ctx = talloc_zero(ldb, struct ldb_request);
- if (tmp_ctx == NULL) {
- ldb_set_errstring(ldb, "Out of Memory");
- return LDB_ERR_OPERATIONS_ERROR;
- }
- seq = talloc_zero(tmp_ctx, struct ldb_seqnum_request);
- if (seq == NULL) {
- ldb_set_errstring(ldb, "Out of Memory");
- ret = LDB_ERR_OPERATIONS_ERROR;
- goto done;
- }
- seq->type = type;
-
- ret = ldb_extended(ldb, LDB_EXTENDED_SEQUENCE_NUMBER, seq, &res);
- if (ret != LDB_SUCCESS) {
- goto done;
- }
- talloc_steal(tmp_ctx, res);
-
- if (strcmp(LDB_EXTENDED_SEQUENCE_NUMBER, res->extended->oid) != 0) {
- ldb_set_errstring(ldb, "Invalid OID in reply");
- ret = LDB_ERR_OPERATIONS_ERROR;
- goto done;
- }
- seqr = talloc_get_type(res->extended->data,
- struct ldb_seqnum_result);
- *seq_num = seqr->seq_num;
-
-done:
- talloc_free(tmp_ctx);
- return ret;
-}
-
-/*
- return extended error information
-*/
-const char *ldb_errstring(struct ldb_context *ldb)
-{
- if (ldb->err_string) {
- return ldb->err_string;
- }
-
- return NULL;
-}
-
-/*
- return a string explaining what a ldb error constant meancs
-*/
-const char *ldb_strerror(int ldb_err)
-{
- switch (ldb_err) {
- case LDB_SUCCESS:
- return "Success";
- case LDB_ERR_OPERATIONS_ERROR:
- return "Operations error";
- case LDB_ERR_PROTOCOL_ERROR:
- return "Protocol error";
- case LDB_ERR_TIME_LIMIT_EXCEEDED:
- return "Time limit exceeded";
- case LDB_ERR_SIZE_LIMIT_EXCEEDED:
- return "Size limit exceeded";
- case LDB_ERR_COMPARE_FALSE:
- return "Compare false";
- case LDB_ERR_COMPARE_TRUE:
- return "Compare true";
- case LDB_ERR_AUTH_METHOD_NOT_SUPPORTED:
- return "Auth method not supported";
- case LDB_ERR_STRONG_AUTH_REQUIRED:
- return "Strong auth required";
-/* 9 RESERVED */
- case LDB_ERR_REFERRAL:
- return "Referral error";
- case LDB_ERR_ADMIN_LIMIT_EXCEEDED:
- return "Admin limit exceeded";
- case LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION:
- return "Unsupported critical extension";
- case LDB_ERR_CONFIDENTIALITY_REQUIRED:
- return "Confidentiality required";
- case LDB_ERR_SASL_BIND_IN_PROGRESS:
- return "SASL bind in progress";
- case LDB_ERR_NO_SUCH_ATTRIBUTE:
- return "No such attribute";
- case LDB_ERR_UNDEFINED_ATTRIBUTE_TYPE:
- return "Undefined attribute type";
- case LDB_ERR_INAPPROPRIATE_MATCHING:
- return "Inappropriate matching";
- case LDB_ERR_CONSTRAINT_VIOLATION:
- return "Constraint violation";
- case LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS:
- return "Attribute or value exists";
- case LDB_ERR_INVALID_ATTRIBUTE_SYNTAX:
- return "Invalid attribute syntax";
-/* 22-31 unused */
- case LDB_ERR_NO_SUCH_OBJECT:
- return "No such object";
- case LDB_ERR_ALIAS_PROBLEM:
- return "Alias problem";
- case LDB_ERR_INVALID_DN_SYNTAX:
- return "Invalid DN syntax";
-/* 35 RESERVED */
- case LDB_ERR_ALIAS_DEREFERENCING_PROBLEM:
- return "Alias dereferencing problem";
-/* 37-47 unused */
- case LDB_ERR_INAPPROPRIATE_AUTHENTICATION:
- return "Inappropriate authentication";
- case LDB_ERR_INVALID_CREDENTIALS:
- return "Invalid credentials";
- case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
- return "insufficient access rights";
- case LDB_ERR_BUSY:
- return "Busy";
- case LDB_ERR_UNAVAILABLE:
- return "Unavailable";
- case LDB_ERR_UNWILLING_TO_PERFORM:
- return "Unwilling to perform";
- case LDB_ERR_LOOP_DETECT:
- return "Loop detect";
-/* 55-63 unused */
- case LDB_ERR_NAMING_VIOLATION:
- return "Naming violation";
- case LDB_ERR_OBJECT_CLASS_VIOLATION:
- return "Object class violation";
- case LDB_ERR_NOT_ALLOWED_ON_NON_LEAF:
- return "Not allowed on non-leaf";
- case LDB_ERR_NOT_ALLOWED_ON_RDN:
- return "Not allowed on RDN";
- case LDB_ERR_ENTRY_ALREADY_EXISTS:
- return "Entry already exists";
- case LDB_ERR_OBJECT_CLASS_MODS_PROHIBITED:
- return "Object class mods prohibited";
-/* 70 RESERVED FOR CLDAP */
- case LDB_ERR_AFFECTS_MULTIPLE_DSAS:
- return "Affects multiple DSAs";
-/* 72-79 unused */
- case LDB_ERR_OTHER:
- return "Other";
- }
-
- return "Unknown error";
-}
-
-/*
- set backend specific opaque parameters
-*/
-int ldb_set_opaque(struct ldb_context *ldb, const char *name, void *value)
-{
- struct ldb_opaque *o;
-
- /* allow updating an existing value */
- for (o=ldb->opaque;o;o=o->next) {
- if (strcmp(o->name, name) == 0) {
- o->value = value;
- return LDB_SUCCESS;
- }
- }
-
- o = talloc(ldb, struct ldb_opaque);
- if (o == NULL) {
- ldb_oom(ldb);
- return LDB_ERR_OTHER;
- }
- o->next = ldb->opaque;
- o->name = name;
- o->value = value;
- ldb->opaque = o;
- return LDB_SUCCESS;
-}
-
-/*
- get a previously set opaque value
-*/
-void *ldb_get_opaque(struct ldb_context *ldb, const char *name)
-{
- struct ldb_opaque *o;
- for (o=ldb->opaque;o;o=o->next) {
- if (strcmp(o->name, name) == 0) {
- return o->value;
- }
- }
- return NULL;
-}
diff --git a/ldb/common/ldb_attributes.c b/ldb/common/ldb_attributes.c
deleted file mode 100644
index 001bc45e..00000000
--- a/ldb/common/ldb_attributes.c
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- ldb database library
-
- Copyright (C) Andrew Tridgell 2005
-
- ** NOTE! The following LGPL license applies to the ldb
- ** library. This does NOT imply that all of Samba is released
- ** under the LGPL
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-/*
- register handlers for specific attributes and objectclass relationships
-
- this allows a backend to store its schema information in any format
- it likes (or to not have any schema information at all) while keeping the
- message matching logic generic
-*/
-
-#include "ldb_includes.h"
-
-/*
- add a attribute to the ldb_schema
-
- if flags contains LDB_ATTR_FLAG_ALLOCATED
- the attribute name string will be copied using
- talloc_strdup(), otherwise it needs to be a static const
- string at least with a lifetime longer than the ldb struct!
-
- the ldb_schema_syntax structure should be a pointer
- to a static const struct or at least it needs to be
- a struct with a longer lifetime than the ldb context!
-
-*/
-int ldb_schema_attribute_add_with_syntax(struct ldb_context *ldb,
- const char *attribute,
- unsigned flags,
- const struct ldb_schema_syntax *syntax)
-{
- int i, n;
- struct ldb_schema_attribute *a;
-
- if (!syntax) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- n = ldb->schema.num_attributes + 1;
-
- a = talloc_realloc(ldb, ldb->schema.attributes,
- struct ldb_schema_attribute, n);
- if (a == NULL) {
- ldb_oom(ldb);
- return -1;
- }
- ldb->schema.attributes = a;
-
- for (i = 0; i < ldb->schema.num_attributes; i++) {
- int cmp = ldb_attr_cmp(attribute, a[i].name);
- if (cmp == 0) {
- /* silently ignore attempts to overwrite fixed attributes */
- if (a[i].flags & LDB_ATTR_FLAG_FIXED) {
- return 0;
- }
- if (a[i].flags & LDB_ATTR_FLAG_ALLOCATED) {
- talloc_free(discard_const_p(char, a[i].name));
- }
- /* To cancel out increment below */
- ldb->schema.num_attributes--;
- break;
- } else if (cmp < 0) {
- memmove(a+i+1, a+i, sizeof(*a) * (ldb->schema.num_attributes-i));
- break;
- }
- }
- ldb->schema.num_attributes++;
-
- a[i].name = attribute;
- a[i].flags = flags;
- a[i].syntax = syntax;
-
- if (a[i].flags & LDB_ATTR_FLAG_ALLOCATED) {
- a[i].name = talloc_strdup(a, a[i].name);
- if (a[i].name == NULL) {
- ldb_oom(ldb);
- return -1;
- }
- }
-
- return 0;
-}
-
-static const struct ldb_schema_syntax ldb_syntax_default = {
- .name = LDB_SYNTAX_OCTET_STRING,
- .ldif_read_fn = ldb_handler_copy,
- .ldif_write_fn = ldb_handler_copy,
- .canonicalise_fn = ldb_handler_copy,
- .comparison_fn = ldb_comparison_binary
-};
-
-static const struct ldb_schema_attribute ldb_attribute_default = {
- .name = NULL,
- .flags = 0,
- .syntax = &ldb_syntax_default
-};
-
-/*
- return the attribute handlers for a given attribute
-*/
-const struct ldb_schema_attribute *ldb_schema_attribute_by_name(struct ldb_context *ldb,
- const char *name)
-{
- int i, e, b = 0, r;
- const struct ldb_schema_attribute *def = &ldb_attribute_default;
-
- /* as handlers are sorted, '*' must be the first if present */
- if (strcmp(ldb->schema.attributes[0].name, "*") == 0) {
- def = &ldb->schema.attributes[0];
- b = 1;
- }
-
- /* do a binary search on the array */
- e = ldb->schema.num_attributes - 1;
-
- while (b <= e) {
-
- i = (b + e) / 2;
-
- r = ldb_attr_cmp(name, ldb->schema.attributes[i].name);
- if (r == 0) {
- return &ldb->schema.attributes[i];
- }
- if (r < 0) {
- e = i - 1;
- } else {
- b = i + 1;
- }
-
- }
-
- return def;
-}
-
-
-/*
- add to the list of ldif handlers for this ldb context
-*/
-void ldb_schema_attribute_remove(struct ldb_context *ldb, const char *name)
-{
- const struct ldb_schema_attribute *a;
- int i;
-
- a = ldb_schema_attribute_by_name(ldb, name);
- if (a == NULL || a->name == NULL) {
- return;
- }
-
- /* FIXED attributes are never removed */
- if (a->flags & LDB_ATTR_FLAG_FIXED) {
- return;
- }
-
- if (a->flags & LDB_ATTR_FLAG_ALLOCATED) {
- talloc_free(discard_const_p(char, a->name));
- }
-
- i = a - ldb->schema.attributes;
- if (i < ldb->schema.num_attributes - 1) {
- memmove(&ldb->schema.attributes[i],
- a+1, sizeof(*a) * (ldb->schema.num_attributes-(i+1)));
- }
-
- ldb->schema.num_attributes--;
-}
-
-/*
- setup a attribute handler using a standard syntax
-*/
-int ldb_schema_attribute_add(struct ldb_context *ldb,
- const char *attribute,
- unsigned flags,
- const char *syntax)
-{
- const struct ldb_schema_syntax *s = ldb_standard_syntax_by_name(ldb, syntax);
- return ldb_schema_attribute_add_with_syntax(ldb, attribute, flags, s);
-}
-
-/*
- setup the attribute handles for well known attributes
-*/
-int ldb_setup_wellknown_attributes(struct ldb_context *ldb)
-{
- const struct {
- const char *attr;
- const char *syntax;
- } wellknown[] = {
- { "dn", LDB_SYNTAX_DN },
- { "distinguishedName", LDB_SYNTAX_DN },
- { "cn", LDB_SYNTAX_DIRECTORY_STRING },
- { "dc", LDB_SYNTAX_DIRECTORY_STRING },
- { "ou", LDB_SYNTAX_DIRECTORY_STRING },
- { "objectClass", LDB_SYNTAX_OBJECTCLASS }
- };
- int i;
- int ret;
-
- for (i=0;i<ARRAY_SIZE(wellknown);i++) {
- ret = ldb_schema_attribute_add(ldb, wellknown[i].attr, 0,
- wellknown[i].syntax);
- if (ret != LDB_SUCCESS) {
- return ret;
- }
- }
-
- return LDB_SUCCESS;
-}
-
-
-/*
- add a extended dn syntax to the ldb_schema
-*/
-int ldb_dn_extended_add_syntax(struct ldb_context *ldb,
- unsigned flags,
- const struct ldb_dn_extended_syntax *syntax)
-{
- int n;
- struct ldb_dn_extended_syntax *a;
-
- if (!syntax) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- n = ldb->schema.num_dn_extended_syntax + 1;
-
- a = talloc_realloc(ldb, ldb->schema.dn_extended_syntax,
- struct ldb_dn_extended_syntax, n);
-
- if (!a) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- a[ldb->schema.num_dn_extended_syntax] = *syntax;
- ldb->schema.dn_extended_syntax = a;
-
- ldb->schema.num_dn_extended_syntax = n;
-
- return LDB_SUCCESS;
-}
-
-/*
- return the extended dn syntax for a given name
-*/
-const struct ldb_dn_extended_syntax *ldb_dn_extended_syntax_by_name(struct ldb_context *ldb,
- const char *name)
-{
- int i;
- for (i=0; i < ldb->schema.num_dn_extended_syntax; i++) {
- if (ldb_attr_cmp(ldb->schema.dn_extended_syntax[i].name, name) == 0) {
- return &ldb->schema.dn_extended_syntax[i];
- }
- }
- return NULL;
-}
-
diff --git a/ldb/common/ldb_controls.c b/ldb/common/ldb_controls.c
deleted file mode 100644
index 6fad5012..00000000
--- a/ldb/common/ldb_controls.c
+++ /dev/null
@@ -1,597 +0,0 @@
-/*
- ldb database library
-
- Copyright (C) Simo Sorce 2005
-
- ** NOTE! The following LGPL license applies to the ldb
- ** library. This does NOT imply that all of Samba is released
- ** under the LGPL
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-/*
- * Name: ldb_controls.c
- *
- * Component: ldb controls utility functions
- *
- * Description: helper functions for control modules
- *
- * Author: Simo Sorce
- */
-
-#include "ldb_includes.h"
-
-/* check if a control with the specified "oid" exist and return it */
-/* returns NULL if not found */
-struct ldb_control *ldb_request_get_control(struct ldb_request *req, const char *oid)
-{
- int i;
-
- /* check if there's a paged request control */
- if (req->controls != NULL) {
- for (i = 0; req->controls[i]; i++) {
- if (strcmp(oid, req->controls[i]->oid) == 0) {
- break;
- }
- }
-
- return req->controls[i];
- }
-
- return NULL;
-}
-
-/* check if a control with the specified "oid" exist and return it */
-/* returns NULL if not found */
-struct ldb_control *ldb_reply_get_control(struct ldb_reply *rep, const char *oid)
-{
- int i;
-
- /* check if there's a paged request control */
- if (rep->controls != NULL) {
- for (i = 0; rep->controls[i]; i++) {
- if (strcmp(oid, rep->controls[i]->oid) == 0) {
- break;
- }
- }
-
- return rep->controls[i];
- }
-
- return NULL;
-}
-
-/* saves the current controls list into the "saver" and replace the one in req with a new one excluding
-the "exclude" control */
-/* returns False on error */
-int save_controls(struct ldb_control *exclude, struct ldb_request *req, struct ldb_control ***saver)
-{
- struct ldb_control **lcs;
- int i, j;
-
- *saver = req->controls;
- for (i = 0; req->controls[i]; i++);
- if (i == 1) {
- req->controls = NULL;
- return 1;
- }
-
- lcs = talloc_array(req, struct ldb_control *, i);
- if (!lcs) {
- return 0;
- }
-
- for (i = 0, j = 0; (*saver)[i]; i++) {
- if (exclude == (*saver)[i]) continue;
- lcs[j] = (*saver)[i];
- j++;
- }
- lcs[j] = NULL;
-
- req->controls = lcs;
- return 1;
-}
-
-/* check if there's any control marked as critical in the list */
-/* return True if any, False if none */
-int check_critical_controls(struct ldb_control **controls)
-{
- int i;
-
- if (controls == NULL) {
- return 0;
- }
-
- for (i = 0; controls[i]; i++) {
- if (controls[i]->critical) {
- return 1;
- }
- }
-
- return 0;
-}
-
-int ldb_request_add_control(struct ldb_request *req, const char *oid, bool critical, void *data)
-{
- unsigned n;
- struct ldb_control **ctrls;
- struct ldb_control *ctrl;
-
- for (n=0; req->controls && req->controls[n];) { n++; }
-
- ctrls = talloc_realloc(req, req->controls,
- struct ldb_control *,
- n + 2);
- if (!ctrls) return LDB_ERR_OPERATIONS_ERROR;
- req->controls = ctrls;
- ctrls[n] = NULL;
- ctrls[n+1] = NULL;
-
- ctrl = talloc(ctrls, struct ldb_control);
- if (!ctrl) return LDB_ERR_OPERATIONS_ERROR;
-
- ctrl->oid = talloc_strdup(ctrl, oid);
- if (!ctrl->oid) return LDB_ERR_OPERATIONS_ERROR;
- ctrl->critical = critical;
- ctrl->data = data;
-
- ctrls[n] = ctrl;
- return LDB_SUCCESS;
-}
-
-/* Parse controls from the format used on the command line and in ejs */
-
-struct ldb_control **ldb_parse_control_strings(struct ldb_context *ldb, void *mem_ctx, const char **control_strings)
-{
- int i;
- struct ldb_control **ctrl;
-
- char *error_string = NULL;
-
- if (control_strings == NULL || control_strings[0] == NULL)
- return NULL;
-
- for (i = 0; control_strings[i]; i++);
-
- ctrl = talloc_array(mem_ctx, struct ldb_control *, i + 1);
-
- for (i = 0; control_strings[i]; i++) {
- if (strncmp(control_strings[i], "vlv:", 4) == 0) {
- struct ldb_vlv_req_control *control;
- const char *p;
- char attr[1024];
- char ctxid[1024];
- int crit, bc, ac, os, cc, ret;
-
- attr[0] = '\0';
- ctxid[0] = '\0';
- p = &(control_strings[i][4]);
- ret = sscanf(p, "%d:%d:%d:%d:%d:%1023[^$]", &crit, &bc, &ac, &os, &cc, ctxid);
- if (ret < 5) {
- ret = sscanf(p, "%d:%d:%d:%1023[^:]:%1023[^$]", &crit, &bc, &ac, attr, ctxid);
- }
-
- if ((ret < 4) || (crit < 0) || (crit > 1)) {
- error_string = talloc_asprintf(mem_ctx, "invalid server_sort control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b):bc(n):ac(n):<os(n):cc(n)|attr(s)>[:ctxid(o)]\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean, n = number, s = string, o = b64 binary blob");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
- return NULL;
- }
- if (!(ctrl[i] = talloc(ctrl, struct ldb_control))) {
- ldb_oom(ldb);
- return NULL;
- }
- ctrl[i]->oid = LDB_CONTROL_VLV_REQ_OID;
- ctrl[i]->critical = crit;
- if (!(control = talloc(ctrl[i],
- struct ldb_vlv_req_control))) {
- ldb_oom(ldb);
- return NULL;
- }
- control->beforeCount = bc;
- control->afterCount = ac;
- if (attr[0]) {
- control->type = 1;
- control->match.gtOrEq.value = talloc_strdup(control, attr);
- control->match.gtOrEq.value_len = strlen(attr);
- } else {
- control->type = 0;
- control->match.byOffset.offset = os;
- control->match.byOffset.contentCount = cc;
- }
- if (ctxid[0]) {
- control->ctxid_len = ldb_base64_decode(ctxid);
- control->contextId = (char *)talloc_memdup(control, ctxid, control->ctxid_len);
- } else {
- control->ctxid_len = 0;
- control->contextId = NULL;
- }
- ctrl[i]->data = control;
-
- continue;
- }
-
- if (strncmp(control_strings[i], "dirsync:", 8) == 0) {
- struct ldb_dirsync_control *control;
- const char *p;
- char cookie[1024];
- int crit, flags, max_attrs, ret;
-
- cookie[0] = '\0';
- p = &(control_strings[i][8]);
- ret = sscanf(p, "%d:%d:%d:%1023[^$]", &crit, &flags, &max_attrs, cookie);
-
- if ((ret < 3) || (crit < 0) || (crit > 1) || (flags < 0) || (max_attrs < 0)) {
- error_string = talloc_asprintf(mem_ctx, "invalid dirsync control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b):flags(n):max_attrs(n)[:cookie(o)]\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean, n = number, o = b64 binary blob");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
- return NULL;
- }
-
- /* w2k3 seems to ignore the parameter,
- * but w2k sends a wrong cookie when this value is to small
- * this would cause looping forever, while getting
- * the same data and same cookie forever
- */
- if (max_attrs == 0) max_attrs = 0x0FFFFFFF;
-
- ctrl[i] = talloc(ctrl, struct ldb_control);
- ctrl[i]->oid = LDB_CONTROL_DIRSYNC_OID;
- ctrl[i]->critical = crit;
- control = talloc(ctrl[i], struct ldb_dirsync_control);
- control->flags = flags;
- control->max_attributes = max_attrs;
- if (*cookie) {
- control->cookie_len = ldb_base64_decode(cookie);
- control->cookie = (char *)talloc_memdup(control, cookie, control->cookie_len);
- } else {
- control->cookie = NULL;
- control->cookie_len = 0;
- }
- ctrl[i]->data = control;
-
- continue;
- }
-
- if (strncmp(control_strings[i], "asq:", 4) == 0) {
- struct ldb_asq_control *control;
- const char *p;
- char attr[256];
- int crit, ret;
-
- attr[0] = '\0';
- p = &(control_strings[i][4]);
- ret = sscanf(p, "%d:%255[^$]", &crit, attr);
- if ((ret != 2) || (crit < 0) || (crit > 1) || (attr[0] == '\0')) {
- error_string = talloc_asprintf(mem_ctx, "invalid asq control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b):attr(s)\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean, s = string");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
- return NULL;
- }
-
- ctrl[i] = talloc(ctrl, struct ldb_control);
- if (!ctrl[i]) {
- ldb_oom(ldb);
- return NULL;
- }
- ctrl[i]->oid = LDB_CONTROL_ASQ_OID;
- ctrl[i]->critical = crit;
- control = talloc(ctrl[i], struct ldb_asq_control);
- control->request = 1;
- control->source_attribute = talloc_strdup(control, attr);
- control->src_attr_len = strlen(attr);
- ctrl[i]->data = control;
-
- continue;
- }
-
- if (strncmp(control_strings[i], "extended_dn:", 12) == 0) {
- struct ldb_extended_dn_control *control;
- const char *p;
- int crit, type, ret;
-
- p = &(control_strings[i][12]);
- ret = sscanf(p, "%d:%d", &crit, &type);
- if ((ret != 2) || (crit < 0) || (crit > 1) || (type < 0) || (type > 1)) {
- ret = sscanf(p, "%d", &crit);
- if ((ret != 1) || (crit < 0) || (crit > 1)) {
- error_string = talloc_asprintf(mem_ctx, "invalid extended_dn control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b)[:type(i)]\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean\n");
- error_string = talloc_asprintf_append(error_string, " i = integer\n");
- error_string = talloc_asprintf_append(error_string, " valid values are: 0 - hexadecimal representation\n");
- error_string = talloc_asprintf_append(error_string, " 1 - normal string representation");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
- return NULL;
- }
- control = NULL;
- } else {
- control = talloc(ctrl, struct ldb_extended_dn_control);
- control->type = type;
- }
-
- ctrl[i] = talloc(ctrl, struct ldb_control);
- if (!ctrl[i]) {
- ldb_oom(ldb);
- return NULL;
- }
- ctrl[i]->oid = LDB_CONTROL_EXTENDED_DN_OID;
- ctrl[i]->critical = crit;
- ctrl[i]->data = talloc_steal(ctrl[i], control);
-
- continue;
- }
-
- if (strncmp(control_strings[i], "sd_flags:", 9) == 0) {
- struct ldb_sd_flags_control *control;
- const char *p;
- int crit, ret;
- unsigned secinfo_flags;
-
- p = &(control_strings[i][9]);
- ret = sscanf(p, "%d:%u", &crit, &secinfo_flags);
- if ((ret != 2) || (crit < 0) || (crit > 1) || (secinfo_flags < 0) || (secinfo_flags > 0xF)) {
- error_string = talloc_asprintf(mem_ctx, "invalid sd_flags control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b):secinfo_flags(n)\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean, n = number");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
- return NULL;
- }
-
- ctrl[i] = talloc(ctrl, struct ldb_control);
- if (!ctrl[i]) {
- ldb_oom(ldb);
- return NULL;
- }
- ctrl[i]->oid = LDB_CONTROL_SD_FLAGS_OID;
- ctrl[i]->critical = crit;
- control = talloc(ctrl[i], struct ldb_sd_flags_control);
- control->secinfo_flags = secinfo_flags;
- ctrl[i]->data = control;
-
- continue;
- }
-
- if (strncmp(control_strings[i], "search_options:", 15) == 0) {
- struct ldb_search_options_control *control;
- const char *p;
- int crit, ret;
- unsigned search_options;
-
- p = &(control_strings[i][15]);
- ret = sscanf(p, "%d:%u", &crit, &search_options);
- if ((ret != 2) || (crit < 0) || (crit > 1) || (search_options < 0) || (search_options > 0xF)) {
- error_string = talloc_asprintf(mem_ctx, "invalid search_options control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b):search_options(n)\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean, n = number");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
- return NULL;
- }
-
- ctrl[i] = talloc(ctrl, struct ldb_control);
- if (!ctrl[i]) {
- ldb_oom(ldb);
- return NULL;
- }
- ctrl[i]->oid = LDB_CONTROL_SEARCH_OPTIONS_OID;
- ctrl[i]->critical = crit;
- control = talloc(ctrl[i], struct ldb_search_options_control);
- control->search_options = search_options;
- ctrl[i]->data = control;
-
- continue;
- }
-
- if (strncmp(control_strings[i], "domain_scope:", 13) == 0) {
- const char *p;
- int crit, ret;
-
- p = &(control_strings[i][13]);
- ret = sscanf(p, "%d", &crit);
- if ((ret != 1) || (crit < 0) || (crit > 1)) {
- error_string = talloc_asprintf(mem_ctx, "invalid domain_scope control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
- return NULL;
- }
-
- ctrl[i] = talloc(ctrl, struct ldb_control);
- if (!ctrl[i]) {
- ldb_oom(ldb);
- return NULL;
- }
- ctrl[i]->oid = LDB_CONTROL_DOMAIN_SCOPE_OID;
- ctrl[i]->critical = crit;
- ctrl[i]->data = NULL;
-
- continue;
- }
-
- if (strncmp(control_strings[i], "paged_results:", 14) == 0) {
- struct ldb_paged_control *control;
- const char *p;
- int crit, size, ret;
-
- p = &(control_strings[i][14]);
- ret = sscanf(p, "%d:%d", &crit, &size);
-
- if ((ret != 2) || (crit < 0) || (crit > 1) || (size < 0)) {
- error_string = talloc_asprintf(mem_ctx, "invalid paged_results control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b):size(n)\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean, n = number");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
- return NULL;
- }
-
- ctrl[i] = talloc(ctrl, struct ldb_control);
- if (!ctrl[i]) {
- ldb_oom(ldb);
- return NULL;
- }
- ctrl[i]->oid = LDB_CONTROL_PAGED_RESULTS_OID;
- ctrl[i]->critical = crit;
- control = talloc(ctrl[i], struct ldb_paged_control);
- control->size = size;
- control->cookie = NULL;
- control->cookie_len = 0;
- ctrl[i]->data = control;
-
- continue;
- }
-
- if (strncmp(control_strings[i], "server_sort:", 12) == 0) {
- struct ldb_server_sort_control **control;
- const char *p;
- char attr[256];
- char rule[128];
- int crit, rev, ret;
-
- attr[0] = '\0';
- rule[0] = '\0';
- p = &(control_strings[i][12]);
- ret = sscanf(p, "%d:%d:%255[^:]:%127[^:]", &crit, &rev, attr, rule);
- if ((ret < 3) || (crit < 0) || (crit > 1) || (rev < 0 ) || (rev > 1) ||attr[0] == '\0') {
- error_string = talloc_asprintf(mem_ctx, "invalid server_sort control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b):rev(b):attr(s)[:rule(s)]\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean, s = string");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
- return NULL;
- }
- ctrl[i] = talloc(ctrl, struct ldb_control);
- if (!ctrl[i]) {
- ldb_oom(ldb);
- return NULL;
- }
- ctrl[i]->oid = LDB_CONTROL_SERVER_SORT_OID;
- ctrl[i]->critical = crit;
- control = talloc_array(ctrl[i], struct ldb_server_sort_control *, 2);
- control[0] = talloc(control, struct ldb_server_sort_control);
- control[0]->attributeName = talloc_strdup(control, attr);
- if (rule[0])
- control[0]->orderingRule = talloc_strdup(control, rule);
- else
- control[0]->orderingRule = NULL;
- control[0]->reverse = rev;
- control[1] = NULL;
- ctrl[i]->data = control;
-
- continue;
- }
-
- if (strncmp(control_strings[i], "notification:", 13) == 0) {
- const char *p;
- int crit, ret;
-
- p = &(control_strings[i][13]);
- ret = sscanf(p, "%d", &crit);
- if ((ret != 1) || (crit < 0) || (crit > 1)) {
- error_string = talloc_asprintf(mem_ctx, "invalid notification control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
- return NULL;
- }
-
- ctrl[i] = talloc(ctrl, struct ldb_control);
- if (!ctrl[i]) {
- ldb_oom(ldb);
- return NULL;
- }
- ctrl[i]->oid = LDB_CONTROL_NOTIFICATION_OID;
- ctrl[i]->critical = crit;
- ctrl[i]->data = NULL;
-
- continue;
- }
-
- if (strncmp(control_strings[i], "show_deleted:", 13) == 0) {
- const char *p;
- int crit, ret;
-
- p = &(control_strings[i][13]);
- ret = sscanf(p, "%d", &crit);
- if ((ret != 1) || (crit < 0) || (crit > 1)) {
- error_string = talloc_asprintf(mem_ctx, "invalid show_deleted control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
- return NULL;
- }
-
- ctrl[i] = talloc(ctrl, struct ldb_control);
- if (!ctrl[i]) {
- ldb_oom(ldb);
- return NULL;
- }
- ctrl[i]->oid = LDB_CONTROL_SHOW_DELETED_OID;
- ctrl[i]->critical = crit;
- ctrl[i]->data = NULL;
-
- continue;
- }
-
- if (strncmp(control_strings[i], "permissive_modify:", 18) == 0) {
- const char *p;
- int crit, ret;
-
- p = &(control_strings[i][18]);
- ret = sscanf(p, "%d", &crit);
- if ((ret != 1) || (crit < 0) || (crit > 1)) {
- error_string = talloc_asprintf(mem_ctx, "invalid permissive_modify control syntax\n");
- error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
- error_string = talloc_asprintf_append(error_string, " note: b = boolean");
- ldb_set_errstring(ldb, error_string);
- talloc_free(error_string);
- return NULL;
- }
-
- ctrl[i] = talloc(ctrl, struct ldb_control);
- if (!ctrl[i]) {
- ldb_oom(ldb);
- return NULL;
- }
- ctrl[i]->oid = LDB_CONTROL_PERMISSIVE_MODIFY_OID;
- ctrl[i]->critical = crit;
- ctrl[i]->data = NULL;
-
- continue;
- }
-
- /* no controls matched, throw an error */
- ldb_asprintf_errstring(ldb, "Invalid control name: '%s'", control_strings[i]);
- return NULL;
- }
-
- ctrl[i] = NULL;
-
- return ctrl;
-}
-
-
diff --git a/ldb/common/ldb_debug.c b/ldb/common/ldb_debug.c
deleted file mode 100644
index 0f78e37c..00000000
--- a/ldb/common/ldb_debug.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- ldb database library
-
- Copyright (C) Andrew Tridgell 2004
-
- ** NOTE! The following LGPL license applies to the ldb
- ** library. This does NOT imply that all of Samba is released
- ** under the LGPL
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-/*
- * Name: ldb
- *
- * Component: ldb debug
- *
- * Description: functions for printing debug messages
- *
- * Author: Andrew Tridgell
- */
-
-#include "ldb_includes.h"
-
-/*
- this allows the user to choose their own debug function
-*/
-int ldb_set_debug(struct ldb_context *ldb,
- void (*debug)(void *context, enum ldb_debug_level level,
- const char *fmt, va_list ap),
- void *context)
-{
- ldb->debug_ops.debug = debug;
- ldb->debug_ops.context = context;
- return 0;
-}
-
-/*
- debug function for ldb_set_debug_stderr
-*/
-static void ldb_debug_stderr(void *context, enum ldb_debug_level level,
- const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0);
-static void ldb_debug_stderr(void *context, enum ldb_debug_level level,
- const char *fmt, va_list ap)
-{
- if (level <= LDB_DEBUG_WARNING) {
- vfprintf(stderr, fmt, ap);
- }
-}
-
-/*
- convenience function to setup debug messages on stderr
- messages of level LDB_DEBUG_WARNING and higher are printed
-*/
-int ldb_set_debug_stderr(struct ldb_context *ldb)
-{
- return ldb_set_debug(ldb, ldb_debug_stderr, ldb);
-}
-
-/*
- log a message
-*/
-void ldb_debug(struct ldb_context *ldb, enum ldb_debug_level level, const char *fmt, ...)
-{
- va_list ap;
- if (ldb->debug_ops.debug == NULL) {
- ldb_set_debug_stderr(ldb);
- }
- va_start(ap, fmt);
- ldb->debug_ops.debug(ldb->debug_ops.context, level, fmt, ap);
- va_end(ap);
-}
-
-
-/*
- log a message, and set the ldb error string to the same message
-*/
-void ldb_debug_set(struct ldb_context *ldb, enum ldb_debug_level level,
- const char *fmt, ...)
-{
- va_list ap;
- char *msg;
- va_start(ap, fmt);
- msg = talloc_vasprintf(ldb, fmt, ap);
- va_end(ap);
- if (msg != NULL) {
- ldb_set_errstring(ldb, msg);
- ldb_debug(ldb, level, "%s", msg);
- }
- talloc_free(msg);
-}
-
diff --git a/ldb/common/ldb_dn.c b/ldb/common/ldb_dn.c
deleted file mode 100644
index 02e21a2b..00000000
--- a/ldb/common/ldb_dn.c
+++ /dev/null
@@ -1,1800 +0,0 @@
-/*
- ldb database library
-
- Copyright (C) Simo Sorce 2005
-
- ** NOTE! The following LGPL license applies to the ldb
- ** library. This does NOT imply that all of Samba is released
- ** under the LGPL
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-/*
- * Name: ldb
- *
- * Component: ldb dn creation and manipulation utility functions
- *
- * Description: - explode a dn into it's own basic elements
- * and put them in a structure (only if necessary)
- * - manipulate ldb_dn structures
- *
- * Author: Simo Sorce
- */
-
-#include "ldb_includes.h"
-#include <ctype.h>
-
-#define LDB_DN_NULL_FAILED(x) if (!(x)) goto failed
-
-#define LDB_FREE(x) do { talloc_free(x); x = NULL; } while(0)
-
-/**
- internal ldb exploded dn structures
-*/
-struct ldb_dn_component {
-
- char *name;
- struct ldb_val value;
-
- char *cf_name;
- struct ldb_val cf_value;
-};
-
-struct ldb_dn_extended_component {
-
- char *name;
- struct ldb_val value;
-};
-
-struct ldb_dn {
-
- struct ldb_context *ldb;
-
- /* Special DNs are always linearized */
- bool special;
- bool invalid;
-
- bool valid_case;
-
- char *linearized;
- char *extended_linearized;
- char *casefold;
-
- unsigned int comp_num;
- struct ldb_dn_component *components;
-
- unsigned int extended_comp_num;
- struct ldb_dn_extended_component *extended_components;
-};
-
-/* strdn may be NULL */
-struct ldb_dn *ldb_dn_from_ldb_val(void *mem_ctx, struct ldb_context *ldb, const struct ldb_val *strdn)
-{
- struct ldb_dn *dn;
-
- if (! ldb) return NULL;
-
- dn = talloc_zero(mem_ctx, struct ldb_dn);
- LDB_DN_NULL_FAILED(dn);
-
- dn->ldb = ldb;
-
- if (strdn->data && strdn->length) {
- if (strdn->data[0] == '@') {
- dn->special = true;
- }
- dn->extended_linearized = talloc_strndup(dn, (const char *)strdn->data, strdn->length);
- LDB_DN_NULL_FAILED(dn->extended_linearized);
-
- if (strdn->data[0] == '<') {
- const char *p_save, *p = dn->extended_linearized;
- do {
- p_save = p;
- p = strstr(p, ">;");
- if (p) {
- p = p + 2;
- }
- } while (p);
-
- if (p_save == dn->extended_linearized) {
- dn->linearized = talloc_strdup(dn, "");
- } else {
- dn->linearized = talloc_strdup(dn, p_save);
- }
- LDB_DN_NULL_FAILED(dn->linearized);
- } else {
- dn->linearized = dn->extended_linearized;
- dn->extended_linearized = NULL;
- }
- } else {
- dn->linearized = talloc_strdup(dn, "");
- LDB_DN_NULL_FAILED(dn->linearized);
- }
-
- return dn;
-
-failed:
- talloc_free(dn);
- return NULL;
-}
-
-/* strdn may be NULL */
-struct ldb_dn *ldb_dn_new(void *mem_ctx, struct ldb_context *ldb, const char *strdn)
-{
- struct ldb_val blob;
- blob.data = strdn;
- blob.length = strdn ? strlen(strdn) : 0;
- return ldb_dn_from_ldb_val(mem_ctx, ldb, &blob);
-}
-
-struct ldb_dn *ldb_dn_new_fmt(void *mem_ctx, struct ldb_context *ldb, const char *new_fmt, ...)
-{
- char *strdn;
- va_list ap;
-
- if ( (! mem_ctx) || (! ldb)) return NULL;
-
- va_start(ap, new_fmt);
- strdn = talloc_vasprintf(mem_ctx, new_fmt, ap);
- va_end(ap);
-
- if (strdn) {
- struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb, strdn);
- talloc_free(strdn);
- return dn;
- }
-
- return NULL;
-}
-
-static int ldb_dn_escape_internal(char *dst, const char *src, int len)
-{
- const char *p, *s;
- char *d;
- int l;
-
- p = s = src;
- d = dst;
-
- while (p - src < len) {
-
- p += strcspn(p, ",=\n+<>#;\\\"");
-
- if (p - src == len) /* found no escapable chars */
- break;
-
- memcpy(d, s, p - s); /* copy the part of the string before the stop */
- d += (p - s); /* move to current position */
-
- if (*p) { /* it is a normal escapable character */
- *d++ = '\\';
- *d++ = *p++;
- } else { /* we have a zero byte in the string */
- strncpy(d, "\00", 3); /* escape the zero */
- d += 3;
- p++; /* skip the zero */
- }
- s = p; /* move forward */
- }
-
- /* copy the last part (with zero) and return */
- l = len - (s - src);
- memcpy(d, s, l + 1);
-
- /* return the length of the resulting string */
- return (l + (d - dst));
-}
-
-char *ldb_dn_escape_value(void *mem_ctx, struct ldb_val value)
-{
- char *dst;
-
- if (!value.length)
- return NULL;
-
- /* allocate destination string, it will be at most 3 times the source */
- dst = talloc_array(mem_ctx, char, value.length * 3 + 1);
- if ( ! dst) {
- talloc_free(dst);
- return NULL;
- }
-
- ldb_dn_escape_internal(dst, (const char *)value.data, value.length);
-
- dst = talloc_realloc(mem_ctx, dst, char, strlen(dst) + 1);
-
- return dst;
-}
-
-/*
- explode a DN string into a ldb_dn structure
- based on RFC4514 except that we don't support multiple valued RDNs
-*/
-static bool ldb_dn_explode(struct ldb_dn *dn)
-{
- char *p, *ex_name, *ex_value, *data, *d, *dt, *t;
- bool trim = false;
- bool in_extended = false;
- bool in_ex_name = false;
- bool in_ex_value = false;
- bool in_attr = false;
- bool in_value = false;
- bool in_quote = false;
- bool is_oid = false;
- bool escape = false;
- unsigned x;
- int l, ret;
- char *parse_dn;
-
- if ( ! dn || dn->invalid) return false;
-
- if (dn->components) {
- return true;
- }
-
- if (dn->extended_linearized) {
- parse_dn = dn->extended_linearized;
- } else {
- parse_dn = dn->linearized;
- }
-
- if ( ! parse_dn ) {
- return false;
- }
-
- /* Empty DNs */
- if (parse_dn[0] == '\0') {
- return true;
- }
-
- /* Special DNs case */
- if (dn->special) {
- return true;
- }
-
- /* make sure we free this if alloced previously before replacing */
- talloc_free(dn->components);
-
- talloc_free(dn->extended_components);
- dn->extended_components = NULL;
-
- /* in the common case we have 3 or more components */
- /* make sure all components are zeroed, other functions depend on this */
- dn->components = talloc_zero_array(dn, struct ldb_dn_component, 3);
- if ( ! dn->components) {
- return false;
- }
- dn->comp_num = 0;
-
- /* Components data space is allocated here once */
- data = talloc_array(dn->components, char, strlen(parse_dn) + 1);
- if (!data) {
- return false;
- }
-
- p = parse_dn;
- in_extended = true;
- in_ex_name = false;
- in_ex_value = false;
- trim = true;
- t = NULL;
- d = dt = data;
-
- while (*p) {
- if (in_extended) {
-
- if (!in_ex_name && !in_ex_value) {
-
- if (p[0] == '<') {
- p++;
- ex_name = d;
- in_ex_name = true;
- continue;
- } else if (p[0] == '\0') {
- p++;
- continue;
- } else {
- in_extended = false;
- in_attr = true;
- dt = d;
-
- continue;
- }
- }
-
- if (in_ex_name && *p == '=') {
- *d++ = '\0';
- p++;
- ex_value = d;
- in_ex_name = false;
- in_ex_value = true;
- continue;
- }
-
- if (in_ex_value && *p == '>') {
- const struct ldb_dn_extended_syntax *extended_syntax;
- struct ldb_val ex_val = {
- .data = ex_value,
- .length = d - ex_value
- };
-
- *d++ = '\0';
- p++;
- in_ex_value = false;
-
- /* Process name and ex_value */
-
- dn->extended_components = talloc_realloc(dn,
- dn->extended_components,
- struct ldb_dn_extended_component,
- dn->extended_comp_num + 1);
- if ( ! dn->extended_components) {
- /* ouch ! */
- goto failed;
- }
-
- extended_syntax = ldb_dn_extended_syntax_by_name(dn->ldb, ex_name);
- if (!extended_syntax) {
- /* We don't know about this type of extended DN */
- goto failed;
- }
-
- dn->extended_components[dn->extended_comp_num].name = talloc_strdup(dn->extended_components, ex_name);
- if (!dn->extended_components[dn->extended_comp_num].name) {
- /* ouch */
- goto failed;
- }
- ret = extended_syntax->read_fn(dn->ldb, dn->extended_components,
- &ex_val, &dn->extended_components[dn->extended_comp_num].value);
- if (ret != LDB_SUCCESS) {
- dn->invalid = true;
- goto failed;
- }
-
- dn->extended_comp_num++;
-
- if (*p == '\0') {
- /* We have reached the end (extended component only)! */
- talloc_free(data);
- return true;
-
- } else if (*p == ';') {
- p++;
- continue;
- } else {
- dn->invalid = true;
- goto failed;
- }
- }
-
- *d++ = *p++;
- continue;
- }
- if (in_attr) {
- if (trim) {
- if (*p == ' ') {
- p++;
- continue;
- }
-
- /* first char */
- trim = false;
-
- if (!isascii(*p)) {
- /* attr names must be ascii only */
- dn->invalid = true;
- goto failed;
- }
-
- if (isdigit(*p)) {
- is_oid = true;
- } else
- if ( ! isalpha(*p)) {
- /* not a digit nor an alpha, invalid attribute name */
- dn->invalid = true;
- goto failed;
- }
-
- /* Copy this character across from parse_dn, now we have trimmed out spaces */
- *d++ = *p++;
- continue;
- }
-
- if (*p == ' ') {
- p++;
- /* valid only if we are at the end */
- trim = true;
- continue;
- }
-
- if (trim && (*p != '=')) {
- /* spaces/tabs are not allowed in attribute names */
- dn->invalid = true;
- goto failed;
- }
-
- if (*p == '=') {
- /* attribute terminated */
- in_attr = false;
- in_value = true;
- trim = true;
- l = 0;
-
- /* Terminate this string in d (which is a copy of parse_dn with spaces trimmed) */
- *d++ = '\0';
- dn->components[dn->comp_num].name = talloc_strdup(dn->components, dt);
- if ( ! dn->components[dn->comp_num].name) {
- /* ouch */
- goto failed;
- }
-
- dt = d;
-
- p++;
- continue;
- }
-
- if (!isascii(*p)) {
- /* attr names must be ascii only */
- dn->invalid = true;
- goto failed;
- }
-
- if (is_oid && ( ! (isdigit(*p) || (*p == '.')))) {
- /* not a digit nor a dot, invalid attribute oid */
- dn->invalid = true;
- goto failed;
- } else
- if ( ! (isalpha(*p) || isdigit(*p) || (*p == '-'))) {
- /* not ALPHA, DIGIT or HYPHEN */
- dn->invalid = true;
- goto failed;
- }
-
- *d++ = *p++;
- continue;
- }
-
- if (in_value) {
- if (in_quote) {
- if (*p == '\"') {
- if (p[-1] != '\\') {
- p++;
- in_quote = false;
- continue;
- }
- }
- *d++ = *p++;
- l++;
- continue;
- }
-
- if (trim) {
- if (*p == ' ') {
- p++;
- continue;
- }
-
- /* first char */
- trim = false;
-
- if (*p == '\"') {
- in_quote = true;
- p++;
- continue;
- }
- }
-
- switch (*p) {
-
- /* TODO: support ber encoded values
- case '#':
- */
-
- case ',':
- if (escape) {
- *d++ = *p++;
- l++;
- escape = false;
- continue;
- }
- /* ok found value terminator */
-
- if ( t ) {
- /* trim back */
- d -= (p - t);
- l -= (p - t);
- }
-
- in_attr = true;
- in_value = false;
- trim = true;
-
- p++;
- *d++ = '\0';
- dn->components[dn->comp_num].value.data = (uint8_t *)talloc_strdup(dn->components, dt);
- dn->components[dn->comp_num].value.length = l;
- if ( ! dn->components[dn->comp_num].value.data) {
- /* ouch ! */
- goto failed;
- }
-
- dt = d;
-
- dn->comp_num++;
- if (dn->comp_num > 2) {
- dn->components = talloc_realloc(dn,
- dn->components,
- struct ldb_dn_component,
- dn->comp_num + 1);
- if ( ! dn->components) {
- /* ouch ! */
- goto failed;
- }
- /* make sure all components are zeroed, other functions depend on this */
- memset(&dn->components[dn->comp_num], '\0', sizeof(struct ldb_dn_component));
- }
-
- continue;
-
- case '=':
- case '\n':
- case '+':
- case '<':
- case '>':
- case '#':
- case ';':
- case '\"':
- /* a string with not escaped specials is invalid (tested) */
- if ( ! escape) {
- dn->invalid = true;
- goto failed;
- }
- escape = false;
-
- *d++ = *p++;
- l++;
-
- if ( t ) t = NULL;
- break;
-
- case '\\':
- if ( ! escape) {
- escape = true;
- p++;
- continue;
- }
- escape = false;
-
- *d++ = *p++;
- l++;
-
- if ( t ) t = NULL;
- break;
-
- default:
- if (escape) {
- if (sscanf(p, "%02x", &x) != 1) {
- /* invalid escaping sequence */
- dn->invalid = true;
- goto failed;
- }
- escape = false;
-
- p += 2;
- *d++ = (unsigned char)x;
- l++;
-
- if ( t ) t = NULL;
- break;
- }
-
- if (*p == ' ') {
- if ( ! t) t = p;
- } else {
- if ( t ) t = NULL;
- }
-
- *d++ = *p++;
- l++;
-
- break;
- }
-
- }
- }
-
- if (in_attr || in_quote) {
- /* invalid dn */
- dn->invalid = true;
- goto failed;
- }
-
- /* save last element */
- if ( t ) {
- /* trim back */
- d -= (p - t);
- l -= (p - t);
- }
-
- *d++ = '\0';
- dn->components[dn->comp_num].value.data = (uint8_t *)talloc_strdup(dn->components, dt);
- dn->components[dn->comp_num].value.length = l;
-
- if ( ! dn->components[dn->comp_num].value.data) {
- /* ouch */
- goto failed;
- }
-
- dn->comp_num++;
-
- talloc_free(data);
- return true;
-
-failed:
- dn->comp_num = 0;
- talloc_free(dn->components);
- return false;
-}
-
-bool ldb_dn_validate(struct ldb_dn *dn)
-{
- return ldb_dn_explode(dn);
-}
-
-const char *ldb_dn_get_linearized(struct ldb_dn *dn)
-{
- int i, len;
- char *d, *n;
-
- if ( ! dn || ( dn->invalid)) return NULL;
-
- if (dn->linearized) return dn->linearized;
-
- if ( ! dn->components) {
- dn->invalid = true;
- return NULL;
- }
-
- if (dn->comp_num == 0) {
- dn->linearized = talloc_strdup(dn, "");
- if ( ! dn->linearized) return NULL;
- return dn->linearized;
- }
-
- /* calculate maximum possible length of DN */
- for (len = 0, i = 0; i < dn->comp_num; i++) {
- len += strlen(dn->components[i].name); /* name len */
- len += (dn->components[i].value.length * 3); /* max escaped data len */
- len += 2; /* '=' and ',' */
- }
- dn->linearized = talloc_array(dn, char, len);
- if ( ! dn->linearized) return NULL;
-
- d = dn->linearized;
-
- for (i = 0; i < dn->comp_num; i++) {
-
- /* copy the name */
- n = dn->components[i].name;
- while (*n) *d++ = *n++;
-
- *d++ = '=';
-
- /* and the value */
- d += ldb_dn_escape_internal( d,
- (char *)dn->components[i].value.data,
- dn->components[i].value.length);
- *d++ = ',';
- }
-
- *(--d) = '\0';
-
- /* don't waste more memory than necessary */
- dn->linearized = talloc_realloc(dn, dn->linearized, char, (d - dn->linearized + 1));
-
- return dn->linearized;
-}
-
-char *ldb_dn_get_extended_linearized(void *mem_ctx, struct ldb_dn *dn, int mode)
-{
- const char *linearized = ldb_dn_get_linearized(dn);
- char *p;
- int i;
-
- if (!linearized) {
- return NULL;
- }
-
- if (!ldb_dn_has_extended(dn)) {
- return talloc_strdup(mem_ctx, linearized);
- }
-
- if (!ldb_dn_validate(dn)) {
- return NULL;
- }
-
- for (i=0; i < dn->extended_comp_num; i++) {
- struct ldb_val val;
- int ret;
- const struct ldb_dn_extended_syntax *extended_syntax;
- const char *name = dn->extended_components[i].name;
-
- extended_syntax = ldb_dn_extended_syntax_by_name(dn->ldb, name);
-
- if (mode == 1) {
- ret = extended_syntax->write_clear_fn(dn->ldb, mem_ctx,
- &dn->extended_components[i].value,
- &val);
- } else if (mode == 0) {
- ret = extended_syntax->write_hex_fn(dn->ldb, mem_ctx,
- &dn->extended_components[i].value,
- &val);
- } else {
- ret = -1;
- }
-
- if (ret != LDB_SUCCESS) {
- return NULL;
- }
-
- if (i == 0) {
- p = talloc_asprintf(mem_ctx, "<%s=%s>", dn->extended_components[i].name, val.data);
- } else {
- p = talloc_asprintf_append(p, ";<%s=%s>", dn->extended_components[i].name, val.data);
- }
-
- talloc_free(val.data);
-
- if (!p) {
- return NULL;
- }
- }
-
- if (dn->extended_comp_num && *linearized) {
- p = talloc_asprintf_append(p, ";%s", linearized);
- }
-
- if (!p) {
- return NULL;
- }
-
- return p;
-}
-
-
-
-char *ldb_dn_alloc_linearized(void *mem_ctx, struct ldb_dn *dn)
-{
- return talloc_strdup(mem_ctx, ldb_dn_get_linearized(dn));
-}
-
-/*
- casefold a dn. We need to casefold the attribute names, and canonicalize
- attribute values of case insensitive attributes.
-*/
-
-static bool ldb_dn_casefold_internal(struct ldb_dn *dn)
-{
- int i, ret;
-
- if ( ! dn || dn->invalid) return false;
-
- if (dn->valid_case) return true;
-
- if (( ! dn->components) && ( ! ldb_dn_explode(dn))) {
- return false;
- }
-
- for (i = 0; i < dn->comp_num; i++) {
- const struct ldb_schema_attribute *a;
-
- dn->components[i].cf_name = ldb_attr_casefold(dn->components, dn->components[i].name);
- if (!dn->components[i].cf_name) {
- goto failed;
- }
-
- a = ldb_schema_attribute_by_name(dn->ldb, dn->components[i].cf_name);
- ret = a->syntax->canonicalise_fn(dn->ldb, dn->components,
- &(dn->components[i].value),
- &(dn->components[i].cf_value));
- if (ret != 0) {
- goto failed;
- }
- }
-
- dn->valid_case = true;
-
- return true;
-
-failed:
- for (i = 0; i < dn->comp_num; i++) {
- LDB_FREE(dn->components[i].cf_name);
- LDB_FREE(dn->components[i].cf_value.data);
- }
- return false;
-}
-
-const char *ldb_dn_get_casefold(struct ldb_dn *dn)
-{
- int i, len;
- char *d, *n;
-
- if (dn->casefold) return dn->casefold;
-
- if (dn->special) {
- dn->casefold = talloc_strdup(dn, dn->linearized);
- if (!dn->casefold) return NULL;
- dn->valid_case = true;
- return dn->casefold;
- }
-
- if ( ! ldb_dn_casefold_internal(dn)) {
- return NULL;
- }
-
- if (dn->comp_num == 0) {
- if (dn->linearized && dn->linearized[0] == '\0') {
- /* hmm a NULL dn, should we faild casefolding ? */
- dn->casefold = talloc_strdup(dn, "");
- return dn->casefold;
- }
- /* A DN must be NULL, special, or have components */
- dn->invalid = true;
- return NULL;
- }
-
- /* calculate maximum possible length of DN */
- for (len = 0, i = 0; i < dn->comp_num; i++) {
- len += strlen(dn->components[i].cf_name); /* name len */
- len += (dn->components[i].cf_value.length * 3); /* max escaped data len */
- len += 2; /* '=' and ',' */
- }
- dn->casefold = talloc_array(dn, char, len);
- if ( ! dn->casefold) return NULL;
-
- d = dn->casefold;
-
- for (i = 0; i < dn->comp_num; i++) {
-
- /* copy the name */
- n = dn->components[i].cf_name;
- while (*n) *d++ = *n++;
-
- *d++ = '=';
-
- /* and the value */
- d += ldb_dn_escape_internal( d,
- (char *)dn->components[i].cf_value.data,
- dn->components[i].cf_value.length);
- *d++ = ',';
- }
- *(--d) = '\0';
-
- /* don't waste more memory than necessary */
- dn->casefold = talloc_realloc(dn, dn->casefold, char, strlen(dn->casefold) + 1);
-
- return dn->casefold;
-}
-
-char *ldb_dn_alloc_casefold(void *mem_ctx, struct ldb_dn *dn)
-{
- return talloc_strdup(mem_ctx, ldb_dn_get_casefold(dn));
-}
-
-/* Determine if dn is below base, in the ldap tree. Used for
- * evaluating a subtree search.
- * 0 if they match, otherwise non-zero
- */
-
-int ldb_dn_compare_base(struct ldb_dn *base, struct ldb_dn *dn)
-{
- int ret;
- int n_base, n_dn;
-
- if ( ! base || base->invalid) return 1;
- if ( ! dn || dn->invalid) return -1;
-
- if (( ! base->valid_case) || ( ! dn->valid_case)) {
- if (base->linearized && dn->linearized) {
- /* try with a normal compare first, if we are lucky
- * we will avoid exploding and casfolding */
- int dif;
- dif = strlen(dn->linearized) - strlen(base->linearized);
- if (dif < 0) return dif;
- if (strcmp(base->linearized, &dn->linearized[dif]) == 0) return 0;
- }
-
- if ( ! ldb_dn_casefold_internal(base)) {
- return 1;
- }
-
- if ( ! ldb_dn_casefold_internal(dn)) {
- return -1;
- }
-
- }
-
- /* if base has more components,
- * they don't have the same base */
- if (base->comp_num > dn->comp_num) {
- return (dn->comp_num - base->comp_num);
- }
-
- if (dn->comp_num == 0) {
- if (dn->special && base->special) {
- return strcmp(base->linearized, dn->linearized);
- } else if (dn->special) {
- return -1;
- } else if (base->special) {
- return 1;
- } else {
- return 0;
- }
- }
-
- n_base = base->comp_num - 1;
- n_dn = dn->comp_num - 1;
-
- while (n_base >= 0) {
- /* compare attr names */
- ret = strcmp(base->components[n_base].cf_name, dn->components[n_dn].cf_name);
- if (ret != 0) return ret;
-
- /* compare attr.cf_value. */
- if (base->components[n_base].cf_value.length != dn->components[n_dn].cf_value.length) {
- return base->components[n_base].cf_value.length - dn->components[n_dn].cf_value.length;
- }
- ret = strcmp((char *)base->components[n_base].cf_value.data, (char *)dn->components[n_dn].cf_value.data);
- if (ret != 0) return ret;
-
- n_base--;
- n_dn--;
- }
-
- return 0;
-}
-
-/* compare DNs using casefolding compare functions.
-
- If they match, then return 0
- */
-
-int ldb_dn_compare(struct ldb_dn *dn0, struct ldb_dn *dn1)
-{
- int i, ret;
-
- if (( ! dn0) || dn0->invalid || ! dn1 || dn1->invalid) return -1;
-
- if (( ! dn0->valid_case) || ( ! dn1->valid_case)) {
- if (dn0->linearized && dn1->linearized) {
- /* try with a normal compare first, if we are lucky
- * we will avoid exploding and casfolding */
- if (strcmp(dn0->linearized, dn1->linearized) == 0) return 0;
- }
-
- if ( ! ldb_dn_casefold_internal(dn0)) {
- return 1;
- }
-
- if ( ! ldb_dn_casefold_internal(dn1)) {
- return -1;
- }
-
- }
-
- if (dn0->comp_num != dn1->comp_num) {
- return (dn1->comp_num - dn0->comp_num);
- }
-
- if (dn0->comp_num == 0) {
- if (dn0->special && dn1->special) {
- return strcmp(dn0->linearized, dn1->linearized);
- } else if (dn0->special) {
- return 1;
- } else if (dn1->special) {
- return -1;
- } else {
- return 0;
- }
- }
-
- for (i = 0; i < dn0->comp_num; i++) {
- /* compare attr names */
- ret = strcmp(dn0->components[i].cf_name, dn1->components[i].cf_name);
- if (ret != 0) return ret;
-
- /* compare attr.cf_value. */
- if (dn0->components[i].cf_value.length != dn1->components[i].cf_value.length) {
- return dn0->components[i].cf_value.length - dn1->components[i].cf_value.length;
- }
- ret = strcmp((char *)dn0->components[i].cf_value.data, (char *)dn1->components[i].cf_value.data);
- if (ret != 0) return ret;
- }
-
- return 0;
-}
-
-static struct ldb_dn_component ldb_dn_copy_component(void *mem_ctx, struct ldb_dn_component *src)
-{
- struct ldb_dn_component dst;
-
- memset(&dst, 0, sizeof(dst));
-
- if (src == NULL) {
- return dst;
- }
-
- dst.value = ldb_val_dup(mem_ctx, &(src->value));
- if (dst.value.data == NULL) {
- return dst;
- }
-
- dst.name = talloc_strdup(mem_ctx, src->name);
- if (dst.name == NULL) {
- LDB_FREE(dst.value.data);
- return dst;
- }
-
- if (src->cf_value.data) {
- dst.cf_value = ldb_val_dup(mem_ctx, &(src->cf_value));
- if (dst.cf_value.data == NULL) {
- LDB_FREE(dst.value.data);
- LDB_FREE(dst.name);
- return dst;
- }
-
- dst.cf_name = talloc_strdup(mem_ctx, src->cf_name);
- if (dst.cf_name == NULL) {
- LDB_FREE(dst.cf_name);
- LDB_FREE(dst.value.data);
- LDB_FREE(dst.name);
- return dst;
- }
- } else {
- dst.cf_value.data = NULL;
- dst.cf_name = NULL;
- }
-
- return dst;
-}
-
-static struct ldb_dn_extended_component ldb_dn_extended_copy_component(void *mem_ctx, struct ldb_dn_extended_component *src)
-{
- struct ldb_dn_extended_component dst;
-
- memset(&dst, 0, sizeof(dst));
-
- if (src == NULL) {
- return dst;
- }
-
- dst.value = ldb_val_dup(mem_ctx, &(src->value));
- if (dst.value.data == NULL) {
- return dst;
- }
-
- dst.name = talloc_strdup(mem_ctx, src->name);
- if (dst.name == NULL) {
- LDB_FREE(dst.value.data);
- return dst;
- }
-
- return dst;
-}
-
-struct ldb_dn *ldb_dn_copy(void *mem_ctx, struct ldb_dn *dn)
-{
- struct ldb_dn *new_dn;
-
- if (!dn || dn->invalid) {
- return NULL;
- }
-
- new_dn = talloc_zero(mem_ctx, struct ldb_dn);
- if ( !new_dn) {
- return NULL;
- }
-
- *new_dn = *dn;
-
- if (dn->components) {
- int i;
-
- new_dn->components = talloc_zero_array(new_dn, struct ldb_dn_component, dn->comp_num);
- if ( ! new_dn->components) {
- talloc_free(new_dn);
- return NULL;
- }
-
- for (i = 0; i < dn->comp_num; i++) {
- new_dn->components[i] = ldb_dn_copy_component(new_dn->components, &dn->components[i]);
- if ( ! new_dn->components[i].value.data) {
- talloc_free(new_dn);
- return NULL;
- }
- }
- }
-
- if (dn->extended_components) {
- int i;
-
- new_dn->extended_components = talloc_zero_array(new_dn, struct ldb_dn_extended_component, dn->extended_comp_num);
- if ( ! new_dn->extended_components) {
- talloc_free(new_dn);
- return NULL;
- }
-
- for (i = 0; i < dn->extended_comp_num; i++) {
- new_dn->extended_components[i] = ldb_dn_extended_copy_component(new_dn->extended_components, &dn->extended_components[i]);
- if ( ! new_dn->extended_components[i].value.data) {
- talloc_free(new_dn);
- return NULL;
- }
- }
- }
-
- if (dn->casefold) {
- new_dn->casefold = talloc_strdup(new_dn, dn->casefold);
- if ( ! new_dn->casefold) {
- talloc_free(new_dn);
- return NULL;
- }
- }
-
- if (dn->linearized) {
- new_dn->linearized = talloc_strdup(new_dn, dn->linearized);
- if ( ! new_dn->linearized) {
- talloc_free(new_dn);
- return NULL;
- }
- }
-
- if (dn->extended_linearized) {
- new_dn->extended_linearized = talloc_strdup(new_dn, dn->extended_linearized);
- if ( ! new_dn->extended_linearized) {
- talloc_free(new_dn);
- return NULL;
- }
- }
-
- return new_dn;
-}
-
-/* modify the given dn by adding a base.
- *
- * return true if successful and false if not
- * if false is returned the dn may be marked invalid
- */
-bool ldb_dn_add_base(struct ldb_dn *dn, struct ldb_dn *base)
-{
- const char *s;
- char *t;
-
- if ( !base || base->invalid || !dn || dn->invalid) {
- return false;
- }
-
- if (dn->components) {
- int i;
-
- if ( ! ldb_dn_validate(base)) {
- return false;
- }
-
- s = NULL;
- if (dn->valid_case) {
- if ( ! (s = ldb_dn_get_casefold(base))) {
- return false;
- }
- }
-
- dn->components = talloc_realloc(dn,
- dn->components,
- struct ldb_dn_component,
- dn->comp_num + base->comp_num);
- if ( ! dn->components) {
- dn->invalid = true;
- return false;
- }
-
- for (i = 0; i < base->comp_num; dn->comp_num++, i++) {
- dn->components[dn->comp_num] = ldb_dn_copy_component(dn->components, &base->components[i]);
- if (dn->components[dn->comp_num].value.data == NULL) {
- dn->invalid = true;
- return false;
- }
- }
-
- if (dn->casefold && s) {
- if (*dn->casefold) {
- t = talloc_asprintf(dn, "%s,%s", dn->casefold, s);
- } else {
- t = talloc_strdup(dn, s);
- }
- LDB_FREE(dn->casefold);
- dn->casefold = t;
- }
- }
-
- if (dn->linearized) {
-
- s = ldb_dn_get_linearized(base);
- if ( ! s) {
- return false;
- }
-
- if (*dn->linearized) {
- t = talloc_asprintf(dn, "%s,%s", dn->linearized, s);
- } else {
- t = talloc_strdup(dn, s);
- }
- if ( ! t) {
- dn->invalid = true;
- return false;
- }
- LDB_FREE(dn->linearized);
- dn->linearized = t;
- }
-
- /* Wipe the extended_linearized DN, as the GUID and SID are almost certainly no longer valid */
- if (dn->extended_linearized) {
- LDB_FREE(dn->extended_linearized);
- }
-
- LDB_FREE(dn->extended_components);
- dn->extended_comp_num = 0;
- return true;
-}
-
-/* modify the given dn by adding a base.
- *
- * return true if successful and false if not
- * if false is returned the dn may be marked invalid
- */
-bool ldb_dn_add_base_fmt(struct ldb_dn *dn, const char *base_fmt, ...)
-{
- struct ldb_dn *base;
- char *base_str;
- va_list ap;
- bool ret;
-
- if ( !dn || dn->invalid) {
- return false;
- }
-
- va_start(ap, base_fmt);
- base_str = talloc_vasprintf(dn, base_fmt, ap);
- va_end(ap);
-
- if (base_str == NULL) {
- return false;
- }
-
- base = ldb_dn_new(base_str, dn->ldb, base_str);
-
- ret = ldb_dn_add_base(dn, base);
-
- talloc_free(base_str);
-
- return ret;
-}
-
-/* modify the given dn by adding children elements.
- *
- * return true if successful and false if not
- * if false is returned the dn may be marked invalid
- */
-bool ldb_dn_add_child(struct ldb_dn *dn, struct ldb_dn *child)
-{
- const char *s;
- char *t;
-
- if ( !child || child->invalid || !dn || dn->invalid) {
- return false;
- }
-
- if (dn->components) {
- int n, i, j;
-
- if ( ! ldb_dn_validate(child)) {
- return false;
- }
-
- s = NULL;
- if (dn->valid_case) {
- if ( ! (s = ldb_dn_get_casefold(child))) {
- return false;
- }
- }
-
- n = dn->comp_num + child->comp_num;
-
- dn->components = talloc_realloc(dn,
- dn->components,
- struct ldb_dn_component,
- n);
- if ( ! dn->components) {
- dn->invalid = true;
- return false;
- }
-
- for (i = dn->comp_num - 1, j = n - 1; i >= 0; i--, j--) {
- dn->components[j] = dn->components[i];
- }
-
- for (i = 0; i < child->comp_num; i++) {
- dn->components[i] = ldb_dn_copy_component(dn->components, &child->components[i]);
- if (dn->components[i].value.data == NULL) {
- dn->invalid = true;
- return false;
- }
- }
-
- dn->comp_num = n;
-
- if (dn->casefold && s) {
- t = talloc_asprintf(dn, "%s,%s", s, dn->casefold);
- LDB_FREE(dn->casefold);
- dn->casefold = t;
- }
- }
-
- if (dn->linearized) {
-
- s = ldb_dn_get_linearized(child);
- if ( ! s) {
- return false;
- }
-
- t = talloc_asprintf(dn, "%s,%s", s, dn->linearized);
- if ( ! t) {
- dn->invalid = true;
- return false;
- }
- LDB_FREE(dn->linearized);
- dn->linearized = t;
- }
-
- /* Wipe the extended_linearized DN, as the GUID and SID are almost certainly no longer valid */
- LDB_FREE(dn->extended_linearized);
-
- LDB_FREE(dn->extended_components);
- dn->extended_comp_num = 0;
-
- return true;
-}
-
-/* modify the given dn by adding children elements.
- *
- * return true if successful and false if not
- * if false is returned the dn may be marked invalid
- */
-bool ldb_dn_add_child_fmt(struct ldb_dn *dn, const char *child_fmt, ...)
-{
- struct ldb_dn *child;
- char *child_str;
- va_list ap;
- bool ret;
-
- if ( !dn || dn->invalid) {
- return false;
- }
-
- va_start(ap, child_fmt);
- child_str = talloc_vasprintf(dn, child_fmt, ap);
- va_end(ap);
-
- if (child_str == NULL) {
- return false;
- }
-
- child = ldb_dn_new(child_str, dn->ldb, child_str);
-
- ret = ldb_dn_add_child(dn, child);
-
- talloc_free(child_str);
-
- return ret;
-}
-
-bool ldb_dn_remove_base_components(struct ldb_dn *dn, unsigned int num)
-{
- int i;
-
- if ( ! ldb_dn_validate(dn)) {
- return false;
- }
-
- if (dn->comp_num < num) {
- return false;
- }
-
- /* free components */
- for (i = num; i > 0; i--) {
- LDB_FREE(dn->components[dn->comp_num - i].name);
- LDB_FREE(dn->components[dn->comp_num - i].value.data);
- LDB_FREE(dn->components[dn->comp_num - i].cf_name);
- LDB_FREE(dn->components[dn->comp_num - i].cf_value.data);
- }
-
- dn->comp_num -= num;
-
- if (dn->valid_case) {
- for (i = 0; i < dn->comp_num; i++) {
- LDB_FREE(dn->components[i].cf_name);
- LDB_FREE(dn->components[i].cf_value.data);
- }
- dn->valid_case = false;
- }
-
- LDB_FREE(dn->casefold);
- LDB_FREE(dn->linearized);
-
- /* Wipe the extended_linearized DN, as the GUID and SID are almost certainly no longer valid */
- LDB_FREE(dn->extended_linearized);
-
- LDB_FREE(dn->extended_components);
- dn->extended_comp_num = 0;
-
- return true;
-}
-
-bool ldb_dn_remove_child_components(struct ldb_dn *dn, unsigned int num)
-{
- int i, j;
-
- if ( ! ldb_dn_validate(dn)) {
- return false;
- }
-
- if (dn->comp_num < num) {
- return false;
- }
-
- for (i = 0, j = num; j < dn->comp_num; i++, j++) {
- if (i < num) {
- LDB_FREE(dn->components[i].name);
- LDB_FREE(dn->components[i].value.data);
- LDB_FREE(dn->components[i].cf_name);
- LDB_FREE(dn->components[i].cf_value.data);
- }
- dn->components[i] = dn->components[j];
- }
-
- dn->comp_num -= num;
-
- if (dn->valid_case) {
- for (i = 0; i < dn->comp_num; i++) {
- LDB_FREE(dn->components[i].cf_name);
- LDB_FREE(dn->components[i].cf_value.data);
- }
- dn->valid_case = false;
- }
-
- LDB_FREE(dn->casefold);
- LDB_FREE(dn->linearized);
-
- /* Wipe the extended_linearized DN, as the GUID and SID are almost certainly no longer valid */
- LDB_FREE(dn->extended_linearized);
-
- LDB_FREE(dn->extended_components);
- dn->extended_comp_num = 0;
- return true;
-}
-
-struct ldb_dn *ldb_dn_get_parent(void *mem_ctx, struct ldb_dn *dn)
-{
- struct ldb_dn *new_dn;
-
- new_dn = ldb_dn_copy(mem_ctx, dn);
- if ( !new_dn ) {
- return NULL;
- }
-
- if ( ! ldb_dn_remove_child_components(new_dn, 1)) {
- talloc_free(new_dn);
- return NULL;
- }
-
- /* Wipe the extended_linearized DN, as the GUID and SID are almost certainly no longer valid */
- LDB_FREE(dn->extended_linearized);
-
- LDB_FREE(dn->extended_components);
- dn->extended_comp_num = 0;
- return new_dn;
-}
-
-/* Create a 'canonical name' string from a DN:
-
- ie dc=samba,dc=org -> samba.org/
- uid=administrator,ou=users,dc=samba,dc=org = samba.org/users/administrator
-
- There are two formats, the EX format has the last / replaced with a newline (\n).
-
-*/
-static char *ldb_dn_canonical(void *mem_ctx, struct ldb_dn *dn, int ex_format) {
- int i;
- TALLOC_CTX *tmpctx;
- char *cracked = NULL;
- const char *format = (ex_format ? "\n" : "/" );
-
- if ( ! ldb_dn_validate(dn)) {
- return NULL;
- }
-
- tmpctx = talloc_new(mem_ctx);
-
- /* Walk backwards down the DN, grabbing 'dc' components at first */
- for (i = dn->comp_num - 1 ; i >= 0; i--) {
- if (ldb_attr_cmp(dn->components[i].name, "dc") != 0) {
- break;
- }
- if (cracked) {
- cracked = talloc_asprintf(tmpctx, "%s.%s",
- ldb_dn_escape_value(tmpctx, dn->components[i].value),
- cracked);
- } else {
- cracked = ldb_dn_escape_value(tmpctx, dn->components[i].value);
- }
- if (!cracked) {
- goto done;
- }
- }
-
- /* Only domain components? Finish here */
- if (i < 0) {
- cracked = talloc_strdup_append_buffer(cracked, format);
- talloc_steal(mem_ctx, cracked);
- goto done;
- }
-
- /* Now walk backwards appending remaining components */
- for (; i > 0; i--) {
- cracked = talloc_asprintf_append_buffer(cracked, "/%s",
- ldb_dn_escape_value(tmpctx, dn->components[i].value));
- if (!cracked) {
- goto done;
- }
- }
-
- /* Last one, possibly a newline for the 'ex' format */
- cracked = talloc_asprintf_append_buffer(cracked, "%s%s", format,
- ldb_dn_escape_value(tmpctx, dn->components[i].value));
-
- talloc_steal(mem_ctx, cracked);
-done:
- talloc_free(tmpctx);
- return cracked;
-}
-
-/* Wrapper functions for the above, for the two different string formats */
-char *ldb_dn_canonical_string(void *mem_ctx, struct ldb_dn *dn) {
- return ldb_dn_canonical(mem_ctx, dn, 0);
-
-}
-
-char *ldb_dn_canonical_ex_string(void *mem_ctx, struct ldb_dn *dn) {
- return ldb_dn_canonical(mem_ctx, dn, 1);
-}
-
-int ldb_dn_get_comp_num(struct ldb_dn *dn)
-{
- if ( ! ldb_dn_validate(dn)) {
- return -1;
- }
- return dn->comp_num;
-}
-
-const char *ldb_dn_get_component_name(struct ldb_dn *dn, unsigned int num)
-{
- if ( ! ldb_dn_validate(dn)) {
- return NULL;
- }
- if (num >= dn->comp_num) return NULL;
- return dn->components[num].name;
-}
-
-const struct ldb_val *ldb_dn_get_component_val(struct ldb_dn *dn, unsigned int num)
-{
- if ( ! ldb_dn_validate(dn)) {
- return NULL;
- }
- if (num >= dn->comp_num) return NULL;
- return &dn->components[num].value;
-}
-
-const char *ldb_dn_get_rdn_name(struct ldb_dn *dn)
-{
- if ( ! ldb_dn_validate(dn)) {
- return NULL;
- }
- if (dn->comp_num == 0) return NULL;
- return dn->components[0].name;
-}
-
-const struct ldb_val *ldb_dn_get_rdn_val(struct ldb_dn *dn)
-{
- if ( ! ldb_dn_validate(dn)) {
- return NULL;
- }
- if (dn->comp_num == 0) return NULL;
- return &dn->components[0].value;
-}
-
-int ldb_dn_set_component(struct ldb_dn *dn, int num, const char *name, const struct ldb_val val)
-{
- char *n;
- struct ldb_val v;
-
- if ( ! ldb_dn_validate(dn)) {
- return LDB_ERR_OTHER;
- }
-
- if (num >= dn->comp_num) {
- return LDB_ERR_OTHER;
- }
-
- n = talloc_strdup(dn, name);
- if ( ! n) {
- return LDB_ERR_OTHER;
- }
-
- v.length = val.length;
- v.data = (uint8_t *)talloc_memdup(dn, val.data, v.length+1);
- if ( ! v.data) {
- talloc_free(n);
- return LDB_ERR_OTHER;
- }
-
- talloc_free(dn->components[num].name);
- talloc_free(dn->components[num].value.data);
- dn->components[num].name = n;
- dn->components[num].value = v;
-
- if (dn->valid_case) {
- int i;
- for (i = 0; i < dn->comp_num; i++) {
- LDB_FREE(dn->components[i].cf_name);
- LDB_FREE(dn->components[i].cf_value.data);
- }
- dn->valid_case = false;
- }
- LDB_FREE(dn->casefold);
- LDB_FREE(dn->linearized);
-
- /* Wipe the extended_linearized DN, as the GUID and SID are almost certainly no longer valid */
- LDB_FREE(dn->extended_linearized);
-
- dn->extended_comp_num = 0;
- LDB_FREE(dn->extended_components);
- return LDB_SUCCESS;
-}
-
-const struct ldb_val *ldb_dn_get_extended_component(struct ldb_dn *dn, const char *name)
-{
- int i;
- if ( ! ldb_dn_validate(dn)) {
- return NULL;
- }
- for (i=0; i < dn->extended_comp_num; i++) {
- if (ldb_attr_cmp(dn->extended_components[i].name, name) == 0) {
- return &dn->extended_components[i].value;
- }
- }
- return NULL;
-}
-
-int ldb_dn_set_extended_component(struct ldb_dn *dn, const char *name, const struct ldb_val *val)
-{
- struct ldb_dn_extended_component *p;
- int i;
-
- if ( ! ldb_dn_validate(dn)) {
- return LDB_ERR_OTHER;
- }
-
- for (i=0; i < dn->extended_comp_num; i++) {
- if (ldb_attr_cmp(dn->extended_components[i].name, name) == 0) {
- if (val) {
- dn->extended_components[i].value = ldb_val_dup(dn->extended_components, val);
-
- dn->extended_components[i].name = talloc_strdup(dn->extended_components, name);
- if (!dn->extended_components[i].name || !dn->extended_components[i].value.data) {
- dn->invalid = true;
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- } else {
- if (i != (dn->extended_comp_num - 1)) {
- memmove(&dn->extended_components[i], &dn->extended_components[i+1],
- ((dn->extended_comp_num-1) - i)*sizeof(*dn->extended_components));
- }
- dn->extended_comp_num--;
-
- dn->extended_components = talloc_realloc(dn,
- dn->extended_components,
- struct ldb_dn_extended_component,
- dn->extended_comp_num);
- if (!dn->extended_components) {
- dn->invalid = true;
- return LDB_ERR_OPERATIONS_ERROR;
- }
- return LDB_SUCCESS;
- }
- }
- }
-
- p = dn->extended_components
- = talloc_realloc(dn,
- dn->extended_components,
- struct ldb_dn_extended_component,
- dn->extended_comp_num + 1);
- if (!dn->extended_components) {
- dn->invalid = true;
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- p[dn->extended_comp_num].value = ldb_val_dup(dn->extended_components, val);
- p[dn->extended_comp_num].name = talloc_strdup(p, name);
-
- if (!dn->extended_components[i].name || !dn->extended_components[i].value.data) {
- dn->invalid = true;
- return LDB_ERR_OPERATIONS_ERROR;
- }
- dn->extended_components = p;
- dn->extended_comp_num++;
-
- return LDB_SUCCESS;
-}
-
-void ldb_dn_remove_extended_components(struct ldb_dn *dn)
-{
- dn->extended_comp_num = 0;
- LDB_FREE(dn->extended_components);
-}
-
-bool ldb_dn_is_valid(struct ldb_dn *dn)
-{
- if ( ! dn) return false;
- return ! dn->invalid;
-}
-
-bool ldb_dn_is_special(struct ldb_dn *dn)
-{
- if ( ! dn || dn->invalid) return false;
- return dn->special;
-}
-
-bool ldb_dn_has_extended(struct ldb_dn *dn)
-{
- if ( ! dn || dn->invalid) return false;
- if (dn->extended_linearized && (dn->extended_linearized[0] == '<')) return true;
- return dn->extended_comp_num != 0;
-}
-
-bool ldb_dn_check_special(struct ldb_dn *dn, const char *check)
-{
- if ( ! dn || dn->invalid) return false;
- return ! strcmp(dn->linearized, check);
-}
-
-bool ldb_dn_is_null(struct ldb_dn *dn)
-{
- if ( ! dn || dn->invalid) return false;
- if (ldb_dn_has_extended(dn)) return false;
- if (dn->linearized && (dn->linearized[0] == '\0')) return true;
- return false;
-}
diff --git a/ldb/common/ldb_ldif.c b/ldb/common/ldb_ldif.c
deleted file mode 100644
index 619c10e1..00000000
--- a/ldb/common/ldb_ldif.c
+++ /dev/null
@@ -1,761 +0,0 @@
-/*
- ldb database library
-
- Copyright (C) Andrew Tridgell 2004
-
- ** NOTE! The following LGPL license applies to the ldb
- ** library. This does NOT imply that all of Samba is released
- ** under the LGPL
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-/*
- * Name: ldb
- *
- * Component: ldif routines
- *
- * Description: ldif pack/unpack routines
- *
- * Author: Andrew Tridgell
- */
-
-/*
- see RFC2849 for the LDIF format definition
-*/
-
-#include "ldb_includes.h"
-#include "system/locale.h"
-
-/*
-
-*/
-static int ldb_read_data_file(void *mem_ctx, struct ldb_val *value)
-{
- struct stat statbuf;
- char *buf;
- int count, size, bytes;
- int ret;
- int f;
- const char *fname = (const char *)value->data;
-
- if (strncmp(fname, "file://", 7) != 0) {
- return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
- }
- fname += 7;
-
- f = open(fname, O_RDONLY);
- if (f == -1) {
- return -1;
- }
-
- if (fstat(f, &statbuf) != 0) {
- ret = -1;
- goto done;
- }
-
- if (statbuf.st_size == 0) {
- ret = -1;
- goto done;
- }
-
- value->data = (uint8_t *)talloc_size(mem_ctx, statbuf.st_size + 1);
- if (value->data == NULL) {
- ret = -1;
- goto done;
- }
- value->data[statbuf.st_size] = 0;
-
- count = 0;
- size = statbuf.st_size;
- buf = (char *)value->data;
- while (count < statbuf.st_size) {
- bytes = read(f, buf, size);
- if (bytes == -1) {
- talloc_free(value->data);
- ret = -1;
- goto done;
- }
- count += bytes;
- buf += bytes;
- size -= bytes;
- }
-
- value->length = statbuf.st_size;
- ret = statbuf.st_size;
-
-done:
- close(f);
- return ret;
-}
-
-/*
- this base64 decoder was taken from jitterbug (written by tridge).
- we might need to replace it with a new version
-*/
-int ldb_base64_decode(char *s)
-{
- const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
- int bit_offset=0, byte_offset, idx, i, n;
- uint8_t *d = (uint8_t *)s;
- char *p=NULL;
-
- n=i=0;
-
- while (*s && (p=strchr(b64,*s))) {
- idx = (int)(p - b64);
- byte_offset = (i*6)/8;
- bit_offset = (i*6)%8;
- d[byte_offset] &= ~((1<<(8-bit_offset))-1);
- if (bit_offset < 3) {
- d[byte_offset] |= (idx << (2-bit_offset));
- n = byte_offset+1;
- } else {
- d[byte_offset] |= (idx >> (bit_offset-2));
- d[byte_offset+1] = 0;
- d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF;
- n = byte_offset+2;
- }
- s++; i++;
- }
- if (bit_offset >= 3) {
- n--;
- }
-
- if (*s && !p) {
- /* the only termination allowed */
- if (*s != '=') {
- return -1;
- }
- }
-
- /* null terminate */
- d[n] = 0;
- return n;
-}
-
-
-/*
- encode as base64
- caller frees
-*/
-char *ldb_base64_encode(void *mem_ctx, const char *buf, int len)
-{
- const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
- int bit_offset, byte_offset, idx, i;
- const uint8_t *d = (const uint8_t *)buf;
- int bytes = (len*8 + 5)/6, pad_bytes = (bytes % 4) ? 4 - (bytes % 4) : 0;
- char *out;
-
- out = talloc_array(mem_ctx, char, bytes+pad_bytes+1);
- if (!out) return NULL;
-
- for (i=0;i<bytes;i++) {
- byte_offset = (i*6)/8;
- bit_offset = (i*6)%8;
- if (bit_offset < 3) {
- idx = (d[byte_offset] >> (2-bit_offset)) & 0x3F;
- } else {
- idx = (d[byte_offset] << (bit_offset-2)) & 0x3F;
- if (byte_offset+1 < len) {
- idx |= (d[byte_offset+1] >> (8-(bit_offset-2)));
- }
- }
- out[i] = b64[idx];
- }
-
- for (;i<bytes+pad_bytes;i++)
- out[i] = '=';
- out[i] = 0;
-
- return out;
-}
-
-/*
- see if a buffer should be base64 encoded
-*/
-int ldb_should_b64_encode(const struct ldb_val *val)
-{
- unsigned int i;
- uint8_t *p = val->data;
-
- if (val->length == 0) {
- return 0;
- }
-
- if (p[0] == ' ' || p[0] == ':') {
- return 1;
- }
-
- for (i=0; i<val->length; i++) {
- if (!isprint(p[i]) || p[i] == '\n') {
- return 1;
- }
- }
- return 0;
-}
-
-/* this macro is used to handle the return checking on fprintf_fn() */
-#define CHECK_RET do { if (ret < 0) return ret; total += ret; } while (0)
-
-/*
- write a line folded string onto a file
-*/
-static int fold_string(int (*fprintf_fn)(void *, const char *, ...), void *private_data,
- const char *buf, size_t length, int start_pos)
-{
- unsigned int i;
- int total=0, ret;
-
- for (i=0;i<length;i++) {
- ret = fprintf_fn(private_data, "%c", buf[i]);
- CHECK_RET;
- if (i != (length-1) && (i + start_pos) % 77 == 0) {
- ret = fprintf_fn(private_data, "\n ");
- CHECK_RET;
- }
- }
-
- return total;
-}
-
-#undef CHECK_RET
-
-/*
- encode as base64 to a file
-*/
-static int base64_encode_f(struct ldb_context *ldb,
- int (*fprintf_fn)(void *, const char *, ...),
- void *private_data,
- const char *buf, int len, int start_pos)
-{
- char *b = ldb_base64_encode(ldb, buf, len);
- int ret;
-
- if (!b) {
- return -1;
- }
-
- ret = fold_string(fprintf_fn, private_data, b, strlen(b), start_pos);
-
- talloc_free(b);
- return ret;
-}
-
-
-static const struct {
- const char *name;
- enum ldb_changetype changetype;
-} ldb_changetypes[] = {
- {"add", LDB_CHANGETYPE_ADD},
- {"delete", LDB_CHANGETYPE_DELETE},
- {"modify", LDB_CHANGETYPE_MODIFY},
- {NULL, 0}
-};
-
-/* this macro is used to handle the return checking on fprintf_fn() */
-#define CHECK_RET do { if (ret < 0) { talloc_free(mem_ctx); return ret; } total += ret; } while (0)
-
-/*
- write to ldif, using a caller supplied write method
-*/
-int ldb_ldif_write(struct ldb_context *ldb,
- int (*fprintf_fn)(void *, const char *, ...),
- void *private_data,
- const struct ldb_ldif *ldif)
-{
- TALLOC_CTX *mem_ctx;
- unsigned int i, j;
- int total=0, ret;
- char *p;
- const struct ldb_message *msg;
-
- mem_ctx = talloc_named_const(NULL, 0, "ldb_ldif_write");
-
- msg = ldif->msg;
- p = ldb_dn_get_extended_linearized(mem_ctx, msg->dn, 1);
- ret = fprintf_fn(private_data, "dn: %s\n", p);
- talloc_free(p);
- CHECK_RET;
-
- if (ldif->changetype != LDB_CHANGETYPE_NONE) {
- for (i=0;ldb_changetypes[i].name;i++) {
- if (ldb_changetypes[i].changetype == ldif->changetype) {
- break;
- }
- }
- if (!ldb_changetypes[i].name) {
- ldb_debug(ldb, LDB_DEBUG_ERROR, "Error: Invalid ldif changetype %d\n",
- ldif->changetype);
- talloc_free(mem_ctx);
- return -1;
- }
- ret = fprintf_fn(private_data, "changetype: %s\n", ldb_changetypes[i].name);
- CHECK_RET;
- }
-
- for (i=0;i<msg->num_elements;i++) {
- const struct ldb_schema_attribute *a;
-
- a = ldb_schema_attribute_by_name(ldb, msg->elements[i].name);
-
- if (ldif->changetype == LDB_CHANGETYPE_MODIFY) {
- switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) {
- case LDB_FLAG_MOD_ADD:
- fprintf_fn(private_data, "add: %s\n",
- msg->elements[i].name);
- break;
- case LDB_FLAG_MOD_DELETE:
- fprintf_fn(private_data, "delete: %s\n",
- msg->elements[i].name);
- break;
- case LDB_FLAG_MOD_REPLACE:
- fprintf_fn(private_data, "replace: %s\n",
- msg->elements[i].name);
- break;
- }
- }
-
- for (j=0;j<msg->elements[i].num_values;j++) {
- struct ldb_val v;
- ret = a->syntax->ldif_write_fn(ldb, mem_ctx, &msg->elements[i].values[j], &v);
- if (ret != LDB_SUCCESS) {
- v = msg->elements[i].values[j];
- }
- if (ret != LDB_SUCCESS || ldb_should_b64_encode(&v)) {
- ret = fprintf_fn(private_data, "%s:: ",
- msg->elements[i].name);
- CHECK_RET;
- ret = base64_encode_f(ldb, fprintf_fn, private_data,
- (char *)v.data, v.length,
- strlen(msg->elements[i].name)+3);
- CHECK_RET;
- ret = fprintf_fn(private_data, "\n");
- CHECK_RET;
- } else {
- ret = fprintf_fn(private_data, "%s: ", msg->elements[i].name);
- CHECK_RET;
- ret = fold_string(fprintf_fn, private_data,
- (char *)v.data, v.length,
- strlen(msg->elements[i].name)+2);
- CHECK_RET;
- ret = fprintf_fn(private_data, "\n");
- CHECK_RET;
- }
- if (v.data != msg->elements[i].values[j].data) {
- talloc_free(v.data);
- }
- }
- if (ldif->changetype == LDB_CHANGETYPE_MODIFY) {
- fprintf_fn(private_data, "-\n");
- }
- }
- ret = fprintf_fn(private_data,"\n");
- CHECK_RET;
-
- return total;
-}
-
-#undef CHECK_RET
-
-
-/*
- pull a ldif chunk, which is defined as a piece of data ending in \n\n or EOF
- this routine removes any RFC2849 continuations and comments
-
- caller frees
-*/
-static char *next_chunk(struct ldb_context *ldb,
- int (*fgetc_fn)(void *), void *private_data)
-{
- size_t alloc_size=0, chunk_size = 0;
- char *chunk = NULL;
- int c;
- int in_comment = 0;
-
- while ((c = fgetc_fn(private_data)) != EOF) {
- if (chunk_size+1 >= alloc_size) {
- char *c2;
- alloc_size += 1024;
- c2 = talloc_realloc(ldb, chunk, char, alloc_size);
- if (!c2) {
- talloc_free(chunk);
- errno = ENOMEM;
- return NULL;
- }
- chunk = c2;
- }
-
- if (in_comment) {
- if (c == '\n') {
- in_comment = 0;
- }
- continue;
- }
-
- /* handle continuation lines - see RFC2849 */
- if (c == ' ' && chunk_size > 1 && chunk[chunk_size-1] == '\n') {
- chunk_size--;
- continue;
- }
-
- /* chunks are terminated by a double line-feed */
- if (c == '\n' && chunk_size > 0 && chunk[chunk_size-1] == '\n') {
- chunk[chunk_size-1] = 0;
- return chunk;
- }
-
- if (c == '#' && (chunk_size == 0 || chunk[chunk_size-1] == '\n')) {
- in_comment = 1;
- continue;
- }
-
- /* ignore leading blank lines */
- if (chunk_size == 0 && c == '\n') {
- continue;
- }
-
- chunk[chunk_size++] = c;
- }
-
- if (chunk) {
- chunk[chunk_size] = 0;
- }
-
- return chunk;
-}
-
-
-/* simple ldif attribute parser */
-static int next_attr(void *mem_ctx, char **s, const char **attr, struct ldb_val *value)
-{
- char *p;
- int base64_encoded = 0;
- int binary_file = 0;
-
- if (strncmp(*s, "-\n", 2) == 0) {
- value->length = 0;
- *attr = "-";
- *s += 2;
- return 0;
- }
-
- p = strchr(*s, ':');
- if (!p) {
- return -1;
- }
-
- *p++ = 0;
-
- if (*p == ':') {
- base64_encoded = 1;
- p++;
- }
-
- if (*p == '<') {
- binary_file = 1;
- p++;
- }
-
- *attr = *s;
-
- while (*p == ' ' || *p == '\t') {
- p++;
- }
-
- value->data = (uint8_t *)p;
-
- p = strchr(p, '\n');
-
- if (!p) {
- value->length = strlen((char *)value->data);
- *s = ((char *)value->data) + value->length;
- } else {
- value->length = p - (char *)value->data;
- *s = p+1;
- *p = 0;
- }
-
- if (base64_encoded) {
- int len = ldb_base64_decode((char *)value->data);
- if (len == -1) {
- /* it wasn't valid base64 data */
- return -1;
- }
- value->length = len;
- }
-
- if (binary_file) {
- int len = ldb_read_data_file(mem_ctx, value);
- if (len == -1) {
- /* an error occured hile trying to retrieve the file */
- return -1;
- }
- }
-
- return 0;
-}
-
-
-/*
- free a message from a ldif_read
-*/
-void ldb_ldif_read_free(struct ldb_context *ldb, struct ldb_ldif *ldif)
-{
- talloc_free(ldif);
-}
-
-/*
- read from a LDIF source, creating a ldb_message
-*/
-struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb,
- int (*fgetc_fn)(void *), void *private_data)
-{
- struct ldb_ldif *ldif;
- struct ldb_message *msg;
- const char *attr=NULL;
- char *chunk=NULL, *s;
- struct ldb_val value;
- unsigned flags = 0;
-
- value.data = NULL;
-
- ldif = talloc(ldb, struct ldb_ldif);
- if (!ldif) return NULL;
-
- ldif->msg = talloc(ldif, struct ldb_message);
- if (ldif->msg == NULL) {
- talloc_free(ldif);
- return NULL;
- }
-
- ldif->changetype = LDB_CHANGETYPE_NONE;
- msg = ldif->msg;
-
- msg->dn = NULL;
- msg->elements = NULL;
- msg->num_elements = 0;
-
- chunk = next_chunk(ldb, fgetc_fn, private_data);
- if (!chunk) {
- goto failed;
- }
- talloc_steal(ldif, chunk);
-
- s = chunk;
-
- if (next_attr(ldif, &s, &attr, &value) != 0) {
- goto failed;
- }
-
- /* first line must be a dn */
- if (ldb_attr_cmp(attr, "dn") != 0) {
- ldb_debug(ldb, LDB_DEBUG_ERROR, "Error: First line of ldif must be a dn not '%s'\n",
- attr);
- goto failed;
- }
-
- msg->dn = ldb_dn_from_ldb_val(msg, ldb, &value);
-
- if ( ! ldb_dn_validate(msg->dn)) {
- ldb_debug(ldb, LDB_DEBUG_ERROR, "Error: Unable to parse dn '%s'\n",
- (char *)value.data);
- goto failed;
- }
-
- while (next_attr(ldif, &s, &attr, &value) == 0) {
- const struct ldb_schema_attribute *a;
- struct ldb_message_element *el;
- int ret, empty = 0;
-
- if (ldb_attr_cmp(attr, "changetype") == 0) {
- int i;
- for (i=0;ldb_changetypes[i].name;i++) {
- if (ldb_attr_cmp((char *)value.data, ldb_changetypes[i].name) == 0) {
- ldif->changetype = ldb_changetypes[i].changetype;
- break;
- }
- }
- if (!ldb_changetypes[i].name) {
- ldb_debug(ldb, LDB_DEBUG_ERROR,
- "Error: Bad ldif changetype '%s'\n",(char *)value.data);
- }
- flags = 0;
- continue;
- }
-
- if (ldb_attr_cmp(attr, "add") == 0) {
- flags = LDB_FLAG_MOD_ADD;
- empty = 1;
- }
- if (ldb_attr_cmp(attr, "delete") == 0) {
- flags = LDB_FLAG_MOD_DELETE;
- empty = 1;
- }
- if (ldb_attr_cmp(attr, "replace") == 0) {
- flags = LDB_FLAG_MOD_REPLACE;
- empty = 1;
- }
- if (ldb_attr_cmp(attr, "-") == 0) {
- flags = 0;
- continue;
- }
-
- if (empty) {
- if (ldb_msg_add_empty(msg, (char *)value.data, flags, NULL) != 0) {
- goto failed;
- }
- continue;
- }
-
- el = &msg->elements[msg->num_elements-1];
-
- a = ldb_schema_attribute_by_name(ldb, attr);
-
- if (msg->num_elements > 0 && ldb_attr_cmp(attr, el->name) == 0 &&
- flags == el->flags) {
- /* its a continuation */
- el->values =
- talloc_realloc(msg->elements, el->values,
- struct ldb_val, el->num_values+1);
- if (!el->values) {
- goto failed;
- }
- ret = a->syntax->ldif_read_fn(ldb, ldif, &value, &el->values[el->num_values]);
- if (ret != 0) {
- goto failed;
- }
- if (value.length == 0) {
- ldb_debug(ldb, LDB_DEBUG_ERROR,
- "Error: Attribute value cannot be empty for attribute '%s'\n", el->name);
- goto failed;
- }
- if (value.data != el->values[el->num_values].data) {
- talloc_steal(el->values, el->values[el->num_values].data);
- }
- el->num_values++;
- } else {
- /* its a new attribute */
- msg->elements = talloc_realloc(ldif, msg->elements,
- struct ldb_message_element,
- msg->num_elements+1);
- if (!msg->elements) {
- goto failed;
- }
- el = &msg->elements[msg->num_elements];
- el->flags = flags;
- el->name = talloc_strdup(msg->elements, attr);
- el->values = talloc(msg->elements, struct ldb_val);
- if (!el->values || !el->name) {
- goto failed;
- }
- el->num_values = 1;
- ret = a->syntax->ldif_read_fn(ldb, ldif, &value, &el->values[0]);
- if (ret != 0) {
- goto failed;
- }
- if (value.data != el->values[0].data) {
- talloc_steal(el->values, el->values[0].data);
- }
- msg->num_elements++;
- }
- }
-
- return ldif;
-
-failed:
- talloc_free(ldif);
- return NULL;
-}
-
-
-
-/*
- a wrapper around ldif_read() for reading from FILE*
-*/
-struct ldif_read_file_state {
- FILE *f;
-};
-
-static int fgetc_file(void *private_data)
-{
- struct ldif_read_file_state *state =
- (struct ldif_read_file_state *)private_data;
- return fgetc(state->f);
-}
-
-struct ldb_ldif *ldb_ldif_read_file(struct ldb_context *ldb, FILE *f)
-{
- struct ldif_read_file_state state;
- state.f = f;
- return ldb_ldif_read(ldb, fgetc_file, &state);
-}
-
-
-/*
- a wrapper around ldif_read() for reading from const char*
-*/
-struct ldif_read_string_state {
- const char *s;
-};
-
-static int fgetc_string(void *private_data)
-{
- struct ldif_read_string_state *state =
- (struct ldif_read_string_state *)private_data;
- if (state->s[0] != 0) {
- return *state->s++;
- }
- return EOF;
-}
-
-struct ldb_ldif *ldb_ldif_read_string(struct ldb_context *ldb, const char **s)
-{
- struct ldif_read_string_state state;
- struct ldb_ldif *ldif;
- state.s = *s;
- ldif = ldb_ldif_read(ldb, fgetc_string, &state);
- *s = state.s;
- return ldif;
-}
-
-
-/*
- wrapper around ldif_write() for a file
-*/
-struct ldif_write_file_state {
- FILE *f;
-};
-
-static int fprintf_file(void *private_data, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
-
-static int fprintf_file(void *private_data, const char *fmt, ...)
-{
- struct ldif_write_file_state *state =
- (struct ldif_write_file_state *)private_data;
- int ret;
- va_list ap;
-
- va_start(ap, fmt);
- ret = vfprintf(state->f, fmt, ap);
- va_end(ap);
- return ret;
-}
-
-int ldb_ldif_write_file(struct ldb_context *ldb, FILE *f, const struct ldb_ldif *ldif)
-{
- struct ldif_write_file_state state;
- state.f = f;
- return ldb_ldif_write(ldb, fprintf_file, &state, ldif);
-}
diff --git a/ldb/common/ldb_match.c b/ldb/common/ldb_match.c
deleted file mode 100644
index 4cde739d..00000000
--- a/ldb/common/ldb_match.c
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
- ldb database library
-
- Copyright (C) Andrew Tridgell 2004-2005
- Copyright (C) Simo Sorce 2005
-
- ** NOTE! The following LGPL license applies to the ldb
- ** library. This does NOT imply that all of Samba is released
- ** under the LGPL
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-/*
- * Name: ldb
- *
- * Component: ldb expression matching
- *
- * Description: ldb expression matching
- *
- * Author: Andrew Tridgell
- */
-
-#include "ldb_includes.h"
-
-/*
- check if the scope matches in a search result
-*/
-static int ldb_match_scope(struct ldb_context *ldb,
- struct ldb_dn *base,
- struct ldb_dn *dn,
- enum ldb_scope scope)
-{
- int ret = 0;
-
- if (base == NULL || dn == NULL) {
- return 1;
- }
-
- switch (scope) {
- case LDB_SCOPE_BASE:
- if (ldb_dn_compare(base, dn) == 0) {
- ret = 1;
- }
- break;
-
- case LDB_SCOPE_ONELEVEL:
- if (ldb_dn_get_comp_num(dn) == (ldb_dn_get_comp_num(base) + 1)) {
- if (ldb_dn_compare_base(base, dn) == 0) {
- ret = 1;
- }
- }
- break;
-
- case LDB_SCOPE_SUBTREE:
- default:
- if (ldb_dn_compare_base(base, dn) == 0) {
- ret = 1;
- }
- break;
- }
-
- return ret;
-}
-
-
-/*
- match if node is present
-*/
-static int ldb_match_present(struct ldb_context *ldb,
- const struct ldb_message *msg,
- const struct ldb_parse_tree *tree,
- enum ldb_scope scope)
-{
- if (ldb_attr_dn(tree->u.present.attr) == 0) {
- return 1;
- }
-
- if (ldb_msg_find_element(msg, tree->u.present.attr)) {
- return 1;
- }
-
- return 0;
-}
-
-static int ldb_match_comparison(struct ldb_context *ldb,
- const struct ldb_message *msg,
- const struct ldb_parse_tree *tree,
- enum ldb_scope scope,
- enum ldb_parse_op comp_op)
-{
- unsigned int i;
- struct ldb_message_element *el;
- const struct ldb_schema_attribute *a;
- int ret;
-
- /* FIXME: APPROX comparison not handled yet */
- if (comp_op == LDB_OP_APPROX) return 0;
-
- el = ldb_msg_find_element(msg, tree->u.comparison.attr);
- if (el == NULL) {
- return 0;
- }
-
- a = ldb_schema_attribute_by_name(ldb, el->name);
-
- for (i = 0; i < el->num_values; i++) {
- ret = a->syntax->comparison_fn(ldb, ldb, &el->values[i], &tree->u.comparison.value);
-
- if (ret == 0) {
- return 1;
- }
- if (ret > 0 && comp_op == LDB_OP_GREATER) {
- return 1;
- }
- if (ret < 0 && comp_op == LDB_OP_LESS) {
- return 1;
- }
- }
-
- return 0;
-}
-
-/*
- match a simple leaf node
-*/
-static int ldb_match_equality(struct ldb_context *ldb,
- const struct ldb_message *msg,
- const struct ldb_parse_tree *tree,
- enum ldb_scope scope)
-{
- unsigned int i;
- struct ldb_message_element *el;
- const struct ldb_schema_attribute *a;
- struct ldb_dn *valuedn;
- int ret;
-
- if (ldb_attr_dn(tree->u.equality.attr) == 0) {
- valuedn = ldb_dn_from_ldb_val(ldb, ldb, &tree->u.equality.value);
- if (valuedn == NULL) {
- return 0;
- }
-
- ret = ldb_dn_compare(msg->dn, valuedn);
-
- talloc_free(valuedn);
-
- if (ret == 0) return 1;
- return 0;
- }
-
- /* TODO: handle the "*" case derived from an extended search
- operation without the attibute type defined */
- el = ldb_msg_find_element(msg, tree->u.equality.attr);
- if (el == NULL) {
- return 0;
- }
-
- a = ldb_schema_attribute_by_name(ldb, el->name);
-
- for (i=0;i<el->num_values;i++) {
- if (a->syntax->comparison_fn(ldb, ldb, &tree->u.equality.value,
- &el->values[i]) == 0) {
- return 1;
- }
- }
-
- return 0;
-}
-
-static int ldb_wildcard_compare(struct ldb_context *ldb,
- const struct ldb_parse_tree *tree,
- const struct ldb_val value)
-{
- const struct ldb_schema_attribute *a;
- struct ldb_val val;
- struct ldb_val cnk;
- struct ldb_val *chunk;
- char *p, *g;
- uint8_t *save_p = NULL;
- int c = 0;
-
- a = ldb_schema_attribute_by_name(ldb, tree->u.substring.attr);
-
- if(a->syntax->canonicalise_fn(ldb, ldb, &value, &val) != 0)
- return -1;
-
- save_p = val.data;
- cnk.data = NULL;
-
- if ( ! tree->u.substring.start_with_wildcard ) {
-
- chunk = tree->u.substring.chunks[c];
- if(a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) goto failed;
-
- /* This deals with wildcard prefix searches on binary attributes (eg objectGUID) */
- if (cnk.length > val.length) {
- goto failed;
- }
- if (memcmp((char *)val.data, (char *)cnk.data, cnk.length) != 0) goto failed;
- val.length -= cnk.length;
- val.data += cnk.length;
- c++;
- talloc_free(cnk.data);
- cnk.data = NULL;
- }
-
- while (tree->u.substring.chunks[c]) {
-
- chunk = tree->u.substring.chunks[c];
- if(a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) goto failed;
-
- /* FIXME: case of embedded nulls */
- p = strstr((char *)val.data, (char *)cnk.data);
- if (p == NULL) goto failed;
- if ( (! tree->u.substring.chunks[c + 1]) && (! tree->u.substring.end_with_wildcard) ) {
- do { /* greedy */
- g = strstr((char *)p + cnk.length, (char *)cnk.data);
- if (g) p = g;
- } while(g);
- }
- val.length = val.length - (p - (char *)(val.data)) - cnk.length;
- val.data = (uint8_t *)(p + cnk.length);
- c++;
- talloc_free(cnk.data);
- cnk.data = NULL;
- }
-
- if ( (! tree->u.substring.end_with_wildcard) && (*(val.data) != 0) ) goto failed; /* last chunk have not reached end of string */
- talloc_free(save_p);
- return 1;
-
-failed:
- talloc_free(save_p);
- talloc_free(cnk.data);
- return 0;
-}
-
-/*
- match a simple leaf node
-*/
-static int ldb_match_substring(struct ldb_context *ldb,
- const struct ldb_message *msg,
- const struct ldb_parse_tree *tree,
- enum ldb_scope scope)
-{
- unsigned int i;
- struct ldb_message_element *el;
-
- el = ldb_msg_find_element(msg, tree->u.substring.attr);
- if (el == NULL) {
- return 0;
- }
-
- for (i = 0; i < el->num_values; i++) {
- if (ldb_wildcard_compare(ldb, tree, el->values[i]) == 1) {
- return 1;
- }
- }
-
- return 0;
-}
-
-
-/*
- bitwise-and comparator
-*/
-static int ldb_comparator_and(const struct ldb_val *v1, const struct ldb_val *v2)
-{
- uint64_t i1, i2;
- i1 = strtoull((char *)v1->data, NULL, 0);
- i2 = strtoull((char *)v2->data, NULL, 0);
- return ((i1 & i2) == i2);
-}
-
-/*
- bitwise-or comparator
-*/
-static int ldb_comparator_or(const struct ldb_val *v1, const struct ldb_val *v2)
-{
- uint64_t i1, i2;
- i1 = strtoull((char *)v1->data, NULL, 0);
- i2 = strtoull((char *)v2->data, NULL, 0);
- return ((i1 & i2) != 0);
-}
-
-
-/*
- extended match, handles things like bitops
-*/
-static int ldb_match_extended(struct ldb_context *ldb,
- const struct ldb_message *msg,
- const struct ldb_parse_tree *tree,
- enum ldb_scope scope)
-{
- int i;
- const struct {
- const char *oid;
- int (*comparator)(const struct ldb_val *, const struct ldb_val *);
- } rules[] = {
- { LDB_OID_COMPARATOR_AND, ldb_comparator_and},
- { LDB_OID_COMPARATOR_OR, ldb_comparator_or}
- };
- int (*comp)(const struct ldb_val *, const struct ldb_val *) = NULL;
- struct ldb_message_element *el;
-
- if (tree->u.extended.dnAttributes) {
- ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: dnAttributes extended match not supported yet");
- return -1;
- }
- if (tree->u.extended.rule_id == NULL) {
- ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: no-rule extended matches not supported yet");
- return -1;
- }
- if (tree->u.extended.attr == NULL) {
- ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: no-attribute extended matches not supported yet");
- return -1;
- }
-
- for (i=0;i<ARRAY_SIZE(rules);i++) {
- if (strcmp(rules[i].oid, tree->u.extended.rule_id) == 0) {
- comp = rules[i].comparator;
- break;
- }
- }
- if (comp == NULL) {
- ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: unknown extended rule_id %s\n",
- tree->u.extended.rule_id);
- return -1;
- }
-
- /* find the message element */
- el = ldb_msg_find_element(msg, tree->u.extended.attr);
- if (el == NULL) {
- return 0;
- }
-
- for (i=0;i<el->num_values;i++) {
- int ret = comp(&el->values[i], &tree->u.extended.value);
- if (ret == -1 || ret == 1) return ret;
- }
-
- return 0;
-}
-
-/*
- return 0 if the given parse tree matches the given message. Assumes
- the message is in sorted order
-
- return 1 if it matches, and 0 if it doesn't match
-
- this is a recursive function, and does short-circuit evaluation
- */
-static int ldb_match_message(struct ldb_context *ldb,
- const struct ldb_message *msg,
- const struct ldb_parse_tree *tree,
- enum ldb_scope scope)
-{
- unsigned int i;
- int v;
-
- switch (tree->operation) {
- case LDB_OP_AND:
- for (i=0;i<tree->u.list.num_elements;i++) {
- v = ldb_match_message(ldb, msg, tree->u.list.elements[i], scope);
- if (!v) return 0;
- }
- return 1;
-
- case LDB_OP_OR:
- for (i=0;i<tree->u.list.num_elements;i++) {
- v = ldb_match_message(ldb, msg, tree->u.list.elements[i], scope);
- if (v) return 1;
- }
- return 0;
-
- case LDB_OP_NOT:
- return ! ldb_match_message(ldb, msg, tree->u.isnot.child, scope);
-
- case LDB_OP_EQUALITY:
- return ldb_match_equality(ldb, msg, tree, scope);
-
- case LDB_OP_SUBSTRING:
- return ldb_match_substring(ldb, msg, tree, scope);
-
- case LDB_OP_GREATER:
- return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_GREATER);
-
- case LDB_OP_LESS:
- return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_LESS);
-
- case LDB_OP_PRESENT:
- return ldb_match_present(ldb, msg, tree, scope);
-
- case LDB_OP_APPROX:
- return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_APPROX);
-
- case LDB_OP_EXTENDED:
- return ldb_match_extended(ldb, msg, tree, scope);
-
- }
-
- return 0;
-}
-
-int ldb_match_msg(struct ldb_context *ldb,
- const struct ldb_message *msg,
- const struct ldb_parse_tree *tree,
- struct ldb_dn *base,
- enum ldb_scope scope)
-{
- if ( ! ldb_match_scope(ldb, base, msg->dn, scope) ) {
- return 0;
- }
-
- return ldb_match_message(ldb, msg, tree, scope);
-}
diff --git a/ldb/common/ldb_modules.c b/ldb/common/ldb_modules.c
deleted file mode 100644
index 0fcdf937..00000000
--- a/ldb/common/ldb_modules.c
+++ /dev/null
@@ -1,777 +0,0 @@
-/*
- ldb database library
-
- Copyright (C) Simo Sorce 2004-2008
-
- ** NOTE! The following LGPL license applies to the ldb
- ** library. This does NOT imply that all of Samba is released
- ** under the LGPL
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-/*
- * Name: ldb
- *
- * Component: ldb modules core
- *
- * Description: core modules routines
- *
- * Author: Simo Sorce
- */
-
-#include "ldb_includes.h"
-
-#if (_SAMBA_BUILD_ >= 4)
-#include "includes.h"
-#endif
-
-#define LDB_MODULE_PREFIX "modules:"
-#define LDB_MODULE_PREFIX_LEN 8
-
-static void *ldb_dso_load_symbol(struct ldb_context *ldb, const char *name,
- const char *symbol);
-
-void ldb_set_modules_dir(struct ldb_context *ldb, const char *path)
-{
- talloc_free(ldb->modules_dir);
- ldb->modules_dir = talloc_strdup(ldb, path);
-}
-
-static char *ldb_modules_strdup_no_spaces(TALLOC_CTX *mem_ctx, const char *string)
-{
- int i, len;
- char *trimmed;
-
- trimmed = talloc_strdup(mem_ctx, string);
- if (!trimmed) {
- return NULL;
- }
-
- len = strlen(trimmed);
- for (i = 0; trimmed[i] != '\0'; i++) {
- switch (trimmed[i]) {
- case ' ':
- case '\t':
- case '\n':
- memmove(&trimmed[i], &trimmed[i + 1], len -i -1);
- break;
- }
- }
-
- return trimmed;
-}
-
-
-/* modules are called in inverse order on the stack.
- Lets place them as an admin would think the right order is.
- Modules order is important */
-const char **ldb_modules_list_from_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *string)
-{
- char **modules = NULL;
- const char **m;
- char *modstr, *p;
- int i;
-
- /* spaces not admitted */
- modstr = ldb_modules_strdup_no_spaces(mem_ctx, string);
- if ( ! modstr) {
- ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in ldb_modules_strdup_no_spaces()\n");
- return NULL;
- }
-
- modules = talloc_realloc(mem_ctx, modules, char *, 2);
- if ( ! modules ) {
- ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in ldb_modules_list_from_string()\n");
- talloc_free(modstr);
- return NULL;
- }
- talloc_steal(modules, modstr);
-
- i = 0;
- /* The str*r*chr walks backwards: This is how we get the inverse order mentioned above */
- while ((p = strrchr(modstr, ',')) != NULL) {
- *p = '\0';
- p++;
- modules[i] = p;
-
- i++;
- modules = talloc_realloc(mem_ctx, modules, char *, i + 2);
- if ( ! modules ) {
- ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in ldb_modules_list_from_string()\n");
- return NULL;
- }
-
- }
- modules[i] = modstr;
-
- modules[i + 1] = NULL;
-
- m = (const char **)modules;
-
- return m;
-}
-
-static struct backends_list_entry {
- struct ldb_backend_ops *ops;
- struct backends_list_entry *prev, *next;
-} *ldb_backends = NULL;
-
-static struct ops_list_entry {
- const struct ldb_module_ops *ops;
- struct ops_list_entry *next;
-} *registered_modules = NULL;
-
-static const struct ldb_builtins {
- const struct ldb_backend_ops *backend_ops;
- const struct ldb_module_ops *module_ops;
-} builtins[];
-
-static ldb_connect_fn ldb_find_backend(const char *url)
-{
- struct backends_list_entry *backend;
- int i;
-
- for (i = 0; builtins[i].backend_ops || builtins[i].module_ops; i++) {
- if (builtins[i].backend_ops == NULL) continue;
-
- if (strncmp(builtins[i].backend_ops->name, url,
- strlen(builtins[i].backend_ops->name)) == 0) {
- return builtins[i].backend_ops->connect_fn;
- }
- }
-
- for (backend = ldb_backends; backend; backend = backend->next) {
- if (strncmp(backend->ops->name, url,
- strlen(backend->ops->name)) == 0) {
- return backend->ops->connect_fn;
- }
- }
-
- return NULL;
-}
-
-/*
- register a new ldb backend
-*/
-int ldb_register_backend(const char *url_prefix, ldb_connect_fn connectfn)
-{
- struct ldb_backend_ops *backend;
- struct backends_list_entry *entry;
-
- backend = talloc(talloc_autofree_context(), struct ldb_backend_ops);
- if (!backend) return LDB_ERR_OPERATIONS_ERROR;
-
- entry = talloc(talloc_autofree_context(), struct backends_list_entry);
- if (!entry) {
- talloc_free(backend);
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- if (ldb_find_backend(url_prefix)) {
- return LDB_SUCCESS;
- }
-
- /* Maybe check for duplicity here later on? */
-
- backend->name = talloc_strdup(backend, url_prefix);
- backend->connect_fn = connectfn;
- entry->ops = backend;
- DLIST_ADD(ldb_backends, entry);
-
- return LDB_SUCCESS;
-}
-
-/*
- Return the ldb module form of a database.
- The URL can either be one of the following forms
- ldb://path
- ldapi://path
-
- flags is made up of LDB_FLG_*
-
- the options are passed uninterpreted to the backend, and are
- backend specific.
-
- This allows modules to get at only the backend module, for example where a
- module may wish to direct certain requests at a particular backend.
-*/
-int ldb_connect_backend(struct ldb_context *ldb,
- const char *url,
- const char *options[],
- struct ldb_module **backend_module)
-{
- int ret;
- char *backend;
- ldb_connect_fn fn;
-
- if (strchr(url, ':') != NULL) {
- backend = talloc_strndup(ldb, url, strchr(url, ':')-url);
- } else {
- /* Default to tdb */
- backend = talloc_strdup(ldb, "tdb");
- }
-
- fn = ldb_find_backend(backend);
-
- if (fn == NULL) {
- struct ldb_backend_ops *ops;
- char *symbol_name = talloc_asprintf(ldb, "ldb_%s_backend_ops", backend);
- if (symbol_name == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
- ops = ldb_dso_load_symbol(ldb, backend, symbol_name);
- if (ops != NULL) {
- fn = ops->connect_fn;
- }
- talloc_free(symbol_name);
- }
-
- talloc_free(backend);
-
- if (fn == NULL) {
- ldb_debug(ldb, LDB_DEBUG_FATAL,
- "Unable to find backend for '%s'\n", url);
- return LDB_ERR_OTHER;
- }
-
- ret = fn(ldb, url, ldb->flags, options, backend_module);
-
- if (ret != LDB_SUCCESS) {
- ldb_debug(ldb, LDB_DEBUG_ERROR,
- "Failed to connect to '%s'\n", url);
- return ret;
- }
- return ret;
-}
-
-static const struct ldb_module_ops *ldb_find_module_ops(const char *name)
-{
- struct ops_list_entry *e;
- int i;
-
- for (i = 0; builtins[i].backend_ops || builtins[i].module_ops; i++) {
- if (builtins[i].module_ops == NULL) continue;
-
- if (strcmp(builtins[i].module_ops->name, name) == 0)
- return builtins[i].module_ops;
- }
-
- for (e = registered_modules; e; e = e->next) {
- if (strcmp(e->ops->name, name) == 0)
- return e->ops;
- }
-
- return NULL;
-}
-
-
-int ldb_register_module(const struct ldb_module_ops *ops)
-{
- struct ops_list_entry *entry = talloc(talloc_autofree_context(), struct ops_list_entry);
-
- if (ldb_find_module_ops(ops->name) != NULL)
- return -1;
-
- if (entry == NULL)
- return -1;
-
- entry->ops = ops;
- entry->next = registered_modules;
- registered_modules = entry;
-
- return 0;
-}
-
-static void *ldb_dso_load_symbol(struct ldb_context *ldb, const char *name,
- const char *symbol)
-{
- char *path;
- void *handle;
- void *sym;
-
- if (ldb->modules_dir == NULL)
- return NULL;
-
- path = talloc_asprintf(ldb, "%s/%s.%s", ldb->modules_dir, name,
- SHLIBEXT);
-
- ldb_debug(ldb, LDB_DEBUG_TRACE, "trying to load %s from %s\n", name, path);
-
- handle = dlopen(path, RTLD_NOW);
- if (handle == NULL) {
- ldb_debug(ldb, LDB_DEBUG_WARNING, "unable to load %s from %s: %s\n", name, path, dlerror());
- return NULL;
- }
-
- sym = (int (*)(void))dlsym(handle, symbol);
-
- if (sym == NULL) {
- ldb_debug(ldb, LDB_DEBUG_ERROR, "no symbol `%s' found in %s: %s\n", symbol, path, dlerror());
- return NULL;
- }
-
- talloc_free(path);
-
- return sym;
-}
-
-int ldb_load_modules_list(struct ldb_context *ldb, const char **module_list, struct ldb_module *backend, struct ldb_module **out)
-{
- struct ldb_module *module;
- int i;
-
- module = backend;
-
- for (i = 0; module_list[i] != NULL; i++) {
- struct ldb_module *current;
- const struct ldb_module_ops *ops;
-
- if (strcmp(module_list[i], "") == 0) {
- continue;
- }
-
- ops = ldb_find_module_ops(module_list[i]);
- if (ops == NULL) {
- char *symbol_name = talloc_asprintf(ldb, "ldb_%s_module_ops",
- module_list[i]);
- if (symbol_name == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
- ops = ldb_dso_load_symbol(ldb, module_list[i], symbol_name);
- talloc_free(symbol_name);
- }
-
- if (ops == NULL) {
- ldb_debug(ldb, LDB_DEBUG_WARNING, "WARNING: Module [%s] not found\n",
- module_list[i]);
- continue;
- }
-
- current = talloc_zero(ldb, struct ldb_module);
- if (current == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
- talloc_set_name(current, "ldb_module: %s", module_list[i]);
-
- current->ldb = ldb;
- current->ops = ops;
-
- DLIST_ADD(module, current);
- }
- *out = module;
- return LDB_SUCCESS;
-}
-
-int ldb_init_module_chain(struct ldb_context *ldb, struct ldb_module *module)
-{
- while (module && module->ops->init_context == NULL)
- module = module->next;
-
- /* init is different in that it is not an error if modules
- * do not require initialization */
-
- if (module) {
- int ret = module->ops->init_context(module);
- if (ret != LDB_SUCCESS) {
- ldb_debug(ldb, LDB_DEBUG_FATAL, "module %s initialization failed\n", module->ops->name);
- return ret;
- }
- }
-
- return LDB_SUCCESS;
-}
-
-int ldb_load_modules(struct ldb_context *ldb, const char *options[])
-{
- const char **modules = NULL;
- int i;
- int ret;
- TALLOC_CTX *mem_ctx = talloc_new(ldb);
- if (!mem_ctx) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- /* find out which modules we are requested to activate */
-
- /* check if we have a custom module list passd as ldb option */
- if (options) {
- for (i = 0; options[i] != NULL; i++) {
- if (strncmp(options[i], LDB_MODULE_PREFIX, LDB_MODULE_PREFIX_LEN) == 0) {
- modules = ldb_modules_list_from_string(ldb, mem_ctx, &options[i][LDB_MODULE_PREFIX_LEN]);
- }
- }
- }
-
- /* if not overloaded by options and the backend is not ldap try to load the modules list from ldb */
- if ((modules == NULL) && (strcmp("ldap", ldb->modules->ops->name) != 0)) {
- const char * const attrs[] = { "@LIST" , NULL};
- struct ldb_result *res = NULL;
- struct ldb_dn *mods_dn;
-
- mods_dn = ldb_dn_new(mem_ctx, ldb, "@MODULES");
- if (mods_dn == NULL) {
- talloc_free(mem_ctx);
- return -1;
- }
-
- ret = ldb_search(ldb, mods_dn, &res, mods_dn, LDB_SCOPE_BASE, attrs, "@LIST=*");
-
- if (ret == LDB_ERR_NO_SUCH_OBJECT) {
- ldb_debug(ldb, LDB_DEBUG_TRACE, "no modules required by the db");
- } else if (ret != LDB_SUCCESS) {
- ldb_debug(ldb, LDB_DEBUG_FATAL, "ldb error (%s) occurred searching for modules, bailing out\n", ldb_errstring(ldb));
- talloc_free(mem_ctx);
- return ret;
- } else {
- const char *module_list;
- if (res->count == 0) {
- ldb_debug(ldb, LDB_DEBUG_TRACE, "no modules required by the db");
- } else if (res->count > 1) {
- ldb_debug(ldb, LDB_DEBUG_FATAL, "Too many records found (%d), bailing out\n", res->count);
- talloc_free(mem_ctx);
- return -1;
- } else {
- module_list = ldb_msg_find_attr_as_string(res->msgs[0], "@LIST", NULL);
- if (!module_list) {
- ldb_debug(ldb, LDB_DEBUG_TRACE, "no modules required by the db");
- }
- modules = ldb_modules_list_from_string(ldb, mem_ctx,
- module_list);
- }
- }
-
- talloc_free(mods_dn);
- }
-
- if (modules != NULL) {
- ret = ldb_load_modules_list(ldb, modules, ldb->modules, &ldb->modules);
- if (ret != LDB_SUCCESS) {
- talloc_free(mem_ctx);
- return ret;
- }
- } else {
- ldb_debug(ldb, LDB_DEBUG_TRACE, "No modules specified for this database");
- }
-
- ret = ldb_init_module_chain(ldb, ldb->modules);
- talloc_free(mem_ctx);
- return ret;
-}
-
-/*
- by using this we allow ldb modules to only implement the functions they care about,
- which makes writing a module simpler, and makes it more likely to keep working
- when ldb is extended
-*/
-#define FIND_OP(module, op) do { \
- struct ldb_context *ldb = module->ldb; \
- module = module->next; \
- while (module && module->ops->op == NULL) module = module->next; \
- if (module == NULL) { \
- ldb_asprintf_errstring(ldb, "Unable to find backend operation for " #op ); \
- return LDB_ERR_OPERATIONS_ERROR; \
- } \
-} while (0)
-
-
-
-struct ldb_context *ldb_module_get_ctx(struct ldb_module *module)
-{
- return module->ldb;
-}
-
-/*
- helper functions to call the next module in chain
-*/
-
-int ldb_next_request(struct ldb_module *module, struct ldb_request *request)
-{
- int ret;
-
- if (request->callback == NULL) {
- ldb_set_errstring(module->ldb, "Requests MUST define callbacks");
- return LDB_ERR_UNWILLING_TO_PERFORM;
- }
-
- switch (request->operation) {
- case LDB_SEARCH:
- FIND_OP(module, search);
- ret = module->ops->search(module, request);
- break;
- case LDB_ADD:
- FIND_OP(module, add);
- ret = module->ops->add(module, request);
- break;
- case LDB_MODIFY:
- FIND_OP(module, modify);
- ret = module->ops->modify(module, request);
- break;
- case LDB_DELETE:
- FIND_OP(module, del);
- ret = module->ops->del(module, request);
- break;
- case LDB_RENAME:
- FIND_OP(module, rename);
- ret = module->ops->rename(module, request);
- break;
- case LDB_EXTENDED:
- FIND_OP(module, extended);
- ret = module->ops->extended(module, request);
- break;
- default:
- FIND_OP(module, request);
- ret = module->ops->request(module, request);
- break;
- }
- if (ret == LDB_SUCCESS) {
- return ret;
- }
- if (!ldb_errstring(module->ldb)) {
- /* Set a default error string, to place the blame somewhere */
- ldb_asprintf_errstring(module->ldb, "error in module %s: %s (%d)", module->ops->name, ldb_strerror(ret), ret);
- }
- return ret;
-}
-
-int ldb_next_init(struct ldb_module *module)
-{
- module = module->next;
-
- return ldb_init_module_chain(module->ldb, module);
-}
-
-int ldb_next_start_trans(struct ldb_module *module)
-{
- FIND_OP(module, start_transaction);
- return module->ops->start_transaction(module);
-}
-
-int ldb_next_end_trans(struct ldb_module *module)
-{
- FIND_OP(module, end_transaction);
- return module->ops->end_transaction(module);
-}
-
-int ldb_next_del_trans(struct ldb_module *module)
-{
- FIND_OP(module, del_transaction);
- return module->ops->del_transaction(module);
-}
-
-struct ldb_handle *ldb_handle_new(TALLOC_CTX *mem_ctx, struct ldb_context *ldb)
-{
- struct ldb_handle *h;
-
- h = talloc_zero(mem_ctx, struct ldb_handle);
- if (h == NULL) {
- ldb_set_errstring(ldb, "Out of Memory");
- return NULL;
- }
-
- h->status = LDB_SUCCESS;
- h->state = LDB_ASYNC_INIT;
- h->ldb = ldb;
-
- return h;
-}
-
-/* calls the request callback to send an entry
- *
- * params:
- * req: the original request passed to your module
- * msg: reply message (must be a talloc pointer, and it will be stolen
- * on the ldb_reply that is sent to the callback)
- * ctrls: controls to send in the reply (must be a talloc pointer, and it will be stolen
- * on the ldb_reply that is sent to the callback)
- */
-
-int ldb_module_send_entry(struct ldb_request *req,
- struct ldb_message *msg,
- struct ldb_control **ctrls)
-{
- struct ldb_reply *ares;
-
- ares = talloc_zero(req, struct ldb_reply);
- if (!ares) {
- ldb_oom(req->handle->ldb);
- req->callback(req, NULL);
- return LDB_ERR_OPERATIONS_ERROR;
- }
- ares->type = LDB_REPLY_ENTRY;
- ares->message = talloc_steal(ares, msg);
- ares->controls = talloc_steal(ares, ctrls);
- ares->error = LDB_SUCCESS;
-
- return req->callback(req, ares);
-}
-
-/* calls the request callback to send an referrals
- *
- * params:
- * req: the original request passed to your module
- * ref: referral string (must be a talloc pointeri, steal)
- */
-
-int ldb_module_send_referral(struct ldb_request *req,
- char *ref)
-{
- struct ldb_reply *ares;
-
- ares = talloc_zero(req, struct ldb_reply);
- if (!ares) {
- ldb_oom(req->handle->ldb);
- req->callback(req, NULL);
- return LDB_ERR_OPERATIONS_ERROR;
- }
- ares->type = LDB_REPLY_REFERRAL;
- ares->referral = talloc_steal(ares, ref);
- ares->error = LDB_SUCCESS;
-
- return req->callback(req, ares);
-}
-
-/* calls the original request callback
- *
- * params:
- * req: the original request passed to your module
- * ctrls: controls to send in the reply (must be a talloc pointer, steal)
- * response: results for extended request (steal)
- * error: LDB_SUCCESS for a succesful return
- * any other ldb error otherwise
- */
-int ldb_module_done(struct ldb_request *req,
- struct ldb_control **ctrls,
- struct ldb_extended *response,
- int error)
-{
- struct ldb_reply *ares;
-
- ares = talloc_zero(req, struct ldb_reply);
- if (!ares) {
- ldb_oom(req->handle->ldb);
- req->callback(req, NULL);
- return LDB_ERR_OPERATIONS_ERROR;
- }
- ares->type = LDB_REPLY_DONE;
- ares->controls = talloc_steal(ares, ctrls);
- ares->response = talloc_steal(ares, response);
- ares->error = error;
-
- req->callback(req, ares);
- return error;
-}
-
-/* to be used *only* in modules init functions.
- * this function i synchronous and will register
- * the requested OID in the rootdse module if present
- * otherwise it will return an error */
-int ldb_mod_register_control(struct ldb_module *module, const char *oid)
-{
- struct ldb_request *req;
- int ret;
-
- req = talloc_zero(module, struct ldb_request);
- if (req == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- req->operation = LDB_REQ_REGISTER_CONTROL;
- req->op.reg_control.oid = oid;
- req->callback = ldb_op_default_callback;
-
- ldb_set_timeout(module->ldb, req, 0);
-
- req->handle = ldb_handle_new(req, module->ldb);
- if (req->handle == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- ret = ldb_request(module->ldb, req);
- if (ret == LDB_SUCCESS) {
- ret = ldb_wait(req->handle, LDB_WAIT_ALL);
- }
- talloc_free(req);
-
- return ret;
-}
-
-#ifndef STATIC_LIBLDB_MODULES
-
-#ifdef HAVE_LDB_LDAP
-#define LDAP_BACKEND LDB_BACKEND(ldap), LDB_BACKEND(ldapi), LDB_BACKEND(ldaps),
-#else
-#define LDAP_BACKEND
-#endif
-
-#ifdef HAVE_LDB_SQLITE3
-#define SQLITE3_BACKEND LDB_BACKEND(sqlite3),
-#else
-#define SQLITE3_BACKEND
-#endif
-
-#define STATIC_LIBLDB_MODULES \
- LDB_BACKEND(tdb), \
- LDAP_BACKEND \
- SQLITE3_BACKEND \
- LDB_MODULE(operational), \
- LDB_MODULE(rdn_name), \
- LDB_MODULE(paged_results), \
- LDB_MODULE(server_sort), \
- LDB_MODULE(asq), \
- NULL
-#endif
-
-/*
- * this is a bit hacked, as STATIC_LIBLDB_MODULES contains ','
- * between the elements and we want to autogenerate the
- * extern struct declarations, so we do some hacks and let the
- * ',' appear in an unused function prototype.
- */
-#undef NULL
-#define NULL LDB_MODULE(NULL),
-
-#define LDB_BACKEND(name) \
- int); \
- extern const struct ldb_backend_ops ldb_ ## name ## _backend_ops;\
- extern void ldb_noop ## name (int
-#define LDB_MODULE(name) \
- int); \
- extern const struct ldb_module_ops ldb_ ## name ## _module_ops;\
- extern void ldb_noop ## name (int
-
-extern void ldb_start_noop(int,
-STATIC_LIBLDB_MODULES
-int);
-
-#undef NULL
-#define NULL { \
- .backend_ops = (void *)0, \
- .module_ops = (void *)0 \
-}
-
-#undef LDB_BACKEND
-#define LDB_BACKEND(name) { \
- .backend_ops = &ldb_ ## name ## _backend_ops, \
- .module_ops = (void *)0 \
-}
-#undef LDB_MODULE
-#define LDB_MODULE(name) { \
- .backend_ops = (void *)0, \
- .module_ops = &ldb_ ## name ## _module_ops \
-}
-
-static const struct ldb_builtins builtins[] = {
- STATIC_LIBLDB_MODULES
-};
diff --git a/ldb/common/ldb_msg.c b/ldb/common/ldb_msg.c
deleted file mode 100644
index 2f5fe1d1..00000000
--- a/ldb/common/ldb_msg.c
+++ /dev/null
@@ -1,899 +0,0 @@
-/*
- ldb database library
-
- Copyright (C) Andrew Tridgell 2004
-
- ** NOTE! The following LGPL license applies to the ldb
- ** library. This does NOT imply that all of Samba is released
- ** under the LGPL
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-/*
- * Name: ldb
- *
- * Component: ldb message component utility functions
- *
- * Description: functions for manipulating ldb_message structures
- *
- * Author: Andrew Tridgell
- */
-
-#include "ldb_includes.h"
-
-/*
- create a new ldb_message in a given memory context (NULL for top level)
-*/
-struct ldb_message *ldb_msg_new(void *mem_ctx)
-{
- return talloc_zero(mem_ctx, struct ldb_message);
-}
-
-/*
- find an element in a message by attribute name
-*/
-struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg,
- const char *attr_name)
-{
- unsigned int i;
- for (i=0;i<msg->num_elements;i++) {
- if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
- return &msg->elements[i];
- }
- }
- return NULL;
-}
-
-/*
- see if two ldb_val structures contain exactly the same data
- return 1 for a match, 0 for a mis-match
-*/
-int ldb_val_equal_exact(const struct ldb_val *v1, const struct ldb_val *v2)
-{
- if (v1->length != v2->length) return 0;
-
- if (v1->length == 0) return 1;
-
- if (memcmp(v1->data, v2->data, v1->length) == 0) {
- return 1;
- }
-
- return 0;
-}
-
-/*
- find a value in an element
- assumes case sensitive comparison
-*/
-struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el,
- struct ldb_val *val)
-{
- unsigned int i;
- for (i=0;i<el->num_values;i++) {
- if (ldb_val_equal_exact(val, &el->values[i])) {
- return &el->values[i];
- }
- }
- return NULL;
-}
-
-/*
- duplicate a ldb_val structure
-*/
-struct ldb_val ldb_val_dup(void *mem_ctx, const struct ldb_val *v)
-{
- struct ldb_val v2;
- v2.length = v->length;
- if (v->data == NULL) {
- v2.data = NULL;
- return v2;
- }
-
- /* the +1 is to cope with buggy C library routines like strndup
- that look one byte beyond */
- v2.data = talloc_array(mem_ctx, uint8_t, v->length+1);
- if (!v2.data) {
- v2.length = 0;
- return v2;
- }
-
- memcpy(v2.data, v->data, v->length);
- ((char *)v2.data)[v->length] = 0;
- return v2;
-}
-
-/*
- add an empty element to a message
-*/
-int ldb_msg_add_empty( struct ldb_message *msg,
- const char *attr_name,
- int flags,
- struct ldb_message_element **return_el)
-{
- struct ldb_message_element *els;
-
- els = talloc_realloc(msg, msg->elements,
- struct ldb_message_element, msg->num_elements+1);
- if (!els) {
- errno = ENOMEM;
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- els[msg->num_elements].values = NULL;
- els[msg->num_elements].num_values = 0;
- els[msg->num_elements].flags = flags;
- els[msg->num_elements].name = talloc_strdup(els, attr_name);
- if (!els[msg->num_elements].name) {
- errno = ENOMEM;
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- msg->elements = els;
- msg->num_elements++;
-
- if (return_el) {
- *return_el = &els[msg->num_elements-1];
- }
-
- return LDB_SUCCESS;
-}
-
-/*
- add an empty element to a message
-*/
-int ldb_msg_add(struct ldb_message *msg,
- const struct ldb_message_element *el,
- int flags)
-{
- /* We have to copy this, just in case *el is a pointer into
- * what ldb_msg_add_empty() is about to realloc() */
- struct ldb_message_element el_copy = *el;
- if (ldb_msg_add_empty(msg, el->name, flags, NULL) != 0) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- msg->elements[msg->num_elements-1] = el_copy;
- msg->elements[msg->num_elements-1].flags = flags;
-
- return LDB_SUCCESS;
-}
-
-/*
- add a value to a message
-*/
-int ldb_msg_add_value(struct ldb_message *msg,
- const char *attr_name,
- const struct ldb_val *val,
- struct ldb_message_element **return_el)
-{
- struct ldb_message_element *el;
- struct ldb_val *vals;
- int ret;
-
- el = ldb_msg_find_element(msg, attr_name);
- if (!el) {
- ret = ldb_msg_add_empty(msg, attr_name, 0, &el);
- if (ret != LDB_SUCCESS) {
- return ret;
- }
- }
-
- vals = talloc_realloc(msg, el->values, struct ldb_val, el->num_values+1);
- if (!vals) {
- errno = ENOMEM;
- return LDB_ERR_OPERATIONS_ERROR;
- }
- el->values = vals;
- el->values[el->num_values] = *val;
- el->num_values++;
-
- if (return_el) {
- *return_el = el;
- }
-
- return LDB_SUCCESS;
-}
-
-
-/*
- add a value to a message, stealing it into the 'right' place
-*/
-int ldb_msg_add_steal_value(struct ldb_message *msg,
- const char *attr_name,
- struct ldb_val *val)
-{
- int ret;
- struct ldb_message_element *el;
-
- ret = ldb_msg_add_value(msg, attr_name, val, &el);
- if (ret == LDB_SUCCESS) {
- talloc_steal(el->values, val->data);
- }
- return ret;
-}
-
-
-/*
- add a string element to a message
-*/
-int ldb_msg_add_string(struct ldb_message *msg,
- const char *attr_name, const char *str)
-{
- struct ldb_val val;
-
- val.data = discard_const_p(uint8_t, str);
- val.length = strlen(str);
-
- if (val.length == 0) {
- /* allow empty strings as non-existant attributes */
- return LDB_SUCCESS;
- }
-
- return ldb_msg_add_value(msg, attr_name, &val, NULL);
-}
-
-/*
- add a string element to a message, stealing it into the 'right' place
-*/
-int ldb_msg_add_steal_string(struct ldb_message *msg,
- const char *attr_name, char *str)
-{
- struct ldb_val val;
-
- val.data = (uint8_t *)str;
- val.length = strlen(str);
-
- return ldb_msg_add_steal_value(msg, attr_name, &val);
-}
-
-/*
- add a printf formatted element to a message
-*/
-int ldb_msg_add_fmt(struct ldb_message *msg,
- const char *attr_name, const char *fmt, ...)
-{
- struct ldb_val val;
- va_list ap;
- char *str;
-
- va_start(ap, fmt);
- str = talloc_vasprintf(msg, fmt, ap);
- va_end(ap);
-
- if (str == NULL) return LDB_ERR_OPERATIONS_ERROR;
-
- val.data = (uint8_t *)str;
- val.length = strlen(str);
-
- return ldb_msg_add_steal_value(msg, attr_name, &val);
-}
-
-/*
- compare two ldb_message_element structures
- assumes case senistive comparison
-*/
-int ldb_msg_element_compare(struct ldb_message_element *el1,
- struct ldb_message_element *el2)
-{
- unsigned int i;
-
- if (el1->num_values != el2->num_values) {
- return el1->num_values - el2->num_values;
- }
-
- for (i=0;i<el1->num_values;i++) {
- if (!ldb_msg_find_val(el2, &el1->values[i])) {
- return -1;
- }
- }
-
- return 0;
-}
-
-/*
- compare two ldb_message_element structures
- comparing by element name
-*/
-int ldb_msg_element_compare_name(struct ldb_message_element *el1,
- struct ldb_message_element *el2)
-{
- return ldb_attr_cmp(el1->name, el2->name);
-}
-
-/*
- convenience functions to return common types from a message
- these return the first value if the attribute is multi-valued
-*/
-const struct ldb_val *ldb_msg_find_ldb_val(const struct ldb_message *msg,
- const char *attr_name)
-{
- struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name);
- if (!el || el->num_values == 0) {
- return NULL;
- }
- return &el->values[0];
-}
-
-int ldb_msg_find_attr_as_int(const struct ldb_message *msg,
- const char *attr_name,
- int default_value)
-{
- const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
- if (!v || !v->data) {
- return default_value;
- }
- return strtol((const char *)v->data, NULL, 0);
-}
-
-unsigned int ldb_msg_find_attr_as_uint(const struct ldb_message *msg,
- const char *attr_name,
- unsigned int default_value)
-{
- const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
- if (!v || !v->data) {
- return default_value;
- }
- return strtoul((const char *)v->data, NULL, 0);
-}
-
-int64_t ldb_msg_find_attr_as_int64(const struct ldb_message *msg,
- const char *attr_name,
- int64_t default_value)
-{
- const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
- if (!v || !v->data) {
- return default_value;
- }
- return strtoll((const char *)v->data, NULL, 0);
-}
-
-uint64_t ldb_msg_find_attr_as_uint64(const struct ldb_message *msg,
- const char *attr_name,
- uint64_t default_value)
-{
- const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
- if (!v || !v->data) {
- return default_value;
- }
- return strtoull((const char *)v->data, NULL, 0);
-}
-
-double ldb_msg_find_attr_as_double(const struct ldb_message *msg,
- const char *attr_name,
- double default_value)
-{
- const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
- if (!v || !v->data) {
- return default_value;
- }
- return strtod((const char *)v->data, NULL);
-}
-
-int ldb_msg_find_attr_as_bool(const struct ldb_message *msg,
- const char *attr_name,
- int default_value)
-{
- const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
- if (!v || !v->data) {
- return default_value;
- }
- if (v->length == 5 && strncasecmp((const char *)v->data, "FALSE", 5) == 0) {
- return 0;
- }
- if (v->length == 4 && strncasecmp((const char *)v->data, "TRUE", 4) == 0) {
- return 1;
- }
- return default_value;
-}
-
-const char *ldb_msg_find_attr_as_string(const struct ldb_message *msg,
- const char *attr_name,
- const char *default_value)
-{
- const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
- if (!v || !v->data) {
- return default_value;
- }
- return (const char *)v->data;
-}
-
-struct ldb_dn *ldb_msg_find_attr_as_dn(struct ldb_context *ldb,
- void *mem_ctx,
- const struct ldb_message *msg,
- const char *attr_name)
-{
- struct ldb_dn *res_dn;
- const struct ldb_val *v;
-
- v = ldb_msg_find_ldb_val(msg, attr_name);
- if (!v || !v->data) {
- return NULL;
- }
- res_dn = ldb_dn_from_ldb_val(mem_ctx, ldb, v);
- if ( ! ldb_dn_validate(res_dn)) {
- talloc_free(res_dn);
- return NULL;
- }
- return res_dn;
-}
-
-/*
- sort the elements of a message by name
-*/
-void ldb_msg_sort_elements(struct ldb_message *msg)
-{
- qsort(msg->elements, msg->num_elements, sizeof(struct ldb_message_element),
- (comparison_fn_t)ldb_msg_element_compare_name);
-}
-
-/*
- shallow copy a message - copying only the elements array so that the caller
- can safely add new elements without changing the message
-*/
-struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx,
- const struct ldb_message *msg)
-{
- struct ldb_message *msg2;
- int i;
-
- msg2 = talloc(mem_ctx, struct ldb_message);
- if (msg2 == NULL) return NULL;
-
- *msg2 = *msg;
-
- msg2->elements = talloc_array(msg2, struct ldb_message_element,
- msg2->num_elements);
- if (msg2->elements == NULL) goto failed;
-
- for (i=0;i<msg2->num_elements;i++) {
- msg2->elements[i] = msg->elements[i];
- }
-
- return msg2;
-
-failed:
- talloc_free(msg2);
- return NULL;
-}
-
-
-/*
- copy a message, allocating new memory for all parts
-*/
-struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx,
- const struct ldb_message *msg)
-{
- struct ldb_message *msg2;
- int i, j;
-
- msg2 = ldb_msg_copy_shallow(mem_ctx, msg);
- if (msg2 == NULL) return NULL;
-
- msg2->dn = ldb_dn_copy(msg2, msg2->dn);
- if (msg2->dn == NULL) goto failed;
-
- for (i=0;i<msg2->num_elements;i++) {
- struct ldb_message_element *el = &msg2->elements[i];
- struct ldb_val *values = el->values;
- el->name = talloc_strdup(msg2->elements, el->name);
- if (el->name == NULL) goto failed;
- el->values = talloc_array(msg2->elements, struct ldb_val, el->num_values);
- for (j=0;j<el->num_values;j++) {
- el->values[j] = ldb_val_dup(el->values, &values[j]);
- if (el->values[j].data == NULL && values[j].length != 0) {
- goto failed;
- }
- }
- }
-
- return msg2;
-
-failed:
- talloc_free(msg2);
- return NULL;
-}
-
-
-/*
- canonicalise a message, merging elements of the same name
-*/
-struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb,
- const struct ldb_message *msg)
-{
- int i;
- struct ldb_message *msg2;
-
- msg2 = ldb_msg_copy(ldb, msg);
- if (msg2 == NULL) return NULL;
-
- ldb_msg_sort_elements(msg2);
-
- for (i=1;i<msg2->num_elements;i++) {
- struct ldb_message_element *el1 = &msg2->elements[i-1];
- struct ldb_message_element *el2 = &msg2->elements[i];
- if (ldb_msg_element_compare_name(el1, el2) == 0) {
- el1->values = talloc_realloc(msg2->elements, el1->values, struct ldb_val,
- el1->num_values + el2->num_values);
- if (el1->values == NULL) {
- return NULL;
- }
- memcpy(el1->values + el1->num_values,
- el2->values,
- sizeof(struct ldb_val) * el2->num_values);
- el1->num_values += el2->num_values;
- talloc_free(discard_const_p(char, el2->name));
- if (i+1<msg2->num_elements) {
- memmove(el2, el2+1, sizeof(struct ldb_message_element) *
- (msg2->num_elements - (i+1)));
- }
- msg2->num_elements--;
- i--;
- }
- }
-
- return msg2;
-}
-
-
-/*
- return a ldb_message representing the differences between msg1 and msg2. If you
- then use this in a ldb_modify() call it can be used to save edits to a message
-*/
-struct ldb_message *ldb_msg_diff(struct ldb_context *ldb,
- struct ldb_message *msg1,
- struct ldb_message *msg2)
-{
- struct ldb_message *mod;
- struct ldb_message_element *el;
- unsigned int i;
-
- mod = ldb_msg_new(ldb);
-
- mod->dn = msg1->dn;
- mod->num_elements = 0;
- mod->elements = NULL;
-
- msg2 = ldb_msg_canonicalize(ldb, msg2);
- if (msg2 == NULL) {
- return NULL;
- }
-
- /* look in msg2 to find elements that need to be added
- or modified */
- for (i=0;i<msg2->num_elements;i++) {
- el = ldb_msg_find_element(msg1, msg2->elements[i].name);
-
- if (el && ldb_msg_element_compare(el, &msg2->elements[i]) == 0) {
- continue;
- }
-
- if (ldb_msg_add(mod,
- &msg2->elements[i],
- el?LDB_FLAG_MOD_REPLACE:LDB_FLAG_MOD_ADD) != 0) {
- return NULL;
- }
- }
-
- /* look in msg1 to find elements that need to be deleted */
- for (i=0;i<msg1->num_elements;i++) {
- el = ldb_msg_find_element(msg2, msg1->elements[i].name);
- if (!el) {
- if (ldb_msg_add_empty(mod,
- msg1->elements[i].name,
- LDB_FLAG_MOD_DELETE, NULL) != 0) {
- return NULL;
- }
- }
- }
-
- return mod;
-}
-
-int ldb_msg_sanity_check(struct ldb_context *ldb,
- const struct ldb_message *msg)
-{
- int i, j;
-
- /* basic check on DN */
- if (msg->dn == NULL) {
- /* TODO: return also an error string */
- ldb_set_errstring(ldb, "ldb message lacks a DN!");
- return LDB_ERR_INVALID_DN_SYNTAX;
- }
-
- /* basic syntax checks */
- for (i = 0; i < msg->num_elements; i++) {
- for (j = 0; j < msg->elements[i].num_values; j++) {
- if (msg->elements[i].values[j].length == 0) {
- TALLOC_CTX *mem_ctx = talloc_new(ldb);
- /* an attribute cannot be empty */
- /* TODO: return also an error string */
- ldb_asprintf_errstring(ldb, "Element %s has empty attribute in ldb message (%s)!",
- msg->elements[i].name,
- ldb_dn_get_linearized(msg->dn));
- talloc_free(mem_ctx);
- return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
- }
- }
- }
-
- return LDB_SUCCESS;
-}
-
-
-
-
-/*
- copy an attribute list. This only copies the array, not the elements
- (ie. the elements are left as the same pointers)
-*/
-const char **ldb_attr_list_copy(TALLOC_CTX *mem_ctx, const char * const *attrs)
-{
- const char **ret;
- int i;
- for (i=0;attrs[i];i++) /* noop */ ;
- ret = talloc_array(mem_ctx, const char *, i+1);
- if (ret == NULL) {
- return NULL;
- }
- for (i=0;attrs[i];i++) {
- ret[i] = attrs[i];
- }
- ret[i] = attrs[i];
- return ret;
-}
-
-
-/*
- copy an attribute list. This only copies the array, not the elements
- (ie. the elements are left as the same pointers). The new attribute is added to the list.
-*/
-const char **ldb_attr_list_copy_add(TALLOC_CTX *mem_ctx, const char * const *attrs, const char *new_attr)
-{
- const char **ret;
- int i;
- bool found = false;
- for (i=0;attrs[i];i++) {
- if (ldb_attr_cmp(attrs[i], new_attr) == 0) {
- found = true;
- }
- }
- if (found) {
- return ldb_attr_list_copy(mem_ctx, attrs);
- }
- ret = talloc_array(mem_ctx, const char *, i+2);
- if (ret == NULL) {
- return NULL;
- }
- for (i=0;attrs[i];i++) {
- ret[i] = attrs[i];
- }
- ret[i] = new_attr;
- ret[i+1] = NULL;
- return ret;
-}
-
-
-/*
- return 1 if an attribute is in a list of attributes, or 0 otherwise
-*/
-int ldb_attr_in_list(const char * const *attrs, const char *attr)
-{
- int i;
- for (i=0;attrs && attrs[i];i++) {
- if (ldb_attr_cmp(attrs[i], attr) == 0) {
- return 1;
- }
- }
- return 0;
-}
-
-
-/*
- rename the specified attribute in a search result
-*/
-int ldb_msg_rename_attr(struct ldb_message *msg, const char *attr, const char *replace)
-{
- struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
- if (el == NULL) {
- return LDB_SUCCESS;
- }
- el->name = talloc_strdup(msg->elements, replace);
- if (el->name == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
- return LDB_SUCCESS;
-}
-
-
-/*
- copy the specified attribute in a search result to a new attribute
-*/
-int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *replace)
-{
- struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
- if (el == NULL) {
- return LDB_SUCCESS;
- }
- if (ldb_msg_add(msg, el, 0) != 0) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
- return ldb_msg_rename_attr(msg, attr, replace);
-}
-
-/*
- remove the specified element in a search result
-*/
-void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el)
-{
- int n = (el - msg->elements);
- if (n != msg->num_elements-1) {
- memmove(el, el+1, ((msg->num_elements-1) - n)*sizeof(*el));
- }
- msg->num_elements--;
-}
-
-
-/*
- remove the specified attribute in a search result
-*/
-void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr)
-{
- struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
- if (el) {
- ldb_msg_remove_element(msg, el);
- }
-}
-
-/*
- return a LDAP formatted GeneralizedTime string
-*/
-char *ldb_timestring(TALLOC_CTX *mem_ctx, time_t t)
-{
- struct tm *tm = gmtime(&t);
- char *ts;
- int r;
-
- if (!tm) {
- return NULL;
- }
-
- /* we now excatly how long this string will be */
- ts = talloc_array(mem_ctx, char, 18);
-
- /* formatted like: 20040408072012.0Z */
- r = snprintf(ts, 18,
- "%04u%02u%02u%02u%02u%02u.0Z",
- tm->tm_year+1900, tm->tm_mon+1,
- tm->tm_mday, tm->tm_hour, tm->tm_min,
- tm->tm_sec);
-
- if (r != 17) {
- talloc_free(ts);
- return NULL;
- }
-
- return ts;
-}
-
-/*
- convert a LDAP GeneralizedTime string to a time_t. Return 0 if unable to convert
-*/
-time_t ldb_string_to_time(const char *s)
-{
- struct tm tm;
-
- if (s == NULL) return 0;
-
- memset(&tm, 0, sizeof(tm));
- if (sscanf(s, "%04u%02u%02u%02u%02u%02u",
- &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
- &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
- return 0;
- }
- tm.tm_year -= 1900;
- tm.tm_mon -= 1;
-
- return timegm(&tm);
-}
-
-/*
- return a LDAP formatted UTCTime string
-*/
-char *ldb_timestring_utc(TALLOC_CTX *mem_ctx, time_t t)
-{
- struct tm *tm = gmtime(&t);
- char *ts;
- int r;
-
- if (!tm) {
- return NULL;
- }
-
- /* we now excatly how long this string will be */
- ts = talloc_array(mem_ctx, char, 14);
-
- /* formatted like: 20040408072012.0Z => 040408072012Z */
- r = snprintf(ts, 14,
- "%02u%02u%02u%02u%02u%02uZ",
- (tm->tm_year+1900)%100, tm->tm_mon+1,
- tm->tm_mday, tm->tm_hour, tm->tm_min,
- tm->tm_sec);
-
- if (r != 13) {
- talloc_free(ts);
- return NULL;
- }
-
- return ts;
-}
-
-/*
- convert a LDAP UTCTime string to a time_t. Return 0 if unable to convert
-*/
-time_t ldb_string_utc_to_time(const char *s)
-{
- struct tm tm;
-
- if (s == NULL) return 0;
-
- memset(&tm, 0, sizeof(tm));
- if (sscanf(s, "%02u%02u%02u%02u%02u%02u",
- &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
- &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
- return 0;
- }
- if (tm.tm_year < 50) {
- tm.tm_year += 100;
- }
- tm.tm_mon -= 1;
-
- return timegm(&tm);
-}
-
-
-/*
- dump a set of results to a file. Useful from within gdb
-*/
-void ldb_dump_results(struct ldb_context *ldb, struct ldb_result *result, FILE *f)
-{
- int i;
-
- for (i = 0; i < result->count; i++) {
- struct ldb_ldif ldif;
- fprintf(f, "# record %d\n", i+1);
- ldif.changetype = LDB_CHANGETYPE_NONE;
- ldif.msg = result->msgs[i];
- ldb_ldif_write_file(ldb, f, &ldif);
- }
-}
-
-int ldb_msg_check_string_attribute(const struct ldb_message *msg, const char *name, const char *value)
-{
- struct ldb_message_element *el;
- struct ldb_val val;
-
- el = ldb_msg_find_element(msg, name);
- if (el == NULL)
- return 0;
-
- val.data = discard_const_p(uint8_t, value);
- val.length = strlen(value);
-
- if (ldb_msg_find_val(el, &val))
- return 1;
-
- return 0;
-}
diff --git a/ldb/common/ldb_parse.c b/ldb/common/ldb_parse.c
deleted file mode 100644
index b2339752..00000000
--- a/ldb/common/ldb_parse.c
+++ /dev/null
@@ -1,819 +0,0 @@
-/*
- ldb database library
-
- Copyright (C) Andrew Tridgell 2004
-
- ** NOTE! The following LGPL license applies to the ldb
- ** library. This does NOT imply that all of Samba is released
- ** under the LGPL
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-/*
- * Name: ldb
- *
- * Component: ldb expression parsing
- *
- * Description: parse LDAP-like search expressions
- *
- * Author: Andrew Tridgell
- */
-
-/*
- TODO:
- - add RFC2254 binary string handling
- - possibly add ~=, <= and >= handling
- - expand the test suite
- - add better parse error handling
-
-*/
-
-#include "ldb_includes.h"
-#include "system/locale.h"
-
-/*
-a filter is defined by:
- <filter> ::= '(' <filtercomp> ')'
- <filtercomp> ::= <and> | <or> | <not> | <simple>
- <and> ::= '&' <filterlist>
- <or> ::= '|' <filterlist>
- <not> ::= '!' <filter>
- <filterlist> ::= <filter> | <filter> <filterlist>
- <simple> ::= <attributetype> <filtertype> <attributevalue>
- <filtertype> ::= '=' | '~=' | '<=' | '>='
-*/
-
-/*
- decode a RFC2254 binary string representation of a buffer.
- Used in LDAP filters.
-*/
-struct ldb_val ldb_binary_decode(void *mem_ctx, const char *str)
-{
- int i, j;
- struct ldb_val ret;
- int slen = str?strlen(str):0;
-
- ret.data = (uint8_t *)talloc_size(mem_ctx, slen+1);
- ret.length = 0;
- if (ret.data == NULL) return ret;
-
- for (i=j=0;i<slen;i++) {
- if (str[i] == '\\') {
- unsigned c;
- if (sscanf(&str[i+1], "%02X", &c) != 1) {
- talloc_free(ret.data);
- memset(&ret, 0, sizeof(ret));
- return ret;
- }
- ((uint8_t *)ret.data)[j++] = c;
- i += 2;
- } else {
- ((uint8_t *)ret.data)[j++] = str[i];
- }
- }
- ret.length = j;
- ((uint8_t *)ret.data)[j] = 0;
-
- return ret;
-}
-
-
-/*
- encode a blob as a RFC2254 binary string, escaping any
- non-printable or '\' characters
-*/
-char *ldb_binary_encode(void *mem_ctx, struct ldb_val val)
-{
- int i;
- char *ret;
- int len = val.length;
- unsigned char *buf = val.data;
-
- for (i=0;i<val.length;i++) {
- if (!isprint(buf[i]) || strchr(" *()\\&|!\"", buf[i])) {
- len += 2;
- }
- }
- ret = talloc_array(mem_ctx, char, len+1);
- if (ret == NULL) return NULL;
-
- len = 0;
- for (i=0;i<val.length;i++) {
- if (!isprint(buf[i]) || strchr(" *()\\&|!\"", buf[i])) {
- snprintf(ret+len, 4, "\\%02X", buf[i]);
- len += 3;
- } else {
- ret[len++] = buf[i];
- }
- }
-
- ret[len] = 0;
-
- return ret;
-}
-
-/*
- encode a string as a RFC2254 binary string, escaping any
- non-printable or '\' characters. This routine is suitable for use
- in escaping user data in ldap filters.
-*/
-char *ldb_binary_encode_string(void *mem_ctx, const char *string)
-{
- struct ldb_val val;
- val.data = discard_const_p(uint8_t, string);
- val.length = strlen(string);
- return ldb_binary_encode(mem_ctx, val);
-}
-
-/* find the first matching wildcard */
-static char *ldb_parse_find_wildcard(char *value)
-{
- while (*value) {
- value = strpbrk(value, "\\*");
- if (value == NULL) return NULL;
-
- if (value[0] == '\\') {
- if (value[1] == '\0') return NULL;
- value += 2;
- continue;
- }
-
- if (value[0] == '*') return value;
- }
-
- return NULL;
-}
-
-/* return a NULL terminated list of binary strings representing the value
- chunks separated by wildcards that makes the value portion of the filter
-*/
-static struct ldb_val **ldb_wildcard_decode(void *mem_ctx, const char *string)
-{
- struct ldb_val **ret = NULL;
- int val = 0;
- char *wc, *str;
-
- wc = talloc_strdup(mem_ctx, string);
- if (wc == NULL) return NULL;
-
- while (wc && *wc) {
- str = wc;
- wc = ldb_parse_find_wildcard(str);
- if (wc && *wc) {
- if (wc == str) {
- wc++;
- continue;
- }
- *wc = 0;
- wc++;
- }
-
- ret = talloc_realloc(mem_ctx, ret, struct ldb_val *, val + 2);
- if (ret == NULL) return NULL;
-
- ret[val] = talloc(mem_ctx, struct ldb_val);
- if (ret[val] == NULL) return NULL;
-
- *(ret[val]) = ldb_binary_decode(mem_ctx, str);
- if ((ret[val])->data == NULL) return NULL;
-
- val++;
- }
-
- if (ret != NULL) {
- ret[val] = NULL;
- }
-
- return ret;
-}
-
-static struct ldb_parse_tree *ldb_parse_filter(void *mem_ctx, const char **s);
-
-
-/*
- parse an extended match
-
- possible forms:
- (attr:oid:=value)
- (attr:dn:oid:=value)
- (attr:dn:=value)
- (:dn:oid:=value)
-
- the ':dn' part sets the dnAttributes boolean if present
- the oid sets the rule_id string
-
-*/
-static struct ldb_parse_tree *ldb_parse_extended(struct ldb_parse_tree *ret,
- char *attr, char *value)
-{
- char *p1, *p2;
-
- ret->operation = LDB_OP_EXTENDED;
- ret->u.extended.value = ldb_binary_decode(ret, value);
- if (ret->u.extended.value.data == NULL) goto failed;
-
- p1 = strchr(attr, ':');
- if (p1 == NULL) goto failed;
- p2 = strchr(p1+1, ':');
-
- *p1 = 0;
- if (p2) *p2 = 0;
-
- ret->u.extended.attr = attr;
- if (strcmp(p1+1, "dn") == 0) {
- ret->u.extended.dnAttributes = 1;
- if (p2) {
- ret->u.extended.rule_id = talloc_strdup(ret, p2+1);
- if (ret->u.extended.rule_id == NULL) goto failed;
- } else {
- ret->u.extended.rule_id = NULL;
- }
- } else {
- ret->u.extended.dnAttributes = 0;
- ret->u.extended.rule_id = talloc_strdup(ret, p1+1);
- if (ret->u.extended.rule_id == NULL) goto failed;
- }
-
- return ret;
-
-failed:
- talloc_free(ret);
- return NULL;
-}
-
-static enum ldb_parse_op ldb_parse_filtertype(void *mem_ctx, char **type, char **value, const char **s)
-{
- enum ldb_parse_op filter = 0;
- char *name, *val, *k;
- const char *p = *s;
- const char *t, *t1;
-
- /* retrieve attributetype name */
- t = p;
-
- if (*p == '@') { /* for internal attributes the first char can be @ */
- p++;
- }
-
- while ((isascii(*p) && isalnum((unsigned char)*p)) || (*p == '-')) { /* attribute names can only be alphanums */
- p++;
- }
-
- if (*p == ':') { /* but extended searches have : and . chars too */
- p = strstr(p, ":=");
- if (p == NULL) { /* malformed attribute name */
- return 0;
- }
- }
-
- t1 = p;
-
- while (isspace((unsigned char)*p)) p++;
-
- if (!strchr("=<>~:", *p)) {
- return 0;
- }
-
- /* save name */
- name = (char *)talloc_memdup(mem_ctx, t, t1 - t + 1);
- if (name == NULL) return 0;
- name[t1 - t] = '\0';
-
- /* retrieve filtertype */
-
- if (*p == '=') {
- filter = LDB_OP_EQUALITY;
- } else if (*(p + 1) == '=') {
- switch (*p) {
- case '<':
- filter = LDB_OP_LESS;
- p++;
- break;
- case '>':
- filter = LDB_OP_GREATER;
- p++;
- break;
- case '~':
- filter = LDB_OP_APPROX;
- p++;
- break;
- case ':':
- filter = LDB_OP_EXTENDED;
- p++;
- break;
- }
- }
- if (!filter) {
- talloc_free(name);
- return filter;
- }
- p++;
-
- while (isspace((unsigned char)*p)) p++;
-
- /* retrieve value */
- t = p;
-
- while (*p && ((*p != ')') || ((*p == ')') && (*(p - 1) == '\\')))) p++;
-
- val = (char *)talloc_memdup(mem_ctx, t, p - t + 1);
- if (val == NULL) {
- talloc_free(name);
- return 0;
- }
- val[p - t] = '\0';
-
- k = &(val[p - t]);
-
- /* remove trailing spaces from value */
- while ((k > val) && (isspace((unsigned char)*(k - 1)))) k--;
- *k = '\0';
-
- *type = name;
- *value = val;
- *s = p;
- return filter;
-}
-
-/*
- <simple> ::= <attributetype> <filtertype> <attributevalue>
-*/
-static struct ldb_parse_tree *ldb_parse_simple(void *mem_ctx, const char **s)
-{
- char *attr, *value;
- struct ldb_parse_tree *ret;
- enum ldb_parse_op filtertype;
-
- ret = talloc(mem_ctx, struct ldb_parse_tree);
- if (!ret) {
- errno = ENOMEM;
- return NULL;
- }
-
- filtertype = ldb_parse_filtertype(ret, &attr, &value, s);
- if (!filtertype) {
- talloc_free(ret);
- return NULL;
- }
-
- switch (filtertype) {
-
- case LDB_OP_PRESENT:
- ret->operation = LDB_OP_PRESENT;
- ret->u.present.attr = attr;
- break;
-
- case LDB_OP_EQUALITY:
-
- if (strcmp(value, "*") == 0) {
- ret->operation = LDB_OP_PRESENT;
- ret->u.present.attr = attr;
- break;
- }
-
- if (ldb_parse_find_wildcard(value) != NULL) {
- ret->operation = LDB_OP_SUBSTRING;
- ret->u.substring.attr = attr;
- ret->u.substring.start_with_wildcard = 0;
- ret->u.substring.end_with_wildcard = 0;
- ret->u.substring.chunks = ldb_wildcard_decode(ret, value);
- if (ret->u.substring.chunks == NULL){
- talloc_free(ret);
- return NULL;
- }
- if (value[0] == '*')
- ret->u.substring.start_with_wildcard = 1;
- if (value[strlen(value) - 1] == '*')
- ret->u.substring.end_with_wildcard = 1;
- talloc_free(value);
-
- break;
- }
-
- ret->operation = LDB_OP_EQUALITY;
- ret->u.equality.attr = attr;
- ret->u.equality.value = ldb_binary_decode(ret, value);
- if (ret->u.equality.value.data == NULL) {
- talloc_free(ret);
- return NULL;
- }
- talloc_free(value);
- break;
-
- case LDB_OP_GREATER:
- ret->operation = LDB_OP_GREATER;
- ret->u.comparison.attr = attr;
- ret->u.comparison.value = ldb_binary_decode(ret, value);
- if (ret->u.comparison.value.data == NULL) {
- talloc_free(ret);
- return NULL;
- }
- talloc_free(value);
- break;
-
- case LDB_OP_LESS:
- ret->operation = LDB_OP_LESS;
- ret->u.comparison.attr = attr;
- ret->u.comparison.value = ldb_binary_decode(ret, value);
- if (ret->u.comparison.value.data == NULL) {
- talloc_free(ret);
- return NULL;
- }
- talloc_free(value);
- break;
-
- case LDB_OP_APPROX:
- ret->operation = LDB_OP_APPROX;
- ret->u.comparison.attr = attr;
- ret->u.comparison.value = ldb_binary_decode(ret, value);
- if (ret->u.comparison.value.data == NULL) {
- talloc_free(ret);
- return NULL;
- }
- talloc_free(value);
- break;
-
- case LDB_OP_EXTENDED:
-
- ret = ldb_parse_extended(ret, attr, value);
- break;
-
- default:
- talloc_free(ret);
- return NULL;
- }
-
- return ret;
-}
-
-
-/*
- parse a filterlist
- <and> ::= '&' <filterlist>
- <or> ::= '|' <filterlist>
- <filterlist> ::= <filter> | <filter> <filterlist>
-*/
-static struct ldb_parse_tree *ldb_parse_filterlist(void *mem_ctx, const char **s)
-{
- struct ldb_parse_tree *ret, *next;
- enum ldb_parse_op op;
- const char *p = *s;
-
- switch (*p) {
- case '&':
- op = LDB_OP_AND;
- break;
- case '|':
- op = LDB_OP_OR;
- break;
- default:
- return NULL;
- }
- p++;
-
- while (isspace((unsigned char)*p)) p++;
-
- ret = talloc(mem_ctx, struct ldb_parse_tree);
- if (!ret) {
- errno = ENOMEM;
- return NULL;
- }
-
- ret->operation = op;
- ret->u.list.num_elements = 1;
- ret->u.list.elements = talloc(ret, struct ldb_parse_tree *);
- if (!ret->u.list.elements) {
- errno = ENOMEM;
- talloc_free(ret);
- return NULL;
- }
-
- ret->u.list.elements[0] = ldb_parse_filter(ret->u.list.elements, &p);
- if (!ret->u.list.elements[0]) {
- talloc_free(ret);
- return NULL;
- }
-
- while (isspace((unsigned char)*p)) p++;
-
- while (*p && (next = ldb_parse_filter(ret->u.list.elements, &p))) {
- struct ldb_parse_tree **e;
- e = talloc_realloc(ret, ret->u.list.elements,
- struct ldb_parse_tree *,
- ret->u.list.num_elements + 1);
- if (!e) {
- errno = ENOMEM;
- talloc_free(ret);
- return NULL;
- }
- ret->u.list.elements = e;
- ret->u.list.elements[ret->u.list.num_elements] = next;
- ret->u.list.num_elements++;
- while (isspace((unsigned char)*p)) p++;
- }
-
- *s = p;
-
- return ret;
-}
-
-
-/*
- <not> ::= '!' <filter>
-*/
-static struct ldb_parse_tree *ldb_parse_not(void *mem_ctx, const char **s)
-{
- struct ldb_parse_tree *ret;
- const char *p = *s;
-
- if (*p != '!') {
- return NULL;
- }
- p++;
-
- ret = talloc(mem_ctx, struct ldb_parse_tree);
- if (!ret) {
- errno = ENOMEM;
- return NULL;
- }
-
- ret->operation = LDB_OP_NOT;
- ret->u.isnot.child = ldb_parse_filter(ret, &p);
- if (!ret->u.isnot.child) {
- talloc_free(ret);
- return NULL;
- }
-
- *s = p;
-
- return ret;
-}
-
-/*
- parse a filtercomp
- <filtercomp> ::= <and> | <or> | <not> | <simple>
-*/
-static struct ldb_parse_tree *ldb_parse_filtercomp(void *mem_ctx, const char **s)
-{
- struct ldb_parse_tree *ret;
- const char *p = *s;
-
- while (isspace((unsigned char)*p)) p++;
-
- switch (*p) {
- case '&':
- ret = ldb_parse_filterlist(mem_ctx, &p);
- break;
-
- case '|':
- ret = ldb_parse_filterlist(mem_ctx, &p);
- break;
-
- case '!':
- ret = ldb_parse_not(mem_ctx, &p);
- break;
-
- case '(':
- case ')':
- return NULL;
-
- default:
- ret = ldb_parse_simple(mem_ctx, &p);
-
- }
-
- *s = p;
- return ret;
-}
-
-
-/*
- <filter> ::= '(' <filtercomp> ')'
-*/
-static struct ldb_parse_tree *ldb_parse_filter(void *mem_ctx, const char **s)
-{
- struct ldb_parse_tree *ret;
- const char *p = *s;
-
- if (*p != '(') {
- return NULL;
- }
- p++;
-
- ret = ldb_parse_filtercomp(mem_ctx, &p);
-
- if (*p != ')') {
- return NULL;
- }
- p++;
-
- while (isspace((unsigned char)*p)) {
- p++;
- }
-
- *s = p;
-
- return ret;
-}
-
-
-/*
- main parser entry point. Takes a search string and returns a parse tree
-
- expression ::= <simple> | <filter>
-*/
-struct ldb_parse_tree *ldb_parse_tree(void *mem_ctx, const char *s)
-{
- if (s == NULL || *s == 0) {
- s = "(|(objectClass=*)(distinguishedName=*))";
- }
-
- while (isspace((unsigned char)*s)) s++;
-
- if (*s == '(') {
- return ldb_parse_filter(mem_ctx, &s);
- }
-
- return ldb_parse_simple(mem_ctx, &s);
-}
-
-
-/*
- construct a ldap parse filter given a parse tree
-*/
-char *ldb_filter_from_tree(void *mem_ctx, struct ldb_parse_tree *tree)
-{
- char *s, *s2, *ret;
- int i;
-
- if (tree == NULL) {
- return NULL;
- }
-
- switch (tree->operation) {
- case LDB_OP_AND:
- case LDB_OP_OR:
- ret = talloc_asprintf(mem_ctx, "(%c", tree->operation==LDB_OP_AND?'&':'|');
- if (ret == NULL) return NULL;
- for (i=0;i<tree->u.list.num_elements;i++) {
- s = ldb_filter_from_tree(mem_ctx, tree->u.list.elements[i]);
- if (s == NULL) {
- talloc_free(ret);
- return NULL;
- }
- s2 = talloc_asprintf_append(ret, "%s", s);
- talloc_free(s);
- if (s2 == NULL) {
- talloc_free(ret);
- return NULL;
- }
- ret = s2;
- }
- s = talloc_asprintf_append(ret, ")");
- if (s == NULL) {
- talloc_free(ret);
- return NULL;
- }
- return s;
- case LDB_OP_NOT:
- s = ldb_filter_from_tree(mem_ctx, tree->u.isnot.child);
- if (s == NULL) return NULL;
-
- ret = talloc_asprintf(mem_ctx, "(!%s)", s);
- talloc_free(s);
- return ret;
- case LDB_OP_EQUALITY:
- s = ldb_binary_encode(mem_ctx, tree->u.equality.value);
- if (s == NULL) return NULL;
- ret = talloc_asprintf(mem_ctx, "(%s=%s)",
- tree->u.equality.attr, s);
- talloc_free(s);
- return ret;
- case LDB_OP_SUBSTRING:
- ret = talloc_asprintf(mem_ctx, "(%s=%s", tree->u.substring.attr,
- tree->u.substring.start_with_wildcard?"*":"");
- if (ret == NULL) return NULL;
- for (i = 0; tree->u.substring.chunks[i]; i++) {
- s2 = ldb_binary_encode(mem_ctx, *(tree->u.substring.chunks[i]));
- if (s2 == NULL) {
- talloc_free(ret);
- return NULL;
- }
- if (tree->u.substring.chunks[i+1] ||
- tree->u.substring.end_with_wildcard) {
- s = talloc_asprintf_append(ret, "%s*", s2);
- } else {
- s = talloc_asprintf_append(ret, "%s", s2);
- }
- if (s == NULL) {
- talloc_free(ret);
- return NULL;
- }
- ret = s;
- }
- s = talloc_asprintf_append(ret, ")");
- if (s == NULL) {
- talloc_free(ret);
- return NULL;
- }
- ret = s;
- return ret;
- case LDB_OP_GREATER:
- s = ldb_binary_encode(mem_ctx, tree->u.equality.value);
- if (s == NULL) return NULL;
- ret = talloc_asprintf(mem_ctx, "(%s>=%s)",
- tree->u.equality.attr, s);
- talloc_free(s);
- return ret;
- case LDB_OP_LESS:
- s = ldb_binary_encode(mem_ctx, tree->u.equality.value);
- if (s == NULL) return NULL;
- ret = talloc_asprintf(mem_ctx, "(%s<=%s)",
- tree->u.equality.attr, s);
- talloc_free(s);
- return ret;
- case LDB_OP_PRESENT:
- ret = talloc_asprintf(mem_ctx, "(%s=*)", tree->u.present.attr);
- return ret;
- case LDB_OP_APPROX:
- s = ldb_binary_encode(mem_ctx, tree->u.equality.value);
- if (s == NULL) return NULL;
- ret = talloc_asprintf(mem_ctx, "(%s~=%s)",
- tree->u.equality.attr, s);
- talloc_free(s);
- return ret;
- case LDB_OP_EXTENDED:
- s = ldb_binary_encode(mem_ctx, tree->u.extended.value);
- if (s == NULL) return NULL;
- ret = talloc_asprintf(mem_ctx, "(%s%s%s%s:=%s)",
- tree->u.extended.attr?tree->u.extended.attr:"",
- tree->u.extended.dnAttributes?":dn":"",
- tree->u.extended.rule_id?":":"",
- tree->u.extended.rule_id?tree->u.extended.rule_id:"",
- s);
- talloc_free(s);
- return ret;
- }
-
- return NULL;
-}
-
-
-/*
- replace any occurances of an attribute name in the parse tree with a
- new name
-*/
-void ldb_parse_tree_attr_replace(struct ldb_parse_tree *tree,
- const char *attr,
- const char *replace)
-{
- int i;
- switch (tree->operation) {
- case LDB_OP_AND:
- case LDB_OP_OR:
- for (i=0;i<tree->u.list.num_elements;i++) {
- ldb_parse_tree_attr_replace(tree->u.list.elements[i],
- attr, replace);
- }
- break;
- case LDB_OP_NOT:
- ldb_parse_tree_attr_replace(tree->u.isnot.child, attr, replace);
- break;
- case LDB_OP_EQUALITY:
- case LDB_OP_GREATER:
- case LDB_OP_LESS:
- case LDB_OP_APPROX:
- if (ldb_attr_cmp(tree->u.equality.attr, attr) == 0) {
- tree->u.equality.attr = replace;
- }
- break;
- case LDB_OP_SUBSTRING:
- if (ldb_attr_cmp(tree->u.substring.attr, attr) == 0) {
- tree->u.substring.attr = replace;
- }
- break;
- case LDB_OP_PRESENT:
- if (ldb_attr_cmp(tree->u.present.attr, attr) == 0) {
- tree->u.present.attr = replace;
- }
- break;
- case LDB_OP_EXTENDED:
- if (tree->u.extended.attr &&
- ldb_attr_cmp(tree->u.extended.attr, attr) == 0) {
- tree->u.extended.attr = replace;
- }
- break;
- }
-}
diff --git a/ldb/common/ldb_utf8.c b/ldb/common/ldb_utf8.c
deleted file mode 100644
index 69ee2b69..00000000
--- a/ldb/common/ldb_utf8.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- ldb database library
-
- Copyright (C) Andrew Tridgell 2004
-
- ** NOTE! The following LGPL license applies to the ldb
- ** library. This does NOT imply that all of Samba is released
- ** under the LGPL
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-/*
- * Name: ldb
- *
- * Component: ldb utf8 handling
- *
- * Description: case folding and case comparison for UTF8 strings
- *
- * Author: Andrew Tridgell
- */
-
-#include "ldb_includes.h"
-#include "system/locale.h"
-
-
-/*
- this allow the user to pass in a caseless comparison
- function to handle utf8 caseless comparisons
- */
-void ldb_set_utf8_fns(struct ldb_context *ldb,
- void *context,
- char *(*casefold)(void *, void *, const char *, size_t))
-{
- if (context)
- ldb->utf8_fns.context = context;
- if (casefold)
- ldb->utf8_fns.casefold = casefold;
-}
-
-/*
- a simple case folding function
- NOTE: does not handle UTF8
-*/
-char *ldb_casefold_default(void *context, void *mem_ctx, const char *s, size_t n)
-{
- int i;
- char *ret = talloc_strndup(mem_ctx, s, n);
- if (!s) {
- errno = ENOMEM;
- return NULL;
- }
- for (i=0;ret[i];i++) {
- ret[i] = toupper((unsigned char)ret[i]);
- }
- return ret;
-}
-
-void ldb_set_utf8_default(struct ldb_context *ldb)
-{
- ldb_set_utf8_fns(ldb, NULL, ldb_casefold_default);
-}
-
-char *ldb_casefold(struct ldb_context *ldb, void *mem_ctx, const char *s, size_t n)
-{
- return ldb->utf8_fns.casefold(ldb->utf8_fns.context, mem_ctx, s, n);
-}
-
-/*
- check the attribute name is valid according to rfc2251
- returns 1 if the name is ok
- */
-
-int ldb_valid_attr_name(const char *s)
-{
- int i;
-
- if (!s || !s[0])
- return 0;
-
- /* handle special ldb_tdb wildcard */
- if (strcmp(s, "*") == 0) return 1;
-
- for (i = 0; s[i]; i++) {
- if (! isascii(s[i])) {
- return 0;
- }
- if (i == 0) { /* first char must be an alpha (or our special '@' identifier) */
- if (! (isalpha(s[i]) || (s[i] == '@'))) {
- return 0;
- }
- } else {
- if (! (isalnum(s[i]) || (s[i] == '-'))) {
- return 0;
- }
- }
- }
- return 1;
-}
-
-char *ldb_attr_casefold(void *mem_ctx, const char *s)
-{
- int i;
- char *ret = talloc_strdup(mem_ctx, s);
- if (!ret) {
- errno = ENOMEM;
- return NULL;
- }
- for (i = 0; ret[i]; i++) {
- ret[i] = toupper((unsigned char)ret[i]);
- }
- return ret;
-}
-
-/*
- we accept either 'dn' or 'distinguishedName' for a distinguishedName
-*/
-int ldb_attr_dn(const char *attr)
-{
- if (ldb_attr_cmp(attr, "dn") == 0 ||
- ldb_attr_cmp(attr, "distinguishedName") == 0) {
- return 0;
- }
- return -1;
-}
diff --git a/ldb/common/qsort.c b/ldb/common/qsort.c
deleted file mode 100644
index 0fa76d3b..00000000
--- a/ldb/common/qsort.c
+++ /dev/null
@@ -1,251 +0,0 @@
-/* Copyright (C) 1991,1992,1996,1997,1999,2004 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */
-
-/* If you consider tuning this algorithm, you should consult first:
- Engineering a sort function; Jon Bentley and M. Douglas McIlroy;
- Software - Practice and Experience; Vol. 23 (11), 1249-1265, 1993. */
-
-/* Modified to be used in samba4 by
- * Simo Sorce <idra@samba.org> 2005
- */
-
-#include "ldb_includes.h"
-
-/* Byte-wise swap two items of size SIZE. */
-#define SWAP(a, b, size) \
- do \
- { \
- register size_t __size = (size); \
- register char *__a = (a), *__b = (b); \
- do \
- { \
- char __tmp = *__a; \
- *__a++ = *__b; \
- *__b++ = __tmp; \
- } while (--__size > 0); \
- } while (0)
-
-/* Discontinue quicksort algorithm when partition gets below this size.
- This particular magic number was chosen to work best on a Sun 4/260. */
-#define MAX_THRESH 4
-
-/* Stack node declarations used to store unfulfilled partition obligations. */
-typedef struct
- {
- char *lo;
- char *hi;
- } stack_node;
-
-/* The next 4 #defines implement a very fast in-line stack abstraction. */
-/* The stack needs log (total_elements) entries (we could even subtract
- log(MAX_THRESH)). Since total_elements has type size_t, we get as
- upper bound for log (total_elements):
- bits per byte (CHAR_BIT) * sizeof(size_t). */
-#ifndef CHAR_BIT
-#define CHAR_BIT 8
-#endif
-#define STACK_SIZE (CHAR_BIT * sizeof(size_t))
-#define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
-#define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
-#define STACK_NOT_EMPTY (stack < top)
-
-
-/* Order size using quicksort. This implementation incorporates
- four optimizations discussed in Sedgewick:
-
- 1. Non-recursive, using an explicit stack of pointer that store the
- next array partition to sort. To save time, this maximum amount
- of space required to store an array of SIZE_MAX is allocated on the
- stack. Assuming a 32-bit (64 bit) integer for size_t, this needs
- only 32 * sizeof(stack_node) == 256 bytes (for 64 bit: 1024 bytes).
- Pretty cheap, actually.
-
- 2. Chose the pivot element using a median-of-three decision tree.
- This reduces the probability of selecting a bad pivot value and
- eliminates certain extraneous comparisons.
-
- 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
- insertion sort to order the MAX_THRESH items within each partition.
- This is a big win, since insertion sort is faster for small, mostly
- sorted array segments.
-
- 4. The larger of the two sub-partitions is always pushed onto the
- stack first, with the algorithm then concentrating on the
- smaller partition. This *guarantees* no more than log (total_elems)
- stack size is needed (actually O(1) in this case)! */
-
-void ldb_qsort (void *const pbase, size_t total_elems, size_t size,
- void *opaque, ldb_qsort_cmp_fn_t cmp)
-{
- register char *base_ptr = (char *) pbase;
-
- const size_t max_thresh = MAX_THRESH * size;
-
- if (total_elems == 0)
- /* Avoid lossage with unsigned arithmetic below. */
- return;
-
- if (total_elems > MAX_THRESH)
- {
- char *lo = base_ptr;
- char *hi = &lo[size * (total_elems - 1)];
- stack_node stack[STACK_SIZE];
- stack_node *top = stack;
-
- PUSH (NULL, NULL);
-
- while (STACK_NOT_EMPTY)
- {
- char *left_ptr;
- char *right_ptr;
-
- /* Select median value from among LO, MID, and HI. Rearrange
- LO and HI so the three values are sorted. This lowers the
- probability of picking a pathological pivot value and
- skips a comparison for both the LEFT_PTR and RIGHT_PTR in
- the while loops. */
-
- char *mid = lo + size * ((hi - lo) / size >> 1);
-
- if ((*cmp) ((void *) mid, (void *) lo, opaque) < 0)
- SWAP (mid, lo, size);
- if ((*cmp) ((void *) hi, (void *) mid, opaque) < 0)
- SWAP (mid, hi, size);
- else
- goto jump_over;
- if ((*cmp) ((void *) mid, (void *) lo, opaque) < 0)
- SWAP (mid, lo, size);
- jump_over:;
-
- left_ptr = lo + size;
- right_ptr = hi - size;
-
- /* Here's the famous ``collapse the walls'' section of quicksort.
- Gotta like those tight inner loops! They are the main reason
- that this algorithm runs much faster than others. */
- do
- {
- while ((*cmp) ((void *) left_ptr, (void *) mid, opaque) < 0)
- left_ptr += size;
-
- while ((*cmp) ((void *) mid, (void *) right_ptr, opaque) < 0)
- right_ptr -= size;
-
- if (left_ptr < right_ptr)
- {
- SWAP (left_ptr, right_ptr, size);
- if (mid == left_ptr)
- mid = right_ptr;
- else if (mid == right_ptr)
- mid = left_ptr;
- left_ptr += size;
- right_ptr -= size;
- }
- else if (left_ptr == right_ptr)
- {
- left_ptr += size;
- right_ptr -= size;
- break;
- }
- }
- while (left_ptr <= right_ptr);
-
- /* Set up pointers for next iteration. First determine whether
- left and right partitions are below the threshold size. If so,
- ignore one or both. Otherwise, push the larger partition's
- bounds on the stack and continue sorting the smaller one. */
-
- if ((size_t) (right_ptr - lo) <= max_thresh)
- {
- if ((size_t) (hi - left_ptr) <= max_thresh)
- /* Ignore both small partitions. */
- POP (lo, hi);
- else
- /* Ignore small left partition. */
- lo = left_ptr;
- }
- else if ((size_t) (hi - left_ptr) <= max_thresh)
- /* Ignore small right partition. */
- hi = right_ptr;
- else if ((right_ptr - lo) > (hi - left_ptr))
- {
- /* Push larger left partition indices. */
- PUSH (lo, right_ptr);
- lo = left_ptr;
- }
- else
- {
- /* Push larger right partition indices. */
- PUSH (left_ptr, hi);
- hi = right_ptr;
- }
- }
- }
-
- /* Once the BASE_PTR array is partially sorted by quicksort the rest
- is completely sorted using insertion sort, since this is efficient
- for partitions below MAX_THRESH size. BASE_PTR points to the beginning
- of the array to sort, and END_PTR points at the very last element in
- the array (*not* one beyond it!). */
-
-#define min(x, y) ((x) < (y) ? (x) : (y))
-
- {
- char *const end_ptr = &base_ptr[size * (total_elems - 1)];
- char *tmp_ptr = base_ptr;
- char *thresh = min(end_ptr, base_ptr + max_thresh);
- register char *run_ptr;
-
- /* Find smallest element in first threshold and place it at the
- array's beginning. This is the smallest array element,
- and the operation speeds up insertion sort's inner loop. */
-
- for (run_ptr = tmp_ptr + size; run_ptr <= thresh; run_ptr += size)
- if ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, opaque) < 0)
- tmp_ptr = run_ptr;
-
- if (tmp_ptr != base_ptr)
- SWAP (tmp_ptr, base_ptr, size);
-
- /* Insertion sort, running from left-hand-side up to right-hand-side. */
-
- run_ptr = base_ptr + size;
- while ((run_ptr += size) <= end_ptr)
- {
- tmp_ptr = run_ptr - size;
- while ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, opaque) < 0)
- tmp_ptr -= size;
-
- tmp_ptr += size;
- if (tmp_ptr != run_ptr)
- {
- char *trav;
-
- trav = run_ptr + size;
- while (--trav >= run_ptr)
- {
- char c = *trav;
- char *hi, *lo;
-
- for (hi = lo = trav; (lo -= size) >= tmp_ptr; hi = lo)
- *hi = *lo;
- *hi = c;
- }
- }
- }
- }
-}