diff options
-rw-r--r-- | source4/lib/ldb/ldb_tdb/ldb_cache.c | 35 | ||||
-rw-r--r-- | source4/lib/ldb/ldb_tdb/ldb_search.c | 122 | ||||
-rw-r--r-- | source4/lib/ldb/ldb_tdb/ldb_tdb.h | 4 |
3 files changed, 144 insertions, 17 deletions
diff --git a/source4/lib/ldb/ldb_tdb/ldb_cache.c b/source4/lib/ldb/ldb_tdb/ldb_cache.c index de489e3d8b..77922a97c7 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_cache.c +++ b/source4/lib/ldb/ldb_tdb/ldb_cache.c @@ -113,11 +113,13 @@ static int ltdb_attributes_load(struct ldb_module *module) if (dn == NULL) goto failed; r = ltdb_search_dn1(module, dn, msg); + talloc_free(dn); if (r != LDB_SUCCESS && r != LDB_ERR_NO_SUCH_OBJECT) { - talloc_free(dn); goto failed; } - talloc_free(dn); + if (r == LDB_ERR_NO_SUCH_OBJECT) { + return 0; + } /* mapping these flags onto ldap 'syntaxes' isn't strictly correct, but its close enough for now */ for (i=0;i<msg->num_elements;i++) { @@ -247,10 +249,10 @@ int ltdb_cache_reload(struct ldb_module *module) int ltdb_cache_load(struct ldb_module *module) { struct ltdb_private *ltdb = (struct ltdb_private *)module->private_data; - struct ldb_dn *baseinfo_dn = NULL; + struct ldb_dn *baseinfo_dn = NULL, *options_dn = NULL; struct ldb_dn *indexlist_dn = NULL; uint64_t seq; - struct ldb_message *baseinfo = NULL; + struct ldb_message *baseinfo = NULL, *options = NULL; int r; /* a very fast check to avoid extra database reads */ @@ -282,7 +284,7 @@ int ltdb_cache_load(struct ldb_module *module) } /* possibly initialise the baseinfo */ - if (!baseinfo->dn) { + if (r == LDB_ERR_NO_SUCH_OBJECT) { if (ltdb_baseinfo_init(module) != LDB_SUCCESS) { goto failed; } @@ -301,6 +303,25 @@ int ltdb_cache_load(struct ldb_module *module) } ltdb->sequence_number = seq; + /* Read an interpret database options */ + options = talloc(ltdb->cache, struct ldb_message); + if (options == NULL) goto failed; + + options_dn = ldb_dn_new(module, module->ldb, LTDB_OPTIONS); + if (options_dn == NULL) goto failed; + + r= ltdb_search_dn1(module, options_dn, options); + if (r != LDB_SUCCESS && r != LDB_ERR_NO_SUCH_OBJECT) { + goto failed; + } + + /* possibly initialise the baseinfo */ + if (r == LDB_SUCCESS) { + ltdb->check_base = ldb_msg_find_attr_as_bool(options, LTDB_CHECK_BASE, false); + } else { + ltdb->check_base = false; + } + talloc_free(ltdb->cache->last_attribute.name); memset(<db->cache->last_attribute, 0, sizeof(ltdb->cache->last_attribute)); @@ -328,12 +349,16 @@ int ltdb_cache_load(struct ldb_module *module) } done: + talloc_free(options); + talloc_free(options_dn); talloc_free(baseinfo); talloc_free(baseinfo_dn); talloc_free(indexlist_dn); return 0; failed: + talloc_free(options); + talloc_free(options_dn); talloc_free(baseinfo); talloc_free(baseinfo_dn); talloc_free(indexlist_dn); 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); diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h index 51e72c1c0f..4beced30eb 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -31,6 +31,8 @@ struct ltdb_private { } *cache; int in_transaction; + + bool check_base; }; /* @@ -58,10 +60,12 @@ struct ltdb_context { #define LTDB_IDXATTR "@IDXATTR" #define LTDB_IDXONE "@IDXONE" #define LTDB_BASEINFO "@BASEINFO" +#define LTDB_OPTIONS "@OPTIONS" #define LTDB_ATTRIBUTES "@ATTRIBUTES" /* special attribute types */ #define LTDB_SEQUENCE_NUMBER "sequenceNumber" +#define LTDB_CHECK_BASE "checkBaseOnSearch" #define LTDB_MOD_TIMESTAMP "whenChanged" #define LTDB_OBJECTCLASS "objectClass" |