From 79ebe463e2aed9125c9086f6bff99adeef5e4b88 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 15 Nov 2004 11:42:17 +0000 Subject: r3755: add missing files (This used to be commit 0b715b6ce21d23970d207d57e90133be17790d15) --- source4/lib/ldb/modules/skel.c | 123 ++++++++++++++++ source4/lib/ldb/modules/timestamps.c | 277 +++++++++++++++++++++++++++++++++++ 2 files changed, 400 insertions(+) create mode 100644 source4/lib/ldb/modules/skel.c create mode 100644 source4/lib/ldb/modules/timestamps.c (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/skel.c b/source4/lib/ldb/modules/skel.c new file mode 100644 index 0000000000..1d6314ee74 --- /dev/null +++ b/source4/lib/ldb/modules/skel.c @@ -0,0 +1,123 @@ +/* + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb skel module + * + * Description: example module + * + * Author: Simo Sorce + */ + +#include "includes.h" + +/* close */ +static int skel_close(struct ldb_module *module) +{ + return ldb_next_close(module); +} + +/* search */ +static int skel_search(struct ldb_module *module, const char *base, + enum ldb_scope scope, const char *expression, + const char * const *attrs, struct ldb_message ***res) +{ + return ldb_next_search(module, base, scope, expression, attrs, res); +} + +/* search_free */ +static int skel_search_free(struct ldb_module *module, struct ldb_message **res) +{ + return ldb_next_search_free(module, res); +} + +/* add_record */ +static int skel_add_record(struct ldb_module *module, const struct ldb_message *msg) +{ + return ldb_next_add_record(module, msg); +} + +/* modify_record */ +static int skel_modify_record(struct ldb_module *module, const struct ldb_message *msg) +{ + return ldb_next_modify_record(module, msg); +} + +/* delete_record */ +static int skel_delete_record(struct ldb_module *module, const char *dn) +{ + return ldb_next_delete_record(module, dn); +} + +/* rename_record */ +static int skel_rename_record(struct ldb_module *module, const char *olddn, const char *newdn) +{ + return ldb_next_rename_record(module, olddn, newdn); +} + +/* return extended error information */ +static const char *skel_errstring(struct ldb_module *module) +{ + return ldb_next_errstring(module); +} + +static void skel_cache_free(struct ldb_module *module) +{ + ldb_next_cache_free(module); +} + +static const struct ldb_module_ops skel_ops = { + "skel", + skel_close, + skel_search, + skel_search_free, + skel_add_record, + skel_modify_record, + skel_delete_record, + skel_rename_record, + skel_errstring, + skel_cache_free +}; + +#ifdef HAVE_DLOPEN + struct ldb_module *init_module(struct ldb_context *ldb, const char *options[]) +#else +struct ldb_module *skel_plugin_init(struct ldb_context *ldb, const char *options[]) +#endif +{ + struct ldb_module *ctx; + + ctx = (struct ldb_module *)malloc(sizeof(struct ldb_module)); + if (!ctx) + return NULL; + + ctx->ldb = ldb; + ctx->prev = ctx->next = NULL; + ctx->private_data = NULL; + ctx->ops = &skel_ops; + + return ctx; +} diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c new file mode 100644 index 0000000000..64d7616fb1 --- /dev/null +++ b/source4/lib/ldb/modules/timestamps.c @@ -0,0 +1,277 @@ +/* + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb timestamps module + * + * Description: add object timestamping functionality + * + * Author: Simo Sorce + */ + +#include "includes.h" +#include + +static int timestamps_close(struct ldb_module *module) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_close\n"); + return ldb_next_close(module); +} + +static int timestamps_search(struct ldb_module *module, const char *base, + enum ldb_scope scope, const char *expression, + const char * const *attrs, struct ldb_message ***res) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_search\n"); + return ldb_next_search(module, base, scope, expression, attrs, res); +} + +static int timestamps_search_free(struct ldb_module *module, struct ldb_message **res) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_search_free\n"); + return ldb_next_search_free(module, res); +} + +static int add_time_element(struct ldb_context *ldb, struct ldb_message *msg, const char *attr_name, const char *time_string, unsigned int flags) +{ + struct ldb_val *values; + char *name, *timestr; + int i; + + for (i = 0; i < msg->num_elements; i++) { + if (strcasecmp(msg->elements[i].name, attr_name) == 0) { + return 0; + } + } + + msg->elements = ldb_realloc_array(ldb, msg->elements, sizeof(struct ldb_message_element), msg->num_elements + 1); + name = ldb_strdup(ldb, attr_name); + timestr = ldb_strdup(ldb, time_string); + values = ldb_malloc(ldb, sizeof(struct ldb_val)); + if (!msg->elements || !name || !timestr || !values) { + return -1; + } + + msg->elements[msg->num_elements].name = name; + msg->elements[msg->num_elements].flags = flags; + msg->elements[msg->num_elements].num_values = 1; + msg->elements[msg->num_elements].values = values; + msg->elements[msg->num_elements].values[0].data = timestr; + msg->elements[msg->num_elements].values[0].length = strlen(timestr); + + msg->num_elements += 1; + + return 0; +} + +static void free_elements(struct ldb_context *ldb, struct ldb_message *msg, int real_el_num) +{ + int i; + + for (i = real_el_num; i < msg->num_elements; i++) { + ldb_free(ldb, msg->elements[i].name); + ldb_free(ldb, msg->elements[i].values[0].data); + ldb_free(ldb, msg->elements[i].values); + } + ldb_free(ldb, msg->elements); + ldb_free(ldb, msg); +} + +/* add_record: add crateTimestamp/modifyTimestamp attributes */ +static int timestamps_add_record(struct ldb_module *module, const struct ldb_message *msg) +{ + struct ldb_message *msg2 = NULL; + struct tm *tm; + char *timestr; + time_t timeval; + int ret, i; + + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_add_record\n"); + + if (msg->dn[0] != '@') { /* do not manipulate our control entries */ + timeval = time(NULL); + tm = gmtime(&timeval); + if (!tm) { + return -1; + } + + /* formatted like: 20040408072012.0Z */ + ldb_asprintf(module->ldb, ×tr, + "%04u%02u%02u%02u%02u%02u.0Z", + tm->tm_year+1900, tm->tm_mon+1, + tm->tm_mday, tm->tm_hour, tm->tm_min, + tm->tm_sec); + + if (!timestr) { + return -1; + } + + msg2 = ldb_malloc_p(module->ldb, struct ldb_message); + if (!msg2) { + return -1; + } + msg2->dn = msg->dn; + msg2->num_elements = msg->num_elements; + msg2->private_data = msg->private_data; + msg2->elements = ldb_malloc_array_p(module->ldb, struct ldb_message_element, msg2->num_elements); + for (i = 0; i < msg2->num_elements; i++) { + msg2->elements[i] = msg->elements[i]; + } + + add_time_element(module->ldb, msg2, "createTimestamp", timestr, LDB_FLAG_MOD_ADD); + add_time_element(module->ldb, msg2, "modifyTimestamp", timestr, LDB_FLAG_MOD_ADD); + add_time_element(module->ldb, msg2, "whenCreated", timestr, LDB_FLAG_MOD_ADD); + add_time_element(module->ldb, msg2, "whenChanged", timestr, LDB_FLAG_MOD_ADD); + + ldb_free(module->ldb, timestr); + } + + if (msg2) { + ret = ldb_next_add_record(module, msg2); + free_elements(module->ldb, msg2, msg->num_elements); + } else { + ret = ldb_next_add_record(module, msg); + } + + return ret; +} + +/* modify_record: change modifyTimestamp as well */ +static int timestamps_modify_record(struct ldb_module *module, const struct ldb_message *msg) +{ + struct ldb_message *msg2 = NULL; + struct tm *tm; + char *timestr; + time_t timeval; + int ret, i; + + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_modify_record\n"); + + if (msg->dn[0] != '@') { /* do not manipulate our control entries */ + timeval = time(NULL); + tm = gmtime(&timeval); + if (!tm) { + return -1; + } + + /* formatted like: 20040408072012.0Z */ + ldb_asprintf(module->ldb, ×tr, + "%04u%02u%02u%02u%02u%02u.0Z", + tm->tm_year+1900, tm->tm_mon+1, + tm->tm_mday, tm->tm_hour, tm->tm_min, + tm->tm_sec); + + if (!timestr) { + return -1; + } + + msg2 = ldb_malloc_p(module->ldb, struct ldb_message); + if (!msg2) { + return -1; + } + msg2->dn = msg->dn; + msg2->num_elements = msg->num_elements; + msg2->private_data = msg->private_data; + msg2->elements = ldb_malloc_array_p(module->ldb, struct ldb_message_element, msg2->num_elements); + for (i = 0; i < msg2->num_elements; i++) { + msg2->elements[i] = msg->elements[i]; + } + + add_time_element(module->ldb, msg2, "modifyTimestamp", timestr, LDB_FLAG_MOD_REPLACE); + add_time_element(module->ldb, msg2, "whenChanged", timestr, LDB_FLAG_MOD_REPLACE); + + ldb_free(module->ldb, timestr); + } + + if (msg2) { + ret = ldb_next_modify_record(module, msg2); + free_elements(module->ldb, msg2, msg->num_elements); + } else { + ret = ldb_next_modify_record(module, msg); + } + + return ret; +} + +static int timestamps_delete_record(struct ldb_module *module, const char *dn) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_delete_record\n"); + return ldb_next_delete_record(module, dn); +} + +static int timestamps_rename_record(struct ldb_module *module, const char *olddn, const char *newdn) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_rename_record\n"); + return ldb_next_rename_record(module, olddn, newdn); +} + +/* return extended error information */ +static const char *timestamps_errstring(struct ldb_module *module) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_errstring\n"); + return ldb_next_errstring(module); +} + +static void timestamps_cache_free(struct ldb_module *module) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_cache_free\n"); + ldb_next_cache_free(module); +} + +static const struct ldb_module_ops timestamps_ops = { + "timestamps", + timestamps_close, + timestamps_search, + timestamps_search_free, + timestamps_add_record, + timestamps_modify_record, + timestamps_delete_record, + timestamps_rename_record, + timestamps_errstring, + timestamps_cache_free +}; + + +/* the init function */ +#ifdef HAVE_DLOPEN_DISABLED + struct ldb_module *init_module(struct ldb_context *ldb, const char *options[]) +#else +struct ldb_module *timestamps_module_init(struct ldb_context *ldb, const char *options[]) +#endif +{ + struct ldb_module *ctx; + + ctx = (struct ldb_module *)malloc(sizeof(struct ldb_module)); + if (!ctx) + return NULL; + + ctx->ldb = ldb; + ctx->prev = ctx->next = NULL; + ctx->private_data = NULL; + ctx->ops = ×tamps_ops; + + return ctx; +} -- cgit From 8a18778286a16423d7d6e483fdb308a91e294efe Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 16 Nov 2004 09:00:52 +0000 Subject: r3783: - don't use make proto for ldb anymore - split ldh.h out of samba's includes.h - make ldb_context and ldb_module private to the subsystem - use ltdb_ prefix for all ldb_tdb functions metze (This used to be commit f5ee40d6ce8224e280070975efc9911558fe675c) --- source4/lib/ldb/modules/skel.c | 2 ++ source4/lib/ldb/modules/timestamps.c | 2 ++ 2 files changed, 4 insertions(+) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/skel.c b/source4/lib/ldb/modules/skel.c index 1d6314ee74..331a2de5e4 100644 --- a/source4/lib/ldb/modules/skel.c +++ b/source4/lib/ldb/modules/skel.c @@ -33,6 +33,8 @@ */ #include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" /* close */ static int skel_close(struct ldb_module *module) diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index 64d7616fb1..521c59d241 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -33,6 +33,8 @@ */ #include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" #include static int timestamps_close(struct ldb_module *module) -- cgit From a4de8cd6a5a882a8d49fdb4b0e625ffdc6b401bb Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 21 Nov 2004 15:51:54 +0000 Subject: r3897: add a locking infrastructure (This used to be commit a99c0adb09e2bc77b876d23cb2d0711ccffd83ca) --- source4/lib/ldb/modules/skel.c | 14 ++++++++++++++ source4/lib/ldb/modules/timestamps.c | 14 ++++++++++++++ 2 files changed, 28 insertions(+) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/skel.c b/source4/lib/ldb/modules/skel.c index 331a2de5e4..3581969c18 100644 --- a/source4/lib/ldb/modules/skel.c +++ b/source4/lib/ldb/modules/skel.c @@ -80,6 +80,18 @@ static int skel_rename_record(struct ldb_module *module, const char *olddn, cons return ldb_next_rename_record(module, olddn, newdn); } +/* named_lock */ +static const char *skel_named_lock(struct ldb_module *module, const char *lockname) +{ + return ldb_next_named_lock(module, lockname); +} + +/* named_unlock */ +static const char *skel_named_unlock(struct ldb_module *module, const char *lockname) +{ + return ldb_next_named_unlock(module, lockname); +} + /* return extended error information */ static const char *skel_errstring(struct ldb_module *module) { @@ -100,6 +112,8 @@ static const struct ldb_module_ops skel_ops = { skel_modify_record, skel_delete_record, skel_rename_record, + skel_named_lock, + skel_named_unlock, skel_errstring, skel_cache_free }; diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index 521c59d241..fde87ef4a6 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -230,6 +230,18 @@ static int timestamps_rename_record(struct ldb_module *module, const char *olddn return ldb_next_rename_record(module, olddn, newdn); } +static int timestamps_lock(struct ldb_module *module, const char *lockname) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_lock\n"); + return ldb_next_named_lock(module, lockname); +} + +static int timestamps_unlock(struct ldb_module *module, const char *lockname) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_unlock\n"); + return ldb_next_named_unlock(module, lockname); +} + /* return extended error information */ static const char *timestamps_errstring(struct ldb_module *module) { @@ -252,6 +264,8 @@ static const struct ldb_module_ops timestamps_ops = { timestamps_modify_record, timestamps_delete_record, timestamps_rename_record, + timestamps_lock, + timestamps_unlock, timestamps_errstring, timestamps_cache_free }; -- cgit From 1a988ec9af7960616fb4661b20d86ff05146d836 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 2 Jan 2005 07:49:29 +0000 Subject: r4474: - converted ldb to use talloc internally - added gcov flags to Makefile.ldb - expanded ldb test suite to get more coverage (This used to be commit 0ab98f50a7e0fe15347a99e5c29a6590a87729a0) --- source4/lib/ldb/modules/skel.c | 8 +--- source4/lib/ldb/modules/timestamps.c | 79 +++++++++++++----------------------- 2 files changed, 29 insertions(+), 58 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/skel.c b/source4/lib/ldb/modules/skel.c index 3581969c18..afafe1bbd9 100644 --- a/source4/lib/ldb/modules/skel.c +++ b/source4/lib/ldb/modules/skel.c @@ -98,11 +98,6 @@ static const char *skel_errstring(struct ldb_module *module) return ldb_next_errstring(module); } -static void skel_cache_free(struct ldb_module *module) -{ - ldb_next_cache_free(module); -} - static const struct ldb_module_ops skel_ops = { "skel", skel_close, @@ -114,8 +109,7 @@ static const struct ldb_module_ops skel_ops = { skel_rename_record, skel_named_lock, skel_named_unlock, - skel_errstring, - skel_cache_free + skel_errstring }; #ifdef HAVE_DLOPEN diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index fde87ef4a6..53c39e751e 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -57,7 +57,8 @@ static int timestamps_search_free(struct ldb_module *module, struct ldb_message return ldb_next_search_free(module, res); } -static int add_time_element(struct ldb_context *ldb, struct ldb_message *msg, const char *attr_name, const char *time_string, unsigned int flags) +static int add_time_element(struct ldb_context *ldb, struct ldb_message *msg, + const char *attr_name, const char *time_string, unsigned int flags) { struct ldb_val *values; char *name, *timestr; @@ -69,10 +70,11 @@ static int add_time_element(struct ldb_context *ldb, struct ldb_message *msg, co } } - msg->elements = ldb_realloc_array(ldb, msg->elements, sizeof(struct ldb_message_element), msg->num_elements + 1); - name = ldb_strdup(ldb, attr_name); - timestr = ldb_strdup(ldb, time_string); - values = ldb_malloc(ldb, sizeof(struct ldb_val)); + msg->elements = talloc_realloc_p(msg, msg->elements, + struct ldb_message_element, msg->num_elements + 1); + name = talloc_strdup(msg->elements, attr_name); + timestr = talloc_strdup(msg->elements, time_string); + values = talloc_p(msg->elements, struct ldb_val); if (!msg->elements || !name || !timestr || !values) { return -1; } @@ -89,19 +91,6 @@ static int add_time_element(struct ldb_context *ldb, struct ldb_message *msg, co return 0; } -static void free_elements(struct ldb_context *ldb, struct ldb_message *msg, int real_el_num) -{ - int i; - - for (i = real_el_num; i < msg->num_elements; i++) { - ldb_free(ldb, msg->elements[i].name); - ldb_free(ldb, msg->elements[i].values[0].data); - ldb_free(ldb, msg->elements[i].values); - } - ldb_free(ldb, msg->elements); - ldb_free(ldb, msg); -} - /* add_record: add crateTimestamp/modifyTimestamp attributes */ static int timestamps_add_record(struct ldb_module *module, const struct ldb_message *msg) { @@ -120,25 +109,24 @@ static int timestamps_add_record(struct ldb_module *module, const struct ldb_mes return -1; } - /* formatted like: 20040408072012.0Z */ - ldb_asprintf(module->ldb, ×tr, - "%04u%02u%02u%02u%02u%02u.0Z", - tm->tm_year+1900, tm->tm_mon+1, - tm->tm_mday, tm->tm_hour, tm->tm_min, - tm->tm_sec); - - if (!timestr) { + msg2 = talloc_p(module, struct ldb_message); + if (!msg2) { return -1; } - msg2 = ldb_malloc_p(module->ldb, struct ldb_message); - if (!msg2) { + /* formatted like: 20040408072012.0Z */ + timestr = talloc_asprintf(msg2, "%04u%02u%02u%02u%02u%02u.0Z", + tm->tm_year+1900, tm->tm_mon+1, + tm->tm_mday, tm->tm_hour, tm->tm_min, + tm->tm_sec); + if (!timestr) { return -1; } + msg2->dn = msg->dn; msg2->num_elements = msg->num_elements; msg2->private_data = msg->private_data; - msg2->elements = ldb_malloc_array_p(module->ldb, struct ldb_message_element, msg2->num_elements); + msg2->elements = talloc_array_p(msg2, struct ldb_message_element, msg2->num_elements); for (i = 0; i < msg2->num_elements; i++) { msg2->elements[i] = msg->elements[i]; } @@ -147,13 +135,11 @@ static int timestamps_add_record(struct ldb_module *module, const struct ldb_mes add_time_element(module->ldb, msg2, "modifyTimestamp", timestr, LDB_FLAG_MOD_ADD); add_time_element(module->ldb, msg2, "whenCreated", timestr, LDB_FLAG_MOD_ADD); add_time_element(module->ldb, msg2, "whenChanged", timestr, LDB_FLAG_MOD_ADD); - - ldb_free(module->ldb, timestr); } if (msg2) { ret = ldb_next_add_record(module, msg2); - free_elements(module->ldb, msg2, msg->num_elements); + talloc_free(msg2); } else { ret = ldb_next_add_record(module, msg); } @@ -179,38 +165,36 @@ static int timestamps_modify_record(struct ldb_module *module, const struct ldb_ return -1; } + msg2 = talloc_p(module, struct ldb_message); + if (!msg2) { + return -1; + } + /* formatted like: 20040408072012.0Z */ - ldb_asprintf(module->ldb, ×tr, + timestr = talloc_asprintf(msg2, "%04u%02u%02u%02u%02u%02u.0Z", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); - if (!timestr) { return -1; } - msg2 = ldb_malloc_p(module->ldb, struct ldb_message); - if (!msg2) { - return -1; - } msg2->dn = msg->dn; msg2->num_elements = msg->num_elements; msg2->private_data = msg->private_data; - msg2->elements = ldb_malloc_array_p(module->ldb, struct ldb_message_element, msg2->num_elements); + msg2->elements = talloc_array_p(msg2, struct ldb_message_element, msg2->num_elements); for (i = 0; i < msg2->num_elements; i++) { msg2->elements[i] = msg->elements[i]; } add_time_element(module->ldb, msg2, "modifyTimestamp", timestr, LDB_FLAG_MOD_REPLACE); add_time_element(module->ldb, msg2, "whenChanged", timestr, LDB_FLAG_MOD_REPLACE); - - ldb_free(module->ldb, timestr); } if (msg2) { ret = ldb_next_modify_record(module, msg2); - free_elements(module->ldb, msg2, msg->num_elements); + talloc_free(msg2); } else { ret = ldb_next_modify_record(module, msg); } @@ -249,12 +233,6 @@ static const char *timestamps_errstring(struct ldb_module *module) return ldb_next_errstring(module); } -static void timestamps_cache_free(struct ldb_module *module) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_cache_free\n"); - ldb_next_cache_free(module); -} - static const struct ldb_module_ops timestamps_ops = { "timestamps", timestamps_close, @@ -266,8 +244,7 @@ static const struct ldb_module_ops timestamps_ops = { timestamps_rename_record, timestamps_lock, timestamps_unlock, - timestamps_errstring, - timestamps_cache_free + timestamps_errstring }; @@ -280,7 +257,7 @@ struct ldb_module *timestamps_module_init(struct ldb_context *ldb, const char *o { struct ldb_module *ctx; - ctx = (struct ldb_module *)malloc(sizeof(struct ldb_module)); + ctx = talloc_p(ldb, struct ldb_module); if (!ctx) return NULL; -- cgit From ab4e92ab21887430774fda380ccbb14a10cab2da Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 3 Jan 2005 08:52:39 +0000 Subject: r4502: add an error reporting function (This used to be commit 985a58a16d04f3b92b4bbff86f6c466385f01321) --- source4/lib/ldb/modules/timestamps.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index 53c39e751e..95a2ddc88e 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -230,6 +230,14 @@ static int timestamps_unlock(struct ldb_module *module, const char *lockname) static const char *timestamps_errstring(struct ldb_module *module) { ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_errstring\n"); + if (data->error_string) { + char *error; + + error = data->error_string; + data->error_string = NULL; + return error; + } + return ldb_next_errstring(module); } @@ -256,14 +264,22 @@ struct ldb_module *timestamps_module_init(struct ldb_context *ldb, const char *o #endif { struct ldb_module *ctx; + struct private_data *data; ctx = talloc_p(ldb, struct ldb_module); if (!ctx) return NULL; + data = talloc_p(ctx, struct private_data); + if (!data) { + talloc_free(ctx); + return NULL; + } + + data->error_string = NULL; + ctx->private_data = data; ctx->ldb = ldb; ctx->prev = ctx->next = NULL; - ctx->private_data = NULL; ctx->ops = ×tamps_ops; return ctx; -- cgit From 8164d2442868a2e8353ee2ae3d61f78aa9ccb226 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 3 Jan 2005 08:59:00 +0000 Subject: r4503: add an error reporting function (fixes) (This used to be commit d11732f4f7f9bc535222aa7a6dd2f15cf5002a4d) --- source4/lib/ldb/modules/timestamps.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index 95a2ddc88e..719aed19ba 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -37,6 +37,10 @@ #include "ldb/include/ldb_private.h" #include +struct private_data { + const char *error_string; +}; + static int timestamps_close(struct ldb_module *module) { ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_close\n"); @@ -57,9 +61,10 @@ static int timestamps_search_free(struct ldb_module *module, struct ldb_message return ldb_next_search_free(module, res); } -static int add_time_element(struct ldb_context *ldb, struct ldb_message *msg, +static int add_time_element(struct ldb_module *module, struct ldb_message *msg, const char *attr_name, const char *time_string, unsigned int flags) { + struct private_data *data = (struct private_data *)module->private_data; struct ldb_val *values; char *name, *timestr; int i; @@ -94,6 +99,7 @@ static int add_time_element(struct ldb_context *ldb, struct ldb_message *msg, /* add_record: add crateTimestamp/modifyTimestamp attributes */ static int timestamps_add_record(struct ldb_module *module, const struct ldb_message *msg) { + struct private_data *data = (struct private_data *)module->private_data; struct ldb_message *msg2 = NULL; struct tm *tm; char *timestr; @@ -131,10 +137,10 @@ static int timestamps_add_record(struct ldb_module *module, const struct ldb_mes msg2->elements[i] = msg->elements[i]; } - add_time_element(module->ldb, msg2, "createTimestamp", timestr, LDB_FLAG_MOD_ADD); - add_time_element(module->ldb, msg2, "modifyTimestamp", timestr, LDB_FLAG_MOD_ADD); - add_time_element(module->ldb, msg2, "whenCreated", timestr, LDB_FLAG_MOD_ADD); - add_time_element(module->ldb, msg2, "whenChanged", timestr, LDB_FLAG_MOD_ADD); + add_time_element(module, msg2, "createTimestamp", timestr, LDB_FLAG_MOD_ADD); + add_time_element(module, msg2, "modifyTimestamp", timestr, LDB_FLAG_MOD_ADD); + add_time_element(module, msg2, "whenCreated", timestr, LDB_FLAG_MOD_ADD); + add_time_element(module, msg2, "whenChanged", timestr, LDB_FLAG_MOD_ADD); } if (msg2) { @@ -150,6 +156,7 @@ static int timestamps_add_record(struct ldb_module *module, const struct ldb_mes /* modify_record: change modifyTimestamp as well */ static int timestamps_modify_record(struct ldb_module *module, const struct ldb_message *msg) { + struct private_data *data = (struct private_data *)module->private_data; struct ldb_message *msg2 = NULL; struct tm *tm; char *timestr; @@ -188,8 +195,8 @@ static int timestamps_modify_record(struct ldb_module *module, const struct ldb_ msg2->elements[i] = msg->elements[i]; } - add_time_element(module->ldb, msg2, "modifyTimestamp", timestr, LDB_FLAG_MOD_REPLACE); - add_time_element(module->ldb, msg2, "whenChanged", timestr, LDB_FLAG_MOD_REPLACE); + add_time_element(module, msg2, "modifyTimestamp", timestr, LDB_FLAG_MOD_REPLACE); + add_time_element(module, msg2, "whenChanged", timestr, LDB_FLAG_MOD_REPLACE); } if (msg2) { @@ -229,9 +236,11 @@ static int timestamps_unlock(struct ldb_module *module, const char *lockname) /* return extended error information */ static const char *timestamps_errstring(struct ldb_module *module) { + struct private_data *data = (struct private_data *)module->private_data; + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_errstring\n"); if (data->error_string) { - char *error; + const char *error; error = data->error_string; data->error_string = NULL; -- cgit From b92afa3838ba14fbe66bb683949a7f3bce946faa Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 3 Jan 2005 14:05:47 +0000 Subject: r4505: Add a first very basic schema module To use it you should provide a schema.ldb file where the schema is stored and load the module in the ldb you want to have schema check activated more info soon. currently schema checks are performed only on new object creation not on modifications Simo. (This used to be commit b8bb62f14419efd434a344606fb3f753384761a0) --- source4/lib/ldb/modules/schema.c | 489 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 489 insertions(+) create mode 100644 source4/lib/ldb/modules/schema.c (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c new file mode 100644 index 0000000000..f083eeb6e5 --- /dev/null +++ b/source4/lib/ldb/modules/schema.c @@ -0,0 +1,489 @@ +/* + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb schema module + * + * Description: add schema check functionality + * + * Author: Simo Sorce + */ + +#include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" + +struct attribute_syntax { + const char *name; + const char *syntax_id; +}; + +static struct attribute_syntax attrsyn[] = { + { "Object(DS-DN)", "2.5.5.1"}, + { "String(Object-Identifier)", "2.5.5.2"}, + { "", "2.5.5.3"}, + { "String(Teletex)", "2.5.5.4"}, + { "String(IA5)", "2.5.5.5"}, /* Also String(Printable) */ + { "String(Numeric)", "2.5.5.6"}, + { "Object(DN-Binary)", "2.5.5.7"}, /* Also Object(OR-Name) */ + { "Boolean", "2.5.5.8"}, + { "Integer", "2.5.5.9"}, /* Also Enumeration (3 types ?) ... */ + { "String(Octet)", "2.5.5.10"}, /* Also Object(Replica-Link) */ + { "String(UTC-Time)", "2.5.5.11"}, /* Also String(Generalized-Time) */ + { "String(Unicode)", "2.5.5.12"}, + { "Object(Presentation-Address)", "2.5.5.13"}, + { "Object(DN-String)", "2.5.5.14"}, /* Also Object(Access-Point) */ + { "String(NT-Sec-Desc))", "2.5.5.15"}, + { "LargeInteger", "2.5.5.16"}, /* Also Interval ... */ + { "String(Sid)", "2.5.5.17"} + }; + +#define SCHEMA_TALLOC_CHECK(root, mem, ret) do { if (!mem) { talloc_free(root); return ret;} } while(0); + +struct private_data { + struct ldb_context *schema_db; + const char *error_string; +}; + +/* close */ +static int schema_close(struct ldb_module *module) +{ + return ldb_next_close(module); +} + +/* search */ +static int schema_search(struct ldb_module *module, const char *base, + enum ldb_scope scope, const char *expression, + const char * const *attrs, struct ldb_message ***res) +{ + return ldb_next_search(module, base, scope, expression, attrs, res); +} + +/* search_free */ +static int schema_search_free(struct ldb_module *module, struct ldb_message **res) +{ + return ldb_next_search_free(module, res); +} + +struct check_list { + int check; + char *name; +}; + +struct attr_list { + int syntax; + char *name; +}; + +struct objc_list { + int aux; + char *name; +}; + +struct schema_structures { + struct check_list *cl; + struct objc_list *ol; + struct attr_list *must; + struct attr_list *may; + int num_cl; + int num_objc; + int num_must; + int num_may; +}; + +/* add_record */ +static int schema_add_record(struct ldb_module *module, const struct ldb_message *msg) +{ + struct private_data *data = (struct private_data *)module->private_data; + struct ldb_message **srch; + struct schema_structures *ss; + int i, j, k, l; + int ret; + + /* First implementation: + Build up a list of must and mays from each objectclass + Check all the musts are there and all the other attributes are mays + Throw an error in case a check fail + Free all structures and commit the change + */ + + ss = talloc_p(module, struct schema_structures); + if (!ss) { + return -1; + } + + ss->ol = NULL; + ss->num_cl = msg->num_elements; + ss->cl = talloc_array_p(ss, struct check_list, ss->num_cl); + SCHEMA_TALLOC_CHECK(ss, ss->cl, -1); + for (i = 0, j = 0; i < msg->num_elements; i++) { + if (strcasecmp(msg->elements[i].name, "objectclass") == 0) { + ss->num_objc = msg->elements[i].num_values; + ss->ol = talloc_array_p(ss, struct objc_list, ss->num_objc); + SCHEMA_TALLOC_CHECK(ss, ss->ol, -1); + for (k = 0; k < ss->num_objc; k++) { + ss->ol[k].name = talloc_strndup(ss->ol, msg->elements[i].values[k].data, msg->elements[i].values[k].length); + SCHEMA_TALLOC_CHECK(ss, ss->ol[k].name, -1); + ss->ol[k].aux = 0; + } + } + + ss->cl[j].check = 0; + ss->cl[j].name = talloc_strdup(ss->cl, msg->elements[i].name); + SCHEMA_TALLOC_CHECK(ss, ss->cl[j].name, -1); + j++; + } + + /* find all other objectclasses recursively */ + ss->must = NULL; + ss->may = NULL; + ss->num_must = 0; + ss->num_may = 0; + for (i = 0; i < ss->num_objc; i++) { + char *filter; + + filter = talloc_asprintf(ss, "lDAPDisplayName=%s", ss->ol[i].name); + SCHEMA_TALLOC_CHECK(ss, filter, -1); + ret = ldb_search(data->schema_db, NULL, LDB_SCOPE_SUBTREE, filter, NULL, &srch); + if (ret == 0) { + int ok; + + ok = 0; + /* suppose auxiliary classess are not required */ + if (ss->ol[i].aux) { + int d; + ok = 1; + ss->num_objc -= 1; + for (d = i; d < ss->num_objc; d++) { + ss->ol[d] = ss->ol[d + 1]; + } + i -= 1; + } + if (!ok) { + /* Schema Violation: Object Class Description Not Found */ + data->error_string = "ObjectClass not found"; + talloc_free(ss); + return -1; + } + continue; + } else { + if (ret < 0) { + /* Schema DB Error: Error occurred retrieving Object Class Description */ + data->error_string = "Internal error. Error retrieving schema objectclass"; + talloc_free(ss); + return -1; + } + if (ret > 1) { + /* Schema DB Error: Too Many Records */ + data->error_string = "Internal error. Too many records searching for schema objectclass"; + talloc_free(ss); + return -1; + } + } + + /* Add inherited classes eliminating duplicates */ + /* fill in kust and may attribute lists */ + for (j = 0; j < (*srch)->num_elements; j++) { + int o, is_aux, is_class; + + is_aux = 0; + is_class = 0; + if (strcasecmp((*srch)->elements[j].name, "systemAuxiliaryclass") == 0) { + is_aux = 1; + is_class = 1; + } + if (strcasecmp((*srch)->elements[j].name, "subClassOf") == 0) { + is_class = 1; + } + + if (is_class) { + o = (*srch)->elements[j].num_values; + ss->ol = talloc_realloc_p(ss, ss->ol, struct objc_list, ss->num_objc + o); + SCHEMA_TALLOC_CHECK(ss, ss->ol, -1); + for (k = 0, l = 0; k < o; k++) { + int c, found, len; + + found = 0; + for (c = 0; c < ss->num_objc; c++) { + len = strlen(ss->ol[c].name); + if (len == (*srch)->elements[j].values[k].length) { + if (strncasecmp(ss->ol[c].name, (*srch)->elements[j].values[k].data, len) == 0) { + found = 1; + break; + } + } + } + if (!found) { + ss->ol[l + ss->num_objc].name = talloc_strndup(ss->ol, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); + SCHEMA_TALLOC_CHECK(ss, ss->ol[l + ss->num_objc].name, -1); + ss->ol[l + ss->num_objc].aux = is_aux; + l++; + } + } + ss->num_objc += l; + } else { + + if (strcasecmp((*srch)->elements[j].name, "mustContain") == 0 || strcasecmp((*srch)->elements[j].name, "SystemMustContain") == 0) { + int m; + + m = (*srch)->elements[j].num_values; + + ss->must = talloc_realloc_p(ss, ss->must, struct attr_list, ss->num_must + m); + SCHEMA_TALLOC_CHECK(ss, ss->must, -1); + for (k = 0, l = 0; k < m; k++) { + int c, found, len; + + found = 0; + for (c = 0; c < ss->num_must; c++) { + len = strlen(ss->must[c].name); + if (len == (*srch)->elements[j].values[k].length) { + if (strncasecmp(ss->must[c].name, (*srch)->elements[j].values[k].data, len) == 0) { + found = 1; + break; + } + } + } + if (!found) { + ss->must[l + ss->num_must].name = talloc_strndup(ss->must, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); + SCHEMA_TALLOC_CHECK(ss, ss->must[l + ss->num_must].name, -1); + l++; + } + } + ss->num_must += l; + } + + if (strcasecmp((*srch)->elements[j].name, "mayContain") == 0 || strcasecmp((*srch)->elements[j].name, "SystemMayContain") == 0) { + int m; + + m = (*srch)->elements[j].num_values; + + ss->may = talloc_realloc_p(ss, ss->may, struct attr_list, ss->num_may + m); + SCHEMA_TALLOC_CHECK(ss, ss->may, -1); + for (k = 0, l = 0; k < m; k++) { + int c, found, len; + + found = 0; + for (c = 0; c < ss->num_may; c++) { + len = strlen(ss->may[c].name); + if (len == (*srch)->elements[j].values[k].length) { + if (strncasecmp(ss->may[c].name, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length) == 0) { + found = 1; + break; + } + } + } + if (!found) { + ss->may[l + ss->num_may].name = talloc_strndup(ss->may, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); + SCHEMA_TALLOC_CHECK(ss, ss->may[l + ss->num_may].name, -1); + l++; + } + } + ss->num_may += l; + } + } + } + + ldb_search_free(module->ldb, srch); + } + + /* now check all musts are present */ + for (i = 0; i < ss->num_must; i++) { + int found; + + found = 0; + for (j = 0; j < ss->num_cl; j++) { + if (strcasecmp(ss->must[i].name, ss->cl[j].name) == 0) { + ss->cl[j].check = 1; + found = 1; + break; + } + } + + if ( ! found ) { + /* TODO: set the error string */ + data->error_string = "Objectclass violation, a required attribute is missing"; + talloc_free(ss); + return -1; + } + } + + /* now check all others atribs are found in mays */ + for (i = 0; i < ss->num_cl; i++) { + + if ( ! ss->cl[i].check ) { + int found; + + found = 0; + for (j = 0; j < ss->num_may; j++) { + if (strcasecmp(ss->may[j].name, ss->cl[i].name) == 0) { + ss->cl[i].check = 1; + found = 1; + break; + } + } + + if ( ! found ) { + data->error_string = "Objectclass violation, an invalid attribute name was found"; + talloc_free(ss); + return -1; + } + } + } + + talloc_free(ss); + + return ldb_next_add_record(module, msg); +} + +/* modify_record */ +static int schema_modify_record(struct ldb_module *module, const struct ldb_message *msg) +{ + struct private_data *data = (struct private_data *)module->private_data; + return ldb_next_modify_record(module, msg); +} + +/* delete_record */ +static int schema_delete_record(struct ldb_module *module, const char *dn) +{ + struct private_data *data = (struct private_data *)module->private_data; + return ldb_next_delete_record(module, dn); +} + +/* rename_record */ +static int schema_rename_record(struct ldb_module *module, const char *olddn, const char *newdn) +{ + return ldb_next_rename_record(module, olddn, newdn); +} + +static int schema_named_lock(struct ldb_module *module, const char *name) { + return ldb_next_named_lock(module, name); +} + +static int schema_named_unlock(struct ldb_module *module, const char *name) { + return ldb_next_named_unlock(module, name); +} + +/* return extended error information */ +static const char *schema_errstring(struct ldb_module *module) +{ + struct private_data *data = (struct private_data *)module->private_data; + + if (data->error_string) { + const char *error; + + error = data->error_string; + data->error_string = NULL; + return error; + } + + return ldb_next_errstring(module); +} + +static const struct ldb_module_ops schema_ops = { + "schema", + schema_close, + schema_search, + schema_search_free, + schema_add_record, + schema_modify_record, + schema_delete_record, + schema_rename_record, + schema_named_lock, + schema_named_unlock, + schema_errstring, +}; + +#define SCHEMA_PREFIX "schema:" +#define SCHEMA_PREFIX_LEN 7 + +#ifdef HAVE_DLOPEN_DISABLED +struct ldb_module *init_module(struct ldb_context *ldb, const char *options[]) +#else +struct ldb_module *schema_module_init(struct ldb_context *ldb, const char *options[]) +#endif +{ + struct ldb_module *ctx; + struct private_data *data; + char *db_url = NULL; + int i; + + ctx = talloc_p(ldb, struct ldb_module); + if (!ctx) { + return NULL; + } + + if (options) { + for (i = 0; options[i] != NULL; i++) { + if (strncmp(options[i], SCHEMA_PREFIX, SCHEMA_PREFIX_LEN) == 0) { + db_url = talloc_strdup(ctx, &options[i][SCHEMA_PREFIX_LEN]); + SCHEMA_TALLOC_CHECK(ctx, db_url, NULL); + } + } + } + + if (!db_url) { /* search if it is defined in the calling ldb */ + int ret; + const char * attrs[] = { "@SCHEMADB", NULL }; + struct ldb_message **msgs; + + ret = ldb_search(ldb, "", LDB_SCOPE_BASE, "dn=@MODULES", (const char * const *)attrs, &msgs); + if (ret == 0) { + ldb_debug(ldb, LDB_DEBUG_TRACE, "Schema DB not found\n"); + ldb_search_free(ldb, msgs); + return NULL; + } else { + if (ret < 0) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "ldb error (%s) occurred searching for schema db, bailing out!\n", ldb_errstring(ldb)); + ldb_search_free(ldb, msgs); + return NULL; + } + if (ret > 1) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "Too many records found, bailing out\n"); + ldb_search_free(ldb, msgs); + return NULL; + } + + db_url = talloc_strndup(ctx, msgs[0]->elements[0].values[0].data, msgs[0]->elements[0].values[0].length); + SCHEMA_TALLOC_CHECK(ctx, db_url, NULL); + } + + ldb_search_free(ldb, msgs); + } + + data = talloc_p(ctx, struct private_data); + SCHEMA_TALLOC_CHECK(ctx, data, NULL); + + data->schema_db = ldb_connect(db_url, 0, NULL); + SCHEMA_TALLOC_CHECK(ctx, data->schema_db, NULL); + + data->error_string = NULL; + ctx->private_data = data; + ctx->ldb = ldb; + ctx->prev = ctx->next = NULL; + ctx->ops = &schema_ops; + + return ctx; +} -- cgit From bb71b37f702bc034a208060b599b384d47fb4fb9 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 3 Jan 2005 14:38:05 +0000 Subject: r4506: fix compiler warnings metze (This used to be commit 1c6accd7cbf9ccb7f642b85200671b9d4fe23f47) --- source4/lib/ldb/modules/timestamps.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index 719aed19ba..09679435f5 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -64,7 +64,6 @@ static int timestamps_search_free(struct ldb_module *module, struct ldb_message static int add_time_element(struct ldb_module *module, struct ldb_message *msg, const char *attr_name, const char *time_string, unsigned int flags) { - struct private_data *data = (struct private_data *)module->private_data; struct ldb_val *values; char *name, *timestr; int i; @@ -99,7 +98,6 @@ static int add_time_element(struct ldb_module *module, struct ldb_message *msg, /* add_record: add crateTimestamp/modifyTimestamp attributes */ static int timestamps_add_record(struct ldb_module *module, const struct ldb_message *msg) { - struct private_data *data = (struct private_data *)module->private_data; struct ldb_message *msg2 = NULL; struct tm *tm; char *timestr; @@ -156,7 +154,6 @@ static int timestamps_add_record(struct ldb_module *module, const struct ldb_mes /* modify_record: change modifyTimestamp as well */ static int timestamps_modify_record(struct ldb_module *module, const struct ldb_message *msg) { - struct private_data *data = (struct private_data *)module->private_data; struct ldb_message *msg2 = NULL; struct tm *tm; char *timestr; -- cgit From 8d8c21f8d0669b469b2540c3f9e91ca5d076db09 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 4 Jan 2005 15:18:50 +0000 Subject: r4513: add experimental modification attribute checking still not complete but works with add and replace, not tested with delete lot of duplicated code to remove (This used to be commit ea051f6cd39d0e729bb425eb08034a0eee0996dc) --- source4/lib/ldb/modules/schema.c | 452 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 451 insertions(+), 1 deletion(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index f083eeb6e5..1f9017976e 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -136,6 +136,7 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message } ss->ol = NULL; + ss->num_objc = 0; ss->num_cl = msg->num_elements; ss->cl = talloc_array_p(ss, struct check_list, ss->num_cl); SCHEMA_TALLOC_CHECK(ss, ss->cl, -1); @@ -306,7 +307,7 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message } } - ldb_search_free(module->ldb, srch); + ldb_search_free(data->schema_db, srch); } /* now check all musts are present */ @@ -362,6 +363,455 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message static int schema_modify_record(struct ldb_module *module, const struct ldb_message *msg) { struct private_data *data = (struct private_data *)module->private_data; + struct ldb_message **srch; + struct schema_structures *ss, *ms; + int i, j, k, l; + int ret; + + /* First implementation: + Retrieve the ldap entry and get the objectclasses, + add msg contained objectclasses if any. + Build up a list of must and mays from each objectclass + Check all musts for the defined objectclass and it's specific + inheritance are there. + Check all other the attributes are mays or musts. + Throw an error in case a check fail. + Free all structures and commit the change. + */ + + ss = talloc_p(module, struct schema_structures); + if (!ss) { + return -1; + } + + ms = talloc_p(module, struct schema_structures); + SCHEMA_TALLOC_CHECK(ss, ms, -1); + + ms->ol = NULL; + ms->num_objc = 0; + ms->num_cl = msg->num_elements; + ms->cl = talloc_array_p(ms, struct check_list, ms->num_cl); + SCHEMA_TALLOC_CHECK(ss, ms->cl, -1); + for (i = 0, j = 0; i < msg->num_elements; i++) { + if (strcasecmp(msg->elements[i].name, "objectclass") == 0) { + ms->num_objc = msg->elements[i].num_values; + ms->ol = talloc_array_p(ms, struct objc_list, ms->num_objc); + SCHEMA_TALLOC_CHECK(ss, ms->ol, -1); + for (k = 0; k < ms->num_objc; k++) { + ms->ol[k].name = talloc_strndup(ms->ol, msg->elements[i].values[k].data, msg->elements[i].values[k].length); + SCHEMA_TALLOC_CHECK(ss, ms->ol[k].name, -1); + ms->ol[k].aux = 0; + } + } + + ms->cl[j].check = 0; + ms->cl[j].name = talloc_strdup(ms->cl, msg->elements[i].name); + SCHEMA_TALLOC_CHECK(ss, ms->cl[j].name, -1); + j++; + } + + /* find all modify objectclasses recursively if any objectclass is being added */ + ms->must = NULL; + ms->may = NULL; + ms->num_must = 0; + ms->num_may = 0; + for (i = 0; i < ms->num_objc; i++) { + char *filter; + + filter = talloc_asprintf(ss, "lDAPDisplayName=%s", ms->ol[i].name); + SCHEMA_TALLOC_CHECK(ss, filter, -1); + ret = ldb_search(data->schema_db, NULL, LDB_SCOPE_SUBTREE, filter, NULL, &srch); + if (ret == 0) { + int ok; + + ok = 0; + /* suppose auxiliary classess are not required */ + if (ms->ol[i].aux) { + int d; + ok = 1; + ms->num_objc -= 1; + for (d = i; d < ms->num_objc; d++) { + ms->ol[d] = ms->ol[d + 1]; + } + i -= 1; + } + if (!ok) { + /* Schema Violation: Object Class Description Not Found */ + data->error_string = "ObjectClass not found"; + talloc_free(ss); + return -1; + } + continue; + } else { + if (ret < 0) { + /* Schema DB Error: Error occurred retrieving Object Class Description */ + data->error_string = "Internal error. Error retrieving schema objectclass"; + talloc_free(ss); + return -1; + } + if (ret > 1) { + /* Schema DB Error: Too Many Records */ + data->error_string = "Internal error. Too many records searching for schema objectclass"; + talloc_free(ss); + return -1; + } + } + + /* Add inherited classes eliminating duplicates */ + /* fill in kust and may attribute lists */ + for (j = 0; j < (*srch)->num_elements; j++) { + int o, is_aux, is_class; + + is_aux = 0; + is_class = 0; + if (strcasecmp((*srch)->elements[j].name, "systemAuxiliaryclass") == 0) { + is_aux = 1; + is_class = 1; + } + if (strcasecmp((*srch)->elements[j].name, "subClassOf") == 0) { + is_class = 1; + } + + if (is_class) { + o = (*srch)->elements[j].num_values; + ms->ol = talloc_realloc_p(ms, ms->ol, struct objc_list, ms->num_objc + o); + SCHEMA_TALLOC_CHECK(ss, ms->ol, -1); + for (k = 0, l = 0; k < o; k++) { + int c, found, len; + + found = 0; + for (c = 0; c < ms->num_objc; c++) { + len = strlen(ms->ol[c].name); + if (len == (*srch)->elements[j].values[k].length) { + if (strncasecmp(ss->ol[c].name, (*srch)->elements[j].values[k].data, len) == 0) { + found = 1; + break; + } + } + } + if (!found) { + ms->ol[l + ms->num_objc].name = talloc_strndup(ms->ol, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); + SCHEMA_TALLOC_CHECK(ss, ms->ol[l + ms->num_objc].name, -1); + ms->ol[l + ms->num_objc].aux = is_aux; + l++; + } + } + ms->num_objc += l; + } else { + + if (strcasecmp((*srch)->elements[j].name, "mustContain") == 0 || strcasecmp((*srch)->elements[j].name, "SystemMustContain") == 0) { + int m; + + m = (*srch)->elements[j].num_values; + + ms->must = talloc_realloc_p(ms, ms->must, struct attr_list, ms->num_must + m); + SCHEMA_TALLOC_CHECK(ss, ms->must, -1); + for (k = 0, l = 0; k < m; k++) { + int c, found, len; + + found = 0; + for (c = 0; c < ms->num_must; c++) { + len = strlen(ms->must[c].name); + if (len == (*srch)->elements[j].values[k].length) { + if (strncasecmp(ms->must[c].name, (*srch)->elements[j].values[k].data, len) == 0) { + found = 1; + break; + } + } + } + if (!found) { + ms->must[l + ms->num_must].name = talloc_strndup(ms->must, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); + SCHEMA_TALLOC_CHECK(ss, ms->must[l + ms->num_must].name, -1); + l++; + } + } + ms->num_must += l; + } + + if (strcasecmp((*srch)->elements[j].name, "mayContain") == 0 || strcasecmp((*srch)->elements[j].name, "SystemMayContain") == 0) { + int m; + + m = (*srch)->elements[j].num_values; + + ms->may = talloc_realloc_p(ms, ms->may, struct attr_list, ms->num_may + m); + SCHEMA_TALLOC_CHECK(ss, ms->may, -1); + for (k = 0, l = 0; k < m; k++) { + int c, found, len; + + found = 0; + for (c = 0; c < ms->num_may; c++) { + len = strlen(ms->may[c].name); + if (len == (*srch)->elements[j].values[k].length) { + if (strncasecmp(ms->may[c].name, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length) == 0) { + found = 1; + break; + } + } + } + if (!found) { + ms->may[l + ms->num_may].name = talloc_strndup(ms->may, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); + SCHEMA_TALLOC_CHECK(ss, ms->may[l + ms->num_may].name, -1); + l++; + } + } + ms->num_may += l; + } + } + } + + ldb_search_free(data->schema_db, srch); + } + + /* now search for the original object objectclasses */ + + ss->ol = NULL; + ss->num_objc = 0; + + /* find all other objectclasses recursively */ + { + char *filter = talloc_asprintf(ss, "dn=%s", msg->dn); + const char *attrs[] = {"objectClass", NULL}; + + ret = ldb_search(module->ldb, NULL, LDB_SCOPE_SUBTREE, filter, attrs, &srch); + if (ret == 1) { + for (i = 0; i < msg->num_elements; i++) { + ss->num_objc = (*srch)->elements[i].num_values; + ss->ol = talloc_array_p(ss, struct objc_list, ss->num_objc); + SCHEMA_TALLOC_CHECK(ss, ss->ol, -1); + for (k = 0; k < ss->num_objc; k++) { + ss->ol[k].name = talloc_strndup(ss->ol, (*srch)->elements[i].values[k].data, (*srch)->elements[i].values[k].length); + SCHEMA_TALLOC_CHECK(ss, ss->ol[k].name, -1); + ss->ol[k].aux = 0; + } + } + ldb_search_free(module->ldb, srch); + } else { + ldb_search_free(module->ldb, srch); + return -1; + } + } + + ss->must = NULL; + ss->may = NULL; + ss->num_must = 0; + ss->num_may = 0; + for (i = 0; i < ss->num_objc; i++) { + char *filter; + + filter = talloc_asprintf(ss, "lDAPDisplayName=%s", ss->ol[i].name); + SCHEMA_TALLOC_CHECK(ss, filter, -1); + ret = ldb_search(data->schema_db, NULL, LDB_SCOPE_SUBTREE, filter, NULL, &srch); + if (ret == 0) { + int ok; + + ok = 0; + /* suppose auxiliary classess are not required */ + if (ss->ol[i].aux) { + int d; + ok = 1; + ss->num_objc -= 1; + for (d = i; d < ss->num_objc; d++) { + ss->ol[d] = ss->ol[d + 1]; + } + i -= 1; + } + if (!ok) { + /* Schema Violation: Object Class Description Not Found */ + data->error_string = "ObjectClass not found"; + talloc_free(ss); + return -1; + } + continue; + } else { + if (ret < 0) { + /* Schema DB Error: Error occurred retrieving Object Class Description */ + data->error_string = "Internal error. Error retrieving schema objectclass"; + talloc_free(ss); + return -1; + } + if (ret > 1) { + /* Schema DB Error: Too Many Records */ + data->error_string = "Internal error. Too many records searching for schema objectclass"; + talloc_free(ss); + return -1; + } + } + + /* Add inherited classes eliminating duplicates */ + /* fill in kust and may attribute lists */ + for (j = 0; j < (*srch)->num_elements; j++) { + int o, is_aux, is_class; + + is_aux = 0; + is_class = 0; + if (strcasecmp((*srch)->elements[j].name, "systemAuxiliaryclass") == 0) { + is_aux = 1; + is_class = 1; + } + if (strcasecmp((*srch)->elements[j].name, "subClassOf") == 0) { + is_class = 1; + } + + if (is_class) { + o = (*srch)->elements[j].num_values; + ss->ol = talloc_realloc_p(ss, ss->ol, struct objc_list, ss->num_objc + o); + SCHEMA_TALLOC_CHECK(ss, ss->ol, -1); + for (k = 0, l = 0; k < o; k++) { + int c, found, len; + + found = 0; + for (c = 0; c < ss->num_objc; c++) { + len = strlen(ss->ol[c].name); + if (len == (*srch)->elements[j].values[k].length) { + if (strncasecmp(ss->ol[c].name, (*srch)->elements[j].values[k].data, len) == 0) { + found = 1; + break; + } + } + } + if (!found) { + ss->ol[l + ss->num_objc].name = talloc_strndup(ss->ol, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); + SCHEMA_TALLOC_CHECK(ss, ss->ol[l + ss->num_objc].name, -1); + ss->ol[l + ss->num_objc].aux = is_aux; + l++; + } + } + ss->num_objc += l; + } else { + + if (strcasecmp((*srch)->elements[j].name, "mustContain") == 0 || strcasecmp((*srch)->elements[j].name, "SystemMustContain") == 0) { + int m; + + m = (*srch)->elements[j].num_values; + + ss->must = talloc_realloc_p(ss, ss->must, struct attr_list, ss->num_must + m); + SCHEMA_TALLOC_CHECK(ss, ss->must, -1); + for (k = 0, l = 0; k < m; k++) { + int c, found, len; + + found = 0; + for (c = 0; c < ss->num_must; c++) { + len = strlen(ss->must[c].name); + if (len == (*srch)->elements[j].values[k].length) { + if (strncasecmp(ss->must[c].name, (*srch)->elements[j].values[k].data, len) == 0) { + found = 1; + break; + } + } + } + if (!found) { + ss->must[l + ss->num_must].name = talloc_strndup(ss->must, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); + SCHEMA_TALLOC_CHECK(ss, ss->must[l + ss->num_must].name, -1); + l++; + } + } + ss->num_must += l; + } + + if (strcasecmp((*srch)->elements[j].name, "mayContain") == 0 || strcasecmp((*srch)->elements[j].name, "SystemMayContain") == 0) { + int m; + + m = (*srch)->elements[j].num_values; + + ss->may = talloc_realloc_p(ss, ss->may, struct attr_list, ss->num_may + m); + SCHEMA_TALLOC_CHECK(ss, ss->may, -1); + for (k = 0, l = 0; k < m; k++) { + int c, found, len; + + found = 0; + for (c = 0; c < ss->num_may; c++) { + len = strlen(ss->may[c].name); + if (len == (*srch)->elements[j].values[k].length) { + if (strncasecmp(ss->may[c].name, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length) == 0) { + found = 1; + break; + } + } + } + if (!found) { + ss->may[l + ss->num_may].name = talloc_strndup(ss->may, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); + SCHEMA_TALLOC_CHECK(ss, ss->may[l + ss->num_may].name, -1); + l++; + } + } + ss->num_may += l; + } + } + } + + ldb_search_free(data->schema_db, srch); + } + + /* now check all entries are present either as musts or mays of curent objectclasses */ + /* do not return errors there may be attirbutes defined in new objectclasses */ + /* just mark them as being proved valid attribs */ + for (i = 0; i < ms->num_cl; i++) { + int found; + + found = 0; + for (j = 0; j < ss->num_may; j++) { + if (strcasecmp(ss->may[j].name, ms->cl[i].name) == 0) { + ms->cl[i].check = 1; + found = 1; + break; + } + } + if ( ! found) { + for (j = 0; j < ss->num_must; j++) { + if (strcasecmp(ss->must[j].name, ms->cl[i].name) == 0) { + ms->cl[i].check = 1; + break; + } + } + } + } + + /* now check all new objectclasses musts are present */ + for (i = 0; i < ms->num_must; i++) { + int found; + + found = 0; + for (j = 0; j < ms->num_cl; j++) { + if (strcasecmp(ms->must[i].name, ms->cl[j].name) == 0) { + ms->cl[j].check = 1; + found = 1; + break; + } + } + + if ( ! found ) { + /* TODO: set the error string */ + data->error_string = "Objectclass violation, a required attribute is missing"; + talloc_free(ss); + return -1; + } + } + + /* now check all others atribs are found in mays */ + for (i = 0; i < ms->num_cl; i++) { + + if ( ! ms->cl[i].check ) { + int found; + + found = 0; + for (j = 0; j < ms->num_may; j++) { + if (strcasecmp(ms->may[j].name, ms->cl[i].name) == 0) { + ms->cl[i].check = 1; + found = 1; + break; + } + } + + if ( ! found ) { + data->error_string = "Objectclass violation, an invalid attribute name was found"; + talloc_free(ss); + return -1; + } + } + } + + talloc_free(ss); + return ldb_next_modify_record(module, msg); } -- cgit From a2f77f979d7271a9708ed06f43b00ffb10ec7f4c Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 12 Jan 2005 16:00:01 +0000 Subject: r4714: move the ldb code to the new talloc interface (eg remove _p suffix) this helps standalone building of ldb renew the schema module split code into functions to improve readability and code reuse add and modify works correctly but we need a proper testsuite Simo (This used to be commit a681ae365ff1b5a2771b42ebd90336651ce1e513) --- source4/lib/ldb/modules/schema.c | 799 ++++++++++++----------------------- source4/lib/ldb/modules/timestamps.c | 16 +- 2 files changed, 275 insertions(+), 540 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index 1f9017976e..63d94eed81 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -63,6 +63,10 @@ static struct attribute_syntax attrsyn[] = { #define SCHEMA_TALLOC_CHECK(root, mem, ret) do { if (!mem) { talloc_free(root); return ret;} } while(0); +#define SA_FLAG_RESET 0 +#define SA_FLAG_AUXCLASS 1 +#define SA_FLAG_CHECKED 2 + struct private_data { struct ldb_context *schema_db; const char *error_string; @@ -88,105 +92,177 @@ static int schema_search_free(struct ldb_module *module, struct ldb_message **re return ldb_next_search_free(module, res); } -struct check_list { - int check; - char *name; -}; - -struct attr_list { - int syntax; - char *name; -}; - -struct objc_list { - int aux; +struct attribute_list { + int flags; char *name; }; struct schema_structures { - struct check_list *cl; - struct objc_list *ol; - struct attr_list *must; - struct attr_list *may; - int num_cl; - int num_objc; - int num_must; - int num_may; + struct attribute_list *check_list; + struct attribute_list *objectclass_list; + struct attribute_list *must; + struct attribute_list *may; + int check_list_num; + int objectclass_list_num; + int must_num; + int may_num; }; -/* add_record */ -static int schema_add_record(struct ldb_module *module, const struct ldb_message *msg) +static int get_object_objectclasses(struct ldb_context *ldb, const char *dn, struct schema_structures *schema_struct) { - struct private_data *data = (struct private_data *)module->private_data; + char *filter = talloc_asprintf(schema_struct, "dn=%s", dn); + const char *attrs[] = {"objectClass", NULL}; struct ldb_message **srch; - struct schema_structures *ss; - int i, j, k, l; - int ret; + int i, j, ret; + + schema_struct->objectclass_list = NULL; + schema_struct->objectclass_list_num = 0; + ret = ldb_search(ldb, NULL, LDB_SCOPE_SUBTREE, filter, attrs, &srch); + if (ret == 1) { + for (i = 0; i < (*srch)->num_elements; i++) { + schema_struct->objectclass_list_num = (*srch)->elements[i].num_values; + schema_struct->objectclass_list = talloc_array(schema_struct, + struct attribute_list, + schema_struct->objectclass_list_num); + if (schema_struct->objectclass_list == 0) { + ldb_search_free(ldb, srch); + return -1; + } + for (j = 0; j < schema_struct->objectclass_list_num; j++) { + schema_struct->objectclass_list[j].name = talloc_strndup(schema_struct->objectclass_list, + (*srch)->elements[i].values[j].data, + (*srch)->elements[i].values[j].length); + if (schema_struct->objectclass_list[j].name == 0) { + ldb_search_free(ldb, srch); + return -1; + } + schema_struct->objectclass_list[j].flags = SA_FLAG_RESET; + } + } + ldb_search_free(ldb, srch); + } else { + ldb_search_free(ldb, srch); + return -1; + } - /* First implementation: - Build up a list of must and mays from each objectclass - Check all the musts are there and all the other attributes are mays - Throw an error in case a check fail - Free all structures and commit the change - */ + return 0; +} - ss = talloc_p(module, struct schema_structures); - if (!ss) { +static int get_check_list(struct ldb_module *module, struct schema_structures *schema_struct, const struct ldb_message *msg) +{ + int i, j, k; + + schema_struct->objectclass_list = NULL; + schema_struct->objectclass_list_num = 0; + schema_struct->check_list_num = msg->num_elements; + schema_struct->check_list = talloc_array(schema_struct, + struct attribute_list, + schema_struct->check_list_num); + if (schema_struct->check_list == 0) { return -1; } - - ss->ol = NULL; - ss->num_objc = 0; - ss->num_cl = msg->num_elements; - ss->cl = talloc_array_p(ss, struct check_list, ss->num_cl); - SCHEMA_TALLOC_CHECK(ss, ss->cl, -1); for (i = 0, j = 0; i < msg->num_elements; i++) { if (strcasecmp(msg->elements[i].name, "objectclass") == 0) { - ss->num_objc = msg->elements[i].num_values; - ss->ol = talloc_array_p(ss, struct objc_list, ss->num_objc); - SCHEMA_TALLOC_CHECK(ss, ss->ol, -1); - for (k = 0; k < ss->num_objc; k++) { - ss->ol[k].name = talloc_strndup(ss->ol, msg->elements[i].values[k].data, msg->elements[i].values[k].length); - SCHEMA_TALLOC_CHECK(ss, ss->ol[k].name, -1); - ss->ol[k].aux = 0; + schema_struct->objectclass_list_num = msg->elements[i].num_values; + schema_struct->objectclass_list = talloc_array(schema_struct, + struct attribute_list, + schema_struct->objectclass_list_num); + if (schema_struct->objectclass_list == 0) { + return -1; + } + for (k = 0; k < schema_struct->objectclass_list_num; k++) { + schema_struct->objectclass_list[k].name = talloc_strndup(schema_struct->objectclass_list, + msg->elements[i].values[k].data, + msg->elements[i].values[k].length); + if (schema_struct->objectclass_list[k].name == 0) { + return -1; + } + schema_struct->objectclass_list[k].flags = SA_FLAG_RESET; } } - ss->cl[j].check = 0; - ss->cl[j].name = talloc_strdup(ss->cl, msg->elements[i].name); - SCHEMA_TALLOC_CHECK(ss, ss->cl[j].name, -1); + schema_struct->check_list[j].flags = SA_FLAG_RESET; + schema_struct->check_list[j].name = talloc_strdup(schema_struct->check_list, + msg->elements[i].name); + if (schema_struct->check_list[j].name == 0) { + return -1; + } j++; } - /* find all other objectclasses recursively */ - ss->must = NULL; - ss->may = NULL; - ss->num_must = 0; - ss->num_may = 0; - for (i = 0; i < ss->num_objc; i++) { + return 0; +} + +static int add_attribute_uniq(struct attribute_list **list, int *list_num, int flags, struct ldb_message_element *el, void *mem_ctx) +{ + int i, j, vals; + + vals = el->num_values; + *list = talloc_realloc(mem_ctx, *list, struct attribute_list, *list_num + vals); + if (list == 0) { + return -1; + } + for (i = 0, j = 0; i < vals; i++) { + int c, found, len; + + found = 0; + for (c = 0; c < *list_num; c++) { + len = strlen((*list)[c].name); + if (len == el->values[i].length) { + if (strncasecmp((*list)[c].name, el->values[i].data, len) == 0) { + found = 1; + break; + } + } + } + if (!found) { + (*list)[j + *list_num].name = talloc_strndup(*list, el->values[i].data, el->values[i].length); + if ((*list)[j + *list_num].name == 0) { + return -1; + } + (*list)[j + *list_num].flags = flags; + j++; + } + } + *list_num += j; + + return 0; +} + +static int get_attr_list_recursive(struct ldb_module *module, struct ldb_context *ldb, struct schema_structures *schema_struct) +{ + struct private_data *data = (struct private_data *)module->private_data; + struct ldb_message **srch; + int i, j; + int ret; + + schema_struct->must = NULL; + schema_struct->may = NULL; + schema_struct->must_num = 0; + schema_struct->may_num = 0; + for (i = 0; i < schema_struct->objectclass_list_num; i++) { char *filter; - filter = talloc_asprintf(ss, "lDAPDisplayName=%s", ss->ol[i].name); - SCHEMA_TALLOC_CHECK(ss, filter, -1); - ret = ldb_search(data->schema_db, NULL, LDB_SCOPE_SUBTREE, filter, NULL, &srch); + filter = talloc_asprintf(schema_struct, "lDAPDisplayName=%s", schema_struct->objectclass_list[i].name); + SCHEMA_TALLOC_CHECK(schema_struct, filter, -1); + ret = ldb_search(ldb, NULL, LDB_SCOPE_SUBTREE, filter, NULL, &srch); if (ret == 0) { int ok; ok = 0; - /* suppose auxiliary classess are not required */ - if (ss->ol[i].aux) { + /* suppose auxiliary classeschema_struct are not required */ + if (schema_struct->objectclass_list[i].flags & SA_FLAG_AUXCLASS) { int d; ok = 1; - ss->num_objc -= 1; - for (d = i; d < ss->num_objc; d++) { - ss->ol[d] = ss->ol[d + 1]; + schema_struct->objectclass_list_num -= 1; + for (d = i; d < schema_struct->objectclass_list_num; d++) { + schema_struct->objectclass_list[d] = schema_struct->objectclass_list[d + 1]; } i -= 1; } if (!ok) { /* Schema Violation: Object Class Description Not Found */ data->error_string = "ObjectClass not found"; - talloc_free(ss); return -1; } continue; @@ -194,13 +270,11 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message if (ret < 0) { /* Schema DB Error: Error occurred retrieving Object Class Description */ data->error_string = "Internal error. Error retrieving schema objectclass"; - talloc_free(ss); return -1; } if (ret > 1) { /* Schema DB Error: Too Many Records */ data->error_string = "Internal error. Too many records searching for schema objectclass"; - talloc_free(ss); return -1; } } @@ -208,12 +282,12 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message /* Add inherited classes eliminating duplicates */ /* fill in kust and may attribute lists */ for (j = 0; j < (*srch)->num_elements; j++) { - int o, is_aux, is_class; + int is_aux, is_class; is_aux = 0; is_class = 0; if (strcasecmp((*srch)->elements[j].name, "systemAuxiliaryclass") == 0) { - is_aux = 1; + is_aux = SA_FLAG_AUXCLASS; is_class = 1; } if (strcasecmp((*srch)->elements[j].name, "subClassOf") == 0) { @@ -221,103 +295,87 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message } if (is_class) { - o = (*srch)->elements[j].num_values; - ss->ol = talloc_realloc_p(ss, ss->ol, struct objc_list, ss->num_objc + o); - SCHEMA_TALLOC_CHECK(ss, ss->ol, -1); - for (k = 0, l = 0; k < o; k++) { - int c, found, len; - - found = 0; - for (c = 0; c < ss->num_objc; c++) { - len = strlen(ss->ol[c].name); - if (len == (*srch)->elements[j].values[k].length) { - if (strncasecmp(ss->ol[c].name, (*srch)->elements[j].values[k].data, len) == 0) { - found = 1; - break; - } - } - } - if (!found) { - ss->ol[l + ss->num_objc].name = talloc_strndup(ss->ol, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); - SCHEMA_TALLOC_CHECK(ss, ss->ol[l + ss->num_objc].name, -1); - ss->ol[l + ss->num_objc].aux = is_aux; - l++; - } + if (add_attribute_uniq(&schema_struct->objectclass_list, + &schema_struct->objectclass_list_num, + is_aux, + &(*srch)->elements[j], + schema_struct) != 0) { + return -1; } - ss->num_objc += l; } else { - if (strcasecmp((*srch)->elements[j].name, "mustContain") == 0 || strcasecmp((*srch)->elements[j].name, "SystemMustContain") == 0) { - int m; - - m = (*srch)->elements[j].num_values; - - ss->must = talloc_realloc_p(ss, ss->must, struct attr_list, ss->num_must + m); - SCHEMA_TALLOC_CHECK(ss, ss->must, -1); - for (k = 0, l = 0; k < m; k++) { - int c, found, len; - - found = 0; - for (c = 0; c < ss->num_must; c++) { - len = strlen(ss->must[c].name); - if (len == (*srch)->elements[j].values[k].length) { - if (strncasecmp(ss->must[c].name, (*srch)->elements[j].values[k].data, len) == 0) { - found = 1; - break; - } - } - } - if (!found) { - ss->must[l + ss->num_must].name = talloc_strndup(ss->must, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); - SCHEMA_TALLOC_CHECK(ss, ss->must[l + ss->num_must].name, -1); - l++; - } + if (strcasecmp((*srch)->elements[j].name, "mustContain") == 0 || + strcasecmp((*srch)->elements[j].name, "SystemMustContain") == 0) { + if (add_attribute_uniq(&schema_struct->must, + &schema_struct->must_num, + SA_FLAG_RESET, + &(*srch)->elements[j], + schema_struct) != 0) { + return -1; } - ss->num_must += l; } - if (strcasecmp((*srch)->elements[j].name, "mayContain") == 0 || strcasecmp((*srch)->elements[j].name, "SystemMayContain") == 0) { - int m; - - m = (*srch)->elements[j].num_values; - - ss->may = talloc_realloc_p(ss, ss->may, struct attr_list, ss->num_may + m); - SCHEMA_TALLOC_CHECK(ss, ss->may, -1); - for (k = 0, l = 0; k < m; k++) { - int c, found, len; - - found = 0; - for (c = 0; c < ss->num_may; c++) { - len = strlen(ss->may[c].name); - if (len == (*srch)->elements[j].values[k].length) { - if (strncasecmp(ss->may[c].name, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length) == 0) { - found = 1; - break; - } - } - } - if (!found) { - ss->may[l + ss->num_may].name = talloc_strndup(ss->may, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); - SCHEMA_TALLOC_CHECK(ss, ss->may[l + ss->num_may].name, -1); - l++; - } + if (strcasecmp((*srch)->elements[j].name, "mayContain") == 0 || + strcasecmp((*srch)->elements[j].name, "SystemMayContain") == 0) { + + if (add_attribute_uniq(&schema_struct->may, + &schema_struct->may_num, + SA_FLAG_RESET, + &(*srch)->elements[j], + schema_struct) != 0) { + return -1; } - ss->num_may += l; } } } - ldb_search_free(data->schema_db, srch); + ldb_search_free(ldb, srch); + } + + return 0; +} + +/* add_record */ +static int schema_add_record(struct ldb_module *module, const struct ldb_message *msg) +{ + struct private_data *data = (struct private_data *)module->private_data; + struct schema_structures *entry_structs; + int i, j; + int ret; + + /* First implementation: + Build up a list of must and mays from each objectclass + Check all the musts are there and all the other attributes are mays + Throw an error in case a check fail + Free all structures and commit the change + */ + + entry_structs = talloc(module, struct schema_structures); + if (!entry_structs) { + return -1; + } + + ret = get_check_list(module, entry_structs, msg); + if (ret != 0) { + talloc_free(entry_structs); + return ret; + } + + /* find all other objectclasses recursively */ + ret = get_attr_list_recursive(module, data->schema_db, entry_structs); + if (ret != 0) { + talloc_free(entry_structs); + return ret; } /* now check all musts are present */ - for (i = 0; i < ss->num_must; i++) { + for (i = 0; i < entry_structs->must_num; i++) { int found; found = 0; - for (j = 0; j < ss->num_cl; j++) { - if (strcasecmp(ss->must[i].name, ss->cl[j].name) == 0) { - ss->cl[j].check = 1; + for (j = 0; j < entry_structs->check_list_num; j++) { + if (strcasecmp(entry_structs->must[i].name, entry_structs->check_list[j].name) == 0) { + entry_structs->check_list[j].flags = SA_FLAG_CHECKED; found = 1; break; } @@ -325,22 +383,22 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message if ( ! found ) { /* TODO: set the error string */ - data->error_string = "Objectclass violation, a required attribute is missing"; - talloc_free(ss); + data->error_string = "Objectclass violation, a required attribute is mischema_structing"; + talloc_free(entry_structs); return -1; } } /* now check all others atribs are found in mays */ - for (i = 0; i < ss->num_cl; i++) { + for (i = 0; i < entry_structs->check_list_num; i++) { - if ( ! ss->cl[i].check ) { + if (entry_structs->check_list[i].flags != SA_FLAG_CHECKED) { int found; found = 0; - for (j = 0; j < ss->num_may; j++) { - if (strcasecmp(ss->may[j].name, ss->cl[i].name) == 0) { - ss->cl[i].check = 1; + for (j = 0; j < entry_structs->may_num; j++) { + if (strcasecmp(entry_structs->may[j].name, entry_structs->check_list[i].name) == 0) { + entry_structs->check_list[i].flags = SA_FLAG_CHECKED; found = 1; break; } @@ -348,13 +406,13 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message if ( ! found ) { data->error_string = "Objectclass violation, an invalid attribute name was found"; - talloc_free(ss); + talloc_free(entry_structs); return -1; } } } - talloc_free(ss); + talloc_free(entry_structs); return ldb_next_add_record(module, msg); } @@ -363,9 +421,8 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message static int schema_modify_record(struct ldb_module *module, const struct ldb_message *msg) { struct private_data *data = (struct private_data *)module->private_data; - struct ldb_message **srch; - struct schema_structures *ss, *ms; - int i, j, k, l; + struct schema_structures *entry_structs, *modify_structs; + int i, j; int ret; /* First implementation: @@ -379,387 +436,65 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess Free all structures and commit the change. */ - ss = talloc_p(module, struct schema_structures); - if (!ss) { + /* allocate object structs */ + entry_structs = talloc(module, struct schema_structures); + if (!entry_structs) { return -1; } - ms = talloc_p(module, struct schema_structures); - SCHEMA_TALLOC_CHECK(ss, ms, -1); - - ms->ol = NULL; - ms->num_objc = 0; - ms->num_cl = msg->num_elements; - ms->cl = talloc_array_p(ms, struct check_list, ms->num_cl); - SCHEMA_TALLOC_CHECK(ss, ms->cl, -1); - for (i = 0, j = 0; i < msg->num_elements; i++) { - if (strcasecmp(msg->elements[i].name, "objectclass") == 0) { - ms->num_objc = msg->elements[i].num_values; - ms->ol = talloc_array_p(ms, struct objc_list, ms->num_objc); - SCHEMA_TALLOC_CHECK(ss, ms->ol, -1); - for (k = 0; k < ms->num_objc; k++) { - ms->ol[k].name = talloc_strndup(ms->ol, msg->elements[i].values[k].data, msg->elements[i].values[k].length); - SCHEMA_TALLOC_CHECK(ss, ms->ol[k].name, -1); - ms->ol[k].aux = 0; - } - } + /* allocate modification entry structs */ + modify_structs = talloc(entry_structs, struct schema_structures); + if (!modify_structs) { + talloc_free(entry_structs); + return -1; + } - ms->cl[j].check = 0; - ms->cl[j].name = talloc_strdup(ms->cl, msg->elements[i].name); - SCHEMA_TALLOC_CHECK(ss, ms->cl[j].name, -1); - j++; + /* get list of values to modify */ + ret = get_check_list(module, modify_structs, msg); + if (ret != 0) { + talloc_free(entry_structs); + return ret; } /* find all modify objectclasses recursively if any objectclass is being added */ - ms->must = NULL; - ms->may = NULL; - ms->num_must = 0; - ms->num_may = 0; - for (i = 0; i < ms->num_objc; i++) { - char *filter; - - filter = talloc_asprintf(ss, "lDAPDisplayName=%s", ms->ol[i].name); - SCHEMA_TALLOC_CHECK(ss, filter, -1); - ret = ldb_search(data->schema_db, NULL, LDB_SCOPE_SUBTREE, filter, NULL, &srch); - if (ret == 0) { - int ok; - - ok = 0; - /* suppose auxiliary classess are not required */ - if (ms->ol[i].aux) { - int d; - ok = 1; - ms->num_objc -= 1; - for (d = i; d < ms->num_objc; d++) { - ms->ol[d] = ms->ol[d + 1]; - } - i -= 1; - } - if (!ok) { - /* Schema Violation: Object Class Description Not Found */ - data->error_string = "ObjectClass not found"; - talloc_free(ss); - return -1; - } - continue; - } else { - if (ret < 0) { - /* Schema DB Error: Error occurred retrieving Object Class Description */ - data->error_string = "Internal error. Error retrieving schema objectclass"; - talloc_free(ss); - return -1; - } - if (ret > 1) { - /* Schema DB Error: Too Many Records */ - data->error_string = "Internal error. Too many records searching for schema objectclass"; - talloc_free(ss); - return -1; - } - } - - /* Add inherited classes eliminating duplicates */ - /* fill in kust and may attribute lists */ - for (j = 0; j < (*srch)->num_elements; j++) { - int o, is_aux, is_class; - - is_aux = 0; - is_class = 0; - if (strcasecmp((*srch)->elements[j].name, "systemAuxiliaryclass") == 0) { - is_aux = 1; - is_class = 1; - } - if (strcasecmp((*srch)->elements[j].name, "subClassOf") == 0) { - is_class = 1; - } - - if (is_class) { - o = (*srch)->elements[j].num_values; - ms->ol = talloc_realloc_p(ms, ms->ol, struct objc_list, ms->num_objc + o); - SCHEMA_TALLOC_CHECK(ss, ms->ol, -1); - for (k = 0, l = 0; k < o; k++) { - int c, found, len; - - found = 0; - for (c = 0; c < ms->num_objc; c++) { - len = strlen(ms->ol[c].name); - if (len == (*srch)->elements[j].values[k].length) { - if (strncasecmp(ss->ol[c].name, (*srch)->elements[j].values[k].data, len) == 0) { - found = 1; - break; - } - } - } - if (!found) { - ms->ol[l + ms->num_objc].name = talloc_strndup(ms->ol, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); - SCHEMA_TALLOC_CHECK(ss, ms->ol[l + ms->num_objc].name, -1); - ms->ol[l + ms->num_objc].aux = is_aux; - l++; - } - } - ms->num_objc += l; - } else { - - if (strcasecmp((*srch)->elements[j].name, "mustContain") == 0 || strcasecmp((*srch)->elements[j].name, "SystemMustContain") == 0) { - int m; - - m = (*srch)->elements[j].num_values; - - ms->must = talloc_realloc_p(ms, ms->must, struct attr_list, ms->num_must + m); - SCHEMA_TALLOC_CHECK(ss, ms->must, -1); - for (k = 0, l = 0; k < m; k++) { - int c, found, len; - - found = 0; - for (c = 0; c < ms->num_must; c++) { - len = strlen(ms->must[c].name); - if (len == (*srch)->elements[j].values[k].length) { - if (strncasecmp(ms->must[c].name, (*srch)->elements[j].values[k].data, len) == 0) { - found = 1; - break; - } - } - } - if (!found) { - ms->must[l + ms->num_must].name = talloc_strndup(ms->must, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); - SCHEMA_TALLOC_CHECK(ss, ms->must[l + ms->num_must].name, -1); - l++; - } - } - ms->num_must += l; - } - - if (strcasecmp((*srch)->elements[j].name, "mayContain") == 0 || strcasecmp((*srch)->elements[j].name, "SystemMayContain") == 0) { - int m; - - m = (*srch)->elements[j].num_values; - - ms->may = talloc_realloc_p(ms, ms->may, struct attr_list, ms->num_may + m); - SCHEMA_TALLOC_CHECK(ss, ms->may, -1); - for (k = 0, l = 0; k < m; k++) { - int c, found, len; - - found = 0; - for (c = 0; c < ms->num_may; c++) { - len = strlen(ms->may[c].name); - if (len == (*srch)->elements[j].values[k].length) { - if (strncasecmp(ms->may[c].name, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length) == 0) { - found = 1; - break; - } - } - } - if (!found) { - ms->may[l + ms->num_may].name = talloc_strndup(ms->may, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); - SCHEMA_TALLOC_CHECK(ss, ms->may[l + ms->num_may].name, -1); - l++; - } - } - ms->num_may += l; - } - } - } - - ldb_search_free(data->schema_db, srch); + ret = get_attr_list_recursive(module, data->schema_db, modify_structs); + if (ret != 0) { + talloc_free(entry_structs); + return ret; } /* now search for the original object objectclasses */ - - ss->ol = NULL; - ss->num_objc = 0; - - /* find all other objectclasses recursively */ - { - char *filter = talloc_asprintf(ss, "dn=%s", msg->dn); - const char *attrs[] = {"objectClass", NULL}; - - ret = ldb_search(module->ldb, NULL, LDB_SCOPE_SUBTREE, filter, attrs, &srch); - if (ret == 1) { - for (i = 0; i < msg->num_elements; i++) { - ss->num_objc = (*srch)->elements[i].num_values; - ss->ol = talloc_array_p(ss, struct objc_list, ss->num_objc); - SCHEMA_TALLOC_CHECK(ss, ss->ol, -1); - for (k = 0; k < ss->num_objc; k++) { - ss->ol[k].name = talloc_strndup(ss->ol, (*srch)->elements[i].values[k].data, (*srch)->elements[i].values[k].length); - SCHEMA_TALLOC_CHECK(ss, ss->ol[k].name, -1); - ss->ol[k].aux = 0; - } - } - ldb_search_free(module->ldb, srch); - } else { - ldb_search_free(module->ldb, srch); - return -1; - } + ret = get_object_objectclasses(module->ldb, msg->dn, entry_structs); + if (ret != 0) { + talloc_free(entry_structs); + return ret; } - ss->must = NULL; - ss->may = NULL; - ss->num_must = 0; - ss->num_may = 0; - for (i = 0; i < ss->num_objc; i++) { - char *filter; - - filter = talloc_asprintf(ss, "lDAPDisplayName=%s", ss->ol[i].name); - SCHEMA_TALLOC_CHECK(ss, filter, -1); - ret = ldb_search(data->schema_db, NULL, LDB_SCOPE_SUBTREE, filter, NULL, &srch); - if (ret == 0) { - int ok; - - ok = 0; - /* suppose auxiliary classess are not required */ - if (ss->ol[i].aux) { - int d; - ok = 1; - ss->num_objc -= 1; - for (d = i; d < ss->num_objc; d++) { - ss->ol[d] = ss->ol[d + 1]; - } - i -= 1; - } - if (!ok) { - /* Schema Violation: Object Class Description Not Found */ - data->error_string = "ObjectClass not found"; - talloc_free(ss); - return -1; - } - continue; - } else { - if (ret < 0) { - /* Schema DB Error: Error occurred retrieving Object Class Description */ - data->error_string = "Internal error. Error retrieving schema objectclass"; - talloc_free(ss); - return -1; - } - if (ret > 1) { - /* Schema DB Error: Too Many Records */ - data->error_string = "Internal error. Too many records searching for schema objectclass"; - talloc_free(ss); - return -1; - } - } - - /* Add inherited classes eliminating duplicates */ - /* fill in kust and may attribute lists */ - for (j = 0; j < (*srch)->num_elements; j++) { - int o, is_aux, is_class; - - is_aux = 0; - is_class = 0; - if (strcasecmp((*srch)->elements[j].name, "systemAuxiliaryclass") == 0) { - is_aux = 1; - is_class = 1; - } - if (strcasecmp((*srch)->elements[j].name, "subClassOf") == 0) { - is_class = 1; - } - - if (is_class) { - o = (*srch)->elements[j].num_values; - ss->ol = talloc_realloc_p(ss, ss->ol, struct objc_list, ss->num_objc + o); - SCHEMA_TALLOC_CHECK(ss, ss->ol, -1); - for (k = 0, l = 0; k < o; k++) { - int c, found, len; - - found = 0; - for (c = 0; c < ss->num_objc; c++) { - len = strlen(ss->ol[c].name); - if (len == (*srch)->elements[j].values[k].length) { - if (strncasecmp(ss->ol[c].name, (*srch)->elements[j].values[k].data, len) == 0) { - found = 1; - break; - } - } - } - if (!found) { - ss->ol[l + ss->num_objc].name = talloc_strndup(ss->ol, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); - SCHEMA_TALLOC_CHECK(ss, ss->ol[l + ss->num_objc].name, -1); - ss->ol[l + ss->num_objc].aux = is_aux; - l++; - } - } - ss->num_objc += l; - } else { - - if (strcasecmp((*srch)->elements[j].name, "mustContain") == 0 || strcasecmp((*srch)->elements[j].name, "SystemMustContain") == 0) { - int m; - - m = (*srch)->elements[j].num_values; - - ss->must = talloc_realloc_p(ss, ss->must, struct attr_list, ss->num_must + m); - SCHEMA_TALLOC_CHECK(ss, ss->must, -1); - for (k = 0, l = 0; k < m; k++) { - int c, found, len; - - found = 0; - for (c = 0; c < ss->num_must; c++) { - len = strlen(ss->must[c].name); - if (len == (*srch)->elements[j].values[k].length) { - if (strncasecmp(ss->must[c].name, (*srch)->elements[j].values[k].data, len) == 0) { - found = 1; - break; - } - } - } - if (!found) { - ss->must[l + ss->num_must].name = talloc_strndup(ss->must, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); - SCHEMA_TALLOC_CHECK(ss, ss->must[l + ss->num_must].name, -1); - l++; - } - } - ss->num_must += l; - } - - if (strcasecmp((*srch)->elements[j].name, "mayContain") == 0 || strcasecmp((*srch)->elements[j].name, "SystemMayContain") == 0) { - int m; - - m = (*srch)->elements[j].num_values; - - ss->may = talloc_realloc_p(ss, ss->may, struct attr_list, ss->num_may + m); - SCHEMA_TALLOC_CHECK(ss, ss->may, -1); - for (k = 0, l = 0; k < m; k++) { - int c, found, len; - - found = 0; - for (c = 0; c < ss->num_may; c++) { - len = strlen(ss->may[c].name); - if (len == (*srch)->elements[j].values[k].length) { - if (strncasecmp(ss->may[c].name, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length) == 0) { - found = 1; - break; - } - } - } - if (!found) { - ss->may[l + ss->num_may].name = talloc_strndup(ss->may, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); - SCHEMA_TALLOC_CHECK(ss, ss->may[l + ss->num_may].name, -1); - l++; - } - } - ss->num_may += l; - } - } - } - - ldb_search_free(data->schema_db, srch); + /* find all other objectclasses recursively */ + ret = get_attr_list_recursive(module, data->schema_db, entry_structs); + if (ret != 0) { + talloc_free(entry_structs); + return ret; } /* now check all entries are present either as musts or mays of curent objectclasses */ /* do not return errors there may be attirbutes defined in new objectclasses */ /* just mark them as being proved valid attribs */ - for (i = 0; i < ms->num_cl; i++) { + for (i = 0; i < modify_structs->check_list_num; i++) { int found; found = 0; - for (j = 0; j < ss->num_may; j++) { - if (strcasecmp(ss->may[j].name, ms->cl[i].name) == 0) { - ms->cl[i].check = 1; + for (j = 0; j < entry_structs->may_num; j++) { + if (strcasecmp(entry_structs->may[j].name, modify_structs->check_list[i].name) == 0) { + modify_structs->check_list[i].flags = SA_FLAG_CHECKED; found = 1; break; } } if ( ! found) { - for (j = 0; j < ss->num_must; j++) { - if (strcasecmp(ss->must[j].name, ms->cl[i].name) == 0) { - ms->cl[i].check = 1; + for (j = 0; j < entry_structs->must_num; j++) { + if (strcasecmp(entry_structs->must[j].name, modify_structs->check_list[i].name) == 0) { + modify_structs->check_list[i].flags = SA_FLAG_CHECKED; break; } } @@ -767,13 +502,13 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess } /* now check all new objectclasses musts are present */ - for (i = 0; i < ms->num_must; i++) { + for (i = 0; i < modify_structs->must_num; i++) { int found; found = 0; - for (j = 0; j < ms->num_cl; j++) { - if (strcasecmp(ms->must[i].name, ms->cl[j].name) == 0) { - ms->cl[j].check = 1; + for (j = 0; j < modify_structs->check_list_num; j++) { + if (strcasecmp(modify_structs->must[i].name, modify_structs->check_list[j].name) == 0) { + modify_structs->check_list[j].flags = SA_FLAG_CHECKED; found = 1; break; } @@ -782,21 +517,21 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess if ( ! found ) { /* TODO: set the error string */ data->error_string = "Objectclass violation, a required attribute is missing"; - talloc_free(ss); + talloc_free(entry_structs); return -1; } } /* now check all others atribs are found in mays */ - for (i = 0; i < ms->num_cl; i++) { + for (i = 0; i < modify_structs->check_list_num; i++) { - if ( ! ms->cl[i].check ) { + if (modify_structs->check_list[i].flags != SA_FLAG_CHECKED) { int found; found = 0; - for (j = 0; j < ms->num_may; j++) { - if (strcasecmp(ms->may[j].name, ms->cl[i].name) == 0) { - ms->cl[i].check = 1; + for (j = 0; j < modify_structs->may_num; j++) { + if (strcasecmp(modify_structs->may[j].name, modify_structs->check_list[i].name) == 0) { + modify_structs->check_list[i].flags = SA_FLAG_CHECKED; found = 1; break; } @@ -804,13 +539,13 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess if ( ! found ) { data->error_string = "Objectclass violation, an invalid attribute name was found"; - talloc_free(ss); + talloc_free(entry_structs); return -1; } } } - talloc_free(ss); + talloc_free(entry_structs); return ldb_next_modify_record(module, msg); } @@ -818,7 +553,7 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess /* delete_record */ static int schema_delete_record(struct ldb_module *module, const char *dn) { - struct private_data *data = (struct private_data *)module->private_data; +/* struct private_data *data = (struct private_data *)module->private_data; */ return ldb_next_delete_record(module, dn); } @@ -880,7 +615,7 @@ struct ldb_module *schema_module_init(struct ldb_context *ldb, const char *optio char *db_url = NULL; int i; - ctx = talloc_p(ldb, struct ldb_module); + ctx = talloc(ldb, struct ldb_module); if (!ctx) { return NULL; } @@ -923,7 +658,7 @@ struct ldb_module *schema_module_init(struct ldb_context *ldb, const char *optio ldb_search_free(ldb, msgs); } - data = talloc_p(ctx, struct private_data); + data = talloc(ctx, struct private_data); SCHEMA_TALLOC_CHECK(ctx, data, NULL); data->schema_db = ldb_connect(db_url, 0, NULL); diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index 09679435f5..4066d231cd 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -74,11 +74,11 @@ static int add_time_element(struct ldb_module *module, struct ldb_message *msg, } } - msg->elements = talloc_realloc_p(msg, msg->elements, + msg->elements = talloc_realloc(msg, msg->elements, struct ldb_message_element, msg->num_elements + 1); name = talloc_strdup(msg->elements, attr_name); timestr = talloc_strdup(msg->elements, time_string); - values = talloc_p(msg->elements, struct ldb_val); + values = talloc(msg->elements, struct ldb_val); if (!msg->elements || !name || !timestr || !values) { return -1; } @@ -113,7 +113,7 @@ static int timestamps_add_record(struct ldb_module *module, const struct ldb_mes return -1; } - msg2 = talloc_p(module, struct ldb_message); + msg2 = talloc(module, struct ldb_message); if (!msg2) { return -1; } @@ -130,7 +130,7 @@ static int timestamps_add_record(struct ldb_module *module, const struct ldb_mes msg2->dn = msg->dn; msg2->num_elements = msg->num_elements; msg2->private_data = msg->private_data; - msg2->elements = talloc_array_p(msg2, struct ldb_message_element, msg2->num_elements); + msg2->elements = talloc_array(msg2, struct ldb_message_element, msg2->num_elements); for (i = 0; i < msg2->num_elements; i++) { msg2->elements[i] = msg->elements[i]; } @@ -169,7 +169,7 @@ static int timestamps_modify_record(struct ldb_module *module, const struct ldb_ return -1; } - msg2 = talloc_p(module, struct ldb_message); + msg2 = talloc(module, struct ldb_message); if (!msg2) { return -1; } @@ -187,7 +187,7 @@ static int timestamps_modify_record(struct ldb_module *module, const struct ldb_ msg2->dn = msg->dn; msg2->num_elements = msg->num_elements; msg2->private_data = msg->private_data; - msg2->elements = talloc_array_p(msg2, struct ldb_message_element, msg2->num_elements); + msg2->elements = talloc_array(msg2, struct ldb_message_element, msg2->num_elements); for (i = 0; i < msg2->num_elements; i++) { msg2->elements[i] = msg->elements[i]; } @@ -272,11 +272,11 @@ struct ldb_module *timestamps_module_init(struct ldb_context *ldb, const char *o struct ldb_module *ctx; struct private_data *data; - ctx = talloc_p(ldb, struct ldb_module); + ctx = talloc(ldb, struct ldb_module); if (!ctx) return NULL; - data = talloc_p(ctx, struct private_data); + data = talloc(ctx, struct private_data); if (!data) { talloc_free(ctx); return NULL; -- cgit From a7bbb190d9845a74c21369ca32eb8446982477db Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 15 Jan 2005 17:24:42 +0000 Subject: r4759: use ldb_attr_cmp() to compare attribute names check required attributes are not deleted on modify operation if the objectclass is deleted then deny the operation if orphan atributes are left behind (This used to be commit 8c11038d67c495f8d5f06cf1fdfe976088864b45) --- source4/lib/ldb/modules/schema.c | 85 ++++++++++++++++++++++-------------- source4/lib/ldb/modules/timestamps.c | 2 +- 2 files changed, 53 insertions(+), 34 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index 63d94eed81..85f57fc2eb 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -63,9 +63,14 @@ static struct attribute_syntax attrsyn[] = { #define SCHEMA_TALLOC_CHECK(root, mem, ret) do { if (!mem) { talloc_free(root); return ret;} } while(0); -#define SA_FLAG_RESET 0 -#define SA_FLAG_AUXCLASS 1 -#define SA_FLAG_CHECKED 2 +#define SCHEMA_FLAG_RESET 0 +#define SCHEMA_FLAG_MOD_MASK 0x03 +#define SCHEMA_FLAG_MOD_ADD 0x01 +#define SCHEMA_FLAG_MOD_REPLACE 0x02 +#define SCHEMA_FLAG_MOD_DELETE 0x03 +#define SCHEMA_FLAG_AUXCLASS 0x10 +#define SCHEMA_FLAG_CHECKED 0x20 + struct private_data { struct ldb_context *schema_db; @@ -136,7 +141,7 @@ static int get_object_objectclasses(struct ldb_context *ldb, const char *dn, str ldb_search_free(ldb, srch); return -1; } - schema_struct->objectclass_list[j].flags = SA_FLAG_RESET; + schema_struct->objectclass_list[j].flags = SCHEMA_FLAG_RESET; } } ldb_search_free(ldb, srch); @@ -162,7 +167,7 @@ static int get_check_list(struct ldb_module *module, struct schema_structures *s return -1; } for (i = 0, j = 0; i < msg->num_elements; i++) { - if (strcasecmp(msg->elements[i].name, "objectclass") == 0) { + if (ldb_attr_cmp(msg->elements[i].name, "objectclass") == 0) { schema_struct->objectclass_list_num = msg->elements[i].num_values; schema_struct->objectclass_list = talloc_array(schema_struct, struct attribute_list, @@ -177,11 +182,11 @@ static int get_check_list(struct ldb_module *module, struct schema_structures *s if (schema_struct->objectclass_list[k].name == 0) { return -1; } - schema_struct->objectclass_list[k].flags = SA_FLAG_RESET; + schema_struct->objectclass_list[k].flags = msg->elements[i].flags; } } - schema_struct->check_list[j].flags = SA_FLAG_RESET; + schema_struct->check_list[j].flags = msg->elements[i].flags; schema_struct->check_list[j].name = talloc_strdup(schema_struct->check_list, msg->elements[i].name); if (schema_struct->check_list[j].name == 0) { @@ -243,6 +248,9 @@ static int get_attr_list_recursive(struct ldb_module *module, struct ldb_context for (i = 0; i < schema_struct->objectclass_list_num; i++) { char *filter; + if ((schema_struct->objectclass_list[i].flags & SCHEMA_FLAG_MOD_MASK) == SCHEMA_FLAG_MOD_DELETE) { + continue; + } filter = talloc_asprintf(schema_struct, "lDAPDisplayName=%s", schema_struct->objectclass_list[i].name); SCHEMA_TALLOC_CHECK(schema_struct, filter, -1); ret = ldb_search(ldb, NULL, LDB_SCOPE_SUBTREE, filter, NULL, &srch); @@ -251,7 +259,7 @@ static int get_attr_list_recursive(struct ldb_module *module, struct ldb_context ok = 0; /* suppose auxiliary classeschema_struct are not required */ - if (schema_struct->objectclass_list[i].flags & SA_FLAG_AUXCLASS) { + if (schema_struct->objectclass_list[i].flags & SCHEMA_FLAG_AUXCLASS) { int d; ok = 1; schema_struct->objectclass_list_num -= 1; @@ -286,11 +294,11 @@ static int get_attr_list_recursive(struct ldb_module *module, struct ldb_context is_aux = 0; is_class = 0; - if (strcasecmp((*srch)->elements[j].name, "systemAuxiliaryclass") == 0) { - is_aux = SA_FLAG_AUXCLASS; + if (ldb_attr_cmp((*srch)->elements[j].name, "systemAuxiliaryclass") == 0) { + is_aux = SCHEMA_FLAG_AUXCLASS; is_class = 1; } - if (strcasecmp((*srch)->elements[j].name, "subClassOf") == 0) { + if (ldb_attr_cmp((*srch)->elements[j].name, "subClassOf") == 0) { is_class = 1; } @@ -304,23 +312,23 @@ static int get_attr_list_recursive(struct ldb_module *module, struct ldb_context } } else { - if (strcasecmp((*srch)->elements[j].name, "mustContain") == 0 || - strcasecmp((*srch)->elements[j].name, "SystemMustContain") == 0) { + if (ldb_attr_cmp((*srch)->elements[j].name, "mustContain") == 0 || + ldb_attr_cmp((*srch)->elements[j].name, "SystemMustContain") == 0) { if (add_attribute_uniq(&schema_struct->must, &schema_struct->must_num, - SA_FLAG_RESET, + SCHEMA_FLAG_RESET, &(*srch)->elements[j], schema_struct) != 0) { return -1; } } - if (strcasecmp((*srch)->elements[j].name, "mayContain") == 0 || - strcasecmp((*srch)->elements[j].name, "SystemMayContain") == 0) { + if (ldb_attr_cmp((*srch)->elements[j].name, "mayContain") == 0 || + ldb_attr_cmp((*srch)->elements[j].name, "SystemMayContain") == 0) { if (add_attribute_uniq(&schema_struct->may, &schema_struct->may_num, - SA_FLAG_RESET, + SCHEMA_FLAG_RESET, &(*srch)->elements[j], schema_struct) != 0) { return -1; @@ -374,8 +382,8 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message found = 0; for (j = 0; j < entry_structs->check_list_num; j++) { - if (strcasecmp(entry_structs->must[i].name, entry_structs->check_list[j].name) == 0) { - entry_structs->check_list[j].flags = SA_FLAG_CHECKED; + if (ldb_attr_cmp(entry_structs->must[i].name, entry_structs->check_list[j].name) == 0) { + entry_structs->check_list[j].flags = SCHEMA_FLAG_CHECKED; found = 1; break; } @@ -392,13 +400,13 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message /* now check all others atribs are found in mays */ for (i = 0; i < entry_structs->check_list_num; i++) { - if (entry_structs->check_list[i].flags != SA_FLAG_CHECKED) { + if (entry_structs->check_list[i].flags != SCHEMA_FLAG_CHECKED) { int found; found = 0; for (j = 0; j < entry_structs->may_num; j++) { - if (strcasecmp(entry_structs->may[j].name, entry_structs->check_list[i].name) == 0) { - entry_structs->check_list[i].flags = SA_FLAG_CHECKED; + if (ldb_attr_cmp(entry_structs->may[j].name, entry_structs->check_list[i].name) == 0) { + entry_structs->check_list[i].flags = SCHEMA_FLAG_CHECKED; found = 1; break; } @@ -484,17 +492,22 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess int found; found = 0; - for (j = 0; j < entry_structs->may_num; j++) { - if (strcasecmp(entry_structs->may[j].name, modify_structs->check_list[i].name) == 0) { - modify_structs->check_list[i].flags = SA_FLAG_CHECKED; + for (j = 0; j < entry_structs->must_num; j++) { + if (ldb_attr_cmp(entry_structs->must[j].name, modify_structs->check_list[i].name) == 0) { + if ((modify_structs->check_list[i].flags & SCHEMA_FLAG_MOD_MASK) == SCHEMA_FLAG_MOD_DELETE) { + data->error_string = "Objectclass violation: trying to delete a required attribute"; + talloc_free(entry_structs); + return -1; + } + modify_structs->check_list[i].flags |= SCHEMA_FLAG_CHECKED; found = 1; break; } } if ( ! found) { - for (j = 0; j < entry_structs->must_num; j++) { - if (strcasecmp(entry_structs->must[j].name, modify_structs->check_list[i].name) == 0) { - modify_structs->check_list[i].flags = SA_FLAG_CHECKED; + for (j = 0; j < entry_structs->may_num; j++) { + if (ldb_attr_cmp(entry_structs->may[j].name, modify_structs->check_list[i].name) == 0) { + modify_structs->check_list[i].flags |= SCHEMA_FLAG_CHECKED; break; } } @@ -507,8 +520,13 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess found = 0; for (j = 0; j < modify_structs->check_list_num; j++) { - if (strcasecmp(modify_structs->must[i].name, modify_structs->check_list[j].name) == 0) { - modify_structs->check_list[j].flags = SA_FLAG_CHECKED; + if (ldb_attr_cmp(modify_structs->must[i].name, modify_structs->check_list[j].name) == 0) { + if ((modify_structs->check_list[i].flags & SCHEMA_FLAG_MOD_MASK) == SCHEMA_FLAG_MOD_DELETE) { + data->error_string = "Objectclass violation: trying to delete a required attribute"; + talloc_free(entry_structs); + return -1; + } + modify_structs->check_list[j].flags |= SCHEMA_FLAG_CHECKED; found = 1; break; } @@ -525,13 +543,14 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess /* now check all others atribs are found in mays */ for (i = 0; i < modify_structs->check_list_num; i++) { - if (modify_structs->check_list[i].flags != SA_FLAG_CHECKED) { + if ((modify_structs->check_list[i].flags & SCHEMA_FLAG_CHECKED) == 0 && + (modify_structs->check_list[i].flags & SCHEMA_FLAG_MOD_MASK) != SCHEMA_FLAG_MOD_DELETE) { int found; found = 0; for (j = 0; j < modify_structs->may_num; j++) { - if (strcasecmp(modify_structs->may[j].name, modify_structs->check_list[i].name) == 0) { - modify_structs->check_list[i].flags = SA_FLAG_CHECKED; + if (ldb_attr_cmp(modify_structs->may[j].name, modify_structs->check_list[i].name) == 0) { + modify_structs->check_list[i].flags |= SCHEMA_FLAG_CHECKED; found = 1; break; } diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index 4066d231cd..1deeeb218b 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -69,7 +69,7 @@ static int add_time_element(struct ldb_module *module, struct ldb_message *msg, int i; for (i = 0; i < msg->num_elements; i++) { - if (strcasecmp(msg->elements[i].name, attr_name) == 0) { + if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) { return 0; } } -- cgit From 1e233e90535188aec8f74b8c30f9f9695ef30f87 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 16 Jan 2005 10:48:46 +0000 Subject: r4775: use schema_attr_cmp wrapper to check for the special dn/distinguishedName case alias (This used to be commit 18cd6cb67404830b8a5d28fa4106dadb275a5222) --- source4/lib/ldb/modules/schema.c | 92 +++++++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 35 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index 85f57fc2eb..114c7f44aa 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -77,26 +77,6 @@ struct private_data { const char *error_string; }; -/* close */ -static int schema_close(struct ldb_module *module) -{ - return ldb_next_close(module); -} - -/* search */ -static int schema_search(struct ldb_module *module, const char *base, - enum ldb_scope scope, const char *expression, - const char * const *attrs, struct ldb_message ***res) -{ - return ldb_next_search(module, base, scope, expression, attrs, res); -} - -/* search_free */ -static int schema_search_free(struct ldb_module *module, struct ldb_message **res) -{ - return ldb_next_search_free(module, res); -} - struct attribute_list { int flags; char *name; @@ -113,6 +93,30 @@ struct schema_structures { int may_num; }; +/* This function embedds the knowledge of aliased names. + Currently it handles only dn vs distinguishedNAme as a special case as AD + only have this special alias case, in future we should read the schema + to find out which names have an alias and check for them */ +static int schema_attr_cmp(const char *attr1, const char *attr2) +{ + int ret; + + ret = ldb_attr_cmp(attr1, attr2); + if (ret != 0) { + if (tolower(*attr1) == 'd' && tolower(*attr2) == 'd') { + if ((ldb_attr_cmp("dn", attr1) == 0) && + (ldb_attr_cmp("distinguishedName", attr2) == 0)) { + return 0; + } + if ((ldb_attr_cmp("dn", attr2) == 0) && + (ldb_attr_cmp("distinguishedName", attr1) == 0)) { + return 0; + } + } + } + return ret; +} + static int get_object_objectclasses(struct ldb_context *ldb, const char *dn, struct schema_structures *schema_struct) { char *filter = talloc_asprintf(schema_struct, "dn=%s", dn); @@ -167,7 +171,7 @@ static int get_check_list(struct ldb_module *module, struct schema_structures *s return -1; } for (i = 0, j = 0; i < msg->num_elements; i++) { - if (ldb_attr_cmp(msg->elements[i].name, "objectclass") == 0) { + if (schema_attr_cmp(msg->elements[i].name, "objectclass") == 0) { schema_struct->objectclass_list_num = msg->elements[i].num_values; schema_struct->objectclass_list = talloc_array(schema_struct, struct attribute_list, @@ -294,11 +298,11 @@ static int get_attr_list_recursive(struct ldb_module *module, struct ldb_context is_aux = 0; is_class = 0; - if (ldb_attr_cmp((*srch)->elements[j].name, "systemAuxiliaryclass") == 0) { + if (schema_attr_cmp((*srch)->elements[j].name, "systemAuxiliaryclass") == 0) { is_aux = SCHEMA_FLAG_AUXCLASS; is_class = 1; } - if (ldb_attr_cmp((*srch)->elements[j].name, "subClassOf") == 0) { + if (schema_attr_cmp((*srch)->elements[j].name, "subClassOf") == 0) { is_class = 1; } @@ -312,8 +316,8 @@ static int get_attr_list_recursive(struct ldb_module *module, struct ldb_context } } else { - if (ldb_attr_cmp((*srch)->elements[j].name, "mustContain") == 0 || - ldb_attr_cmp((*srch)->elements[j].name, "SystemMustContain") == 0) { + if (schema_attr_cmp((*srch)->elements[j].name, "mustContain") == 0 || + schema_attr_cmp((*srch)->elements[j].name, "SystemMustContain") == 0) { if (add_attribute_uniq(&schema_struct->must, &schema_struct->must_num, SCHEMA_FLAG_RESET, @@ -323,8 +327,8 @@ static int get_attr_list_recursive(struct ldb_module *module, struct ldb_context } } - if (ldb_attr_cmp((*srch)->elements[j].name, "mayContain") == 0 || - ldb_attr_cmp((*srch)->elements[j].name, "SystemMayContain") == 0) { + if (schema_attr_cmp((*srch)->elements[j].name, "mayContain") == 0 || + schema_attr_cmp((*srch)->elements[j].name, "SystemMayContain") == 0) { if (add_attribute_uniq(&schema_struct->may, &schema_struct->may_num, @@ -343,6 +347,26 @@ static int get_attr_list_recursive(struct ldb_module *module, struct ldb_context return 0; } +/* close */ +static int schema_close(struct ldb_module *module) +{ + return ldb_next_close(module); +} + +/* search */ +static int schema_search(struct ldb_module *module, const char *base, + enum ldb_scope scope, const char *expression, + const char * const *attrs, struct ldb_message ***res) +{ + return ldb_next_search(module, base, scope, expression, attrs, res); +} + +/* search_free */ +static int schema_search_free(struct ldb_module *module, struct ldb_message **res) +{ + return ldb_next_search_free(module, res); +} + /* add_record */ static int schema_add_record(struct ldb_module *module, const struct ldb_message *msg) { @@ -382,7 +406,7 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message found = 0; for (j = 0; j < entry_structs->check_list_num; j++) { - if (ldb_attr_cmp(entry_structs->must[i].name, entry_structs->check_list[j].name) == 0) { + if (schema_attr_cmp(entry_structs->must[i].name, entry_structs->check_list[j].name) == 0) { entry_structs->check_list[j].flags = SCHEMA_FLAG_CHECKED; found = 1; break; @@ -390,7 +414,6 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message } if ( ! found ) { - /* TODO: set the error string */ data->error_string = "Objectclass violation, a required attribute is mischema_structing"; talloc_free(entry_structs); return -1; @@ -405,7 +428,7 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message found = 0; for (j = 0; j < entry_structs->may_num; j++) { - if (ldb_attr_cmp(entry_structs->may[j].name, entry_structs->check_list[i].name) == 0) { + if (schema_attr_cmp(entry_structs->may[j].name, entry_structs->check_list[i].name) == 0) { entry_structs->check_list[i].flags = SCHEMA_FLAG_CHECKED; found = 1; break; @@ -493,7 +516,7 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess found = 0; for (j = 0; j < entry_structs->must_num; j++) { - if (ldb_attr_cmp(entry_structs->must[j].name, modify_structs->check_list[i].name) == 0) { + if (schema_attr_cmp(entry_structs->must[j].name, modify_structs->check_list[i].name) == 0) { if ((modify_structs->check_list[i].flags & SCHEMA_FLAG_MOD_MASK) == SCHEMA_FLAG_MOD_DELETE) { data->error_string = "Objectclass violation: trying to delete a required attribute"; talloc_free(entry_structs); @@ -506,7 +529,7 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess } if ( ! found) { for (j = 0; j < entry_structs->may_num; j++) { - if (ldb_attr_cmp(entry_structs->may[j].name, modify_structs->check_list[i].name) == 0) { + if (schema_attr_cmp(entry_structs->may[j].name, modify_structs->check_list[i].name) == 0) { modify_structs->check_list[i].flags |= SCHEMA_FLAG_CHECKED; break; } @@ -520,7 +543,7 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess found = 0; for (j = 0; j < modify_structs->check_list_num; j++) { - if (ldb_attr_cmp(modify_structs->must[i].name, modify_structs->check_list[j].name) == 0) { + if (schema_attr_cmp(modify_structs->must[i].name, modify_structs->check_list[j].name) == 0) { if ((modify_structs->check_list[i].flags & SCHEMA_FLAG_MOD_MASK) == SCHEMA_FLAG_MOD_DELETE) { data->error_string = "Objectclass violation: trying to delete a required attribute"; talloc_free(entry_structs); @@ -533,7 +556,6 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess } if ( ! found ) { - /* TODO: set the error string */ data->error_string = "Objectclass violation, a required attribute is missing"; talloc_free(entry_structs); return -1; @@ -549,7 +571,7 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess found = 0; for (j = 0; j < modify_structs->may_num; j++) { - if (ldb_attr_cmp(modify_structs->may[j].name, modify_structs->check_list[i].name) == 0) { + if (schema_attr_cmp(modify_structs->may[j].name, modify_structs->check_list[i].name) == 0) { modify_structs->check_list[i].flags |= SCHEMA_FLAG_CHECKED; found = 1; break; -- cgit From 5dbebbe2add359da8c416634e3ec2d8e2569478a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 16 Jan 2005 20:48:53 +0000 Subject: r4781: the tolower() in schema.c is a premature optimisation. I suspect the "distinguishedName" checking in that module is incorrect and should be removed, but meanwhile, lets not make it slow down the compile of every other module. (This used to be commit 6534ce650bef7405e0926c9b75b185943429ed18) --- source4/lib/ldb/modules/schema.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index 114c7f44aa..7a772d87aa 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -35,6 +35,7 @@ #include "includes.h" #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" +#include struct attribute_syntax { const char *name; @@ -103,15 +104,13 @@ static int schema_attr_cmp(const char *attr1, const char *attr2) ret = ldb_attr_cmp(attr1, attr2); if (ret != 0) { - if (tolower(*attr1) == 'd' && tolower(*attr2) == 'd') { - if ((ldb_attr_cmp("dn", attr1) == 0) && - (ldb_attr_cmp("distinguishedName", attr2) == 0)) { - return 0; - } - if ((ldb_attr_cmp("dn", attr2) == 0) && - (ldb_attr_cmp("distinguishedName", attr1) == 0)) { - return 0; - } + if ((ldb_attr_cmp("dn", attr1) == 0) && + (ldb_attr_cmp("distinguishedName", attr2) == 0)) { + return 0; + } + if ((ldb_attr_cmp("dn", attr2) == 0) && + (ldb_attr_cmp("distinguishedName", attr1) == 0)) { + return 0; } } return ret; -- cgit From 63f79d11b802bebe105eccd385fab452e4a68e39 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 16 Jan 2005 22:30:38 +0000 Subject: r4784: finally make schema module use a single ldb add the new test-schema test (This used to be commit 42a20f6fa4073fc5ea1ca6254137a4ef53caee01) --- source4/lib/ldb/modules/schema.c | 65 +++++++++------------------------------- 1 file changed, 14 insertions(+), 51 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index 7a772d87aa..97cc26a0dd 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -32,6 +32,7 @@ * Author: Simo Sorce */ +#include #include "includes.h" #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" @@ -74,7 +75,6 @@ static struct attribute_syntax attrsyn[] = { struct private_data { - struct ldb_context *schema_db; const char *error_string; }; @@ -273,6 +273,7 @@ static int get_attr_list_recursive(struct ldb_module *module, struct ldb_context } if (!ok) { /* Schema Violation: Object Class Description Not Found */ + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Objectclass %s not found.\n", schema_struct->objectclass_list[i].name); data->error_string = "ObjectClass not found"; return -1; } @@ -280,11 +281,13 @@ static int get_attr_list_recursive(struct ldb_module *module, struct ldb_context } else { if (ret < 0) { /* Schema DB Error: Error occurred retrieving Object Class Description */ + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Error retrieving Objectclass %s.\n", schema_struct->objectclass_list[i].name); data->error_string = "Internal error. Error retrieving schema objectclass"; return -1; } if (ret > 1) { /* Schema DB Error: Too Many Records */ + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Too many records found retrieving Objectclass %s.\n", schema_struct->objectclass_list[i].name); data->error_string = "Internal error. Too many records searching for schema objectclass"; return -1; } @@ -393,7 +396,7 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message } /* find all other objectclasses recursively */ - ret = get_attr_list_recursive(module, data->schema_db, entry_structs); + ret = get_attr_list_recursive(module, module->ldb, entry_structs); if (ret != 0) { talloc_free(entry_structs); return ret; @@ -413,7 +416,8 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message } if ( ! found ) { - data->error_string = "Objectclass violation, a required attribute is mischema_structing"; + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "The required attribute %s is missing.\n", entry_structs->must[i].name); + data->error_string = "Objectclass violation, a required attribute is missing"; talloc_free(entry_structs); return -1; } @@ -435,6 +439,7 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message } if ( ! found ) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "The attribute %s is not referenced by any objectclass.\n", entry_structs->check_list[i].name); data->error_string = "Objectclass violation, an invalid attribute name was found"; talloc_free(entry_structs); return -1; @@ -487,7 +492,7 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess } /* find all modify objectclasses recursively if any objectclass is being added */ - ret = get_attr_list_recursive(module, data->schema_db, modify_structs); + ret = get_attr_list_recursive(module, module->ldb, modify_structs); if (ret != 0) { talloc_free(entry_structs); return ret; @@ -501,7 +506,7 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess } /* find all other objectclasses recursively */ - ret = get_attr_list_recursive(module, data->schema_db, entry_structs); + ret = get_attr_list_recursive(module, module->ldb, entry_structs); if (ret != 0) { talloc_free(entry_structs); return ret; @@ -517,6 +522,7 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess for (j = 0; j < entry_structs->must_num; j++) { if (schema_attr_cmp(entry_structs->must[j].name, modify_structs->check_list[i].name) == 0) { if ((modify_structs->check_list[i].flags & SCHEMA_FLAG_MOD_MASK) == SCHEMA_FLAG_MOD_DELETE) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Trying to delete the required attribute %s.\n", modify_structs->check_list[i].name); data->error_string = "Objectclass violation: trying to delete a required attribute"; talloc_free(entry_structs); return -1; @@ -544,6 +550,7 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess for (j = 0; j < modify_structs->check_list_num; j++) { if (schema_attr_cmp(modify_structs->must[i].name, modify_structs->check_list[j].name) == 0) { if ((modify_structs->check_list[i].flags & SCHEMA_FLAG_MOD_MASK) == SCHEMA_FLAG_MOD_DELETE) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Trying to delete the required attribute %s.\n", modify_structs->must[i].name); data->error_string = "Objectclass violation: trying to delete a required attribute"; talloc_free(entry_structs); return -1; @@ -555,6 +562,7 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess } if ( ! found ) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "The required attribute %s is missing.\n", modify_structs->must[i].name); data->error_string = "Objectclass violation, a required attribute is missing"; talloc_free(entry_structs); return -1; @@ -578,6 +586,7 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess } if ( ! found ) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "The attribute %s is not referenced by any objectclass.\n", modify_structs->check_list[i].name); data->error_string = "Objectclass violation, an invalid attribute name was found"; talloc_free(entry_structs); return -1; @@ -641,9 +650,6 @@ static const struct ldb_module_ops schema_ops = { schema_errstring, }; -#define SCHEMA_PREFIX "schema:" -#define SCHEMA_PREFIX_LEN 7 - #ifdef HAVE_DLOPEN_DISABLED struct ldb_module *init_module(struct ldb_context *ldb, const char *options[]) #else @@ -652,58 +658,15 @@ struct ldb_module *schema_module_init(struct ldb_context *ldb, const char *optio { struct ldb_module *ctx; struct private_data *data; - char *db_url = NULL; - int i; ctx = talloc(ldb, struct ldb_module); if (!ctx) { return NULL; } - if (options) { - for (i = 0; options[i] != NULL; i++) { - if (strncmp(options[i], SCHEMA_PREFIX, SCHEMA_PREFIX_LEN) == 0) { - db_url = talloc_strdup(ctx, &options[i][SCHEMA_PREFIX_LEN]); - SCHEMA_TALLOC_CHECK(ctx, db_url, NULL); - } - } - } - - if (!db_url) { /* search if it is defined in the calling ldb */ - int ret; - const char * attrs[] = { "@SCHEMADB", NULL }; - struct ldb_message **msgs; - - ret = ldb_search(ldb, "", LDB_SCOPE_BASE, "dn=@MODULES", (const char * const *)attrs, &msgs); - if (ret == 0) { - ldb_debug(ldb, LDB_DEBUG_TRACE, "Schema DB not found\n"); - ldb_search_free(ldb, msgs); - return NULL; - } else { - if (ret < 0) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "ldb error (%s) occurred searching for schema db, bailing out!\n", ldb_errstring(ldb)); - ldb_search_free(ldb, msgs); - return NULL; - } - if (ret > 1) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "Too many records found, bailing out\n"); - ldb_search_free(ldb, msgs); - return NULL; - } - - db_url = talloc_strndup(ctx, msgs[0]->elements[0].values[0].data, msgs[0]->elements[0].values[0].length); - SCHEMA_TALLOC_CHECK(ctx, db_url, NULL); - } - - ldb_search_free(ldb, msgs); - } - data = talloc(ctx, struct private_data); SCHEMA_TALLOC_CHECK(ctx, data, NULL); - data->schema_db = ldb_connect(db_url, 0, NULL); - SCHEMA_TALLOC_CHECK(ctx, data->schema_db, NULL); - data->error_string = NULL; ctx->private_data = data; ctx->ldb = ldb; -- cgit From 9f3d73430828bdc94ae59cb2db1c3ba79c710ab4 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 16 Jan 2005 22:41:43 +0000 Subject: r4786: forgot to commit the exclusion for schema checking against our control entries (This used to be commit e895fcf4a33aeaf228d8b4b367c4e768506275bb) --- source4/lib/ldb/modules/schema.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index 97cc26a0dd..a56e71ef7a 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -384,6 +384,10 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message Free all structures and commit the change */ + if (msg->dn[0] == '@') { /* do not check on our control entries */ + return ldb_next_add_record(module, msg); + } + entry_structs = talloc(module, struct schema_structures); if (!entry_structs) { return -1; @@ -471,6 +475,10 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess Free all structures and commit the change. */ + if (msg->dn[0] == '@') { /* do not check on our control entries */ + return ldb_next_modify_record(module, msg); + } + /* allocate object structs */ entry_structs = talloc(module, struct schema_structures); if (!entry_structs) { -- cgit From ec6f6aeda18f905ba58a86f61b8eabf306ed22e2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 17 Jan 2005 11:54:22 +0000 Subject: r4801: remove the two bogus ctype.h includes (This used to be commit b221c3dbb9a7af88f917562b6f907fd0617eb05f) --- source4/lib/ldb/modules/schema.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index a56e71ef7a..912c8657d2 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -32,11 +32,9 @@ * Author: Simo Sorce */ -#include #include "includes.h" #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" -#include struct attribute_syntax { const char *name; -- cgit From f19049c9c9fcf891c638c56c13071d09a3a46c54 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 19 Jan 2005 13:54:10 +0000 Subject: r4844: - Remove the unused attrsyn structure - Change 0 to NULL when checking allocations - Introduce the schema_attr_cmp hepler function - Do not allow auxiliary classes to be missing - Try to ease code readability and try to get main code out of loops when possibile. (This used to be commit a30f647b8abe6b77ef73018f58af2f8a11689b91) --- source4/lib/ldb/modules/schema.c | 339 +++++++++++++++++++-------------------- 1 file changed, 164 insertions(+), 175 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index 912c8657d2..b396ae0459 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -36,33 +36,6 @@ #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" -struct attribute_syntax { - const char *name; - const char *syntax_id; -}; - -static struct attribute_syntax attrsyn[] = { - { "Object(DS-DN)", "2.5.5.1"}, - { "String(Object-Identifier)", "2.5.5.2"}, - { "", "2.5.5.3"}, - { "String(Teletex)", "2.5.5.4"}, - { "String(IA5)", "2.5.5.5"}, /* Also String(Printable) */ - { "String(Numeric)", "2.5.5.6"}, - { "Object(DN-Binary)", "2.5.5.7"}, /* Also Object(OR-Name) */ - { "Boolean", "2.5.5.8"}, - { "Integer", "2.5.5.9"}, /* Also Enumeration (3 types ?) ... */ - { "String(Octet)", "2.5.5.10"}, /* Also Object(Replica-Link) */ - { "String(UTC-Time)", "2.5.5.11"}, /* Also String(Generalized-Time) */ - { "String(Unicode)", "2.5.5.12"}, - { "Object(Presentation-Address)", "2.5.5.13"}, - { "Object(DN-String)", "2.5.5.14"}, /* Also Object(Access-Point) */ - { "String(NT-Sec-Desc))", "2.5.5.15"}, - { "LargeInteger", "2.5.5.16"}, /* Also Interval ... */ - { "String(Sid)", "2.5.5.17"} - }; - -#define SCHEMA_TALLOC_CHECK(root, mem, ret) do { if (!mem) { talloc_free(root); return ret;} } while(0); - #define SCHEMA_FLAG_RESET 0 #define SCHEMA_FLAG_MOD_MASK 0x03 #define SCHEMA_FLAG_MOD_ADD 0x01 @@ -114,6 +87,18 @@ static int schema_attr_cmp(const char *attr1, const char *attr2) return ret; } +struct attribute_list *schema_find_attribute(struct attribute_list *list, int attr_num, const char *attr_name) +{ + unsigned int i; + for (i = 0; i < attr_num; i++) { + if (ldb_attr_cmp(list[i].name, attr_name) == 0) { + return &list[i]; + } + } + return NULL; +} + +/* get objectclasses of dn */ static int get_object_objectclasses(struct ldb_context *ldb, const char *dn, struct schema_structures *schema_struct) { char *filter = talloc_asprintf(schema_struct, "dn=%s", dn); @@ -124,36 +109,39 @@ static int get_object_objectclasses(struct ldb_context *ldb, const char *dn, str schema_struct->objectclass_list = NULL; schema_struct->objectclass_list_num = 0; ret = ldb_search(ldb, NULL, LDB_SCOPE_SUBTREE, filter, attrs, &srch); - if (ret == 1) { - for (i = 0; i < (*srch)->num_elements; i++) { - schema_struct->objectclass_list_num = (*srch)->elements[i].num_values; - schema_struct->objectclass_list = talloc_array(schema_struct, - struct attribute_list, - schema_struct->objectclass_list_num); - if (schema_struct->objectclass_list == 0) { + if (ret != 1) { + ldb_search_free(ldb, srch); + return -1; + } + + for (i = 0; i < (*srch)->num_elements; i++) { + schema_struct->objectclass_list_num = (*srch)->elements[i].num_values; + schema_struct->objectclass_list = talloc_array(schema_struct, + struct attribute_list, + schema_struct->objectclass_list_num); + if (schema_struct->objectclass_list == NULL) { + ldb_search_free(ldb, srch); + return -1; + } + for (j = 0; j < schema_struct->objectclass_list_num; j++) { + schema_struct->objectclass_list[j].name = talloc_strndup(schema_struct->objectclass_list, + (*srch)->elements[i].values[j].data, + (*srch)->elements[i].values[j].length); + if (schema_struct->objectclass_list[j].name == NULL) { ldb_search_free(ldb, srch); return -1; } - for (j = 0; j < schema_struct->objectclass_list_num; j++) { - schema_struct->objectclass_list[j].name = talloc_strndup(schema_struct->objectclass_list, - (*srch)->elements[i].values[j].data, - (*srch)->elements[i].values[j].length); - if (schema_struct->objectclass_list[j].name == 0) { - ldb_search_free(ldb, srch); - return -1; - } - schema_struct->objectclass_list[j].flags = SCHEMA_FLAG_RESET; - } + schema_struct->objectclass_list[j].flags = SCHEMA_FLAG_RESET; } - ldb_search_free(ldb, srch); - } else { - ldb_search_free(ldb, srch); - return -1; } + ldb_search_free(ldb, srch); return 0; } +/* get all the attributes and objectclasses found in msg and put them in schema_structure + attributes go in the check_list structure for later checking + objectclasses go in the objectclass_list structure */ static int get_check_list(struct ldb_module *module, struct schema_structures *schema_struct, const struct ldb_message *msg) { int i, j, k; @@ -164,7 +152,7 @@ static int get_check_list(struct ldb_module *module, struct schema_structures *s schema_struct->check_list = talloc_array(schema_struct, struct attribute_list, schema_struct->check_list_num); - if (schema_struct->check_list == 0) { + if (schema_struct->check_list == NULL) { return -1; } for (i = 0, j = 0; i < msg->num_elements; i++) { @@ -173,14 +161,14 @@ static int get_check_list(struct ldb_module *module, struct schema_structures *s schema_struct->objectclass_list = talloc_array(schema_struct, struct attribute_list, schema_struct->objectclass_list_num); - if (schema_struct->objectclass_list == 0) { + if (schema_struct->objectclass_list == NULL) { return -1; } for (k = 0; k < schema_struct->objectclass_list_num; k++) { schema_struct->objectclass_list[k].name = talloc_strndup(schema_struct->objectclass_list, msg->elements[i].values[k].data, msg->elements[i].values[k].length); - if (schema_struct->objectclass_list[k].name == 0) { + if (schema_struct->objectclass_list[k].name == NULL) { return -1; } schema_struct->objectclass_list[k].flags = msg->elements[i].flags; @@ -190,7 +178,7 @@ static int get_check_list(struct ldb_module *module, struct schema_structures *s schema_struct->check_list[j].flags = msg->elements[i].flags; schema_struct->check_list[j].name = talloc_strdup(schema_struct->check_list, msg->elements[i].name); - if (schema_struct->check_list[j].name == 0) { + if (schema_struct->check_list[j].name == NULL) { return -1; } j++; @@ -199,6 +187,7 @@ static int get_check_list(struct ldb_module *module, struct schema_structures *s return 0; } +/* add all attributes in el avoiding duplicates in attribute_list */ static int add_attribute_uniq(struct attribute_list **list, int *list_num, int flags, struct ldb_message_element *el, void *mem_ctx) { int i, j, vals; @@ -235,6 +224,9 @@ static int add_attribute_uniq(struct attribute_list **list, int *list_num, int f return 0; } + +/* we need to get all attributes referenced by the entry objectclasses, + recursively get parent objectlasses attributes */ static int get_attr_list_recursive(struct ldb_module *module, struct ldb_context *ldb, struct schema_structures *schema_struct) { struct private_data *data = (struct private_data *)module->private_data; @@ -253,46 +245,27 @@ static int get_attr_list_recursive(struct ldb_module *module, struct ldb_context continue; } filter = talloc_asprintf(schema_struct, "lDAPDisplayName=%s", schema_struct->objectclass_list[i].name); - SCHEMA_TALLOC_CHECK(schema_struct, filter, -1); + if (filter == NULL) { + return -1; + } + ret = ldb_search(ldb, NULL, LDB_SCOPE_SUBTREE, filter, NULL, &srch); - if (ret == 0) { - int ok; - - ok = 0; - /* suppose auxiliary classeschema_struct are not required */ - if (schema_struct->objectclass_list[i].flags & SCHEMA_FLAG_AUXCLASS) { - int d; - ok = 1; - schema_struct->objectclass_list_num -= 1; - for (d = i; d < schema_struct->objectclass_list_num; d++) { - schema_struct->objectclass_list[d] = schema_struct->objectclass_list[d + 1]; - } - i -= 1; - } - if (!ok) { - /* Schema Violation: Object Class Description Not Found */ - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Objectclass %s not found.\n", schema_struct->objectclass_list[i].name); - data->error_string = "ObjectClass not found"; - return -1; - } - continue; - } else { - if (ret < 0) { - /* Schema DB Error: Error occurred retrieving Object Class Description */ - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Error retrieving Objectclass %s.\n", schema_struct->objectclass_list[i].name); - data->error_string = "Internal error. Error retrieving schema objectclass"; - return -1; - } - if (ret > 1) { - /* Schema DB Error: Too Many Records */ - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Too many records found retrieving Objectclass %s.\n", schema_struct->objectclass_list[i].name); - data->error_string = "Internal error. Too many records searching for schema objectclass"; - return -1; - } + + if (ret <= 0) { + /* Schema DB Error: Error occurred retrieving Object Class Description */ + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Error retrieving Objectclass %s.\n", schema_struct->objectclass_list[i].name); + data->error_string = "Internal error. Error retrieving schema objectclass"; + return -1; + } + if (ret > 1) { + /* Schema DB Error: Too Many Records */ + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Too many records found retrieving Objectclass %s.\n", schema_struct->objectclass_list[i].name); + data->error_string = "Internal error. Too many records searching for schema objectclass"; + return -1; } /* Add inherited classes eliminating duplicates */ - /* fill in kust and may attribute lists */ + /* fill in required and optional attribute lists */ for (j = 0; j < (*srch)->num_elements; j++) { int is_aux, is_class; @@ -372,12 +345,13 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message { struct private_data *data = (struct private_data *)module->private_data; struct schema_structures *entry_structs; - int i, j; + unsigned int i; int ret; /* First implementation: - Build up a list of must and mays from each objectclass - Check all the musts are there and all the other attributes are mays + Build up a list of required and optional attributes from each objectclass + Check all the required attributes are present and all the other attributes + are optional attributes Throw an error in case a check fail Free all structures and commit the change */ @@ -404,44 +378,43 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message return ret; } - /* now check all musts are present */ + /* now check all required attributes are present */ for (i = 0; i < entry_structs->must_num; i++) { - int found; + struct attribute_list *attr; - found = 0; - for (j = 0; j < entry_structs->check_list_num; j++) { - if (schema_attr_cmp(entry_structs->must[i].name, entry_structs->check_list[j].name) == 0) { - entry_structs->check_list[j].flags = SCHEMA_FLAG_CHECKED; - found = 1; - break; - } - } + attr = schema_find_attribute(entry_structs->check_list, + entry_structs->check_list_num, + entry_structs->must[i].name); + + if (attr == NULL) { /* not found */ + ldb_debug(module->ldb, LDB_DEBUG_ERROR, + "The required attribute %s is missing.\n", + entry_structs->must[i].name); - if ( ! found ) { - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "The required attribute %s is missing.\n", entry_structs->must[i].name); data->error_string = "Objectclass violation, a required attribute is missing"; talloc_free(entry_structs); return -1; } + + /* mark the attribute as checked */ + attr->flags = SCHEMA_FLAG_CHECKED; } - /* now check all others atribs are found in mays */ + /* now check all others atribs are at least optional */ for (i = 0; i < entry_structs->check_list_num; i++) { if (entry_structs->check_list[i].flags != SCHEMA_FLAG_CHECKED) { - int found; + struct attribute_list *attr; - found = 0; - for (j = 0; j < entry_structs->may_num; j++) { - if (schema_attr_cmp(entry_structs->may[j].name, entry_structs->check_list[i].name) == 0) { - entry_structs->check_list[i].flags = SCHEMA_FLAG_CHECKED; - found = 1; - break; - } - } + attr = schema_find_attribute(entry_structs->may, + entry_structs->may_num, + entry_structs->check_list[i].name); + + if (attr == NULL) { /* not found */ + ldb_debug(module->ldb, LDB_DEBUG_ERROR, + "The attribute %s is not referenced by any objectclass.\n", + entry_structs->check_list[i].name); - if ( ! found ) { - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "The attribute %s is not referenced by any objectclass.\n", entry_structs->check_list[i].name); data->error_string = "Objectclass violation, an invalid attribute name was found"; talloc_free(entry_structs); return -1; @@ -459,16 +432,16 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess { struct private_data *data = (struct private_data *)module->private_data; struct schema_structures *entry_structs, *modify_structs; - int i, j; + unsigned int i; int ret; /* First implementation: Retrieve the ldap entry and get the objectclasses, add msg contained objectclasses if any. - Build up a list of must and mays from each objectclass - Check all musts for the defined objectclass and it's specific - inheritance are there. - Check all other the attributes are mays or musts. + Build up a list of required and optional attributes from each objectclass + Check all required one for the defined objectclass and all its parent + objectclasses. + Check all other the attributes are optional or required. Throw an error in case a check fail. Free all structures and commit the change. */ @@ -478,13 +451,13 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess } /* allocate object structs */ - entry_structs = talloc(module, struct schema_structures); + entry_structs = talloc_zero(module, struct schema_structures); if (!entry_structs) { return -1; } /* allocate modification entry structs */ - modify_structs = talloc(entry_structs, struct schema_structures); + modify_structs = talloc_zero(entry_structs, struct schema_structures); if (!modify_structs) { talloc_free(entry_structs); return -1; @@ -518,85 +491,98 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess return ret; } - /* now check all entries are present either as musts or mays of curent objectclasses */ - /* do not return errors there may be attirbutes defined in new objectclasses */ - /* just mark them as being proved valid attribs */ + /* now check all entries are present either as required or optional atributes of entry objectclasses */ + /* if they are required and we are going to delete them then throw an error */ + /* just mark them if being proved valid attribs */ for (i = 0; i < modify_structs->check_list_num; i++) { - int found; + struct attribute_list *attr; - found = 0; - for (j = 0; j < entry_structs->must_num; j++) { - if (schema_attr_cmp(entry_structs->must[j].name, modify_structs->check_list[i].name) == 0) { - if ((modify_structs->check_list[i].flags & SCHEMA_FLAG_MOD_MASK) == SCHEMA_FLAG_MOD_DELETE) { - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Trying to delete the required attribute %s.\n", modify_structs->check_list[i].name); - data->error_string = "Objectclass violation: trying to delete a required attribute"; - talloc_free(entry_structs); - return -1; - } + attr = schema_find_attribute(entry_structs->must, + entry_structs->must_num, + modify_structs->check_list[i].name); + + if (attr == NULL) { /* not found */ + + attr = schema_find_attribute(entry_structs->may, + entry_structs->may_num, + modify_structs->check_list[i].name); + + if (attr != NULL) { /* found*/ modify_structs->check_list[i].flags |= SCHEMA_FLAG_CHECKED; - found = 1; - break; } + + break; /* not found, go on */ } - if ( ! found) { - for (j = 0; j < entry_structs->may_num; j++) { - if (schema_attr_cmp(entry_structs->may[j].name, modify_structs->check_list[i].name) == 0) { - modify_structs->check_list[i].flags |= SCHEMA_FLAG_CHECKED; - break; - } - } + + if ((modify_structs->check_list[i].flags & SCHEMA_FLAG_MOD_MASK) == SCHEMA_FLAG_MOD_DELETE) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, + "Trying to delete the required attribute %s.\n", + modify_structs->check_list[i].name); + + data->error_string = "Objectclass violation: trying to delete a required attribute"; + talloc_free(entry_structs); + return -1; } + + modify_structs->check_list[i].flags |= SCHEMA_FLAG_CHECKED; } - /* now check all new objectclasses musts are present */ + /* now check all new objectclasses required attributes are present */ for (i = 0; i < modify_structs->must_num; i++) { - int found; + struct attribute_list *attr; - found = 0; - for (j = 0; j < modify_structs->check_list_num; j++) { - if (schema_attr_cmp(modify_structs->must[i].name, modify_structs->check_list[j].name) == 0) { - if ((modify_structs->check_list[i].flags & SCHEMA_FLAG_MOD_MASK) == SCHEMA_FLAG_MOD_DELETE) { - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Trying to delete the required attribute %s.\n", modify_structs->must[i].name); - data->error_string = "Objectclass violation: trying to delete a required attribute"; - talloc_free(entry_structs); - return -1; - } - modify_structs->check_list[j].flags |= SCHEMA_FLAG_CHECKED; - found = 1; - break; - } - } + attr = schema_find_attribute(modify_structs->check_list, + modify_structs->check_list_num, + modify_structs->must[i].name); + + + if (attr == NULL) { /* not found */ + ldb_debug(module->ldb, LDB_DEBUG_ERROR, + "The required attribute %s is missing.\n", + modify_structs->must[i].name); - if ( ! found ) { - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "The required attribute %s is missing.\n", modify_structs->must[i].name); data->error_string = "Objectclass violation, a required attribute is missing"; talloc_free(entry_structs); return -1; } + + if ((modify_structs->check_list[i].flags & SCHEMA_FLAG_MOD_MASK) == SCHEMA_FLAG_MOD_DELETE) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, + "Trying to delete the required attribute %s.\n", + modify_structs->must[i].name); + + data->error_string = "Objectclass violation: trying to delete a required attribute"; + talloc_free(entry_structs); + return -1; + } + + attr->flags |= SCHEMA_FLAG_CHECKED; } - /* now check all others atribs are found in mays */ + /* now check all others attributes are at least optional */ for (i = 0; i < modify_structs->check_list_num; i++) { if ((modify_structs->check_list[i].flags & SCHEMA_FLAG_CHECKED) == 0 && (modify_structs->check_list[i].flags & SCHEMA_FLAG_MOD_MASK) != SCHEMA_FLAG_MOD_DELETE) { - int found; + struct attribute_list *attr; + + attr = schema_find_attribute(modify_structs->may, + modify_structs->may_num, + modify_structs->check_list[i].name); - found = 0; - for (j = 0; j < modify_structs->may_num; j++) { - if (schema_attr_cmp(modify_structs->may[j].name, modify_structs->check_list[i].name) == 0) { - modify_structs->check_list[i].flags |= SCHEMA_FLAG_CHECKED; - found = 1; - break; - } - } - if ( ! found ) { - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "The attribute %s is not referenced by any objectclass.\n", modify_structs->check_list[i].name); + if (attr == NULL) { /* not found */ + ldb_debug(module->ldb, LDB_DEBUG_ERROR, + "The attribute %s is not referenced by any objectclass.\n", + modify_structs->check_list[i].name); + data->error_string = "Objectclass violation, an invalid attribute name was found"; talloc_free(entry_structs); return -1; } + + modify_structs->check_list[i].flags |= SCHEMA_FLAG_CHECKED; + } } @@ -671,7 +657,10 @@ struct ldb_module *schema_module_init(struct ldb_context *ldb, const char *optio } data = talloc(ctx, struct private_data); - SCHEMA_TALLOC_CHECK(ctx, data, NULL); + if (data == NULL) { + talloc_free(ctx); + return NULL; + } data->error_string = NULL; ctx->private_data = data; -- cgit From 23f92c16349a3142012e54afc3854c469f32a165 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 19 Jan 2005 22:26:14 +0000 Subject: r4859: changed a numbe rof things: - Try to no tcopy memory if not necessary - let the searches hang around until we finish the operation - greatly simplify the modify operation still todo: - check attributes syntax - check objectclasses type, we cannot allow to add a new structural objectclass to an exixting entry unless the existing one is a parent - more tests (This used to be commit c6257379e094881987cd11e05502129b2ce1c5a0) --- source4/lib/ldb/modules/schema.c | 394 +++++++++++++++------------------------ 1 file changed, 150 insertions(+), 244 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index b396ae0459..b16849c2fe 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -37,32 +37,39 @@ #include "ldb/include/ldb_private.h" #define SCHEMA_FLAG_RESET 0 -#define SCHEMA_FLAG_MOD_MASK 0x03 -#define SCHEMA_FLAG_MOD_ADD 0x01 -#define SCHEMA_FLAG_MOD_REPLACE 0x02 -#define SCHEMA_FLAG_MOD_DELETE 0x03 -#define SCHEMA_FLAG_AUXCLASS 0x10 -#define SCHEMA_FLAG_CHECKED 0x20 - +#define SCHEMA_FLAG_MOD_MASK 0x003 +#define SCHEMA_FLAG_MOD_ADD 0x001 +#define SCHEMA_FLAG_MOD_REPLACE 0x002 +#define SCHEMA_FLAG_MOD_DELETE 0x003 +#define SCHEMA_FLAG_AUXILIARY 0x010 +#define SCHEMA_FLAG_ABSTRACT 0x020 +#define SCHEMA_FLAG_STRUCTURAL 0x040 +#define SCHEMA_FLAG_CHECKED 0x100 + + +/* TODO: check attributes syntaxes + check there's only one structrual class (or a chain of structural classes) +*/ struct private_data { const char *error_string; }; -struct attribute_list { +struct schema_attribute { int flags; char *name; }; +struct schema_attribute_list { + struct schema_attribute *attr; + int num; +}; + struct schema_structures { - struct attribute_list *check_list; - struct attribute_list *objectclass_list; - struct attribute_list *must; - struct attribute_list *may; - int check_list_num; - int objectclass_list_num; - int must_num; - int may_num; + struct schema_attribute_list entry_attrs; + struct schema_attribute_list objectclasses; + struct schema_attribute_list required_attrs; + struct schema_attribute_list optional_attrs; }; /* This function embedds the knowledge of aliased names. @@ -87,139 +94,114 @@ static int schema_attr_cmp(const char *attr1, const char *attr2) return ret; } -struct attribute_list *schema_find_attribute(struct attribute_list *list, int attr_num, const char *attr_name) +struct schema_attribute *schema_find_attribute(struct schema_attribute_list *list, const char *attr_name) { unsigned int i; - for (i = 0; i < attr_num; i++) { - if (ldb_attr_cmp(list[i].name, attr_name) == 0) { - return &list[i]; + for (i = 0; i < list->num; i++) { + if (ldb_attr_cmp(list->attr[i].name, attr_name) == 0) { + return &(list->attr[i]); } } return NULL; } -/* get objectclasses of dn */ -static int get_object_objectclasses(struct ldb_context *ldb, const char *dn, struct schema_structures *schema_struct) +/* get all the attributes and objectclasses found in msg and put them in schema_structure + attributes go in the entry_attrs structure for later checking + objectclasses go in the objectclasses structure */ +static int get_msg_attributes(struct schema_structures *ss, const struct ldb_message *msg) { - char *filter = talloc_asprintf(schema_struct, "dn=%s", dn); - const char *attrs[] = {"objectClass", NULL}; - struct ldb_message **srch; - int i, j, ret; + int i, j, k, l; - schema_struct->objectclass_list = NULL; - schema_struct->objectclass_list_num = 0; - ret = ldb_search(ldb, NULL, LDB_SCOPE_SUBTREE, filter, attrs, &srch); - if (ret != 1) { - ldb_search_free(ldb, srch); + ss->entry_attrs.attr = talloc_realloc(ss, ss->entry_attrs.attr, + struct schema_attribute, + ss->entry_attrs.num + msg->num_elements); + if (ss->entry_attrs.attr == NULL) { return -1; } - for (i = 0; i < (*srch)->num_elements; i++) { - schema_struct->objectclass_list_num = (*srch)->elements[i].num_values; - schema_struct->objectclass_list = talloc_array(schema_struct, - struct attribute_list, - schema_struct->objectclass_list_num); - if (schema_struct->objectclass_list == NULL) { - ldb_search_free(ldb, srch); - return -1; - } - for (j = 0; j < schema_struct->objectclass_list_num; j++) { - schema_struct->objectclass_list[j].name = talloc_strndup(schema_struct->objectclass_list, - (*srch)->elements[i].values[j].data, - (*srch)->elements[i].values[j].length); - if (schema_struct->objectclass_list[j].name == NULL) { - ldb_search_free(ldb, srch); + for (i = 0, j = ss->entry_attrs.num; i < msg->num_elements; i++) { + + if (schema_attr_cmp(msg->elements[i].name, "objectclass") == 0) { + + ss->objectclasses.attr = talloc_realloc(ss, ss->objectclasses.attr, + struct schema_attribute, + ss->objectclasses.num + msg->elements[i].num_values); + if (ss->objectclasses.attr == NULL) { return -1; } - schema_struct->objectclass_list[j].flags = SCHEMA_FLAG_RESET; + + for (k = 0, l = ss->objectclasses.num; k < msg->elements[i].num_values; k++) { + ss->objectclasses.attr[l].name = msg->elements[i].values[k].data; + ss->objectclasses.attr[l].flags = msg->elements[i].flags; + l++; + } + ss->objectclasses.num += msg->elements[i].num_values; } + + ss->entry_attrs.attr[j].flags = msg->elements[i].flags; + ss->entry_attrs.attr[j].name = talloc_reference(ss->entry_attrs.attr, + msg->elements[i].name); + if (ss->entry_attrs.attr[j].name == NULL) { + return -1; + } + j++; } - ldb_search_free(ldb, srch); + ss->entry_attrs.num += msg->num_elements; return 0; } -/* get all the attributes and objectclasses found in msg and put them in schema_structure - attributes go in the check_list structure for later checking - objectclasses go in the objectclass_list structure */ -static int get_check_list(struct ldb_module *module, struct schema_structures *schema_struct, const struct ldb_message *msg) +static int get_entry_attributes(struct ldb_context *ldb, const char *dn, struct schema_structures *ss) { - int i, j, k; - - schema_struct->objectclass_list = NULL; - schema_struct->objectclass_list_num = 0; - schema_struct->check_list_num = msg->num_elements; - schema_struct->check_list = talloc_array(schema_struct, - struct attribute_list, - schema_struct->check_list_num); - if (schema_struct->check_list == NULL) { - return -1; + char *filter = talloc_asprintf(ss, "dn=%s", dn); + struct ldb_message **srch; + int ret; + + ret = ldb_search(ldb, NULL, LDB_SCOPE_SUBTREE, filter, NULL, &srch); + if (ret != 1) { + return ret; } - for (i = 0, j = 0; i < msg->num_elements; i++) { - if (schema_attr_cmp(msg->elements[i].name, "objectclass") == 0) { - schema_struct->objectclass_list_num = msg->elements[i].num_values; - schema_struct->objectclass_list = talloc_array(schema_struct, - struct attribute_list, - schema_struct->objectclass_list_num); - if (schema_struct->objectclass_list == NULL) { - return -1; - } - for (k = 0; k < schema_struct->objectclass_list_num; k++) { - schema_struct->objectclass_list[k].name = talloc_strndup(schema_struct->objectclass_list, - msg->elements[i].values[k].data, - msg->elements[i].values[k].length); - if (schema_struct->objectclass_list[k].name == NULL) { - return -1; - } - schema_struct->objectclass_list[k].flags = msg->elements[i].flags; - } - } + talloc_steal(ss, srch); - schema_struct->check_list[j].flags = msg->elements[i].flags; - schema_struct->check_list[j].name = talloc_strdup(schema_struct->check_list, - msg->elements[i].name); - if (schema_struct->check_list[j].name == NULL) { - return -1; - } - j++; + ret = get_msg_attributes(ss, *srch); + if (ret != 0) { + ldb_search_free(ldb, srch); + return ret; } return 0; } -/* add all attributes in el avoiding duplicates in attribute_list */ -static int add_attribute_uniq(struct attribute_list **list, int *list_num, int flags, struct ldb_message_element *el, void *mem_ctx) +/* add all attributes in el avoiding duplicates in schema_attribute_list */ +static int add_attribute_uniq(void *mem_ctx, struct schema_attribute_list *list, int flags, struct ldb_message_element *el) { int i, j, vals; vals = el->num_values; - *list = talloc_realloc(mem_ctx, *list, struct attribute_list, *list_num + vals); - if (list == 0) { + list->attr = talloc_realloc(mem_ctx, list->attr, struct schema_attribute, list->num + vals); + if (list->attr == NULL) { return -1; } for (i = 0, j = 0; i < vals; i++) { int c, found, len; found = 0; - for (c = 0; c < *list_num; c++) { - len = strlen((*list)[c].name); + for (c = 0; c < list->num; c++) { + len = strlen(list->attr[c].name); if (len == el->values[i].length) { - if (strncasecmp((*list)[c].name, el->values[i].data, len) == 0) { + if (schema_attr_cmp(list->attr[c].name, el->values[i].data) == 0) { found = 1; break; } } } if (!found) { - (*list)[j + *list_num].name = talloc_strndup(*list, el->values[i].data, el->values[i].length); - if ((*list)[j + *list_num].name == 0) { - return -1; - } - (*list)[j + *list_num].flags = flags; + list->attr[j + list->num].name = el->values[i].data; + list->attr[j + list->num].flags = flags; j++; } } - *list_num += j; + list->num += j; return 0; } @@ -227,52 +209,52 @@ static int add_attribute_uniq(struct attribute_list **list, int *list_num, int f /* we need to get all attributes referenced by the entry objectclasses, recursively get parent objectlasses attributes */ -static int get_attr_list_recursive(struct ldb_module *module, struct ldb_context *ldb, struct schema_structures *schema_struct) +static int get_attr_list_recursive(struct ldb_module *module, struct schema_structures *schema_struct) { struct private_data *data = (struct private_data *)module->private_data; struct ldb_message **srch; int i, j; int ret; - schema_struct->must = NULL; - schema_struct->may = NULL; - schema_struct->must_num = 0; - schema_struct->may_num = 0; - for (i = 0; i < schema_struct->objectclass_list_num; i++) { + for (i = 0; i < schema_struct->objectclasses.num; i++) { char *filter; - if ((schema_struct->objectclass_list[i].flags & SCHEMA_FLAG_MOD_MASK) == SCHEMA_FLAG_MOD_DELETE) { + if ((schema_struct->objectclasses.attr[i].flags & SCHEMA_FLAG_MOD_MASK) == SCHEMA_FLAG_MOD_DELETE) { continue; } - filter = talloc_asprintf(schema_struct, "lDAPDisplayName=%s", schema_struct->objectclass_list[i].name); + filter = talloc_asprintf(schema_struct, "lDAPDisplayName=%s", schema_struct->objectclasses.attr[i].name); if (filter == NULL) { return -1; } - ret = ldb_search(ldb, NULL, LDB_SCOPE_SUBTREE, filter, NULL, &srch); + ret = ldb_search(module->ldb, NULL, LDB_SCOPE_SUBTREE, filter, NULL, &srch); + if (ret != 1) { + return ret; + } + talloc_steal(schema_struct, srch); if (ret <= 0) { /* Schema DB Error: Error occurred retrieving Object Class Description */ - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Error retrieving Objectclass %s.\n", schema_struct->objectclass_list[i].name); + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Error retrieving Objectclass %s.\n", schema_struct->objectclasses.attr[i].name); data->error_string = "Internal error. Error retrieving schema objectclass"; return -1; } if (ret > 1) { /* Schema DB Error: Too Many Records */ - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Too many records found retrieving Objectclass %s.\n", schema_struct->objectclass_list[i].name); + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Too many records found retrieving Objectclass %s.\n", schema_struct->objectclasses.attr[i].name); data->error_string = "Internal error. Too many records searching for schema objectclass"; return -1; } /* Add inherited classes eliminating duplicates */ - /* fill in required and optional attribute lists */ + /* fill in required_attrs and optional_attrs attribute lists */ for (j = 0; j < (*srch)->num_elements; j++) { int is_aux, is_class; is_aux = 0; is_class = 0; if (schema_attr_cmp((*srch)->elements[j].name, "systemAuxiliaryclass") == 0) { - is_aux = SCHEMA_FLAG_AUXCLASS; + is_aux = SCHEMA_FLAG_AUXILIARY; is_class = 1; } if (schema_attr_cmp((*srch)->elements[j].name, "subClassOf") == 0) { @@ -280,22 +262,20 @@ static int get_attr_list_recursive(struct ldb_module *module, struct ldb_context } if (is_class) { - if (add_attribute_uniq(&schema_struct->objectclass_list, - &schema_struct->objectclass_list_num, + if (add_attribute_uniq(schema_struct, + &schema_struct->objectclasses, is_aux, - &(*srch)->elements[j], - schema_struct) != 0) { + &(*srch)->elements[j]) != 0) { return -1; } } else { if (schema_attr_cmp((*srch)->elements[j].name, "mustContain") == 0 || schema_attr_cmp((*srch)->elements[j].name, "SystemMustContain") == 0) { - if (add_attribute_uniq(&schema_struct->must, - &schema_struct->must_num, + if (add_attribute_uniq(schema_struct, + &schema_struct->required_attrs, SCHEMA_FLAG_RESET, - &(*srch)->elements[j], - schema_struct) != 0) { + &(*srch)->elements[j]) != 0) { return -1; } } @@ -303,18 +283,15 @@ static int get_attr_list_recursive(struct ldb_module *module, struct ldb_context if (schema_attr_cmp((*srch)->elements[j].name, "mayContain") == 0 || schema_attr_cmp((*srch)->elements[j].name, "SystemMayContain") == 0) { - if (add_attribute_uniq(&schema_struct->may, - &schema_struct->may_num, + if (add_attribute_uniq(schema_struct, + &schema_struct->optional_attrs, SCHEMA_FLAG_RESET, - &(*srch)->elements[j], - schema_struct) != 0) { + &(*srch)->elements[j]) != 0) { return -1; } } } } - - ldb_search_free(ldb, srch); } return 0; @@ -349,9 +326,9 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message int ret; /* First implementation: - Build up a list of required and optional attributes from each objectclass - Check all the required attributes are present and all the other attributes - are optional attributes + Build up a list of required_attrs and optional_attrs attributes from each objectclass + Check all the required_attrs attributes are present and all the other attributes + are optional_attrs attributes Throw an error in case a check fail Free all structures and commit the change */ @@ -360,36 +337,34 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message return ldb_next_add_record(module, msg); } - entry_structs = talloc(module, struct schema_structures); + entry_structs = talloc_zero(module, struct schema_structures); if (!entry_structs) { return -1; } - ret = get_check_list(module, entry_structs, msg); + ret = get_msg_attributes(entry_structs, msg); if (ret != 0) { talloc_free(entry_structs); return ret; } - /* find all other objectclasses recursively */ - ret = get_attr_list_recursive(module, module->ldb, entry_structs); + ret = get_attr_list_recursive(module, entry_structs); if (ret != 0) { talloc_free(entry_structs); return ret; } - /* now check all required attributes are present */ - for (i = 0; i < entry_structs->must_num; i++) { - struct attribute_list *attr; + /* now check all required_attrs attributes are present */ + for (i = 0; i < entry_structs->required_attrs.num; i++) { + struct schema_attribute *attr; - attr = schema_find_attribute(entry_structs->check_list, - entry_structs->check_list_num, - entry_structs->must[i].name); + attr = schema_find_attribute(&entry_structs->entry_attrs, + entry_structs->required_attrs.attr[i].name); if (attr == NULL) { /* not found */ ldb_debug(module->ldb, LDB_DEBUG_ERROR, - "The required attribute %s is missing.\n", - entry_structs->must[i].name); + "The required_attrs attribute %s is missing.\n", + entry_structs->required_attrs.attr[i].name); data->error_string = "Objectclass violation, a required attribute is missing"; talloc_free(entry_structs); @@ -400,20 +375,19 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message attr->flags = SCHEMA_FLAG_CHECKED; } - /* now check all others atribs are at least optional */ - for (i = 0; i < entry_structs->check_list_num; i++) { + /* now check all others atribs are at least optional_attrs */ + for (i = 0; i < entry_structs->entry_attrs.num; i++) { - if (entry_structs->check_list[i].flags != SCHEMA_FLAG_CHECKED) { - struct attribute_list *attr; + if (entry_structs->entry_attrs.attr[i].flags != SCHEMA_FLAG_CHECKED) { + struct schema_attribute *attr; - attr = schema_find_attribute(entry_structs->may, - entry_structs->may_num, - entry_structs->check_list[i].name); + attr = schema_find_attribute(&entry_structs->optional_attrs, + entry_structs->entry_attrs.attr[i].name); if (attr == NULL) { /* not found */ ldb_debug(module->ldb, LDB_DEBUG_ERROR, "The attribute %s is not referenced by any objectclass.\n", - entry_structs->check_list[i].name); + entry_structs->entry_attrs.attr[i].name); data->error_string = "Objectclass violation, an invalid attribute name was found"; talloc_free(entry_structs); @@ -431,17 +405,17 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message static int schema_modify_record(struct ldb_module *module, const struct ldb_message *msg) { struct private_data *data = (struct private_data *)module->private_data; - struct schema_structures *entry_structs, *modify_structs; + struct schema_structures *entry_structs; unsigned int i; int ret; /* First implementation: Retrieve the ldap entry and get the objectclasses, add msg contained objectclasses if any. - Build up a list of required and optional attributes from each objectclass - Check all required one for the defined objectclass and all its parent + Build up a list of required_attrs and optional_attrs attributes from each objectclass + Check all required_attrs one for the defined objectclass and all its parent objectclasses. - Check all other the attributes are optional or required. + Check all other the attributes are optional_attrs or required_attrs. Throw an error in case a check fail. Free all structures and commit the change. */ @@ -456,133 +430,65 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess return -1; } - /* allocate modification entry structs */ - modify_structs = talloc_zero(entry_structs, struct schema_structures); - if (!modify_structs) { - talloc_free(entry_structs); - return -1; - } - - /* get list of values to modify */ - ret = get_check_list(module, modify_structs, msg); - if (ret != 0) { - talloc_free(entry_structs); - return ret; - } - - /* find all modify objectclasses recursively if any objectclass is being added */ - ret = get_attr_list_recursive(module, module->ldb, modify_structs); + /* now search for the stored entry objectclasses and attributes*/ + ret = get_entry_attributes(module->ldb, msg->dn, entry_structs); if (ret != 0) { talloc_free(entry_structs); return ret; } - /* now search for the original object objectclasses */ - ret = get_object_objectclasses(module->ldb, msg->dn, entry_structs); + /* get list of values to modify */ + ret = get_msg_attributes(entry_structs, msg); if (ret != 0) { talloc_free(entry_structs); return ret; } - /* find all other objectclasses recursively */ - ret = get_attr_list_recursive(module, module->ldb, entry_structs); + ret = get_attr_list_recursive(module, entry_structs); if (ret != 0) { talloc_free(entry_structs); return ret; } - /* now check all entries are present either as required or optional atributes of entry objectclasses */ - /* if they are required and we are going to delete them then throw an error */ - /* just mark them if being proved valid attribs */ - for (i = 0; i < modify_structs->check_list_num; i++) { - struct attribute_list *attr; + /* now check all required_attrs attributes are present */ + for (i = 0; i < entry_structs->required_attrs.num; i++) { + struct schema_attribute *attr; - attr = schema_find_attribute(entry_structs->must, - entry_structs->must_num, - modify_structs->check_list[i].name); + attr = schema_find_attribute(&entry_structs->entry_attrs, + entry_structs->required_attrs.attr[i].name); if (attr == NULL) { /* not found */ - - attr = schema_find_attribute(entry_structs->may, - entry_structs->may_num, - modify_structs->check_list[i].name); - - if (attr != NULL) { /* found*/ - modify_structs->check_list[i].flags |= SCHEMA_FLAG_CHECKED; - } - - break; /* not found, go on */ - } - - if ((modify_structs->check_list[i].flags & SCHEMA_FLAG_MOD_MASK) == SCHEMA_FLAG_MOD_DELETE) { ldb_debug(module->ldb, LDB_DEBUG_ERROR, - "Trying to delete the required attribute %s.\n", - modify_structs->check_list[i].name); - - data->error_string = "Objectclass violation: trying to delete a required attribute"; - talloc_free(entry_structs); - return -1; - } - - modify_structs->check_list[i].flags |= SCHEMA_FLAG_CHECKED; - } - - /* now check all new objectclasses required attributes are present */ - for (i = 0; i < modify_structs->must_num; i++) { - struct attribute_list *attr; - - attr = schema_find_attribute(modify_structs->check_list, - modify_structs->check_list_num, - modify_structs->must[i].name); - - - if (attr == NULL) { /* not found */ - ldb_debug(module->ldb, LDB_DEBUG_ERROR, - "The required attribute %s is missing.\n", - modify_structs->must[i].name); + "The required_attrs attribute %s is missing.\n", + entry_structs->required_attrs.attr[i].name); data->error_string = "Objectclass violation, a required attribute is missing"; talloc_free(entry_structs); return -1; } - if ((modify_structs->check_list[i].flags & SCHEMA_FLAG_MOD_MASK) == SCHEMA_FLAG_MOD_DELETE) { - ldb_debug(module->ldb, LDB_DEBUG_ERROR, - "Trying to delete the required attribute %s.\n", - modify_structs->must[i].name); - - data->error_string = "Objectclass violation: trying to delete a required attribute"; - talloc_free(entry_structs); - return -1; - } - - attr->flags |= SCHEMA_FLAG_CHECKED; + /* mark the attribute as checked */ + attr->flags = SCHEMA_FLAG_CHECKED; } - /* now check all others attributes are at least optional */ - for (i = 0; i < modify_structs->check_list_num; i++) { - - if ((modify_structs->check_list[i].flags & SCHEMA_FLAG_CHECKED) == 0 && - (modify_structs->check_list[i].flags & SCHEMA_FLAG_MOD_MASK) != SCHEMA_FLAG_MOD_DELETE) { - struct attribute_list *attr; + /* now check all others atribs are at least optional_attrs */ + for (i = 0; i < entry_structs->entry_attrs.num; i++) { - attr = schema_find_attribute(modify_structs->may, - modify_structs->may_num, - modify_structs->check_list[i].name); + if (entry_structs->entry_attrs.attr[i].flags != SCHEMA_FLAG_CHECKED) { + struct schema_attribute *attr; + attr = schema_find_attribute(&entry_structs->optional_attrs, + entry_structs->entry_attrs.attr[i].name); if (attr == NULL) { /* not found */ ldb_debug(module->ldb, LDB_DEBUG_ERROR, "The attribute %s is not referenced by any objectclass.\n", - modify_structs->check_list[i].name); + entry_structs->entry_attrs.attr[i].name); data->error_string = "Objectclass violation, an invalid attribute name was found"; talloc_free(entry_structs); return -1; } - - modify_structs->check_list[i].flags |= SCHEMA_FLAG_CHECKED; - } } -- cgit From bc2ae4e4cd96311a028486cac78960142e9b41c5 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 19 Jan 2005 22:56:14 +0000 Subject: r4862: - better structure schema tests - fix check for deletion of required attributes on modify removed by mistake with the previous commits (This used to be commit 0315159daf157b64ef3452372dd74199600e24b8) --- source4/lib/ldb/modules/schema.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index b16849c2fe..86dc617d99 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -371,6 +371,18 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message return -1; } + /* check we are not trying to delete a required attribute */ + /* TODO: consider multivalued attrs */ + if ((attr->flags & SCHEMA_FLAG_MOD_DELETE) != 0) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, + "Trying to delete the required attribute %s.\n", + attr->name); + + data->error_string = "Objectclass violation, a required attribute cannot be removed"; + talloc_free(entry_structs); + return -1; + } + /* mark the attribute as checked */ attr->flags = SCHEMA_FLAG_CHECKED; } @@ -413,9 +425,7 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess Retrieve the ldap entry and get the objectclasses, add msg contained objectclasses if any. Build up a list of required_attrs and optional_attrs attributes from each objectclass - Check all required_attrs one for the defined objectclass and all its parent - objectclasses. - Check all other the attributes are optional_attrs or required_attrs. + Check all the attributes are optional_attrs or required_attrs. Throw an error in case a check fail. Free all structures and commit the change. */ -- cgit From b808d49cd5e72c5c3560a334fdfefe40f3da721f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 20 Jan 2005 00:46:04 +0000 Subject: r4863: schema_find_attribute() should be static (This used to be commit e7262dccce1ccc563fad48023c733c1d13929b4b) --- source4/lib/ldb/modules/schema.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index 86dc617d99..2921bdc68b 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -94,7 +94,7 @@ static int schema_attr_cmp(const char *attr1, const char *attr2) return ret; } -struct schema_attribute *schema_find_attribute(struct schema_attribute_list *list, const char *attr_name) +static struct schema_attribute *schema_find_attribute(struct schema_attribute_list *list, const char *attr_name) { unsigned int i; for (i = 0; i < list->num; i++) { -- cgit From b1b14817eaa6e6579596d54166e17bc8d5605c01 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 27 Feb 2005 11:35:47 +0000 Subject: r5585: LDB interfaces change: changes: - ldb_wrap disappears from code and become a private structure of db_wrap.c thanks to our move to talloc in ldb code, we do not need to expose it anymore - removal of ldb_close() function form the code thanks to our move to talloc in ldb code, we do not need it anymore use talloc_free() to close and free an ldb database - some minor updates to ldb modules code to cope with the change and fix some bugs I found out during the process (This used to be commit d58be9e74b786a11a57e89df36081d55730dfe0a) --- source4/lib/ldb/modules/schema.c | 40 ++++++----- source4/lib/ldb/modules/skel.c | 16 +++-- source4/lib/ldb/modules/timestamps.c | 134 ++++++++++++++++++----------------- 3 files changed, 100 insertions(+), 90 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index 2921bdc68b..ef766b55ee 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -297,12 +297,6 @@ static int get_attr_list_recursive(struct ldb_module *module, struct schema_stru return 0; } -/* close */ -static int schema_close(struct ldb_module *module) -{ - return ldb_next_close(module); -} - /* search */ static int schema_search(struct ldb_module *module, const char *base, enum ldb_scope scope, const char *expression, @@ -371,18 +365,6 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message return -1; } - /* check we are not trying to delete a required attribute */ - /* TODO: consider multivalued attrs */ - if ((attr->flags & SCHEMA_FLAG_MOD_DELETE) != 0) { - ldb_debug(module->ldb, LDB_DEBUG_ERROR, - "Trying to delete the required attribute %s.\n", - attr->name); - - data->error_string = "Objectclass violation, a required attribute cannot be removed"; - talloc_free(entry_structs); - return -1; - } - /* mark the attribute as checked */ attr->flags = SCHEMA_FLAG_CHECKED; } @@ -477,6 +459,18 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess return -1; } + /* check we are not trying to delete a required attribute */ + /* TODO: consider multivalued attrs */ + if ((attr->flags & SCHEMA_FLAG_MOD_DELETE) != 0) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, + "Trying to delete the required attribute %s.\n", + attr->name); + + data->error_string = "Objectclass violation, a required attribute cannot be removed"; + talloc_free(entry_structs); + return -1; + } + /* mark the attribute as checked */ attr->flags = SCHEMA_FLAG_CHECKED; } @@ -544,9 +538,15 @@ static const char *schema_errstring(struct ldb_module *module) return ldb_next_errstring(module); } +static int schema_destructor(void *module_ctx) +{ + struct ldb_module *ctx = module_ctx; + /* put your clean-up functions here */ + return 0; +} + static const struct ldb_module_ops schema_ops = { "schema", - schema_close, schema_search, schema_search_free, schema_add_record, @@ -584,5 +584,7 @@ struct ldb_module *schema_module_init(struct ldb_context *ldb, const char *optio ctx->prev = ctx->next = NULL; ctx->ops = &schema_ops; + talloc_set_destructor (ctx, schema_destructor); + return ctx; } diff --git a/source4/lib/ldb/modules/skel.c b/source4/lib/ldb/modules/skel.c index afafe1bbd9..882a776819 100644 --- a/source4/lib/ldb/modules/skel.c +++ b/source4/lib/ldb/modules/skel.c @@ -36,12 +36,6 @@ #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" -/* close */ -static int skel_close(struct ldb_module *module) -{ - return ldb_next_close(module); -} - /* search */ static int skel_search(struct ldb_module *module, const char *base, enum ldb_scope scope, const char *expression, @@ -98,9 +92,15 @@ static const char *skel_errstring(struct ldb_module *module) return ldb_next_errstring(module); } +static int skel_destructor(void *module_ctx) +{ + struct ldb_module *ctx = module_ctx; + /* put your clean-up functions here */ + return 0; +} + static const struct ldb_module_ops skel_ops = { "skel", - skel_close, skel_search, skel_search_free, skel_add_record, @@ -129,5 +129,7 @@ struct ldb_module *skel_plugin_init(struct ldb_context *ldb, const char *options ctx->private_data = NULL; ctx->ops = &skel_ops; + talloc_set_destructor (ctx, skel_destructor); + return ctx; } diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index 1deeeb218b..dec564bf66 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -41,12 +41,6 @@ struct private_data { const char *error_string; }; -static int timestamps_close(struct ldb_module *module) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_close\n"); - return ldb_next_close(module); -} - static int timestamps_search(struct ldb_module *module, const char *base, enum ldb_scope scope, const char *expression, const char * const *attrs, struct ldb_message ***res) @@ -106,41 +100,43 @@ static int timestamps_add_record(struct ldb_module *module, const struct ldb_mes ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_add_record\n"); - if (msg->dn[0] != '@') { /* do not manipulate our control entries */ - timeval = time(NULL); - tm = gmtime(&timeval); - if (!tm) { - return -1; - } + if (msg->dn[0] == '@') { /* do not manipulate our control entries */ + return ldb_next_add_record(module, msg); + } - msg2 = talloc(module, struct ldb_message); - if (!msg2) { - return -1; - } + timeval = time(NULL); + tm = gmtime(&timeval); + if (!tm) { + return -1; + } - /* formatted like: 20040408072012.0Z */ - timestr = talloc_asprintf(msg2, "%04u%02u%02u%02u%02u%02u.0Z", - tm->tm_year+1900, tm->tm_mon+1, - tm->tm_mday, tm->tm_hour, tm->tm_min, - tm->tm_sec); - if (!timestr) { - return -1; - } + msg2 = talloc(module, struct ldb_message); + if (!msg2) { + return -1; + } - msg2->dn = msg->dn; - msg2->num_elements = msg->num_elements; - msg2->private_data = msg->private_data; - msg2->elements = talloc_array(msg2, struct ldb_message_element, msg2->num_elements); - for (i = 0; i < msg2->num_elements; i++) { - msg2->elements[i] = msg->elements[i]; - } + /* formatted like: 20040408072012.0Z */ + timestr = talloc_asprintf(msg2, "%04u%02u%02u%02u%02u%02u.0Z", + tm->tm_year+1900, tm->tm_mon+1, + tm->tm_mday, tm->tm_hour, tm->tm_min, + tm->tm_sec); + if (!timestr) { + return -1; + } - add_time_element(module, msg2, "createTimestamp", timestr, LDB_FLAG_MOD_ADD); - add_time_element(module, msg2, "modifyTimestamp", timestr, LDB_FLAG_MOD_ADD); - add_time_element(module, msg2, "whenCreated", timestr, LDB_FLAG_MOD_ADD); - add_time_element(module, msg2, "whenChanged", timestr, LDB_FLAG_MOD_ADD); + msg2->dn = msg->dn; + msg2->num_elements = msg->num_elements; + msg2->private_data = msg->private_data; + msg2->elements = talloc_array(msg2, struct ldb_message_element, msg2->num_elements); + for (i = 0; i < msg2->num_elements; i++) { + msg2->elements[i] = msg->elements[i]; } + add_time_element(module, msg2, "createTimestamp", timestr, LDB_FLAG_MOD_ADD); + add_time_element(module, msg2, "modifyTimestamp", timestr, LDB_FLAG_MOD_ADD); + add_time_element(module, msg2, "whenCreated", timestr, LDB_FLAG_MOD_ADD); + add_time_element(module, msg2, "whenChanged", timestr, LDB_FLAG_MOD_ADD); + if (msg2) { ret = ldb_next_add_record(module, msg2); talloc_free(msg2); @@ -162,40 +158,42 @@ static int timestamps_modify_record(struct ldb_module *module, const struct ldb_ ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_modify_record\n"); - if (msg->dn[0] != '@') { /* do not manipulate our control entries */ - timeval = time(NULL); - tm = gmtime(&timeval); - if (!tm) { - return -1; - } + if (msg->dn[0] == '@') { /* do not manipulate our control entries */ + return ldb_next_modify_record(module, msg); + } - msg2 = talloc(module, struct ldb_message); - if (!msg2) { - return -1; - } + timeval = time(NULL); + tm = gmtime(&timeval); + if (!tm) { + return -1; + } - /* formatted like: 20040408072012.0Z */ - timestr = talloc_asprintf(msg2, - "%04u%02u%02u%02u%02u%02u.0Z", - tm->tm_year+1900, tm->tm_mon+1, - tm->tm_mday, tm->tm_hour, tm->tm_min, - tm->tm_sec); - if (!timestr) { - return -1; - } + msg2 = talloc(module, struct ldb_message); + if (!msg2) { + return -1; + } - msg2->dn = msg->dn; - msg2->num_elements = msg->num_elements; - msg2->private_data = msg->private_data; - msg2->elements = talloc_array(msg2, struct ldb_message_element, msg2->num_elements); - for (i = 0; i < msg2->num_elements; i++) { - msg2->elements[i] = msg->elements[i]; - } + /* formatted like: 20040408072012.0Z */ + timestr = talloc_asprintf(msg2, + "%04u%02u%02u%02u%02u%02u.0Z", + tm->tm_year+1900, tm->tm_mon+1, + tm->tm_mday, tm->tm_hour, tm->tm_min, + tm->tm_sec); + if (!timestr) { + return -1; + } - add_time_element(module, msg2, "modifyTimestamp", timestr, LDB_FLAG_MOD_REPLACE); - add_time_element(module, msg2, "whenChanged", timestr, LDB_FLAG_MOD_REPLACE); + msg2->dn = msg->dn; + msg2->num_elements = msg->num_elements; + msg2->private_data = msg->private_data; + msg2->elements = talloc_array(msg2, struct ldb_message_element, msg2->num_elements); + for (i = 0; i < msg2->num_elements; i++) { + msg2->elements[i] = msg->elements[i]; } + add_time_element(module, msg2, "modifyTimestamp", timestr, LDB_FLAG_MOD_REPLACE); + add_time_element(module, msg2, "whenChanged", timestr, LDB_FLAG_MOD_REPLACE); + if (msg2) { ret = ldb_next_modify_record(module, msg2); talloc_free(msg2); @@ -247,9 +245,15 @@ static const char *timestamps_errstring(struct ldb_module *module) return ldb_next_errstring(module); } +static int timestamps_destructor(void *module_ctx) +{ + struct ldb_module *ctx = module_ctx; + /* put your clean-up functions here */ + return 0; +} + static const struct ldb_module_ops timestamps_ops = { "timestamps", - timestamps_close, timestamps_search, timestamps_search_free, timestamps_add_record, @@ -288,5 +292,7 @@ struct ldb_module *timestamps_module_init(struct ldb_context *ldb, const char *o ctx->prev = ctx->next = NULL; ctx->ops = ×tamps_ops; + talloc_set_destructor (ctx, timestamps_destructor); + return ctx; } -- cgit From 0b4c61a05a9a070db489986fda5c57697cfd092a Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 6 Mar 2005 15:33:40 +0000 Subject: r5670: simplify and clarify ldb_modules.c code rectify the test schema correct a glitch in schema module (This used to be commit 0579b5f7adfe160be8ecf124934b6593a02ed06f) --- source4/lib/ldb/modules/schema.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index ef766b55ee..1b08db6170 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -108,7 +108,7 @@ static struct schema_attribute *schema_find_attribute(struct schema_attribute_li /* get all the attributes and objectclasses found in msg and put them in schema_structure attributes go in the entry_attrs structure for later checking objectclasses go in the objectclasses structure */ -static int get_msg_attributes(struct schema_structures *ss, const struct ldb_message *msg) +static int get_msg_attributes(struct schema_structures *ss, const struct ldb_message *msg, int flag_mask) { int i, j, k, l; @@ -132,13 +132,13 @@ static int get_msg_attributes(struct schema_structures *ss, const struct ldb_mes for (k = 0, l = ss->objectclasses.num; k < msg->elements[i].num_values; k++) { ss->objectclasses.attr[l].name = msg->elements[i].values[k].data; - ss->objectclasses.attr[l].flags = msg->elements[i].flags; + ss->objectclasses.attr[l].flags = msg->elements[i].flags & flag_mask; l++; } ss->objectclasses.num += msg->elements[i].num_values; } - ss->entry_attrs.attr[j].flags = msg->elements[i].flags; + ss->entry_attrs.attr[j].flags = msg->elements[i].flags & flag_mask; ss->entry_attrs.attr[j].name = talloc_reference(ss->entry_attrs.attr, msg->elements[i].name); if (ss->entry_attrs.attr[j].name == NULL) { @@ -163,7 +163,8 @@ static int get_entry_attributes(struct ldb_context *ldb, const char *dn, struct } talloc_steal(ss, srch); - ret = get_msg_attributes(ss, *srch); + /* set flags to 0 as flags on search have undefined values */ + ret = get_msg_attributes(ss, *srch, 0); if (ret != 0) { ldb_search_free(ldb, srch); return ret; @@ -336,7 +337,7 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message return -1; } - ret = get_msg_attributes(entry_structs, msg); + ret = get_msg_attributes(entry_structs, msg, SCHEMA_FLAG_MOD_MASK); if (ret != 0) { talloc_free(entry_structs); return ret; @@ -430,7 +431,7 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess } /* get list of values to modify */ - ret = get_msg_attributes(entry_structs, msg); + ret = get_msg_attributes(entry_structs, msg, SCHEMA_FLAG_MOD_MASK); if (ret != 0) { talloc_free(entry_structs); return ret; -- cgit From f58143b0256d470e17f2c0a09a7c1a352855d385 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sat, 12 Mar 2005 09:55:08 +0000 Subject: r5769: Fix unused variable warning. (This used to be commit 80dfac3640443a41f7e45e9164ca1a6749494011) --- source4/lib/ldb/modules/timestamps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index dec564bf66..c472fc3c55 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -247,7 +247,7 @@ static const char *timestamps_errstring(struct ldb_module *module) static int timestamps_destructor(void *module_ctx) { - struct ldb_module *ctx = module_ctx; + /* struct ldb_module *ctx = module_ctx; */ /* put your clean-up functions here */ return 0; } -- cgit From b9456e9d67e794d37b395bcb01a758ef15e20123 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 17 Apr 2005 00:07:40 +0000 Subject: r6360: Quieten unused variable warning. (This used to be commit 5a598f5da17b60ad52b2ae9d8e4484286e492a1f) --- source4/lib/ldb/modules/schema.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index 1b08db6170..4502bba9ed 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -541,7 +541,7 @@ static const char *schema_errstring(struct ldb_module *module) static int schema_destructor(void *module_ctx) { - struct ldb_module *ctx = module_ctx; +/* struct ldb_module *ctx = module_ctx; */ /* put your clean-up functions here */ return 0; } -- cgit From fe4d985b6f3d318d9b58a16677be3b4ae34fba15 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 25 Apr 2005 12:46:18 +0000 Subject: r6470: Remove ldb_search_free() it is not needed anymore. Just use talloc_free() to release the memory after an ldb_search(). (This used to be commit 4f0948dab0aa5e8b6a4ce486f3668ca8dfae23db) --- source4/lib/ldb/modules/schema.c | 9 +-------- source4/lib/ldb/modules/skel.c | 7 ------- source4/lib/ldb/modules/timestamps.c | 7 ------- 3 files changed, 1 insertion(+), 22 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index 4502bba9ed..29e5194416 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -166,7 +166,7 @@ static int get_entry_attributes(struct ldb_context *ldb, const char *dn, struct /* set flags to 0 as flags on search have undefined values */ ret = get_msg_attributes(ss, *srch, 0); if (ret != 0) { - ldb_search_free(ldb, srch); + talloc_free(srch); return ret; } @@ -306,12 +306,6 @@ static int schema_search(struct ldb_module *module, const char *base, return ldb_next_search(module, base, scope, expression, attrs, res); } -/* search_free */ -static int schema_search_free(struct ldb_module *module, struct ldb_message **res) -{ - return ldb_next_search_free(module, res); -} - /* add_record */ static int schema_add_record(struct ldb_module *module, const struct ldb_message *msg) { @@ -549,7 +543,6 @@ static int schema_destructor(void *module_ctx) static const struct ldb_module_ops schema_ops = { "schema", schema_search, - schema_search_free, schema_add_record, schema_modify_record, schema_delete_record, diff --git a/source4/lib/ldb/modules/skel.c b/source4/lib/ldb/modules/skel.c index 882a776819..09f2452365 100644 --- a/source4/lib/ldb/modules/skel.c +++ b/source4/lib/ldb/modules/skel.c @@ -44,12 +44,6 @@ static int skel_search(struct ldb_module *module, const char *base, return ldb_next_search(module, base, scope, expression, attrs, res); } -/* search_free */ -static int skel_search_free(struct ldb_module *module, struct ldb_message **res) -{ - return ldb_next_search_free(module, res); -} - /* add_record */ static int skel_add_record(struct ldb_module *module, const struct ldb_message *msg) { @@ -102,7 +96,6 @@ static int skel_destructor(void *module_ctx) static const struct ldb_module_ops skel_ops = { "skel", skel_search, - skel_search_free, skel_add_record, skel_modify_record, skel_delete_record, diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index c472fc3c55..1c01bd14fd 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -49,12 +49,6 @@ static int timestamps_search(struct ldb_module *module, const char *base, return ldb_next_search(module, base, scope, expression, attrs, res); } -static int timestamps_search_free(struct ldb_module *module, struct ldb_message **res) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_search_free\n"); - return ldb_next_search_free(module, res); -} - static int add_time_element(struct ldb_module *module, struct ldb_message *msg, const char *attr_name, const char *time_string, unsigned int flags) { @@ -255,7 +249,6 @@ static int timestamps_destructor(void *module_ctx) static const struct ldb_module_ops timestamps_ops = { "timestamps", timestamps_search, - timestamps_search_free, timestamps_add_record, timestamps_modify_record, timestamps_delete_record, -- cgit From 3d97821243b0d4af866ccc158e0134a49c0e4901 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 22 May 2005 10:27:51 +0000 Subject: r6934: thanks to HotaruT for pointing out skel.c was not in line with the rest of the code (This used to be commit 9f0963c97f94687a1226d224f80b2aac1128d1a0) --- source4/lib/ldb/modules/skel.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/skel.c b/source4/lib/ldb/modules/skel.c index 09f2452365..33e5d53cef 100644 --- a/source4/lib/ldb/modules/skel.c +++ b/source4/lib/ldb/modules/skel.c @@ -36,6 +36,10 @@ #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" +static struct private_data { + const char *error_string; +}; + /* search */ static int skel_search(struct ldb_module *module, const char *base, enum ldb_scope scope, const char *expression, @@ -69,13 +73,13 @@ static int skel_rename_record(struct ldb_module *module, const char *olddn, cons } /* named_lock */ -static const char *skel_named_lock(struct ldb_module *module, const char *lockname) +static int skel_named_lock(struct ldb_module *module, const char *lockname) { return ldb_next_named_lock(module, lockname); } /* named_unlock */ -static const char *skel_named_unlock(struct ldb_module *module, const char *lockname) +static int skel_named_unlock(struct ldb_module *module, const char *lockname) { return ldb_next_named_unlock(module, lockname); } @@ -105,18 +109,28 @@ static const struct ldb_module_ops skel_ops = { skel_errstring }; -#ifdef HAVE_DLOPEN - struct ldb_module *init_module(struct ldb_context *ldb, const char *options[]) +#ifdef HAVE_DLOPEN_DISABLED +struct ldb_module *init_module(struct ldb_context *ldb, const char *options[]) #else -struct ldb_module *skel_plugin_init(struct ldb_context *ldb, const char *options[]) +struct ldb_module *skel_module_init(struct ldb_context *ldb, const char *options[]) #endif { struct ldb_module *ctx; + struct private_data *data; - ctx = (struct ldb_module *)malloc(sizeof(struct ldb_module)); + ctx = talloc(ldb, struct ldb_module); if (!ctx) return NULL; + data = talloc(ctx, struct private_data); + if (data == NULL) { + talloc_free(ctx); + return NULL; + } + + data->error_string = NULL; + ctx->private_data = data; + ctx->ldb = ldb; ctx->prev = ctx->next = NULL; ctx->private_data = NULL; -- cgit From e4553307c1e3e44a7f772818aae18cca0aca92a3 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 22 May 2005 10:40:54 +0000 Subject: r6935: don't do three things at a time :-) (This used to be commit a97eb63c11be6ce2bb94bca61078b303f15c9b9a) --- source4/lib/ldb/modules/skel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/skel.c b/source4/lib/ldb/modules/skel.c index 33e5d53cef..9fb01941c9 100644 --- a/source4/lib/ldb/modules/skel.c +++ b/source4/lib/ldb/modules/skel.c @@ -36,7 +36,8 @@ #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" -static struct private_data { +const struct private_data { + const char *error_string; }; @@ -133,7 +134,6 @@ struct ldb_module *skel_module_init(struct ldb_context *ldb, const char *options ctx->ldb = ldb; ctx->prev = ctx->next = NULL; - ctx->private_data = NULL; ctx->ops = &skel_ops; talloc_set_destructor (ctx, skel_destructor); -- cgit From 4f4b92a6904210a467282a997e81a4e8ab1f415a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 23 May 2005 06:49:17 +0000 Subject: r6937: some minor fixes and updates metze (This used to be commit 03b1ff48f97fa81c515f90a398c6f8cde579cb51) --- source4/lib/ldb/modules/skel.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/skel.c b/source4/lib/ldb/modules/skel.c index 9fb01941c9..505b19a288 100644 --- a/source4/lib/ldb/modules/skel.c +++ b/source4/lib/ldb/modules/skel.c @@ -36,9 +36,9 @@ #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" -const struct private_data { +struct private_data { - const char *error_string; + char *errstring; }; /* search */ @@ -93,21 +93,23 @@ static const char *skel_errstring(struct ldb_module *module) static int skel_destructor(void *module_ctx) { - struct ldb_module *ctx = module_ctx; + struct ldb_module *ctx = talloc_get_type(module_ctx, struct ldb_module); + struct private_data *data = talloc_get_type(ctx->private_data, struct private_data); /* put your clean-up functions here */ + if (data->errstring) talloc_free(data->errstring); return 0; } static const struct ldb_module_ops skel_ops = { - "skel", - skel_search, - skel_add_record, - skel_modify_record, - skel_delete_record, - skel_rename_record, - skel_named_lock, - skel_named_unlock, - skel_errstring + .name = "skel", + .search = skel_search, + .add_record = skel_add_record, + .modify_record = skel_modify_record, + .delete_record = skel_delete_record, + .rename_record = skel_rename_record, + .named_lock = skel_named_lock, + .named_unlock = skel_named_unlock, + .errstring = skel_errstring }; #ifdef HAVE_DLOPEN_DISABLED @@ -129,7 +131,7 @@ struct ldb_module *skel_module_init(struct ldb_context *ldb, const char *options return NULL; } - data->error_string = NULL; + data->errstring = NULL; ctx->private_data = data; ctx->ldb = ldb; -- cgit From 4b0e5bd75373ffa2d847706a71fd0349dfa15e71 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 13 Jun 2005 09:10:17 +0000 Subject: r7527: - added a ldb_search_bytree() interface, which takes a ldb_parse_tree instead of a search expression. This allows our ldap server to pass its ASN.1 parsed search expressions straight to ldb, instead of going via strings. - updated all the ldb modules code to handle the new interface - got rid of the separate ldb_parse.h now that the ldb_parse structures are exposed externally - moved to C99 structure initialisation in ldb - switched ldap server to using ldb_search_bytree() (This used to be commit 96620ab2ee5d440bbbc51c1bc0cad9977770f897) --- source4/lib/ldb/modules/schema.c | 26 +++++++++++++++++--------- source4/lib/ldb/modules/skel.c | 1 + source4/lib/ldb/modules/timestamps.c | 27 ++++++++++++++++++--------- 3 files changed, 36 insertions(+), 18 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index 29e5194416..e11c8b4e4e 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -306,6 +306,13 @@ static int schema_search(struct ldb_module *module, const char *base, return ldb_next_search(module, base, scope, expression, attrs, res); } +static int schema_search_bytree(struct ldb_module *module, const char *base, + enum ldb_scope scope, struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res) +{ + return ldb_next_search_bytree(module, base, scope, tree, attrs, res); +} + /* add_record */ static int schema_add_record(struct ldb_module *module, const struct ldb_message *msg) { @@ -541,15 +548,16 @@ static int schema_destructor(void *module_ctx) } static const struct ldb_module_ops schema_ops = { - "schema", - schema_search, - schema_add_record, - schema_modify_record, - schema_delete_record, - schema_rename_record, - schema_named_lock, - schema_named_unlock, - schema_errstring, + .name = "schema", + .search = schema_search, + .search_bytree = schema_search_bytree, + .add_record = schema_add_record, + .modify_record = schema_modify_record, + .delete_record = schema_delete_record, + .rename_record = schema_rename_record, + .named_lock = schema_named_lock, + .named_unlock = schema_named_unlock, + .errstring = schema_errstring, }; #ifdef HAVE_DLOPEN_DISABLED diff --git a/source4/lib/ldb/modules/skel.c b/source4/lib/ldb/modules/skel.c index 505b19a288..1221ac70f1 100644 --- a/source4/lib/ldb/modules/skel.c +++ b/source4/lib/ldb/modules/skel.c @@ -103,6 +103,7 @@ static int skel_destructor(void *module_ctx) static const struct ldb_module_ops skel_ops = { .name = "skel", .search = skel_search, + .search_bytree = skel_search_bytree, .add_record = skel_add_record, .modify_record = skel_modify_record, .delete_record = skel_delete_record, diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index 1c01bd14fd..c1db85a284 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -49,6 +49,14 @@ static int timestamps_search(struct ldb_module *module, const char *base, return ldb_next_search(module, base, scope, expression, attrs, res); } +static int timestamps_search_bytree(struct ldb_module *module, const char *base, + enum ldb_scope scope, struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_search\n"); + return ldb_next_search_bytree(module, base, scope, tree, attrs, res); +} + static int add_time_element(struct ldb_module *module, struct ldb_message *msg, const char *attr_name, const char *time_string, unsigned int flags) { @@ -247,15 +255,16 @@ static int timestamps_destructor(void *module_ctx) } static const struct ldb_module_ops timestamps_ops = { - "timestamps", - timestamps_search, - timestamps_add_record, - timestamps_modify_record, - timestamps_delete_record, - timestamps_rename_record, - timestamps_lock, - timestamps_unlock, - timestamps_errstring + .name = "timestamps", + .search = timestamps_search, + .search_bytree = timestamps_search_bytree, + .add_record = timestamps_add_record, + .modify_record = timestamps_modify_record, + .delete_record = timestamps_delete_record, + .rename_record = timestamps_rename_record, + .named_lock = timestamps_lock, + .named_unlock = timestamps_unlock, + .errstring = timestamps_errstring }; -- cgit From 24d2107324982d8ad69fb89d13037ba591f49534 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 20 Jul 2005 11:43:23 +0000 Subject: r8650: Use the timestamps and a new objectguid module rather than placing boilerplate attributes in every entry in provision.ldif. The next step will be to use templates. Andrew Bartlett (This used to be commit 940ed9827f5ab83b668a60a2b0110567dd54c3e2) --- source4/lib/ldb/modules/objectguid.c | 220 +++++++++++++++++++++++++++++++++++ 1 file changed, 220 insertions(+) create mode 100644 source4/lib/ldb/modules/objectguid.c (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/objectguid.c b/source4/lib/ldb/modules/objectguid.c new file mode 100644 index 0000000000..0e789c2bda --- /dev/null +++ b/source4/lib/ldb/modules/objectguid.c @@ -0,0 +1,220 @@ +/* + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb objectguid module + * + * Description: add a unique objectGUID onto every new record + * + * Author: Simo Sorce + */ + +#include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" +#include + +struct private_data { + const char *error_string; +}; + +static int objectguid_search(struct ldb_module *module, const char *base, + enum ldb_scope scope, const char *expression, + const char * const *attrs, struct ldb_message ***res) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_search\n"); + return ldb_next_search(module, base, scope, expression, attrs, res); +} + +static int objectguid_search_bytree(struct ldb_module *module, const char *base, + enum ldb_scope scope, struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_search\n"); + return ldb_next_search_bytree(module, base, scope, tree, attrs, res); +} + +static struct ldb_message_element *objectguid_find_attribute(const struct ldb_message *msg, const char *name) +{ + int i; + + for (i = 0; i < msg->num_elements; i++) { + if (ldb_attr_cmp(name, msg->elements[i].name) == 0) { + return &msg->elements[i]; + } + } + + return NULL; +} + +/* add_record: add crateTimestamp/modifyTimestamp attributes */ +static int objectguid_add_record(struct ldb_module *module, const struct ldb_message *msg) +{ + struct ldb_message *msg2; + struct ldb_message_element *attribute; + struct GUID guid; + char *guidstr; + int ret, i; + + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_add_record\n"); + + if (msg->dn[0] == '@') { /* do not manipulate our control entries */ + return ldb_next_add_record(module, msg); + } + + if ((attribute = objectguid_find_attribute(msg, "objectGUID")) != NULL ) { + return ldb_next_add_record(module, msg); + } + + msg2 = talloc(module, struct ldb_message); + if (!msg2) { + return -1; + } + + msg2->dn = msg->dn; + msg2->num_elements = msg->num_elements; + msg2->private_data = msg->private_data; + msg2->elements = talloc_array(msg2, struct ldb_message_element, msg2->num_elements); + for (i = 0; i < msg2->num_elements; i++) { + msg2->elements[i] = msg->elements[i]; + } + + /* a new GUID */ + guid = GUID_random(); + guidstr = GUID_string(msg2, &guid); + if (!guidstr) { + return -1; + } + + if (ldb_msg_add_string(module->ldb, msg2, "objectGUID", guidstr) != 0) { + return -1; + } + + ret = ldb_next_add_record(module, msg2); + talloc_free(msg2); + + return ret; +} + +/* modify_record: change modifyTimestamp as well */ +static int objectguid_modify_record(struct ldb_module *module, const struct ldb_message *msg) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_modify_record\n"); + return ldb_next_modify_record(module, msg); +} + +static int objectguid_delete_record(struct ldb_module *module, const char *dn) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_delete_record\n"); + return ldb_next_delete_record(module, dn); +} + +static int objectguid_rename_record(struct ldb_module *module, const char *olddn, const char *newdn) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_rename_record\n"); + return ldb_next_rename_record(module, olddn, newdn); +} + +static int objectguid_lock(struct ldb_module *module, const char *lockname) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_lock\n"); + return ldb_next_named_lock(module, lockname); +} + +static int objectguid_unlock(struct ldb_module *module, const char *lockname) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_unlock\n"); + return ldb_next_named_unlock(module, lockname); +} + +/* return extended error information */ +static const char *objectguid_errstring(struct ldb_module *module) +{ + struct private_data *data = (struct private_data *)module->private_data; + + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_errstring\n"); + if (data->error_string) { + const char *error; + + error = data->error_string; + data->error_string = NULL; + return error; + } + + return ldb_next_errstring(module); +} + +static int objectguid_destructor(void *module_ctx) +{ + /* struct ldb_module *ctx = module_ctx; */ + /* put your clean-up functions here */ + return 0; +} + +static const struct ldb_module_ops objectguid_ops = { + .name = "objectguid", + .search = objectguid_search, + .search_bytree = objectguid_search_bytree, + .add_record = objectguid_add_record, + .modify_record = objectguid_modify_record, + .delete_record = objectguid_delete_record, + .rename_record = objectguid_rename_record, + .named_lock = objectguid_lock, + .named_unlock = objectguid_unlock, + .errstring = objectguid_errstring +}; + + +/* the init function */ +#ifdef HAVE_DLOPEN_DISABLED + struct ldb_module *init_module(struct ldb_context *ldb, const char *options[]) +#else +struct ldb_module *objectguid_module_init(struct ldb_context *ldb, const char *options[]) +#endif +{ + struct ldb_module *ctx; + struct private_data *data; + + ctx = talloc(ldb, struct ldb_module); + if (!ctx) + return NULL; + + data = talloc(ctx, struct private_data); + if (!data) { + talloc_free(ctx); + return NULL; + } + + data->error_string = NULL; + ctx->private_data = data; + ctx->ldb = ldb; + ctx->prev = ctx->next = NULL; + ctx->ops = &objectguid_ops; + + talloc_set_destructor (ctx, objectguid_destructor); + + return ctx; +} -- cgit From 2a0cf520e3255d8e1bdec1bedd710489619de614 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 21 Jul 2005 07:59:01 +0000 Subject: r8667: Further simply the provision script, by removing the 'name' attribute. This is now calculated on the fly for every add and modify. Andrew Bartlett (This used to be commit ed1f2e029c840d2b3ecb49dbe6e8cd67588eeeed) --- source4/lib/ldb/modules/rdn_name.c | 276 +++++++++++++++++++++++++++++++++++ source4/lib/ldb/modules/timestamps.c | 37 ++--- 2 files changed, 292 insertions(+), 21 deletions(-) create mode 100644 source4/lib/ldb/modules/rdn_name.c (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/rdn_name.c b/source4/lib/ldb/modules/rdn_name.c new file mode 100644 index 0000000000..6a11ab87fe --- /dev/null +++ b/source4/lib/ldb/modules/rdn_name.c @@ -0,0 +1,276 @@ +/* + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb objectguid module + * + * Description: add a unique objectGUID onto every new record + * + * Author: Simo Sorce + */ + +#include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" +#include + +struct private_data { + const char *error_string; +}; + +static int rdn_name_search(struct ldb_module *module, const char *base, + enum ldb_scope scope, const char *expression, + const char * const *attrs, struct ldb_message ***res) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_search\n"); + return ldb_next_search(module, base, scope, expression, attrs, res); +} + +static int rdn_name_search_bytree(struct ldb_module *module, const char *base, + enum ldb_scope scope, struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_search\n"); + return ldb_next_search_bytree(module, base, scope, tree, attrs, res); +} + +static struct ldb_message_element *rdn_name_find_attribute(const struct ldb_message *msg, const char *name) +{ + int i; + + for (i = 0; i < msg->num_elements; i++) { + if (ldb_attr_cmp(name, msg->elements[i].name) == 0) { + return &msg->elements[i]; + } + } + + return NULL; +} + +static struct ldb_dn_component *get_rdn(void *mem_ctx, const char *dn) +{ + struct ldb_dn *dn_exploded = ldb_dn_explode(mem_ctx, dn); + + if (!dn_exploded) { + return NULL; + } + + if (dn_exploded->comp_num < 1) { + return NULL; + } + + return &dn_exploded->components[0]; +} + +/* add_record: add crateTimestamp/modifyTimestamp attributes */ +static int rdn_name_add_record(struct ldb_module *module, const struct ldb_message *msg) +{ + struct ldb_message *msg2; + struct ldb_message_element *attribute; + struct ldb_dn_component *rdn; + int ret, i; + + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_add_record\n"); + + if (msg->dn[0] == '@') { /* do not manipulate our control entries */ + return ldb_next_add_record(module, msg); + } + + /* Perhaps someone above us knows better */ + if ((attribute = rdn_name_find_attribute(msg, "name")) != NULL ) { + return ldb_next_add_record(module, msg); + } + + msg2 = talloc(module, struct ldb_message); + if (!msg2) { + return -1; + } + + msg2->dn = msg->dn; + msg2->num_elements = msg->num_elements; + msg2->private_data = msg->private_data; + msg2->elements = talloc_array(msg2, struct ldb_message_element, msg2->num_elements); + for (i = 0; i < msg2->num_elements; i++) { + msg2->elements[i] = msg->elements[i]; + } + + rdn = get_rdn(msg2, msg2->dn); + if (!rdn) { + return -1; + } + + if (ldb_msg_add_value(module->ldb, msg2, "name", &rdn->value) != 0) { + return -1; + } + + ret = ldb_next_add_record(module, msg2); + talloc_free(msg2); + + return ret; +} + +/* modify_record: change modifyTimestamp as well */ +static int rdn_name_modify_record(struct ldb_module *module, const struct ldb_message *msg) +{ + struct ldb_message *msg2; + struct ldb_message_element *attribute; + struct ldb_dn_component *rdn; + int ret, i; + + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_modify_record\n"); + + /* Perhaps someone above us knows better */ + if ((attribute = rdn_name_find_attribute(msg, "name")) != NULL ) { + return ldb_next_add_record(module, msg); + } + + msg2 = talloc(module, struct ldb_message); + if (!msg2) { + return -1; + } + + msg2->dn = msg->dn; + msg2->num_elements = msg->num_elements; + msg2->private_data = msg->private_data; + msg2->elements = talloc_array(msg2, struct ldb_message_element, msg2->num_elements); + for (i = 0; i < msg2->num_elements; i++) { + msg2->elements[i] = msg->elements[i]; + } + + rdn = get_rdn(msg2, msg2->dn); + if (!rdn) { + return -1; + } + + if (ldb_msg_add_value(module->ldb, msg2, "name", &rdn->value) != 0) { + return -1; + } + + attribute = rdn_name_find_attribute(msg2, "name"); + if (!attribute) { + return -1; + } + + attribute->flags = LDB_FLAG_MOD_REPLACE; + + ret = ldb_next_modify_record(module, msg2); + talloc_free(msg2); + + return ret; +} + +static int rdn_name_delete_record(struct ldb_module *module, const char *dn) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_delete_record\n"); + return ldb_next_delete_record(module, dn); +} + +static int rdn_name_rename_record(struct ldb_module *module, const char *olddn, const char *newdn) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_rename_record\n"); + return ldb_next_rename_record(module, olddn, newdn); +} + +static int rdn_name_lock(struct ldb_module *module, const char *lockname) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_lock\n"); + return ldb_next_named_lock(module, lockname); +} + +static int rdn_name_unlock(struct ldb_module *module, const char *lockname) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_unlock\n"); + return ldb_next_named_unlock(module, lockname); +} + +/* return extended error information */ +static const char *rdn_name_errstring(struct ldb_module *module) +{ + struct private_data *data = (struct private_data *)module->private_data; + + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_errstring\n"); + if (data->error_string) { + const char *error; + + error = data->error_string; + data->error_string = NULL; + return error; + } + + return ldb_next_errstring(module); +} + +static int rdn_name_destructor(void *module_ctx) +{ + /* struct ldb_module *ctx = module_ctx; */ + /* put your clean-up functions here */ + return 0; +} + +static const struct ldb_module_ops rdn_name_ops = { + .name = "rdn_name", + .search = rdn_name_search, + .search_bytree = rdn_name_search_bytree, + .add_record = rdn_name_add_record, + .modify_record = rdn_name_modify_record, + .delete_record = rdn_name_delete_record, + .rename_record = rdn_name_rename_record, + .named_lock = rdn_name_lock, + .named_unlock = rdn_name_unlock, + .errstring = rdn_name_errstring +}; + + +/* the init function */ +#ifdef HAVE_DLOPEN_DISABLED + struct ldb_module *init_module(struct ldb_context *ldb, const char *options[]) +#else +struct ldb_module *rdn_name_module_init(struct ldb_context *ldb, const char *options[]) +#endif +{ + struct ldb_module *ctx; + struct private_data *data; + + ctx = talloc(ldb, struct ldb_module); + if (!ctx) + return NULL; + + data = talloc(ctx, struct private_data); + if (!data) { + talloc_free(ctx); + return NULL; + } + + data->error_string = NULL; + ctx->private_data = data; + ctx->ldb = ldb; + ctx->prev = ctx->next = NULL; + ctx->ops = &rdn_name_ops; + + talloc_set_destructor (ctx, rdn_name_destructor); + + return ctx; +} diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index c1db85a284..b067d8e8d6 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -60,8 +60,8 @@ static int timestamps_search_bytree(struct ldb_module *module, const char *base, static int add_time_element(struct ldb_module *module, struct ldb_message *msg, const char *attr_name, const char *time_string, unsigned int flags) { - struct ldb_val *values; - char *name, *timestr; + struct ldb_message_element *attribute = NULL; + int i; for (i = 0; i < msg->num_elements; i++) { @@ -70,23 +70,22 @@ static int add_time_element(struct ldb_module *module, struct ldb_message *msg, } } - msg->elements = talloc_realloc(msg, msg->elements, - struct ldb_message_element, msg->num_elements + 1); - name = talloc_strdup(msg->elements, attr_name); - timestr = talloc_strdup(msg->elements, time_string); - values = talloc(msg->elements, struct ldb_val); - if (!msg->elements || !name || !timestr || !values) { + if (ldb_msg_add_string(module->ldb, msg, attr_name, time_string) != 0) { return -1; } - msg->elements[msg->num_elements].name = name; - msg->elements[msg->num_elements].flags = flags; - msg->elements[msg->num_elements].num_values = 1; - msg->elements[msg->num_elements].values = values; - msg->elements[msg->num_elements].values[0].data = timestr; - msg->elements[msg->num_elements].values[0].length = strlen(timestr); + for (i = 0; i < msg->num_elements; i++) { + if (ldb_attr_cmp(attr_name, msg->elements[i].name) == 0) { + attribute = &msg->elements[i]; + break; + } + } - msg->num_elements += 1; + if (!attribute) { + return -1; + } + + attribute->flags = flags; return 0; } @@ -196,12 +195,8 @@ static int timestamps_modify_record(struct ldb_module *module, const struct ldb_ add_time_element(module, msg2, "modifyTimestamp", timestr, LDB_FLAG_MOD_REPLACE); add_time_element(module, msg2, "whenChanged", timestr, LDB_FLAG_MOD_REPLACE); - if (msg2) { - ret = ldb_next_modify_record(module, msg2); - talloc_free(msg2); - } else { - ret = ldb_next_modify_record(module, msg); - } + ret = ldb_next_modify_record(module, msg2); + talloc_free(msg2); return ret; } -- cgit From 4396d0d1482d4033a469f7a3e3835a6f3b145046 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 21 Jul 2005 08:32:07 +0000 Subject: r8669: The objectguid module belongs in Samba's ldb module collection, not in ldb, as it can't build without the NDR and GUID code. Also make it properly use the NDR encoding for the GUID (I forgot last time, and used a string), as well as set the dependencies on the module correctly. Andrew Bartlett (This used to be commit 8054abc76e5e3588cebc7fc01062a1223b7f140b) --- source4/lib/ldb/modules/objectguid.c | 220 ----------------------------------- 1 file changed, 220 deletions(-) delete mode 100644 source4/lib/ldb/modules/objectguid.c (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/objectguid.c b/source4/lib/ldb/modules/objectguid.c deleted file mode 100644 index 0e789c2bda..0000000000 --- a/source4/lib/ldb/modules/objectguid.c +++ /dev/null @@ -1,220 +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 2 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, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* - * Name: ldb - * - * Component: ldb objectguid module - * - * Description: add a unique objectGUID onto every new record - * - * Author: Simo Sorce - */ - -#include "includes.h" -#include "ldb/include/ldb.h" -#include "ldb/include/ldb_private.h" -#include - -struct private_data { - const char *error_string; -}; - -static int objectguid_search(struct ldb_module *module, const char *base, - enum ldb_scope scope, const char *expression, - const char * const *attrs, struct ldb_message ***res) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_search\n"); - return ldb_next_search(module, base, scope, expression, attrs, res); -} - -static int objectguid_search_bytree(struct ldb_module *module, const char *base, - enum ldb_scope scope, struct ldb_parse_tree *tree, - const char * const *attrs, struct ldb_message ***res) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_search\n"); - return ldb_next_search_bytree(module, base, scope, tree, attrs, res); -} - -static struct ldb_message_element *objectguid_find_attribute(const struct ldb_message *msg, const char *name) -{ - int i; - - for (i = 0; i < msg->num_elements; i++) { - if (ldb_attr_cmp(name, msg->elements[i].name) == 0) { - return &msg->elements[i]; - } - } - - return NULL; -} - -/* add_record: add crateTimestamp/modifyTimestamp attributes */ -static int objectguid_add_record(struct ldb_module *module, const struct ldb_message *msg) -{ - struct ldb_message *msg2; - struct ldb_message_element *attribute; - struct GUID guid; - char *guidstr; - int ret, i; - - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_add_record\n"); - - if (msg->dn[0] == '@') { /* do not manipulate our control entries */ - return ldb_next_add_record(module, msg); - } - - if ((attribute = objectguid_find_attribute(msg, "objectGUID")) != NULL ) { - return ldb_next_add_record(module, msg); - } - - msg2 = talloc(module, struct ldb_message); - if (!msg2) { - return -1; - } - - msg2->dn = msg->dn; - msg2->num_elements = msg->num_elements; - msg2->private_data = msg->private_data; - msg2->elements = talloc_array(msg2, struct ldb_message_element, msg2->num_elements); - for (i = 0; i < msg2->num_elements; i++) { - msg2->elements[i] = msg->elements[i]; - } - - /* a new GUID */ - guid = GUID_random(); - guidstr = GUID_string(msg2, &guid); - if (!guidstr) { - return -1; - } - - if (ldb_msg_add_string(module->ldb, msg2, "objectGUID", guidstr) != 0) { - return -1; - } - - ret = ldb_next_add_record(module, msg2); - talloc_free(msg2); - - return ret; -} - -/* modify_record: change modifyTimestamp as well */ -static int objectguid_modify_record(struct ldb_module *module, const struct ldb_message *msg) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_modify_record\n"); - return ldb_next_modify_record(module, msg); -} - -static int objectguid_delete_record(struct ldb_module *module, const char *dn) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_delete_record\n"); - return ldb_next_delete_record(module, dn); -} - -static int objectguid_rename_record(struct ldb_module *module, const char *olddn, const char *newdn) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_rename_record\n"); - return ldb_next_rename_record(module, olddn, newdn); -} - -static int objectguid_lock(struct ldb_module *module, const char *lockname) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_lock\n"); - return ldb_next_named_lock(module, lockname); -} - -static int objectguid_unlock(struct ldb_module *module, const char *lockname) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_unlock\n"); - return ldb_next_named_unlock(module, lockname); -} - -/* return extended error information */ -static const char *objectguid_errstring(struct ldb_module *module) -{ - struct private_data *data = (struct private_data *)module->private_data; - - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_errstring\n"); - if (data->error_string) { - const char *error; - - error = data->error_string; - data->error_string = NULL; - return error; - } - - return ldb_next_errstring(module); -} - -static int objectguid_destructor(void *module_ctx) -{ - /* struct ldb_module *ctx = module_ctx; */ - /* put your clean-up functions here */ - return 0; -} - -static const struct ldb_module_ops objectguid_ops = { - .name = "objectguid", - .search = objectguid_search, - .search_bytree = objectguid_search_bytree, - .add_record = objectguid_add_record, - .modify_record = objectguid_modify_record, - .delete_record = objectguid_delete_record, - .rename_record = objectguid_rename_record, - .named_lock = objectguid_lock, - .named_unlock = objectguid_unlock, - .errstring = objectguid_errstring -}; - - -/* the init function */ -#ifdef HAVE_DLOPEN_DISABLED - struct ldb_module *init_module(struct ldb_context *ldb, const char *options[]) -#else -struct ldb_module *objectguid_module_init(struct ldb_context *ldb, const char *options[]) -#endif -{ - struct ldb_module *ctx; - struct private_data *data; - - ctx = talloc(ldb, struct ldb_module); - if (!ctx) - return NULL; - - data = talloc(ctx, struct private_data); - if (!data) { - talloc_free(ctx); - return NULL; - } - - data->error_string = NULL; - ctx->private_data = data; - ctx->ldb = ldb; - ctx->prev = ctx->next = NULL; - ctx->ops = &objectguid_ops; - - talloc_set_destructor (ctx, objectguid_destructor); - - return ctx; -} -- cgit From a7f9d9c5b8e77e0530ace68bd2ed4a7c374bf0fa Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 25 Jul 2005 01:17:09 +0000 Subject: r8740: Extend the rdn_name module to handle adding the rdn as an attribute. ie: dn: cn=foo,ou=bar objectClass: person implies dn: cn=foo,ou=bar objectClass: person cn: foo (as well as a pile more default attributes) We also correct the case in the attirbute to match that in the DN (win2k3 behaviour) and I have a testsuite (in ejs) to prove it. This module also found a bug in our provision.ldif, so and reduces code complexity in the samdb module. Andrew Bartlett (This used to be commit 0cc58f5c3cce12341ad0f7a90cdd85a3fab786b3) --- source4/lib/ldb/modules/rdn_name.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/rdn_name.c b/source4/lib/ldb/modules/rdn_name.c index 6a11ab87fe..89cc49eb3e 100644 --- a/source4/lib/ldb/modules/rdn_name.c +++ b/source4/lib/ldb/modules/rdn_name.c @@ -88,10 +88,12 @@ static struct ldb_dn_component *get_rdn(void *mem_ctx, const char *dn) /* add_record: add crateTimestamp/modifyTimestamp attributes */ static int rdn_name_add_record(struct ldb_module *module, const struct ldb_message *msg) { + struct private_data *data = (struct private_data *)module->private_data; + struct ldb_message *msg2; struct ldb_message_element *attribute; struct ldb_dn_component *rdn; - int ret, i; + int i, ret; ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_add_record\n"); @@ -126,6 +128,29 @@ static int rdn_name_add_record(struct ldb_module *module, const struct ldb_messa return -1; } + attribute = rdn_name_find_attribute(msg2, rdn->name); + + if (!attribute) { + if (ldb_msg_add_value(module->ldb, msg2, rdn->name, &rdn->value) != 0) { + return -1; + } + } else { + const struct ldb_attrib_handler *handler + = ldb_attrib_handler(module->ldb, rdn->name); + for (i=0; i < attribute->num_values; i++) { + if (handler->comparison_fn(module->ldb, msg2, &rdn->value, &attribute->values[i]) == 0) { + /* overwrite so it matches in case */ + attribute->values[i] = rdn->value; + break; + } + } + if (i == attribute->num_values) { + data->error_string = talloc_asprintf(data, "RDN mismatch on %s: %s", msg2->dn, rdn->name); + ldb_debug(module->ldb, LDB_DEBUG_FATAL, "%s\n", data->error_string); + return -1; + } + } + ret = ldb_next_add_record(module, msg2); talloc_free(msg2); -- cgit From 3e4c4cff2177af33efdb15f03a1bbcb639505cee Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 18 Aug 2005 15:02:01 +0000 Subject: r9391: Convert all the code to use struct ldb_dn to ohandle ldap like distinguished names Provide more functions to handle DNs in this form (This used to be commit 692e35b7797e39533dd2a1c4b63d9da30f1eb5ba) --- source4/lib/ldb/modules/rdn_name.c | 44 +++++++++--------- source4/lib/ldb/modules/schema.c | 87 +++++++++++++++--------------------- source4/lib/ldb/modules/skel.c | 6 +-- source4/lib/ldb/modules/timestamps.c | 16 ++++--- 4 files changed, 69 insertions(+), 84 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/rdn_name.c b/source4/lib/ldb/modules/rdn_name.c index 89cc49eb3e..d59205c6e4 100644 --- a/source4/lib/ldb/modules/rdn_name.c +++ b/source4/lib/ldb/modules/rdn_name.c @@ -41,7 +41,7 @@ struct private_data { const char *error_string; }; -static int rdn_name_search(struct ldb_module *module, const char *base, +static int rdn_name_search(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, const char *expression, const char * const *attrs, struct ldb_message ***res) { @@ -49,7 +49,7 @@ static int rdn_name_search(struct ldb_module *module, const char *base, return ldb_next_search(module, base, scope, expression, attrs, res); } -static int rdn_name_search_bytree(struct ldb_module *module, const char *base, +static int rdn_name_search_bytree(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const *attrs, struct ldb_message ***res) { @@ -70,21 +70,6 @@ static struct ldb_message_element *rdn_name_find_attribute(const struct ldb_mess return NULL; } -static struct ldb_dn_component *get_rdn(void *mem_ctx, const char *dn) -{ - struct ldb_dn *dn_exploded = ldb_dn_explode(mem_ctx, dn); - - if (!dn_exploded) { - return NULL; - } - - if (dn_exploded->comp_num < 1) { - return NULL; - } - - return &dn_exploded->components[0]; -} - /* add_record: add crateTimestamp/modifyTimestamp attributes */ static int rdn_name_add_record(struct ldb_module *module, const struct ldb_message *msg) { @@ -97,7 +82,8 @@ static int rdn_name_add_record(struct ldb_module *module, const struct ldb_messa ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_add_record\n"); - if (msg->dn[0] == '@') { /* do not manipulate our control entries */ + /* do not manipulate our control entries */ + if (ldb_dn_is_special(msg->dn)) { return ldb_next_add_record(module, msg); } @@ -119,12 +105,14 @@ static int rdn_name_add_record(struct ldb_module *module, const struct ldb_messa msg2->elements[i] = msg->elements[i]; } - rdn = get_rdn(msg2, msg2->dn); + rdn = ldb_dn_get_rdn(msg2, msg2->dn); if (!rdn) { + talloc_free(msg2); return -1; } if (ldb_msg_add_value(module->ldb, msg2, "name", &rdn->value) != 0) { + talloc_free(msg2); return -1; } @@ -132,6 +120,7 @@ static int rdn_name_add_record(struct ldb_module *module, const struct ldb_messa if (!attribute) { if (ldb_msg_add_value(module->ldb, msg2, rdn->name, &rdn->value) != 0) { + talloc_free(msg2); return -1; } } else { @@ -145,8 +134,9 @@ static int rdn_name_add_record(struct ldb_module *module, const struct ldb_messa } } if (i == attribute->num_values) { - data->error_string = talloc_asprintf(data, "RDN mismatch on %s: %s", msg2->dn, rdn->name); + data->error_string = talloc_asprintf(data, "RDN mismatch on %s: %s", ldb_dn_linearize(msg2, msg2->dn), rdn->name); ldb_debug(module->ldb, LDB_DEBUG_FATAL, "%s\n", data->error_string); + talloc_free(msg2); return -1; } } @@ -167,6 +157,11 @@ static int rdn_name_modify_record(struct ldb_module *module, const struct ldb_me ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_modify_record\n"); + /* do not manipulate our control entries */ + if (ldb_dn_is_special(msg->dn)) { + return ldb_next_add_record(module, msg); + } + /* Perhaps someone above us knows better */ if ((attribute = rdn_name_find_attribute(msg, "name")) != NULL ) { return ldb_next_add_record(module, msg); @@ -185,17 +180,20 @@ static int rdn_name_modify_record(struct ldb_module *module, const struct ldb_me msg2->elements[i] = msg->elements[i]; } - rdn = get_rdn(msg2, msg2->dn); + rdn = ldb_dn_get_rdn(msg2, msg2->dn); if (!rdn) { + talloc_free(msg2); return -1; } if (ldb_msg_add_value(module->ldb, msg2, "name", &rdn->value) != 0) { + talloc_free(msg2); return -1; } attribute = rdn_name_find_attribute(msg2, "name"); if (!attribute) { + talloc_free(msg2); return -1; } @@ -207,13 +205,13 @@ static int rdn_name_modify_record(struct ldb_module *module, const struct ldb_me return ret; } -static int rdn_name_delete_record(struct ldb_module *module, const char *dn) +static int rdn_name_delete_record(struct ldb_module *module, const struct ldb_dn *dn) { ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_delete_record\n"); return ldb_next_delete_record(module, dn); } -static int rdn_name_rename_record(struct ldb_module *module, const char *olddn, const char *newdn) +static int rdn_name_rename_record(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn) { ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_rename_record\n"); return ldb_next_rename_record(module, olddn, newdn); diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index e11c8b4e4e..baf038de0c 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -1,7 +1,7 @@ /* ldb database library - Copyright (C) Simo Sorce 2004 + Copyright (C) Simo Sorce 2004-2005 ** NOTE! The following LGPL license applies to the ldb ** library. This does NOT imply that all of Samba is released @@ -72,28 +72,6 @@ struct schema_structures { struct schema_attribute_list optional_attrs; }; -/* This function embedds the knowledge of aliased names. - Currently it handles only dn vs distinguishedNAme as a special case as AD - only have this special alias case, in future we should read the schema - to find out which names have an alias and check for them */ -static int schema_attr_cmp(const char *attr1, const char *attr2) -{ - int ret; - - ret = ldb_attr_cmp(attr1, attr2); - if (ret != 0) { - if ((ldb_attr_cmp("dn", attr1) == 0) && - (ldb_attr_cmp("distinguishedName", attr2) == 0)) { - return 0; - } - if ((ldb_attr_cmp("dn", attr2) == 0) && - (ldb_attr_cmp("distinguishedName", attr1) == 0)) { - return 0; - } - } - return ret; -} - static struct schema_attribute *schema_find_attribute(struct schema_attribute_list *list, const char *attr_name) { unsigned int i; @@ -110,7 +88,7 @@ static struct schema_attribute *schema_find_attribute(struct schema_attribute_li objectclasses go in the objectclasses structure */ static int get_msg_attributes(struct schema_structures *ss, const struct ldb_message *msg, int flag_mask) { - int i, j, k, l; + int i, j, anum, cnum; ss->entry_attrs.attr = talloc_realloc(ss, ss->entry_attrs.attr, struct schema_attribute, @@ -119,9 +97,9 @@ static int get_msg_attributes(struct schema_structures *ss, const struct ldb_mes return -1; } - for (i = 0, j = ss->entry_attrs.num; i < msg->num_elements; i++) { + for (i = 0, anum = ss->entry_attrs.num; i < msg->num_elements; i++) { - if (schema_attr_cmp(msg->elements[i].name, "objectclass") == 0) { + if (ldb_attr_cmp(msg->elements[i].name, "objectclass") == 0) { ss->objectclasses.attr = talloc_realloc(ss, ss->objectclasses.attr, struct schema_attribute, @@ -130,34 +108,33 @@ static int get_msg_attributes(struct schema_structures *ss, const struct ldb_mes return -1; } - for (k = 0, l = ss->objectclasses.num; k < msg->elements[i].num_values; k++) { - ss->objectclasses.attr[l].name = msg->elements[i].values[k].data; - ss->objectclasses.attr[l].flags = msg->elements[i].flags & flag_mask; - l++; + for (j = 0, cnum = ss->objectclasses.num; j < msg->elements[i].num_values; j++) { + ss->objectclasses.attr[cnum+j].name = msg->elements[i].values[j].data; + ss->objectclasses.attr[cnum+j].flags = msg->elements[i].flags & flag_mask; } ss->objectclasses.num += msg->elements[i].num_values; } - ss->entry_attrs.attr[j].flags = msg->elements[i].flags & flag_mask; - ss->entry_attrs.attr[j].name = talloc_reference(ss->entry_attrs.attr, + /* TODO: Check for proper attribute Syntax ! */ + + ss->entry_attrs.attr[anum+i].flags = msg->elements[i].flags & flag_mask; + ss->entry_attrs.attr[anum+i].name = talloc_reference(ss->entry_attrs.attr, msg->elements[i].name); - if (ss->entry_attrs.attr[j].name == NULL) { + if (ss->entry_attrs.attr[anum+i].name == NULL) { return -1; } - j++; } ss->entry_attrs.num += msg->num_elements; return 0; } -static int get_entry_attributes(struct ldb_context *ldb, const char *dn, struct schema_structures *ss) +static int get_entry_attributes(struct ldb_context *ldb, const struct ldb_dn *dn, struct schema_structures *ss) { - char *filter = talloc_asprintf(ss, "dn=%s", dn); struct ldb_message **srch; int ret; - ret = ldb_search(ldb, NULL, LDB_SCOPE_SUBTREE, filter, NULL, &srch); + ret = ldb_search(ldb, dn, LDB_SCOPE_BASE, NULL, NULL, &srch); if (ret != 1) { return ret; } @@ -190,7 +167,7 @@ static int add_attribute_uniq(void *mem_ctx, struct schema_attribute_list *list, for (c = 0; c < list->num; c++) { len = strlen(list->attr[c].name); if (len == el->values[i].length) { - if (schema_attr_cmp(list->attr[c].name, el->values[i].data) == 0) { + if (ldb_attr_cmp(list->attr[c].name, el->values[i].data) == 0) { found = 1; break; } @@ -254,11 +231,15 @@ static int get_attr_list_recursive(struct ldb_module *module, struct schema_stru is_aux = 0; is_class = 0; - if (schema_attr_cmp((*srch)->elements[j].name, "systemAuxiliaryclass") == 0) { + if (ldb_attr_cmp((*srch)->elements[j].name, "systemAuxiliaryclass") == 0) { is_aux = SCHEMA_FLAG_AUXILIARY; is_class = 1; } - if (schema_attr_cmp((*srch)->elements[j].name, "subClassOf") == 0) { + if (ldb_attr_cmp((*srch)->elements[j].name, "auxiliaryClass") == 0) { + is_aux = SCHEMA_FLAG_AUXILIARY; + is_class = 1; + } + if (ldb_attr_cmp((*srch)->elements[j].name, "subClassOf") == 0) { is_class = 1; } @@ -271,8 +252,8 @@ static int get_attr_list_recursive(struct ldb_module *module, struct schema_stru } } else { - if (schema_attr_cmp((*srch)->elements[j].name, "mustContain") == 0 || - schema_attr_cmp((*srch)->elements[j].name, "SystemMustContain") == 0) { + if (ldb_attr_cmp((*srch)->elements[j].name, "mustContain") == 0 || + ldb_attr_cmp((*srch)->elements[j].name, "SystemMustContain") == 0) { if (add_attribute_uniq(schema_struct, &schema_struct->required_attrs, SCHEMA_FLAG_RESET, @@ -281,8 +262,8 @@ static int get_attr_list_recursive(struct ldb_module *module, struct schema_stru } } - if (schema_attr_cmp((*srch)->elements[j].name, "mayContain") == 0 || - schema_attr_cmp((*srch)->elements[j].name, "SystemMayContain") == 0) { + if (ldb_attr_cmp((*srch)->elements[j].name, "mayContain") == 0 || + ldb_attr_cmp((*srch)->elements[j].name, "SystemMayContain") == 0) { if (add_attribute_uniq(schema_struct, &schema_struct->optional_attrs, @@ -299,14 +280,14 @@ static int get_attr_list_recursive(struct ldb_module *module, struct schema_stru } /* search */ -static int schema_search(struct ldb_module *module, const char *base, +static int schema_search(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, const char *expression, const char * const *attrs, struct ldb_message ***res) { return ldb_next_search(module, base, scope, expression, attrs, res); } -static int schema_search_bytree(struct ldb_module *module, const char *base, +static int schema_search_bytree(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const *attrs, struct ldb_message ***res) { @@ -329,10 +310,13 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message Free all structures and commit the change */ - if (msg->dn[0] == '@') { /* do not check on our control entries */ + /* do not check on our control entries */ + if (ldb_dn_is_special(msg->dn)) { return ldb_next_add_record(module, msg); } + /* TODO: check parent exists */ + entry_structs = talloc_zero(module, struct schema_structures); if (!entry_structs) { return -1; @@ -414,8 +398,9 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess Free all structures and commit the change. */ - if (msg->dn[0] == '@') { /* do not check on our control entries */ - return ldb_next_modify_record(module, msg); + /* do not check on our control entries */ + if (ldb_dn_is_special(msg->dn)) { + return ldb_next_add_record(module, msg); } /* allocate object structs */ @@ -504,14 +489,14 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess } /* delete_record */ -static int schema_delete_record(struct ldb_module *module, const char *dn) +static int schema_delete_record(struct ldb_module *module, const struct ldb_dn *dn) { /* struct private_data *data = (struct private_data *)module->private_data; */ return ldb_next_delete_record(module, dn); } /* rename_record */ -static int schema_rename_record(struct ldb_module *module, const char *olddn, const char *newdn) +static int schema_rename_record(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn) { return ldb_next_rename_record(module, olddn, newdn); } diff --git a/source4/lib/ldb/modules/skel.c b/source4/lib/ldb/modules/skel.c index 1221ac70f1..57c89a6a65 100644 --- a/source4/lib/ldb/modules/skel.c +++ b/source4/lib/ldb/modules/skel.c @@ -42,7 +42,7 @@ struct private_data { }; /* search */ -static int skel_search(struct ldb_module *module, const char *base, +static int skel_search(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, const char *expression, const char * const *attrs, struct ldb_message ***res) { @@ -62,13 +62,13 @@ static int skel_modify_record(struct ldb_module *module, const struct ldb_messag } /* delete_record */ -static int skel_delete_record(struct ldb_module *module, const char *dn) +static int skel_delete_record(struct ldb_module *module, const struct ldb_dn *dn) { return ldb_next_delete_record(module, dn); } /* rename_record */ -static int skel_rename_record(struct ldb_module *module, const char *olddn, const char *newdn) +static int skel_rename_record(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn) { return ldb_next_rename_record(module, olddn, newdn); } diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index b067d8e8d6..4819e0466b 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -41,7 +41,7 @@ struct private_data { const char *error_string; }; -static int timestamps_search(struct ldb_module *module, const char *base, +static int timestamps_search(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, const char *expression, const char * const *attrs, struct ldb_message ***res) { @@ -49,7 +49,7 @@ static int timestamps_search(struct ldb_module *module, const char *base, return ldb_next_search(module, base, scope, expression, attrs, res); } -static int timestamps_search_bytree(struct ldb_module *module, const char *base, +static int timestamps_search_bytree(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const *attrs, struct ldb_message ***res) { @@ -101,7 +101,8 @@ static int timestamps_add_record(struct ldb_module *module, const struct ldb_mes ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_add_record\n"); - if (msg->dn[0] == '@') { /* do not manipulate our control entries */ + /* do not manipulate our control entries */ + if (ldb_dn_is_special(msg->dn)) { return ldb_next_add_record(module, msg); } @@ -159,8 +160,9 @@ static int timestamps_modify_record(struct ldb_module *module, const struct ldb_ ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_modify_record\n"); - if (msg->dn[0] == '@') { /* do not manipulate our control entries */ - return ldb_next_modify_record(module, msg); + /* do not manipulate our control entries */ + if (ldb_dn_is_special(msg->dn)) { + return ldb_next_add_record(module, msg); } timeval = time(NULL); @@ -201,13 +203,13 @@ static int timestamps_modify_record(struct ldb_module *module, const struct ldb_ return ret; } -static int timestamps_delete_record(struct ldb_module *module, const char *dn) +static int timestamps_delete_record(struct ldb_module *module, const struct ldb_dn *dn) { ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_delete_record\n"); return ldb_next_delete_record(module, dn); } -static int timestamps_rename_record(struct ldb_module *module, const char *olddn, const char *newdn) +static int timestamps_rename_record(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn) { ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_rename_record\n"); return ldb_next_rename_record(module, olddn, newdn); -- cgit From f9447d2a17089178d311e03e398c25c749450f6d Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 30 Aug 2005 11:08:03 +0000 Subject: r9786: Move ldb_map into ldb/modules/ Move samba3sam to dsdb/ (This used to be commit eb9d615bcd49328131613f64745760a90553b7f2) --- source4/lib/ldb/modules/ldb_map.c | 1151 +++++++++++++++++++++++++++++++++++++ source4/lib/ldb/modules/ldb_map.h | 108 ++++ 2 files changed, 1259 insertions(+) create mode 100644 source4/lib/ldb/modules/ldb_map.c create mode 100644 source4/lib/ldb/modules/ldb_map.h (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c new file mode 100644 index 0000000000..531d5ccd67 --- /dev/null +++ b/source4/lib/ldb/modules/ldb_map.c @@ -0,0 +1,1151 @@ +/* + ldb database library - map backend + + Copyright (C) Jelmer Vernooij 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "includes.h" +#include "lib/ldb/include/ldb.h" +#include "lib/ldb/include/ldb_private.h" +#include "lib/ldb/modules/ldb_map.h" + +/* TODO: + * - objectclass hint in ldb_map_attribute + * for use when multiple remote attributes (independant of each other) + * map to one local attribute. E.g.: (uid, gidNumber) -> unixName + * (use MAP_GENERATE instead ?) + */ + +/* + - special attribute 'isMapped' + - add/modify + - split up ldb_message into fallback and mapped parts if is_mappable + - search: + - search local one for not isMapped entries + - remove remote attributes from ldb_parse_tree + - search remote one + - per record, search local one for additional data (by dn) + - test if (full expression) is now true + - delete + - delete both + - rename + - rename locally and remotely +*/ + +static const struct ldb_map_attribute builtin_attribute_maps[]; + +struct map_private { + struct ldb_map_context context; + const char *last_err_string; +}; + +static struct ldb_map_context *map_get_privdat(struct ldb_module *module) +{ + return &((struct map_private *)module->private_data)->context; +} + +static const struct ldb_map_objectclass *map_find_objectclass_local(struct ldb_map_context *privdat, const char *name) +{ + int i; + for (i = 0; privdat->objectclass_maps[i].local_name; i++) { + if (!ldb_attr_cmp(privdat->objectclass_maps[i].local_name, name)) + return &privdat->objectclass_maps[i]; + } + + return NULL; +} + +/* Decide whether a add/modify should be pushed to the + * remote LDAP server. We currently only do this if we see an objectClass we know */ +static BOOL map_is_mappable(struct ldb_map_context *privdat, const struct ldb_message *msg) +{ + int i; + struct ldb_message_element *el = ldb_msg_find_element(msg, "objectClass"); + + /* No objectClass... */ + if (el == NULL) { + return False; + } + + for (i = 0; i < el->num_values; i++) { + if (map_find_objectclass_local(privdat, (char *)el->values[i].data)) + return True; + } + + return False; +} + +/* find an attribute by the local name */ +static const struct ldb_map_attribute *map_find_attr_local(struct ldb_map_context *privdat, const char *attr) +{ + int i; + + for (i = 0; privdat->attribute_maps[i].local_name; i++) { + if (!ldb_attr_cmp(privdat->attribute_maps[i].local_name, attr)) + return &privdat->attribute_maps[i]; + } + + return NULL; +} + +/* find an attribute by the remote name */ +static const struct ldb_map_attribute *map_find_attr_remote(struct ldb_map_context *privdat, const char *attr) +{ + int i; + + for (i = 0; privdat->attribute_maps[i].local_name; i++) { + if (privdat->attribute_maps[i].type == MAP_IGNORE) + continue; + + if (privdat->attribute_maps[i].type == MAP_GENERATE) + continue; + + if (privdat->attribute_maps[i].type == MAP_KEEP && + ldb_attr_cmp(privdat->attribute_maps[i].local_name, attr) == 0) + return &privdat->attribute_maps[i]; + + if ((privdat->attribute_maps[i].type == MAP_RENAME || + privdat->attribute_maps[i].type == MAP_CONVERT) && + ldb_attr_cmp(privdat->attribute_maps[i].u.rename.remote_name, attr) == 0) + return &privdat->attribute_maps[i]; + + } + + return NULL; +} + +static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_parse_tree *tree) +{ + int i; + const struct ldb_map_attribute *attr; + struct ldb_parse_tree *new_tree; + enum ldb_map_attr_type map_type; + struct ldb_val value, newvalue; + struct ldb_map_context *privdat = map_get_privdat(module); + + if (tree == NULL) + return NULL; + + + /* Find attr in question and: + * - if it has a convert_operator function, run that + * - otherwise, replace attr name with required[0] */ + + if (tree->operation == LDB_OP_AND || + tree->operation == LDB_OP_OR) { + + new_tree = talloc_memdup(ctx, tree, sizeof(*tree)); + new_tree->u.list.elements = talloc_array(new_tree, struct ldb_parse_tree *, tree->u.list.num_elements); + new_tree->u.list.num_elements = 0; + for (i = 0; i < tree->u.list.num_elements; i++) { + struct ldb_parse_tree *child = ldb_map_parse_tree(module, new_tree, tree->u.list.elements[i]); + + if (child) { + new_tree->u.list.elements[i] = child; + new_tree->u.list.num_elements++; + } + } + + return new_tree; + } + + if (tree->operation == LDB_OP_NOT) { + struct ldb_parse_tree *child; + + new_tree = talloc_memdup(ctx, tree, sizeof(*tree)); + child = ldb_map_parse_tree(module, new_tree, tree->u.isnot.child); + + if (!child) { + talloc_free(new_tree); + return NULL; + } + + new_tree->u.isnot.child = child; + return new_tree; + } + + /* tree->operation is LDB_OP_EQUALITY, LDB_OP_SUBSTRING, LDB_OP_GREATER, + * LDB_OP_LESS, LDB_OP_APPROX, LDB_OP_PRESENT or LDB_OP_EXTENDED + * + * (all have attr as the first element) + */ + + attr = map_find_attr_local(privdat, tree->u.equality.attr); + + if (!attr) { + ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Unable to find local attribute '%s', leaving as is\n", tree->u.equality.attr); + map_type = MAP_KEEP; + } else { + map_type = attr->type; + } + + if (attr && attr->convert_operator) { + /* Run convert_operator */ + return attr->convert_operator(privdat, module, tree); + } + + if (map_type == MAP_IGNORE) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Search on ignored attribute '%s'\n", tree->u.equality.attr); + return NULL; + } + + if (map_type == MAP_GENERATE) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Can't do conversion for MAP_GENERATE in map_parse_tree without convert_operator for '%s'\n", tree->u.equality.attr); + return NULL; + } + + if (tree->operation == LDB_OP_EQUALITY) { + value = tree->u.equality.value; + } else if (tree->operation == LDB_OP_LESS || tree->operation == LDB_OP_GREATER || + tree->operation == LDB_OP_APPROX) { + value = tree->u.comparison.value; + } else if (tree->operation == LDB_OP_EXTENDED) { + value = tree->u.extended.value; + } + + new_tree = talloc_memdup(ctx, tree, sizeof(*tree)); + + if (map_type == MAP_KEEP) { + new_tree->u.equality.attr = talloc_strdup(new_tree, tree->u.equality.attr); + } else { /* MAP_RENAME / MAP_CONVERT */ + new_tree->u.equality.attr = talloc_strdup(new_tree, attr->u.rename.remote_name); + } + + if (new_tree->operation == LDB_OP_PRESENT) + return new_tree; + + if (new_tree->operation == LDB_OP_SUBSTRING) { + new_tree->u.substring.chunks = NULL; /* FIXME! */ + return new_tree; + } + + if (map_type == MAP_CONVERT) { + newvalue = attr->u.convert.convert_local(privdat, new_tree, &value); + } else { + newvalue = ldb_val_dup(new_tree, &value); + } + + if (new_tree->operation == LDB_OP_EQUALITY) { + new_tree->u.equality.value = newvalue; + } else if (new_tree->operation == LDB_OP_LESS || new_tree->operation == LDB_OP_GREATER || + new_tree->operation == LDB_OP_APPROX) { + new_tree->u.comparison.value = newvalue; + } else if (new_tree->operation == LDB_OP_EXTENDED) { + new_tree->u.extended.value = newvalue; + new_tree->u.extended.rule_id = talloc_strdup(new_tree, tree->u.extended.rule_id); + } + + return new_tree; +} + +/* Remote DN -> Local DN */ +static struct ldb_dn *map_remote_dn(struct ldb_map_context *privdat, TALLOC_CTX *ctx, const struct ldb_dn *dn) +{ + struct ldb_dn *newdn; + int i; + + if (dn == NULL) + return NULL; + + newdn = talloc_memdup(ctx, dn, sizeof(*dn)); + if (!newdn) + return NULL; + + newdn->components = talloc_array(newdn, struct ldb_dn_component, newdn->comp_num); + + if (!newdn->components) + return NULL; + + /* For each rdn, map the attribute name and possibly the + * complete rdn */ + + for (i = 0; i < dn->comp_num; i++) { + const struct ldb_map_attribute *attr = map_find_attr_remote(privdat, dn->components[i].name); + enum ldb_map_attr_type map_type; + + /* Unknown attribute - leave this dn as is and hope the best... */ + if (!attr) map_type = MAP_KEEP; + else map_type = attr->type; + + switch (map_type) { + case MAP_IGNORE: + case MAP_GENERATE: + DEBUG(0, ("Local MAP_IGNORE or MAP_GENERATE attribute '%s' used in DN!", dn->components[i].name)); + talloc_free(newdn); + return NULL; + + case MAP_KEEP: + newdn->components[i].name = talloc_strdup(newdn->components, dn->components[i].name); + newdn->components[i].value = ldb_val_dup(newdn->components, &dn->components[i].value); + break; + + case MAP_CONVERT: + newdn->components[i].name = talloc_strdup(newdn->components, attr->local_name); + newdn->components[i].value = attr->u.convert.convert_remote(privdat, ctx, &dn->components[i].value); + break; + + case MAP_RENAME: + newdn->components[i].name = talloc_strdup(newdn->components, attr->local_name); + newdn->components[i].value = ldb_val_dup(newdn->components, &dn->components[i].value); + break; + } + } + return newdn; +} + +/* Local DN -> Remote DN */ +static struct ldb_dn *map_local_dn(struct ldb_map_context *privdat, TALLOC_CTX *ctx, const struct ldb_dn *dn) +{ + struct ldb_dn *newdn; + int i; + + if (dn == NULL) + return NULL; + + newdn = talloc_memdup(ctx, dn, sizeof(*dn)); + if (!newdn) + return NULL; + + newdn->components = talloc_array(newdn, struct ldb_dn_component, newdn->comp_num); + + if (!newdn->components) + return NULL; + + /* For each rdn, map the attribute name and possibly the + * complete rdn using an equality convert_operator call */ + + for (i = 0; i < dn->comp_num; i++) { + const struct ldb_map_attribute *attr = map_find_attr_local(privdat, dn->components[i].name); + enum ldb_map_attr_type map_type; + + /* Unknown attribute - leave this dn as is and hope the best... */ + if (!attr) map_type = MAP_KEEP; else map_type = attr->type; + + switch (map_type) + { + case MAP_IGNORE: + case MAP_GENERATE: + DEBUG(0, ("Local MAP_IGNORE/MAP_GENERATE attribute '%s' used in DN!", dn->components[i].name)); + talloc_free(newdn); + return NULL; + + case MAP_CONVERT: + newdn->components[i].name = talloc_strdup(newdn->components, attr->u.convert.remote_name); + newdn->components[i].value = attr->u.convert.convert_local(privdat, newdn->components, &dn->components[i].value); + break; + + case MAP_RENAME: + newdn->components[i].name = talloc_strdup(newdn->components, attr->u.rename.remote_name); + newdn->components[i].value = ldb_val_dup(newdn->components, &dn->components[i].value); + break; + + case MAP_KEEP: + newdn->components[i].name = talloc_strdup(newdn->components, dn->components[i].name); + newdn->components[i].value = ldb_val_dup(newdn->components, &dn->components[i].value); + continue; + } + } + + return newdn; +} + +/* Loop over ldb_map_attribute array and add remote_names */ +static const char **ldb_map_attrs(struct ldb_module *module, const char *const attrs[]) +{ + int i; + const char **ret; + int ar_size = 0, last_element = 0; + struct ldb_map_context *privdat = map_get_privdat(module); + + if (attrs == NULL) + return NULL; + + /* Start with good guess of number of elements */ + for (i = 0; attrs[i]; i++); + + ret = talloc_array(module, const char *, i); + ar_size = i; + + for (i = 0; attrs[i]; i++) { + int j; + const struct ldb_map_attribute *attr = map_find_attr_local(privdat, attrs[i]); + enum ldb_map_attr_type map_type; + + if (!attr) { + ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Local attribute '%s' does not have a definition!\n", attrs[i]); + map_type = MAP_IGNORE; + } else map_type = attr->type; + + switch (map_type) + { + case MAP_IGNORE: break; + case MAP_KEEP: + if (last_element >= ar_size) { + ret = talloc_realloc(module, ret, const char *, ar_size+1); + ar_size++; + } + ret[last_element] = attr->local_name; + last_element++; + break; + + case MAP_RENAME: + case MAP_CONVERT: + if (last_element >= ar_size) { + ret = talloc_realloc(module, ret, const char *, ar_size+1); + ar_size++; + } + ret[last_element] = attr->u.rename.remote_name; + last_element++; + break; + + case MAP_GENERATE: + /* Add remote_names[] for this attribute to the list of + * attributes to request from the remote server */ + for (j = 0; attr->u.generate.remote_names[j]; j++) { + if (last_element >= ar_size) { + ret = talloc_realloc(module, ret, const char *, ar_size+1); + ar_size++; + } + ret[last_element] = attr->u.generate.remote_names[j]; + last_element++; + } + break; + } + } + + if (last_element >= ar_size) { + ret = talloc_realloc(module, ret, const char *, ar_size+1); + ar_size++; + } + + ret[last_element] = NULL; + + return ret; +} + +static const char **available_local_attributes(struct ldb_module *module, const struct ldb_message *msg) +{ + struct ldb_map_context *privdat = map_get_privdat(module); + int i, j; + int count = 0; + const char **ret = talloc_array(module, const char *, 1); + + ret[0] = NULL; + + for (i = 0; privdat->attribute_maps[i].local_name; i++) { + BOOL avail = False; + const struct ldb_map_attribute *attr = &privdat->attribute_maps[i]; + + /* If all remote attributes for this attribute are present, add the + * local one to the list */ + + switch (attr->type) { + case MAP_IGNORE: break; + case MAP_KEEP: + avail = (ldb_msg_find_ldb_val(msg, attr->local_name) != NULL); + break; + + case MAP_RENAME: + case MAP_CONVERT: + avail = (ldb_msg_find_ldb_val(msg, attr->u.rename.remote_name) != NULL); + break; + + case MAP_GENERATE: + avail = True; + for (j = 0; attr->u.generate.remote_names[j]; j++) { + avail &= (ldb_msg_find_ldb_val(msg, attr->u.generate.remote_names[j]) != NULL); + } + break; + } + + if (!avail) + continue; + + ret = talloc_realloc(module, ret, const char *, count+2); + ret[count] = attr->local_name; + ret[count+1] = NULL; + count++; + } + + return ret; +} + +/* Used for search */ +static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, const char * const*attrs, const struct ldb_message *mi) +{ + int i, j; + struct ldb_message *msg = talloc_zero(module, struct ldb_message); + struct ldb_message_element *elm, *oldelm; + struct ldb_map_context *privdat = map_get_privdat(module); + const char **newattrs = NULL; + + msg->dn = map_remote_dn(privdat, module, mi->dn); + + ldb_msg_add_string(module->ldb, msg, "mappedFromDn", ldb_dn_linearize(msg, mi->dn)); + + /* Loop over attrs, find in ldb_map_attribute array and + * run generate() */ + + if (attrs == NULL) { + /* Generate list of the local attributes that /can/ be generated + * using the specific remote attributes */ + + attrs = newattrs = available_local_attributes(module, mi); + } + + for (i = 0; attrs[i]; i++) { + const struct ldb_map_attribute *attr = map_find_attr_local(privdat, attrs[i]); + enum ldb_map_attr_type map_type; + + if (!attr) { + ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Unable to find local attribute '%s' when generating incoming message\n", attrs[i]); + map_type = MAP_IGNORE; + } else map_type = attr->type; + + switch (map_type) { + case MAP_IGNORE:break; + case MAP_RENAME: + oldelm = ldb_msg_find_element(mi, attr->u.rename.remote_name); + if (!oldelm) continue; + + elm = talloc(msg, struct ldb_message_element); + elm->name = talloc_strdup(elm, attr->local_name); + elm->num_values = oldelm->num_values; + elm->values = talloc_reference(elm, oldelm->values); + + ldb_msg_add(module->ldb, msg, elm, oldelm->flags); + break; + + case MAP_CONVERT: + oldelm = ldb_msg_find_element(mi, attr->u.rename.remote_name); + if (!oldelm) continue; + + elm = talloc(msg, struct ldb_message_element); + elm->name = talloc_strdup(elm, attr->local_name); + elm->num_values = oldelm->num_values; + elm->values = talloc_array(elm, struct ldb_val, elm->num_values); + + for (j = 0; j < oldelm->num_values; j++) + elm->values[j] = attr->u.convert.convert_remote(privdat, elm, &oldelm->values[j]); + + ldb_msg_add(module->ldb, msg, elm, oldelm->flags); + break; + + case MAP_KEEP: + oldelm = ldb_msg_find_element(mi, attr->local_name); + if (!oldelm) continue; + + elm = talloc(msg, struct ldb_message_element); + + elm->num_values = oldelm->num_values; + elm->values = talloc_reference(elm, oldelm->values); + elm->name = talloc_strdup(elm, oldelm->name); + + ldb_msg_add(module->ldb, msg, elm, oldelm->flags); + break; + + case MAP_GENERATE: + elm = attr->u.generate.generate_local(privdat, msg, attr->local_name, mi); + if (!elm) continue; + + ldb_msg_add(module->ldb, msg, elm, elm->flags); + break; + default: + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Unknown attr->type for %s", attr->local_name); + break; + } + } + + talloc_free(newattrs); + + return msg; +} + +/* Used for add, modify */ +static int ldb_map_message_outgoing(struct ldb_module *module, const struct ldb_message *mo, struct ldb_message **fb, struct ldb_message **mp) +{ + struct ldb_map_context *privdat = map_get_privdat(module); + struct ldb_message *msg = talloc_zero(module, struct ldb_message); + struct ldb_message_element *elm; + int i,j; + + *fb = talloc_zero(module, struct ldb_message); + (*fb)->dn = talloc_reference(*fb, mo->dn); + + *mp = msg; + + msg->private_data = mo->private_data; + + msg->dn = map_local_dn(privdat, module, mo->dn); + + /* Loop over mi and call generate_remote for each attribute */ + for (i = 0; i < mo->num_elements; i++) { + const struct ldb_map_attribute *attr = map_find_attr_local(privdat, mo->elements[i].name); + enum ldb_map_attr_type map_type; + + if (!attr) { + ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Undefined local attribute '%s', ignoring\n", mo->elements[i].name); + map_type = MAP_IGNORE; + continue; + } else map_type = attr->type; + + switch (map_type) { + case MAP_IGNORE: /* Add to fallback message */ + elm = talloc(*fb, struct ldb_message_element); + + elm->num_values = mo->elements[i].num_values; + elm->values = talloc_reference(elm, mo->elements[i].values); + elm->name = talloc_strdup(elm, mo->elements[i].name); + + ldb_msg_add(module->ldb, *fb, elm, mo->elements[i].flags); + break; + case MAP_RENAME: + elm = talloc(msg, struct ldb_message_element); + + elm->name = talloc_strdup(elm, attr->u.rename.remote_name); + elm->num_values = mo->elements[i].num_values; + elm->values = talloc_reference(elm, mo->elements[i].values); + + ldb_msg_add(module->ldb, msg, elm, mo->elements[i].flags); + break; + + case MAP_CONVERT: + elm = talloc(msg, struct ldb_message_element); + + elm->name = talloc_strdup(elm, attr->u.rename.remote_name); + elm->num_values = mo->elements[i].num_values; + elm->values = talloc_array(elm, struct ldb_val, elm->num_values); + + for (j = 0; j < elm->num_values; j++) { + elm->values[j] = attr->u.convert.convert_local(privdat, msg, &mo->elements[i].values[j]); + } + + ldb_msg_add(module->ldb, msg, elm, mo->elements[i].flags); + break; + + case MAP_KEEP: + elm = talloc(msg, struct ldb_message_element); + + elm->num_values = mo->elements[i].num_values; + elm->values = talloc_reference(elm, mo->elements[i].values); + elm->name = talloc_strdup(elm, mo->elements[i].name); + + ldb_msg_add(module->ldb, msg, elm, mo->elements[i].flags); + break; + + case MAP_GENERATE: + attr->u.generate.generate_remote(privdat, attr->local_name, mo, msg); + break; + } + } + + return 0; +} + + +/* + rename a record +*/ +static int map_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn) +{ + struct ldb_map_context *privdat = map_get_privdat(module); + struct ldb_dn *n_olddn, *n_newdn; + int ret; + + ret = ldb_next_rename_record(module, olddn, newdn); + + n_olddn = map_local_dn(privdat, module, olddn); + n_newdn = map_local_dn(privdat, module, newdn); + + ret = ldb_rename(privdat->mapped_ldb, n_olddn, n_newdn); + + talloc_free(n_olddn); + talloc_free(n_newdn); + + return ret; +} + +/* + delete a record +*/ +static int map_delete(struct ldb_module *module, const struct ldb_dn *dn) +{ + struct ldb_map_context *privdat = map_get_privdat(module); + struct ldb_dn *newdn; + int ret; + + ret = ldb_next_delete_record(module, dn); + + newdn = map_local_dn(privdat, module, dn); + + ret = ldb_delete(privdat->mapped_ldb, newdn); + + talloc_free(newdn); + + return ret; +} + +/* search fallback database */ +static int map_search_bytree_fb(struct ldb_module *module, const struct ldb_dn *base, + enum ldb_scope scope, struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res) +{ + int ret; + struct ldb_parse_tree t_and, t_not, t_present, *childs[2]; + + t_present.operation = LDB_OP_PRESENT; + t_present.u.present.attr = talloc_strdup(NULL, "isMapped"); + + t_not.operation = LDB_OP_NOT; + t_not.u.isnot.child = &t_present; + + childs[0] = &t_not; + childs[1] = tree; + t_and.operation = LDB_OP_AND; + t_and.u.list.num_elements = 2; + t_and.u.list.elements = childs; + + ret = ldb_next_search_bytree(module, base, scope, &t_and, attrs, res); + + talloc_free(t_present.u.present.attr); + + return ret; +} + +static int map_search_bytree_mp(struct ldb_module *module, const struct ldb_dn *base, + enum ldb_scope scope, struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res) +{ + struct ldb_parse_tree *new_tree; + struct ldb_dn *new_base; + struct ldb_message **newres; + const char **newattrs; + int mpret, ret; + struct ldb_map_context *privdat = map_get_privdat(module); + int i; + + /*- search mapped database */ + + new_tree = ldb_map_parse_tree(module, module, tree); + newattrs = ldb_map_attrs(module, attrs); + new_base = map_local_dn(privdat, module, base); + + mpret = ldb_search_bytree(privdat->mapped_ldb, new_base, scope, new_tree, newattrs, &newres); + + talloc_free(new_base); + talloc_free(new_tree); + talloc_free(newattrs); + + if (mpret == -1) { + struct map_private *map_private = module->private_data; + map_private->last_err_string = ldb_errstring(privdat->mapped_ldb); + return -1; + } + + /* + - per returned record, search fallback database for additional data (by dn) + - test if (full expression) is now true + */ + + *res = talloc_array(module, struct ldb_message *, mpret); + + ret = 0; + + for (i = 0; i < mpret; i++) { + struct ldb_message *merged = ldb_map_message_incoming(module, attrs, newres[i]); + struct ldb_message **extrares = NULL; + int extraret; + + /* Merge with additional data from local database */ + extraret = ldb_next_search(module, merged->dn, LDB_SCOPE_BASE, "", NULL, &extrares); + + if (extraret == -1) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Error searching for extra data!\n"); + } else if (extraret > 1) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "More than one result for extra data!\n"); + talloc_free(newres); + return -1; + } else if (extraret == 0) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "No extra data found for remote DN"); + } + + if (extraret == 1) { + int j; + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Extra data found for remote DN"); + for (j = 0; j < extrares[0]->num_elements; j++) { + ldb_msg_add(module->ldb, merged, &(extrares[0]->elements[j]), extrares[0]->elements[j].flags); + } + + ldb_msg_add_string(module->ldb, merged, "extraMapped", "TRUE"); + } else { + ldb_msg_add_string(module->ldb, merged, "extraMapped", "FALSE"); + } + + if (ldb_match_msg(module->ldb, merged, tree, base, scope)) { + (*res)[ret] = merged; + ret++; + } else { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Discarded merged message because it did not match"); + } + } + + talloc_free(newres); + + return ret; +} + + +/* + search for matching records using a ldb_parse_tree +*/ +static int map_search_bytree(struct ldb_module *module, const struct ldb_dn *base, + enum ldb_scope scope, struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res) +{ + struct ldb_message **fbres, **mpres; + int i; + int ret_fb, ret_mp; + + ret_fb = map_search_bytree_fb(module, base, scope, tree, attrs, &fbres); + if (ret_fb == -1) + return -1; + + ret_mp = map_search_bytree_mp(module, base, scope, tree, attrs, &mpres); + if (ret_mp == -1) { + return -1; + } + + /* Merge results */ + *res = talloc_array(module, struct ldb_message *, ret_fb + ret_mp); + + for (i = 0; i < ret_fb; i++) (*res)[i] = fbres[i]; + for (i = 0; i < ret_mp; i++) (*res)[ret_fb+i] = mpres[i]; + + return ret_fb + ret_mp; +} +/* + search for matching records +*/ +static int map_search(struct ldb_module *module, const struct ldb_dn *base, + enum ldb_scope scope, const char *expression, + const char * const *attrs, struct ldb_message ***res) +{ + struct map_private *map = module->private_data; + struct ldb_parse_tree *tree; + int ret; + + tree = ldb_parse_tree(NULL, expression); + if (tree == NULL) { + map->last_err_string = "expression parse failed"; + return -1; + } + + ret = map_search_bytree(module, base, scope, tree, attrs, res); + talloc_free(tree); + return ret; +} + +/* + add a record +*/ +static int map_add(struct ldb_module *module, const struct ldb_message *msg) +{ + int ret; + struct ldb_map_context *privdat = map_get_privdat(module); + struct ldb_message *fb, *mp; + + if (!map_is_mappable(privdat, msg)) { + return ldb_next_add_record(module, msg); + } + + if (ldb_map_message_outgoing(module, msg, &fb, &mp) == -1) + return -1; + + ldb_msg_add_string(module->ldb, fb, "isMapped", "TRUE"); + + ret = ldb_next_add_record(module, fb); + if (ret == -1) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Adding fallback record failed"); + return -1; + } + + ret = ldb_add(privdat->mapped_ldb, mp); + if (ret == -1) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Adding mapped record failed"); + return -1; + } + + talloc_free(fb); + talloc_free(mp); + + return ret; +} + + +/* + modify a record +*/ +static int map_modify(struct ldb_module *module, const struct ldb_message *msg) +{ + struct ldb_map_context *privdat = map_get_privdat(module); + struct ldb_message *fb, *mp; + int ret; + + if (!map_is_mappable(privdat, msg)) + return ldb_next_modify_record(module, msg); + + + if (ldb_map_message_outgoing(module, msg, &fb, &mp) == -1) + return -1; + + ldb_msg_add_string(module->ldb, fb, "isMapped", "TRUE"); + + ret = ldb_next_modify_record(module, fb); + + ret = ldb_modify(privdat->mapped_ldb, mp); + + talloc_free(fb); + talloc_free(mp); + + return ret; +} + +static int map_lock(struct ldb_module *module, const char *lockname) +{ + return ldb_next_named_lock(module, lockname); +} + +static int map_unlock(struct ldb_module *module, const char *lockname) +{ + return ldb_next_named_unlock(module, lockname); +} + +/* + return extended error information +*/ +static const char *map_errstring(struct ldb_module *module) +{ + struct map_private *map = module->private_data; + + if (map->last_err_string) + return map->last_err_string; + + return ldb_next_errstring(module); +} + +static const struct ldb_module_ops map_ops = { + .name = "map", + .search = map_search, + .search_bytree = map_search_bytree, + .add_record = map_add, + .modify_record = map_modify, + .delete_record = map_delete, + .rename_record = map_rename, + .named_lock = map_lock, + .named_unlock = map_unlock, + .errstring = map_errstring +}; + +static char *map_find_url(struct ldb_context *ldb, const char *name) +{ + const char * const attrs[] = { "@MAP_URL" , NULL}; + struct ldb_message **msg = NULL; + struct ldb_dn *mods; + char *url; + int ret; + + mods = ldb_dn_string_compose(ldb, NULL, "@MAP=%s", name); + if (mods == NULL) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "Can't construct DN"); + return NULL; + } + + ret = ldb_search(ldb, mods, LDB_SCOPE_BASE, "", attrs, &msg); + talloc_free(mods); + if (ret < 1) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "Not enough results found looking for @MAP"); + return NULL; + } + + url = talloc_strdup(ldb, ldb_msg_find_string(msg[0], "@MAP_URL", NULL)); + + talloc_free(msg); + + return url; +} + +/* the init function */ +struct ldb_module *ldb_map_init(struct ldb_context *ldb, const struct ldb_map_attribute *attrs, const struct ldb_map_objectclass *ocls, const char *name) +{ + int i, j; + struct ldb_module *ctx; + struct map_private *data; + char *url; + + ctx = talloc(ldb, struct ldb_module); + if (!ctx) + return NULL; + + data = talloc(ctx, struct map_private); + if (!data) { + talloc_free(ctx); + return NULL; + } + + data->context.mapped_ldb = ldb_init(data); + url = map_find_url(ldb, name); + + if (!url) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "@MAP=%s not set!\n", name); + return NULL; + } + + if (ldb_connect(data->context.mapped_ldb, url, 0, NULL) != 0) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "Unable to open mapped database for %s at '%s'\n", name, url); + return NULL; + } + + talloc_free(url); + + data->last_err_string = NULL; + + /* Get list of attribute maps */ + j = 0; + data->context.attribute_maps = NULL; + + for (i = 0; attrs[i].local_name; i++) { + data->context.attribute_maps = talloc_realloc(data, data->context.attribute_maps, struct ldb_map_attribute, j+1); + data->context.attribute_maps[j] = attrs[i]; + j++; + } + + for (i = 0; builtin_attribute_maps[i].local_name; i++) { + data->context.attribute_maps = talloc_realloc(data, data->context.attribute_maps, struct ldb_map_attribute, j+1); + data->context.attribute_maps[j] = builtin_attribute_maps[i]; + j++; + } + + data->context.attribute_maps = talloc_realloc(data, data->context.attribute_maps, struct ldb_map_attribute, j+1); + ZERO_STRUCT(data->context.attribute_maps[j].local_name); + + data->context.objectclass_maps = ocls; + ctx->private_data = data; + ctx->ldb = ldb; + ctx->prev = ctx->next = NULL; + ctx->ops = &map_ops; + + return ctx; +} + +static struct ldb_val map_convert_local_dn(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) +{ + struct ldb_dn *dn, *newdn;; + struct ldb_val *newval; + + dn = ldb_dn_explode(ctx, (char *)val->data); + + newdn = map_local_dn(map, ctx, dn); + + talloc_free(dn); + + newval = talloc(ctx, struct ldb_val); + newval->data = (uint8_t *)ldb_dn_linearize(ctx, newdn); + newval->length = strlen((char *)newval->data); + + talloc_free(newdn); + + return *newval; +} + +static struct ldb_val map_convert_remote_dn(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) +{ + struct ldb_dn *dn, *newdn;; + struct ldb_val *newval; + + dn = ldb_dn_explode(ctx, (char *)val->data); + + newdn = map_remote_dn(map, ctx, dn); + + talloc_free(dn); + + newval = talloc(ctx, struct ldb_val); + newval->data = (uint8_t *)ldb_dn_linearize(ctx, newdn); + newval->length = strlen((char *)newval->data); + + talloc_free(newdn); + + return *newval; +} + +static struct ldb_val map_convert_local_objectclass(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) +{ + int i; + + for (i = 0; map->objectclass_maps[i].local_name; i++) { + if (!strcmp(map->objectclass_maps[i].local_name, (char *)val->data)) { + struct ldb_val newval; + newval.data = (uint8_t*)talloc_strdup(ctx, map->objectclass_maps[i].remote_name); + newval.length = strlen((char *)newval.data); + + return ldb_val_dup(ctx, &newval); + } + } + + return ldb_val_dup(ctx, val); +} + +static struct ldb_val map_convert_remote_objectclass(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) +{ + int i; + + for (i = 0; map->objectclass_maps[i].remote_name; i++) { + if (!strcmp(map->objectclass_maps[i].remote_name, (char *)val->data)) { + struct ldb_val newval; + newval.data = (uint8_t*)talloc_strdup(ctx, map->objectclass_maps[i].local_name); + newval.length = strlen((char *)newval.data); + + return ldb_val_dup(ctx, &newval); + } + } + + return ldb_val_dup(ctx, val); +} + +static const struct ldb_map_attribute builtin_attribute_maps[] = { + { + .local_name = "dn", + .type = MAP_CONVERT, + .u.convert.remote_name = "dn", + .u.convert.convert_local = map_convert_local_dn, + .u.convert.convert_remote = map_convert_remote_dn, + }, + { + .local_name = "objectclass", + .type = MAP_CONVERT, + .u.convert.remote_name = "objectclass", + .u.convert.convert_local = map_convert_local_objectclass, + .u.convert.convert_remote = map_convert_remote_objectclass, + }, + { + .local_name = NULL, + } +}; + diff --git a/source4/lib/ldb/modules/ldb_map.h b/source4/lib/ldb/modules/ldb_map.h new file mode 100644 index 0000000000..02fec649c6 --- /dev/null +++ b/source4/lib/ldb/modules/ldb_map.h @@ -0,0 +1,108 @@ +/* + ldb database library - map backend + + Copyright (C) Jelmer Vernooij 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __LDB_MAP_H__ +#define __LDB_MAP_H__ + +/* ldb_map is a skeleton LDB module that can be used for any other modules + * that need to map attributes. + * + * The term 'remote' in this header refers to the connection where the + * original schema is used on while 'local' means the local connection + * that any upper layers will use. + * + * All local attributes will have to have a definition. Not all remote + * attributes need a definition as LDB is a lot less stricter then LDAP + * (in other words, sending unknown attributes to an LDAP server hurts us, + * returning too much attributes in ldb_search() doesn't) + */ + +struct ldb_map_context; + +struct ldb_map_attribute +{ + const char *local_name; /* local name */ + + enum ldb_map_attr_type { + MAP_IGNORE, /* Ignore this local attribute. Doesn't exist remotely. */ + MAP_KEEP, /* Keep as is. Same name locally and remotely. */ + MAP_RENAME, /* Simply rename the attribute. Name changes, data is the same */ + MAP_CONVERT, /* Rename + convert data */ + MAP_GENERATE /* Use generate function for generating new name/data. + Used for generating attributes based on + multiple remote attributes. */ + } type; + + /* if set, will be called for expressions that contain this attribute */ + struct ldb_parse_tree *(*convert_operator) (struct ldb_map_context *, TALLOC_CTX *ctx, const struct ldb_parse_tree *); + + union { + struct { + const char *remote_name; + } rename; + + struct { + const char *remote_name; + struct ldb_val (*convert_local) (struct ldb_map_context *, TALLOC_CTX *, const struct ldb_val *); + struct ldb_val (*convert_remote) (struct ldb_map_context *, TALLOC_CTX *, const struct ldb_val *); + } convert; + + struct { + /* Generate the local attribute from remote message */ + struct ldb_message_element *(*generate_local) ( + struct ldb_map_context *, + TALLOC_CTX *ctx, + const char *attr, + const struct ldb_message *remote); + + /* Update remote message with information from local message */ + void (*generate_remote) ( + struct ldb_map_context *, + const char *local_attr, + const struct ldb_message *local, + struct ldb_message *remote); + + /* Name(s) for this attribute on the remote server. This is an array since + * one local attribute's data can be split up into several attributes + * remotely */ +#define LDB_MAP_MAX_REMOTE_NAMES 10 + const char *remote_names[LDB_MAP_MAX_REMOTE_NAMES]; + } generate; + } u; +}; + +struct ldb_map_objectclass +{ + const char *local_name; + const char *remote_name; +}; + +struct ldb_map_context +{ + struct ldb_map_attribute *attribute_maps; + const struct ldb_map_objectclass *objectclass_maps; + struct ldb_context *mapped_ldb; +}; + +#endif /* __LDB_MAP_H__ */ -- cgit From 81e130b592d128a1dc1e9f2abf91b1e376512b88 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 30 Aug 2005 11:37:58 +0000 Subject: r9789: Patch from Volker that fixes the build on AIX. (This used to be commit 9a1a7fb60e6531ff74e6817313548f3cee37a990) --- source4/lib/ldb/modules/ldb_map.c | 53 +++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 21 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index 531d5ccd67..c5ddcc7e13 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -50,7 +50,38 @@ - rename locally and remotely */ -static const struct ldb_map_attribute builtin_attribute_maps[]; +static struct ldb_val map_convert_local_dn(struct ldb_map_context *map, + TALLOC_CTX *ctx, + const struct ldb_val *val); +static struct ldb_val map_convert_remote_dn(struct ldb_map_context *map, + TALLOC_CTX *ctx, + const struct ldb_val *val); +static struct ldb_val map_convert_local_objectclass(struct ldb_map_context *map, + TALLOC_CTX *ctx, + const struct ldb_val *val); +static struct ldb_val map_convert_remote_objectclass(struct ldb_map_context *map, + TALLOC_CTX *ctx, + const struct ldb_val *val); + +static const struct ldb_map_attribute builtin_attribute_maps[] = { + { + .local_name = "dn", + .type = MAP_CONVERT, + .u.convert.remote_name = "dn", + .u.convert.convert_local = map_convert_local_dn, + .u.convert.convert_remote = map_convert_remote_dn, + }, + { + .local_name = "objectclass", + .type = MAP_CONVERT, + .u.convert.remote_name = "objectclass", + .u.convert.convert_local = map_convert_local_objectclass, + .u.convert.convert_remote = map_convert_remote_objectclass, + }, + { + .local_name = NULL, + } +}; struct map_private { struct ldb_map_context context; @@ -1129,23 +1160,3 @@ static struct ldb_val map_convert_remote_objectclass(struct ldb_map_context *map return ldb_val_dup(ctx, val); } -static const struct ldb_map_attribute builtin_attribute_maps[] = { - { - .local_name = "dn", - .type = MAP_CONVERT, - .u.convert.remote_name = "dn", - .u.convert.convert_local = map_convert_local_dn, - .u.convert.convert_remote = map_convert_remote_dn, - }, - { - .local_name = "objectclass", - .type = MAP_CONVERT, - .u.convert.remote_name = "objectclass", - .u.convert.convert_local = map_convert_local_objectclass, - .u.convert.convert_remote = map_convert_remote_objectclass, - }, - { - .local_name = NULL, - } -}; - -- cgit From 84bfcd3c78afefd8d2869c695c116c9df7ee03c4 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 31 Aug 2005 18:33:57 +0000 Subject: r9835: Make ldb_map compile in the stand-alone LDB build (This used to be commit 2283a336e0e31e6857621d9806bba54c400bd986) --- source4/lib/ldb/modules/ldb_map.c | 81 ++++++++++++++++++++------------------- source4/lib/ldb/modules/ldb_map.h | 8 ++-- 2 files changed, 46 insertions(+), 43 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index c5ddcc7e13..f40506c03b 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -23,9 +23,9 @@ */ #include "includes.h" -#include "lib/ldb/include/ldb.h" -#include "lib/ldb/include/ldb_private.h" -#include "lib/ldb/modules/ldb_map.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" +#include "ldb/modules/ldb_map.h" /* TODO: * - objectclass hint in ldb_map_attribute @@ -50,16 +50,16 @@ - rename locally and remotely */ -static struct ldb_val map_convert_local_dn(struct ldb_map_context *map, +static struct ldb_val map_convert_local_dn(struct ldb_module *map, TALLOC_CTX *ctx, const struct ldb_val *val); -static struct ldb_val map_convert_remote_dn(struct ldb_map_context *map, +static struct ldb_val map_convert_remote_dn(struct ldb_module *map, TALLOC_CTX *ctx, const struct ldb_val *val); -static struct ldb_val map_convert_local_objectclass(struct ldb_map_context *map, +static struct ldb_val map_convert_local_objectclass(struct ldb_module *map, TALLOC_CTX *ctx, const struct ldb_val *val); -static struct ldb_val map_convert_remote_objectclass(struct ldb_map_context *map, +static struct ldb_val map_convert_remote_objectclass(struct ldb_module *map, TALLOC_CTX *ctx, const struct ldb_val *val); @@ -106,22 +106,22 @@ static const struct ldb_map_objectclass *map_find_objectclass_local(struct ldb_m /* Decide whether a add/modify should be pushed to the * remote LDAP server. We currently only do this if we see an objectClass we know */ -static BOOL map_is_mappable(struct ldb_map_context *privdat, const struct ldb_message *msg) +static int map_is_mappable(struct ldb_map_context *privdat, const struct ldb_message *msg) { int i; struct ldb_message_element *el = ldb_msg_find_element(msg, "objectClass"); /* No objectClass... */ if (el == NULL) { - return False; + return 0; } for (i = 0; i < el->num_values; i++) { if (map_find_objectclass_local(privdat, (char *)el->values[i].data)) - return True; + return 1; } - return False; + return 0; } /* find an attribute by the local name */ @@ -269,7 +269,7 @@ static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, TALL } if (map_type == MAP_CONVERT) { - newvalue = attr->u.convert.convert_local(privdat, new_tree, &value); + newvalue = attr->u.convert.convert_local(module, new_tree, &value); } else { newvalue = ldb_val_dup(new_tree, &value); } @@ -288,7 +288,7 @@ static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, TALL } /* Remote DN -> Local DN */ -static struct ldb_dn *map_remote_dn(struct ldb_map_context *privdat, TALLOC_CTX *ctx, const struct ldb_dn *dn) +static struct ldb_dn *map_remote_dn(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_dn *dn) { struct ldb_dn *newdn; int i; @@ -309,7 +309,7 @@ static struct ldb_dn *map_remote_dn(struct ldb_map_context *privdat, TALLOC_CTX * complete rdn */ for (i = 0; i < dn->comp_num; i++) { - const struct ldb_map_attribute *attr = map_find_attr_remote(privdat, dn->components[i].name); + const struct ldb_map_attribute *attr = map_find_attr_remote(module->private_data, dn->components[i].name); enum ldb_map_attr_type map_type; /* Unknown attribute - leave this dn as is and hope the best... */ @@ -319,7 +319,7 @@ static struct ldb_dn *map_remote_dn(struct ldb_map_context *privdat, TALLOC_CTX switch (map_type) { case MAP_IGNORE: case MAP_GENERATE: - DEBUG(0, ("Local MAP_IGNORE or MAP_GENERATE attribute '%s' used in DN!", dn->components[i].name)); + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Local MAP_IGNORE or MAP_GENERATE attribute '%s' used in DN!", dn->components[i].name); talloc_free(newdn); return NULL; @@ -330,7 +330,7 @@ static struct ldb_dn *map_remote_dn(struct ldb_map_context *privdat, TALLOC_CTX case MAP_CONVERT: newdn->components[i].name = talloc_strdup(newdn->components, attr->local_name); - newdn->components[i].value = attr->u.convert.convert_remote(privdat, ctx, &dn->components[i].value); + newdn->components[i].value = attr->u.convert.convert_remote(module, ctx, &dn->components[i].value); break; case MAP_RENAME: @@ -343,7 +343,7 @@ static struct ldb_dn *map_remote_dn(struct ldb_map_context *privdat, TALLOC_CTX } /* Local DN -> Remote DN */ -static struct ldb_dn *map_local_dn(struct ldb_map_context *privdat, TALLOC_CTX *ctx, const struct ldb_dn *dn) +static struct ldb_dn *map_local_dn(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_dn *dn) { struct ldb_dn *newdn; int i; @@ -364,7 +364,7 @@ static struct ldb_dn *map_local_dn(struct ldb_map_context *privdat, TALLOC_CTX * * complete rdn using an equality convert_operator call */ for (i = 0; i < dn->comp_num; i++) { - const struct ldb_map_attribute *attr = map_find_attr_local(privdat, dn->components[i].name); + const struct ldb_map_attribute *attr = map_find_attr_local(module->private_data, dn->components[i].name); enum ldb_map_attr_type map_type; /* Unknown attribute - leave this dn as is and hope the best... */ @@ -374,13 +374,13 @@ static struct ldb_dn *map_local_dn(struct ldb_map_context *privdat, TALLOC_CTX * { case MAP_IGNORE: case MAP_GENERATE: - DEBUG(0, ("Local MAP_IGNORE/MAP_GENERATE attribute '%s' used in DN!", dn->components[i].name)); + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Local MAP_IGNORE/MAP_GENERATE attribute '%s' used in DN!", dn->components[i].name); talloc_free(newdn); return NULL; case MAP_CONVERT: newdn->components[i].name = talloc_strdup(newdn->components, attr->u.convert.remote_name); - newdn->components[i].value = attr->u.convert.convert_local(privdat, newdn->components, &dn->components[i].value); + newdn->components[i].value = attr->u.convert.convert_local(module, newdn->components, &dn->components[i].value); break; case MAP_RENAME: @@ -482,7 +482,7 @@ static const char **available_local_attributes(struct ldb_module *module, const ret[0] = NULL; for (i = 0; privdat->attribute_maps[i].local_name; i++) { - BOOL avail = False; + int avail = 0; const struct ldb_map_attribute *attr = &privdat->attribute_maps[i]; /* If all remote attributes for this attribute are present, add the @@ -500,7 +500,7 @@ static const char **available_local_attributes(struct ldb_module *module, const break; case MAP_GENERATE: - avail = True; + avail = 1; for (j = 0; attr->u.generate.remote_names[j]; j++) { avail &= (ldb_msg_find_ldb_val(msg, attr->u.generate.remote_names[j]) != NULL); } @@ -528,7 +528,7 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c struct ldb_map_context *privdat = map_get_privdat(module); const char **newattrs = NULL; - msg->dn = map_remote_dn(privdat, module, mi->dn); + msg->dn = map_remote_dn(module, module, mi->dn); ldb_msg_add_string(module->ldb, msg, "mappedFromDn", ldb_dn_linearize(msg, mi->dn)); @@ -575,7 +575,7 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c elm->values = talloc_array(elm, struct ldb_val, elm->num_values); for (j = 0; j < oldelm->num_values; j++) - elm->values[j] = attr->u.convert.convert_remote(privdat, elm, &oldelm->values[j]); + elm->values[j] = attr->u.convert.convert_remote(module, elm, &oldelm->values[j]); ldb_msg_add(module->ldb, msg, elm, oldelm->flags); break; @@ -594,7 +594,7 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c break; case MAP_GENERATE: - elm = attr->u.generate.generate_local(privdat, msg, attr->local_name, mi); + elm = attr->u.generate.generate_local(module, msg, attr->local_name, mi); if (!elm) continue; ldb_msg_add(module->ldb, msg, elm, elm->flags); @@ -625,7 +625,7 @@ static int ldb_map_message_outgoing(struct ldb_module *module, const struct ldb_ msg->private_data = mo->private_data; - msg->dn = map_local_dn(privdat, module, mo->dn); + msg->dn = map_local_dn(module, module, mo->dn); /* Loop over mi and call generate_remote for each attribute */ for (i = 0; i < mo->num_elements; i++) { @@ -666,7 +666,7 @@ static int ldb_map_message_outgoing(struct ldb_module *module, const struct ldb_ elm->values = talloc_array(elm, struct ldb_val, elm->num_values); for (j = 0; j < elm->num_values; j++) { - elm->values[j] = attr->u.convert.convert_local(privdat, msg, &mo->elements[i].values[j]); + elm->values[j] = attr->u.convert.convert_local(module, msg, &mo->elements[i].values[j]); } ldb_msg_add(module->ldb, msg, elm, mo->elements[i].flags); @@ -683,7 +683,7 @@ static int ldb_map_message_outgoing(struct ldb_module *module, const struct ldb_ break; case MAP_GENERATE: - attr->u.generate.generate_remote(privdat, attr->local_name, mo, msg); + attr->u.generate.generate_remote(module, attr->local_name, mo, msg); break; } } @@ -703,8 +703,8 @@ static int map_rename(struct ldb_module *module, const struct ldb_dn *olddn, con ret = ldb_next_rename_record(module, olddn, newdn); - n_olddn = map_local_dn(privdat, module, olddn); - n_newdn = map_local_dn(privdat, module, newdn); + n_olddn = map_local_dn(module, module, olddn); + n_newdn = map_local_dn(module, module, newdn); ret = ldb_rename(privdat->mapped_ldb, n_olddn, n_newdn); @@ -725,7 +725,7 @@ static int map_delete(struct ldb_module *module, const struct ldb_dn *dn) ret = ldb_next_delete_record(module, dn); - newdn = map_local_dn(privdat, module, dn); + newdn = map_local_dn(module, module, dn); ret = ldb_delete(privdat->mapped_ldb, newdn); @@ -777,7 +777,7 @@ static int map_search_bytree_mp(struct ldb_module *module, const struct ldb_dn * new_tree = ldb_map_parse_tree(module, module, tree); newattrs = ldb_map_attrs(module, attrs); - new_base = map_local_dn(privdat, module, base); + new_base = map_local_dn(module, module, base); mpret = ldb_search_bytree(privdat->mapped_ldb, new_base, scope, new_tree, newattrs, &newres); @@ -1042,6 +1042,7 @@ struct ldb_module *ldb_map_init(struct ldb_context *ldb, const struct ldb_map_at } data->context.mapped_ldb = ldb_init(data); + ldb_set_debug(data->context.mapped_ldb, ldb->debug_ops.debug, ldb->debug_ops.context); url = map_find_url(ldb, name); if (!url) { @@ -1075,7 +1076,7 @@ struct ldb_module *ldb_map_init(struct ldb_context *ldb, const struct ldb_map_at } data->context.attribute_maps = talloc_realloc(data, data->context.attribute_maps, struct ldb_map_attribute, j+1); - ZERO_STRUCT(data->context.attribute_maps[j].local_name); + memset(&data->context.attribute_maps[j], 0, sizeof(struct ldb_map_attribute)); data->context.objectclass_maps = ocls; ctx->private_data = data; @@ -1086,14 +1087,14 @@ struct ldb_module *ldb_map_init(struct ldb_context *ldb, const struct ldb_map_at return ctx; } -static struct ldb_val map_convert_local_dn(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) +static struct ldb_val map_convert_local_dn(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val) { struct ldb_dn *dn, *newdn;; struct ldb_val *newval; dn = ldb_dn_explode(ctx, (char *)val->data); - newdn = map_local_dn(map, ctx, dn); + newdn = map_local_dn(module, ctx, dn); talloc_free(dn); @@ -1106,14 +1107,14 @@ static struct ldb_val map_convert_local_dn(struct ldb_map_context *map, TALLOC_C return *newval; } -static struct ldb_val map_convert_remote_dn(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) +static struct ldb_val map_convert_remote_dn(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val) { struct ldb_dn *dn, *newdn;; struct ldb_val *newval; dn = ldb_dn_explode(ctx, (char *)val->data); - newdn = map_remote_dn(map, ctx, dn); + newdn = map_remote_dn(module, ctx, dn); talloc_free(dn); @@ -1126,9 +1127,10 @@ static struct ldb_val map_convert_remote_dn(struct ldb_map_context *map, TALLOC_ return *newval; } -static struct ldb_val map_convert_local_objectclass(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) +static struct ldb_val map_convert_local_objectclass(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val) { int i; + struct ldb_map_context *map = module->private_data; for (i = 0; map->objectclass_maps[i].local_name; i++) { if (!strcmp(map->objectclass_maps[i].local_name, (char *)val->data)) { @@ -1143,9 +1145,10 @@ static struct ldb_val map_convert_local_objectclass(struct ldb_map_context *map, return ldb_val_dup(ctx, val); } -static struct ldb_val map_convert_remote_objectclass(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) +static struct ldb_val map_convert_remote_objectclass(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val) { int i; + struct ldb_map_context *map = module->private_data; for (i = 0; map->objectclass_maps[i].remote_name; i++) { if (!strcmp(map->objectclass_maps[i].remote_name, (char *)val->data)) { diff --git a/source4/lib/ldb/modules/ldb_map.h b/source4/lib/ldb/modules/ldb_map.h index 02fec649c6..4077660160 100644 --- a/source4/lib/ldb/modules/ldb_map.h +++ b/source4/lib/ldb/modules/ldb_map.h @@ -64,21 +64,21 @@ struct ldb_map_attribute struct { const char *remote_name; - struct ldb_val (*convert_local) (struct ldb_map_context *, TALLOC_CTX *, const struct ldb_val *); - struct ldb_val (*convert_remote) (struct ldb_map_context *, TALLOC_CTX *, const struct ldb_val *); + struct ldb_val (*convert_local) (struct ldb_module *, TALLOC_CTX *, const struct ldb_val *); + struct ldb_val (*convert_remote) (struct ldb_module *, TALLOC_CTX *, const struct ldb_val *); } convert; struct { /* Generate the local attribute from remote message */ struct ldb_message_element *(*generate_local) ( - struct ldb_map_context *, + struct ldb_module *, TALLOC_CTX *ctx, const char *attr, const struct ldb_message *remote); /* Update remote message with information from local message */ void (*generate_remote) ( - struct ldb_map_context *, + struct ldb_module *, const char *local_attr, const struct ldb_message *local, struct ldb_message *remote); -- cgit From 222fdd5237c1fd8551c39ce544171df3a5a41831 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 31 Aug 2005 21:04:17 +0000 Subject: r9842: More error checks in the ldb_map modules, extend testsuite (This used to be commit b7992de4b7d42a55e00509c887a269a07c19627d) --- source4/lib/ldb/modules/ldb_map.c | 143 ++++++++++++++++++++++++++------------ 1 file changed, 99 insertions(+), 44 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index f40506c03b..513e065f2e 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -109,7 +109,12 @@ static const struct ldb_map_objectclass *map_find_objectclass_local(struct ldb_m static int map_is_mappable(struct ldb_map_context *privdat, const struct ldb_message *msg) { int i; - struct ldb_message_element *el = ldb_msg_find_element(msg, "objectClass"); + struct ldb_message_element *el; + + if (ldb_dn_is_special(msg->dn)) + return 0; + + el = ldb_msg_find_element(msg, "objectClass"); /* No objectClass... */ if (el == NULL) { @@ -222,8 +227,8 @@ static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, TALL attr = map_find_attr_local(privdat, tree->u.equality.attr); if (!attr) { - ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Unable to find local attribute '%s', leaving as is\n", tree->u.equality.attr); - map_type = MAP_KEEP; + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Unable to find local attribute '%s', removing from parse tree\n", tree->u.equality.attr); + map_type = MAP_IGNORE; } else { map_type = attr->type; } @@ -234,7 +239,7 @@ static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, TALL } if (map_type == MAP_IGNORE) { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Search on ignored attribute '%s'\n", tree->u.equality.attr); + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Not mapping search on ignored attribute '%s'\n", tree->u.equality.attr); return NULL; } @@ -554,20 +559,26 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c switch (map_type) { case MAP_IGNORE:break; case MAP_RENAME: + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Renaming remote attribute %s to %s", attr->u.rename.remote_name, attr->local_name); oldelm = ldb_msg_find_element(mi, attr->u.rename.remote_name); - if (!oldelm) continue; + if (!oldelm) + continue; elm = talloc(msg, struct ldb_message_element); elm->name = talloc_strdup(elm, attr->local_name); elm->num_values = oldelm->num_values; - elm->values = talloc_reference(elm, oldelm->values); + elm->values = talloc_array(elm, struct ldb_val, elm->num_values); + for (j = 0; j < oldelm->num_values; j++) + elm->values[j] = ldb_val_dup(elm, &oldelm->values[j]); ldb_msg_add(module->ldb, msg, elm, oldelm->flags); break; case MAP_CONVERT: + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Converting remote attribute %s to %s", attr->u.rename.remote_name, attr->local_name); oldelm = ldb_msg_find_element(mi, attr->u.rename.remote_name); - if (!oldelm) continue; + if (!oldelm) + continue; elm = talloc(msg, struct ldb_message_element); elm->name = talloc_strdup(elm, attr->local_name); @@ -581,19 +592,24 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c break; case MAP_KEEP: + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Keeping remote attribute %s", attr->local_name); oldelm = ldb_msg_find_element(mi, attr->local_name); if (!oldelm) continue; elm = talloc(msg, struct ldb_message_element); elm->num_values = oldelm->num_values; - elm->values = talloc_reference(elm, oldelm->values); + elm->values = talloc_array(elm, struct ldb_val, elm->num_values); + for (j = 0; j < oldelm->num_values; j++) + elm->values[j] = ldb_val_dup(elm, &oldelm->values[j]); + elm->name = talloc_strdup(elm, oldelm->name); ldb_msg_add(module->ldb, msg, elm, oldelm->flags); break; case MAP_GENERATE: + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Generating local attribute %s", attr->local_name); elm = attr->u.generate.generate_local(module, msg, attr->local_name, mi); if (!elm) continue; @@ -614,18 +630,14 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c static int ldb_map_message_outgoing(struct ldb_module *module, const struct ldb_message *mo, struct ldb_message **fb, struct ldb_message **mp) { struct ldb_map_context *privdat = map_get_privdat(module); - struct ldb_message *msg = talloc_zero(module, struct ldb_message); struct ldb_message_element *elm; int i,j; *fb = talloc_zero(module, struct ldb_message); (*fb)->dn = talloc_reference(*fb, mo->dn); - *mp = msg; - - msg->private_data = mo->private_data; - - msg->dn = map_local_dn(module, module, mo->dn); + *mp = talloc_zero(module, struct ldb_message); + (*mp)->dn = map_local_dn(module, module, mo->dn); /* Loop over mi and call generate_remote for each attribute */ for (i = 0; i < mo->num_elements; i++) { @@ -649,45 +661,59 @@ static int ldb_map_message_outgoing(struct ldb_module *module, const struct ldb_ ldb_msg_add(module->ldb, *fb, elm, mo->elements[i].flags); break; case MAP_RENAME: - elm = talloc(msg, struct ldb_message_element); + elm = talloc(*mp, struct ldb_message_element); elm->name = talloc_strdup(elm, attr->u.rename.remote_name); elm->num_values = mo->elements[i].num_values; elm->values = talloc_reference(elm, mo->elements[i].values); - ldb_msg_add(module->ldb, msg, elm, mo->elements[i].flags); + ldb_msg_add(module->ldb, *mp, elm, mo->elements[i].flags); break; case MAP_CONVERT: - elm = talloc(msg, struct ldb_message_element); + elm = talloc(*mp, struct ldb_message_element); elm->name = talloc_strdup(elm, attr->u.rename.remote_name); elm->num_values = mo->elements[i].num_values; elm->values = talloc_array(elm, struct ldb_val, elm->num_values); for (j = 0; j < elm->num_values; j++) { - elm->values[j] = attr->u.convert.convert_local(module, msg, &mo->elements[i].values[j]); + elm->values[j] = attr->u.convert.convert_local(module, *mp, &mo->elements[i].values[j]); } - ldb_msg_add(module->ldb, msg, elm, mo->elements[i].flags); + ldb_msg_add(module->ldb, *mp, elm, mo->elements[i].flags); break; case MAP_KEEP: - elm = talloc(msg, struct ldb_message_element); + elm = talloc(*mp, struct ldb_message_element); elm->num_values = mo->elements[i].num_values; elm->values = talloc_reference(elm, mo->elements[i].values); elm->name = talloc_strdup(elm, mo->elements[i].name); - ldb_msg_add(module->ldb, msg, elm, mo->elements[i].flags); + ldb_msg_add(module->ldb, *mp, elm, mo->elements[i].flags); break; case MAP_GENERATE: - attr->u.generate.generate_remote(module, attr->local_name, mo, msg); + attr->u.generate.generate_remote(module, attr->local_name, mo, *mp); break; } } + if ((*fb)->num_elements == 0) { + /* No elements, discard.. */ + talloc_free(*fb); + *fb = NULL; + } else { + ldb_msg_add_string(module->ldb, *fb, "isMapped", "TRUE"); + } + + if ((*mp)->num_elements == 0) { + /* No elements, discard.. */ + talloc_free(*mp); + *mp = NULL; + } + return 0; } @@ -761,6 +787,7 @@ static int map_search_bytree_fb(struct ldb_module *module, const struct ldb_dn * return ret; } +/* Search in the database against which we are mapping */ static int map_search_bytree_mp(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const *attrs, struct ldb_message ***res) @@ -776,6 +803,16 @@ static int map_search_bytree_mp(struct ldb_module *module, const struct ldb_dn * /*- search mapped database */ new_tree = ldb_map_parse_tree(module, module, tree); + if (new_tree == NULL) { + /* All attributes used in the parse tree are + * local, apparently. Fall back to enumerating the complete remote + * database... Rather a slow search then no results. */ + new_tree = talloc_zero(module, struct ldb_parse_tree); + new_tree->operation = LDB_OP_PRESENT; + new_tree->u.present.attr = talloc_strdup(new_tree, "dn"); + return 0; + } + newattrs = ldb_map_attrs(module, attrs); new_base = map_local_dn(module, module, base); @@ -801,9 +838,15 @@ static int map_search_bytree_mp(struct ldb_module *module, const struct ldb_dn * ret = 0; for (i = 0; i < mpret; i++) { - struct ldb_message *merged = ldb_map_message_incoming(module, attrs, newres[i]); + struct ldb_message *merged; struct ldb_message **extrares = NULL; int extraret; + + /* Always get special DN's from the fallback database */ + if (ldb_dn_is_special(newres[i]->dn)) + continue; + + merged = ldb_map_message_incoming(module, attrs, newres[i]); /* Merge with additional data from local database */ extraret = ldb_next_search(module, merged->dn, LDB_SCOPE_BASE, "", NULL, &extrares); @@ -815,12 +858,12 @@ static int map_search_bytree_mp(struct ldb_module *module, const struct ldb_dn * talloc_free(newres); return -1; } else if (extraret == 0) { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "No extra data found for remote DN"); + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "No extra data found for remote DN: %s", ldb_dn_linearize(merged, merged->dn)); } if (extraret == 1) { int j; - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Extra data found for remote DN"); + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Extra data found for remote DN: %s", ldb_dn_linearize(merged, merged->dn)); for (j = 0; j < extrares[0]->num_elements; j++) { ldb_msg_add(module->ldb, merged, &(extrares[0]->elements[j]), extrares[0]->elements[j].flags); } @@ -830,7 +873,7 @@ static int map_search_bytree_mp(struct ldb_module *module, const struct ldb_dn * ldb_msg_add_string(module->ldb, merged, "extraMapped", "FALSE"); } - if (ldb_match_msg(module->ldb, merged, tree, base, scope)) { + if (ldb_match_msg(module->ldb, merged, tree, base, scope) != 0) { (*res)[ret] = merged; ret++; } else { @@ -859,6 +902,12 @@ static int map_search_bytree(struct ldb_module *module, const struct ldb_dn *bas if (ret_fb == -1) return -1; + /* special dn's are never mapped.. */ + if (ldb_dn_is_special(base)) { + *res = fbres; + return ret_fb; + } + ret_mp = map_search_bytree_mp(module, base, scope, tree, attrs, &mpres); if (ret_mp == -1) { return -1; @@ -867,6 +916,8 @@ static int map_search_bytree(struct ldb_module *module, const struct ldb_dn *bas /* Merge results */ *res = talloc_array(module, struct ldb_message *, ret_fb + ret_mp); + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Merging %d mapped and %d fallback messages", ret_mp, ret_fb); + for (i = 0; i < ret_fb; i++) (*res)[i] = fbres[i]; for (i = 0; i < ret_mp; i++) (*res)[ret_fb+i] = mpres[i]; @@ -909,22 +960,25 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) if (ldb_map_message_outgoing(module, msg, &fb, &mp) == -1) return -1; - - ldb_msg_add_string(module->ldb, fb, "isMapped", "TRUE"); - ret = ldb_next_add_record(module, fb); - if (ret == -1) { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Adding fallback record failed"); - return -1; + if (fb != NULL) { + ret = ldb_next_add_record(module, fb); + if (ret == -1) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Adding fallback record failed"); + return -1; + } } + + talloc_free(fb); - ret = ldb_add(privdat->mapped_ldb, mp); - if (ret == -1) { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Adding mapped record failed"); - return -1; + if (mp != NULL) { + ret = ldb_add(privdat->mapped_ldb, mp); + if (ret == -1) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Adding mapped record failed"); + return -1; + } } - talloc_free(fb); talloc_free(mp); return ret; @@ -946,15 +1000,16 @@ static int map_modify(struct ldb_module *module, const struct ldb_message *msg) if (ldb_map_message_outgoing(module, msg, &fb, &mp) == -1) return -1; - - ldb_msg_add_string(module->ldb, fb, "isMapped", "TRUE"); - ret = ldb_next_modify_record(module, fb); - - ret = ldb_modify(privdat->mapped_ldb, mp); + if (fb != NULL) { + ret = ldb_next_modify_record(module, fb); + talloc_free(fb); + } - talloc_free(fb); - talloc_free(mp); + if (mp != NULL) { + ret = ldb_modify(privdat->mapped_ldb, mp); + talloc_free(mp); + } return ret; } -- cgit From 05db3024ba6a8cd0b3182595f4f6f2f1f0987e44 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 1 Sep 2005 00:37:52 +0000 Subject: r9854: Finish ldb_map testsuite Update PLAN Some more small other fixes (This used to be commit de2bde2526ffaf521253e3b9e58fc11417986321) --- source4/lib/ldb/modules/ldb_map.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index 513e065f2e..de7a00ef60 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -27,11 +27,15 @@ #include "ldb/include/ldb_private.h" #include "ldb/modules/ldb_map.h" -/* TODO: - * - objectclass hint in ldb_map_attribute - * for use when multiple remote attributes (independant of each other) - * map to one local attribute. E.g.: (uid, gidNumber) -> unixName - * (use MAP_GENERATE instead ?) +/* + * - map_message_outgoing() should: + * - modify: not worry about anything simply map and hope everything + * will be ok. + * - make a list of remote objectclasses that will be used + * given the attributes that are available + * - only add attribute to the remote message if + * it is allowed by the objectclass + * */ /* @@ -701,10 +705,6 @@ static int ldb_map_message_outgoing(struct ldb_module *module, const struct ldb_ } if ((*fb)->num_elements == 0) { - /* No elements, discard.. */ - talloc_free(*fb); - *fb = NULL; - } else { ldb_msg_add_string(module->ldb, *fb, "isMapped", "TRUE"); } @@ -727,8 +727,8 @@ static int map_rename(struct ldb_module *module, const struct ldb_dn *olddn, con struct ldb_dn *n_olddn, *n_newdn; int ret; - ret = ldb_next_rename_record(module, olddn, newdn); - + ret = ldb_next_rename_record(module, n_olddn, n_newdn); + n_olddn = map_local_dn(module, module, olddn); n_newdn = map_local_dn(module, module, newdn); @@ -753,7 +753,7 @@ static int map_delete(struct ldb_module *module, const struct ldb_dn *dn) newdn = map_local_dn(module, module, dn); - ret = ldb_delete(privdat->mapped_ldb, newdn); + ldb_delete(privdat->mapped_ldb, newdn); talloc_free(newdn); @@ -996,7 +996,6 @@ static int map_modify(struct ldb_module *module, const struct ldb_message *msg) if (!map_is_mappable(privdat, msg)) return ldb_next_modify_record(module, msg); - if (ldb_map_message_outgoing(module, msg, &fb, &mp) == -1) return -1; -- cgit From 1b5cb7309d13b472eff12e1bfb5191ca8e0391ae Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 1 Sep 2005 01:11:15 +0000 Subject: r9857: Fix rename/delete issues (This used to be commit d6dce7ef3eb21a5e90244cf2ce7403ab43b12d63) --- source4/lib/ldb/modules/ldb_map.c | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index de7a00ef60..cdf0e29405 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -725,19 +725,26 @@ static int map_rename(struct ldb_module *module, const struct ldb_dn *olddn, con { struct ldb_map_context *privdat = map_get_privdat(module); struct ldb_dn *n_olddn, *n_newdn; - int ret; - - ret = ldb_next_rename_record(module, n_olddn, n_newdn); - + int fb_ret, mp_ret; + n_olddn = map_local_dn(module, module, olddn); n_newdn = map_local_dn(module, module, newdn); - ret = ldb_rename(privdat->mapped_ldb, n_olddn, n_newdn); + mp_ret = ldb_rename(privdat->mapped_ldb, n_olddn, n_newdn); + if (mp_ret != -1) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Mapped record renamed"); + } + + fb_ret = ldb_next_rename_record(module, olddn, newdn); + + if (fb_ret != -1) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Fallback record renamed"); + } talloc_free(n_olddn); talloc_free(n_newdn); - return ret; + return (fb_ret == -1 && mp_ret == -1)?-1:0; } /* @@ -747,17 +754,23 @@ static int map_delete(struct ldb_module *module, const struct ldb_dn *dn) { struct ldb_map_context *privdat = map_get_privdat(module); struct ldb_dn *newdn; - int ret; + int fb_ret, mp_ret; - ret = ldb_next_delete_record(module, dn); - newdn = map_local_dn(module, module, dn); - ldb_delete(privdat->mapped_ldb, newdn); + mp_ret = ldb_delete(privdat->mapped_ldb, newdn); + if (mp_ret != -1) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Mapped record deleted"); + } + + fb_ret = ldb_next_delete_record(module, dn); + if (fb_ret != -1) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Fallback record deleted"); + } talloc_free(newdn); - return ret; + return (fb_ret == -1 && mp_ret == -1)?-1:0; } /* search fallback database */ -- cgit From 7a3e0a89f11f11527bc5e35310185efd210fa9ce Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 1 Sep 2005 07:29:33 +0000 Subject: r9879: A quick check to see if nested initialisers (?) is portable across the build farm. I have a feeling it isn't. (This used to be commit 7cc8df0c2f46fb9ce753e368ce645bcb69585334) --- source4/lib/ldb/modules/ldb_map.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index cdf0e29405..076aa4c1dc 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -71,7 +71,11 @@ static const struct ldb_map_attribute builtin_attribute_maps[] = { { .local_name = "dn", .type = MAP_CONVERT, - .u.convert.remote_name = "dn", + .u = { + .convert = { + .remote_name = "dn", + } + }, .u.convert.convert_local = map_convert_local_dn, .u.convert.convert_remote = map_convert_remote_dn, }, -- cgit From 4d0ec61e49b459b61fa45304e1ab434e7d337fc0 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 1 Sep 2005 07:37:13 +0000 Subject: r9880: Convert remaining initialisers to more portable form. This should clean out a lot of build farm breakage. (This used to be commit c34fbdc6c3fd2c066c713bdd84e6f40f6aa8cd43) --- source4/lib/ldb/modules/ldb_map.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index 076aa4c1dc..423dab38bb 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -74,17 +74,21 @@ static const struct ldb_map_attribute builtin_attribute_maps[] = { .u = { .convert = { .remote_name = "dn", - } + .convert_local = map_convert_local_dn, + .convert_remote = map_convert_remote_dn, + }, }, - .u.convert.convert_local = map_convert_local_dn, - .u.convert.convert_remote = map_convert_remote_dn, }, { .local_name = "objectclass", .type = MAP_CONVERT, - .u.convert.remote_name = "objectclass", - .u.convert.convert_local = map_convert_local_objectclass, - .u.convert.convert_remote = map_convert_remote_objectclass, + .u = { + .convert = { + .remote_name = "objectclass", + .convert_local = map_convert_local_objectclass, + .convert_remote = map_convert_remote_objectclass, + }, + }, }, { .local_name = NULL, -- cgit From b2c54c08bf2a5ac2fd564c219ecf54af9bb43e54 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 1 Sep 2005 07:44:59 +0000 Subject: r9881: I can't believe this can make a difference... (This used to be commit 31069bfd18c4b7355dbf85df9fb479705b0e3b4b) --- source4/lib/ldb/modules/ldb_map.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index 423dab38bb..5b1afb56bc 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -1164,7 +1164,7 @@ struct ldb_module *ldb_map_init(struct ldb_context *ldb, const struct ldb_map_at static struct ldb_val map_convert_local_dn(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val) { - struct ldb_dn *dn, *newdn;; + struct ldb_dn *dn, *newdn; struct ldb_val *newval; dn = ldb_dn_explode(ctx, (char *)val->data); @@ -1184,7 +1184,7 @@ static struct ldb_val map_convert_local_dn(struct ldb_module *module, TALLOC_CTX static struct ldb_val map_convert_remote_dn(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val) { - struct ldb_dn *dn, *newdn;; + struct ldb_dn *dn, *newdn; struct ldb_val *newval; dn = ldb_dn_explode(ctx, (char *)val->data); -- cgit From e2e2508b586a112e612bf3660f80d25c9bf8bc90 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 1 Sep 2005 15:33:31 +0000 Subject: r9899: Be more conservative about what is sent to the remote server in ldb_map. (This used to be commit 76e943d4416e38ce4cce27d5403bc3e133d0025b) --- source4/lib/ldb/modules/ldb_map.c | 507 +++++++++++++++++++++++++------------- source4/lib/ldb/modules/ldb_map.h | 10 +- 2 files changed, 350 insertions(+), 167 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index 5b1afb56bc..5a5575d1e0 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -27,15 +27,13 @@ #include "ldb/include/ldb_private.h" #include "ldb/modules/ldb_map.h" -/* - * - map_message_outgoing() should: - * - modify: not worry about anything simply map and hope everything - * will be ok. - * - make a list of remote objectclasses that will be used - * given the attributes that are available - * - only add attribute to the remote message if - * it is allowed by the objectclass - * +/* FIXME: + * - per remote objectclass: + * - remote name + * - local name + * - remote bases + * - musts + * - mays */ /* @@ -95,6 +93,17 @@ static const struct ldb_map_attribute builtin_attribute_maps[] = { } }; +static const struct ldb_map_objectclass *map_find_objectclass_remote(struct ldb_map_context *privdat, const char *name) +{ + int i; + for (i = 0; privdat->objectclass_maps[i].remote_name; i++) { + if (!ldb_attr_cmp(privdat->objectclass_maps[i].remote_name, name)) + return &privdat->objectclass_maps[i]; + } + + return NULL; +} + struct map_private { struct ldb_map_context context; const char *last_err_string; @@ -105,41 +114,39 @@ static struct ldb_map_context *map_get_privdat(struct ldb_module *module) return &((struct map_private *)module->private_data)->context; } -static const struct ldb_map_objectclass *map_find_objectclass_local(struct ldb_map_context *privdat, const char *name) -{ - int i; - for (i = 0; privdat->objectclass_maps[i].local_name; i++) { - if (!ldb_attr_cmp(privdat->objectclass_maps[i].local_name, name)) - return &privdat->objectclass_maps[i]; - } - - return NULL; -} - -/* Decide whether a add/modify should be pushed to the - * remote LDAP server. We currently only do this if we see an objectClass we know */ -static int map_is_mappable(struct ldb_map_context *privdat, const struct ldb_message *msg) +/* Check whether the given attribute can fit into the specified + * message, obeying objectClass restrictions */ +static int map_msg_valid_attr(struct ldb_module *module, const struct ldb_message *msg, const char *attr) { - int i; - struct ldb_message_element *el; - - if (ldb_dn_is_special(msg->dn)) - return 0; - - el = ldb_msg_find_element(msg, "objectClass"); + struct ldb_map_context *map = module->private_data; + int i, j; + struct ldb_message_element *el = ldb_msg_find_element(msg, "objectClass"); - /* No objectClass... */ if (el == NULL) { + ldb_debug(module->ldb, LDB_DEBUG_FATAL, "Can't find objectClass"); return 0; } for (i = 0; i < el->num_values; i++) { - if (map_find_objectclass_local(privdat, (char *)el->values[i].data)) - return 1; + const struct ldb_map_objectclass *class = map_find_objectclass_remote(map, (char *)el->values[i].data); + + if (!class) + continue; + + for (j = 0; class->musts[j]; j++) { + if (!ldb_attr_cmp(class->musts[j], attr)) + return 1; + } + + for (j = 0; class->mays[j]; j++) { + if (!ldb_attr_cmp(class->mays[j], attr)) + return 1; + } } return 0; -} +} + /* find an attribute by the local name */ static const struct ldb_map_attribute *map_find_attr_local(struct ldb_map_context *privdat, const char *attr) @@ -154,6 +161,40 @@ static const struct ldb_map_attribute *map_find_attr_local(struct ldb_map_contex return NULL; } +/* Check if a given attribute can be created by doing mapping from a local attribute to a remote one */ +static int map_msg_can_map_attr(struct ldb_module *module, const struct ldb_message *msg, const char *attr_name) +{ + struct ldb_map_context *map = module->private_data; + int i, j; + + for (i = 0; i < msg->num_elements; i++) { + const struct ldb_map_attribute *attr = map_find_attr_local(map, msg->elements[i].name); + + if (!attr) + continue; + + switch (attr->type) { + case MAP_IGNORE: continue; + case MAP_KEEP: + if (ldb_attr_cmp(attr->local_name, attr_name) == 0) return 1; + break; + case MAP_RENAME: + case MAP_CONVERT: + if (ldb_attr_cmp(attr->u.rename.remote_name, attr_name) == 0) return 1; + break; + case MAP_GENERATE: + for (j = 0; attr->u.generate.remote_names[j]; j++) { + if (ldb_attr_cmp(attr->u.generate.remote_names[j], attr_name) == 0) return 1; + } + break; + } + } + + return 0; +} + + + /* find an attribute by the remote name */ static const struct ldb_map_attribute *map_find_attr_remote(struct ldb_map_context *privdat, const char *attr) { @@ -547,8 +588,6 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c msg->dn = map_remote_dn(module, module, mi->dn); - ldb_msg_add_string(module->ldb, msg, "mappedFromDn", ldb_dn_linearize(msg, mi->dn)); - /* Loop over attrs, find in ldb_map_attribute array and * run generate() */ @@ -638,94 +677,6 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c return msg; } -/* Used for add, modify */ -static int ldb_map_message_outgoing(struct ldb_module *module, const struct ldb_message *mo, struct ldb_message **fb, struct ldb_message **mp) -{ - struct ldb_map_context *privdat = map_get_privdat(module); - struct ldb_message_element *elm; - int i,j; - - *fb = talloc_zero(module, struct ldb_message); - (*fb)->dn = talloc_reference(*fb, mo->dn); - - *mp = talloc_zero(module, struct ldb_message); - (*mp)->dn = map_local_dn(module, module, mo->dn); - - /* Loop over mi and call generate_remote for each attribute */ - for (i = 0; i < mo->num_elements; i++) { - const struct ldb_map_attribute *attr = map_find_attr_local(privdat, mo->elements[i].name); - enum ldb_map_attr_type map_type; - - if (!attr) { - ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Undefined local attribute '%s', ignoring\n", mo->elements[i].name); - map_type = MAP_IGNORE; - continue; - } else map_type = attr->type; - - switch (map_type) { - case MAP_IGNORE: /* Add to fallback message */ - elm = talloc(*fb, struct ldb_message_element); - - elm->num_values = mo->elements[i].num_values; - elm->values = talloc_reference(elm, mo->elements[i].values); - elm->name = talloc_strdup(elm, mo->elements[i].name); - - ldb_msg_add(module->ldb, *fb, elm, mo->elements[i].flags); - break; - case MAP_RENAME: - elm = talloc(*mp, struct ldb_message_element); - - elm->name = talloc_strdup(elm, attr->u.rename.remote_name); - elm->num_values = mo->elements[i].num_values; - elm->values = talloc_reference(elm, mo->elements[i].values); - - ldb_msg_add(module->ldb, *mp, elm, mo->elements[i].flags); - break; - - case MAP_CONVERT: - elm = talloc(*mp, struct ldb_message_element); - - elm->name = talloc_strdup(elm, attr->u.rename.remote_name); - elm->num_values = mo->elements[i].num_values; - elm->values = talloc_array(elm, struct ldb_val, elm->num_values); - - for (j = 0; j < elm->num_values; j++) { - elm->values[j] = attr->u.convert.convert_local(module, *mp, &mo->elements[i].values[j]); - } - - ldb_msg_add(module->ldb, *mp, elm, mo->elements[i].flags); - break; - - case MAP_KEEP: - elm = talloc(*mp, struct ldb_message_element); - - elm->num_values = mo->elements[i].num_values; - elm->values = talloc_reference(elm, mo->elements[i].values); - elm->name = talloc_strdup(elm, mo->elements[i].name); - - ldb_msg_add(module->ldb, *mp, elm, mo->elements[i].flags); - break; - - case MAP_GENERATE: - attr->u.generate.generate_remote(module, attr->local_name, mo, *mp); - break; - } - } - - if ((*fb)->num_elements == 0) { - ldb_msg_add_string(module->ldb, *fb, "isMapped", "TRUE"); - } - - if ((*mp)->num_elements == 0) { - /* No elements, discard.. */ - talloc_free(*mp); - *mp = NULL; - } - - return 0; -} - - /* rename a record */ @@ -734,6 +685,13 @@ static int map_rename(struct ldb_module *module, const struct ldb_dn *olddn, con struct ldb_map_context *privdat = map_get_privdat(module); struct ldb_dn *n_olddn, *n_newdn; int fb_ret, mp_ret; + + fb_ret = ldb_next_rename_record(module, olddn, newdn); + + if (fb_ret != -1) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Fallback record renamed"); + return fb_ret; + } n_olddn = map_local_dn(module, module, olddn); n_newdn = map_local_dn(module, module, newdn); @@ -743,16 +701,12 @@ static int map_rename(struct ldb_module *module, const struct ldb_dn *olddn, con ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Mapped record renamed"); } - fb_ret = ldb_next_rename_record(module, olddn, newdn); + ldb_next_rename_record(module, olddn, newdn); - if (fb_ret != -1) { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Fallback record renamed"); - } - talloc_free(n_olddn); talloc_free(n_newdn); - return (fb_ret == -1 && mp_ret == -1)?-1:0; + return mp_ret; } /* @@ -764,6 +718,12 @@ static int map_delete(struct ldb_module *module, const struct ldb_dn *dn) struct ldb_dn *newdn; int fb_ret, mp_ret; + fb_ret = ldb_next_delete_record(module, dn); + if (fb_ret != -1) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Fallback record deleted"); + return fb_ret; + } + newdn = map_local_dn(module, module, dn); mp_ret = ldb_delete(privdat->mapped_ldb, newdn); @@ -771,14 +731,11 @@ static int map_delete(struct ldb_module *module, const struct ldb_dn *dn) ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Mapped record deleted"); } - fb_ret = ldb_next_delete_record(module, dn); - if (fb_ret != -1) { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Fallback record deleted"); - } + ldb_next_delete_record(module, newdn); talloc_free(newdn); - return (fb_ret == -1 && mp_ret == -1)?-1:0; + return mp_ret; } /* search fallback database */ @@ -869,7 +826,7 @@ static int map_search_bytree_mp(struct ldb_module *module, const struct ldb_dn * merged = ldb_map_message_incoming(module, attrs, newres[i]); - /* Merge with additional data from local database */ + /* Merge with additional data from fallback database */ extraret = ldb_next_search(module, merged->dn, LDB_SCOPE_BASE, "", NULL, &extrares); if (extraret == -1) { @@ -888,10 +845,6 @@ static int map_search_bytree_mp(struct ldb_module *module, const struct ldb_dn * for (j = 0; j < extrares[0]->num_elements; j++) { ldb_msg_add(module->ldb, merged, &(extrares[0]->elements[j]), extrares[0]->elements[j].flags); } - - ldb_msg_add_string(module->ldb, merged, "extraMapped", "TRUE"); - } else { - ldb_msg_add_string(module->ldb, merged, "extraMapped", "FALSE"); } if (ldb_match_msg(module->ldb, merged, tree, base, scope) != 0) { @@ -966,6 +919,20 @@ static int map_search(struct ldb_module *module, const struct ldb_dn *base, return ret; } +static int msg_contains_objectclass(const struct ldb_message *msg, const char *name) +{ + struct ldb_message_element *el = ldb_msg_find_element(msg, "objectClass"); + int i; + + for (i = 0; i < el->num_values; i++) { + if (ldb_attr_cmp((char *)el->values[i].data, name) == 0) { + return 1; + } + } + + return 0; +} + /* add a record */ @@ -974,32 +941,159 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) int ret; struct ldb_map_context *privdat = map_get_privdat(module); struct ldb_message *fb, *mp; + struct ldb_message_element *ocs; + int i; + + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_map_add"); - if (!map_is_mappable(privdat, msg)) { + if (ldb_dn_is_special(msg->dn)) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_map_add: Added fallback record"); return ldb_next_add_record(module, msg); } - if (ldb_map_message_outgoing(module, msg, &fb, &mp) == -1) - return -1; + mp = talloc_zero(module, struct ldb_message); + mp->dn = map_local_dn(module, mp, msg->dn); - if (fb != NULL) { - ret = ldb_next_add_record(module, fb); - if (ret == -1) { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Adding fallback record failed"); - return -1; + fb = talloc_zero(module, struct ldb_message); + fb->dn = talloc_reference(fb, msg->dn); + + /* We add objectClass, so 'top' should be no problem */ + ldb_msg_add_string(module->ldb, mp, "objectClass", "top"); + + /* make a list of remote objectclasses that can be used + * given the attributes that are available and add to + * mp_msg */ + for (i = 0; privdat->objectclass_maps[i].local_name; i++) { + int j, has_musts, has_baseclasses; + + /* Add this objectClass to the list if all musts are present */ + for (j = 0; privdat->objectclass_maps[i].musts[j]; j++) { + if (!map_msg_can_map_attr(module, msg, privdat->objectclass_maps[i].musts[j])) + break; } - } - talloc_free(fb); + has_musts = (privdat->objectclass_maps[i].musts[j] == NULL); + + /* Check if base classes are present as well */ + for (j = 0; privdat->objectclass_maps[i].base_classes[j]; j++) { + if (!msg_contains_objectclass(mp, privdat->objectclass_maps[i].base_classes[j])) + break; + } + + has_baseclasses = (privdat->objectclass_maps[i].base_classes[j] == NULL); - if (mp != NULL) { - ret = ldb_add(privdat->mapped_ldb, mp); - if (ret == -1) { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Adding mapped record failed"); - return -1; + /* Apparently, it contains all required elements */ + if (has_musts && has_baseclasses) { + ldb_msg_add_string(module->ldb, mp, "objectClass", privdat->objectclass_maps[i].remote_name); } } + ocs = ldb_msg_find_element(mp, "objectClass"); + if (ocs->num_values == 1) { /* Only top */ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_map_add: Added fallback record"); + return ldb_next_add_record(module, msg); + } + + /* + * - try to map as much attributes as possible where allowed and add them to mp_msg + * - add other attributes to fb_msg + */ + for (i = 0; i < msg->num_elements; i++) { + const struct ldb_map_attribute *attr; + struct ldb_message_element *elm; + enum ldb_map_attr_type map_type; + int j; + int mapped = 0; + + if (ldb_attr_cmp(msg->elements[i].name, "objectClass") == 0) + continue; + + attr = map_find_attr_local(privdat, msg->elements[i].name); + + if (!attr) { + ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Undefined local attribute '%s', ignoring\n", msg->elements[i].name); + map_type = MAP_IGNORE; + } else map_type = attr->type; + + /* Decide whether or not we need to map or fallback */ + switch (map_type) { + case MAP_GENERATE: + attr->u.generate.generate_remote(module, attr->local_name, msg, mp, fb); + continue; + case MAP_KEEP: + mapped = map_msg_valid_attr(module, mp, attr->local_name); + case MAP_IGNORE: mapped = 0; break; + case MAP_CONVERT: + case MAP_RENAME: mapped = map_msg_valid_attr(module, mp, attr->u.rename.remote_name); + break; + } + + if (mapped) { + switch (map_type) { + case MAP_KEEP: + elm = talloc(fb, struct ldb_message_element); + + elm->num_values = msg->elements[i].num_values; + elm->values = talloc_reference(elm, msg->elements[i].values); + elm->name = talloc_strdup(elm, msg->elements[i].name); + break; + + case MAP_RENAME: + elm = talloc(mp, struct ldb_message_element); + + elm->name = talloc_strdup(elm, attr->u.rename.remote_name); + elm->num_values = msg->elements[i].num_values; + elm->values = talloc_reference(elm, msg->elements[i].values); + break; + + case MAP_CONVERT: + elm = talloc(mp, struct ldb_message_element); + + elm->name = talloc_strdup(elm, attr->u.rename.remote_name); + elm->num_values = msg->elements[i].num_values; + elm->values = talloc_array(elm, struct ldb_val, elm->num_values); + + for (j = 0; j < elm->num_values; j++) { + elm->values[j] = attr->u.convert.convert_local(module, mp, &msg->elements[i].values[j]); + } + + mapped = map_msg_valid_attr(module, mp, attr->u.convert.remote_name); + + break; + + case MAP_GENERATE: + case MAP_IGNORE: + ldb_debug(module->ldb, LDB_DEBUG_FATAL, "This line should never be reached"); + break; + } + ldb_msg_add(module->ldb, mp, elm, 0); + } else { + elm = talloc(fb, struct ldb_message_element); + + elm->num_values = msg->elements[i].num_values; + elm->values = talloc_reference(elm, msg->elements[i].values); + elm->name = talloc_strdup(elm, msg->elements[i].name); + + ldb_msg_add(module->ldb, fb, elm, 0); + } + } + + ret = ldb_add(privdat->mapped_ldb, mp); + if (ret == -1) { + ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Adding mapped record failed: %s", ldb_errstring(privdat->mapped_ldb)); + return -1; + } + + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_map_add: Added mapped record"); + + ldb_msg_add_string(module->ldb, fb, "isMapped", "TRUE"); + ret = ldb_next_add_record(module, fb); + if (ret == -1) { + ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Adding fallback record failed: %s", ldb_next_errstring(module)); + return -1; + } + + talloc_free(fb); talloc_free(mp); return ret; @@ -1013,25 +1107,106 @@ static int map_modify(struct ldb_module *module, const struct ldb_message *msg) { struct ldb_map_context *privdat = map_get_privdat(module); struct ldb_message *fb, *mp; - int ret; + struct ldb_message_element *elm; + int fb_ret, mp_ret; + int i,j; + + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_map_modify"); - if (!map_is_mappable(privdat, msg)) + if (ldb_dn_is_special(msg->dn)) return ldb_next_modify_record(module, msg); - if (ldb_map_message_outgoing(module, msg, &fb, &mp) == -1) - return -1; + fb = talloc_zero(module, struct ldb_message); + fb->dn = talloc_reference(fb, msg->dn); + + mp = talloc_zero(module, struct ldb_message); + mp->dn = map_local_dn(module, mp, msg->dn); + + /* Loop over mi and call generate_remote for each attribute */ + for (i = 0; i < msg->num_elements; i++) { + const struct ldb_map_attribute *attr; + enum ldb_map_attr_type map_type; + + if (ldb_attr_cmp(msg->elements[i].name, "isMapped") == 0) + continue; + + attr = map_find_attr_local(privdat, msg->elements[i].name); + + if (!attr) { + ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Undefined local attribute '%s', ignoring\n", msg->elements[i].name); + map_type = MAP_IGNORE; + } else map_type = attr->type; + + switch (map_type) { + case MAP_IGNORE: /* Add to fallback message */ + elm = talloc(fb, struct ldb_message_element); + + elm->num_values = msg->elements[i].num_values; + elm->values = talloc_reference(elm, msg->elements[i].values); + elm->name = talloc_strdup(elm, msg->elements[i].name); + + ldb_msg_add(module->ldb, fb, elm, msg->elements[i].flags); + break; + case MAP_RENAME: + elm = talloc(mp, struct ldb_message_element); + + elm->name = talloc_strdup(elm, attr->u.rename.remote_name); + elm->num_values = msg->elements[i].num_values; + elm->values = talloc_array(elm, struct ldb_val, elm->num_values); + for (j = 0; j < elm->num_values; j++) { + elm->values[j] = msg->elements[i].values[j]; + } + + ldb_msg_add(module->ldb, mp, elm, msg->elements[i].flags); + break; + + case MAP_CONVERT: + elm = talloc(mp, struct ldb_message_element); + + elm->name = talloc_strdup(elm, attr->u.rename.remote_name); + elm->num_values = msg->elements[i].num_values; + elm->values = talloc_array(elm, struct ldb_val, elm->num_values); + + for (j = 0; j < elm->num_values; j++) { + elm->values[j] = attr->u.convert.convert_local(module, mp, &msg->elements[i].values[j]); + } + + ldb_msg_add(module->ldb, mp, elm, msg->elements[i].flags); + break; + + case MAP_KEEP: + elm = talloc(mp, struct ldb_message_element); - if (fb != NULL) { - ret = ldb_next_modify_record(module, fb); - talloc_free(fb); + elm->num_values = msg->elements[i].num_values; + elm->values = talloc_reference(elm, msg->elements[i].values); + elm->name = talloc_strdup(elm, msg->elements[i].name); + + ldb_msg_add(module->ldb, mp, elm, msg->elements[i].flags); + break; + + case MAP_GENERATE: + attr->u.generate.generate_remote(module, attr->local_name, msg, mp, fb); + break; + } + } + + if (fb->num_elements > 0) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Modifying fallback record with %d elements", fb->num_elements); + fb_ret = ldb_next_modify_record(module, fb); + if (fb_ret == -1) { + ldb_msg_add_string(module->ldb, fb, "isMapped", "TRUE"); + fb_ret = ldb_next_add_record(module, fb); + } } + talloc_free(fb); - if (mp != NULL) { - ret = ldb_modify(privdat->mapped_ldb, mp); - talloc_free(mp); + if (mp->num_elements > 0) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Modifying mapped record with %d elements", mp->num_elements); + mp_ret = ldb_modify(privdat->mapped_ldb, mp); } + talloc_free(mp); - return ret; + return (mp_ret == -1 || fb_ret == -1)?-1:0; } static int map_lock(struct ldb_module *module, const char *lockname) diff --git a/source4/lib/ldb/modules/ldb_map.h b/source4/lib/ldb/modules/ldb_map.h index 4077660160..984a4a2cd5 100644 --- a/source4/lib/ldb/modules/ldb_map.h +++ b/source4/lib/ldb/modules/ldb_map.h @@ -81,7 +81,8 @@ struct ldb_map_attribute struct ldb_module *, const char *local_attr, const struct ldb_message *local, - struct ldb_message *remote); + struct ldb_message *remote_mp, + struct ldb_message *remote_fb); /* Name(s) for this attribute on the remote server. This is an array since * one local attribute's data can be split up into several attributes @@ -92,15 +93,22 @@ struct ldb_map_attribute } u; }; +#define LDB_MAP_MAX_SUBCLASSES 10 +#define LDB_MAP_MAX_MUSTS 10 +#define LDB_MAP_MAX_MAYS 50 struct ldb_map_objectclass { const char *local_name; const char *remote_name; + const char *base_classes[LDB_MAP_MAX_SUBCLASSES]; + const char *musts[LDB_MAP_MAX_MUSTS]; + const char *mays[LDB_MAP_MAX_MAYS]; }; struct ldb_map_context { struct ldb_map_attribute *attribute_maps; + /* NOTE: Always declare base classes first here */ const struct ldb_map_objectclass *objectclass_maps; struct ldb_context *mapped_ldb; }; -- cgit From ca6c0af86f3bbefbc29c4bf4815da963ca857cef Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 1 Sep 2005 18:04:23 +0000 Subject: r9908: Generate posixUser and posixGroup as well (This used to be commit ebed25b47d3d8bd350b51b462d605d713f17602d) --- source4/lib/ldb/modules/ldb_map.c | 116 ++++++++++++++++++++------------------ 1 file changed, 61 insertions(+), 55 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index 5a5575d1e0..f3ece2621e 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -27,15 +27,6 @@ #include "ldb/include/ldb_private.h" #include "ldb/modules/ldb_map.h" -/* FIXME: - * - per remote objectclass: - * - remote name - * - local name - * - remote bases - * - musts - * - mays - */ - /* - special attribute 'isMapped' - add/modify @@ -164,33 +155,39 @@ static const struct ldb_map_attribute *map_find_attr_local(struct ldb_map_contex /* Check if a given attribute can be created by doing mapping from a local attribute to a remote one */ static int map_msg_can_map_attr(struct ldb_module *module, const struct ldb_message *msg, const char *attr_name) { - struct ldb_map_context *map = module->private_data; - int i, j; - - for (i = 0; i < msg->num_elements; i++) { - const struct ldb_map_attribute *attr = map_find_attr_local(map, msg->elements[i].name); + struct ldb_map_context *privdat = module->private_data; + int i,j; - if (!attr) + for (i = 0; privdat->attribute_maps[i].local_name; i++) { + switch (privdat->attribute_maps[i].type) { + case MAP_IGNORE: /* No remote name at all */ continue; - - switch (attr->type) { - case MAP_IGNORE: continue; case MAP_KEEP: - if (ldb_attr_cmp(attr->local_name, attr_name) == 0) return 1; - break; + if (ldb_attr_cmp(attr_name, privdat->attribute_maps[i].local_name) == 0) + goto found; + break; case MAP_RENAME: case MAP_CONVERT: - if (ldb_attr_cmp(attr->u.rename.remote_name, attr_name) == 0) return 1; - break; + if (ldb_attr_cmp(attr_name, privdat->attribute_maps[i].u.rename.remote_name) == 0) + goto found; + break; case MAP_GENERATE: - for (j = 0; attr->u.generate.remote_names[j]; j++) { - if (ldb_attr_cmp(attr->u.generate.remote_names[j], attr_name) == 0) return 1; - } - break; + for (j = 0; privdat->attribute_maps[i].u.generate.remote_names[j]; j++) { + if (ldb_attr_cmp(attr_name, privdat->attribute_maps[i].u.generate.remote_names[j]) == 0) + goto found; + } + break; } } return 0; + +found: + + if (ldb_msg_find_element(msg, privdat->attribute_maps[i].local_name)) + return 1; + + return 0; } @@ -684,29 +681,28 @@ static int map_rename(struct ldb_module *module, const struct ldb_dn *olddn, con { struct ldb_map_context *privdat = map_get_privdat(module); struct ldb_dn *n_olddn, *n_newdn; - int fb_ret, mp_ret; + int ret; - fb_ret = ldb_next_rename_record(module, olddn, newdn); - - if (fb_ret != -1) { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Fallback record renamed"); - return fb_ret; - } - n_olddn = map_local_dn(module, module, olddn); n_newdn = map_local_dn(module, module, newdn); - mp_ret = ldb_rename(privdat->mapped_ldb, n_olddn, n_newdn); - if (mp_ret != -1) { + ret = ldb_rename(privdat->mapped_ldb, n_olddn, n_newdn); + if (ret != -1) { ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Mapped record renamed"); + ldb_next_rename_record(module, olddn, newdn); + } else { + ret = ldb_next_rename_record(module, olddn, newdn); + + if (ret != -1) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Fallback record renamed"); + } } - ldb_next_rename_record(module, olddn, newdn); talloc_free(n_olddn); talloc_free(n_newdn); - return mp_ret; + return ret; } /* @@ -716,26 +712,25 @@ static int map_delete(struct ldb_module *module, const struct ldb_dn *dn) { struct ldb_map_context *privdat = map_get_privdat(module); struct ldb_dn *newdn; - int fb_ret, mp_ret; - - fb_ret = ldb_next_delete_record(module, dn); - if (fb_ret != -1) { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Fallback record deleted"); - return fb_ret; - } + int ret; newdn = map_local_dn(module, module, dn); - mp_ret = ldb_delete(privdat->mapped_ldb, newdn); - if (mp_ret != -1) { + ret = ldb_delete(privdat->mapped_ldb, newdn); + if (ret != -1) { ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Mapped record deleted"); + } else { + ret = ldb_next_delete_record(module, dn); + if (ret != -1) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Fallback record deleted"); + } } ldb_next_delete_record(module, newdn); talloc_free(newdn); - return mp_ret; + return ret; } /* search fallback database */ @@ -868,7 +863,7 @@ static int map_search_bytree(struct ldb_module *module, const struct ldb_dn *bas enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const *attrs, struct ldb_message ***res) { - struct ldb_message **fbres, **mpres; + struct ldb_message **fbres, **mpres = NULL; int i; int ret_fb, ret_mp; @@ -968,16 +963,20 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) /* Add this objectClass to the list if all musts are present */ for (j = 0; privdat->objectclass_maps[i].musts[j]; j++) { - if (!map_msg_can_map_attr(module, msg, privdat->objectclass_maps[i].musts[j])) + if (!map_msg_can_map_attr(module, msg, privdat->objectclass_maps[i].musts[j])) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "map_add: Not adding objectClass %s because it is not possible to create remote attribute %s", privdat->objectclass_maps[i].local_name, privdat->objectclass_maps[i].musts[j]); break; + } } has_musts = (privdat->objectclass_maps[i].musts[j] == NULL); /* Check if base classes are present as well */ for (j = 0; privdat->objectclass_maps[i].base_classes[j]; j++) { - if (!msg_contains_objectclass(mp, privdat->objectclass_maps[i].base_classes[j])) + if (!msg_contains_objectclass(mp, privdat->objectclass_maps[i].base_classes[j])) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "map_add: Not adding objectClass %s of missing base class %s", privdat->objectclass_maps[i].local_name, privdat->objectclass_maps[i].base_classes[j]); break; + } } has_baseclasses = (privdat->objectclass_maps[i].base_classes[j] == NULL); @@ -985,6 +984,7 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) /* Apparently, it contains all required elements */ if (has_musts && has_baseclasses) { ldb_msg_add_string(module->ldb, mp, "objectClass", privdat->objectclass_maps[i].remote_name); + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "map_add: Adding objectClass %s", privdat->objectclass_maps[i].remote_name); } } @@ -1000,7 +1000,7 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) */ for (i = 0; i < msg->num_elements; i++) { const struct ldb_map_attribute *attr; - struct ldb_message_element *elm; + struct ldb_message_element *elm = NULL; enum ldb_map_attr_type map_type; int j; int mapped = 0; @@ -1018,10 +1018,12 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) /* Decide whether or not we need to map or fallback */ switch (map_type) { case MAP_GENERATE: + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Generating from %s", attr->local_name); attr->u.generate.generate_remote(module, attr->local_name, msg, mp, fb); continue; case MAP_KEEP: mapped = map_msg_valid_attr(module, mp, attr->local_name); + break; case MAP_IGNORE: mapped = 0; break; case MAP_CONVERT: case MAP_RENAME: mapped = map_msg_valid_attr(module, mp, attr->u.rename.remote_name); @@ -1031,6 +1033,7 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) if (mapped) { switch (map_type) { case MAP_KEEP: + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Keeping %s", attr->local_name); elm = talloc(fb, struct ldb_message_element); elm->num_values = msg->elements[i].num_values; @@ -1039,6 +1042,7 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) break; case MAP_RENAME: + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Renaming %s -> %s", attr->local_name, attr->u.rename.remote_name); elm = talloc(mp, struct ldb_message_element); elm->name = talloc_strdup(elm, attr->u.rename.remote_name); @@ -1047,6 +1051,7 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) break; case MAP_CONVERT: + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Converting %s -> %s", attr->local_name, attr->u.convert.remote_name); elm = talloc(mp, struct ldb_message_element); elm->name = talloc_strdup(elm, attr->u.rename.remote_name); @@ -1064,10 +1069,11 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) case MAP_GENERATE: case MAP_IGNORE: ldb_debug(module->ldb, LDB_DEBUG_FATAL, "This line should never be reached"); - break; + continue; } ldb_msg_add(module->ldb, mp, elm, 0); } else { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Fallback storing %s", msg->elements[i].name); elm = talloc(fb, struct ldb_message_element); elm->num_values = msg->elements[i].num_values; @@ -1197,13 +1203,13 @@ static int map_modify(struct ldb_module *module, const struct ldb_message *msg) ldb_msg_add_string(module->ldb, fb, "isMapped", "TRUE"); fb_ret = ldb_next_add_record(module, fb); } - } + } else fb_ret = 0; talloc_free(fb); if (mp->num_elements > 0) { ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Modifying mapped record with %d elements", mp->num_elements); mp_ret = ldb_modify(privdat->mapped_ldb, mp); - } + } else mp_ret = 0; talloc_free(mp); return (mp_ret == -1 || fb_ret == -1)?-1:0; -- cgit From 4f4dae05f03c76b81cbc71ee80f7f1a34644936f Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 1 Sep 2005 18:55:51 +0000 Subject: r9912: Fix another bug in ldb_map. (This used to be commit 4c3b37d660e798764e35a31221f4939ab6f36948) --- source4/lib/ldb/modules/ldb_map.c | 165 +++++++++++++++++++++----------------- source4/lib/ldb/modules/ldb_map.h | 4 + 2 files changed, 97 insertions(+), 72 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index f3ece2621e..3bbf893a27 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -1001,37 +1001,39 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) for (i = 0; i < msg->num_elements; i++) { const struct ldb_map_attribute *attr; struct ldb_message_element *elm = NULL; - enum ldb_map_attr_type map_type; - int j; + int j, k; int mapped = 0; if (ldb_attr_cmp(msg->elements[i].name, "objectClass") == 0) continue; - attr = map_find_attr_local(privdat, msg->elements[i].name); + /* Loop over all attribute_maps with msg->elements[i].name as local_name */ + for (k = 0; privdat->attribute_maps[k].local_name; k++) { + if (ldb_attr_cmp(msg->elements[i].name, privdat->attribute_maps[k].local_name) != 0) + continue; - if (!attr) { - ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Undefined local attribute '%s', ignoring\n", msg->elements[i].name); - map_type = MAP_IGNORE; - } else map_type = attr->type; + attr = &privdat->attribute_maps[k]; - /* Decide whether or not we need to map or fallback */ - switch (map_type) { - case MAP_GENERATE: - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Generating from %s", attr->local_name); - attr->u.generate.generate_remote(module, attr->local_name, msg, mp, fb); - continue; - case MAP_KEEP: - mapped = map_msg_valid_attr(module, mp, attr->local_name); - break; - case MAP_IGNORE: mapped = 0; break; - case MAP_CONVERT: - case MAP_RENAME: mapped = map_msg_valid_attr(module, mp, attr->u.rename.remote_name); - break; - } + /* Decide whether or not we need to map or fallback */ + switch (attr->type) { + case MAP_GENERATE: + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Generating from %s", attr->local_name); + attr->u.generate.generate_remote(module, attr->local_name, msg, mp, fb); + mapped++; + continue; + case MAP_KEEP: + if (!map_msg_valid_attr(module, mp, attr->local_name)) + continue; + break; + case MAP_IGNORE: continue; + case MAP_CONVERT: + case MAP_RENAME: + if (!map_msg_valid_attr(module, mp, attr->u.rename.remote_name)) + continue; + break; + } - if (mapped) { - switch (map_type) { + switch (attr->type) { case MAP_KEEP: ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Keeping %s", attr->local_name); elm = talloc(fb, struct ldb_message_element); @@ -1062,8 +1064,6 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) elm->values[j] = attr->u.convert.convert_local(module, mp, &msg->elements[i].values[j]); } - mapped = map_msg_valid_attr(module, mp, attr->u.convert.remote_name); - break; case MAP_GENERATE: @@ -1071,8 +1071,12 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) ldb_debug(module->ldb, LDB_DEBUG_FATAL, "This line should never be reached"); continue; } + ldb_msg_add(module->ldb, mp, elm, 0); - } else { + mapped++; + } + + if (mapped == 0) { ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Fallback storing %s", msg->elements[i].name); elm = talloc(fb, struct ldb_message_element); @@ -1131,69 +1135,82 @@ static int map_modify(struct ldb_module *module, const struct ldb_message *msg) /* Loop over mi and call generate_remote for each attribute */ for (i = 0; i < msg->num_elements; i++) { const struct ldb_map_attribute *attr; - enum ldb_map_attr_type map_type; + int k; + int mapped = 0; if (ldb_attr_cmp(msg->elements[i].name, "isMapped") == 0) continue; - attr = map_find_attr_local(privdat, msg->elements[i].name); + for (k = 0; privdat->attribute_maps[k].local_name; k++) + { + if (ldb_attr_cmp(privdat->attribute_maps[k].local_name, msg->elements[i].name) != 0) + continue; - if (!attr) { - ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Undefined local attribute '%s', ignoring\n", msg->elements[i].name); - map_type = MAP_IGNORE; - } else map_type = attr->type; - - switch (map_type) { - case MAP_IGNORE: /* Add to fallback message */ - elm = talloc(fb, struct ldb_message_element); + attr = &privdat->attribute_maps[k]; - elm->num_values = msg->elements[i].num_values; - elm->values = talloc_reference(elm, msg->elements[i].values); - elm->name = talloc_strdup(elm, msg->elements[i].name); - - ldb_msg_add(module->ldb, fb, elm, msg->elements[i].flags); - break; - case MAP_RENAME: - elm = talloc(mp, struct ldb_message_element); + switch (attr->type) { + case MAP_IGNORE: continue; + case MAP_RENAME: + elm = talloc(mp, struct ldb_message_element); - elm->name = talloc_strdup(elm, attr->u.rename.remote_name); - elm->num_values = msg->elements[i].num_values; - elm->values = talloc_array(elm, struct ldb_val, elm->num_values); - for (j = 0; j < elm->num_values; j++) { - elm->values[j] = msg->elements[i].values[j]; - } + elm->name = talloc_strdup(elm, attr->u.rename.remote_name); + elm->num_values = msg->elements[i].num_values; + elm->values = talloc_array(elm, struct ldb_val, elm->num_values); + for (j = 0; j < elm->num_values; j++) { + elm->values[j] = msg->elements[i].values[j]; + } - ldb_msg_add(module->ldb, mp, elm, msg->elements[i].flags); - break; + ldb_msg_add(module->ldb, mp, elm, msg->elements[i].flags); + mapped++; + continue; - case MAP_CONVERT: - elm = talloc(mp, struct ldb_message_element); + case MAP_CONVERT: + elm = talloc(mp, struct ldb_message_element); - elm->name = talloc_strdup(elm, attr->u.rename.remote_name); - elm->num_values = msg->elements[i].num_values; - elm->values = talloc_array(elm, struct ldb_val, elm->num_values); - - for (j = 0; j < elm->num_values; j++) { - elm->values[j] = attr->u.convert.convert_local(module, mp, &msg->elements[i].values[j]); - } + elm->name = talloc_strdup(elm, attr->u.rename.remote_name); + elm->num_values = msg->elements[i].num_values; + elm->values = talloc_array(elm, struct ldb_val, elm->num_values); - ldb_msg_add(module->ldb, mp, elm, msg->elements[i].flags); - break; + for (j = 0; j < elm->num_values; j++) { + elm->values[j] = attr->u.convert.convert_local(module, mp, &msg->elements[i].values[j]); + } - case MAP_KEEP: - elm = talloc(mp, struct ldb_message_element); + ldb_msg_add(module->ldb, mp, elm, msg->elements[i].flags); + mapped++; + continue; + + case MAP_KEEP: + elm = talloc(mp, struct ldb_message_element); + + elm->num_values = msg->elements[i].num_values; + elm->values = talloc_array(elm, struct ldb_val, elm->num_values); + for (j = 0; j < elm->num_values; j++) { + elm->values[j] = msg->elements[i].values[j]; + } + + elm->name = talloc_strdup(elm, msg->elements[i].name); + + ldb_msg_add(module->ldb, mp, elm, msg->elements[i].flags); + mapped++; + continue; + + case MAP_GENERATE: + attr->u.generate.generate_remote(module, attr->local_name, msg, mp, fb); + mapped++; + continue; + } + } + + if (mapped == 0) {/* Add to fallback message */ + elm = talloc(fb, struct ldb_message_element); elm->num_values = msg->elements[i].num_values; elm->values = talloc_reference(elm, msg->elements[i].values); elm->name = talloc_strdup(elm, msg->elements[i].name); - ldb_msg_add(module->ldb, mp, elm, msg->elements[i].flags); - break; + ldb_msg_add(module->ldb, fb, elm, msg->elements[i].flags); - case MAP_GENERATE: - attr->u.generate.generate_remote(module, attr->local_name, msg, mp, fb); - break; - } + } } if (fb->num_elements > 0) { @@ -1356,7 +1373,11 @@ static struct ldb_val map_convert_local_dn(struct ldb_module *module, TALLOC_CTX newval = talloc(ctx, struct ldb_val); newval->data = (uint8_t *)ldb_dn_linearize(ctx, newdn); - newval->length = strlen((char *)newval->data); + if (newval->data) { + newval->length = strlen((char *)newval->data); + } else { + newval->length = 0; + } talloc_free(newdn); diff --git a/source4/lib/ldb/modules/ldb_map.h b/source4/lib/ldb/modules/ldb_map.h index 984a4a2cd5..42eba23aa6 100644 --- a/source4/lib/ldb/modules/ldb_map.h +++ b/source4/lib/ldb/modules/ldb_map.h @@ -2,6 +2,7 @@ ldb database library - map backend Copyright (C) Jelmer Vernooij 2005 + Development sponsored by the Google Summer of Code program ** NOTE! The following LGPL license applies to the ldb ** library. This does NOT imply that all of Samba is released @@ -65,6 +66,9 @@ struct ldb_map_attribute struct { const char *remote_name; struct ldb_val (*convert_local) (struct ldb_module *, TALLOC_CTX *, const struct ldb_val *); + + /* an entry can have convert_remote set to NULL, as long as there as an entry with the same local_name + * that is non-NULL before it. */ struct ldb_val (*convert_remote) (struct ldb_module *, TALLOC_CTX *, const struct ldb_val *); } convert; -- cgit From 08f630be8230ce061badd84bef952d5753afdff0 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 1 Sep 2005 20:28:03 +0000 Subject: r9915: Some more mappings. Fix weird sAMAccountName values. (This used to be commit 8ff1358f401e0086b941f4ff73af5d4c38a1f8bf) --- source4/lib/ldb/modules/ldb_map.c | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index 3bbf893a27..9b62b1314a 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -324,6 +324,8 @@ static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, TALL } if (map_type == MAP_CONVERT) { + if (!attr->u.convert.convert_local) + return NULL; newvalue = attr->u.convert.convert_local(module, new_tree, &value); } else { newvalue = ldb_val_dup(new_tree, &value); @@ -435,6 +437,11 @@ static struct ldb_dn *map_local_dn(struct ldb_module *module, TALLOC_CTX *ctx, c case MAP_CONVERT: newdn->components[i].name = talloc_strdup(newdn->components, attr->u.convert.remote_name); + if (attr->u.convert.convert_local == NULL) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "convert_local not set for attribute '%s' used in DN!", dn->components[i].name); + talloc_free(newdn); + return NULL; + } newdn->components[i].value = attr->u.convert.convert_local(module, newdn->components, &dn->components[i].value); break; @@ -658,8 +665,12 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c case MAP_GENERATE: ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Generating local attribute %s", attr->local_name); + if (!attr->u.generate.generate_local) + continue; + elm = attr->u.generate.generate_local(module, msg, attr->local_name, mi); - if (!elm) continue; + if (!elm) + continue; ldb_msg_add(module->ldb, msg, elm, elm->flags); break; @@ -1039,7 +1050,12 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) elm = talloc(fb, struct ldb_message_element); elm->num_values = msg->elements[i].num_values; - elm->values = talloc_reference(elm, msg->elements[i].values); + elm->values = talloc_array(elm, struct ldb_val, elm->num_values); + + for (j = 0; j < elm->num_values; j++) { + elm->values[j] = ldb_val_dup(elm, &msg->elements[i].values[j]); + } + elm->name = talloc_strdup(elm, msg->elements[i].name); break; @@ -1049,10 +1065,16 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) elm->name = talloc_strdup(elm, attr->u.rename.remote_name); elm->num_values = msg->elements[i].num_values; - elm->values = talloc_reference(elm, msg->elements[i].values); + elm->values = talloc_array(elm, struct ldb_val, elm->num_values); + + for (j = 0; j < elm->num_values; j++) { + elm->values[j] = ldb_val_dup(elm, &msg->elements[i].values[j]); + } break; case MAP_CONVERT: + if (attr->u.convert.convert_local == NULL) + continue; ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Converting %s -> %s", attr->local_name, attr->u.convert.remote_name); elm = talloc(mp, struct ldb_message_element); @@ -1165,6 +1187,8 @@ static int map_modify(struct ldb_module *module, const struct ldb_message *msg) continue; case MAP_CONVERT: + if (!attr->u.convert.convert_local) + continue; elm = talloc(mp, struct ldb_message_element); elm->name = talloc_strdup(elm, attr->u.rename.remote_name); @@ -1397,7 +1421,11 @@ static struct ldb_val map_convert_remote_dn(struct ldb_module *module, TALLOC_CT newval = talloc(ctx, struct ldb_val); newval->data = (uint8_t *)ldb_dn_linearize(ctx, newdn); - newval->length = strlen((char *)newval->data); + if (newval->data) { + newval->length = strlen((char *)newval->data); + } else { + newval->length = 0; + } talloc_free(newdn); -- cgit From f14f4fd7068e0ce55350c713d1925680876606bb Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 1 Sep 2005 21:32:43 +0000 Subject: r9918: Fix two copy-n-paste bugs that were preventing the modification of special DN's when the rdn_name or timestamps modules were in use. (This used to be commit c61efb2ff851f8f55b4747c8068c7e780083e35c) --- source4/lib/ldb/modules/rdn_name.c | 4 ++-- source4/lib/ldb/modules/timestamps.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/rdn_name.c b/source4/lib/ldb/modules/rdn_name.c index d59205c6e4..09e9c72811 100644 --- a/source4/lib/ldb/modules/rdn_name.c +++ b/source4/lib/ldb/modules/rdn_name.c @@ -159,12 +159,12 @@ static int rdn_name_modify_record(struct ldb_module *module, const struct ldb_me /* do not manipulate our control entries */ if (ldb_dn_is_special(msg->dn)) { - return ldb_next_add_record(module, msg); + return ldb_next_modify_record(module, msg); } /* Perhaps someone above us knows better */ if ((attribute = rdn_name_find_attribute(msg, "name")) != NULL ) { - return ldb_next_add_record(module, msg); + return ldb_next_modify_record(module, msg); } msg2 = talloc(module, struct ldb_message); diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index 4819e0466b..f712505211 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -162,7 +162,7 @@ static int timestamps_modify_record(struct ldb_module *module, const struct ldb_ /* do not manipulate our control entries */ if (ldb_dn_is_special(msg->dn)) { - return ldb_next_add_record(module, msg); + return ldb_next_modify_record(module, msg); } timeval = time(NULL); -- cgit From 4462869db22983d1a6634fd7bec5c6a073404b10 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 2 Sep 2005 11:33:35 +0000 Subject: r9948: Be a bit less verbose (This used to be commit 071dba2d0ae964e9901adf0c4870894deed43650) --- source4/lib/ldb/modules/ldb_map.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index 9b62b1314a..ba98a5f495 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -483,7 +483,7 @@ static const char **ldb_map_attrs(struct ldb_module *module, const char *const a enum ldb_map_attr_type map_type; if (!attr) { - ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Local attribute '%s' does not have a definition!\n", attrs[i]); + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Local attribute '%s' does not have a definition!\n", attrs[i]); map_type = MAP_IGNORE; } else map_type = attr->type; -- cgit From 8919d6bf9a88ce9ac43dae61989c33082c984b66 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 17 Sep 2005 19:25:50 +0000 Subject: r10299: remove the public (un)lock functions and introduce a transaction based private ldb API ldb_sqlite3 is already working with this model and ldb_tdb will do as soon as tridge finishes the tdb transaction code. currently the transactions are always implicit and wrap any single ldb API call except searching, the transaction functions are currently not made public on purpose. Simo. (This used to be commit 1da4ac2cdcb7e54076f85242a93784260dced918) --- source4/lib/ldb/modules/ldb_map.c | 28 ++++++++++++++-------------- source4/lib/ldb/modules/rdn_name.c | 32 ++++++++++++++++---------------- source4/lib/ldb/modules/schema.c | 28 ++++++++++++++-------------- source4/lib/ldb/modules/skel.c | 32 ++++++++++++++++---------------- source4/lib/ldb/modules/timestamps.c | 32 ++++++++++++++++---------------- 5 files changed, 76 insertions(+), 76 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index ba98a5f495..93ae13ffc2 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -1256,14 +1256,14 @@ static int map_modify(struct ldb_module *module, const struct ldb_message *msg) return (mp_ret == -1 || fb_ret == -1)?-1:0; } -static int map_lock(struct ldb_module *module, const char *lockname) +static int map_start_trans(struct ldb_module *module) { - return ldb_next_named_lock(module, lockname); + return ldb_next_start_trans(module); } -static int map_unlock(struct ldb_module *module, const char *lockname) +static int map_end_trans(struct ldb_module *module, int status) { - return ldb_next_named_unlock(module, lockname); + return ldb_next_end_trans(module, status); } /* @@ -1280,16 +1280,16 @@ static const char *map_errstring(struct ldb_module *module) } static const struct ldb_module_ops map_ops = { - .name = "map", - .search = map_search, - .search_bytree = map_search_bytree, - .add_record = map_add, - .modify_record = map_modify, - .delete_record = map_delete, - .rename_record = map_rename, - .named_lock = map_lock, - .named_unlock = map_unlock, - .errstring = map_errstring + .name = "map", + .search = map_search, + .search_bytree = map_search_bytree, + .add_record = map_add, + .modify_record = map_modify, + .delete_record = map_delete, + .rename_record = map_rename, + .start_transaction = map_start_trans, + .end_transaction = map_end_trans, + .errstring = map_errstring }; static char *map_find_url(struct ldb_context *ldb, const char *name) diff --git a/source4/lib/ldb/modules/rdn_name.c b/source4/lib/ldb/modules/rdn_name.c index 09e9c72811..ed5400176c 100644 --- a/source4/lib/ldb/modules/rdn_name.c +++ b/source4/lib/ldb/modules/rdn_name.c @@ -217,16 +217,16 @@ static int rdn_name_rename_record(struct ldb_module *module, const struct ldb_dn return ldb_next_rename_record(module, olddn, newdn); } -static int rdn_name_lock(struct ldb_module *module, const char *lockname) +static int rdn_start_trans(struct ldb_module *module) { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_lock\n"); - return ldb_next_named_lock(module, lockname); + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_start_trans\n"); + return ldb_next_start_trans(module); } -static int rdn_name_unlock(struct ldb_module *module, const char *lockname) +static int rdn_end_trans(struct ldb_module *module, int status) { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_unlock\n"); - return ldb_next_named_unlock(module, lockname); + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_end_trans\n"); + return ldb_next_end_trans(module, status); } /* return extended error information */ @@ -254,16 +254,16 @@ static int rdn_name_destructor(void *module_ctx) } static const struct ldb_module_ops rdn_name_ops = { - .name = "rdn_name", - .search = rdn_name_search, - .search_bytree = rdn_name_search_bytree, - .add_record = rdn_name_add_record, - .modify_record = rdn_name_modify_record, - .delete_record = rdn_name_delete_record, - .rename_record = rdn_name_rename_record, - .named_lock = rdn_name_lock, - .named_unlock = rdn_name_unlock, - .errstring = rdn_name_errstring + .name = "rdn_name", + .search = rdn_name_search, + .search_bytree = rdn_name_search_bytree, + .add_record = rdn_name_add_record, + .modify_record = rdn_name_modify_record, + .delete_record = rdn_name_delete_record, + .rename_record = rdn_name_rename_record, + .start_transaction = rdn_start_trans, + .end_transaction = rdn_end_trans, + .errstring = rdn_name_errstring }; diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index baf038de0c..9406d54ce7 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -501,12 +501,12 @@ static int schema_rename_record(struct ldb_module *module, const struct ldb_dn * return ldb_next_rename_record(module, olddn, newdn); } -static int schema_named_lock(struct ldb_module *module, const char *name) { - return ldb_next_named_lock(module, name); +static int schema_start_trans(struct ldb_module *module) { + return ldb_next_start_trans(module); } -static int schema_named_unlock(struct ldb_module *module, const char *name) { - return ldb_next_named_unlock(module, name); +static int schema_end_trans(struct ldb_module *module, int status) { + return ldb_next_end_trans(module, status); } /* return extended error information */ @@ -533,16 +533,16 @@ static int schema_destructor(void *module_ctx) } static const struct ldb_module_ops schema_ops = { - .name = "schema", - .search = schema_search, - .search_bytree = schema_search_bytree, - .add_record = schema_add_record, - .modify_record = schema_modify_record, - .delete_record = schema_delete_record, - .rename_record = schema_rename_record, - .named_lock = schema_named_lock, - .named_unlock = schema_named_unlock, - .errstring = schema_errstring, + .name = "schema", + .search = schema_search, + .search_bytree = schema_search_bytree, + .add_record = schema_add_record, + .modify_record = schema_modify_record, + .delete_record = schema_delete_record, + .rename_record = schema_rename_record, + .start_transaction = schema_start_trans, + .end_transaction = schema_end_trans, + .errstring = schema_errstring, }; #ifdef HAVE_DLOPEN_DISABLED diff --git a/source4/lib/ldb/modules/skel.c b/source4/lib/ldb/modules/skel.c index 57c89a6a65..37c0417c64 100644 --- a/source4/lib/ldb/modules/skel.c +++ b/source4/lib/ldb/modules/skel.c @@ -73,16 +73,16 @@ static int skel_rename_record(struct ldb_module *module, const struct ldb_dn *ol return ldb_next_rename_record(module, olddn, newdn); } -/* named_lock */ -static int skel_named_lock(struct ldb_module *module, const char *lockname) +/* start a transaction */ +static int skel_start_trans(struct ldb_module *module) { - return ldb_next_named_lock(module, lockname); + return ldb_next_start_trans(module); } -/* named_unlock */ -static int skel_named_unlock(struct ldb_module *module, const char *lockname) +/* end a transaction */ +static int skel_end_trans(struct ldb_module *module, int status) { - return ldb_next_named_unlock(module, lockname); + return ldb_next_end_trans(module, status); } /* return extended error information */ @@ -101,16 +101,16 @@ static int skel_destructor(void *module_ctx) } static const struct ldb_module_ops skel_ops = { - .name = "skel", - .search = skel_search, - .search_bytree = skel_search_bytree, - .add_record = skel_add_record, - .modify_record = skel_modify_record, - .delete_record = skel_delete_record, - .rename_record = skel_rename_record, - .named_lock = skel_named_lock, - .named_unlock = skel_named_unlock, - .errstring = skel_errstring + .name = "skel", + .search = skel_search, + .search_bytree = skel_search_bytree, + .add_record = skel_add_record, + .modify_record = skel_modify_record, + .delete_record = skel_delete_record, + .rename_record = skel_rename_record, + .start_transaction = skel_start_trans, + .end_transaction = skel_end_trans, + .errstring = skel_errstring }; #ifdef HAVE_DLOPEN_DISABLED diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index f712505211..6687b1929d 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -215,16 +215,16 @@ static int timestamps_rename_record(struct ldb_module *module, const struct ldb_ return ldb_next_rename_record(module, olddn, newdn); } -static int timestamps_lock(struct ldb_module *module, const char *lockname) +static int timestamps_start_trans(struct ldb_module *module) { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_lock\n"); - return ldb_next_named_lock(module, lockname); + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_start_trans\n"); + return ldb_next_start_trans(module); } -static int timestamps_unlock(struct ldb_module *module, const char *lockname) +static int timestamps_end_trans(struct ldb_module *module, int status) { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_unlock\n"); - return ldb_next_named_unlock(module, lockname); + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_end_trans\n"); + return ldb_next_end_trans(module, status); } /* return extended error information */ @@ -252,16 +252,16 @@ static int timestamps_destructor(void *module_ctx) } static const struct ldb_module_ops timestamps_ops = { - .name = "timestamps", - .search = timestamps_search, - .search_bytree = timestamps_search_bytree, - .add_record = timestamps_add_record, - .modify_record = timestamps_modify_record, - .delete_record = timestamps_delete_record, - .rename_record = timestamps_rename_record, - .named_lock = timestamps_lock, - .named_unlock = timestamps_unlock, - .errstring = timestamps_errstring + .name = "timestamps", + .search = timestamps_search, + .search_bytree = timestamps_search_bytree, + .add_record = timestamps_add_record, + .modify_record = timestamps_modify_record, + .delete_record = timestamps_delete_record, + .rename_record = timestamps_rename_record, + .start_transaction = timestamps_start_trans, + .end_transaction = timestamps_end_trans, + .errstring = timestamps_errstring }; -- cgit From 16aff2a184f7fab64d718b356056070e305e99e9 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 18 Sep 2005 18:49:06 +0000 Subject: r10305: start implementing better error handling changed the prioivate modules API error string are now not spread over all modules but are kept in a single place. This allows a better control of memory and error reporting. (This used to be commit 3fc676ac1d6f59d08bedbbd9377986154cf84ce4) --- source4/lib/ldb/modules/ldb_map.c | 27 ++-------- source4/lib/ldb/modules/rdn_name.c | 43 +++------------ source4/lib/ldb/modules/schema.c | 102 ++++++++++++++++------------------- source4/lib/ldb/modules/skel.c | 13 ++--- source4/lib/ldb/modules/timestamps.c | 34 +----------- 5 files changed, 62 insertions(+), 157 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index 93ae13ffc2..69e021b4ee 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -97,7 +97,6 @@ static const struct ldb_map_objectclass *map_find_objectclass_remote(struct ldb_ struct map_private { struct ldb_map_context context; - const char *last_err_string; }; static struct ldb_map_context *map_get_privdat(struct ldb_module *module) @@ -807,8 +806,7 @@ static int map_search_bytree_mp(struct ldb_module *module, const struct ldb_dn * talloc_free(newattrs); if (mpret == -1) { - struct map_private *map_private = module->private_data; - map_private->last_err_string = ldb_errstring(privdat->mapped_ldb); + ldb_set_errstring(module, talloc_strdup(module, ldb_errstring(privdat->mapped_ldb))); return -1; } @@ -910,13 +908,12 @@ static int map_search(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, const char *expression, const char * const *attrs, struct ldb_message ***res) { - struct map_private *map = module->private_data; struct ldb_parse_tree *tree; int ret; tree = ldb_parse_tree(NULL, expression); if (tree == NULL) { - map->last_err_string = "expression parse failed"; + ldb_set_errstring(module, talloc_strdup(module, "expression parse failed")); return -1; } @@ -1121,7 +1118,7 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) ldb_msg_add_string(module->ldb, fb, "isMapped", "TRUE"); ret = ldb_next_add_record(module, fb); if (ret == -1) { - ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Adding fallback record failed: %s", ldb_next_errstring(module)); + ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Adding fallback record failed: %s", ldb_errstring(module->ldb)); return -1; } @@ -1266,19 +1263,6 @@ static int map_end_trans(struct ldb_module *module, int status) return ldb_next_end_trans(module, status); } -/* - return extended error information -*/ -static const char *map_errstring(struct ldb_module *module) -{ - struct map_private *map = module->private_data; - - if (map->last_err_string) - return map->last_err_string; - - return ldb_next_errstring(module); -} - static const struct ldb_module_ops map_ops = { .name = "map", .search = map_search, @@ -1288,8 +1272,7 @@ static const struct ldb_module_ops map_ops = { .delete_record = map_delete, .rename_record = map_rename, .start_transaction = map_start_trans, - .end_transaction = map_end_trans, - .errstring = map_errstring + .end_transaction = map_end_trans }; static char *map_find_url(struct ldb_context *ldb, const char *name) @@ -1354,8 +1337,6 @@ struct ldb_module *ldb_map_init(struct ldb_context *ldb, const struct ldb_map_at talloc_free(url); - data->last_err_string = NULL; - /* Get list of attribute maps */ j = 0; data->context.attribute_maps = NULL; diff --git a/source4/lib/ldb/modules/rdn_name.c b/source4/lib/ldb/modules/rdn_name.c index ed5400176c..c1a0c0852a 100644 --- a/source4/lib/ldb/modules/rdn_name.c +++ b/source4/lib/ldb/modules/rdn_name.c @@ -37,10 +37,6 @@ #include "ldb/include/ldb_private.h" #include -struct private_data { - const char *error_string; -}; - static int rdn_name_search(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, const char *expression, const char * const *attrs, struct ldb_message ***res) @@ -73,8 +69,6 @@ static struct ldb_message_element *rdn_name_find_attribute(const struct ldb_mess /* add_record: add crateTimestamp/modifyTimestamp attributes */ static int rdn_name_add_record(struct ldb_module *module, const struct ldb_message *msg) { - struct private_data *data = (struct private_data *)module->private_data; - struct ldb_message *msg2; struct ldb_message_element *attribute; struct ldb_dn_component *rdn; @@ -134,8 +128,11 @@ static int rdn_name_add_record(struct ldb_module *module, const struct ldb_messa } } if (i == attribute->num_values) { - data->error_string = talloc_asprintf(data, "RDN mismatch on %s: %s", ldb_dn_linearize(msg2, msg2->dn), rdn->name); - ldb_debug(module->ldb, LDB_DEBUG_FATAL, "%s\n", data->error_string); + char *error_string = talloc_asprintf(module, "RDN mismatch on %s: %s", ldb_dn_linearize(msg2, msg2->dn), rdn->name); + if (error_string) { + ldb_set_errstring(module, error_string); + ldb_debug(module->ldb, LDB_DEBUG_FATAL, "%s\n", error_string); + } talloc_free(msg2); return -1; } @@ -229,23 +226,6 @@ static int rdn_end_trans(struct ldb_module *module, int status) return ldb_next_end_trans(module, status); } -/* return extended error information */ -static const char *rdn_name_errstring(struct ldb_module *module) -{ - struct private_data *data = (struct private_data *)module->private_data; - - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_errstring\n"); - if (data->error_string) { - const char *error; - - error = data->error_string; - data->error_string = NULL; - return error; - } - - return ldb_next_errstring(module); -} - static int rdn_name_destructor(void *module_ctx) { /* struct ldb_module *ctx = module_ctx; */ @@ -262,8 +242,7 @@ static const struct ldb_module_ops rdn_name_ops = { .delete_record = rdn_name_delete_record, .rename_record = rdn_name_rename_record, .start_transaction = rdn_start_trans, - .end_transaction = rdn_end_trans, - .errstring = rdn_name_errstring + .end_transaction = rdn_end_trans }; @@ -275,20 +254,12 @@ struct ldb_module *rdn_name_module_init(struct ldb_context *ldb, const char *opt #endif { struct ldb_module *ctx; - struct private_data *data; ctx = talloc(ldb, struct ldb_module); if (!ctx) return NULL; - data = talloc(ctx, struct private_data); - if (!data) { - talloc_free(ctx); - return NULL; - } - - data->error_string = NULL; - ctx->private_data = data; + ctx->private_data = NULL; ctx->ldb = ldb; ctx->prev = ctx->next = NULL; ctx->ops = &rdn_name_ops; diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index 9406d54ce7..1a2c2b8f97 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -34,6 +34,7 @@ #include "includes.h" #include "ldb/include/ldb.h" +#include "ldb/include/ldb_errors.h" #include "ldb/include/ldb_private.h" #define SCHEMA_FLAG_RESET 0 @@ -51,10 +52,6 @@ check there's only one structrual class (or a chain of structural classes) */ -struct private_data { - const char *error_string; -}; - struct schema_attribute { int flags; char *name; @@ -189,8 +186,8 @@ static int add_attribute_uniq(void *mem_ctx, struct schema_attribute_list *list, recursively get parent objectlasses attributes */ static int get_attr_list_recursive(struct ldb_module *module, struct schema_structures *schema_struct) { - struct private_data *data = (struct private_data *)module->private_data; struct ldb_message **srch; + char *error_string; int i, j; int ret; @@ -213,14 +210,20 @@ static int get_attr_list_recursive(struct ldb_module *module, struct schema_stru if (ret <= 0) { /* Schema DB Error: Error occurred retrieving Object Class Description */ - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Error retrieving Objectclass %s.\n", schema_struct->objectclasses.attr[i].name); - data->error_string = "Internal error. Error retrieving schema objectclass"; + error_string = talloc_asprintf(module, "Error retrieving Objectclass %s.\n", schema_struct->objectclasses.attr[i].name); + if (error_string) { + ldb_set_errstring(module, error_string); + ldb_debug(module->ldb, LDB_DEBUG_ERROR, error_string); + } return -1; } if (ret > 1) { /* Schema DB Error: Too Many Records */ - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Too many records found retrieving Objectclass %s.\n", schema_struct->objectclasses.attr[i].name); - data->error_string = "Internal error. Too many records searching for schema objectclass"; + error_string = talloc_asprintf(module, "Too many records found retrieving Objectclass %s.\n", schema_struct->objectclasses.attr[i].name); + if (error_string) { + ldb_set_errstring(module, error_string); + ldb_debug(module->ldb, LDB_DEBUG_ERROR, error_string); + } return -1; } @@ -297,8 +300,8 @@ static int schema_search_bytree(struct ldb_module *module, const struct ldb_dn * /* add_record */ static int schema_add_record(struct ldb_module *module, const struct ldb_message *msg) { - struct private_data *data = (struct private_data *)module->private_data; struct schema_structures *entry_structs; + char *error_string; unsigned int i; int ret; @@ -342,13 +345,15 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message entry_structs->required_attrs.attr[i].name); if (attr == NULL) { /* not found */ - ldb_debug(module->ldb, LDB_DEBUG_ERROR, + error_string = talloc_asprintf(module, "The required_attrs attribute %s is missing.\n", entry_structs->required_attrs.attr[i].name); - - data->error_string = "Objectclass violation, a required attribute is missing"; + if (error_string) { + ldb_set_errstring(module, error_string); + ldb_debug(module->ldb, LDB_DEBUG_ERROR, error_string); + } talloc_free(entry_structs); - return -1; + return LDB_ERR_OBJECT_CLASS_VIOLATION; } /* mark the attribute as checked */ @@ -365,13 +370,15 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message entry_structs->entry_attrs.attr[i].name); if (attr == NULL) { /* not found */ - ldb_debug(module->ldb, LDB_DEBUG_ERROR, + error_string = talloc_asprintf(module, "The attribute %s is not referenced by any objectclass.\n", entry_structs->entry_attrs.attr[i].name); - - data->error_string = "Objectclass violation, an invalid attribute name was found"; + if (error_string) { + ldb_set_errstring(module, error_string); + ldb_debug(module->ldb, LDB_DEBUG_ERROR, error_string); + } talloc_free(entry_structs); - return -1; + return LDB_ERR_OBJECT_CLASS_VIOLATION; } } } @@ -384,8 +391,8 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message /* modify_record */ static int schema_modify_record(struct ldb_module *module, const struct ldb_message *msg) { - struct private_data *data = (struct private_data *)module->private_data; struct schema_structures *entry_structs; + char *error_string; unsigned int i; int ret; @@ -437,25 +444,30 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess entry_structs->required_attrs.attr[i].name); if (attr == NULL) { /* not found */ - ldb_debug(module->ldb, LDB_DEBUG_ERROR, + error_string = talloc_asprintf(module, "The required_attrs attribute %s is missing.\n", entry_structs->required_attrs.attr[i].name); - - data->error_string = "Objectclass violation, a required attribute is missing"; + if (error_string) { + ldb_set_errstring(module, error_string); + ldb_debug(module->ldb, LDB_DEBUG_ERROR, error_string); + } talloc_free(entry_structs); - return -1; + return LDB_ERR_OBJECT_CLASS_VIOLATION; } /* check we are not trying to delete a required attribute */ /* TODO: consider multivalued attrs */ if ((attr->flags & SCHEMA_FLAG_MOD_DELETE) != 0) { - ldb_debug(module->ldb, LDB_DEBUG_ERROR, + error_string = talloc_asprintf(module, "Trying to delete the required attribute %s.\n", attr->name); + if (error_string) { + ldb_set_errstring(module, error_string); + ldb_debug(module->ldb, LDB_DEBUG_ERROR, error_string); + } - data->error_string = "Objectclass violation, a required attribute cannot be removed"; talloc_free(entry_structs); - return -1; + return LDB_ERR_OBJECT_CLASS_VIOLATION; } /* mark the attribute as checked */ @@ -472,13 +484,16 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess entry_structs->entry_attrs.attr[i].name); if (attr == NULL) { /* not found */ - ldb_debug(module->ldb, LDB_DEBUG_ERROR, + error_string = talloc_asprintf(module, "The attribute %s is not referenced by any objectclass.\n", entry_structs->entry_attrs.attr[i].name); + if (error_string) { + ldb_set_errstring(module, error_string); + ldb_debug(module->ldb, LDB_DEBUG_ERROR, error_string); + } - data->error_string = "Objectclass violation, an invalid attribute name was found"; talloc_free(entry_structs); - return -1; + return LDB_ERR_OBJECT_CLASS_VIOLATION; } } } @@ -509,22 +524,6 @@ static int schema_end_trans(struct ldb_module *module, int status) { return ldb_next_end_trans(module, status); } -/* return extended error information */ -static const char *schema_errstring(struct ldb_module *module) -{ - struct private_data *data = (struct private_data *)module->private_data; - - if (data->error_string) { - const char *error; - - error = data->error_string; - data->error_string = NULL; - return error; - } - - return ldb_next_errstring(module); -} - static int schema_destructor(void *module_ctx) { /* struct ldb_module *ctx = module_ctx; */ @@ -541,8 +540,7 @@ static const struct ldb_module_ops schema_ops = { .delete_record = schema_delete_record, .rename_record = schema_rename_record, .start_transaction = schema_start_trans, - .end_transaction = schema_end_trans, - .errstring = schema_errstring, + .end_transaction = schema_end_trans }; #ifdef HAVE_DLOPEN_DISABLED @@ -552,21 +550,13 @@ struct ldb_module *schema_module_init(struct ldb_context *ldb, const char *optio #endif { struct ldb_module *ctx; - struct private_data *data; ctx = talloc(ldb, struct ldb_module); if (!ctx) { return NULL; } - data = talloc(ctx, struct private_data); - if (data == NULL) { - talloc_free(ctx); - return NULL; - } - - data->error_string = NULL; - ctx->private_data = data; + ctx->private_data = NULL; ctx->ldb = ldb; ctx->prev = ctx->next = NULL; ctx->ops = &schema_ops; diff --git a/source4/lib/ldb/modules/skel.c b/source4/lib/ldb/modules/skel.c index 37c0417c64..701128cd27 100644 --- a/source4/lib/ldb/modules/skel.c +++ b/source4/lib/ldb/modules/skel.c @@ -38,7 +38,7 @@ struct private_data { - char *errstring; + char *some_private_data; }; /* search */ @@ -85,18 +85,12 @@ static int skel_end_trans(struct ldb_module *module, int status) return ldb_next_end_trans(module, status); } -/* return extended error information */ -static const char *skel_errstring(struct ldb_module *module) -{ - return ldb_next_errstring(module); -} - static int skel_destructor(void *module_ctx) { struct ldb_module *ctx = talloc_get_type(module_ctx, struct ldb_module); struct private_data *data = talloc_get_type(ctx->private_data, struct private_data); /* put your clean-up functions here */ - if (data->errstring) talloc_free(data->errstring); + if (data->some_private_data) talloc_free(data->some_private_data); return 0; } @@ -110,7 +104,6 @@ static const struct ldb_module_ops skel_ops = { .rename_record = skel_rename_record, .start_transaction = skel_start_trans, .end_transaction = skel_end_trans, - .errstring = skel_errstring }; #ifdef HAVE_DLOPEN_DISABLED @@ -132,7 +125,7 @@ struct ldb_module *skel_module_init(struct ldb_context *ldb, const char *options return NULL; } - data->errstring = NULL; + data->some_private_data = NULL; ctx->private_data = data; ctx->ldb = ldb; diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index 6687b1929d..dc91937f85 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -37,10 +37,6 @@ #include "ldb/include/ldb_private.h" #include -struct private_data { - const char *error_string; -}; - static int timestamps_search(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, const char *expression, const char * const *attrs, struct ldb_message ***res) @@ -227,23 +223,6 @@ static int timestamps_end_trans(struct ldb_module *module, int status) return ldb_next_end_trans(module, status); } -/* return extended error information */ -static const char *timestamps_errstring(struct ldb_module *module) -{ - struct private_data *data = (struct private_data *)module->private_data; - - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_errstring\n"); - if (data->error_string) { - const char *error; - - error = data->error_string; - data->error_string = NULL; - return error; - } - - return ldb_next_errstring(module); -} - static int timestamps_destructor(void *module_ctx) { /* struct ldb_module *ctx = module_ctx; */ @@ -260,8 +239,7 @@ static const struct ldb_module_ops timestamps_ops = { .delete_record = timestamps_delete_record, .rename_record = timestamps_rename_record, .start_transaction = timestamps_start_trans, - .end_transaction = timestamps_end_trans, - .errstring = timestamps_errstring + .end_transaction = timestamps_end_trans }; @@ -273,20 +251,12 @@ struct ldb_module *timestamps_module_init(struct ldb_context *ldb, const char *o #endif { struct ldb_module *ctx; - struct private_data *data; ctx = talloc(ldb, struct ldb_module); if (!ctx) return NULL; - data = talloc(ctx, struct private_data); - if (!data) { - talloc_free(ctx); - return NULL; - } - - data->error_string = NULL; - ctx->private_data = data; + ctx->private_data = NULL; ctx->ldb = ldb; ctx->prev = ctx->next = NULL; ctx->ops = ×tamps_ops; -- cgit From 63b43dd12fb579aaaccedd07aaa630cb1cd7aa88 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 24 Sep 2005 15:42:15 +0000 Subject: r10477: expose transactions outside ldb and change the API once more do not autostart transactions on ldb operations if a transaction is already in place test transactions on winsdb all my tests passes so far tridge please confirm this is ok for you (This used to be commit c2bb2a36bdbe0ec7519697a9a9ba7526a0defac2) --- source4/lib/ldb/modules/ldb_map.c | 12 +++++++++--- source4/lib/ldb/modules/rdn_name.c | 13 ++++++++++--- source4/lib/ldb/modules/schema.c | 11 ++++++++--- source4/lib/ldb/modules/skel.c | 11 +++++++++-- source4/lib/ldb/modules/timestamps.c | 13 ++++++++++--- 5 files changed, 46 insertions(+), 14 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index 69e021b4ee..1133991ac4 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -1258,9 +1258,14 @@ static int map_start_trans(struct ldb_module *module) return ldb_next_start_trans(module); } -static int map_end_trans(struct ldb_module *module, int status) +static int map_end_trans(struct ldb_module *module) { - return ldb_next_end_trans(module, status); + return ldb_next_end_trans(module); +} + +static int map_del_trans(struct ldb_module *module) +{ + return ldb_next_del_trans(module); } static const struct ldb_module_ops map_ops = { @@ -1272,7 +1277,8 @@ static const struct ldb_module_ops map_ops = { .delete_record = map_delete, .rename_record = map_rename, .start_transaction = map_start_trans, - .end_transaction = map_end_trans + .end_transaction = map_end_trans, + .del_transaction = map_del_trans }; static char *map_find_url(struct ldb_context *ldb, const char *name) diff --git a/source4/lib/ldb/modules/rdn_name.c b/source4/lib/ldb/modules/rdn_name.c index c1a0c0852a..3e3fbd544f 100644 --- a/source4/lib/ldb/modules/rdn_name.c +++ b/source4/lib/ldb/modules/rdn_name.c @@ -220,10 +220,16 @@ static int rdn_start_trans(struct ldb_module *module) return ldb_next_start_trans(module); } -static int rdn_end_trans(struct ldb_module *module, int status) +static int rdn_end_trans(struct ldb_module *module) { ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_end_trans\n"); - return ldb_next_end_trans(module, status); + return ldb_next_end_trans(module); +} + +static int rdn_del_trans(struct ldb_module *module) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_del_trans\n"); + return ldb_next_del_trans(module); } static int rdn_name_destructor(void *module_ctx) @@ -242,7 +248,8 @@ static const struct ldb_module_ops rdn_name_ops = { .delete_record = rdn_name_delete_record, .rename_record = rdn_name_rename_record, .start_transaction = rdn_start_trans, - .end_transaction = rdn_end_trans + .end_transaction = rdn_end_trans, + .del_transaction = rdn_del_trans }; diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index 1a2c2b8f97..e882f72bd4 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -520,8 +520,12 @@ static int schema_start_trans(struct ldb_module *module) { return ldb_next_start_trans(module); } -static int schema_end_trans(struct ldb_module *module, int status) { - return ldb_next_end_trans(module, status); +static int schema_end_trans(struct ldb_module *module) { + return ldb_next_end_trans(module); +} + +static int schema_del_trans(struct ldb_module *module) { + return ldb_next_del_trans(module); } static int schema_destructor(void *module_ctx) @@ -540,7 +544,8 @@ static const struct ldb_module_ops schema_ops = { .delete_record = schema_delete_record, .rename_record = schema_rename_record, .start_transaction = schema_start_trans, - .end_transaction = schema_end_trans + .end_transaction = schema_end_trans, + .del_transaction = schema_del_trans }; #ifdef HAVE_DLOPEN_DISABLED diff --git a/source4/lib/ldb/modules/skel.c b/source4/lib/ldb/modules/skel.c index 701128cd27..5d14a27a7b 100644 --- a/source4/lib/ldb/modules/skel.c +++ b/source4/lib/ldb/modules/skel.c @@ -80,9 +80,15 @@ static int skel_start_trans(struct ldb_module *module) } /* end a transaction */ -static int skel_end_trans(struct ldb_module *module, int status) +static int skel_end_trans(struct ldb_module *module) { - return ldb_next_end_trans(module, status); + return ldb_next_end_trans(module); +} + +/* delete a transaction */ +static int skel_del_trans(struct ldb_module *module) +{ + return ldb_next_del_trans(module); } static int skel_destructor(void *module_ctx) @@ -104,6 +110,7 @@ static const struct ldb_module_ops skel_ops = { .rename_record = skel_rename_record, .start_transaction = skel_start_trans, .end_transaction = skel_end_trans, + .del_transaction = skel_del_trans, }; #ifdef HAVE_DLOPEN_DISABLED diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index dc91937f85..01e5c2c37c 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -217,10 +217,16 @@ static int timestamps_start_trans(struct ldb_module *module) return ldb_next_start_trans(module); } -static int timestamps_end_trans(struct ldb_module *module, int status) +static int timestamps_end_trans(struct ldb_module *module) { ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_end_trans\n"); - return ldb_next_end_trans(module, status); + return ldb_next_end_trans(module); +} + +static int timestamps_del_trans(struct ldb_module *module) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_del_trans\n"); + return ldb_next_del_trans(module); } static int timestamps_destructor(void *module_ctx) @@ -239,7 +245,8 @@ static const struct ldb_module_ops timestamps_ops = { .delete_record = timestamps_delete_record, .rename_record = timestamps_rename_record, .start_transaction = timestamps_start_trans, - .end_transaction = timestamps_end_trans + .end_transaction = timestamps_end_trans, + .del_transaction = timestamps_del_trans }; -- cgit From 5fd031c97daaa1bf09a7ad80550753acd434075f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 6 Oct 2005 05:24:46 +0000 Subject: r10753: don't require every ldb module to implement both a search_bytree() and a search() function, instead each module now only implements the bytree method, and the expression based search is handled generically by the modules code. This makes for more consistency and less code duplication. fixed the tdb backend to handle BASE searches much more efficiently. They now always only lookup one record, regardless of the search expression (This used to be commit 7e44f9153c5578624e2fca04cdc0a00af0fd9eb4) --- source4/lib/ldb/modules/ldb_map.c | 37 ++++++++---------------------------- source4/lib/ldb/modules/rdn_name.c | 13 ++----------- source4/lib/ldb/modules/schema.c | 8 -------- source4/lib/ldb/modules/skel.c | 7 +++---- source4/lib/ldb/modules/timestamps.c | 9 --------- 5 files changed, 13 insertions(+), 61 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index 1133991ac4..1da1ef661a 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -744,9 +744,9 @@ static int map_delete(struct ldb_module *module, const struct ldb_dn *dn) } /* search fallback database */ -static int map_search_bytree_fb(struct ldb_module *module, const struct ldb_dn *base, - enum ldb_scope scope, struct ldb_parse_tree *tree, - const char * const *attrs, struct ldb_message ***res) +static int map_search_fb(struct ldb_module *module, const struct ldb_dn *base, + enum ldb_scope scope, struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res) { int ret; struct ldb_parse_tree t_and, t_not, t_present, *childs[2]; @@ -771,7 +771,7 @@ static int map_search_bytree_fb(struct ldb_module *module, const struct ldb_dn * } /* Search in the database against which we are mapping */ -static int map_search_bytree_mp(struct ldb_module *module, const struct ldb_dn *base, +static int map_search_mp(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const *attrs, struct ldb_message ***res) { @@ -869,14 +869,14 @@ static int map_search_bytree_mp(struct ldb_module *module, const struct ldb_dn * search for matching records using a ldb_parse_tree */ static int map_search_bytree(struct ldb_module *module, const struct ldb_dn *base, - enum ldb_scope scope, struct ldb_parse_tree *tree, - const char * const *attrs, struct ldb_message ***res) + enum ldb_scope scope, struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res) { struct ldb_message **fbres, **mpres = NULL; int i; int ret_fb, ret_mp; - ret_fb = map_search_bytree_fb(module, base, scope, tree, attrs, &fbres); + ret_fb = map_search_fb(module, base, scope, tree, attrs, &fbres); if (ret_fb == -1) return -1; @@ -886,7 +886,7 @@ static int map_search_bytree(struct ldb_module *module, const struct ldb_dn *bas return ret_fb; } - ret_mp = map_search_bytree_mp(module, base, scope, tree, attrs, &mpres); + ret_mp = map_search_mp(module, base, scope, tree, attrs, &mpres); if (ret_mp == -1) { return -1; } @@ -901,26 +901,6 @@ static int map_search_bytree(struct ldb_module *module, const struct ldb_dn *bas return ret_fb + ret_mp; } -/* - search for matching records -*/ -static int map_search(struct ldb_module *module, const struct ldb_dn *base, - enum ldb_scope scope, const char *expression, - const char * const *attrs, struct ldb_message ***res) -{ - struct ldb_parse_tree *tree; - int ret; - - tree = ldb_parse_tree(NULL, expression); - if (tree == NULL) { - ldb_set_errstring(module, talloc_strdup(module, "expression parse failed")); - return -1; - } - - ret = map_search_bytree(module, base, scope, tree, attrs, res); - talloc_free(tree); - return ret; -} static int msg_contains_objectclass(const struct ldb_message *msg, const char *name) { @@ -1270,7 +1250,6 @@ static int map_del_trans(struct ldb_module *module) static const struct ldb_module_ops map_ops = { .name = "map", - .search = map_search, .search_bytree = map_search_bytree, .add_record = map_add, .modify_record = map_modify, diff --git a/source4/lib/ldb/modules/rdn_name.c b/source4/lib/ldb/modules/rdn_name.c index 3e3fbd544f..0275952780 100644 --- a/source4/lib/ldb/modules/rdn_name.c +++ b/source4/lib/ldb/modules/rdn_name.c @@ -37,17 +37,9 @@ #include "ldb/include/ldb_private.h" #include -static int rdn_name_search(struct ldb_module *module, const struct ldb_dn *base, - enum ldb_scope scope, const char *expression, - const char * const *attrs, struct ldb_message ***res) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_search\n"); - return ldb_next_search(module, base, scope, expression, attrs, res); -} - static int rdn_name_search_bytree(struct ldb_module *module, const struct ldb_dn *base, - enum ldb_scope scope, struct ldb_parse_tree *tree, - const char * const *attrs, struct ldb_message ***res) + enum ldb_scope scope, struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res) { ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_search\n"); return ldb_next_search_bytree(module, base, scope, tree, attrs, res); @@ -241,7 +233,6 @@ static int rdn_name_destructor(void *module_ctx) static const struct ldb_module_ops rdn_name_ops = { .name = "rdn_name", - .search = rdn_name_search, .search_bytree = rdn_name_search_bytree, .add_record = rdn_name_add_record, .modify_record = rdn_name_modify_record, diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index e882f72bd4..7c1753b215 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -283,13 +283,6 @@ static int get_attr_list_recursive(struct ldb_module *module, struct schema_stru } /* search */ -static int schema_search(struct ldb_module *module, const struct ldb_dn *base, - enum ldb_scope scope, const char *expression, - const char * const *attrs, struct ldb_message ***res) -{ - return ldb_next_search(module, base, scope, expression, attrs, res); -} - static int schema_search_bytree(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const *attrs, struct ldb_message ***res) @@ -537,7 +530,6 @@ static int schema_destructor(void *module_ctx) static const struct ldb_module_ops schema_ops = { .name = "schema", - .search = schema_search, .search_bytree = schema_search_bytree, .add_record = schema_add_record, .modify_record = schema_modify_record, diff --git a/source4/lib/ldb/modules/skel.c b/source4/lib/ldb/modules/skel.c index 5d14a27a7b..f882a840e1 100644 --- a/source4/lib/ldb/modules/skel.c +++ b/source4/lib/ldb/modules/skel.c @@ -43,10 +43,10 @@ struct private_data { /* search */ static int skel_search(struct ldb_module *module, const struct ldb_dn *base, - enum ldb_scope scope, const char *expression, + enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const *attrs, struct ldb_message ***res) { - return ldb_next_search(module, base, scope, expression, attrs, res); + return ldb_next_search(module, base, scope, tree, attrs, res); } /* add_record */ @@ -102,8 +102,7 @@ static int skel_destructor(void *module_ctx) static const struct ldb_module_ops skel_ops = { .name = "skel", - .search = skel_search, - .search_bytree = skel_search_bytree, + .search_bytree = skel_search_bytree, .add_record = skel_add_record, .modify_record = skel_modify_record, .delete_record = skel_delete_record, diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index 01e5c2c37c..5a1e54486a 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -37,14 +37,6 @@ #include "ldb/include/ldb_private.h" #include -static int timestamps_search(struct ldb_module *module, const struct ldb_dn *base, - enum ldb_scope scope, const char *expression, - const char * const *attrs, struct ldb_message ***res) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_search\n"); - return ldb_next_search(module, base, scope, expression, attrs, res); -} - static int timestamps_search_bytree(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const *attrs, struct ldb_message ***res) @@ -238,7 +230,6 @@ static int timestamps_destructor(void *module_ctx) static const struct ldb_module_ops timestamps_ops = { .name = "timestamps", - .search = timestamps_search, .search_bytree = timestamps_search_bytree, .add_record = timestamps_add_record, .modify_record = timestamps_modify_record, -- cgit From 78d0e79c9f9263e7f3798aa2e174a347ea1a3df1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 6 Oct 2005 06:57:09 +0000 Subject: r10759: make modules easier to write by allowing modules to only implement the functions they care about, instead of all functions. This also makes it more likely that future changes to ldb will not break existing modules (This used to be commit 45f0c967b58e7c1b2e900a4d74cfde2a2c527dfa) --- source4/lib/ldb/modules/ldb_map.c | 20 +--------------- source4/lib/ldb/modules/rdn_name.c | 39 +------------------------------ source4/lib/ldb/modules/schema.c | 26 +-------------------- source4/lib/ldb/modules/timestamps.c | 45 +----------------------------------- 4 files changed, 4 insertions(+), 126 deletions(-) (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index 1da1ef661a..246fc5709d 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -1233,31 +1233,13 @@ static int map_modify(struct ldb_module *module, const struct ldb_message *msg) return (mp_ret == -1 || fb_ret == -1)?-1:0; } -static int map_start_trans(struct ldb_module *module) -{ - return ldb_next_start_trans(module); -} - -static int map_end_trans(struct ldb_module *module) -{ - return ldb_next_end_trans(module); -} - -static int map_del_trans(struct ldb_module *module) -{ - return ldb_next_del_trans(module); -} - static const struct ldb_module_ops map_ops = { .name = "map", .search_bytree = map_search_bytree, .add_record = map_add, .modify_record = map_modify, .delete_record = map_delete, - .rename_record = map_rename, - .start_transaction = map_start_trans, - .end_transaction = map_end_trans, - .del_transaction = map_del_trans + .rename_record = map_rename }; static char *map_find_url(struct ldb_context *ldb, const char *name) diff --git a/source4/lib/ldb/modules/rdn_name.c b/source4/lib/ldb/modules/rdn_name.c index 0275952780..40ff75744e 100644 --- a/source4/lib/ldb/modules/rdn_name.c +++ b/source4/lib/ldb/modules/rdn_name.c @@ -194,53 +194,18 @@ static int rdn_name_modify_record(struct ldb_module *module, const struct ldb_me return ret; } -static int rdn_name_delete_record(struct ldb_module *module, const struct ldb_dn *dn) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_delete_record\n"); - return ldb_next_delete_record(module, dn); -} - static int rdn_name_rename_record(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn) { ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_rename_record\n"); return ldb_next_rename_record(module, olddn, newdn); } -static int rdn_start_trans(struct ldb_module *module) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_start_trans\n"); - return ldb_next_start_trans(module); -} - -static int rdn_end_trans(struct ldb_module *module) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_end_trans\n"); - return ldb_next_end_trans(module); -} - -static int rdn_del_trans(struct ldb_module *module) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_del_trans\n"); - return ldb_next_del_trans(module); -} - -static int rdn_name_destructor(void *module_ctx) -{ - /* struct ldb_module *ctx = module_ctx; */ - /* put your clean-up functions here */ - return 0; -} - static const struct ldb_module_ops rdn_name_ops = { .name = "rdn_name", .search_bytree = rdn_name_search_bytree, .add_record = rdn_name_add_record, .modify_record = rdn_name_modify_record, - .delete_record = rdn_name_delete_record, - .rename_record = rdn_name_rename_record, - .start_transaction = rdn_start_trans, - .end_transaction = rdn_end_trans, - .del_transaction = rdn_del_trans + .rename_record = rdn_name_rename_record }; @@ -262,7 +227,5 @@ struct ldb_module *rdn_name_module_init(struct ldb_context *ldb, const char *opt ctx->prev = ctx->next = NULL; ctx->ops = &rdn_name_ops; - talloc_set_destructor (ctx, rdn_name_destructor); - return ctx; } diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index 7c1753b215..0cae110487 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -509,35 +509,13 @@ static int schema_rename_record(struct ldb_module *module, const struct ldb_dn * return ldb_next_rename_record(module, olddn, newdn); } -static int schema_start_trans(struct ldb_module *module) { - return ldb_next_start_trans(module); -} - -static int schema_end_trans(struct ldb_module *module) { - return ldb_next_end_trans(module); -} - -static int schema_del_trans(struct ldb_module *module) { - return ldb_next_del_trans(module); -} - -static int schema_destructor(void *module_ctx) -{ -/* struct ldb_module *ctx = module_ctx; */ - /* put your clean-up functions here */ - return 0; -} - static const struct ldb_module_ops schema_ops = { .name = "schema", .search_bytree = schema_search_bytree, .add_record = schema_add_record, .modify_record = schema_modify_record, .delete_record = schema_delete_record, - .rename_record = schema_rename_record, - .start_transaction = schema_start_trans, - .end_transaction = schema_end_trans, - .del_transaction = schema_del_trans + .rename_record = schema_rename_record }; #ifdef HAVE_DLOPEN_DISABLED @@ -558,7 +536,5 @@ struct ldb_module *schema_module_init(struct ldb_context *ldb, const char *optio ctx->prev = ctx->next = NULL; ctx->ops = &schema_ops; - talloc_set_destructor (ctx, schema_destructor); - return ctx; } diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index 5a1e54486a..13e9c2ccc4 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -191,53 +191,12 @@ static int timestamps_modify_record(struct ldb_module *module, const struct ldb_ return ret; } -static int timestamps_delete_record(struct ldb_module *module, const struct ldb_dn *dn) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_delete_record\n"); - return ldb_next_delete_record(module, dn); -} - -static int timestamps_rename_record(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_rename_record\n"); - return ldb_next_rename_record(module, olddn, newdn); -} - -static int timestamps_start_trans(struct ldb_module *module) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_start_trans\n"); - return ldb_next_start_trans(module); -} - -static int timestamps_end_trans(struct ldb_module *module) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_end_trans\n"); - return ldb_next_end_trans(module); -} - -static int timestamps_del_trans(struct ldb_module *module) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_del_trans\n"); - return ldb_next_del_trans(module); -} - -static int timestamps_destructor(void *module_ctx) -{ - /* struct ldb_module *ctx = module_ctx; */ - /* put your clean-up functions here */ - return 0; -} static const struct ldb_module_ops timestamps_ops = { .name = "timestamps", .search_bytree = timestamps_search_bytree, .add_record = timestamps_add_record, - .modify_record = timestamps_modify_record, - .delete_record = timestamps_delete_record, - .rename_record = timestamps_rename_record, - .start_transaction = timestamps_start_trans, - .end_transaction = timestamps_end_trans, - .del_transaction = timestamps_del_trans + .modify_record = timestamps_modify_record }; @@ -259,7 +218,5 @@ struct ldb_module *timestamps_module_init(struct ldb_context *ldb, const char *o ctx->prev = ctx->next = NULL; ctx->ops = ×tamps_ops; - talloc_set_destructor (ctx, timestamps_destructor); - return ctx; } -- cgit From a599edf04cbdeef9014923ba0d3713b8ff84f266 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 12 Oct 2005 06:10:23 +0000 Subject: r10913: This patch isn't as big as it looks ... most of the changes are fixes to make all the ldb code compile without warnings on gcc4. Unfortunately That required a lot of casts :-( I have also added the start of an 'operational' module, which will replace the timestamp module, plus add support for some other operational attributes In ldb_msg_*() I added some new utility functions to make the operational module sane, and remove the 'ldb' argument from the ldb_msg_add_*() functions. That argument was only needed back in the early days of ldb when we didn't use the hierarchical talloc and thus needed a place to get the allocation function from. Now its just a pain to pass around everywhere. Also added a ldb_debug_set() function that calls ldb_debug() plus sets the result using ldb_set_errstring(). That saves on some awkward coding in a few places. (This used to be commit f6818daecca95760c12f79fd307770cbe3346f57) --- source4/lib/ldb/modules/ldb_map.c | 37 +++--- source4/lib/ldb/modules/operational.c | 217 ++++++++++++++++++++++++++++++++++ source4/lib/ldb/modules/rdn_name.c | 6 +- source4/lib/ldb/modules/schema.c | 81 +++++-------- source4/lib/ldb/modules/timestamps.c | 2 +- 5 files changed, 267 insertions(+), 76 deletions(-) create mode 100644 source4/lib/ldb/modules/operational.c (limited to 'source4/lib/ldb/modules') diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index 246fc5709d..48aa7e2ef5 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -625,7 +625,7 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c for (j = 0; j < oldelm->num_values; j++) elm->values[j] = ldb_val_dup(elm, &oldelm->values[j]); - ldb_msg_add(module->ldb, msg, elm, oldelm->flags); + ldb_msg_add(msg, elm, oldelm->flags); break; case MAP_CONVERT: @@ -642,7 +642,7 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c for (j = 0; j < oldelm->num_values; j++) elm->values[j] = attr->u.convert.convert_remote(module, elm, &oldelm->values[j]); - ldb_msg_add(module->ldb, msg, elm, oldelm->flags); + ldb_msg_add(msg, elm, oldelm->flags); break; case MAP_KEEP: @@ -659,7 +659,7 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c elm->name = talloc_strdup(elm, oldelm->name); - ldb_msg_add(module->ldb, msg, elm, oldelm->flags); + ldb_msg_add(msg, elm, oldelm->flags); break; case MAP_GENERATE: @@ -671,7 +671,7 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c if (!elm) continue; - ldb_msg_add(module->ldb, msg, elm, elm->flags); + ldb_msg_add(msg, elm, elm->flags); break; default: ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Unknown attr->type for %s", attr->local_name); @@ -750,9 +750,11 @@ static int map_search_fb(struct ldb_module *module, const struct ldb_dn *base, { int ret; struct ldb_parse_tree t_and, t_not, t_present, *childs[2]; + char *ismapped; t_present.operation = LDB_OP_PRESENT; - t_present.u.present.attr = talloc_strdup(NULL, "isMapped"); + ismapped = talloc_strdup(module, "isMapped"); + t_present.u.present.attr = ismapped; t_not.operation = LDB_OP_NOT; t_not.u.isnot.child = &t_present; @@ -765,7 +767,7 @@ static int map_search_fb(struct ldb_module *module, const struct ldb_dn *base, ret = ldb_next_search_bytree(module, base, scope, &t_and, attrs, res); - talloc_free(t_present.u.present.attr); + talloc_free(ismapped); return ret; } @@ -847,7 +849,7 @@ static int map_search_mp(struct ldb_module *module, const struct ldb_dn *base, int j; ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Extra data found for remote DN: %s", ldb_dn_linearize(merged, merged->dn)); for (j = 0; j < extrares[0]->num_elements; j++) { - ldb_msg_add(module->ldb, merged, &(extrares[0]->elements[j]), extrares[0]->elements[j].flags); + ldb_msg_add(merged, &(extrares[0]->elements[j]), extrares[0]->elements[j].flags); } } @@ -941,7 +943,7 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) fb->dn = talloc_reference(fb, msg->dn); /* We add objectClass, so 'top' should be no problem */ - ldb_msg_add_string(module->ldb, mp, "objectClass", "top"); + ldb_msg_add_string(mp, "objectClass", "top"); /* make a list of remote objectclasses that can be used * given the attributes that are available and add to @@ -971,7 +973,7 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) /* Apparently, it contains all required elements */ if (has_musts && has_baseclasses) { - ldb_msg_add_string(module->ldb, mp, "objectClass", privdat->objectclass_maps[i].remote_name); + ldb_msg_add_string(mp, "objectClass", privdat->objectclass_maps[i].remote_name); ldb_debug(module->ldb, LDB_DEBUG_TRACE, "map_add: Adding objectClass %s", privdat->objectclass_maps[i].remote_name); } } @@ -1071,7 +1073,7 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) continue; } - ldb_msg_add(module->ldb, mp, elm, 0); + ldb_msg_add(mp, elm, 0); mapped++; } @@ -1083,7 +1085,7 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) elm->values = talloc_reference(elm, msg->elements[i].values); elm->name = talloc_strdup(elm, msg->elements[i].name); - ldb_msg_add(module->ldb, fb, elm, 0); + ldb_msg_add(fb, elm, 0); } } @@ -1095,7 +1097,7 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_map_add: Added mapped record"); - ldb_msg_add_string(module->ldb, fb, "isMapped", "TRUE"); + ldb_msg_add_string(fb, "isMapped", "TRUE"); ret = ldb_next_add_record(module, fb); if (ret == -1) { ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Adding fallback record failed: %s", ldb_errstring(module->ldb)); @@ -1159,7 +1161,7 @@ static int map_modify(struct ldb_module *module, const struct ldb_message *msg) elm->values[j] = msg->elements[i].values[j]; } - ldb_msg_add(module->ldb, mp, elm, msg->elements[i].flags); + ldb_msg_add(mp, elm, msg->elements[i].flags); mapped++; continue; @@ -1176,7 +1178,7 @@ static int map_modify(struct ldb_module *module, const struct ldb_message *msg) elm->values[j] = attr->u.convert.convert_local(module, mp, &msg->elements[i].values[j]); } - ldb_msg_add(module->ldb, mp, elm, msg->elements[i].flags); + ldb_msg_add(mp, elm, msg->elements[i].flags); mapped++; continue; @@ -1191,7 +1193,7 @@ static int map_modify(struct ldb_module *module, const struct ldb_message *msg) elm->name = talloc_strdup(elm, msg->elements[i].name); - ldb_msg_add(module->ldb, mp, elm, msg->elements[i].flags); + ldb_msg_add(mp, elm, msg->elements[i].flags); mapped++; continue; @@ -1209,8 +1211,7 @@ static int map_modify(struct ldb_module *module, const struct ldb_message *msg) elm->values = talloc_reference(elm, msg->elements[i].values); elm->name = talloc_strdup(elm, msg->elements[i].name); - ldb_msg_add(module->ldb, fb, elm, msg->elements[i].flags); - + ldb_msg_add(fb, elm, msg->elements[i].flags); } } @@ -1218,7 +1219,7 @@ static int map_modify(struct ldb_module *module, const struct ldb_message *msg) ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Modifying fallback record with %d elements", fb->num_elements); fb_ret = ldb_next_modify_record(module, fb); if (fb_ret == -1) { - ldb_msg_add_string(module->ldb, fb, "isMapped", "TRUE"); + ldb_msg_add_string(fb, "isMapped", "TRUE"); fb_ret = ldb_next_add_record(module, fb); } } else fb_ret = 0; diff --git a/source4/lib/ldb/modules/operational.c b/source4/lib/ldb/modules/operational.c new file mode 100644 index 0000000000..911bc087ca --- /dev/null +++ b/source4/lib/ldb/modules/operational.c @@ -0,0 +1,217 @@ +/* + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/* + handle operational attributes + */ + +/* + createTimestamp: HIDDEN, searchable, ldaptime, alias for whenCreated + modifyTimestamp: HIDDEN, searchable, ldaptime, alias for whenChanged + + for the above two, we do the search as normal, and if + createTimestamp or modifyTimestamp is asked for, then do + additional searches for whenCreated and whenChanged and fill in + the resulting values + + we also need to replace these with the whenCreated/whenChanged + equivalent in the search expression trees + + whenCreated: not-HIDDEN, CONSTRUCTED, SEARCHABLE + whenChanged: not-HIDDEN, CONSTRUCTED, SEARCHABLE + + on init we need to setup attribute handlers for these so + comparisons are done correctly. The resolution is 1 second. + + on add we need to add both the above, for current time + + on modify we need to change whenChanged + + + subschemaSubentry: HIDDEN, not-searchable, + points at DN CN=Aggregate,CN=Schema,CN=Configuration,$BASEDN + + for this one we do the search as normal, then add the static + value if requested. How do we work out the $BASEDN from inside a + module? + + + structuralObjectClass: HIDDEN, CONSTRUCTED, not-searchable. always same as objectclass? + + for this one we do the search as normal, then if requested ask + for objectclass, change the attribute name, and add it + + attributeTypes: in schema only + objectClasses: in schema only + matchingRules: in schema only + matchingRuleUse: in schema only + creatorsName: not supported by w2k3? + modifiersName: not supported by w2k3? +*/ + + +#include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" +#include + +/* + a list of attribute names that should be substituted in the parse + tree before the search is done +*/ +static const struct { + const char *attr; + const char *replace; +} parse_tree_sub[] = { + { "createTimestamp", "whenCreated" }, + { "modifyTimestamp", "whenChanged" } +}; + +/* + a list of attribute names that are hidden, but can be searched for + using another (non-hidden) name to produce the correct result +*/ +static const struct { + const char *attr; + const char *replace; +} search_sub[] = { + { "createTimestamp", "whenCreated" }, + { "modifyTimestamp", "whenChanged" }, + { "structuralObjectClass", "objectClass" } +}; + +/* + hook search operations +*/ +static int operational_search_bytree(struct ldb_module *module, + const struct ldb_dn *base, + enum ldb_scope scope, struct ldb_parse_tree *tree, + const char * const *attrs, + struct ldb_message ***res) +{ + int i, r, a; + int ret; + const char **search_attrs = NULL; + + /* replace any attributes in the parse tree that are + searchable, but are stored using a different name in the + backend */ + for (i=0;i