diff options
Diffstat (limited to 'source4/dsdb/samdb/ldb_modules')
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/config.mk | 11 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/extended_dn.c | 4 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/partition.c | 297 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/rootdse.c | 50 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/samldb.c | 2 |
5 files changed, 356 insertions, 8 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/config.mk b/source4/dsdb/samdb/ldb_modules/config.mk index 3790d731d9..ce4f12bcfe 100644 --- a/source4/dsdb/samdb/ldb_modules/config.mk +++ b/source4/dsdb/samdb/ldb_modules/config.mk @@ -92,3 +92,14 @@ OBJ_FILES = \ # End MODULE ldb_extended_dn ################################################ +################################################ +# Start MODULE ldb_partition +[MODULE::ldb_partition] +SUBSYSTEM = ldb +INIT_FUNCTION = ldb_partition_init +OBJ_FILES = \ + partition.o +# +# End MODULE ldb_partition +################################################ + diff --git a/source4/dsdb/samdb/ldb_modules/extended_dn.c b/source4/dsdb/samdb/ldb_modules/extended_dn.c index 71f7a2dc7e..aa800a0ae1 100644 --- a/source4/dsdb/samdb/ldb_modules/extended_dn.c +++ b/source4/dsdb/samdb/ldb_modules/extended_dn.c @@ -311,8 +311,8 @@ static int extended_init(struct ldb_module *module) return LDB_ERR_OPERATIONS_ERROR; } - req->operation = LDB_REQ_REGISTER; - req->op.reg.oid = LDB_CONTROL_EXTENDED_DN_OID; + req->operation = LDB_REQ_REGISTER_CONTROL; + req->op.reg_control.oid = LDB_CONTROL_EXTENDED_DN_OID; req->controls = NULL; ret = ldb_request(module->ldb, req); diff --git a/source4/dsdb/samdb/ldb_modules/partition.c b/source4/dsdb/samdb/ldb_modules/partition.c new file mode 100644 index 0000000000..6d3d42c23a --- /dev/null +++ b/source4/dsdb/samdb/ldb_modules/partition.c @@ -0,0 +1,297 @@ +/* + Partitions ldb module + + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006 + + * NOTICE: this module is NOT released under the GNU LGPL license as + * other ldb code. This module is release under the GNU GPL v2 or + * later license. + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + * Name: ldb + * + * Component: ldb partitions module + * + * Description: Implement LDAP partitions + * + * Author: Andrew Bartlett + */ + +#include "includes.h" +#include "ldb/include/includes.h" + +struct partition { + struct ldb_module *module; + const char *backend; + struct ldb_dn *dn; +}; +struct partition_private_data { + struct partition **partitions; +}; + +struct ldb_module *find_backend(struct ldb_module *module, struct ldb_request *req, const struct ldb_dn *dn) +{ + int i; + struct partition_private_data *data = talloc_get_type(module->private_data, + struct partition_private_data); + /* Look at base DN */ + /* Figure out which partition it is under */ + /* Skip the lot if 'data' isn't here yet (initialistion) */ + for (i=0; data && data->partitions && data->partitions[i]; i++) { + if (ldb_dn_compare_base(module->ldb, + data->partitions[i]->dn, + dn) == 0) { + struct ldb_module *current; + static const struct ldb_module_ops ops; /* zero */ + current = talloc_zero(req, struct ldb_module); + if (current == NULL) { + return module; + } + + current->ldb = module->ldb; + current->ops = &ops; + current->prev = module; + current->next = data->partitions[i]->module; + return current; + } + } + + return module; +}; + +/* search */ +static int partition_search(struct ldb_module *module, struct ldb_request *req) +{ + /* Find backend */ + struct ldb_module *backend = find_backend(module, req, req->op.search.base); + + /* issue request */ + + /* (later) consider if we should be searching multiple + * partitions (for 'invisible' partition behaviour */ + return ldb_next_request(backend, req); +} + +/* add */ +static int partition_add(struct ldb_module *module, struct ldb_request *req) +{ + /* Find backend */ + struct ldb_module *backend = find_backend(module, req, req->op.add.message->dn); + + /* issue request */ + + return ldb_next_request(backend, req); +} + +/* modify */ +static int partition_modify(struct ldb_module *module, struct ldb_request *req) +{ + /* Find backend */ + struct ldb_module *backend = find_backend(module, req, req->op.mod.message->dn); + + /* issue request */ + + return ldb_next_request(backend, req); +} + +/* delete */ +static int partition_delete(struct ldb_module *module, struct ldb_request *req) +{ + /* Find backend */ + struct ldb_module *backend = find_backend(module, req, req->op.del.dn); + + /* issue request */ + + return ldb_next_request(backend, req); +} + +/* rename */ +static int partition_rename(struct ldb_module *module, struct ldb_request *req) +{ + /* Find backend */ + struct ldb_module *backend = find_backend(module, req, req->op.rename.olddn); + struct ldb_module *backend2 = find_backend(module, req, req->op.rename.newdn); + + if (backend->next != backend2->next) { + return LDB_ERR_AFFECTS_MULTIPLE_DSAS; + } + + /* issue request */ + + /* (later) consider if we should be searching multiple partitions */ + return ldb_next_request(backend, req); +} + +#if 0 +/* We should do this over the entire list of partitions */ + +/* start a transaction */ +static int partition_start_trans(struct ldb_module *module) +{ + return ldb_next_start_trans(module); +} + +/* end a transaction */ +static int partition_end_trans(struct ldb_module *module) +{ + return ldb_next_end_trans(module); +} + +/* delete a transaction */ +static int partition_del_trans(struct ldb_module *module) +{ + return ldb_next_del_trans(module); +} +#endif + +static int partition_init(struct ldb_module *module) +{ + int ret, i; + TALLOC_CTX *mem_ctx = talloc_new(module); + static const char *attrs[] = { "partition", NULL }; + struct ldb_result *res; + struct ldb_message *msg; + struct ldb_message_element *partition_attributes; + + struct partition_private_data *data; + + if (!mem_ctx) { + return LDB_ERR_OPERATIONS_ERROR; + } + + data = talloc(mem_ctx, struct partition_private_data); + if (data == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_search(module->ldb, ldb_dn_explode(mem_ctx, "@PARTITION"), + LDB_SCOPE_BASE, + NULL, attrs, + &res); + if (ret != LDB_SUCCESS) { + talloc_free(mem_ctx); + return ret; + } + talloc_steal(mem_ctx, res); + if (res->count == 0) { + talloc_free(mem_ctx); + return ldb_next_init(module); + } + + if (res->count > 1) { + talloc_free(mem_ctx); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + + msg = res->msgs[0]; + + partition_attributes = ldb_msg_find_element(msg, "partition"); + if (!partition_attributes) { + ldb_set_errstring(module->ldb, + talloc_asprintf(module, "partition_init: " + "no partitions specified")); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + data->partitions = talloc_array(data, struct partition *, partition_attributes->num_values + 1); + if (!data->partitions) { + talloc_free(mem_ctx); + return LDB_ERR_OPERATIONS_ERROR; + } + for (i=0; i < partition_attributes->num_values; i++) { + struct ldb_request *req; + + char *base = talloc_strdup(data->partitions, (char *)partition_attributes->values[i].data); + char *p = strchr(base, ':'); + if (!p) { + ldb_set_errstring(module->ldb, + talloc_asprintf(module, "partition_init: " + "invalid form for partition record (missing ':'): %s", base)); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + p[0] = '\0'; + p++; + if (!p[0]) { + ldb_set_errstring(module->ldb, + talloc_asprintf(module, "partition_init: " + "invalid form for partition record (missing backend database): %s", base)); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + data->partitions[i] = talloc(data->partitions, struct partition); + if (!data->partitions[i]) { + talloc_free(mem_ctx); + return LDB_ERR_OPERATIONS_ERROR; + } + + data->partitions[i]->dn = ldb_dn_explode(data->partitions[i], base); + if (!data->partitions[i]->dn) { + ldb_set_errstring(module->ldb, + talloc_asprintf(module, "partition_init: " + "invalid DN in partition record: %s", base)); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + + data->partitions[i]->backend = private_path(data->partitions[i], p); + ret = ldb_connect_backend(module->ldb, data->partitions[i]->backend, 0, NULL, &data->partitions[i]->module); + if (ret != LDB_SUCCESS) { + return ret; + } + + req = talloc_zero(mem_ctx, struct ldb_request); + if (req == NULL) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "partition: Out of memory!\n"); + return LDB_ERR_OPERATIONS_ERROR; + } + + req->operation = LDB_REQ_REGISTER_PARTITION; + req->op.reg_partition.dn = data->partitions[i]->dn; + + ret = ldb_request(module->ldb, req); + if (ret != LDB_SUCCESS) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "partition: Unable to register partition with rootdse!\n"); + return LDB_ERR_OTHER; + } + talloc_free(req); + } + data->partitions[i] = NULL; + + module->private_data = data; + talloc_steal(module, data); + + talloc_free(mem_ctx); + return ldb_next_init(module); +} + +static const struct ldb_module_ops partition_ops = { + .name = "partition", + .init_context = partition_init, + .search = partition_search, + .add = partition_add, + .modify = partition_modify, + .del = partition_delete, + .rename = partition_rename, +#if 0 + .start_transaction = partition_start_trans, + .end_transaction = partition_end_trans, + .del_transaction = partition_del_trans, +#endif +}; + +int ldb_partition_init(void) +{ + return ldb_register_module(&partition_ops); +} diff --git a/source4/dsdb/samdb/ldb_modules/rootdse.c b/source4/dsdb/samdb/ldb_modules/rootdse.c index 49d93be7f2..fd3d2d0fe7 100644 --- a/source4/dsdb/samdb/ldb_modules/rootdse.c +++ b/source4/dsdb/samdb/ldb_modules/rootdse.c @@ -31,6 +31,8 @@ struct private_data { int num_controls; char **controls; + int num_partitions; + struct ldb_dn **partitions; }; /* @@ -54,8 +56,10 @@ static int rootdse_add_dynamic(struct ldb_module *module, struct ldb_message *ms msg->dn = ldb_dn_explode(msg, ""); - /* don't return the distinduishedName attribute if any */ + /* don't return the distinduishedName, cn and name attributes */ ldb_msg_remove_attr(msg, "distinguishedName"); + ldb_msg_remove_attr(msg, "cn"); + ldb_msg_remove_attr(msg, "name"); if (do_attribute(attrs, "currentTime")) { if (ldb_msg_add_steal_string(msg, "currentTime", @@ -78,6 +82,17 @@ static int rootdse_add_dynamic(struct ldb_module *module, struct ldb_message *ms } } + if (do_attribute(attrs, "namingContexts")) { + int i; + for (i = 0; i < priv->num_partitions; i++) { + struct ldb_dn *dn = priv->partitions[i]; + if (ldb_msg_add_steal_string(msg, "namingContexts", + ldb_dn_linearize(msg, dn)) != 0) { + goto failed; + } + } + } + server_creds = talloc_get_type(ldb_get_opaque(module->ldb, "server_credentials"), struct cli_credentials); if (server_creds && do_attribute(attrs, "supportedSASLMechanisms")) { @@ -111,7 +126,7 @@ static int rootdse_add_dynamic(struct ldb_module *module, struct ldb_message *ms } } } - + /* TODO: lots more dynamic attributes should be added here */ return LDB_SUCCESS; @@ -189,7 +204,7 @@ static int rootdse_search(struct ldb_module *module, struct ldb_request *req) /* in our db we store the rootDSE with a DN of cn=rootDSE */ down_req->op.search.base = ldb_dn_explode(down_req, "cn=rootDSE"); down_req->op.search.scope = LDB_SCOPE_BASE; - down_req->op.search.tree = ldb_parse_tree(down_req, "dn=*"); + down_req->op.search.tree = ldb_parse_tree(down_req, NULL); if (down_req->op.search.base == NULL || down_req->op.search.tree == NULL) { ldb_oom(module->ldb); talloc_free(down_req); @@ -224,7 +239,7 @@ static int rootdse_register_control(struct ldb_module *module, struct ldb_reques return LDB_ERR_OPERATIONS_ERROR; } - list[priv->num_controls] = talloc_strdup(list, req->op.reg.oid); + list[priv->num_controls] = talloc_strdup(list, req->op.reg_control.oid); if (!list[priv->num_controls]) { return LDB_ERR_OPERATIONS_ERROR; } @@ -235,13 +250,36 @@ static int rootdse_register_control(struct ldb_module *module, struct ldb_reques return LDB_SUCCESS; } +static int rootdse_register_partition(struct ldb_module *module, struct ldb_request *req) +{ + struct private_data *priv = talloc_get_type(module->private_data, struct private_data); + struct ldb_dn **list; + + list = talloc_realloc(priv, priv->partitions, struct ldb_dn *, priv->num_partitions + 1); + if (!list) { + return LDB_ERR_OPERATIONS_ERROR; + } + + list[priv->num_partitions] = talloc_reference(list, req->op.reg_partition.dn); + if (!list[priv->num_partitions]) { + return LDB_ERR_OPERATIONS_ERROR; + } + + priv->num_partitions += 1; + priv->partitions = list; + + return LDB_SUCCESS; +} + static int rootdse_request(struct ldb_module *module, struct ldb_request *req) { switch (req->operation) { - case LDB_REQ_REGISTER: + case LDB_REQ_REGISTER_CONTROL: return rootdse_register_control(module, req); + case LDB_REQ_REGISTER_PARTITION: + return rootdse_register_partition(module, req); default: break; @@ -260,6 +298,8 @@ static int rootdse_init(struct ldb_module *module) data->num_controls = 0; data->controls = NULL; + data->num_partitions = 0; + data->partitions = NULL; module->private_data = data; return ldb_next_init(module); diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index b883809417..2f0c6f2d17 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -490,7 +490,7 @@ static int samldb_copy_template(struct ldb_module *module, struct ldb_message *m struct ldb_message *t; int ret, i, j; - struct ldb_dn *basedn = ldb_dn_string_compose(msg, samdb_base_dn(msg), "cn=Templates"); + struct ldb_dn *basedn = ldb_dn_explode(msg, "cn=Templates"); /* pull the template record */ ret = ldb_search(module->ldb, basedn, LDB_SCOPE_SUBTREE, filter, NULL, &res); |