summaryrefslogtreecommitdiff
path: root/source4/lib/ldb/ldb_tdb/ldb_search.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/lib/ldb/ldb_tdb/ldb_search.c')
-rw-r--r--source4/lib/ldb/ldb_tdb/ldb_search.c122
1 files changed, 110 insertions, 12 deletions
diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c
index 8151b458d4..1fa20740a5 100644
--- a/source4/lib/ldb/ldb_tdb/ldb_search.c
+++ b/source4/lib/ldb/ldb_tdb/ldb_search.c
@@ -200,6 +200,35 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_module *module,
return ret;
}
+/*
+ search the database for a single simple dn.
+ return LDB_ERR_NO_SUCH_OBJECT on record-not-found
+ and LDB_SUCCESS on success
+*/
+int ltdb_search_base(struct ldb_module *module, struct ldb_dn *dn)
+{
+ struct ltdb_private *ltdb = (struct ltdb_private *)module->private_data;
+ TDB_DATA tdb_key, tdb_data;
+
+ if (ldb_dn_is_null(dn)) {
+ return LDB_ERR_NO_SUCH_OBJECT;
+ }
+
+ /* form the key */
+ tdb_key = ltdb_key(module, dn);
+ if (!tdb_key.dptr) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ tdb_data = tdb_fetch(ltdb->tdb, tdb_key);
+ talloc_free(tdb_key.dptr);
+ if (!tdb_data.dptr) {
+ return LDB_ERR_NO_SUCH_OBJECT;
+ }
+
+ free(tdb_data.dptr);
+ return LDB_SUCCESS;
+}
/*
search the database for a single simple dn, returning all attributes
@@ -227,7 +256,7 @@ int ltdb_search_dn1(struct ldb_module *module, struct ldb_dn *dn, struct ldb_mes
if (!tdb_data.dptr) {
return LDB_ERR_NO_SUCH_OBJECT;
}
-
+
msg->num_elements = 0;
msg->elements = NULL;
@@ -473,10 +502,6 @@ int ltdb_search(struct ldb_module *module, struct ldb_request *req)
struct ldb_reply *ares;
int ret;
- if ((( ! ldb_dn_is_valid(req->op.search.base)) || ldb_dn_is_null(req->op.search.base)) &&
- (req->op.search.scope == LDB_SCOPE_BASE || req->op.search.scope == LDB_SCOPE_ONELEVEL))
- return LDB_ERR_OPERATIONS_ERROR;
-
if (ltdb_lock_read(module) != 0) {
return LDB_ERR_OPERATIONS_ERROR;
}
@@ -496,6 +521,65 @@ int ltdb_search(struct ldb_module *module, struct ldb_request *req)
ltdb_unlock_read(module);
return LDB_ERR_OPERATIONS_ERROR;
}
+
+ if ((req->op.search.base == NULL) || (ldb_dn_is_null(req->op.search.base) == true)) {
+
+ /* Check what we should do with a NULL dn */
+ switch (req->op.search.scope) {
+ case LDB_SCOPE_BASE:
+ ldb_asprintf_errstring(module->ldb,
+ "NULL Base DN invalid for a base search");
+ ret = LDB_ERR_INVALID_DN_SYNTAX;
+ case LDB_SCOPE_ONELEVEL:
+ ldb_asprintf_errstring(module->ldb,
+ "NULL Base DN invalid for a one-level search");
+ ret = LDB_ERR_INVALID_DN_SYNTAX;
+ case LDB_SCOPE_SUBTREE:
+ default:
+ /* We accept subtree searches from a NULL base DN, ie over the whole DB */
+ ret = LDB_SUCCESS;
+ }
+ } else if (ldb_dn_is_valid(req->op.search.base) == false) {
+
+ /* We don't want invalid base DNs here */
+ ldb_asprintf_errstring(module->ldb,
+ "Invalid Base DN: %s",
+ ldb_dn_get_linearized(req->op.search.base));
+ ret = LDB_ERR_INVALID_DN_SYNTAX;
+
+ } else if (ldb_dn_is_null(req->op.search.base) == true) {
+
+ /* Check what we should do with a NULL dn */
+ switch (req->op.search.scope) {
+ case LDB_SCOPE_BASE:
+ ldb_asprintf_errstring(module->ldb,
+ "NULL Base DN invalid for a base search");
+ ret = LDB_ERR_INVALID_DN_SYNTAX;
+ case LDB_SCOPE_ONELEVEL:
+ ldb_asprintf_errstring(module->ldb,
+ "NULL Base DN invalid for a one-level search");
+ ret = LDB_ERR_INVALID_DN_SYNTAX;
+ case LDB_SCOPE_SUBTREE:
+ default:
+ /* We accept subtree searches from a NULL base DN, ie over the whole DB */
+ ret = LDB_SUCCESS;
+ }
+
+ } else if (ltdb->check_base) {
+ /* This database has been marked as 'checkBaseOnSearch', so do a spot check of the base dn */
+ ret = ltdb_search_base(module, req->op.search.base);
+
+ if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+ ldb_asprintf_errstring(module->ldb,
+ "No such Base DN: %s",
+ ldb_dn_get_linearized(req->op.search.base));
+ }
+
+ } else {
+ /* If we are not checking the base DN life is easy */
+ ret = LDB_SUCCESS;
+ }
+
ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
ltdb_ac->tree = req->op.search.tree;
@@ -503,12 +587,23 @@ int ltdb_search(struct ldb_module *module, struct ldb_request *req)
ltdb_ac->base = req->op.search.base;
ltdb_ac->attrs = req->op.search.attrs;
- ret = ltdb_search_indexed(req->handle);
- if (ret == LDB_ERR_OPERATIONS_ERROR) {
- ret = ltdb_search_full(req->handle);
+
+ if (ret == LDB_SUCCESS) {
+ ret = ltdb_search_indexed(req->handle);
+ if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+ /* Not in the index, therefore OK! */
+ ret = LDB_SUCCESS;
+
+ } else if (ret == LDB_ERR_OPERATIONS_ERROR) {
+ /* Not indexed, so we need to do a full scan */
+ ret = ltdb_search_full(req->handle);
+ if (ret != LDB_SUCCESS) {
+ ldb_set_errstring(module->ldb, "Indexed and full searches both failed!\n");
+ }
+ }
}
+
if (ret != LDB_SUCCESS) {
- ldb_set_errstring(module->ldb, "Indexed and full searches both failed!\n");
req->handle->state = LDB_ASYNC_DONE;
req->handle->status = ret;
}
@@ -522,10 +617,13 @@ int ltdb_search(struct ldb_module *module, struct ldb_request *req)
}
req->handle->state = LDB_ASYNC_DONE;
- ares->type = LDB_REPLY_DONE;
- ret = req->callback(module->ldb, req->context, ares);
- req->handle->status = ret;
+ if (ret == LDB_SUCCESS) {
+ ares->type = LDB_REPLY_DONE;
+
+ ret = req->callback(module->ldb, req->context, ares);
+ req->handle->status = ret;
+ }
ltdb_unlock_read(module);