From fc336590dc35f1737ddc74333b959bdd32ee22d3 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 6 May 2010 10:41:43 +0200 Subject: Remove the copy of ldb from Samba 3. There were two utility functions that other parts of Samba 3 still relied on; they have been moved to lib/ldb_compat.[ch]. --- source3/lib/ldb/common/attrib_handlers.c | 405 ----------- source3/lib/ldb/common/ldb.c | 1136 ------------------------------ source3/lib/ldb/common/ldb_attributes.c | 308 -------- source3/lib/ldb/common/ldb_controls.c | 105 --- source3/lib/ldb/common/ldb_debug.c | 104 --- source3/lib/ldb/common/ldb_dn.c | 1050 --------------------------- source3/lib/ldb/common/ldb_ldif.c | 760 -------------------- source3/lib/ldb/common/ldb_match.c | 430 ----------- source3/lib/ldb/common/ldb_modules.c | 459 ------------ source3/lib/ldb/common/ldb_msg.c | 829 ---------------------- source3/lib/ldb/common/ldb_parse.c | 818 --------------------- source3/lib/ldb/common/ldb_utf8.c | 148 ---- source3/lib/ldb/common/qsort.c | 252 ------- 13 files changed, 6804 deletions(-) delete mode 100644 source3/lib/ldb/common/attrib_handlers.c delete mode 100644 source3/lib/ldb/common/ldb.c delete mode 100644 source3/lib/ldb/common/ldb_attributes.c delete mode 100644 source3/lib/ldb/common/ldb_controls.c delete mode 100644 source3/lib/ldb/common/ldb_debug.c delete mode 100644 source3/lib/ldb/common/ldb_dn.c delete mode 100644 source3/lib/ldb/common/ldb_ldif.c delete mode 100644 source3/lib/ldb/common/ldb_match.c delete mode 100644 source3/lib/ldb/common/ldb_modules.c delete mode 100644 source3/lib/ldb/common/ldb_msg.c delete mode 100644 source3/lib/ldb/common/ldb_parse.c delete mode 100644 source3/lib/ldb/common/ldb_utf8.c delete mode 100644 source3/lib/ldb/common/qsort.c (limited to 'source3/lib/ldb/common') diff --git a/source3/lib/ldb/common/attrib_handlers.c b/source3/lib/ldb/common/attrib_handlers.c deleted file mode 100644 index 5f26db6776..0000000000 --- a/source3/lib/ldb/common/attrib_handlers.c +++ /dev/null @@ -1,405 +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 . -*/ -/* - attribute handlers for well known attribute types, selected by syntax OID - see rfc2252 -*/ - -#include "includes.h" -#include "ldb/include/includes.h" -#include "system/locale.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 -*/ -static 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)); - 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 -*/ -static 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 -*/ -static 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 -*/ -static 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; - const char *u1, *u2; - char *b1, *b2; - int ret; - while (*s1 == ' ') s1++; - while (*s2 == ' ') s2++; - /* TODO: make utf8 safe, possibly with helper function from application */ - while (*s1 && *s2) { - /* 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]) s1++; - while (s2[0] == s2[1]) s2++; - } - s1++; s2++; - } - 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++; - while (*s2 == ' ') s2++; - } - 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); - b2 = ldb_casefold(ldb, mem_ctx, s2); - - 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 -*/ -static 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_explode_casefold(ldb, mem_ctx, (char *)in->data); - if (dn == NULL) { - return -1; - } - - out->data = (uint8_t *)ldb_dn_linearize(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 -*/ -static 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_explode_casefold(ldb, mem_ctx, (char *)v1->data); - if (dn1 == NULL) return -1; - - dn2 = ldb_dn_explode_casefold(ldb, mem_ctx, (char *)v2->data); - if (dn2 == NULL) { - talloc_free(dn1); - return -1; - } - - ret = ldb_dn_compare(ldb, dn1, dn2); - - talloc_free(dn1); - talloc_free(dn2); - return ret; -} - -/* - compare two objectclasses, looking at subclasses -*/ -static int ldb_comparison_objectclass(struct ldb_context *ldb, void *mem_ctx, - const struct ldb_val *v1, const struct ldb_val *v2) -{ - int ret, i; - const char **subclasses; - ret = ldb_comparison_fold(ldb, mem_ctx, v1, v2); - if (ret == 0) { - return 0; - } - subclasses = ldb_subclass_list(ldb, (char *)v1->data); - if (subclasses == NULL) { - return ret; - } - for (i=0;subclasses[i];i++) { - struct ldb_val vs; - vs.data = discard_const_p(uint8_t, subclasses[i]); - vs.length = strlen(subclasses[i]); - if (ldb_comparison_objectclass(ldb, mem_ctx, &vs, v2) == 0) { - return 0; - } - } - return ret; -} - -/* - compare two utc time values. 1 second resolution -*/ -static 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 -*/ -static 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_attrib_handler ldb_standard_attribs[] = { - { - .attr = LDB_SYNTAX_INTEGER, - .flags = 0, - .ldif_read_fn = ldb_handler_copy, - .ldif_write_fn = ldb_handler_copy, - .canonicalise_fn = ldb_canonicalise_Integer, - .comparison_fn = ldb_comparison_Integer - }, - { - .attr = LDB_SYNTAX_OCTET_STRING, - .flags = 0, - .ldif_read_fn = ldb_handler_copy, - .ldif_write_fn = ldb_handler_copy, - .canonicalise_fn = ldb_handler_copy, - .comparison_fn = ldb_comparison_binary - }, - { - .attr = LDB_SYNTAX_DIRECTORY_STRING, - .flags = 0, - .ldif_read_fn = ldb_handler_copy, - .ldif_write_fn = ldb_handler_copy, - .canonicalise_fn = ldb_handler_fold, - .comparison_fn = ldb_comparison_fold - }, - { - .attr = LDB_SYNTAX_DN, - .flags = 0, - .ldif_read_fn = ldb_handler_copy, - .ldif_write_fn = ldb_handler_copy, - .canonicalise_fn = ldb_canonicalise_dn, - .comparison_fn = ldb_comparison_dn - }, - { - .attr = LDB_SYNTAX_OBJECTCLASS, - .flags = 0, - .ldif_read_fn = ldb_handler_copy, - .ldif_write_fn = ldb_handler_copy, - .canonicalise_fn = ldb_handler_fold, - .comparison_fn = ldb_comparison_objectclass - }, - { - .attr = LDB_SYNTAX_UTC_TIME, - .flags = 0, - .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_attrib_handler *ldb_attrib_handler_syntax(struct ldb_context *ldb, - const char *syntax) -{ - int i; - unsigned num_handlers = sizeof(ldb_standard_attribs)/sizeof(ldb_standard_attribs[0]); - /* TODO: should be replaced with a binary search */ - for (i=0;i. -*/ - -/* - * Name: ldb - * - * Component: ldb core API - * - * Description: core API routines interfacing to ldb backends - * - * Author: Andrew Tridgell - */ - -#include "includes.h" -#include "ldb/include/includes.h" - -/* - initialise a ldb context - The mem_ctx is optional -*/ -struct ldb_context *ldb_init(void *mem_ctx, struct tevent_context *tev_ctx) -{ - struct ldb_context *ldb = talloc_zero(mem_ctx, struct ldb_context); - int ret; - - ret = ldb_setup_wellknown_attributes(ldb); - if (ret != 0) { - talloc_free(ldb); - return NULL; - } - - ldb_set_utf8_default(ldb); - ldb_set_create_perms(ldb, 0600); - - return ldb; -} - -static struct ldb_backend { - const char *name; - ldb_connect_fn connect_fn; - struct ldb_backend *prev, *next; -} *ldb_backends = NULL; - - -static ldb_connect_fn ldb_find_backend(const char *url) -{ - struct ldb_backend *backend; - - for (backend = ldb_backends; backend; backend = backend->next) { - if (strncmp(backend->name, url, strlen(backend->name)) == 0) { - return backend->connect_fn; - } - } - - return NULL; -} - -/* - register a new ldb backend -*/ -int ldb_register_backend(const char *url_prefix, ldb_connect_fn connectfn) -{ - struct ldb_backend *backend = talloc(talloc_autofree_context(), struct ldb_backend); - - 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; - DLIST_ADD(ldb_backends, backend); - - 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) { - if (ldb_try_load_dso(ldb, backend) == 0) { - fn = ldb_find_backend(backend); - } - } - - 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; -} - -/* - 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. -*/ -static const struct ldb_dn *ldb_set_default_basedn(struct ldb_context *ldb) -{ - TALLOC_CTX *tmp_ctx; - int ret; - static const char *attrs[] = { "defaultNamingContext", NULL }; - struct ldb_result *res; - struct ldb_dn *basedn=NULL; - - basedn = (struct ldb_dn *)ldb_get_opaque(ldb, "default_baseDN"); - if (basedn) { - return basedn; - } - - tmp_ctx = talloc_new(ldb); - ret = ldb_search(ldb, ldb, &res, ldb_dn_new(tmp_ctx, ldb, NULL), LDB_SCOPE_BASE, - attrs, "(objectClass=*)"); - if (ret == LDB_SUCCESS) { - if (res->count == 1) { - basedn = ldb_msg_find_attr_as_dn(ldb, res->msgs[0], "defaultNamingContext"); - ldb_set_opaque(ldb, "default_baseDN", basedn); - } - talloc_free(res); - } - - talloc_free(tmp_ctx); - return basedn; -} - -const struct ldb_dn *ldb_get_default_basedn(struct ldb_context *ldb) -{ - return (const struct ldb_dn *)ldb_get_opaque(ldb, "default_baseDN"); -} - -/* - 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; - - ldb->flags = flags; - - 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; - } - - /* TODO: get timeout from options if available there */ - ldb->default_timeout = 300; /* set default to 5 minutes */ - - /* set the default base dn */ - ldb_set_default_basedn(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; - - if (ldb->err_string) { - talloc_free(ldb->err_string); - } - - va_start(ap, format); - ldb->err_string = talloc_vasprintf(ldb, format, ap); - va_end(ap); -} - -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) -{ - if (!handle) { - return LDB_SUCCESS; - } - - return handle->module->ops->wait(handle, type); -} - -/* set the specified timeout or, if timeout is 0 set the default timeout */ -/* timeout == -1 means no 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) -{ - time_t now; - - if (newreq == NULL) return LDB_ERR_OPERATIONS_ERROR; - - now = time(NULL); - - if (oldreq == NULL) - return ldb_set_timeout(ldb, newreq, 0); - - if ((now - oldreq->starttime) > oldreq->timeout) { - return LDB_ERR_TIME_LIMIT_EXCEEDED; - } - newreq->starttime = oldreq->starttime; - newreq->timeout = oldreq->timeout - (now - oldreq->starttime); - - 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; -} - -/* - 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; - - 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_SEQUENCE_NUMBER: - FIRST_OP(ldb, sequence_number); - ret = module->ops->sequence_number(module, req); - break; - default: - FIRST_OP(ldb, request); - ret = module->ops->request(module, req); - break; - } - - return ret; -} - -/* - 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_context *ldb, void *context, struct ldb_reply *ares) -{ - struct ldb_result *res; - int n; - - if (!context) { - ldb_set_errstring(ldb, "NULL Context in callback"); - return LDB_ERR_OPERATIONS_ERROR; - } - - res = talloc_get_type(context, struct ldb_result); - - if (!res || !ares) { - ldb_set_errstring(ldb, "NULL res or ares in callback"); - goto error; - } - - switch (ares->type) { - case LDB_REPLY_ENTRY: - res->msgs = talloc_realloc(res, res->msgs, struct ldb_message *, res->count + 2); - if (! res->msgs) { - goto 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) { - goto error; - } - - res->refs[n] = talloc_move(res->refs, &ares->referral); - res->refs[n + 1] = NULL; - case LDB_REPLY_EXTENDED: - case LDB_REPLY_DONE: - /* TODO: we should really support controls on entries and referrals too! */ - res->controls = talloc_move(res, &ares->controls); - break; - } - talloc_free(ares); - return LDB_SUCCESS; - -error: - talloc_free(ares); - return LDB_ERR_OPERATIONS_ERROR; -} - -int ldb_build_search_req(struct ldb_request **ret_req, - struct ldb_context *ldb, - void *mem_ctx, - const 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 *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_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 = ldb_parse_tree(req, expression); - if (req->op.search.tree == NULL) { - ldb_set_errstring(ldb, "Unable to parse search expression"); - talloc_free(req); - return LDB_ERR_OPERATIONS_ERROR; - } - - req->op.search.attrs = attrs; - req->controls = controls; - req->context = context; - req->callback = callback; - - *ret_req = req; - return LDB_SUCCESS; -} - -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 *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; - - *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 *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; - - *ret_req = req; - - return LDB_SUCCESS; -} - -int ldb_build_del_req(struct ldb_request **ret_req, - struct ldb_context *ldb, - void *mem_ctx, - const struct ldb_dn *dn, - struct ldb_control **controls, - void *context, - ldb_request_callback_t callback) -{ - 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; - - *ret_req = req; - - return LDB_SUCCESS; -} - -int ldb_build_rename_req(struct ldb_request **ret_req, - struct ldb_context *ldb, - void *mem_ctx, - const struct ldb_dn *olddn, - const struct ldb_dn *newdn, - struct ldb_control **controls, - void *context, - ldb_request_callback_t callback) -{ - 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; - - *ret_req = req; - - return LDB_SUCCESS; -} - -/* - note that ldb_search() will automatically replace a NULL 'base' value with the - defaultNamingContext from the rootDSE if available. -*/ -static int _ldb_search(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, - struct ldb_result **_res, - const struct ldb_dn *base, - enum ldb_scope scope, - const char * const *attrs, - const char *expression) -{ - struct ldb_request *req; - int ret; - struct ldb_result *res; - - *_res = NULL; - - res = talloc_zero(mem_ctx, struct ldb_result); - if (!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); - - 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 = NULL; - } - - *_res = res; - return ret; -} - -/* - a useful search function where you can easily define the expression and that - takes a memory context where results are allocated -*/ - -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_result *res; - char *expression; - va_list ap; - int ret; - - expression = NULL; - res = NULL; - *result = NULL; - - if (exp_fmt) { - va_start(ap, exp_fmt); - expression = talloc_vasprintf(mem_ctx, exp_fmt, ap); - va_end(ap); - - if ( ! expression) { - return LDB_ERR_OPERATIONS_ERROR; - } - } - - ret = _ldb_search(ldb, ldb, &res, base, scope, attrs, expression); - - if (ret == LDB_SUCCESS) { - talloc_steal(mem_ctx, res); - *result = res; - } else { - talloc_free(res); - } - - talloc_free(expression); - - 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, - NULL); - - if (ret != LDB_SUCCESS) return ret; - - ldb_set_timeout(ldb, req, 0); /* use default timeout */ - - /* 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, - NULL); - - if (ret != LDB_SUCCESS) return ret; - - ldb_set_timeout(ldb, req, 0); /* use default timeout */ - - /* 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, const struct ldb_dn *dn) -{ - struct ldb_request *req; - int ret; - - ret = ldb_build_del_req(&req, ldb, ldb, - dn, - NULL, - NULL, - NULL); - - if (ret != LDB_SUCCESS) return ret; - - ldb_set_timeout(ldb, req, 0); /* use default timeout */ - - /* 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, const struct ldb_dn *olddn, const struct ldb_dn *newdn) -{ - struct ldb_request *req; - int ret; - - ret = ldb_build_rename_req(&req, ldb, ldb, - olddn, - newdn, - NULL, - NULL, - NULL); - - if (ret != LDB_SUCCESS) return ret; - - ldb_set_timeout(ldb, req, 0); /* use default timeout */ - - /* 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_request *req; - int ret; - - req = talloc(ldb, struct ldb_request); - if (req == NULL) { - ldb_set_errstring(ldb, "Out of Memory"); - return LDB_ERR_OPERATIONS_ERROR; - } - - req->operation = LDB_SEQUENCE_NUMBER; - req->controls = NULL; - req->context = NULL; - req->callback = NULL; - ldb_set_timeout(ldb, req, 0); /* use default timeout */ - - req->op.seq_num.type = type; - /* do request and autostart a transaction */ - ret = ldb_request(ldb, req); - - if (ret == LDB_SUCCESS) { - *seq_num = req->op.seq_num.seq_num; - } - - talloc_free(req); - 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/source3/lib/ldb/common/ldb_attributes.c b/source3/lib/ldb/common/ldb_attributes.c deleted file mode 100644 index 5ecbdc7940..0000000000 --- a/source3/lib/ldb/common/ldb_attributes.c +++ /dev/null @@ -1,308 +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 . -*/ -/* - 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 "includes.h" -#include "ldb/include/includes.h" - -/* - add to the list of ldif handlers for this ldb context -*/ -int ldb_set_attrib_handlers(struct ldb_context *ldb, - const struct ldb_attrib_handler *handlers, - unsigned num_handlers) -{ - int i; - struct ldb_attrib_handler *h; - h = talloc_realloc(ldb, ldb->schema.attrib_handlers, - struct ldb_attrib_handler, - ldb->schema.num_attrib_handlers + num_handlers); - if (h == NULL) { - ldb_oom(ldb); - return -1; - } - ldb->schema.attrib_handlers = h; - memcpy(h + ldb->schema.num_attrib_handlers, - handlers, sizeof(*h) * num_handlers); - for (i=0;ischema.num_attrib_handlers+i].flags & LDB_ATTR_FLAG_ALLOCATED) { - h[ldb->schema.num_attrib_handlers+i].attr = talloc_strdup(ldb->schema.attrib_handlers, - h[ldb->schema.num_attrib_handlers+i].attr); - if (h[ldb->schema.num_attrib_handlers+i].attr == NULL) { - ldb_oom(ldb); - return -1; - } - } - } - ldb->schema.num_attrib_handlers += num_handlers; - return 0; -} - - -/* - default function for read/write/canonicalise -*/ -static int ldb_default_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 (out->data == NULL && in->data != NULL) { - return -1; - } - - return 0; -} - -/* - default function for comparison -*/ -static int ldb_default_cmp(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); -} - -/* - default handler function pointers -*/ -static const struct ldb_attrib_handler ldb_default_attrib_handler = { - .attr = NULL, - .ldif_read_fn = ldb_default_copy, - .ldif_write_fn = ldb_default_copy, - .canonicalise_fn = ldb_default_copy, - .comparison_fn = ldb_default_cmp, -}; - -/* - return the attribute handlers for a given attribute -*/ -const struct ldb_attrib_handler *ldb_attrib_handler(struct ldb_context *ldb, - const char *attrib) -{ - int i; - const struct ldb_attrib_handler *def = &ldb_default_attrib_handler; - /* TODO: should be replaced with a binary search, with a sort on add */ - for (i=0;ischema.num_attrib_handlers;i++) { - if (strcmp(ldb->schema.attrib_handlers[i].attr, "*") == 0) { - def = &ldb->schema.attrib_handlers[i]; - } - if (ldb_attr_cmp(attrib, ldb->schema.attrib_handlers[i].attr) == 0) { - return &ldb->schema.attrib_handlers[i]; - } - } - return def; -} - - -/* - add to the list of ldif handlers for this ldb context -*/ -void ldb_remove_attrib_handler(struct ldb_context *ldb, const char *attrib) -{ - const struct ldb_attrib_handler *h; - int i; - h = ldb_attrib_handler(ldb, attrib); - if (h == &ldb_default_attrib_handler) { - return; - } - if (h->flags & LDB_ATTR_FLAG_ALLOCATED) { - talloc_free(discard_const_p(char, h->attr)); - } - i = h - ldb->schema.attrib_handlers; - if (i < ldb->schema.num_attrib_handlers - 1) { - memmove(&ldb->schema.attrib_handlers[i], - h+1, sizeof(*h) * (ldb->schema.num_attrib_handlers-(i+1))); - } - ldb->schema.num_attrib_handlers--; -} - -/* - setup a attribute handler using a standard syntax -*/ -int ldb_set_attrib_handler_syntax(struct ldb_context *ldb, - const char *attr, const char *syntax) -{ - const struct ldb_attrib_handler *h = ldb_attrib_handler_syntax(ldb, syntax); - struct ldb_attrib_handler h2; - if (h == NULL) { - ldb_debug(ldb, LDB_DEBUG_ERROR, "Unknown syntax '%s'\n", syntax); - return -1; - } - h2 = *h; - h2.attr = attr; - return ldb_set_attrib_handlers(ldb, &h2, 1); -} - -/* - 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 }, - { "ncName", 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; - for (i=0;ischema.num_classes;i++) { - if (ldb_attr_cmp(classname, ldb->schema.classes[i].name) == 0) { - return (const char **)ldb->schema.classes[i].subclasses; - } - } - return NULL; -} - - -/* - add a new subclass -*/ -static int ldb_subclass_new(struct ldb_context *ldb, const char *classname, const char *subclass) -{ - struct ldb_subclass *s, *c; - s = talloc_realloc(ldb, ldb->schema.classes, struct ldb_subclass, ldb->schema.num_classes+1); - if (s == NULL) goto failed; - - ldb->schema.classes = s; - c = &s[ldb->schema.num_classes]; - c->name = talloc_strdup(s, classname); - if (c->name == NULL) goto failed; - - c->subclasses = talloc_array(s, char *, 2); - if (c->subclasses == NULL) goto failed; - - c->subclasses[0] = talloc_strdup(c->subclasses, subclass); - if (c->subclasses[0] == NULL) goto failed; - c->subclasses[1] = NULL; - - ldb->schema.num_classes++; - - return 0; -failed: - ldb_oom(ldb); - return -1; -} - -/* - add a subclass -*/ -int ldb_subclass_add(struct ldb_context *ldb, const char *classname, const char *subclass) -{ - int i, n; - struct ldb_subclass *c; - char **s; - - for (i=0;ischema.num_classes;i++) { - if (ldb_attr_cmp(classname, ldb->schema.classes[i].name) == 0) { - break; - } - } - if (i == ldb->schema.num_classes) { - return ldb_subclass_new(ldb, classname, subclass); - } - c = &ldb->schema.classes[i]; - - for (n=0;c->subclasses[n];n++) /* noop */; - - s = talloc_realloc(ldb->schema.classes, c->subclasses, char *, n+2); - if (s == NULL) { - ldb_oom(ldb); - return -1; - } - - c->subclasses = s; - s[n] = talloc_strdup(s, subclass); - if (s[n] == NULL) { - ldb_oom(ldb); - return -1; - } - s[n+1] = NULL; - - return 0; -} - -/* - remove a set of subclasses for a class -*/ -void ldb_subclass_remove(struct ldb_context *ldb, const char *classname) -{ - int i; - struct ldb_subclass *c; - - for (i=0;ischema.num_classes;i++) { - if (ldb_attr_cmp(classname, ldb->schema.classes[i].name) == 0) { - break; - } - } - if (i == ldb->schema.num_classes) { - return; - } - - c = &ldb->schema.classes[i]; - talloc_free(c->name); - talloc_free(c->subclasses); - if (ldb->schema.num_classes-(i+1) > 0) { - memmove(c, c+1, sizeof(*c) * (ldb->schema.num_classes-(i+1))); - } - ldb->schema.num_classes--; - if (ldb->schema.num_classes == 0) { - talloc_free(ldb->schema.classes); - ldb->schema.classes = NULL; - } -} diff --git a/source3/lib/ldb/common/ldb_controls.c b/source3/lib/ldb/common/ldb_controls.c deleted file mode 100644 index 9b49470941..0000000000 --- a/source3/lib/ldb/common/ldb_controls.c +++ /dev/null @@ -1,105 +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 . -*/ - -/* - * Name: ldb_controls.c - * - * Component: ldb controls utility functions - * - * Description: helper functions for control modules - * - * Author: Simo Sorce - */ - -#include "includes.h" -#include "ldb/include/includes.h" - -/* check if a control with the specified "oid" exist and return it */ -/* returns NULL if not found */ -struct ldb_control *get_control_from_list(struct ldb_control **controls, const char *oid) -{ - int i; - - /* check if there's a paged request control */ - if (controls != NULL) { - for (i = 0; controls[i]; i++) { - if (strcmp(oid, controls[i]->oid) == 0) { - break; - } - } - - return 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; -} diff --git a/source3/lib/ldb/common/ldb_debug.c b/source3/lib/ldb/common/ldb_debug.c deleted file mode 100644 index 3c9442ea9c..0000000000 --- a/source3/lib/ldb/common/ldb_debug.c +++ /dev/null @@ -1,104 +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 . -*/ - -/* - * Name: ldb - * - * Component: ldb debug - * - * Description: functions for printing debug messages - * - * Author: Andrew Tridgell - */ - -#include "includes.h" -#include "ldb/include/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/source3/lib/ldb/common/ldb_dn.c b/source3/lib/ldb/common/ldb_dn.c deleted file mode 100644 index fb7f3e99f3..0000000000 --- a/source3/lib/ldb/common/ldb_dn.c +++ /dev/null @@ -1,1050 +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 . -*/ - -/* - * Name: ldb - * - * Component: ldb dn explode and utility functions - * - * Description: - explode a dn into its own basic elements - * and put them in a structure - * - manipulate ldb_dn structures - * - * Author: Simo Sorce - */ - -#include "includes.h" -#include "ldb/include/includes.h" - -#define LDB_DN_NULL_FAILED(x) if (!(x)) goto failed - -#define LDB_SPECIAL "@SPECIAL" - -/** - internal ldb exploded dn structures -*/ -struct ldb_dn_component { - char *name; - struct ldb_val value; -}; - -struct ldb_dn { - int comp_num; - struct ldb_dn_component *components; -}; - -int ldb_dn_is_special(const struct ldb_dn *dn) -{ - if (dn == NULL || dn->comp_num != 1) return 0; - - return ! strcmp(dn->components[0].name, LDB_SPECIAL); -} - -int ldb_dn_check_special(const struct ldb_dn *dn, const char *check) -{ - if (dn == NULL || dn->comp_num != 1) return 0; - - return ! strcmp((char *)dn->components[0].value.data, check); -} - -char *ldb_dn_escape_value(void *mem_ctx, struct ldb_val value) -{ - const char *p, *s, *src; - char *d, *dst; - int len; - - if (!value.length) - return NULL; - - p = s = src = (const char *)value.data; - len = value.length; - - /* allocate destination string, it will be at most 3 times the source */ - dst = d = talloc_array(mem_ctx, char, len * 3 + 1); - LDB_DN_NULL_FAILED(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 = d + 3; - p++; /* skip the zero */ - } - s = p; /* move forward */ - } - - /* copy the last part (with zero) and return */ - memcpy(d, s, &src[len] - s + 1); - - return dst; - -failed: - talloc_free(dst); - return NULL; -} - -static struct ldb_val ldb_dn_unescape_value(void *mem_ctx, const char *src) -{ - struct ldb_val value; - unsigned x; - char *p, *dst = NULL, *end; - - memset(&value, 0, sizeof(value)); - - LDB_DN_NULL_FAILED(src); - - dst = p = (char *)talloc_memdup(mem_ctx, src, strlen(src) + 1); - LDB_DN_NULL_FAILED(dst); - - end = &dst[strlen(dst)]; - - while (*p) { - p += strcspn(p, ",=\n+<>#;\\\""); - - if (*p == '\\') { - if (strchr(",=\n+<>#;\\\"", p[1])) { - memmove(p, p + 1, end - (p + 1) + 1); - end--; - p++; - continue; - } - - if (sscanf(p + 1, "%02x", &x) == 1) { - *p = (unsigned char)x; - memmove(p + 1, p + 3, end - (p + 3) + 1); - end -= 2; - p++; - continue; - } - } - - /* a string with not escaped specials is invalid (tested) */ - if (*p != '\0') { - goto failed; - } - } - - value.length = end - dst; - value.data = (uint8_t *)dst; - return value; - -failed: - talloc_free(dst); - return value; -} - -/* check if the string contains quotes - * skips leading and trailing spaces - * - returns 0 if no quotes found - * - returns 1 if quotes are found and put their position - * in *quote_start and *quote_end parameters - * - return -1 if there are open quotes - */ - -static int get_quotes_position(const char *source, int *quote_start, int *quote_end) -{ - const char *p; - - if (source == NULL || quote_start == NULL || quote_end == NULL) return -1; - - p = source; - - /* check if there are quotes surrounding the value */ - p += strspn(p, " \n"); /* skip white spaces */ - - if (*p == '\"') { - *quote_start = p - source; - - p++; - while (*p != '\"') { - p = strchr(p, '\"'); - LDB_DN_NULL_FAILED(p); - - if (*(p - 1) == '\\') - p++; - } - - *quote_end = p - source; - return 1; - } - - return 0; - -failed: - return -1; -} - -static char *seek_to_separator(char *string, const char *separators) -{ - char *p, *q; - int ret, qs, qe, escaped; - - if (string == NULL || separators == NULL) return NULL; - - p = strchr(string, '='); - LDB_DN_NULL_FAILED(p); - - p++; - - /* check if there are quotes surrounding the value */ - - ret = get_quotes_position(p, &qs, &qe); - if (ret == -1) - return NULL; - - if (ret == 1) { /* quotes found */ - - p += qe; /* positioning after quotes */ - p += strspn(p, " \n"); /* skip white spaces after the quote */ - - if (strcspn(p, separators) != 0) /* if there are characters between quotes */ - return NULL; /* and separators, the dn is invalid */ - - return p; /* return on the separator */ - } - - /* no quotes found seek to separators */ - q = p; - do { - escaped = 0; - ret = strcspn(q, separators); - - if (q[ret - 1] == '\\') { - escaped = 1; - q = q + ret + 1; - } - } while (escaped); - - if (ret == 0 && p == q) /* no separators ?! bail out */ - return NULL; - - return q + ret; - -failed: - return NULL; -} - -static char *ldb_dn_trim_string(char *string, const char *edge) -{ - char *s, *p; - - /* seek out edge from start of string */ - s = string + strspn(string, edge); - - /* backwards skip from end of string */ - p = &s[strlen(s) - 1]; - while (p > s && strchr(edge, *p)) { - *p = '\0'; - p--; - } - - return s; -} - -/* we choosed to not support multpile valued components */ -static struct ldb_dn_component ldb_dn_explode_component(void *mem_ctx, char *raw_component) -{ - struct ldb_dn_component dc; - char *p; - int ret, qs, qe; - - memset(&dc, 0, sizeof(dc)); - - if (raw_component == NULL) { - return dc; - } - - /* find attribute type/value separator */ - p = strchr(raw_component, '='); - LDB_DN_NULL_FAILED(p); - - *p++ = '\0'; /* terminate name and point to value */ - - /* copy and trim name in the component */ - dc.name = talloc_strdup(mem_ctx, ldb_dn_trim_string(raw_component, " \n")); - if (!dc.name) - return dc; - - if (! ldb_valid_attr_name(dc.name)) { - goto failed; - } - - ret = get_quotes_position(p, &qs, &qe); - - switch (ret) { - case 0: /* no quotes trim the string */ - p = ldb_dn_trim_string(p, " \n"); - dc.value = ldb_dn_unescape_value(mem_ctx, p); - break; - - case 1: /* quotes found get the unquoted string */ - p[qe] = '\0'; - p = p + qs + 1; - dc.value.length = strlen(p); - dc.value.data = (uint8_t *)talloc_memdup(mem_ctx, p, - dc.value.length + 1); - break; - - default: /* mismatched quotes ot other error, bail out */ - goto failed; - } - - if (dc.value.length == 0) { - goto failed; - } - - return dc; - -failed: - talloc_free(dc.name); - dc.name = NULL; - return dc; -} - -struct ldb_dn *ldb_dn_new(void *mem_ctx, struct ldb_context *ldb, const char *text) -{ - struct ldb_dn *edn; - - if (text == NULL) { - edn = talloc_zero(mem_ctx, struct ldb_dn); - } else { - edn = ldb_dn_explode(mem_ctx, text); - } - - return edn; -} - -bool ldb_dn_validate(struct ldb_dn *dn) -{ - /* This implementation does not do "lazy" evaluation of DN's, so - * if a DN can be created it will be valid. */ - return true; -} - -struct ldb_dn *ldb_dn_new_fmt(void *mem_ctx, struct ldb_context *ldb, const char *new_fmt, ...) -{ - char *strdn; - va_list ap; - struct ldb_dn *dn; - - if ( (! mem_ctx) || (! ldb)) return NULL; - - va_start(ap, new_fmt); - strdn = talloc_vasprintf(mem_ctx, new_fmt, ap); - va_end(ap); - if (strdn == NULL) - return NULL; - - dn = ldb_dn_explode(mem_ctx, strdn); - - talloc_free(strdn); - return dn; -} - -/* - explode a DN string into a ldb_dn structure -*/ -struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn) -{ - struct ldb_dn *edn; /* the exploded dn */ - char *pdn, *p; - - if (dn == NULL) return NULL; - - /* Allocate a structure to hold the exploded DN */ - edn = talloc_zero(mem_ctx, struct ldb_dn); - if (edn == NULL) { - return NULL; - } - - pdn = NULL; - - /* Empty DNs */ - if (dn[0] == '\0') { - return edn; - } - - /* Special DNs case */ - if (dn[0] == '@') { - edn->comp_num = 1; - edn->components = talloc(edn, struct ldb_dn_component); - if (edn->components == NULL) goto failed; - edn->components[0].name = talloc_strdup(edn->components, LDB_SPECIAL); - if (edn->components[0].name == NULL) goto failed; - edn->components[0].value.data = (uint8_t *)talloc_strdup(edn->components, dn); - if (edn->components[0].value.data== NULL) goto failed; - edn->components[0].value.length = strlen(dn); - return edn; - } - - pdn = p = talloc_strdup(edn, dn); - LDB_DN_NULL_FAILED(pdn); - - /* get the components */ - do { - char *t; - - /* terminate the current component and return pointer to the next one */ - t = seek_to_separator(p, ",;"); - LDB_DN_NULL_FAILED(t); - - if (*t) { /* here there is a separator */ - *t = '\0'; /*terminate */ - t++; /* a separtor means another component follows */ - } - - /* allocate space to hold the dn component */ - edn->components = talloc_realloc(edn, edn->components, - struct ldb_dn_component, - edn->comp_num + 1); - if (edn->components == NULL) - goto failed; - - /* store the exploded component in the main structure */ - edn->components[edn->comp_num] = ldb_dn_explode_component(edn, p); - LDB_DN_NULL_FAILED(edn->components[edn->comp_num].name); - - edn->comp_num++; - - /* jump to the next component if any */ - p = t; - - } while(*p); - - talloc_free(pdn); - return edn; - -failed: - talloc_free(pdn); - talloc_free(edn); - return NULL; -} - -struct ldb_dn *ldb_dn_explode_or_special(void *mem_ctx, const char *dn) -{ - struct ldb_dn *edn; /* the exploded dn */ - - if (dn == NULL) return NULL; - - if (strncasecmp(dn, "comp_num = 1; - edn->components = talloc(edn, struct ldb_dn_component); - if (edn->components == NULL) goto failed; - edn->components[0].name = talloc_strdup(edn->components, LDB_SPECIAL); - if (edn->components[0].name == NULL) goto failed; - edn->components[0].value.data = (uint8_t *)talloc_strdup(edn->components, dn); - if (edn->components[0].value.data== NULL) goto failed; - edn->components[0].value.length = strlen(dn); - return edn; - - } - - return ldb_dn_explode(mem_ctx, dn); - -failed: - talloc_free(edn); - return NULL; -} - -char *ldb_dn_linearize(void *mem_ctx, const struct ldb_dn *edn) -{ - char *dn, *value; - int i; - - if (edn == NULL) return NULL; - - /* Special DNs */ - if (ldb_dn_is_special(edn)) { - dn = talloc_strdup(mem_ctx, (char *)edn->components[0].value.data); - return dn; - } - - dn = talloc_strdup(mem_ctx, ""); - LDB_DN_NULL_FAILED(dn); - - for (i = 0; i < edn->comp_num; i++) { - value = ldb_dn_escape_value(dn, edn->components[i].value); - LDB_DN_NULL_FAILED(value); - - if (i == 0) { - dn = talloc_asprintf_append(dn, "%s=%s", edn->components[i].name, value); - } else { - dn = talloc_asprintf_append(dn, ",%s=%s", edn->components[i].name, value); - } - LDB_DN_NULL_FAILED(dn); - - talloc_free(value); - } - - return dn; - -failed: - talloc_free(dn); - return NULL; -} - -/* 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_context *ldb, - const struct ldb_dn *base, - const struct ldb_dn *dn) -{ - int ret; - int n0, n1; - - if (base == NULL || base->comp_num == 0) return 0; - if (dn == NULL || dn->comp_num == 0) return -1; - - /* if the base has more componts than the dn, then they differ */ - if (base->comp_num > dn->comp_num) { - return (dn->comp_num - base->comp_num); - } - - n0 = base->comp_num - 1; - n1 = dn->comp_num - 1; - while (n0 >= 0 && n1 >= 0) { - const struct ldb_attrib_handler *h; - - /* compare names (attribute names are guaranteed to be ASCII only) */ - ret = ldb_attr_cmp(base->components[n0].name, - dn->components[n1].name); - if (ret) { - return ret; - } - - /* names match, compare values */ - h = ldb_attrib_handler(ldb, base->components[n0].name); - ret = h->comparison_fn(ldb, ldb, &(base->components[n0].value), - &(dn->components[n1].value)); - if (ret) { - return ret; - } - n1--; - n0--; - } - - return 0; -} - -/* compare DNs using casefolding compare functions. - - If they match, then return 0 - */ - -int ldb_dn_compare(struct ldb_context *ldb, - const struct ldb_dn *edn0, - const struct ldb_dn *edn1) -{ - if (edn0 == NULL || edn1 == NULL) return edn1 - edn0; - - if (edn0->comp_num != edn1->comp_num) - return (edn1->comp_num - edn0->comp_num); - - return ldb_dn_compare_base(ldb, edn0, edn1); -} - -int ldb_dn_cmp(struct ldb_context *ldb, const char *dn0, const char *dn1) -{ - struct ldb_dn *edn0; - struct ldb_dn *edn1; - int ret; - - if (dn0 == NULL || dn1 == NULL) return dn1 - dn0; - - edn0 = ldb_dn_explode_casefold(ldb, ldb, dn0); - if (edn0 == NULL) return 1; - - edn1 = ldb_dn_explode_casefold(ldb, ldb, dn1); - if (edn1 == NULL) { - talloc_free(edn0); - return -1; - } - - ret = ldb_dn_compare(ldb, edn0, edn1); - - talloc_free(edn0); - talloc_free(edn1); - - return ret; -} - -/* - casefold a dn. We need to casefold the attribute names, and canonicalize - attribute values of case insensitive attributes. -*/ -struct ldb_dn *ldb_dn_casefold(struct ldb_context *ldb, void *mem_ctx, const struct ldb_dn *edn) -{ - struct ldb_dn *cedn; - int i, ret; - - if (edn == NULL) return NULL; - - cedn = talloc_zero(mem_ctx, struct ldb_dn); - if (!cedn) { - return NULL; - } - - cedn->comp_num = edn->comp_num; - cedn->components = talloc_array(cedn, struct ldb_dn_component, edn->comp_num); - if (!cedn->components) { - talloc_free(cedn); - return NULL; - } - - for (i = 0; i < edn->comp_num; i++) { - struct ldb_dn_component dc; - const struct ldb_attrib_handler *h; - - memset(&dc, 0, sizeof(dc)); - dc.name = ldb_attr_casefold(cedn->components, edn->components[i].name); - if (!dc.name) { - talloc_free(cedn); - return NULL; - } - - h = ldb_attrib_handler(ldb, dc.name); - ret = h->canonicalise_fn(ldb, cedn->components, - &(edn->components[i].value), - &(dc.value)); - if (ret != 0) { - talloc_free(cedn); - return NULL; - } - - cedn->components[i] = dc; - } - - return cedn; -} - -struct ldb_dn *ldb_dn_explode_casefold(struct ldb_context *ldb, void *mem_ctx, const char *dn) -{ - struct ldb_dn *edn, *cdn; - - if (dn == NULL) return NULL; - - edn = ldb_dn_explode(ldb, dn); - if (edn == NULL) return NULL; - - cdn = ldb_dn_casefold(ldb, mem_ctx, edn); - - talloc_free(edn); - return cdn; -} - -char *ldb_dn_linearize_casefold(struct ldb_context *ldb, void *mem_ctx, const struct ldb_dn *edn) -{ - struct ldb_dn *cdn; - char *dn; - - if (edn == NULL) return NULL; - - /* Special DNs */ - if (ldb_dn_is_special(edn)) { - dn = talloc_strdup(mem_ctx, (char *)edn->components[0].value.data); - return dn; - } - - cdn = ldb_dn_casefold(ldb, mem_ctx, edn); - if (cdn == NULL) return NULL; - - dn = ldb_dn_linearize(ldb, cdn); - if (dn == NULL) { - talloc_free(cdn); - return NULL; - } - - talloc_free(cdn); - return dn; -} - -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) { - talloc_free(dst.value.data); - dst.value.data = NULL; - } - - return dst; -} - -/* Copy a DN but replace the old with the new base DN. */ -struct ldb_dn *ldb_dn_copy_rebase(void *mem_ctx, const struct ldb_dn *old, const struct ldb_dn *old_base, const struct ldb_dn *new_base) -{ - struct ldb_dn *new_dn; - int i, offset; - - /* Perhaps we don't need to rebase at all? */ - if (!old_base || !new_base) { - return ldb_dn_copy(mem_ctx, old); - } - - offset = old->comp_num - old_base->comp_num; - if (!(new_dn = ldb_dn_copy_partial(mem_ctx, new_base, - offset + new_base->comp_num))) { - return NULL; - } - for (i = 0; i < offset; i++) { - new_dn->components[i] = ldb_dn_copy_component(new_dn->components, &(old->components[i])); - } - - return new_dn; -} - -/* copy specified number of elements of a dn into a new one - element are copied from top level up to the unique rdn - num_el may be greater than dn->comp_num (see ldb_dn_make_child) -*/ -struct ldb_dn *ldb_dn_copy_partial(void *mem_ctx, const struct ldb_dn *dn, int num_el) -{ - struct ldb_dn *newdn; - int i, n, e; - - if (dn == NULL) return NULL; - if (num_el <= 0) return NULL; - - newdn = talloc_zero(mem_ctx, struct ldb_dn); - LDB_DN_NULL_FAILED(newdn); - - newdn->comp_num = num_el; - n = newdn->comp_num - 1; - newdn->components = talloc_array(newdn, struct ldb_dn_component, newdn->comp_num); - if (newdn->components == NULL) goto failed; - - if (dn->comp_num == 0) return newdn; - e = dn->comp_num - 1; - - for (i = 0; i < newdn->comp_num; i++) { - newdn->components[n - i] = ldb_dn_copy_component(newdn->components, - &(dn->components[e - i])); - if ((e - i) == 0) { - return newdn; - } - } - - return newdn; - -failed: - talloc_free(newdn); - return NULL; -} - -struct ldb_dn *ldb_dn_copy(void *mem_ctx, const struct ldb_dn *dn) -{ - if (dn == NULL) return NULL; - return ldb_dn_copy_partial(mem_ctx, dn, dn->comp_num); -} - -struct ldb_dn *ldb_dn_get_parent(void *mem_ctx, const struct ldb_dn *dn) -{ - if (dn == NULL) return NULL; - return ldb_dn_copy_partial(mem_ctx, dn, dn->comp_num - 1); -} - -struct ldb_dn_component *ldb_dn_build_component(void *mem_ctx, const char *attr, - const char *val) -{ - struct ldb_dn_component *dc; - - if (attr == NULL || val == NULL) return NULL; - - dc = talloc(mem_ctx, struct ldb_dn_component); - if (dc == NULL) return NULL; - - dc->name = talloc_strdup(dc, attr); - if (dc->name == NULL) { - talloc_free(dc); - return NULL; - } - - dc->value.data = (uint8_t *)talloc_strdup(dc, val); - if (dc->value.data == NULL) { - talloc_free(dc); - return NULL; - } - - dc->value.length = strlen(val); - - return dc; -} - -struct ldb_dn *ldb_dn_build_child(void *mem_ctx, const char *attr, - const char * value, - const struct ldb_dn *base) -{ - struct ldb_dn *newdn; - if (! ldb_valid_attr_name(attr)) return NULL; - if (value == NULL || value == '\0') return NULL; - - if (base != NULL) { - newdn = ldb_dn_copy_partial(mem_ctx, base, base->comp_num + 1); - LDB_DN_NULL_FAILED(newdn); - } else { - newdn = talloc_zero(mem_ctx, struct ldb_dn); - LDB_DN_NULL_FAILED(newdn); - - newdn->comp_num = 1; - newdn->components = talloc_array(newdn, struct ldb_dn_component, newdn->comp_num); - LDB_DN_NULL_FAILED(newdn->components); - } - - newdn->components[0].name = talloc_strdup(newdn->components, attr); - LDB_DN_NULL_FAILED(newdn->components[0].name); - - newdn->components[0].value.data = (uint8_t *)talloc_strdup(newdn->components, value); - LDB_DN_NULL_FAILED(newdn->components[0].value.data); - newdn->components[0].value.length = strlen((char *)newdn->components[0].value.data); - - return newdn; - -failed: - talloc_free(newdn); - return NULL; - -} - -struct ldb_dn *ldb_dn_compose(void *mem_ctx, const struct ldb_dn *dn1, const struct ldb_dn *dn2) -{ - int i; - struct ldb_dn *newdn; - - if (dn2 == NULL && dn1 == NULL) { - return NULL; - } - - if (dn2 == NULL) { - newdn = talloc_zero(mem_ctx, struct ldb_dn); - LDB_DN_NULL_FAILED(newdn); - - newdn->comp_num = dn1->comp_num; - newdn->components = talloc_array(newdn, struct ldb_dn_component, newdn->comp_num); - LDB_DN_NULL_FAILED(newdn->components); - } else { - int comp_num = dn2->comp_num; - if (dn1 != NULL) comp_num += dn1->comp_num; - newdn = ldb_dn_copy_partial(mem_ctx, dn2, comp_num); - LDB_DN_NULL_FAILED(newdn); - } - - if (dn1 == NULL) { - return newdn; - } - - for (i = 0; i < dn1->comp_num; i++) { - newdn->components[i] = ldb_dn_copy_component(newdn->components, - &(dn1->components[i])); - if (newdn->components[i].value.data == NULL) { - goto failed; - } - } - - return newdn; - -failed: - talloc_free(newdn); - return NULL; -} - -struct ldb_dn *ldb_dn_string_compose(void *mem_ctx, const struct ldb_dn *base, const char *child_fmt, ...) -{ - struct ldb_dn *dn, *dn1; - char *child_str; - va_list ap; - - if (child_fmt == NULL) return NULL; - - va_start(ap, child_fmt); - child_str = talloc_vasprintf(mem_ctx, child_fmt, ap); - va_end(ap); - - if (child_str == NULL) return NULL; - - dn1 = ldb_dn_explode(mem_ctx, child_str); - dn = ldb_dn_compose(mem_ctx, dn1, base); - - talloc_free(child_str); - talloc_free(dn1); - - return 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, const struct ldb_dn *dn, int ex_format) { - int i; - char *cracked = NULL; - - /* 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(mem_ctx, "%s.%s", - ldb_dn_escape_value(mem_ctx, dn->components[i].value), - cracked); - } else { - cracked = ldb_dn_escape_value(mem_ctx, dn->components[i].value); - } - if (!cracked) { - return NULL; - } - } - - /* Only domain components? Finish here */ - if (i < 0) { - if (ex_format) { - cracked = talloc_asprintf(mem_ctx, "%s\n", cracked); - } else { - cracked = talloc_asprintf(mem_ctx, "%s/", cracked); - } - return cracked; - } - - /* Now walk backwards appending remaining components */ - for (; i > 0; i--) { - cracked = talloc_asprintf(mem_ctx, "%s/%s", cracked, - ldb_dn_escape_value(mem_ctx, dn->components[i].value)); - if (!cracked) { - return NULL; - } - } - - /* Last one, possibly a newline for the 'ex' format */ - if (ex_format) { - cracked = talloc_asprintf(mem_ctx, "%s\n%s", cracked, - ldb_dn_escape_value(mem_ctx, dn->components[i].value)); - } else { - cracked = talloc_asprintf(mem_ctx, "%s/%s", cracked, - ldb_dn_escape_value(mem_ctx, dn->components[i].value)); - } - return cracked; -} - -/* Wrapper functions for the above, for the two different string formats */ -char *ldb_dn_canonical_string(void *mem_ctx, const struct ldb_dn *dn) { - return ldb_dn_canonical(mem_ctx, dn, 0); - -} - -char *ldb_dn_canonical_ex_string(void *mem_ctx, const struct ldb_dn *dn) { - return ldb_dn_canonical(mem_ctx, dn, 1); -} - -int ldb_dn_get_comp_num(const struct ldb_dn *dn) -{ - return dn->comp_num; -} - -const char *ldb_dn_get_component_name(const struct ldb_dn *dn, unsigned int num) -{ - if (num >= dn->comp_num) return NULL; - return dn->components[num].name; -} - -const struct ldb_val *ldb_dn_get_component_val(const struct ldb_dn *dn, unsigned int num) -{ - if (num >= dn->comp_num) return NULL; - return &dn->components[num].value; -} - -const char *ldb_dn_get_rdn_name(const struct ldb_dn *dn) { - if (dn->comp_num == 0) return NULL; - return dn->components[0].name; -} - -const struct ldb_val *ldb_dn_get_rdn_val(const struct ldb_dn *dn) { - 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 (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) { - 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; - - return LDB_SUCCESS; -} diff --git a/source3/lib/ldb/common/ldb_ldif.c b/source3/lib/ldb/common/ldb_ldif.c deleted file mode 100644 index a6ed1b6055..0000000000 --- a/source3/lib/ldb/common/ldb_ldif.c +++ /dev/null @@ -1,760 +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 . -*/ - -/* - * Name: ldb - * - * Component: ldif routines - * - * Description: ldif pack/unpack routines - * - * Author: Andrew Tridgell - */ - -/* - see RFC2849 for the LDIF format definition -*/ - -#include "includes.h" -#include "ldb/include/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> (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 (;idata; - - if (val->length == 0) { - return 0; - } - - if (p[0] == ' ' || p[0] == ':') { - return 1; - } - - for (i=0; ilength; 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;imsg; - - ret = fprintf_fn(private_data, "dn: %s\n", ldb_dn_linearize(msg->dn, msg->dn)); - 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;inum_elements;i++) { - const struct ldb_attrib_handler *h; - - h = ldb_attrib_handler(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;jelements[i].num_values;j++) { - struct ldb_val v; - ret = h->ldif_write_fn(ldb, mem_ctx, &msg->elements[i].values[j], &v); - CHECK_RET; - if (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; - msg->private_data = NULL; - - chunk = next_chunk(ldb, fgetc_fn, private_data); - if (!chunk) { - goto failed; - } - talloc_steal(ldif, chunk); - - msg->private_data = 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_explode(msg, (char *)value.data); - - if (msg->dn == NULL) { - ldb_debug(ldb, LDB_DEBUG_ERROR, "Error: Unable to parse dn '%s'\n", - value.data); - goto failed; - } - - while (next_attr(ldif, &s, &attr, &value) == 0) { - const struct ldb_attrib_handler *h; - 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]; - - h = ldb_attrib_handler(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 = h->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 = h->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/source3/lib/ldb/common/ldb_match.c b/source3/lib/ldb/common/ldb_match.c deleted file mode 100644 index 066c997cee..0000000000 --- a/source3/lib/ldb/common/ldb_match.c +++ /dev/null @@ -1,430 +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 . -*/ - -/* - * Name: ldb - * - * Component: ldb expression matching - * - * Description: ldb expression matching - * - * Author: Andrew Tridgell - */ - -#include "includes.h" -#include "ldb/include/includes.h" - -/* - check if the scope matches in a search result -*/ -static int ldb_match_scope(struct ldb_context *ldb, - const struct ldb_dn *base, - const 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(ldb, 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(ldb, base, dn) == 0) { - ret = 1; - } - } - break; - - case LDB_SCOPE_SUBTREE: - default: - if (ldb_dn_compare_base(ldb, 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_attrib_handler *h; - 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; - } - - h = ldb_attrib_handler(ldb, el->name); - - for (i = 0; i < el->num_values; i++) { - ret = h->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_attrib_handler *h; - struct ldb_dn *valuedn; - int ret; - - if (ldb_attr_dn(tree->u.equality.attr) == 0) { - valuedn = ldb_dn_explode_casefold(ldb, ldb, - (char *)tree->u.equality.value.data); - if (valuedn == NULL) { - return 0; - } - - ret = ldb_dn_compare(ldb, 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; - } - - h = ldb_attrib_handler(ldb, el->name); - - for (i=0;inum_values;i++) { - if (h->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_attrib_handler *h; - struct ldb_val val; - struct ldb_val cnk; - struct ldb_val *chunk; - char *p, *g; - uint8_t *save_p = NULL; - int c = 0; - - h = ldb_attrib_handler(ldb, tree->u.substring.attr); - - if(h->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(h->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(h->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;iu.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;inum_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;iu.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;iu.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, - const 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/source3/lib/ldb/common/ldb_modules.c b/source3/lib/ldb/common/ldb_modules.c deleted file mode 100644 index 8699cd8b95..0000000000 --- a/source3/lib/ldb/common/ldb_modules.c +++ /dev/null @@ -1,459 +0,0 @@ - -/* - ldb database library - - Copyright (C) Simo Sorce 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 . -*/ - -/* - * Name: ldb - * - * Component: ldb modules core - * - * Description: core modules routines - * - * Author: Simo Sorce - */ - -#include "includes.h" -#include "ldb/include/includes.h" - -#if (_SAMBA_BUILD_ >= 4) -#include "build.h" -#include "dynconfig.h" -#endif - -#define LDB_MODULE_PREFIX "modules:" -#define LDB_MODULE_PREFIX_LEN 8 - -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 ops_list_entry { - const struct ldb_module_ops *ops; - struct ops_list_entry *next; -} *registered_modules = NULL; - -static const struct ldb_module_ops *ldb_find_module_ops(const char *name) -{ - struct ops_list_entry *e; - - for (e = registered_modules; e; e = e->next) { - if (strcmp(e->ops->name, name) == 0) - return e->ops; - } - - return NULL; -} - -#ifndef STATIC_ldb_MODULES - -#ifdef HAVE_LDB_LDAP -#define LDAP_INIT ldb_ldap_init, -#else -#define LDAP_INIT -#endif - -#ifdef HAVE_LDB_SQLITE3 -#define SQLITE3_INIT ldb_sqlite3_init, -#else -#define SQLITE3_INIT -#endif - -#define STATIC_ldb_MODULES \ - { \ - LDAP_INIT \ - SQLITE3_INIT \ - ldb_tdb_init, \ - ldb_operational_init, \ - ldb_rdn_name_init, \ - ldb_objectclass_init, \ - ldb_paged_results_init, \ - ldb_sort_init, \ - ldb_asq_init, \ - NULL \ - } -#endif - -int ldb_global_init(void) -{ - static int (*static_init_fns[])(void) = STATIC_ldb_MODULES; - - static int initialized = 0; - int ret = 0, i; - - if (initialized) - return 0; - - initialized = 1; - - for (i = 0; static_init_fns[i]; i++) { - if (static_init_fns[i]() == -1) - ret = -1; - } - - return ret; -} - -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; -} - -int ldb_try_load_dso(struct ldb_context *ldb, const char *name) -{ - char *path; - void *handle; - int (*init_fn) (void); - char *modulesdir; - int ret; - -#ifdef HAVE_DLOPEN - if (getenv("LD_LDB_MODULE_PATH") != NULL) { - modulesdir = talloc_strdup(ldb, getenv("LD_LDB_MODULE_PATH")); - } else { -#ifdef _SAMBA_BUILD_ - modulesdir = talloc_asprintf(ldb, "%s/ldb", get_dyn_LIBDIR()); -#else - modulesdir = talloc_strdup(ldb, MODULESDIR); -#endif - } - - path = talloc_asprintf(ldb, "%s/%s.%s", modulesdir, name, SHLIBEXT); - - talloc_free(modulesdir); - - 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 -1; - } - - init_fn = (int (*)(void))dlsym(handle, "init_samba_module"); - - if (init_fn == NULL) { - ldb_debug(ldb, LDB_DEBUG_ERROR, "no symbol " - "`init_samba_module' found in %s: %s\n", path, - dlerror()); - dlclose(handle); - return -1; - } - - talloc_free(path); - - ret = init_fn(); - if (ret == -1) { - dlclose(handle); - } - return ret; -#else - ldb_debug(ldb, LDB_DEBUG_TRACE, "no dlopen() - not trying to load %s module\n", name); - return -1; -#endif -} - -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; - - ops = ldb_find_module_ops(module_list[i]); - if (ops == NULL) { - if (ldb_try_load_dso(ldb, module_list[i]) == 0) { - ops = ldb_find_module_ops(module_list[i]); - } - } - - 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; - - if (module && module->ops->init_context && - module->ops->init_context(module) != LDB_SUCCESS) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "module initialization failed\n"); - return LDB_ERR_OPERATIONS_ERROR; - } - - 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_explode(mem_ctx, "@MODULES"); - if (mods_dn == NULL) { - talloc_free(mem_ctx); - return -1; - } - - ret = ldb_search(ldb, ldb, &res, mods_dn, LDB_SCOPE_BASE, attrs, ""); - talloc_steal(mods_dn, res); - if (ret == LDB_SUCCESS && (res->count == 0 || res->msgs[0]->num_elements == 0)) { - ldb_debug(ldb, LDB_DEBUG_TRACE, "no modules required by the db\n"); - } 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 -1; - } - 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; - } - - modules = ldb_modules_list_from_string(ldb, mem_ctx, - (const char *)res->msgs[0]->elements[0].values[0].data); - - } - - talloc_free(mods_dn); - } - - if (modules != NULL) { - ret = ldb_load_modules_list(ldb, modules, ldb->modules, &ldb->modules); - talloc_free(modules); - if (ret != LDB_SUCCESS) { - return ret; - } - } else { - ldb_debug(ldb, LDB_DEBUG_TRACE, "No modules specified for this database\n"); - } - - return ldb_init_module_chain(ldb, ldb->modules); -} - -/* - 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) - - -/* - helper functions to call the next module in chain -*/ - -int ldb_next_request(struct ldb_module *module, struct ldb_request *request) -{ - switch (request->operation) { - case LDB_SEARCH: - FIND_OP(module, search); - return module->ops->search(module, request); - case LDB_ADD: - FIND_OP(module, add); - return module->ops->add(module, request); - case LDB_MODIFY: - FIND_OP(module, modify); - return module->ops->modify(module, request); - case LDB_DELETE: - FIND_OP(module, del); - return module->ops->del(module, request); - case LDB_RENAME: - FIND_OP(module, rename); - return module->ops->rename(module, request); - case LDB_SEQUENCE_NUMBER: - FIND_OP(module, sequence_number); - return module->ops->sequence_number(module, request); - default: - FIND_OP(module, request); - return module->ops->request(module, request); - } -} - -int ldb_next_init(struct ldb_module *module) -{ - /* init is different in that it is not an error if modules - * do not require initialization */ - - module = module->next; - - while (module && module->ops->init_context == NULL) - module = module->next; - - if (module == NULL) - return LDB_SUCCESS; - - return module->ops->init_context(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); -} diff --git a/source3/lib/ldb/common/ldb_msg.c b/source3/lib/ldb/common/ldb_msg.c deleted file mode 100644 index a8a6e93f12..0000000000 --- a/source3/lib/ldb/common/ldb_msg.c +++ /dev/null @@ -1,829 +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 . -*/ - -/* - * Name: ldb - * - * Component: ldb message component utility functions - * - * Description: functions for manipulating ldb_message structures - * - * Author: Andrew Tridgell - */ - -#include "includes.h" -#include "ldb/include/includes.h" - -void ldb_dump_results(struct ldb_context *ldb, struct ldb_result *result, FILE *f); -int ldb_msg_element_compare_name(struct ldb_message_element *el1, - struct ldb_message_element *el2); - -/* - 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;inum_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;inum_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; - - if (! ldb_valid_attr_name(attr_name)) { - return LDB_ERR_OPERATIONS_ERROR; - } - - 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) -{ - if (ldb_msg_add_empty(msg, el->name, flags, NULL) != 0) { - return LDB_ERR_OPERATIONS_ERROR; - } - - msg->elements[msg->num_elements-1] = *el; - 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;inum_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 (strcasecmp((const char *)v->data, "FALSE") == 0) { - return 0; - } - if (strcasecmp((const char *)v->data, "TRUE") == 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(void *mem_ctx, - const struct ldb_message *msg, - const char *attr_name) -{ - const struct ldb_val *v; - - v = ldb_msg_find_ldb_val(msg, attr_name); - if (!v || !v->data) { - return NULL; - } - return ldb_dn_explode(mem_ctx, (const char *)v->data); -} - -/* - 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->private_data = NULL; - - msg2->elements = talloc_array(msg2, struct ldb_message_element, - msg2->num_elements); - if (msg2->elements == NULL) goto failed; - - for (i=0;inum_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;inum_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;jnum_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;inum_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+1num_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;inum_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;inum_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_linearize(mem_ctx, 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; - for (i=0;attrs[i];i++) /* noop */ ; - 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[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 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) { - 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 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--; -} - -/* - return a LDAP formatted time string -*/ -char *ldb_timestring(TALLOC_CTX *mem_ctx, time_t t) -{ - struct tm *tm = gmtime(&t); - - if (!tm) { - return NULL; - } - - /* formatted like: 20040408072012.0Z */ - return talloc_asprintf(mem_ctx, - "%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); -} - - -/* - convert a LDAP time 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); -} - - -/* - 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/source3/lib/ldb/common/ldb_parse.c b/source3/lib/ldb/common/ldb_parse.c deleted file mode 100644 index bcc92c5b5c..0000000000 --- a/source3/lib/ldb/common/ldb_parse.c +++ /dev/null @@ -1,818 +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 . -*/ - -/* - * 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 "includes.h" -#include "ldb/include/includes.h" -#include "system/locale.h" - -struct ldb_val ldb_binary_decode(void *mem_ctx, const char *str); - -/* -a filter is defined by: - ::= '(' ')' - ::= | | | - ::= '&' - ::= '|' - ::= '!' - ::= | - ::= - ::= '=' | '~=' | '<=' | '>=' -*/ - -/* - 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;idata == 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; - - 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; -} - -/* - ::= -*/ -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 - ::= '&' - ::= '|' - ::= | -*/ -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; -} - - -/* - ::= '!' -*/ -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 - ::= | | | -*/ -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; -} - - -/* - ::= '(' ')' -*/ -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 ::= | -*/ -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;iu.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;iu.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/source3/lib/ldb/common/ldb_utf8.c b/source3/lib/ldb/common/ldb_utf8.c deleted file mode 100644 index c576453b27..0000000000 --- a/source3/lib/ldb/common/ldb_utf8.c +++ /dev/null @@ -1,148 +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 . -*/ - -/* - * Name: ldb - * - * Component: ldb utf8 handling - * - * Description: case folding and case comparison for UTF8 strings - * - * Author: Andrew Tridgell - */ - -#include "includes.h" -#include "ldb/include/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 *)) -{ - 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) -{ - int i; - char *ret = talloc_strdup(mem_ctx, s); - 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) -{ - return ldb->utf8_fns.casefold(ldb->utf8_fns.context, mem_ctx, s); -} - -/* - 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; -} - -/* - compare two attribute names - attribute names are restricted by rfc2251 so using - strcasecmp and toupper here is ok. - return 0 for match -*/ -int ldb_attr_cmp(const char *attr1, const char *attr2) -{ - return strcasecmp(attr1, attr2); -} - -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/source3/lib/ldb/common/qsort.c b/source3/lib/ldb/common/qsort.c deleted file mode 100644 index 79dd64128f..0000000000 --- a/source3/lib/ldb/common/qsort.c +++ /dev/null @@ -1,252 +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 . */ - -/* 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 2005 - */ - -#include "includes.h" -#include "ldb/include/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; - } - } - } - } -} -- cgit