summaryrefslogtreecommitdiff
path: root/source4/dsdb/samdb
diff options
context:
space:
mode:
Diffstat (limited to 'source4/dsdb/samdb')
-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
-rw-r--r--source4/dsdb/samdb/samdb.c9
6 files changed, 361 insertions, 12 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);
diff --git a/source4/dsdb/samdb/samdb.c b/source4/dsdb/samdb/samdb.c
index 1b95fdf970..399308967e 100644
--- a/source4/dsdb/samdb/samdb.c
+++ b/source4/dsdb/samdb/samdb.c
@@ -404,7 +404,7 @@ struct dom_sid *samdb_result_dom_sid(TALLOC_CTX *mem_ctx, struct ldb_message *ms
/*
pull a guid structure from a objectGUID in a result set.
*/
-struct GUID samdb_result_guid(struct ldb_message *msg, const char *attr)
+struct GUID samdb_result_guid(const struct ldb_message *msg, const char *attr)
{
const struct ldb_val *v;
NTSTATUS status;
@@ -630,9 +630,10 @@ int samdb_copy_template(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx,
struct ldb_message **res, *t;
int ret, i, j;
+ struct ldb_dn *basedn = ldb_dn_explode(msg, "cn=Templates");
/* pull the template record */
- ret = gendb_search(sam_ldb, mem_ctx, NULL, &res, NULL, "%s", expression);
+ ret = gendb_search(sam_ldb, mem_ctx, basedn, &res, NULL, "%s", expression);
if (ret != 1) {
DEBUG(1,("samdb: ERROR: template '%s' matched %d records\n",
expression, ret));
@@ -1136,7 +1137,7 @@ _PUBLIC_ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ct
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- count = gendb_search(ctx, mem_ctx, NULL, &res, domain_attrs,
+ count = gendb_search(ctx, mem_ctx, samdb_base_dn(mem_ctx), &res, domain_attrs,
"(objectSid=%s)",
ldap_encode_ndr_dom_sid(mem_ctx, domain_sid));
if (count != 1) {
@@ -1313,7 +1314,7 @@ _PUBLIC_ NTSTATUS samdb_set_password_sid(struct ldb_context *ctx, TALLOC_CTX *me
return NT_STATUS_TRANSACTION_ABORTED;
}
- user_dn = samdb_search_dn(ctx, mem_ctx, NULL,
+ user_dn = samdb_search_dn(ctx, mem_ctx, samdb_base_dn(mem_ctx),
"(&(objectSid=%s)(objectClass=user))",
ldap_encode_ndr_dom_sid(mem_ctx, user_sid));
if (!user_dn) {