From 3f7ec9bf191f2179c2112191d0c909e309411c29 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 11 Jan 2008 10:44:49 +1100 Subject: Add in new module to normalise DNs being returned from OpenLDAP. This fixes the case of the attribute in teh DN. Fix option spelling for example re-provision Andrew Bartlett (This used to be commit e3a76be04760a81a9c1b7ad9b139f088decc9ee6) --- source4/dsdb/samdb/ldb_modules/config.mk | 13 +++ source4/dsdb/samdb/ldb_modules/normalise.c | 166 +++++++++++++++++++++++++++++ 2 files changed, 179 insertions(+) create mode 100644 source4/dsdb/samdb/ldb_modules/normalise.c (limited to 'source4/dsdb') diff --git a/source4/dsdb/samdb/ldb_modules/config.mk b/source4/dsdb/samdb/ldb_modules/config.mk index 95bb7de06c..a41a29b5dd 100644 --- a/source4/dsdb/samdb/ldb_modules/config.mk +++ b/source4/dsdb/samdb/ldb_modules/config.mk @@ -320,3 +320,16 @@ OBJ_FILES = \ # End MODULE ldb_anr ################################################ +################################################ +# Start MODULE ldb_normalise +[MODULE::ldb_normalise] +INIT_FUNCTION = ldb_normalise_init +CFLAGS = -Ilib/ldb/include +OUTPUT_TYPE = SHARED_LIBRARY +PRIVATE_DEPENDENCIES = LIBTALLOC LIBSAMBA-UTIL SAMDB +SUBSYSTEM = LIBLDB +OBJ_FILES = \ + normalise.o +# End MODULE ldb_normalise +################################################ + diff --git a/source4/dsdb/samdb/ldb_modules/normalise.c b/source4/dsdb/samdb/ldb_modules/normalise.c new file mode 100644 index 0000000000..efc9bb29e8 --- /dev/null +++ b/source4/dsdb/samdb/ldb_modules/normalise.c @@ -0,0 +1,166 @@ +/* + ldb database library + + Copyright (C) Amdrew Bartlett 2007-2008 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/* + * Name: ldb + * + * Component: ldb normalisation module + * + * Description: module to ensure all DNs and attribute names are normalised + * + * Author: Andrew Bartlett + */ + +#include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_errors.h" +#include "ldb/include/ldb_private.h" +#include "dsdb/samdb/samdb.h" + +/* Fix up the DN to be in the standard form, taking particular care to match the parent DN + + This should mean that if the parent is: + CN=Users,DC=samba,DC=example,DC=com + and a proposed child is + cn=Admins ,cn=USERS,dc=Samba,dc=example,dc=COM + + The resulting DN should be: + + CN=Admins,CN=Users,DC=samba,DC=example,DC=com + + */ +static int fix_dn(struct ldb_dn *dn) +{ + int i, ret; + char *upper_rdn_attr; + + for (i=0; i < ldb_dn_get_comp_num(dn); i++) { + /* We need the attribute name in upper case */ + upper_rdn_attr = strupper_talloc(dn, + ldb_dn_get_component_name(dn, i)); + if (!upper_rdn_attr) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* And replace it with CN=foo (we need the attribute in upper case */ + ret = ldb_dn_set_component(dn, i, upper_rdn_attr, + *ldb_dn_get_component_val(dn, i)); + talloc_free(upper_rdn_attr); + if (ret != LDB_SUCCESS) { + return ret; + } + } + return LDB_SUCCESS; +} + +static int normalise_search_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares) +{ + const struct dsdb_schema *schema = dsdb_get_schema(ldb); + struct ldb_request *orig_req = talloc_get_type(context, struct ldb_request); + TALLOC_CTX *mem_ctx; + int i, j, ret; + + /* Only entries are interesting, and we handle the case of the parent seperatly */ + if (ares->type != LDB_REPLY_ENTRY) { + return orig_req->callback(ldb, orig_req->context, ares); + } + + if (!schema) { + return orig_req->callback(ldb, orig_req->context, ares); + } + + mem_ctx = talloc_new(ares); + if (!mem_ctx) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* OK, we have one of *many* search results passing by here, + * but we should get them one at a time */ + + ret = fix_dn(ares->message->dn); + if (ret != LDB_SUCCESS) { + talloc_free(mem_ctx); + return ret; + } + + for (i = 0; i < ares->message->num_elements; i++) { + const struct dsdb_attribute *attribute = dsdb_attribute_by_lDAPDisplayName(schema, ares->message->elements[i].name); + if (!attribute) { + continue; + } + if ((strcmp(attribute->attributeSyntax_oid, "2.5.5.1") != 0) && + (strcmp(attribute->attributeSyntax_oid, "2.5.5.7") != 0)) { + continue; + } + for (j = 0; j < ares->message->elements[i].num_values; j++) { + const char *dn_str; + struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb, (const char *)ares->message->elements[i].values[j].data); + if (!dn) { + talloc_free(mem_ctx); + return LDB_ERR_OPERATIONS_ERROR; + } + ret = fix_dn(ares->message->dn); + if (ret != LDB_SUCCESS) { + talloc_free(mem_ctx); + return ret; + } + dn_str = talloc_steal(ares->message->elements[i].values, ldb_dn_get_linearized(dn)); + ares->message->elements[i].values[j] = data_blob_string_const(dn_str); + talloc_free(dn); + } + } + talloc_free(mem_ctx); + return orig_req->callback(ldb, orig_req->context, ares); +} + +/* search */ +static int normalise_search(struct ldb_module *module, struct ldb_request *req) +{ + int ret; + struct ldb_request *down_req = talloc(req, struct ldb_request); + if (!down_req) { + ldb_oom(module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + *down_req = *req; + down_req->context = req; + down_req->callback = normalise_search_callback; + + ret = ldb_next_request(module, down_req); + + /* do not free down_req as the call results may be linked to it, + * it will be freed when the upper level request get freed */ + if (ret == LDB_SUCCESS) { + req->handle = down_req->handle; + } + return ret; +} + + +static const struct ldb_module_ops normalise_ops = { + .name = "normalise", + .search = normalise_search, +}; + +int ldb_normalise_init(void) +{ + return ldb_register_module(&normalise_ops); +} -- cgit From ac4810f1bb8984971a98d30c6a3b0b29367d1e2e Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 11 Jan 2008 15:19:27 +1100 Subject: Remove 'dn' from mapping, it isn't a valid attribute in AD, and causes problems with ldap.js test with OpenLDAP as the backend. Likewise, remove it from the template lookup (for consistancy). TODO: see if it can be removed from ldb Andrew Bartlett (This used to be commit 47a1b76f7fff30229d3f23c6723f047923faf196) --- source4/dsdb/samdb/ldb_modules/simple_ldap_map.c | 18 ------------------ source4/dsdb/samdb/samdb.c | 2 +- 2 files changed, 1 insertion(+), 19 deletions(-) (limited to 'source4/dsdb') diff --git a/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c b/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c index 91001d43d7..970106787b 100644 --- a/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c +++ b/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c @@ -375,15 +375,6 @@ static const struct ldb_map_attribute entryuuid_attributes[] = } } }, - { - .local_name = "dn", - .type = MAP_RENAME, - .u = { - .rename = { - .remote_name = "entryDN" - } - } - }, { .local_name = "groupType", .type = MAP_CONVERT, @@ -533,15 +524,6 @@ static const struct ldb_map_attribute nsuniqueid_attributes[] = } } }, - { - .local_name = "dn", - .type = MAP_RENAME, - .u = { - .rename = { - .remote_name = "entryDN" - } - } - }, { .local_name = "groupType", .type = MAP_CONVERT, diff --git a/source4/dsdb/samdb/samdb.c b/source4/dsdb/samdb/samdb.c index b042d1d3b7..c11eea1757 100644 --- a/source4/dsdb/samdb/samdb.c +++ b/source4/dsdb/samdb/samdb.c @@ -134,7 +134,7 @@ int samdb_copy_template(struct ldb_context *ldb, } /* pull the template record */ - ret = ldb_search(templates_ldb, basedn, LDB_SCOPE_BASE, "(dn=*)", NULL, &res); + ret = ldb_search(templates_ldb, basedn, LDB_SCOPE_BASE, "distinguishedName=*", NULL, &res); talloc_free(basedn); if (ret != LDB_SUCCESS) { *errstring = talloc_steal(msg, ldb_errstring(templates_ldb)); -- cgit From 483164e1eb2a5b863cdd8adb515f4e4925f33a25 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 16 Jan 2008 08:49:54 +1100 Subject: Rework control handling to remove the 'domain_scope' control Also remove the search_options control earlier, before, rather than after duplicating the request. When we generate referalls in the partition module, the domain_scope control with suppress them. Andrew Bartlett (This used to be commit fc57a119f53a7bc0a0eb76b868bbd7386b3c5008) --- source4/dsdb/samdb/ldb_modules/partition.c | 54 ++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 17 deletions(-) (limited to 'source4/dsdb') diff --git a/source4/dsdb/samdb/ldb_modules/partition.c b/source4/dsdb/samdb/ldb_modules/partition.c index 4586810d96..61b64441a7 100644 --- a/source4/dsdb/samdb/ldb_modules/partition.c +++ b/source4/dsdb/samdb/ldb_modules/partition.c @@ -169,13 +169,12 @@ static int partition_other_callback(struct ldb_context *ldb, void *context, stru } -static int partition_send_request(struct partition_context *ac, struct ldb_control *remove_control, +static int partition_send_request(struct partition_context *ac, struct dsdb_control_current_partition *partition) { int ret; struct ldb_module *backend; struct ldb_request *req; - struct ldb_control **saved_controls; if (partition) { backend = make_module_for_next_request(ac, ac->module->ldb, partition->module); @@ -225,12 +224,6 @@ static int partition_send_request(struct partition_context *ac, struct ldb_contr req->context = ac; } - /* Remove a control, so we don't confuse a backend server */ - if (remove_control && !save_controls(remove_control, req, &saved_controls)) { - ldb_oom(ac->module->ldb); - return LDB_ERR_OPERATIONS_ERROR; - } - if (partition) { ret = ldb_request_add_control(req, DSDB_CONTROL_CURRENT_PARTITION_OID, false, partition); if (ret != LDB_SUCCESS) { @@ -253,18 +246,17 @@ static int partition_send_request(struct partition_context *ac, struct ldb_contr */ static int partition_send_all(struct ldb_module *module, struct partition_context *ac, - struct ldb_control *remove_control, struct ldb_request *req) { int i; struct partition_private_data *data = talloc_get_type(module->private_data, struct partition_private_data); - int ret = partition_send_request(ac, remove_control, NULL); + int ret = partition_send_request(ac, NULL); if (ret != LDB_SUCCESS) { return ret; } for (i=0; data && data->partitions && data->partitions[i]; i++) { - ret = partition_send_request(ac, remove_control, data->partitions[i]); + ret = partition_send_request(ac, data->partitions[i]); if (ret != LDB_SUCCESS) { return ret; } @@ -297,7 +289,7 @@ static int partition_replicate(struct ldb_module *module, struct ldb_request *re return LDB_ERR_OPERATIONS_ERROR; } - return partition_send_all(module, ac, NULL, req); + return partition_send_all(module, ac, req); } } } @@ -314,6 +306,7 @@ static int partition_replicate(struct ldb_module *module, struct ldb_request *re * TODO: we should maybe return an error here * if it's not a special dn */ + return ldb_next_request(module, req); } @@ -334,6 +327,8 @@ static int partition_replicate(struct ldb_module *module, struct ldb_request *re /* search */ static int partition_search(struct ldb_module *module, struct ldb_request *req) { + struct ldb_control **saved_controls; + /* Find backend */ struct partition_private_data *data = talloc_get_type(module->private_data, struct partition_private_data); @@ -342,19 +337,34 @@ static int partition_search(struct ldb_module *module, struct ldb_request *req) /* (later) consider if we should be searching multiple * partitions (for 'invisible' partition behaviour */ struct ldb_control *search_control = ldb_request_get_control(req, LDB_CONTROL_SEARCH_OPTIONS_OID); + struct ldb_control *domain_scope_control = ldb_request_get_control(req, LDB_CONTROL_DOMAIN_SCOPE_OID); struct ldb_search_options_control *search_options = NULL; if (search_control) { search_options = talloc_get_type(search_control->data, struct ldb_search_options_control); } + /* Remove the domain_scope control, so we don't confuse a backend server */ + if (domain_scope_control && !save_controls(domain_scope_control, req, &saved_controls)) { + ldb_oom(module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* TODO: + Generate referrals (look for a partition under this DN) if we don't have the above control specified + */ + if (search_options && (search_options->search_options & LDB_SEARCH_OPTION_PHANTOM_ROOT)) { int ret, i; struct partition_context *ac; - struct ldb_control *remove_control = NULL; if ((search_options->search_options & ~LDB_SEARCH_OPTION_PHANTOM_ROOT) == 0) { /* We have processed this flag, so we are done with this control now */ - remove_control = search_control; + + /* Remove search control, so we don't confuse a backend server */ + if (search_control && !save_controls(search_control, req, &saved_controls)) { + ldb_oom(module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } } ac = partition_init_handle(req, module); if (!ac) { @@ -363,12 +373,12 @@ static int partition_search(struct ldb_module *module, struct ldb_request *req) /* Search from the base DN */ if (!req->op.search.base || ldb_dn_is_null(req->op.search.base)) { - return partition_send_all(module, ac, remove_control, req); + return partition_send_all(module, ac, req); } for (i=0; data && data->partitions && data->partitions[i]; i++) { /* Find all partitions under the search base */ if (ldb_dn_compare_base(req->op.search.base, data->partitions[i]->dn) == 0) { - ret = partition_send_request(ac, remove_control, data->partitions[i]); + ret = partition_send_request(ac, data->partitions[i]); if (ret != LDB_SUCCESS) { return ret; } @@ -384,6 +394,16 @@ static int partition_search(struct ldb_module *module, struct ldb_request *req) return LDB_SUCCESS; } else { /* Handle this like all other requests */ + if (search_control && (search_options->search_options & ~LDB_SEARCH_OPTION_PHANTOM_ROOT) == 0) { + /* We have processed this flag, so we are done with this control now */ + + /* Remove search control, so we don't confuse a backend server */ + if (search_control && !save_controls(search_control, req, &saved_controls)) { + ldb_oom(module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + } + return partition_replicate(module, req, req->op.search.base); } } @@ -693,7 +713,7 @@ static int partition_extended(struct ldb_module *module, struct ldb_request *req return LDB_ERR_OPERATIONS_ERROR; } - return partition_send_all(module, ac, NULL, req); + return partition_send_all(module, ac, req); } static int sort_compare(void *void1, -- cgit From e72760b218e60acfc04c6c22a43820683172df09 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 16 Jan 2008 15:14:05 +1100 Subject: Rework linked_attributes module for the REPLACE case. This moves to a smarter 'find the delta' based operation of the linked attributes module, when the caller asks for a 'replace' of the link source. Previously we would spray operations all over the database, even if the net result was just to modify one record. This also means we need the transaction safety less, which may be useful for some LDAP backends that don't provide this functionality on the LDAP server. Andrew Bartlett (This used to be commit 8c88e4eb1c0a606e7899091525260e8d6558ffd0) --- source4/dsdb/samdb/ldb_modules/linked_attributes.c | 92 ++++++++++++++++++++-- 1 file changed, 86 insertions(+), 6 deletions(-) (limited to 'source4/dsdb') diff --git a/source4/dsdb/samdb/ldb_modules/linked_attributes.c b/source4/dsdb/samdb/ldb_modules/linked_attributes.c index 803d24e34e..b3fdffe566 100644 --- a/source4/dsdb/samdb/ldb_modules/linked_attributes.c +++ b/source4/dsdb/samdb/ldb_modules/linked_attributes.c @@ -279,6 +279,27 @@ static int linked_attributes_add(struct ldb_module *module, struct ldb_request * return setup_modifies(module->ldb, ac, ac, req->op.add.message, NULL, req->op.add.message->dn); } +struct merge { + struct ldb_dn *dn; + bool add; + bool ignore; +}; + +static int merge_cmp(struct merge *merge1, struct merge *merge2) { + int ret; + ret = ldb_dn_compare(merge1->dn, merge2->dn); + if (ret == 0) { + if (merge1->add == merge2->add) { + return 0; + } + if (merge1->add == true) { + return 1; + } + return -1; + } + return ret; +} + static int linked_attributes_mod_replace_search_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares) { struct replace_context *ac2 = talloc_get_type(context, struct replace_context); @@ -296,16 +317,63 @@ static int linked_attributes_mod_replace_search_callback(struct ldb_context *ldb /* See if this element already exists */ if (search_el) { - int ret; + + struct merge *merged_list = NULL; + + int ret, size = 0, i; struct ldb_message *msg = ldb_msg_new(ac); if (!msg) { ldb_oom(ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } - /* Lazy option: Delete and add the elements on all members */ - msg->num_elements = 1; - msg->elements = search_el; + /* Add all the existing elements, marking as 'proposed for delete' by setting .add = false */ + for (i=0; i < search_el->num_values; i++) { + merged_list = talloc_realloc(ares, merged_list, struct merge, size + 1); + merged_list[size].dn = ldb_dn_new(merged_list, ldb, (char *)search_el->values[i].data); + merged_list[size].add = false; + merged_list[size].ignore = false; + size++; + } + + /* Add all the new replacement elements, marking as 'proposed for add' by setting .add = true */ + for (i=0; i < ac2->el->num_values; i++) { + merged_list = talloc_realloc(ares, merged_list, struct merge, size + 1); + merged_list[size].dn = ldb_dn_new(merged_list, ldb, (char *)ac2->el->values[i].data); + merged_list[size].add = true; + merged_list[size].ignore = false; + size++; + } + + /* Sort the list, so we can pick out an add and delete for the same DN, and eliminate them */ + qsort(merged_list, size, + sizeof(*merged_list), + (comparison_fn_t)merge_cmp); + + /* Now things are sorted, it is trivial to mark pairs of DNs as 'ignore' */ + for (i=0; i + 1 < size; i++) { + if (ldb_dn_compare(merged_list[i].dn, + merged_list[i+1].dn) == 0 + /* Fortunetly the sort also sorts 'add == false' first */ + && merged_list[i].add == false + && merged_list[i+1].add == true) { + + /* Mark as ignore, so we include neither in the actual operations */ + merged_list[i].ignore = true; + merged_list[i+1].ignore = true; + } + } + + /* Arrange to delete anything the search found that we don't re-add */ + for (i=0; i < size; i++) { + if (merged_list[i].ignore == false + && merged_list[i].add == false) { + ldb_msg_add_steal_string(msg, search_el->name, + ldb_dn_get_linearized(merged_list[i].dn)); + } + } + + /* The DN to set on the linked attributes is the original DN of the modify message */ msg->dn = ac->orig_req->op.mod.message->dn; ret = setup_modifies(ac->module->ldb, ac2, ac, msg, ares->message->dn, NULL); @@ -313,13 +381,21 @@ static int linked_attributes_mod_replace_search_callback(struct ldb_context *ldb return ret; } - msg->elements = ac2->el; + /* Now add links for all the actually new elements */ + for (i=0; i < size; i++) { + if (merged_list[i].ignore == false && merged_list[i].add == true) { + ldb_msg_add_steal_string(msg, search_el->name, + ldb_dn_get_linearized(merged_list[i].dn)); + } + } ret = setup_modifies(ac->module->ldb, ac2, ac, msg, NULL, ares->message->dn); if (ret != LDB_SUCCESS) { return ret; } + talloc_free(merged_list); + } else { /* Looks like it doesn't exist, process like an 'add' */ struct ldb_message *msg = ldb_msg_new(ac); @@ -411,6 +487,7 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques return LDB_ERR_OBJECT_CLASS_VIOLATION; } + /* Replace with new set of values */ if (((el->flags & LDB_FLAG_MOD_MASK) == LDB_FLAG_MOD_REPLACE) && el->num_values > 0) { struct replace_context *ac2 = talloc(ac, struct replace_context); @@ -461,6 +538,8 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques } continue; + + /* Delete all values case */ } else if (((el->flags & LDB_FLAG_MOD_MASK) & (LDB_FLAG_MOD_DELETE|LDB_FLAG_MOD_REPLACE)) && el->num_values == 0) { const char **attrs = talloc_array(ac, const char *, 2); @@ -508,7 +587,8 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques continue; } - /* Prepare the modify (mod element) on the targets */ + + /* Prepare the modify (mod element) on the targets, for a normal modify request */ /* For each value being moded, we need to setup the modify */ for (j=0; j < el->num_values; j++) { -- cgit From d5fd15005c0cad9e9018e81ab5c30b87cb2f605a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 17 Jan 2008 08:53:18 +1100 Subject: ldb_map objectClass munging: Don't hard-code 'extensibleObject'. This allows objectClass munging to be removed, or modified to not include adding an objectClass, or for that objectClass to be something different. Andrew Bartlett (This used to be commit ee93b4e2ee1dd1cd38bcf14b2bb62556a13cec4a) --- source4/dsdb/samdb/ldb_modules/samba3sam.c | 2 +- source4/dsdb/samdb/ldb_modules/simple_ldap_map.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/dsdb') diff --git a/source4/dsdb/samdb/ldb_modules/samba3sam.c b/source4/dsdb/samdb/ldb_modules/samba3sam.c index 0bfc9a3dae..3a666b5380 100644 --- a/source4/dsdb/samdb/ldb_modules/samba3sam.c +++ b/source4/dsdb/samdb/ldb_modules/samba3sam.c @@ -918,7 +918,7 @@ static int samba3sam_init(struct ldb_module *module) { int ret; - ret = ldb_map_init(module, samba3_attributes, samba3_objectclasses, NULL, "samba3sam"); + ret = ldb_map_init(module, samba3_attributes, samba3_objectclasses, NULL, NULL, "samba3sam"); if (ret != LDB_SUCCESS) return ret; diff --git a/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c b/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c index 970106787b..6e66d0783a 100644 --- a/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c +++ b/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c @@ -667,7 +667,7 @@ static int entryuuid_init(struct ldb_module *module) struct map_private *map_private; struct entryuuid_private *entryuuid_private; - ret = ldb_map_init(module, entryuuid_attributes, entryuuid_objectclasses, entryuuid_wildcard_attributes, NULL); + ret = ldb_map_init(module, entryuuid_attributes, entryuuid_objectclasses, entryuuid_wildcard_attributes, "extensibleObject", NULL); if (ret != LDB_SUCCESS) return ret; @@ -688,7 +688,7 @@ static int nsuniqueid_init(struct ldb_module *module) struct map_private *map_private; struct entryuuid_private *entryuuid_private; - ret = ldb_map_init(module, nsuniqueid_attributes, NULL, nsuniqueid_wildcard_attributes, NULL); + ret = ldb_map_init(module, nsuniqueid_attributes, NULL, nsuniqueid_wildcard_attributes, "extensibleObject", NULL); if (ret != LDB_SUCCESS) return ret; -- cgit From 8d36d43e5258aa80855a9baa707a9fcad77a0d03 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 18 Jan 2008 10:13:43 +1100 Subject: Add in a new module to handle instanceType This code raided from the repl_meta_data module, which probably needs to be downsized to just handling the replication data. Andrew Bartlett (This used to be commit 2a418f33705a792d9d16cf1d4aa3dcda467e6e04) --- source4/dsdb/samdb/ldb_modules/config.mk | 13 +++ source4/dsdb/samdb/ldb_modules/instancetype.c | 128 ++++++++++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 source4/dsdb/samdb/ldb_modules/instancetype.c (limited to 'source4/dsdb') diff --git a/source4/dsdb/samdb/ldb_modules/config.mk b/source4/dsdb/samdb/ldb_modules/config.mk index a41a29b5dd..dc407fbd8a 100644 --- a/source4/dsdb/samdb/ldb_modules/config.mk +++ b/source4/dsdb/samdb/ldb_modules/config.mk @@ -333,3 +333,16 @@ OBJ_FILES = \ # End MODULE ldb_normalise ################################################ +################################################ +# Start MODULE ldb_instancetype +[MODULE::ldb_instancetype] +INIT_FUNCTION = ldb_instancetype_init +CFLAGS = -Ilib/ldb/include +OUTPUT_TYPE = SHARED_LIBRARY +PRIVATE_DEPENDENCIES = LIBTALLOC +SUBSYSTEM = LIBLDB +OBJ_FILES = \ + instancetype.o +# End MODULE ldb_instancetype +################################################ + diff --git a/source4/dsdb/samdb/ldb_modules/instancetype.c b/source4/dsdb/samdb/ldb_modules/instancetype.c new file mode 100644 index 0000000000..ee1f2ff7ba --- /dev/null +++ b/source4/dsdb/samdb/ldb_modules/instancetype.c @@ -0,0 +1,128 @@ +/* + ldb database library + + Copyright (C) Simo Sorce 2004-2006 + Copyright (C) Andrew Bartlett 2005 + Copyright (C) Andrew Tridgell 2005 + Copyright (C) Stefan Metzmacher 2007 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +/* + * Name: ldb + * + * Component: ldb instancetype module + * + * Description: add an instanceType onto every new record + * + * Author: Simo Sorce + */ + +#include "includes.h" +#include "ldb/include/ldb_includes.h" +#include "librpc/gen_ndr/ndr_misc.h" +#include "param/param.h" +#include "dsdb/samdb/samdb.h" +#include "dsdb/common/flags.h" + +/* add_record: add instancetype attribute */ +static int instancetype_add(struct ldb_module *module, struct ldb_request *req) +{ + struct ldb_request *down_req; + struct ldb_message *msg; + uint32_t instance_type; + int ret; + const struct ldb_control *partition_ctrl; + const struct dsdb_control_current_partition *partition; + + + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "instancetype_add_record\n"); + + /* do not manipulate our control entries */ + if (ldb_dn_is_special(req->op.add.message->dn)) { + return ldb_next_request(module, req); + } + + partition_ctrl = ldb_request_get_control(req, DSDB_CONTROL_CURRENT_PARTITION_OID); + if (!partition_ctrl) { + ldb_debug_set(module->ldb, LDB_DEBUG_FATAL, + "instancetype_add: no current partition control found"); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + + partition = talloc_get_type(partition_ctrl->data, + struct dsdb_control_current_partition); + SMB_ASSERT(partition && partition->version == DSDB_CONTROL_CURRENT_PARTITION_VERSION); + + down_req = talloc(req, struct ldb_request); + if (down_req == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + *down_req = *req; + + /* we have to copy the message as the caller might have it as a const */ + down_req->op.add.message = msg = ldb_msg_copy_shallow(down_req, req->op.add.message); + if (msg == NULL) { + talloc_free(down_req); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* + * TODO: calculate correct instance type + */ + instance_type = INSTANCE_TYPE_WRITE; + if (ldb_dn_compare(partition->dn, msg->dn) == 0) { + instance_type |= INSTANCE_TYPE_IS_NC_HEAD; + if (ldb_dn_compare(msg->dn, samdb_base_dn(module->ldb)) != 0) { + instance_type |= INSTANCE_TYPE_NC_ABOVE; + } + } + + ret = ldb_msg_add_fmt(msg, "instanceType", "%u", instance_type); + if (ret != LDB_SUCCESS) { + talloc_free(down_req); + ldb_oom(module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + ldb_set_timeout_from_prev_req(module->ldb, req, down_req); + + /* go on with the call chain */ + ret = ldb_next_request(module, down_req); + + /* do not free down_req as the call results may be linked to it, + * it will be freed when the upper level request get freed */ + if (ret == LDB_SUCCESS) { + req->handle = down_req->handle; + } + + return ret; +} + +static const struct ldb_module_ops instancetype_ops = { + .name = "instancetype", + .add = instancetype_add, +}; + + +int ldb_instancetype_init(void) +{ + return ldb_register_module(&instancetype_ops); +} -- cgit From 564e021ed974b4bb3472ec3fc091746663808afd Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 18 Jan 2008 12:16:27 +1100 Subject: Correct authorship of instanceType module Andrew Bartlett (This used to be commit d427cf4fa67e84ccdece9a3fb31d8e89379a86e7) --- source4/dsdb/samdb/ldb_modules/instancetype.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/dsdb') diff --git a/source4/dsdb/samdb/ldb_modules/instancetype.c b/source4/dsdb/samdb/ldb_modules/instancetype.c index ee1f2ff7ba..064c28ec65 100644 --- a/source4/dsdb/samdb/ldb_modules/instancetype.c +++ b/source4/dsdb/samdb/ldb_modules/instancetype.c @@ -31,7 +31,7 @@ * * Description: add an instanceType onto every new record * - * Author: Simo Sorce + * Author: Andrew Bartlett */ #include "includes.h" -- cgit From f106e67599a02426d5eaf87e9d76bec486427add Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 18 Jan 2008 13:27:05 +1100 Subject: Search for memberOf when clients ask for a wildcard against OpenLDAP The memberOf module in OpenLDAP make this attribute operational, so we need to add it here or clients won't get it when using *. Andrew Bartlett (This used to be commit 35148fd51f22d81fe9f590b7d6f13285c35656a7) --- source4/dsdb/samdb/ldb_modules/simple_ldap_map.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/dsdb') diff --git a/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c b/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c index 6e66d0783a..acf2fd622c 100644 --- a/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c +++ b/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c @@ -448,6 +448,7 @@ static const char * const entryuuid_wildcard_attributes[] = { "whenChanged", "usnCreated", "usnChanged", + "memberOf", NULL }; -- cgit From 391f089d71b4b51a130819ab681dcd1253f16b8c Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 18 Jan 2008 16:56:41 +1100 Subject: Add showInAdvancedViewOnly to every new object Unless already set, the default value for this comes from the defaultHidingValue in the schema. Andrew Bartlett (This used to be commit 673f1805006f879fa5302aab8411767a22488e64) --- source4/dsdb/samdb/ldb_modules/objectclass.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source4/dsdb') diff --git a/source4/dsdb/samdb/ldb_modules/objectclass.c b/source4/dsdb/samdb/ldb_modules/objectclass.c index d3beedc689..871c38476b 100644 --- a/source4/dsdb/samdb/ldb_modules/objectclass.c +++ b/source4/dsdb/samdb/ldb_modules/objectclass.c @@ -532,6 +532,10 @@ static int objectclass_do_add(struct ldb_handle *h) ldb_msg_add_string(msg, "objectCategory", current->objectclass->defaultObjectCategory); } + if (!ldb_msg_find_element(msg, "showInAdvancedViewOnly")) { + ldb_msg_add_string(msg, "showInAdvancedViewOnly", + current->objectclass->defaultHidingValue ? "TRUE" : "FALSE"); + } if (!ldb_msg_find_element(msg, "nTSecurityDescriptor")) { DATA_BLOB *sd = get_sd(ac->module, mem_ctx, current->objectclass); ldb_msg_add_steal_value(msg, "nTSecurityDescriptor", sd); -- cgit From 7e2ea67b2118d31d11ed668d081568f7ef2243ae Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 18 Jan 2008 18:08:49 +1100 Subject: Only set showOnlyInAdvancedView: TRUE when adding default values. False is the default, so only set this when the schema requires the hiding behaviour. Andrew Bartlett (This used to be commit 45f6ccefda39e8f0a9820ba55b1924b7cfb12262) --- source4/dsdb/samdb/ldb_modules/objectclass.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/dsdb') diff --git a/source4/dsdb/samdb/ldb_modules/objectclass.c b/source4/dsdb/samdb/ldb_modules/objectclass.c index 871c38476b..737475ca78 100644 --- a/source4/dsdb/samdb/ldb_modules/objectclass.c +++ b/source4/dsdb/samdb/ldb_modules/objectclass.c @@ -532,9 +532,9 @@ static int objectclass_do_add(struct ldb_handle *h) ldb_msg_add_string(msg, "objectCategory", current->objectclass->defaultObjectCategory); } - if (!ldb_msg_find_element(msg, "showInAdvancedViewOnly")) { + if (!ldb_msg_find_element(msg, "showInAdvancedViewOnly") && (current->objectclass->defaultHidingValue == true)) { ldb_msg_add_string(msg, "showInAdvancedViewOnly", - current->objectclass->defaultHidingValue ? "TRUE" : "FALSE"); + "TRUE"); } if (!ldb_msg_find_element(msg, "nTSecurityDescriptor")) { DATA_BLOB *sd = get_sd(ac->module, mem_ctx, current->objectclass); -- cgit