summaryrefslogtreecommitdiff
path: root/source4/dsdb/samdb/ldb_modules
diff options
context:
space:
mode:
Diffstat (limited to 'source4/dsdb/samdb/ldb_modules')
-rw-r--r--source4/dsdb/samdb/ldb_modules/config.mk11
-rw-r--r--source4/dsdb/samdb/ldb_modules/extended_dn.c4
-rw-r--r--source4/dsdb/samdb/ldb_modules/partition.c297
-rw-r--r--source4/dsdb/samdb/ldb_modules/rootdse.c50
-rw-r--r--source4/dsdb/samdb/ldb_modules/samldb.c2
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);