summaryrefslogtreecommitdiffstats
path: root/ldb/common
diff options
context:
space:
mode:
authorSimo Sorce <ssorce@redhat.com>2009-02-25 16:43:57 -0500
committerSimo Sorce <ssorce@redhat.com>2009-02-26 09:13:32 -0500
commit77454c07ba109a3ea6af0da86ba954b28b1fd02f (patch)
tree5e5be00f9b77c42e697617acb9fd695f7c6a0e58 /ldb/common
parentc9f6d2795fde2f9bf80277d425df2b44bc860226 (diff)
downloadsssd-77454c07ba109a3ea6af0da86ba954b28b1fd02f.tar.gz
sssd-77454c07ba109a3ea6af0da86ba954b28b1fd02f.tar.xz
sssd-77454c07ba109a3ea6af0da86ba954b28b1fd02f.zip
Remove our copies of the samba libraries.
Packages are already available in debian unstable and will soon land in Fedora. See BUILD.TXT for details. We still keep libreplace as we still use its configure macros, until we find time to extract only waht we need and have our own macros.
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 5ec86b5b8..000000000
--- 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 c013565da..000000000
--- 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 001bc45ee..000000000
--- 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 6fad5012b..000000000
--- 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 0f78e37c1..000000000
--- 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 02e21a2b2..000000000
--- 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 619c10e11..000000000
--- 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 4cde739d6..000000000
--- 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 0fcdf937c..000000000
--- 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 2f5fe1d18..000000000
--- 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 b23397522..000000000
--- 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 69ee2b696..000000000
--- 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 0fa76d3b4..000000000
--- 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;
- }
- }
- }
- }
-}