summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
-rw-r--r--source4/lib/ldb/include/ldb.h11
-rw-r--r--source4/lib/ldb/modules/asq.c4
-rw-r--r--source4/lib/ldb/modules/paged_results.c4
-rw-r--r--source4/lib/ldb/modules/sort.c4
-rw-r--r--source4/scripting/libjs/provision.js169
-rwxr-xr-xsource4/setup/provision15
-rw-r--r--source4/setup/provision.ldif43
-rw-r--r--source4/setup/provision_basedn.ldif8
-rw-r--r--source4/setup/provision_basedn_modify.ldif90
-rw-r--r--source4/setup/provision_templates.ldif19
-rw-r--r--source4/setup/provision_users.ldif2
17 files changed, 650 insertions, 92 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) {
diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h
index 033a9c1f39..b684b03ef4 100644
--- a/source4/lib/ldb/include/ldb.h
+++ b/source4/lib/ldb/include/ldb.h
@@ -567,7 +567,8 @@ enum ldb_request_type {
LDB_MODIFY,
LDB_DELETE,
LDB_RENAME,
- LDB_REQ_REGISTER,
+ LDB_REQ_REGISTER_CONTROL,
+ LDB_REQ_REGISTER_PARTITION,
LDB_SEQUENCE_NUMBER
};
@@ -638,6 +639,10 @@ struct ldb_register_control {
const char *oid;
};
+struct ldb_register_partition {
+ const struct ldb_dn *dn;
+};
+
struct ldb_sequence_number {
uint64_t seq_num;
};
@@ -652,7 +657,8 @@ struct ldb_request {
struct ldb_modify mod;
struct ldb_delete del;
struct ldb_rename rename;
- struct ldb_register_control reg;
+ struct ldb_register_control reg_control;
+ struct ldb_register_partition reg_partition;
struct ldb_sequence_number seq_num;
} op;
@@ -1245,6 +1251,7 @@ const struct ldb_attrib_handler *ldb_attrib_handler(struct ldb_context *ldb,
const char **ldb_attr_list_copy(void *mem_ctx, const char * const *attrs);
+const char **ldb_attr_list_copy_add(void *mem_ctx, const char * const *attrs, const char *new_attr);
int ldb_attr_in_list(const char * const *attrs, const char *attr);
diff --git a/source4/lib/ldb/modules/asq.c b/source4/lib/ldb/modules/asq.c
index 75ef4a487e..2c0baa6827 100644
--- a/source4/lib/ldb/modules/asq.c
+++ b/source4/lib/ldb/modules/asq.c
@@ -442,8 +442,8 @@ static int asq_init(struct ldb_module *module)
return LDB_ERR_OPERATIONS_ERROR;
}
- req->operation = LDB_REQ_REGISTER;
- req->op.reg.oid = LDB_CONTROL_ASQ_OID;
+ req->operation = LDB_REQ_REGISTER_CONTROL;
+ req->op.reg_control.oid = LDB_CONTROL_ASQ_OID;
ret = ldb_request(module->ldb, req);
if (ret != LDB_SUCCESS) {
diff --git a/source4/lib/ldb/modules/paged_results.c b/source4/lib/ldb/modules/paged_results.c
index bdfaea6d51..c5a1504fa5 100644
--- a/source4/lib/ldb/modules/paged_results.c
+++ b/source4/lib/ldb/modules/paged_results.c
@@ -542,8 +542,8 @@ static int paged_request_init(struct ldb_module *module)
return LDB_ERR_OPERATIONS_ERROR;
}
- req->operation = LDB_REQ_REGISTER;
- req->op.reg.oid = LDB_CONTROL_PAGED_RESULTS_OID;
+ req->operation = LDB_REQ_REGISTER_CONTROL;
+ req->op.reg_control.oid = LDB_CONTROL_PAGED_RESULTS_OID;
req->controls = NULL;
ret = ldb_request(module->ldb, req);
diff --git a/source4/lib/ldb/modules/sort.c b/source4/lib/ldb/modules/sort.c
index 23f4f36478..d72647be66 100644
--- a/source4/lib/ldb/modules/sort.c
+++ b/source4/lib/ldb/modules/sort.c
@@ -429,8 +429,8 @@ static int server_sort_init(struct ldb_module *module)
return LDB_ERR_OPERATIONS_ERROR;
}
- req->operation = LDB_REQ_REGISTER;
- req->op.reg.oid = LDB_CONTROL_SERVER_SORT_OID;
+ req->operation = LDB_REQ_REGISTER_CONTROL;
+ req->op.reg_control.oid = LDB_CONTROL_SERVER_SORT_OID;
req->controls = NULL;
ret = ldb_request(module->ldb, req);
diff --git a/source4/scripting/libjs/provision.js b/source4/scripting/libjs/provision.js
index 64485efa03..877d8530e5 100644
--- a/source4/scripting/libjs/provision.js
+++ b/source4/scripting/libjs/provision.js
@@ -71,7 +71,7 @@ function setup_name_mapping(info, ldb, sid, unixname)
{
var attrs = new Array("dn");
var res = ldb.search(sprintf("objectSid=%s", sid),
- NULL, ldb.SCOPE_DEFAULT, attrs);
+ info.subobj.BASEDN, ldb.SCOPE_SUBTREE, attrs);
if (res.length != 1) {
info.message("Failed to find record for objectSid %s\n", sid);
return false;
@@ -187,12 +187,72 @@ function ldb_erase(ldb)
}
/*
+ erase an ldb, removing all records
+*/
+function ldb_erase_partitions(info, dbname)
+{
+ var rootDSE_attrs = new Array("namingContexts");
+ var ldb = ldb_init();
+ var lp = loadparm_init();
+ var j;
+
+ ldb.session_info = info.session_info;
+ ldb.credentials = info.credentials;
+
+
+ ldb.filename = dbname;
+
+ var connect_ok = ldb.connect(dbname);
+ assert(connect_ok);
+
+ ldb.transaction_start();
+
+ var res = ldb.search("(objectClass=*)", "", ldb.SCOPE_BASE, rootDSE_attrs);
+ assert(typeof(res) != "undefined");
+ assert(res.length == 1);
+ for (j=0; j<res[0].namingContexts.length; j++) {
+ var attrs = new Array("dn");
+ var basedn = res[0].namingContexts[j];
+ var k;
+ var previous_remaining = 1;
+ var current_remaining = 0;
+
+ for (k=0; k < 10 && (previous_remaining != current_remaining); k++) {
+ /* and the rest */
+ var res2 = ldb.search("(|(objectclass=*)(dn=*))", basedn, ldb.SCOPE_SUBTREE, attrs);
+ var i;
+ if (typeof(res2) == "undefined") {
+ info.message("ldb search failed: " + ldb.errstring() + "\n");
+ continue;
+ }
+ previous_remaining = current_remaining;
+ current_remaining = res2.length;
+ for (i=0;i<res2.length;i++) {
+ ldb.del(res2[i].dn);
+ }
+
+ var res3 = ldb.search("(|(objectclass=*)(dn=*))", basedn, ldb.SCOPE_SUBTREE, attrs);
+ if (res3.length != 0) {
+ info.message("Failed to delete all records under " + basedn + ", " + res3.length + " records remaining\n");
+ }
+ }
+ }
+
+ var commit_ok = ldb.transaction_commit();
+ if (!commit_ok) {
+ info.message("ldb commit failed: " + ldb.errstring() + "\n");
+ assert(add_ok);
+ }
+}
+
+/*
setup a ldb in the private dir
*/
function setup_ldb(ldif, info, dbname)
{
var erase = true;
var extra = "";
+ var failok = false;
var ldb = ldb_init();
var lp = loadparm_init();
ldb.session_info = info.session_info;
@@ -202,10 +262,14 @@ function setup_ldb(ldif, info, dbname)
extra = arguments[3];
}
- if (arguments.length == 5) {
+ if (arguments.length >= 5) {
erase = arguments[4];
}
+ if (arguments.length == 6) {
+ failok = arguments[5];
+ }
+
var src = lp.get("setup directory") + "/" + ldif;
var data = sys.file_load(src);
@@ -215,7 +279,11 @@ function setup_ldb(ldif, info, dbname)
ldb.filename = dbname;
var connect_ok = ldb.connect(dbname);
- assert(connect_ok);
+ if (!connect_ok) {
+ sys.unlink(sprintf("%s/%s", lp.get("private dir"), dbname));
+ connect_ok = ldb.connect(dbname);
+ assert(connect_ok);
+ }
ldb.transaction_start();
@@ -226,12 +294,50 @@ function setup_ldb(ldif, info, dbname)
var add_ok = ldb.add(data);
if (!add_ok) {
info.message("ldb load failed: " + ldb.errstring() + "\n");
- assert(add_ok);
+ if (!failok) {
+ assert(add_ok);
+ }
+ }
+ if (add_ok) {
+ var commit_ok = ldb.transaction_commit();
+ if (!commit_ok) {
+ info.message("ldb commit failed: " + ldb.errstring() + "\n");
+ assert(commit_ok);
+ }
+ }
+}
+
+/*
+ setup a ldb in the private dir
+ */
+function setup_ldb_modify(ldif, info, dbname)
+{
+ var ldb = ldb_init();
+ var lp = loadparm_init();
+ ldb.session_info = info.session_info;
+ ldb.credentials = info.credentials;
+
+ var src = lp.get("setup directory") + "/" + ldif;
+
+ var data = sys.file_load(src);
+ data = substitute_var(data, info.subobj);
+
+ ldb.filename = dbname;
+
+ var connect_ok = ldb.connect(dbname);
+ assert(connect_ok);
+
+ ldb.transaction_start();
+
+ var mod_ok = ldb.modify(data);
+ if (!mod_ok) {
+ info.message("ldb load failed: " + ldb.errstring() + "\n");
+ assert(mod_ok);
}
var commit_ok = ldb.transaction_commit();
if (!commit_ok) {
info.message("ldb commit failed: " + ldb.errstring() + "\n");
- assert(add_ok);
+ assert(commit_ok);
}
}
@@ -271,6 +377,7 @@ function provision_default_paths(subobj)
paths.secrets = "secrets.ldb";
paths.dns = lp.get("private dir") + "/" + subobj.DNSDOMAIN + ".zone";
paths.winsdb = "wins.ldb";
+ paths.ldap_basedn_ldif = lp.get("private dir") + "/" + subobj.DNSDOMAIN + ".ldif";
return paths;
}
@@ -289,12 +396,8 @@ function setup_name_mappings(info, subobj, session_info, credentials)
return false;
}
var attrs = new Array("objectSid");
- var res = ldb.search("dnsDomain=" + subobj.REALM,
- NULL, ldb.SCOPE_DEFAULT, attrs);
- if (res.length != 1) {
- info.message("Failed to find dnsDomain %s\n", subobj.REALM);
- return false;
- }
+ res = ldb.search("objectSid=*", subobj.BASEDN, ldb.SCOPE_BASE, attrs);
+ assert(res.length == 1 && res[0].objectSid != undefined);
var sid = res[0].objectSid;
/* add some foreign sids if they are not present already */
@@ -369,9 +472,16 @@ function provision(subobj, message, blank, paths, session_info, credentials)
message("Setting up hklm.ldb\n");
setup_ldb("hklm.ldif", info, paths.hklm);
-
message("Setting up sam.ldb attributes\n");
setup_ldb("provision_init.ldif", info, paths.samdb);
+ message("Erasing data from partitions\n");
+ ldb_erase_partitions(info, paths.samdb);
+
+ message("Adding baseDN: " + subobj.BASEDN + "\n");
+ setup_ldb("provision_basedn.ldif", info, paths.samdb, NULL, false, true);
+ message("Modifying baseDN: " + subobj.BASEDN + "\n");
+ setup_ldb_modify("provision_basedn_modify.ldif", info, paths.samdb)
+
message("Setting up sam.ldb schema\n");
setup_ldb("schema.ldif", info, paths.samdb, NULL, false);
message("Setting up display specifiers\n");
@@ -408,10 +518,12 @@ function provision_dns(subobj, message, paths, session_info, credentials)
assert(ok);
/* These values may have changed, due to an incoming SamSync, so fetch them from the database */
- subobj.DOMAINGUID = searchone(ldb, "(&(objectClass=domainDNS)(dnsDomain=" + subobj.DNSDOMAIN + "))", "objectGUID");
- assert(subobj.DOMAINGUID != undefined);
+ var attrs = new Array("objectGUID");
+ res = ldb.search("objectGUID=*", subobj.BASEDN, ldb.SCOPE_BASE, attrs);
+ assert(res.length == 1 && res[0].objectGUID != undefined)
+ subobj.DOMAINGUID = res[0].objectGUID;
- subobj.HOSTGUID = searchone(ldb, "(&(objectClass=computer)(cn=" + subobj.NETBIOSNAME + "))", "objectGUID");
+ subobj.HOSTGUID = searchone(ldb, subobj.BASEDN, "(&(objectClass=computer)(cn=" + subobj.NETBIOSNAME + "))", "objectGUID");
assert(subobj.HOSTGUID != undefined);
setup_file("provision.zone",
@@ -421,6 +533,21 @@ function provision_dns(subobj, message, paths, session_info, credentials)
message("Please install the zone located in " + paths.dns + " into your DNS server\n");
}
+/* Write out a DNS zone file, from the info in the current database */
+function provision_ldapbase(subobj, message, paths)
+{
+ message("Setting up LDAP base entry: " + subobj.BASEDN + " \n");
+ var rdns = split(",", subobj.BASEDN);
+ subobj.RDN_DC = substr(rdns[0], strlen("DC="));
+
+ setup_file("provision_basedn.ldif",
+ message, paths.ldap_basedn_ldif,
+ subobj);
+
+ message("Please install the LDIF located in " + paths.ldap_basedn_ldif + " into your LDAP server, and re-run with --ldap-backend=ldap://my.ldap.server\n");
+}
+
+
/*
guess reasonably default options for provisioning
*/
@@ -466,16 +593,17 @@ function provision_guess()
subobj.DNSDOMAIN);
rdn_list = split(".", subobj.DNSDOMAIN);
subobj.BASEDN = "DC=" + join(",DC=", rdn_list);
+ subobj.LDAPBACKEND = "users.ldb";
return subobj;
}
/*
search for one attribute as a string
*/
-function searchone(ldb, expression, attribute)
+function searchone(ldb, basedn, expression, attribute)
{
var attrs = new Array(attribute);
- res = ldb.search(expression, attrs);
+ res = ldb.search(expression, basedn, ldb.SCOPE_SUBTREE, attrs);
if (res.length != 1 ||
res[0][attribute] == undefined) {
return undefined;
@@ -524,9 +652,12 @@ function newuser(username, unixname, password, message, session_info, credential
ldb.transaction_start();
/* find the DNs for the domain and the domain users group */
- var domain_dn = searchone(ldb, "objectClass=domainDNS", "dn");
+ var attrs = new Array("defaultNamingContext");
+ res = ldb.search("defaultNamingContext=*", "", ldb.SCOPE_BASE, attrs);
+ assert(res.length == 1 && res[0].defaultNamingContext != undefined)
+ var domain_dn = res[0].defaultNamingContext;
assert(domain_dn != undefined);
- var dom_users = searchone(ldb, "name=Domain Users", "dn");
+ var dom_users = searchone(ldb, domain_dn, "name=Domain Users", "dn");
assert(dom_users != undefined);
var user_dn = sprintf("CN=%s,CN=Users,%s", username, domain_dn);
diff --git a/source4/setup/provision b/source4/setup/provision
index d6497cf180..a58f4a5dce 100755
--- a/source4/setup/provision
+++ b/source4/setup/provision
@@ -28,7 +28,9 @@ options = GetOptions(ARGV,
'wheel=s',
'users=s',
'quiet',
- 'blank');
+ 'blank',
+ 'ldap-base',
+ 'ldap-backend=s');
if (options == undefined) {
println("Failed to parse options");
@@ -75,6 +77,8 @@ provision [options]
--users GROUPNAME choose 'users' group
--quiet Be quiet
--blank do not add users or groups, just the structure
+ --ldap-base output only an LDIF file, suitable for creating an LDAP baseDN
+ --ldap-backend LDAPSERVER LDAP server to use for this provision
You must provide at least a realm and domain
@@ -108,6 +112,7 @@ for (r in options) {
}
var blank = (options["blank"] != undefined);
+var ldapbase = (options["ldap-base"] != undefined);
if (!provision_validate(subobj, message)) {
return -1;
@@ -118,7 +123,11 @@ var creds = options.get_credentials();
var paths = provision_default_paths(subobj);
message("Provisioning for %s in realm %s\n", subobj.DOMAIN, subobj.REALM);
message("Using administrator password: %s\n", subobj.ADMINPASS);
-provision(subobj, message, blank, paths, system_session, creds);
-provision_dns(subobj, message, paths, system_session, creds);
+if (ldapbase) {
+ provision_ldapbase(subobj, message, paths);
+} else {
+ provision(subobj, message, blank, paths, system_session, creds);
+ provision_dns(subobj, message, paths, system_session, creds);
+}
message("All OK\n");
return 0;
diff --git a/source4/setup/provision.ldif b/source4/setup/provision.ldif
index f59d92e769..c047d6d93a 100644
--- a/source4/setup/provision.ldif
+++ b/source4/setup/provision.ldif
@@ -1,38 +1,3 @@
-###############################
-# Domain Naming Context
-###############################
-dn: ${BASEDN}
-objectClass: top
-objectClass: domain
-objectClass: domainDNS
-dnsDomain: ${DNSDOMAIN}
-dc: ${RDN_DC}
-objectGUID: ${DOMAINGUID}
-creationTime: ${NTTIME}
-forceLogoff: 9223372036854775808
-lockoutDuration: -18000000000
-lockOutObservationWindow: -18000000000
-lockoutThreshold: 0
-maxPwdAge: -37108517437440
-minPwdAge: 0
-minPwdLength: 7
-modifiedCountAtLastProm: 0
-nextRid: 1000
-pwdProperties: 1
-pwdHistoryLength: 24
-objectSid: ${DOMAINSID}
-oEMInformation: Provisioned by Samba4: ${LDAPTIME}
-serverState: 1
-nTMixedDomain: 1
-msDS-Behavior-Version: 0
-ridManagerReference: CN=RID Manager$,CN=System,${BASEDN}
-uASCompat: 1
-modifiedCount: 1
-objectCategory: CN=Domain-DNS,CN=Schema,CN=Configuration,${BASEDN}
-isCriticalSystemObject: TRUE
-subRefs: CN=Configuration,${BASEDN}
-subRefs: CN=Schema,CN=Configuration,${BASEDN}
-
dn: CN=Users,${BASEDN}
objectClass: top
objectClass: container
@@ -57,15 +22,15 @@ systemFlags: 2348810240
objectCategory: CN=Container,CN=Schema,CN=Configuration,${BASEDN}
isCriticalSystemObject: TRUE
-dn: OU=Domain Controllers,${BASEDN}
+dn: CN=Domain Controllers,${BASEDN}
objectClass: top
-objectClass: organizationalUnit
-ou: Domain Controllers
+objectClass: container
+cn: Domain Controllers
description: Default container for domain controllers
instanceType: 4
showInAdvancedViewOnly: FALSE
systemFlags: 2348810240
-objectCategory: CN=Organizational-Unit,CN=Schema,CN=Configuration,${BASEDN}
+objectCategory: CN=Container,CN=Schema,CN=Configuration,${BASEDN}
isCriticalSystemObject: TRUE
dn: CN=ForeignSecurityPrincipals,${BASEDN}
diff --git a/source4/setup/provision_basedn.ldif b/source4/setup/provision_basedn.ldif
new file mode 100644
index 0000000000..4cf850e728
--- /dev/null
+++ b/source4/setup/provision_basedn.ldif
@@ -0,0 +1,8 @@
+################################
+## Domain Naming Context
+################################
+dn: ${BASEDN}
+objectClass: top
+objectClass: domain
+dc: ${RDN_DC}
+
diff --git a/source4/setup/provision_basedn_modify.ldif b/source4/setup/provision_basedn_modify.ldif
new file mode 100644
index 0000000000..91a8d66f24
--- /dev/null
+++ b/source4/setup/provision_basedn_modify.ldif
@@ -0,0 +1,90 @@
+###############################
+# Domain Naming Context
+###############################
+dn: ${BASEDN}
+changetype: modify
+replace: objectClass
+objectClass: top
+objectClass: domain
+objectClass: domainDNS
+-
+replace: dnsDomain
+dnsDomain: ${DNSDOMAIN}
+-
+replace: dc
+dc: ${RDN_DC}
+-
+replace: objectGUID
+objectGUID: ${DOMAINGUID}
+-
+replace: creationTime
+creationTime: ${NTTIME}
+-
+replace: forceLogoff
+forceLogoff: 9223372036854775808
+-
+replace: lockoutDuration
+lockoutDuration: -18000000000
+-
+replace: lockOutObservationWindow
+lockOutObservationWindow: -18000000000
+-
+replace: lockoutThreshold
+lockoutThreshold: 0
+-
+replace: maxPwdAge
+maxPwdAge: -37108517437440
+-
+replace: minPwdAge
+minPwdAge: 0
+-
+replace: minPwdLength
+minPwdLength: 7
+-
+replace: modifiedCountAtLastProm
+modifiedCountAtLastProm: 0
+-
+replace: nextRid
+nextRid: 1000
+-
+replace: pwdProperties
+pwdProperties: 1
+-
+replace: pwdHistoryLength
+pwdHistoryLength: 24
+-
+replace: objectSid
+objectSid: ${DOMAINSID}
+-
+replace: oEMInformation
+oEMInformation: Provisioned by Samba4: ${LDAPTIME}
+-
+replace: serverState
+serverState: 1
+-
+replace: nTMixedDomain
+nTMixedDomain: 1
+-
+replace: msDS-Behavior-Version
+msDS-Behavior-Version: 0
+-
+replace: ridManagerReference
+ridManagerReference: CN=RID Manager$,CN=System,${BASEDN}
+-
+replace: uASCompat
+uASCompat: 1
+-
+replace: modifiedCount
+modifiedCount: 1
+-
+replace: objectCategory
+objectCategory: CN=Domain-DNS,CN=Schema,CN=Configuration,${BASEDN}
+-
+replace: isCriticalSystemObject
+isCriticalSystemObject: TRUE
+-
+replace: subRefs
+subRefs: CN=Configuration,${BASEDN}
+subRefs: CN=Schema,CN=Configuration,${BASEDN}
+-
+
diff --git a/source4/setup/provision_templates.ldif b/source4/setup/provision_templates.ldif
index 11501a5b42..3b70d42520 100644
--- a/source4/setup/provision_templates.ldif
+++ b/source4/setup/provision_templates.ldif
@@ -1,4 +1,4 @@
-dn: CN=Templates,${BASEDN}
+dn: CN=Templates
objectClass: top
objectClass: container
cn: Templates
@@ -14,7 +14,7 @@ isCriticalSystemObject: TRUE
# with what classes you put them in
###
-dn: CN=TemplateUser,CN=Templates,${BASEDN}
+dn: CN=TemplateUser,CN=Templates
objectClass: top
objectClass: person
objectClass: organizationalPerson
@@ -36,7 +36,7 @@ logonCount: 0
sAMAccountType: 805306368
objectCategory: CN=Person,CN=Schema,CN=Configuration,${BASEDN}
-dn: CN=TemplateComputer,CN=Templates,${BASEDN}
+dn: CN=TemplateComputer,CN=Templates
objectClass: top
objectClass: person
objectClass: organizationalPerson
@@ -58,7 +58,7 @@ logonCount: 0
sAMAccountType: 805306369
objectCategory: CN=Computer,CN=Schema,CN=Configuration,${BASEDN}
-dn: CN=TemplateTrustingDomain,CN=Templates,${BASEDN}
+dn: CN=TemplateTrustingDomain,CN=Templates
objectClass: top
objectClass: Template
objectClass: userTemplate
@@ -71,13 +71,12 @@ countryCode: 0
badPasswordTime: 0
lastLogoff: 0
lastLogon: 0
-pwdLastSet: 0
primaryGroupID: 513
accountExpires: -1
logonCount: 0
sAMAccountType: 805306370
-dn: CN=TemplateGroup,CN=Templates,${BASEDN}
+dn: CN=TemplateGroup,CN=Templates
objectClass: top
objectClass: Template
objectClass: groupTemplate
@@ -89,7 +88,7 @@ objectCategory: CN=Group,CN=Schema,CN=Configuration,${BASEDN}
# Currently this isn't used, we don't have a way to detect it different from an incoming alias
#
-# dn: CN=TemplateAlias,CN=Templates,${BASEDN}
+# dn: CN=TemplateAlias,CN=Templates
# objectClass: top
# objectClass: Template
# objectClass: aliasTemplate
@@ -98,7 +97,7 @@ objectCategory: CN=Group,CN=Schema,CN=Configuration,${BASEDN}
# groupType: -2147483644
# sAMAccountType: 268435456
-dn: CN=TemplateForeignSecurityPrincipal,CN=Templates,${BASEDN}
+dn: CN=TemplateForeignSecurityPrincipal,CN=Templates
objectClass: top
objectClass: Template
objectClass: foreignSecurityPrincipalTemplate
@@ -107,7 +106,7 @@ instanceType: 4
showInAdvancedViewOnly: TRUE
objectCategory: CN=Foreign-Security-Principal,CN=Schema,CN=Configuration,${BASEDN}
-dn: CN=TemplateSecret,CN=Templates,${BASEDN}
+dn: CN=TemplateSecret,CN=Templates
objectClass: top
objectClass: leaf
objectClass: Template
@@ -115,7 +114,7 @@ objectClass: secretTemplate
cn: TemplateSecret
instanceType: 4
-dn: CN=TemplateTrustedDomain,CN=Templates,${BASEDN}
+dn: CN=TemplateTrustedDomain,CN=Templates
objectClass: top
objectClass: leaf
objectClass: Template
diff --git a/source4/setup/provision_users.ldif b/source4/setup/provision_users.ldif
index dc7bc016d5..5cd5991c41 100644
--- a/source4/setup/provision_users.ldif
+++ b/source4/setup/provision_users.ldif
@@ -68,7 +68,7 @@ privilege: SeNetworkLogonRight
privilege: SeRemoteInteractiveLogonRight
-dn: CN=${NETBIOSNAME},OU=Domain Controllers,${BASEDN}
+dn: CN=${NETBIOSNAME},CN=Domain Controllers,${BASEDN}
objectClass: computer
cn: ${NETBIOSNAME}
objectGUID: ${HOSTGUID}