summaryrefslogtreecommitdiff
path: root/source4/dsdb/samdb/ldb_modules
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2009-10-17 10:36:33 -0700
committerJeremy Allison <jra@samba.org>2009-10-17 10:36:33 -0700
commit7c51fa6d699a653cafa90df8e44911b576118ebd (patch)
tree543bf9ca698e03eff81104898b33e77f1abed319 /source4/dsdb/samdb/ldb_modules
parentcc3a6770c77ec8fe1cd63bf4c682853c56201f0c (diff)
parent3e3214fd91471bca5b6c4d3782e922d252d588fb (diff)
downloadsamba-7c51fa6d699a653cafa90df8e44911b576118ebd.tar.gz
samba-7c51fa6d699a653cafa90df8e44911b576118ebd.tar.bz2
samba-7c51fa6d699a653cafa90df8e44911b576118ebd.zip
Merge branch 'master' of ssh://jra@git.samba.org/data/git/samba
Diffstat (limited to 'source4/dsdb/samdb/ldb_modules')
-rw-r--r--source4/dsdb/samdb/ldb_modules/acl.c3
-rw-r--r--source4/dsdb/samdb/ldb_modules/anr.c14
-rw-r--r--source4/dsdb/samdb/ldb_modules/config.mk32
-rw-r--r--source4/dsdb/samdb/ldb_modules/extended_dn_out.c6
-rw-r--r--source4/dsdb/samdb/ldb_modules/extended_dn_store.c6
-rw-r--r--source4/dsdb/samdb/ldb_modules/instancetype.c38
-rw-r--r--source4/dsdb/samdb/ldb_modules/kludge_acl.c2
-rw-r--r--source4/dsdb/samdb/ldb_modules/lazy_commit.c132
-rw-r--r--source4/dsdb/samdb/ldb_modules/local_password.c5
-rw-r--r--source4/dsdb/samdb/ldb_modules/naming_fsmo.c26
-rw-r--r--source4/dsdb/samdb/ldb_modules/objectclass.c101
-rw-r--r--source4/dsdb/samdb/ldb_modules/objectguid.c4
-rw-r--r--source4/dsdb/samdb/ldb_modules/partition.c20
-rw-r--r--source4/dsdb/samdb/ldb_modules/password_hash.c53
-rw-r--r--source4/dsdb/samdb/ldb_modules/pdc_fsmo.c20
-rw-r--r--source4/dsdb/samdb/ldb_modules/repl_meta_data.c100
-rw-r--r--source4/dsdb/samdb/ldb_modules/rootdse.c4
-rw-r--r--source4/dsdb/samdb/ldb_modules/samldb.c21
-rw-r--r--source4/dsdb/samdb/ldb_modules/schema_fsmo.c113
-rw-r--r--source4/dsdb/samdb/ldb_modules/subtree_delete.c2
-rw-r--r--source4/dsdb/samdb/ldb_modules/tests/samba3sam.py26
-rw-r--r--source4/dsdb/samdb/ldb_modules/util.c128
-rw-r--r--source4/dsdb/samdb/ldb_modules/util.h22
23 files changed, 678 insertions, 200 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/acl.c b/source4/dsdb/samdb/ldb_modules/acl.c
index 1b02abcb8e..2f123145db 100644
--- a/source4/dsdb/samdb/ldb_modules/acl.c
+++ b/source4/dsdb/samdb/ldb_modules/acl.c
@@ -802,6 +802,7 @@ static int acl_modify(struct ldb_module *module, struct ldb_request *req)
return LDB_ERR_OPERATIONS_ERROR;
}
+/* TODO Is this really right? */
/* if (what_is_user(module) == SECURITY_SYSTEM) */
return ldb_next_request(module, req);
@@ -813,7 +814,7 @@ static int acl_modify(struct ldb_module *module, struct ldb_request *req)
ac->user_type = what_is_user(module);
ac->sec_result = LDB_SUCCESS;
if (!is_root_base_dn(ldb, req->op.mod.message->dn) && parent && !is_root_base_dn(ldb, parent)){
- filter = talloc_asprintf(req,"(&(objectClass=*)(|(%s=%s)(%s=%s))))",
+ filter = talloc_asprintf(req,"(&(objectClass=*)(|(%s=%s)(%s=%s))))",
ldb_dn_get_component_name(parent,0),
ldb_dn_get_component_val(parent,0)->data,
ldb_dn_get_component_name(req->op.mod.message->dn,0),
diff --git a/source4/dsdb/samdb/ldb_modules/anr.c b/source4/dsdb/samdb/ldb_modules/anr.c
index deeccac072..a5220b3f91 100644
--- a/source4/dsdb/samdb/ldb_modules/anr.c
+++ b/source4/dsdb/samdb/ldb_modules/anr.c
@@ -67,8 +67,10 @@ static struct ldb_parse_tree *make_parse_list(struct ldb_module *module,
* Make an equality or prefix match tree, from the attribute, operation and matching value supplied
*/
static struct ldb_parse_tree *make_match_tree(struct ldb_module *module,
- TALLOC_CTX *mem_ctx, enum ldb_parse_op op,
- const char *attr, const DATA_BLOB *match)
+ TALLOC_CTX *mem_ctx,
+ enum ldb_parse_op op,
+ const char *attr,
+ struct ldb_val *match)
{
struct ldb_context *ldb;
struct ldb_parse_tree *match_tree;
@@ -123,7 +125,7 @@ struct anr_context {
*/
static int anr_replace_value(struct anr_context *ac,
TALLOC_CTX *mem_ctx,
- const struct ldb_val *match,
+ struct ldb_val *match,
struct ldb_parse_tree **ntree)
{
struct ldb_parse_tree *tree = NULL;
@@ -146,7 +148,7 @@ static int anr_replace_value(struct anr_context *ac,
ac->found_anr = true;
if (match->length > 1 && match->data[0] == '=') {
- DATA_BLOB *match2 = talloc(mem_ctx, DATA_BLOB);
+ struct ldb_val *match2 = talloc(mem_ctx, struct ldb_val);
*match2 = data_blob_const(match->data+1, match->length - 1);
if (match2 == NULL){
ldb_oom(ldb);
@@ -181,8 +183,8 @@ static int anr_replace_value(struct anr_context *ac,
if (p) {
struct ldb_parse_tree *first_split_filter, *second_split_filter, *split_filters, *match_tree_1, *match_tree_2;
- DATA_BLOB *first_match = talloc(tree, DATA_BLOB);
- DATA_BLOB *second_match = talloc(tree, DATA_BLOB);
+ struct ldb_val *first_match = talloc(tree, struct ldb_val);
+ struct ldb_val *second_match = talloc(tree, struct ldb_val);
if (!first_match || !second_match) {
ldb_oom(ldb);
return LDB_ERR_OPERATIONS_ERROR;
diff --git a/source4/dsdb/samdb/ldb_modules/config.mk b/source4/dsdb/samdb/ldb_modules/config.mk
index a49b238591..ea4e722822 100644
--- a/source4/dsdb/samdb/ldb_modules/config.mk
+++ b/source4/dsdb/samdb/ldb_modules/config.mk
@@ -1,4 +1,14 @@
################################################
+# Start SUBSYSTEM DSDB_MODULE_HELPERS
+[SUBSYSTEM::DSDB_MODULE_HELPERS]
+PRIVATE_DEPENDENCIES = LIBLDB
+
+DSDB_MODULE_HELPERS_OBJ_FILES = $(dsdbsrcdir)/samdb/ldb_modules/util.o
+
+$(eval $(call proto_header_template,$(dsdbsrcdir)/samdb/ldb_modules/util_proto.h,$(DSDB_MODULE_HELPERS_OBJ_FILES:.o=.c)))
+
+
+################################################
# Start MODULE ldb_objectguid
[MODULE::ldb_objectguid]
SUBSYSTEM = LIBLDB
@@ -15,7 +25,7 @@ ldb_objectguid_OBJ_FILES = $(dsdbsrcdir)/samdb/ldb_modules/objectguid.o
SUBSYSTEM = LIBLDB
PRIVATE_DEPENDENCIES = SAMDB LIBTALLOC LIBEVENTS \
LIBNDR NDR_DRSUAPI \
- NDR_DRSBLOBS LIBNDR
+ NDR_DRSBLOBS LIBNDR DSDB_MODULE_HELPERS
INIT_FUNCTION = LDB_MODULE(repl_meta_data)
# End MODULE ldb_repl_meta_data
################################################
@@ -39,7 +49,7 @@ ldb_dsdb_cache_OBJ_FILES = \
# Start MODULE ldb_schema_fsmo
[MODULE::ldb_schema_fsmo]
SUBSYSTEM = LIBLDB
-PRIVATE_DEPENDENCIES = SAMDB LIBTALLOC LIBEVENTS
+PRIVATE_DEPENDENCIES = SAMDB LIBTALLOC LIBEVENTS DSDB_MODULE_HELPERS
INIT_FUNCTION = LDB_MODULE(schema_fsmo)
# End MODULE ldb_schema_fsmo
################################################
@@ -51,7 +61,7 @@ ldb_schema_fsmo_OBJ_FILES = \
# Start MODULE ldb_naming_fsmo
[MODULE::ldb_naming_fsmo]
SUBSYSTEM = LIBLDB
-PRIVATE_DEPENDENCIES = SAMDB LIBTALLOC LIBEVENTS
+PRIVATE_DEPENDENCIES = SAMDB LIBTALLOC LIBEVENTS DSDB_MODULE_HELPERS
INIT_FUNCTION = LDB_MODULE(naming_fsmo)
# End MODULE ldb_naming_fsmo
################################################
@@ -63,7 +73,7 @@ ldb_naming_fsmo_OBJ_FILES = \
# Start MODULE ldb_pdc_fsmo
[MODULE::ldb_pdc_fsmo]
SUBSYSTEM = LIBLDB
-PRIVATE_DEPENDENCIES = SAMDB LIBTALLOC LIBEVENTS
+PRIVATE_DEPENDENCIES = SAMDB LIBTALLOC LIBEVENTS DSDB_MODULE_HELPERS
INIT_FUNCTION = LDB_MODULE(pdc_fsmo)
# End MODULE ldb_pdc_fsmo
################################################
@@ -220,7 +230,7 @@ ldb_show_deleted_OBJ_FILES = $(dsdbsrcdir)/samdb/ldb_modules/show_deleted.o
# Start MODULE ldb_partition
[MODULE::ldb_partition]
SUBSYSTEM = LIBLDB
-PRIVATE_DEPENDENCIES = LIBTALLOC LIBEVENTS SAMDB
+PRIVATE_DEPENDENCIES = LIBTALLOC LIBEVENTS SAMDB DSDB_MODULE_HELPERS
INIT_FUNCTION = LDB_MODULE(partition)
# End MODULE ldb_partition
################################################
@@ -369,3 +379,15 @@ INIT_FUNCTION = LDB_MODULE(acl)
################################################
ldb_acl_OBJ_FILES = $(dsdbsrcdir)/samdb/ldb_modules/acl.o
+
+################################################
+# Start MODULE ldb_lazy_commit
+[MODULE::ldb_lazy_commit]
+PRIVATE_DEPENDENCIES = SAMDB
+SUBSYSTEM = LIBLDB
+INIT_FUNCTION = LDB_MODULE(lazy_commit)
+
+# End MODULE ldb_lazy_commit
+################################################
+
+ldb_lazy_commit_OBJ_FILES = $(dsdbsrcdir)/samdb/ldb_modules/lazy_commit.o
diff --git a/source4/dsdb/samdb/ldb_modules/extended_dn_out.c b/source4/dsdb/samdb/ldb_modules/extended_dn_out.c
index f93090ace9..bb5e3795db 100644
--- a/source4/dsdb/samdb/ldb_modules/extended_dn_out.c
+++ b/source4/dsdb/samdb/ldb_modules/extended_dn_out.c
@@ -340,7 +340,8 @@ static int extended_callback(struct ldb_request *req, struct ldb_reply *ares)
}
/* Look to see if this attributeSyntax is a DN */
- if (strcmp(attribute->attributeSyntax_oid, "2.5.5.1") != 0) {
+ if (strcmp(attribute->attributeSyntax_oid, "2.5.5.1") != 0 &&
+ strcmp(attribute->attributeSyntax_oid, "2.5.5.7") != 0) {
continue;
}
@@ -617,7 +618,8 @@ static int extended_dn_out_dereference_init(struct ldb_module *module)
NULL
};
- if (strcmp(cur->syntax->attributeSyntax_oid, "2.5.5.1") != 0) {
+ if (strcmp(cur->syntax->attributeSyntax_oid, "2.5.5.1") != 0 &&
+ strcmp(cur->syntax->attributeSyntax_oid, "2.5.5.7") != 0) {
continue;
}
dereference_control->dereference
diff --git a/source4/dsdb/samdb/ldb_modules/extended_dn_store.c b/source4/dsdb/samdb/ldb_modules/extended_dn_store.c
index 3234f6f269..122a9bb2b7 100644
--- a/source4/dsdb/samdb/ldb_modules/extended_dn_store.c
+++ b/source4/dsdb/samdb/ldb_modules/extended_dn_store.c
@@ -303,7 +303,8 @@ static int extended_dn_add(struct ldb_module *module, struct ldb_request *req)
}
/* We only setup an extended DN GUID on these particular DN objects */
- if (strcmp(schema_attr->attributeSyntax_oid, "2.5.5.1") != 0) {
+ if (strcmp(schema_attr->attributeSyntax_oid, "2.5.5.1") != 0 &&
+ strcmp(schema_attr->attributeSyntax_oid, "2.5.5.7") != 0) {
continue;
}
@@ -376,7 +377,8 @@ static int extended_dn_modify(struct ldb_module *module, struct ldb_request *req
}
/* We only setup an extended DN GUID on these particular DN objects */
- if (strcmp(schema_attr->attributeSyntax_oid, "2.5.5.1") != 0) {
+ if (strcmp(schema_attr->attributeSyntax_oid, "2.5.5.1") != 0 &&
+ strcmp(schema_attr->attributeSyntax_oid, "2.5.5.7") != 0) {
continue;
}
diff --git a/source4/dsdb/samdb/ldb_modules/instancetype.c b/source4/dsdb/samdb/ldb_modules/instancetype.c
index de46c0a42a..201ed04412 100644
--- a/source4/dsdb/samdb/ldb_modules/instancetype.c
+++ b/source4/dsdb/samdb/ldb_modules/instancetype.c
@@ -77,8 +77,6 @@ static int instancetype_add(struct ldb_module *module, struct ldb_request *req)
struct it_context *ac;
uint32_t instance_type;
int ret;
- const struct ldb_control *partition_ctrl;
- const struct dsdb_control_current_partition *partition;
ldb = ldb_module_get_ctx(module);
@@ -90,31 +88,19 @@ static int instancetype_add(struct ldb_module *module, struct ldb_request *req)
}
if (ldb_msg_find_element(req->op.add.message, "instanceType")) {
+ unsigned int instanceType = ldb_msg_find_attr_as_uint(req->op.add.message, "instanceType", 0);
+
+ if (instanceType & INSTANCE_TYPE_IS_NC_HEAD) {
+ /* Do something in future */
+ }
+
/* TODO: we need to validate and possibly create a new
partition */
return ldb_next_request(module, req);
}
- partition_ctrl = ldb_request_get_control(req, DSDB_CONTROL_CURRENT_PARTITION_OID);
- if (!partition_ctrl) {
- ldb_debug_set(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);
-
- ac = talloc(req, struct it_context);
- if (ac == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
- ac->module = module;
- ac->req = req;
-
/* we have to copy the message as the caller might have it as a const */
- msg = ldb_msg_copy_shallow(ac, req->op.add.message);
+ msg = ldb_msg_copy_shallow(req, req->op.add.message);
if (msg == NULL) {
ldb_oom(ldb);
return LDB_ERR_OPERATIONS_ERROR;
@@ -124,12 +110,6 @@ static int instancetype_add(struct ldb_module *module, struct ldb_request *req)
* 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(ldb)) != 0) {
- instance_type |= INSTANCE_TYPE_NC_ABOVE;
- }
- }
ret = ldb_msg_add_fmt(msg, "instanceType", "%u", instance_type);
if (ret != LDB_SUCCESS) {
@@ -137,10 +117,10 @@ static int instancetype_add(struct ldb_module *module, struct ldb_request *req)
return LDB_ERR_OPERATIONS_ERROR;
}
- ret = ldb_build_add_req(&down_req, ldb, ac,
+ ret = ldb_build_add_req(&down_req, ldb, req,
msg,
req->controls,
- ac, it_callback,
+ req->context, req->callback,
req);
if (ret != LDB_SUCCESS) {
return ret;
diff --git a/source4/dsdb/samdb/ldb_modules/kludge_acl.c b/source4/dsdb/samdb/ldb_modules/kludge_acl.c
index 34f848de8a..79309e82bf 100644
--- a/source4/dsdb/samdb/ldb_modules/kludge_acl.c
+++ b/source4/dsdb/samdb/ldb_modules/kludge_acl.c
@@ -379,7 +379,7 @@ static int kludge_acl_search(struct ldb_module *module, struct ldb_request *req)
ac, kludge_acl_callback,
req);
if (ret != LDB_SUCCESS) {
- return LDB_ERR_OPERATIONS_ERROR;
+ return ret;
}
/* check if there's an SD_FLAGS control */
diff --git a/source4/dsdb/samdb/ldb_modules/lazy_commit.c b/source4/dsdb/samdb/ldb_modules/lazy_commit.c
new file mode 100644
index 0000000000..69ac99e246
--- /dev/null
+++ b/source4/dsdb/samdb/ldb_modules/lazy_commit.c
@@ -0,0 +1,132 @@
+/*
+ ldb database library
+
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
+
+ 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 <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Name: ldb
+ *
+ * Component: ldb lazy_commit module
+ *
+ * Description: module to pretend to support the 'lazy commit' control
+ *
+ * Author: Andrew Bartlett
+ */
+
+#include "ldb_module.h"
+
+static int unlazy_op(struct ldb_module *module, struct ldb_request *req)
+{
+ int ret;
+ struct ldb_request *new_req;
+ struct ldb_control **saved_controls;
+ struct ldb_control *control = ldb_request_get_control(req, LDB_CONTROL_SERVER_LAZY_COMMIT);
+ if (!control) {
+ return ldb_next_request(module, req);
+ }
+
+ switch (req->operation) {
+ case LDB_SEARCH:
+ ret = ldb_build_search_req_ex(&new_req, ldb_module_get_ctx(module),
+ req,
+ req->op.search.base,
+ req->op.search.scope,
+ req->op.search.tree,
+ req->op.search.attrs,
+ req->controls,
+ req->context, req->callback,
+ req);
+ break;
+ case LDB_ADD:
+ ret = ldb_build_add_req(&new_req, ldb_module_get_ctx(module), req,
+ req->op.add.message,
+ req->controls,
+ req->context, req->callback,
+ req);
+ break;
+ case LDB_MODIFY:
+ ret = ldb_build_mod_req(&new_req, ldb_module_get_ctx(module), req,
+ req->op.mod.message,
+ req->controls,
+ req->context, req->callback,
+ req);
+ break;
+ case LDB_DELETE:
+ ret = ldb_build_del_req(&new_req, ldb_module_get_ctx(module), req,
+ req->op.del.dn,
+ req->controls,
+ req->context, req->callback,
+ req);
+ break;
+ case LDB_RENAME:
+ ret = ldb_build_rename_req(&new_req, ldb_module_get_ctx(module), req,
+ req->op.rename.olddn,
+ req->op.rename.newdn,
+ req->controls,
+ req->context, req->callback,
+ req);
+ break;
+ case LDB_EXTENDED:
+ ret = ldb_build_extended_req(&new_req, ldb_module_get_ctx(module),
+ req,
+ req->op.extended.oid,
+ req->op.extended.data,
+ req->controls,
+ req->context, req->callback,
+ req);
+ break;
+ default:
+ ldb_set_errstring(ldb_module_get_ctx(module),
+ "Unsupported request type!");
+ ret = LDB_ERR_UNWILLING_TO_PERFORM;
+ }
+
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ save_controls(control, req, &saved_controls);
+ return ldb_next_request(module, new_req);
+}
+
+static int unlazy_init(struct ldb_module *module)
+{
+ int ret;
+ struct ldb_context *ldb;
+ ldb = ldb_module_get_ctx(module);
+
+ ret = ldb_mod_register_control(module, LDB_CONTROL_SHOW_DELETED_OID);
+ if (ret != LDB_SUCCESS) {
+ ldb_debug(ldb, LDB_DEBUG_ERROR,
+ "lazy_commit: Unable to register control with rootdse!\n");
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ return ldb_next_init(module);
+}
+
+const struct ldb_module_ops ldb_lazy_commit_module_ops = {
+ .name = "lazy_commit",
+ .search = unlazy_op,
+ .add = unlazy_op,
+ .modify = unlazy_op,
+ .del = unlazy_op,
+ .rename = unlazy_op,
+ .request = unlazy_op,
+ .extended = unlazy_op,
+ .init_context = unlazy_init,
+};
diff --git a/source4/dsdb/samdb/ldb_modules/local_password.c b/source4/dsdb/samdb/ldb_modules/local_password.c
index 58c0f1f0d5..9c386b354d 100644
--- a/source4/dsdb/samdb/ldb_modules/local_password.c
+++ b/source4/dsdb/samdb/ldb_modules/local_password.c
@@ -633,8 +633,7 @@ static int lpdb_delete_callabck(struct ldb_request *req,
ret = ldb_next_request(ac->module, search_req);
if (ret != LDB_SUCCESS) {
- return ldb_module_done(ac->req, NULL, NULL,
- LDB_ERR_OPERATIONS_ERROR);
+ return ldb_module_done(ac->req, NULL, NULL, ret);
}
return LDB_SUCCESS;
}
@@ -1082,7 +1081,7 @@ static int local_password_search(struct ldb_module *module, struct ldb_request *
ac, lpdb_remote_search_callback,
req);
if (ret != LDB_SUCCESS) {
- return LDB_ERR_OPERATIONS_ERROR;
+ return ret;
}
/* perform the search */
diff --git a/source4/dsdb/samdb/ldb_modules/naming_fsmo.c b/source4/dsdb/samdb/ldb_modules/naming_fsmo.c
index 607bf054d2..15cad259ce 100644
--- a/source4/dsdb/samdb/ldb_modules/naming_fsmo.c
+++ b/source4/dsdb/samdb/ldb_modules/naming_fsmo.c
@@ -28,6 +28,7 @@
#include "librpc/gen_ndr/ndr_drsuapi.h"
#include "librpc/gen_ndr/ndr_drsblobs.h"
#include "../lib/util/dlinklist.h"
+#include "dsdb/samdb/ldb_modules/util.h"
static int naming_fsmo_init(struct ldb_module *module)
{
@@ -65,34 +66,15 @@ static int naming_fsmo_init(struct ldb_module *module)
}
ldb_module_set_private(module, naming_fsmo);
- ret = ldb_search(ldb, mem_ctx, &naming_res,
- naming_dn, LDB_SCOPE_BASE,
- naming_attrs, NULL);
+ ret = dsdb_module_search_dn(module, mem_ctx, &naming_res,
+ naming_dn,
+ naming_attrs);
if (ret == LDB_ERR_NO_SUCH_OBJECT) {
ldb_debug(ldb, LDB_DEBUG_WARNING,
"naming_fsmo_init: no partitions dn present: (skip loading of naming contexts details)\n");
talloc_free(mem_ctx);
return ldb_next_init(module);
}
- if (ret != LDB_SUCCESS) {
- ldb_debug_set(ldb, LDB_DEBUG_FATAL,
- "naming_fsmo_init: failed to search the cross-ref container: %s: %s",
- ldb_strerror(ret), ldb_errstring(ldb));
- talloc_free(mem_ctx);
- return ret;
- }
- if (naming_res->count == 0) {
- ldb_debug(ldb, LDB_DEBUG_WARNING,
- "naming_fsmo_init: no cross-ref container present: (skip loading of naming contexts details)\n");
- talloc_free(mem_ctx);
- return ldb_next_init(module);
- } else if (naming_res->count > 1) {
- ldb_debug_set(ldb, LDB_DEBUG_FATAL,
- "naming_fsmo_init: [%u] cross-ref containers found on a base search",
- naming_res->count);
- talloc_free(mem_ctx);
- return LDB_ERR_CONSTRAINT_VIOLATION;
- }
naming_fsmo->master_dn = ldb_msg_find_attr_as_dn(ldb, naming_fsmo, naming_res->msgs[0], "fSMORoleOwner");
if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), naming_fsmo->master_dn) == 0) {
diff --git a/source4/dsdb/samdb/ldb_modules/objectclass.c b/source4/dsdb/samdb/ldb_modules/objectclass.c
index 3cf252c71a..003d6731d4 100644
--- a/source4/dsdb/samdb/ldb_modules/objectclass.c
+++ b/source4/dsdb/samdb/ldb_modules/objectclass.c
@@ -2,7 +2,7 @@
ldb database library
Copyright (C) Simo Sorce 2006-2008
- Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2007
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2009
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
@@ -42,6 +42,7 @@
#include "libcli/security/security.h"
#include "auth/auth.h"
#include "param/param.h"
+#include "../libds/common/flags.h"
struct oc_context {
@@ -138,7 +139,13 @@ static int objectclass_sort(struct ldb_module *module,
if (!current->objectclass) {
ldb_asprintf_errstring(ldb, "objectclass %.*s is not a valid objectClass in schema",
(int)objectclass_element->values[i].length, (const char *)objectclass_element->values[i].data);
- return LDB_ERR_OBJECT_CLASS_VIOLATION;
+ /* This looks weird, but windows apparently returns this for invalid objectClass values */
+ return LDB_ERR_NO_SUCH_ATTRIBUTE;
+ } else if (current->objectclass->isDefunct) {
+ ldb_asprintf_errstring(ldb, "objectclass %.*s marked as isDefunct objectClass in schema - not valid for new objects",
+ (int)objectclass_element->values[i].length, (const char *)objectclass_element->values[i].data);
+ /* This looks weird, but windows apparently returns this for invalid objectClass values */
+ return LDB_ERR_NO_SUCH_ATTRIBUTE;
}
/* this is the root of the tree. We will start
@@ -323,6 +330,8 @@ static int fix_dn(TALLOC_CTX *mem_ctx,
struct ldb_dn **fixed_dn)
{
char *upper_rdn_attr;
+ const struct ldb_val *rdn_val;
+
/* Fix up the DN to be in the standard form, taking particular care to match the parent DN */
*fixed_dn = ldb_dn_copy(mem_ctx, parent_dn);
@@ -332,15 +341,21 @@ static int fix_dn(TALLOC_CTX *mem_ctx,
if (!upper_rdn_attr) {
return LDB_ERR_OPERATIONS_ERROR;
}
-
+
/* Create a new child */
if (ldb_dn_add_child_fmt(*fixed_dn, "X=X") == false) {
return LDB_ERR_OPERATIONS_ERROR;
}
+ /* AD doesn't allow the rDN to be longer than 64 characters */
+ rdn_val = ldb_dn_get_rdn_val(newdn);
+ if (!rdn_val || rdn_val->length > 64) {
+ DEBUG(2,(__location__ ": rDN longer than 64 limit for '%s'\n", ldb_dn_get_linearized(newdn)));
+ return LDB_ERR_CONSTRAINT_VIOLATION;
+ }
+
/* And replace it with CN=foo (we need the attribute in upper case */
- return ldb_dn_set_component(*fixed_dn, 0, upper_rdn_attr,
- *ldb_dn_get_rdn_val(newdn));
+ return ldb_dn_set_component(*fixed_dn, 0, upper_rdn_attr, *rdn_val);
}
/* Fix all attribute names to be in the correct case, and check they are all valid per the schema */
@@ -355,7 +370,8 @@ static int fix_attributes(struct ldb_context *ldb, const struct dsdb_schema *sch
if (!attribute) {
if (strcasecmp(msg->elements[i].name, "clearTextPassword") != 0) {
ldb_asprintf_errstring(ldb, "attribute %s is not a valid attribute in schema", msg->elements[i].name);
- return LDB_ERR_UNDEFINED_ATTRIBUTE_TYPE;
+ /* Apparently Windows sends exactly this behaviour */
+ return LDB_ERR_NO_SUCH_ATTRIBUTE;
}
} else {
msg->elements[i].name = attribute->lDAPDisplayName;
@@ -374,7 +390,7 @@ static int objectclass_add(struct ldb_module *module, struct ldb_request *req)
struct oc_context *ac;
struct ldb_dn *parent_dn;
int ret;
- static const char * const parent_attrs[] = { "objectGUID", NULL };
+ static const char * const parent_attrs[] = { "objectGUID", "objectClass", NULL };
ldb = ldb_module_get_ctx(module);
@@ -458,7 +474,7 @@ static int objectclass_do_add(struct oc_context *ac)
ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, parent does not exist!",
ldb_dn_get_linearized(msg->dn));
talloc_free(mem_ctx);
- return LDB_ERR_UNWILLING_TO_PERFORM;
+ return LDB_ERR_NO_SUCH_OBJECT;
}
} else {
const struct ldb_val *parent_guid;
@@ -484,9 +500,6 @@ static int objectclass_do_add(struct oc_context *ac)
return LDB_ERR_UNWILLING_TO_PERFORM;
}
- /* TODO: Check this is a valid child to this parent,
- * by reading the allowedChildClasses and
- * allowedChildClasssesEffective attributes */
ret = ldb_msg_add_steal_value(msg, "parentGUID", discard_const(parent_guid));
if (ret != LDB_SUCCESS) {
ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, failed to add parentGUID",
@@ -547,7 +560,59 @@ static int objectclass_do_add(struct oc_context *ac)
if (!current->next) {
struct ldb_message_element *el;
int32_t systemFlags = 0;
- DATA_BLOB *sd;
+ const char *rdn_name = ldb_dn_get_rdn_name(msg->dn);
+ if (current->objectclass->rDNAttID
+ && ldb_attr_cmp(rdn_name, current->objectclass->rDNAttID) != 0) {
+ ldb_asprintf_errstring(ldb,
+ "RDN %s is not correct for most specific structural objectclass %s, should be %s",
+ rdn_name, current->objectclass->lDAPDisplayName, current->objectclass->rDNAttID);
+ return LDB_ERR_NAMING_VIOLATION;
+ }
+
+ if (ac->search_res && ac->search_res->message) {
+ struct ldb_message_element *oc_el
+ = ldb_msg_find_element(ac->search_res->message, "objectClass");
+
+ bool allowed_class = false;
+ int i, j;
+ for (i=0; allowed_class == false && oc_el && i < oc_el->num_values; i++) {
+ const struct dsdb_class *sclass;
+
+ sclass = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &oc_el->values[i]);
+ if (!sclass) {
+ /* We don't know this class? what is going on? */
+ continue;
+ }
+ if (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
+ for (j=0; sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
+ if (ldb_attr_cmp(current->objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) == 0) {
+ allowed_class = true;
+ break;
+ }
+ }
+ } else {
+ for (j=0; sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
+ if (ldb_attr_cmp(current->objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) == 0) {
+ allowed_class = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (!allowed_class) {
+ ldb_asprintf_errstring(ldb, "structural objectClass %s is not a valid child class for %s",
+ current->objectclass->lDAPDisplayName, ldb_dn_get_linearized(ac->search_res->message->dn));
+ return LDB_ERR_NAMING_VIOLATION;
+ }
+ }
+
+ if (current->objectclass->systemOnly && !ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
+ ldb_asprintf_errstring(ldb, "objectClass %s is systemOnly, rejecting creation of %s",
+ current->objectclass->lDAPDisplayName, ldb_dn_get_linearized(msg->dn));
+ return LDB_ERR_UNWILLING_TO_PERFORM;
+ }
+
if (!ldb_msg_find_element(msg, "objectCategory")) {
value = talloc_strdup(msg, current->objectclass->defaultObjectCategory);
if (value == NULL) {
@@ -649,7 +714,13 @@ static int objectclass_modify(struct ldb_module *module, struct ldb_request *req
if (!schema) {
return ldb_next_request(module, req);
}
- objectclass_element = ldb_msg_find_element(req->op.mod.message, "objectClass");
+
+ /* As with the "real" AD we don't accept empty messages */
+ if (req->op.mod.message->num_elements == 0) {
+ ldb_set_errstring(ldb, "objectclass: modify message must have "
+ "elements/attributes!");
+ return LDB_ERR_UNWILLING_TO_PERFORM;
+ }
ac = oc_init_context(module, req);
if (ac == NULL) {
@@ -658,6 +729,7 @@ static int objectclass_modify(struct ldb_module *module, struct ldb_request *req
/* If no part of this touches the objectClass, then we don't
* need to make any changes. */
+ objectclass_element = ldb_msg_find_element(req->op.mod.message, "objectClass");
/* If the only operation is the deletion of the objectClass
* then go on with just fixing the attribute case */
@@ -824,6 +896,8 @@ static int oc_modify_callback(struct ldb_request *req, struct ldb_reply *ares)
LDB_ERR_OPERATIONS_ERROR);
}
+ talloc_free(ares);
+
ret = ldb_build_search_req(&search_req, ldb, ac,
ac->req->op.mod.message->dn, LDB_SCOPE_BASE,
"(objectClass=*)",
@@ -1032,6 +1106,7 @@ static int objectclass_rename_callback(struct ldb_request *req, struct ldb_reply
ares->response, ares->error);
}
+ talloc_free(ares);
/* the ac->search_res should contain the new parents objectGUID */
parent_guid = ldb_msg_find_ldb_val(ac->search_res->message, "objectGUID");
diff --git a/source4/dsdb/samdb/ldb_modules/objectguid.c b/source4/dsdb/samdb/ldb_modules/objectguid.c
index 3d218edc76..12dd402617 100644
--- a/source4/dsdb/samdb/ldb_modules/objectguid.c
+++ b/source4/dsdb/samdb/ldb_modules/objectguid.c
@@ -209,7 +209,7 @@ static int objectguid_add(struct ldb_module *module, struct ldb_request *req)
ac, og_op_callback,
req);
if (ret != LDB_SUCCESS) {
- return LDB_ERR_OPERATIONS_ERROR;
+ return ret;
}
/* go on with the call chain */
@@ -267,7 +267,7 @@ static int objectguid_modify(struct ldb_module *module, struct ldb_request *req)
ac, og_op_callback,
req);
if (ret != LDB_SUCCESS) {
- return LDB_ERR_OPERATIONS_ERROR;
+ return ret;
}
/* go on with the call chain */
diff --git a/source4/dsdb/samdb/ldb_modules/partition.c b/source4/dsdb/samdb/ldb_modules/partition.c
index 6e86d4c484..c5bbdf8dce 100644
--- a/source4/dsdb/samdb/ldb_modules/partition.c
+++ b/source4/dsdb/samdb/ldb_modules/partition.c
@@ -829,14 +829,22 @@ static int partition_sequence_number(struct ldb_module *module, struct ldb_reque
res,
ldb_extended_default_callback,
NULL);
- ret = ldb_next_request(module, treq);
- if (ret == LDB_SUCCESS) {
- ret = ldb_wait(treq->handle, LDB_WAIT_ALL);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(res);
+ return ret;
}
+
+ ret = ldb_next_request(module, treq);
if (ret != LDB_SUCCESS) {
talloc_free(res);
return ret;
}
+ ret = ldb_wait(treq->handle, LDB_WAIT_ALL);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(res);
+ return ret;
+ }
+
seqr = talloc_get_type(res->extended->data,
struct ldb_seqnum_result);
if (seqr->flags & LDB_SEQ_TIMESTAMP_SEQUENCE) {
@@ -1083,7 +1091,7 @@ static int partition_extended_schema_update_now(struct ldb_module *module, struc
}
/* fire the first one */
- ret = partition_call_first(ac);
+ ret = partition_call_first(ac);
if (ret != LDB_SUCCESS){
return ret;
@@ -1385,14 +1393,14 @@ static int partition_init(struct ldb_module *module)
if (ret != LDB_SUCCESS) {
ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_ERROR,
"partition: Unable to register control with rootdse!\n");
- return LDB_ERR_OPERATIONS_ERROR;
+ return ret;
}
ret = ldb_mod_register_control(module, LDB_CONTROL_SEARCH_OPTIONS_OID);
if (ret != LDB_SUCCESS) {
ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_ERROR,
"partition: Unable to register control with rootdse!\n");
- return LDB_ERR_OPERATIONS_ERROR;
+ return ret;
}
talloc_free(mem_ctx);
diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c
index fdb044198b..a3c99f4222 100644
--- a/source4/dsdb/samdb/ldb_modules/password_hash.c
+++ b/source4/dsdb/samdb/ldb_modules/password_hash.c
@@ -87,9 +87,9 @@ struct domain_data {
bool store_cleartext;
uint_t pwdProperties;
uint_t pwdHistoryLength;
- char *netbios_domain;
- char *dns_domain;
- char *realm;
+ const char *netbios_domain;
+ const char *dns_domain;
+ const char *realm;
};
struct setup_password_fields_io {
@@ -1552,9 +1552,8 @@ static int get_domain_data_callback(struct ldb_request *req,
struct ldb_context *ldb;
struct domain_data *data;
struct ph_context *ac;
+ struct loadparm_context *lp_ctx;
int ret;
- char *tmp;
- char *p;
ac = talloc_get_type(req->context, struct ph_context);
ldb = ldb_module_get_ctx(ac->module);
@@ -1591,43 +1590,13 @@ static int get_domain_data_callback(struct ldb_request *req,
* but that doesn't really matter, as it's just used for salt
* and kerberos principals, which don't exist here */
- tmp = ldb_dn_canonical_string(data, ares->message->dn);
- if (!tmp) {
- return ldb_module_done(ac->req, NULL, NULL,
- LDB_ERR_OPERATIONS_ERROR);
- }
+ lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
+ struct loadparm_context);
- /* But it puts a trailing (or just before 'builtin') / on things, so kill that */
- p = strchr(tmp, '/');
- if (p) {
- p[0] = '\0';
- }
-
- data->dns_domain = strlower_talloc(data, tmp);
- if (data->dns_domain == NULL) {
- ldb_oom(ldb);
- return ldb_module_done(ac->req, NULL, NULL,
- LDB_ERR_OPERATIONS_ERROR);
- }
- data->realm = strupper_talloc(data, tmp);
- if (data->realm == NULL) {
- ldb_oom(ldb);
- return ldb_module_done(ac->req, NULL, NULL,
- LDB_ERR_OPERATIONS_ERROR);
- }
- /* FIXME: NetbIOS name is *always* the first domain component ?? -SSS */
- p = strchr(tmp, '.');
- if (p) {
- p[0] = '\0';
- }
- data->netbios_domain = strupper_talloc(data, tmp);
- if (data->netbios_domain == NULL) {
- ldb_oom(ldb);
- return ldb_module_done(ac->req, NULL, NULL,
- LDB_ERR_OPERATIONS_ERROR);
- }
+ data->dns_domain = lp_dnsdomain(lp_ctx);
+ data->realm = lp_realm(lp_ctx);
+ data->netbios_domain = lp_workgroup(lp_ctx);
- talloc_free(tmp);
ac->domain = data;
break;
@@ -1673,7 +1642,7 @@ static int build_domain_data_request(struct ph_context *ac)
ldb = ldb_module_get_ctx(ac->module);
filter = talloc_asprintf(ac,
- "(&(objectSid=%s)(|(|(objectClass=domain)(objectClass=builtinDomain))(objectClass=samba4LocalDomain)))",
+ "(objectSid=%s)",
ldap_encode_ndr_dom_sid(ac, ac->domain_sid));
if (filter == NULL) {
ldb_oom(ldb);
@@ -1682,7 +1651,7 @@ static int build_domain_data_request(struct ph_context *ac)
return ldb_build_search_req(&ac->dom_req, ldb, ac,
ldb_get_default_basedn(ldb),
- LDB_SCOPE_SUBTREE,
+ LDB_SCOPE_BASE,
filter, attrs,
NULL,
ac, get_domain_data_callback,
diff --git a/source4/dsdb/samdb/ldb_modules/pdc_fsmo.c b/source4/dsdb/samdb/ldb_modules/pdc_fsmo.c
index 950f87eb74..6d814f9334 100644
--- a/source4/dsdb/samdb/ldb_modules/pdc_fsmo.c
+++ b/source4/dsdb/samdb/ldb_modules/pdc_fsmo.c
@@ -27,6 +27,7 @@
#include "librpc/gen_ndr/ndr_drsuapi.h"
#include "librpc/gen_ndr/ndr_drsblobs.h"
#include "../lib/util/dlinklist.h"
+#include "dsdb/samdb/ldb_modules/util.h"
static int pdc_fsmo_init(struct ldb_module *module)
{
@@ -64,9 +65,9 @@ static int pdc_fsmo_init(struct ldb_module *module)
}
ldb_module_set_private(module, pdc_fsmo);
- ret = ldb_search(ldb, mem_ctx, &pdc_res,
- pdc_dn, LDB_SCOPE_BASE,
- pdc_attrs, NULL);
+ ret = dsdb_module_search_dn(module, mem_ctx, &pdc_res,
+ pdc_dn,
+ pdc_attrs);
if (ret == LDB_ERR_NO_SUCH_OBJECT) {
ldb_debug(ldb, LDB_DEBUG_WARNING,
"pdc_fsmo_init: no domain object present: (skip loading of domain details)\n");
@@ -79,19 +80,6 @@ static int pdc_fsmo_init(struct ldb_module *module)
talloc_free(mem_ctx);
return ret;
}
- if (pdc_res->count == 0) {
- ldb_debug(ldb, LDB_DEBUG_WARNING,
- "pdc_fsmo_init: no domain object present: (skip loading of domain details)\n");
- talloc_free(mem_ctx);
- return ldb_next_init(module);
- } else if (pdc_res->count > 1) {
- ldb_debug_set(ldb, LDB_DEBUG_FATAL,
- "pdc_fsmo_init: [%u] domain objects found on a base search",
- pdc_res->count);
- DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
- talloc_free(mem_ctx);
- return LDB_ERR_CONSTRAINT_VIOLATION;
- }
pdc_fsmo->master_dn = ldb_msg_find_attr_as_dn(ldb, mem_ctx, pdc_res->msgs[0], "fSMORoleOwner");
if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), pdc_fsmo->master_dn) == 0) {
diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
index 253596ddea..74dd7e5bbb 100644
--- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
+++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
@@ -457,11 +457,14 @@ static int replmd_op_callback(struct ldb_request *req, struct ldb_reply *ares)
static int replmd_add(struct ldb_module *module, struct ldb_request *req)
{
struct ldb_context *ldb;
+ struct ldb_control *control;
+ struct ldb_control **saved_controls;
struct replmd_replicated_request *ac;
const struct dsdb_schema *schema;
enum ndr_err_code ndr_err;
struct ldb_request *down_req;
struct ldb_message *msg;
+ const DATA_BLOB *guid_blob;
struct GUID guid;
struct ldb_val guid_value;
struct replPropertyMetaDataBlob nmd;
@@ -473,6 +476,14 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req)
char *time_str;
int ret;
uint32_t i, ni=0;
+ bool allow_add_guid = false;
+ bool remove_current_guid = false;
+
+ /* check if there's a show relax control (used by provision to say 'I know what I'm doing') */
+ control = ldb_request_get_control(req, LDB_CONTROL_RELAX_OID);
+ if (control) {
+ allow_add_guid = 1;
+ }
/* do not manipulate our control entries */
if (ldb_dn_is_special(req->op.add.message->dn)) {
@@ -498,26 +509,43 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req)
ac->schema = schema;
- if (ldb_msg_find_element(req->op.add.message, "objectGUID") != NULL) {
- ldb_debug_set(ldb, LDB_DEBUG_ERROR,
+ guid_blob = ldb_msg_find_ldb_val(req->op.add.message, "objectGUID");
+ if ( guid_blob != NULL ) {
+ if( !allow_add_guid ) {
+ ldb_debug_set(ldb, LDB_DEBUG_ERROR,
"replmd_add: it's not allowed to add an object with objectGUID\n");
- return LDB_ERR_UNWILLING_TO_PERFORM;
+ talloc_free(ac);
+ return LDB_ERR_UNWILLING_TO_PERFORM;
+ } else {
+ NTSTATUS status = GUID_from_data_blob(guid_blob,&guid);
+ if ( !NT_STATUS_IS_OK(status)) {
+ ldb_debug_set(ldb, LDB_DEBUG_ERROR,
+ "replmd_add: Unable to parse as a GUID the attribute objectGUID\n");
+ talloc_free(ac);
+ return LDB_ERR_UNWILLING_TO_PERFORM;
+ }
+ /* we remove this attribute as it can be a string and will not be treated
+ correctly and then we will readd it latter on in the good format*/
+ remove_current_guid = true;
+ }
+ } else {
+ /* a new GUID */
+ guid = GUID_random();
}
/* Get a sequence number from the backend */
ret = ldb_sequence_number(ldb, LDB_SEQ_NEXT, &seq_num);
if (ret != LDB_SUCCESS) {
+ talloc_free(ac);
return ret;
}
- /* a new GUID */
- guid = GUID_random();
-
/* get our invocationId */
our_invocation_id = samdb_ntds_invocation_id(ldb);
if (!our_invocation_id) {
ldb_debug_set(ldb, LDB_DEBUG_ERROR,
"replmd_add: unable to find invocationId\n");
+ talloc_free(ac);
return LDB_ERR_OPERATIONS_ERROR;
}
@@ -525,6 +553,7 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req)
msg = ldb_msg_copy_shallow(ac, req->op.add.message);
if (msg == NULL) {
ldb_oom(ldb);
+ talloc_free(ac);
return LDB_ERR_OPERATIONS_ERROR;
}
@@ -532,8 +561,13 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req)
unix_to_nt_time(&now, t);
time_str = ldb_timestring(msg, t);
if (!time_str) {
+ ldb_oom(ldb);
+ talloc_free(ac);
return LDB_ERR_OPERATIONS_ERROR;
}
+ if (remove_current_guid) {
+ ldb_msg_remove_attr(msg,"objectGUID");
+ }
/*
* remove autogenerated attributes
@@ -548,7 +582,8 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req)
ret = ldb_msg_add_fmt(msg, "instanceType", "%u", INSTANCE_TYPE_WRITE);
if (ret != LDB_SUCCESS) {
ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
+ talloc_free(ac);
+ return ret;
}
}
@@ -558,7 +593,8 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req)
ret = ldb_msg_add_string(msg, "whenCreated", time_str);
if (ret != LDB_SUCCESS) {
ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
+ talloc_free(ac);
+ return ret;
}
/* build the replication meta_data */
@@ -570,6 +606,7 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req)
nmd.ctr.ctr1.count);
if (!nmd.ctr.ctr1.array) {
ldb_oom(ldb);
+ talloc_free(ac);
return LDB_ERR_OPERATIONS_ERROR;
}
@@ -585,6 +622,7 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req)
ldb_debug_set(ldb, LDB_DEBUG_ERROR,
"replmd_add: attribute '%s' not defined in schema\n",
e->name);
+ talloc_free(ac);
return LDB_ERR_NO_SUCH_ATTRIBUTE;
}
@@ -612,6 +650,7 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req)
*/
ret = replmd_replPropertyMetaDataCtr1_sort(&nmd.ctr.ctr1, schema, msg->dn);
if (ret != LDB_SUCCESS) {
+ talloc_free(ac);
return ret;
}
@@ -622,6 +661,7 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req)
(ndr_push_flags_fn_t)ndr_push_GUID);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
ldb_oom(ldb);
+ talloc_free(ac);
return LDB_ERR_OPERATIONS_ERROR;
}
ndr_err = ndr_push_struct_blob(&nmd_value, msg,
@@ -630,6 +670,7 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req)
(ndr_push_flags_fn_t)ndr_push_replPropertyMetaDataBlob);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
ldb_oom(ldb);
+ talloc_free(ac);
return LDB_ERR_OPERATIONS_ERROR;
}
@@ -639,27 +680,32 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req)
ret = ldb_msg_add_value(msg, "objectGUID", &guid_value, NULL);
if (ret != LDB_SUCCESS) {
ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
+ talloc_free(ac);
+ return ret;
}
ret = ldb_msg_add_string(msg, "whenChanged", time_str);
if (ret != LDB_SUCCESS) {
ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
+ talloc_free(ac);
+ return ret;
}
ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNCreated", seq_num);
if (ret != LDB_SUCCESS) {
ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
+ talloc_free(ac);
+ return ret;
}
ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNChanged", seq_num);
if (ret != LDB_SUCCESS) {
ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
+ talloc_free(ac);
+ return ret;
}
ret = ldb_msg_add_value(msg, "replPropertyMetaData", &nmd_value, NULL);
if (ret != LDB_SUCCESS) {
ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
+ talloc_free(ac);
+ return ret;
}
/*
@@ -673,14 +719,22 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req)
ac, replmd_op_callback,
req);
if (ret != LDB_SUCCESS) {
+ talloc_free(ac);
return ret;
}
ret = replmd_notify(module, msg->dn, seq_num);
if (ret != LDB_SUCCESS) {
+ talloc_free(ac);
return ret;
}
+ /* if a control is there remove if from the modified request */
+ if (control && !save_controls(control, down_req, &saved_controls)) {
+ talloc_free(ac);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
/* go on with the call chain */
return ldb_next_request(module, down_req);
}
@@ -785,7 +839,7 @@ static int replmd_update_rpmd(struct ldb_module *module,
/* search for the existing replPropertyMetaDataBlob */
ret = dsdb_search_dn_with_deleted(ldb, msg, &res, msg->dn, attrs);
- if (ret != LDB_SUCCESS || res->count < 1) {
+ if (ret != LDB_SUCCESS || res->count != 1) {
DEBUG(0,(__location__ ": Object %s failed to find replPropertyMetaData\n",
ldb_dn_get_linearized(msg->dn)));
return LDB_ERR_OPERATIONS_ERROR;
@@ -880,9 +934,10 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req)
const struct dsdb_schema *schema;
struct ldb_request *down_req;
struct ldb_message *msg;
- int ret;
+ struct ldb_result *res;
time_t t = time(NULL);
uint64_t seq_num = 0;
+ int ret;
/* do not manipulate our control entries */
if (ldb_dn_is_special(req->op.mod.message->dn)) {
@@ -911,13 +966,12 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req)
/* we have to copy the message as the caller might have it as a const */
msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
if (msg == NULL) {
+ ldb_oom(ldb);
talloc_free(ac);
return LDB_ERR_OPERATIONS_ERROR;
}
/* TODO:
- * - get the whole old object
- * - if the old object doesn't exist report an error
* - give an error when a readonly attribute should
* be modified
* - merge the changed into the old object
@@ -926,8 +980,15 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req)
* attribute was changed
*/
+ ret = dsdb_search_dn_with_deleted(ldb, msg, &res, msg->dn, NULL);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(ac);
+ return ret;
+ }
+
ret = replmd_update_rpmd(module, msg, &seq_num);
if (ret != LDB_SUCCESS) {
+ talloc_free(ac);
return ret;
}
@@ -941,6 +1002,7 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req)
ac, replmd_op_callback,
req);
if (ret != LDB_SUCCESS) {
+ talloc_free(ac);
return ret;
}
talloc_steal(down_req, msg);
@@ -950,12 +1012,12 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req)
if (seq_num != 0) {
if (add_time_element(msg, "whenChanged", t) != LDB_SUCCESS) {
talloc_free(ac);
- return LDB_ERR_OPERATIONS_ERROR;
+ return ret;
}
if (add_uint64_element(msg, "uSNChanged", seq_num) != LDB_SUCCESS) {
talloc_free(ac);
- return LDB_ERR_OPERATIONS_ERROR;
+ return ret;
}
}
diff --git a/source4/dsdb/samdb/ldb_modules/rootdse.c b/source4/dsdb/samdb/ldb_modules/rootdse.c
index a8e08ec3ad..83e4e3b50e 100644
--- a/source4/dsdb/samdb/ldb_modules/rootdse.c
+++ b/source4/dsdb/samdb/ldb_modules/rootdse.c
@@ -722,9 +722,9 @@ static int rootdse_modify(struct ldb_module *module, struct ldb_request *req)
}
_PUBLIC_ const struct ldb_module_ops ldb_rootdse_module_ops = {
- .name = "rootdse",
+ .name = "rootdse",
.init_context = rootdse_init,
.search = rootdse_search,
- .request = rootdse_request,
+ .request = rootdse_request,
.modify = rootdse_modify
};
diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c
index e59b5dd1ce..2a0bb2dfe6 100644
--- a/source4/dsdb/samdb/ldb_modules/samldb.c
+++ b/source4/dsdb/samdb/ldb_modules/samldb.c
@@ -284,8 +284,7 @@ static int samldb_get_parent_domain(struct samldb_ctx *ac)
ret = ldb_build_search_req(&req, ldb, ac,
dn, LDB_SCOPE_BASE,
"(|(objectClass=domain)"
- "(objectClass=builtinDomain)"
- "(objectClass=samba4LocalDomain))",
+ "(objectClass=builtinDomain))",
attrs,
NULL,
ac, samldb_get_parent_domain_callback,
@@ -559,10 +558,10 @@ static int samldb_get_sid_domain(struct samldb_ctx *ac)
/* get the domain component part of the provided SID */
ac->domain_sid->num_auths--;
- filter = talloc_asprintf(ac, "(&(objectSid=%s)"
- "(|(objectClass=domain)"
- "(objectClass=builtinDomain)"
- "(objectClass=samba4LocalDomain)))",
+ filter = talloc_asprintf(ac,
+ "(&(objectSid=%s)"
+ "(|(objectClass=domain)"
+ "(objectClass=builtinDomain)))",
ldap_encode_ndr_dom_sid(ac, ac->domain_sid));
if (filter == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
@@ -699,8 +698,14 @@ static int samldb_check_primaryGroupID_1(struct samldb_ctx *ac)
static int samldb_check_primaryGroupID_2(struct samldb_ctx *ac)
{
- if (ac->res_dn == NULL)
+ if (ac->res_dn == NULL) {
+ struct ldb_context *ldb;
+ ldb = ldb_module_get_ctx(ac->module);
+ ldb_asprintf_errstring(ldb,
+ "Failed to find group sid %s",
+ dom_sid_string(ac->sid, ac->sid));
return LDB_ERR_UNWILLING_TO_PERFORM;
+ }
return samldb_next_step(ac);
}
@@ -1866,7 +1871,7 @@ static int samldb_add(struct ldb_module *module, struct ldb_request *req)
int ret;
ldb = ldb_module_get_ctx(module);
- ldb_debug(ldb, LDB_DEBUG_TRACE, "samldb_add_record\n");
+ ldb_debug(ldb, LDB_DEBUG_TRACE, "samldb_add\n");
/* do not manipulate our control entries */
if (ldb_dn_is_special(req->op.add.message->dn)) {
diff --git a/source4/dsdb/samdb/ldb_modules/schema_fsmo.c b/source4/dsdb/samdb/ldb_modules/schema_fsmo.c
index c482ab57df..2b6606c147 100644
--- a/source4/dsdb/samdb/ldb_modules/schema_fsmo.c
+++ b/source4/dsdb/samdb/ldb_modules/schema_fsmo.c
@@ -5,6 +5,7 @@
checkings, it also loads the dsdb_schema.
Copyright (C) Stefan Metzmacher <metze@samba.org> 2007
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
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
@@ -28,6 +29,7 @@
#include "librpc/gen_ndr/ndr_drsuapi.h"
#include "librpc/gen_ndr/ndr_drsblobs.h"
#include "param/param.h"
+#include "dsdb/samdb/ldb_modules/util.h"
static int generate_objectClasses(struct ldb_context *ldb, struct ldb_message *msg,
const struct dsdb_schema *schema);
@@ -90,13 +92,107 @@ struct schema_fsmo_search_data {
const struct dsdb_schema *schema;
};
+/*
+ Given an LDB module (pointing at the schema DB), and the DN, set the populated schema
+*/
+
+static int dsdb_schema_from_schema_dn(TALLOC_CTX *mem_ctx, struct ldb_module *module,
+ struct smb_iconv_convenience *iconv_convenience,
+ struct ldb_dn *schema_dn,
+ struct dsdb_schema **schema)
+{
+ TALLOC_CTX *tmp_ctx;
+ char *error_string;
+ int ret;
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
+ struct ldb_result *schema_res;
+ struct ldb_result *a_res;
+ struct ldb_result *c_res;
+ static const char *schema_attrs[] = {
+ "prefixMap",
+ "schemaInfo",
+ "fSMORoleOwner",
+ NULL
+ };
+ unsigned flags;
+
+ tmp_ctx = talloc_new(mem_ctx);
+ if (!tmp_ctx) {
+ ldb_oom(ldb);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ /* we don't want to trace the schema load */
+ flags = ldb_get_flags(ldb);
+ ldb_set_flags(ldb, flags & ~LDB_FLG_ENABLE_TRACING);
+
+ /*
+ * setup the prefix mappings and schema info
+ */
+ ret = dsdb_module_search_dn(module, tmp_ctx, &schema_res,
+ schema_dn, schema_attrs);
+ if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+ goto failed;
+ } else if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb,
+ "dsdb_schema: failed to search the schema head: %s",
+ ldb_errstring(ldb));
+ goto failed;
+ }
+
+ /*
+ * load the attribute definitions
+ */
+ ret = dsdb_module_search(module, tmp_ctx, &a_res,
+ schema_dn, LDB_SCOPE_ONELEVEL, NULL,
+ "(objectClass=attributeSchema)");
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb,
+ "dsdb_schema: failed to search attributeSchema objects: %s",
+ ldb_errstring(ldb));
+ goto failed;
+ }
+
+ /*
+ * load the objectClass definitions
+ */
+ ret = dsdb_module_search(module, tmp_ctx, &c_res,
+ schema_dn, LDB_SCOPE_ONELEVEL, NULL,
+ "(objectClass=classSchema)");
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb,
+ "dsdb_schema: failed to search attributeSchema objects: %s",
+ ldb_errstring(ldb));
+ goto failed;
+ }
+
+ ret = dsdb_schema_from_ldb_results(tmp_ctx, ldb,
+ lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
+ schema_res, a_res, c_res, schema, &error_string);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb,
+ "dsdb_schema load failed: %s",
+ error_string);
+ goto failed;
+ }
+ talloc_steal(mem_ctx, *schema);
+
+failed:
+ if (flags & LDB_FLG_ENABLE_TRACING) {
+ flags = ldb_get_flags(ldb);
+ ldb_set_flags(ldb, flags | LDB_FLG_ENABLE_TRACING);
+ }
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+
static int schema_fsmo_init(struct ldb_module *module)
{
struct ldb_context *ldb;
TALLOC_CTX *mem_ctx;
struct ldb_dn *schema_dn;
struct dsdb_schema *schema;
- char *error_string = NULL;
int ret;
struct schema_fsmo_private_data *data;
@@ -134,9 +230,9 @@ static int schema_fsmo_init(struct ldb_module *module)
return LDB_ERR_OPERATIONS_ERROR;
}
- ret = dsdb_schema_from_schema_dn(mem_ctx, ldb,
+ ret = dsdb_schema_from_schema_dn(mem_ctx, module,
lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
- schema_dn, &schema, &error_string);
+ schema_dn, &schema);
if (ret == LDB_ERR_NO_SUCH_OBJECT) {
ldb_reset_err_string(ldb);
@@ -147,9 +243,6 @@ static int schema_fsmo_init(struct ldb_module *module)
}
if (ret != LDB_SUCCESS) {
- ldb_asprintf_errstring(ldb,
- "schema_fsmo_init: dsdb_schema load failed: %s",
- error_string);
talloc_free(mem_ctx);
return ret;
}
@@ -246,7 +339,6 @@ static int schema_fsmo_extended(struct ldb_module *module, struct ldb_request *r
struct ldb_context *ldb;
struct ldb_dn *schema_dn;
struct dsdb_schema *schema;
- char *error_string = NULL;
int ret;
TALLOC_CTX *mem_ctx;
@@ -270,9 +362,9 @@ static int schema_fsmo_extended(struct ldb_module *module, struct ldb_request *r
return LDB_ERR_OPERATIONS_ERROR;
}
- ret = dsdb_schema_from_schema_dn(mem_ctx, ldb,
+ ret = dsdb_schema_from_schema_dn(mem_ctx, module,
lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
- schema_dn, &schema, &error_string);
+ schema_dn, &schema);
if (ret == LDB_ERR_NO_SUCH_OBJECT) {
ldb_reset_err_string(ldb);
@@ -283,9 +375,6 @@ static int schema_fsmo_extended(struct ldb_module *module, struct ldb_request *r
}
if (ret != LDB_SUCCESS) {
- ldb_asprintf_errstring(ldb,
- "schema_fsmo_extended: dsdb_schema load failed: %s",
- error_string);
talloc_free(mem_ctx);
return ldb_next_request(module, req);
}
diff --git a/source4/dsdb/samdb/ldb_modules/subtree_delete.c b/source4/dsdb/samdb/ldb_modules/subtree_delete.c
index 241cc5f7d6..e1ce9c1fa8 100644
--- a/source4/dsdb/samdb/ldb_modules/subtree_delete.c
+++ b/source4/dsdb/samdb/ldb_modules/subtree_delete.c
@@ -55,6 +55,8 @@ static struct subtree_delete_context *subdel_ctx_init(struct ldb_module *module,
ac->module = module;
ac->req = req;
+ ac->num_children = 0;
+
return ac;
}
diff --git a/source4/dsdb/samdb/ldb_modules/tests/samba3sam.py b/source4/dsdb/samdb/ldb_modules/tests/samba3sam.py
index fe96b88221..c61d3973a1 100644
--- a/source4/dsdb/samdb/ldb_modules/tests/samba3sam.py
+++ b/source4/dsdb/samdb/ldb_modules/tests/samba3sam.py
@@ -313,6 +313,14 @@ class MapTestCase(MapBaseTestCase):
# Add a set of split records
self.ldb.add_ldif("""
+dn: """+ self.samba4.dn("cn=Domain Users") + """
+objectClass: group
+cn: Domain Users
+objectSid: S-1-5-21-4231626423-2410014848-2360679739-513
+""")
+
+ # Add a set of split records
+ self.ldb.add_ldif("""
dn: """+ self.samba4.dn("cn=X") + """
objectClass: user
cn: X
@@ -459,7 +467,7 @@ objectSid: S-1-5-21-4231626423-2410014848-2360679739-552
# errors, letting the search fail with no results.
#res = self.ldb.search("(objectSid=S-1-5-21-4231626423-2410014848-2360679739-552)", scope=SCOPE_DEFAULT, attrs)
res = self.ldb.search(expression="(objectSid=*)", base=None, scope=SCOPE_DEFAULT, attrs=["dnsHostName", "lastLogon", "objectSid"])
- self.assertEquals(len(res), 3)
+ self.assertEquals(len(res), 4)
self.assertEquals(str(res[0].dn), self.samba4.dn("cn=X"))
self.assertEquals(str(res[0]["dnsHostName"]), "x")
self.assertEquals(str(res[0]["lastLogon"]), "x")
@@ -621,7 +629,7 @@ objectSid: S-1-5-21-4231626423-2410014848-2360679739-552
# Search by negated local attribute
res = self.ldb.search(expression="(!(revision=x))",
attrs=["dnsHostName", "lastLogon"])
- self.assertEquals(len(res), 5)
+ self.assertEquals(len(res), 6)
self.assertEquals(str(res[0].dn), self.samba4.dn("cn=B"))
self.assertTrue(not "dnsHostName" in res[0])
self.assertEquals(str(res[0]["lastLogon"]), "y")
@@ -638,7 +646,7 @@ objectSid: S-1-5-21-4231626423-2410014848-2360679739-552
# Search by negated remote attribute
res = self.ldb.search(expression="(!(description=x))",
attrs=["dnsHostName", "lastLogon"])
- self.assertEquals(len(res), 3)
+ self.assertEquals(len(res), 4)
self.assertEquals(str(res[0].dn), self.samba4.dn("cn=Z"))
self.assertEquals(str(res[0]["dnsHostName"]), "z")
self.assertEquals(str(res[0]["lastLogon"]), "z")
@@ -649,7 +657,7 @@ objectSid: S-1-5-21-4231626423-2410014848-2360679739-552
# Search by negated conjunction of local attributes
res = self.ldb.search(expression="(!(&(codePage=x)(revision=x)))",
attrs=["dnsHostName", "lastLogon"])
- self.assertEquals(len(res), 5)
+ self.assertEquals(len(res), 6)
self.assertEquals(str(res[0].dn), self.samba4.dn("cn=B"))
self.assertTrue(not "dnsHostName" in res[0])
self.assertEquals(str(res[0]["lastLogon"]), "y")
@@ -666,7 +674,7 @@ objectSid: S-1-5-21-4231626423-2410014848-2360679739-552
# Search by negated conjunction of remote attributes
res = self.ldb.search(expression="(!(&(lastLogon=x)(description=x)))",
attrs=["dnsHostName", "lastLogon"])
- self.assertEquals(len(res), 5)
+ self.assertEquals(len(res), 6)
self.assertEquals(str(res[0].dn), self.samba4.dn("cn=Y"))
self.assertEquals(str(res[0]["dnsHostName"]), "y")
self.assertEquals(str(res[0]["lastLogon"]), "y")
@@ -683,7 +691,7 @@ objectSid: S-1-5-21-4231626423-2410014848-2360679739-552
# Search by negated conjunction of local and remote attribute
res = self.ldb.search(expression="(!(&(codePage=x)(description=x)))",
attrs=["dnsHostName", "lastLogon"])
- self.assertEquals(len(res), 5)
+ self.assertEquals(len(res), 6)
self.assertEquals(str(res[0].dn), self.samba4.dn("cn=B"))
self.assertTrue(not "dnsHostName" in res[0])
self.assertEquals(str(res[0]["lastLogon"]), "y")
@@ -716,7 +724,7 @@ objectSid: S-1-5-21-4231626423-2410014848-2360679739-552
# Search by negated disjunction of remote attributes
res = self.ldb.search(expression="(!(|(badPwdCount=x)(lastLogon=x)))",
attrs=["dnsHostName", "lastLogon"])
- self.assertEquals(len(res), 4)
+ self.assertEquals(len(res), 5)
self.assertEquals(str(res[0].dn), self.samba4.dn("cn=Y"))
self.assertEquals(str(res[0]["dnsHostName"]), "y")
self.assertEquals(str(res[0]["lastLogon"]), "y")
@@ -730,7 +738,7 @@ objectSid: S-1-5-21-4231626423-2410014848-2360679739-552
# Search by negated disjunction of local and remote attribute
res = self.ldb.search(expression="(!(|(revision=x)(lastLogon=y)))",
attrs=["dnsHostName", "lastLogon"])
- self.assertEquals(len(res), 4)
+ self.assertEquals(len(res), 5)
self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A"))
self.assertTrue(not "dnsHostName" in res[0])
self.assertEquals(str(res[0]["lastLogon"]), "x")
@@ -743,7 +751,7 @@ objectSid: S-1-5-21-4231626423-2410014848-2360679739-552
# Search by complex parse tree
res = self.ldb.search(expression="(|(&(revision=x)(dnsHostName=x))(!(&(description=x)(nextRid=y)))(badPwdCount=y))", attrs=["dnsHostName", "lastLogon"])
- self.assertEquals(len(res), 6)
+ self.assertEquals(len(res), 7)
self.assertEquals(str(res[0].dn), self.samba4.dn("cn=B"))
self.assertTrue(not "dnsHostName" in res[0])
self.assertEquals(str(res[0]["lastLogon"]), "y")
diff --git a/source4/dsdb/samdb/ldb_modules/util.c b/source4/dsdb/samdb/ldb_modules/util.c
new file mode 100644
index 0000000000..476eb08ed0
--- /dev/null
+++ b/source4/dsdb/samdb/ldb_modules/util.c
@@ -0,0 +1,128 @@
+/*
+ Unix SMB/CIFS implementation.
+ Samba utility functions
+
+ Copyright (C) Andrew Tridgell 2009
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
+
+ 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 <http://www.gnu.org/licenses/>.
+*/
+
+#include "ldb.h"
+#include "ldb_module.h"
+
+/*
+ search for attrs on one DN, in the modules below
+ */
+int dsdb_module_search_dn(struct ldb_module *module,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_result **_res,
+ struct ldb_dn *basedn,
+ const char * const *attrs)
+{
+ int ret;
+ struct ldb_request *req;
+ TALLOC_CTX *tmp_ctx;
+ struct ldb_result *res;
+
+ tmp_ctx = talloc_new(mem_ctx);
+
+ res = talloc_zero(tmp_ctx, struct ldb_result);
+ if (!res) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
+ basedn,
+ LDB_SCOPE_BASE,
+ NULL,
+ attrs,
+ NULL,
+ res,
+ ldb_search_default_callback,
+ NULL);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ ret = ldb_next_request(module, req);
+ if (ret == LDB_SUCCESS) {
+ ret = ldb_wait(req->handle, LDB_WAIT_ALL);
+ }
+
+ if (ret != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ if (res->count != 1) {
+ /* we may be reading a DB that does not have the 'check base on search' option... */
+ ret = LDB_ERR_NO_SUCH_OBJECT;
+ } else {
+ *_res = talloc_steal(mem_ctx, res);
+ }
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+/*
+ search for attrs in the modules below
+ */
+int dsdb_module_search(struct ldb_module *module,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_result **_res,
+ struct ldb_dn *basedn, enum ldb_scope scope,
+ const char * const *attrs,
+ const char *expression)
+{
+ int ret;
+ struct ldb_request *req;
+ TALLOC_CTX *tmp_ctx;
+ struct ldb_result *res;
+
+ tmp_ctx = talloc_new(mem_ctx);
+
+ res = talloc_zero(tmp_ctx, struct ldb_result);
+ if (!res) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
+ basedn,
+ scope,
+ expression,
+ attrs,
+ NULL,
+ res,
+ ldb_search_default_callback,
+ NULL);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ ret = ldb_next_request(module, req);
+ if (ret == LDB_SUCCESS) {
+ ret = ldb_wait(req->handle, LDB_WAIT_ALL);
+ }
+
+ talloc_free(req);
+ if (ret == LDB_SUCCESS) {
+ *_res = talloc_steal(mem_ctx, res);
+ }
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
diff --git a/source4/dsdb/samdb/ldb_modules/util.h b/source4/dsdb/samdb/ldb_modules/util.h
new file mode 100644
index 0000000000..0a1ab83c6d
--- /dev/null
+++ b/source4/dsdb/samdb/ldb_modules/util.h
@@ -0,0 +1,22 @@
+/*
+ Unix SMB/CIFS implementation.
+ Samba utility functions
+
+ Copyright (C) Andrew Tridgell 2009
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
+
+ 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 <http://www.gnu.org/licenses/>.
+*/
+
+#include "dsdb/samdb/ldb_modules/util_proto.h"