This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
+ version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
/*
* Author: Derrell Lipman (based on Andrew Tridgell's LDAP backend)
*/
-#include "includes.h"
-#include "ldb/include/includes.h"
+#include "ldb_module.h"
#include <sqlite3.h>
struct lsql_context {
struct ldb_module *module;
+ struct ldb_request *req;
/* search stuff */
long long current_eid;
const char * const * attrs;
struct ldb_reply *ares;
-
- /* async stuff */
- void *context;
- int (*callback)(struct ldb_context *, void *, struct ldb_reply *);
};
-static struct ldb_handle *init_handle(struct lsqlite3_private *lsqlite3,
- struct ldb_module *module,
- struct ldb_request *req)
-{
- struct lsql_context *ac;
- struct ldb_handle *h;
-
- h = talloc_zero(lsqlite3, struct ldb_handle);
- if (h == NULL) {
- ldb_set_errstring(module->ldb, "Out of Memory");
- return NULL;
- }
-
- h->module = module;
-
- ac = talloc(h, struct lsql_context);
- if (ac == NULL) {
- ldb_set_errstring(module->ldb, "Out of Memory");
- talloc_free(h);
- return NULL;
- }
-
- h->private_data = (void *)ac;
-
- h->state = LDB_ASYNC_INIT;
- h->status = LDB_SUCCESS;
-
- ac->module = module;
- ac->context = req->context;
- ac->callback = req->callback;
-
- return h;
-}
-
/*
* Macros used throughout
*/
void *mem_ctx,
const struct ldb_parse_tree *t)
{
- const struct ldb_attrib_handler *h;
+ const struct ldb_schema_attribute *a;
struct ldb_val value, subval;
char *wild_card_string;
char *child, *tmp;
*/
attr = ldb_attr_casefold(mem_ctx, t->u.equality.attr);
if (attr == NULL) return NULL;
- h = ldb_attrib_handler(module->ldb, attr);
+ a = ldb_schema_attribute_by_name(module->ldb, attr);
/* Get a canonicalised copy of the data */
- h->canonicalise_fn(module->ldb, mem_ctx, &(t->u.equality.value), &value);
+ a->syntax->canonicalise_fn(module->ldb, mem_ctx, &(t->u.equality.value), &value);
if (value.data == NULL) {
return NULL;
}
- if (strcasecmp(t->u.equality.attr, "objectclass") == 0) {
- /*
- * For object classes, we want to search for all objectclasses
- * that are subclasses as well.
- */
- return lsqlite3_tprintf(mem_ctx,
- "SELECT eid FROM ldb_attribute_values\n"
- "WHERE norm_attr_name = 'OBJECTCLASS' "
- "AND norm_attr_value IN\n"
- " (SELECT class_name FROM ldb_object_classes\n"
- " WHERE tree_key GLOB\n"
- " (SELECT tree_key FROM ldb_object_classes\n"
- " WHERE class_name = '%q'\n"
- " ) || '*'\n"
- " )\n", value.data);
-
- } else if (strcasecmp(t->u.equality.attr, "dn") == 0) {
+ if (strcasecmp(t->u.equality.attr, "dn") == 0) {
/* DN query is a special ldb case */
const char *cdn = ldb_dn_get_casefold(
ldb_dn_new(mem_ctx, module->ldb,
attr = ldb_attr_casefold(mem_ctx, t->u.substring.attr);
if (attr == NULL) return NULL;
- h = ldb_attrib_handler(module->ldb, attr);
+ a = ldb_schema_attribute_by_name(module->ldb, attr);
subval.data = (void *)wild_card_string;
subval.length = strlen(wild_card_string) + 1;
/* Get a canonicalised copy of the data */
- h->canonicalise_fn(module->ldb, mem_ctx, &(subval), &value);
+ a->syntax->canonicalise_fn(module->ldb, mem_ctx, &(subval), &value);
if (value.data == NULL) {
return NULL;
}
case LDB_OP_GREATER:
attr = ldb_attr_casefold(mem_ctx, t->u.equality.attr);
if (attr == NULL) return NULL;
- h = ldb_attrib_handler(module->ldb, attr);
+ a = ldb_schema_attribute_by_name(module->ldb, attr);
/* Get a canonicalised copy of the data */
- h->canonicalise_fn(module->ldb, mem_ctx, &(t->u.equality.value), &value);
+ a->syntax->canonicalise_fn(module->ldb, mem_ctx, &(t->u.equality.value), &value);
if (value.data == NULL) {
return NULL;
}
case LDB_OP_LESS:
attr = ldb_attr_casefold(mem_ctx, t->u.equality.attr);
if (attr == NULL) return NULL;
- h = ldb_attrib_handler(module->ldb, attr);
+ a = ldb_schema_attribute_by_name(module->ldb, attr);
/* Get a canonicalised copy of the data */
- h->canonicalise_fn(module->ldb, mem_ctx, &(t->u.equality.value), &value);
+ a->syntax->canonicalise_fn(module->ldb, mem_ctx, &(t->u.equality.value), &value);
if (value.data == NULL) {
return NULL;
}
case LDB_OP_APPROX:
attr = ldb_attr_casefold(mem_ctx, t->u.equality.attr);
if (attr == NULL) return NULL;
- h = ldb_attrib_handler(module->ldb, attr);
+ a = ldb_schema_attribute_by_name(module->ldb, attr);
/* Get a canonicalised copy of the data */
- h->canonicalise_fn(module->ldb, mem_ctx, &(t->u.equality.value), &value);
+ a->syntax->canonicalise_fn(module->ldb, mem_ctx, &(t->u.equality.value), &value);
if (value.data == NULL) {
return NULL;
}
const char *func = (const char *)sqlite3_value_text(argv[1]);
const char *cmp = (const char *)sqlite3_value_text(argv[2]);
const char *attr = (const char *)sqlite3_value_text(argv[3]);
- const struct ldb_attrib_handler *h;
+ const struct ldb_schema_attribute *a;
struct ldb_val valX;
struct ldb_val valY;
int ret;
switch (func[0]) {
/* greater */
case '>': /* >= */
- h = ldb_attrib_handler(ldb, attr);
+ a = ldb_schema_attribute_by_name(ldb, attr);
valX.data = (void *)cmp;
valX.length = strlen(cmp);
valY.data = (void *)val;
valY.length = strlen(val);
- ret = h->comparison_fn(ldb, ldb, &valY, &valX);
+ ret = a->syntax->comparison_fn(ldb, ldb, &valY, &valX);
if (ret >= 0)
sqlite3_result_int(ctx, 1);
else
/* lesser */
case '<': /* <= */
- h = ldb_attrib_handler(ldb, attr);
+ a = ldb_schema_attribute_by_name(ldb, attr);
valX.data = (void *)cmp;
valX.length = strlen(cmp);
valY.data = (void *)val;
valY.length = strlen(val);
- ret = h->comparison_fn(ldb, ldb, &valY, &valX);
+ ret = a->syntax->comparison_fn(ldb, ldb, &valY, &valX);
if (ret <= 0)
sqlite3_result_int(ctx, 1);
else
char *query = NULL;
int ret;
- req->handle = init_handle(lsqlite3, module, req);
- if (req->handle == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
lsql_ac = talloc_get_type(req->handle->private_data, struct lsql_context);
- if ((req->op.search.base == NULL || req->op.search.base->comp_num == 0) &&
+ 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;
int i;
int ret = LDB_SUCCESS;
- req->handle = init_handle(lsqlite3, module, req);
- if (req->handle == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
lsql_ac = talloc_get_type(req->handle->private_data, struct lsql_context);
req->handle->state = LDB_ASYNC_DONE;
req->handle->status = LDB_SUCCESS;
/* See if this is an ltdb special */
if (ldb_dn_is_special(msg->dn)) {
- struct ldb_dn *c;
-
- c = ldb_dn_new(lsql_ac, module->ldb, "@SUBCLASSES");
- if (ldb_dn_compare(module->ldb, msg->dn, c) == 0) {
-#warning "insert subclasses into object class tree"
- ret = LDB_ERR_UNWILLING_TO_PERFORM;
- goto done;
- }
-
/*
+ struct ldb_dn *c;
c = ldb_dn_new(local_ctx, module->ldb, "@INDEXLIST");
if (ldb_dn_compare(module->ldb, msg->dn, c) == 0) {
#warning "should we handle indexes somehow ?"
for (i = 0; i < msg->num_elements; i++) {
const struct ldb_message_element *el = &msg->elements[i];
- const struct ldb_attrib_handler *h;
+ const struct ldb_schema_attribute *a;
char *attr;
int j;
goto done;
}
- h = ldb_attrib_handler(module->ldb, el->name);
+ a = ldb_schema_attribute_by_name(module->ldb, el->name);
/* For each value of the specified attribute name... */
for (j = 0; j < el->num_values; j++) {
char *insert;
/* Get a canonicalised copy of the data */
- h->canonicalise_fn(module->ldb, lsql_ac, &(el->values[j]), &value);
+ a->syntax->canonicalise_fn(module->ldb, lsql_ac, &(el->values[j]), &value);
if (value.data == NULL) {
ret = LDB_ERR_OTHER;
goto done;
int i;
int ret = LDB_SUCCESS;
- req->handle = init_handle(lsqlite3, module, req);
- if (req->handle == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
lsql_ac = talloc_get_type(req->handle->private_data, struct lsql_context);
req->handle->state = LDB_ASYNC_DONE;
req->handle->status = LDB_SUCCESS;
/* See if this is an ltdb special */
if (ldb_dn_is_special(msg->dn)) {
- struct ldb_dn *c;
-
- c = ldb_dn_new(lsql_ac, module->ldb, "@SUBCLASSES");
- if (ldb_dn_compare(module->ldb, msg->dn, c) == 0) {
-#warning "modify subclasses into object class tree"
- ret = LDB_ERR_UNWILLING_TO_PERFORM;
- goto done;
- }
-
/* Others return an error */
ret = LDB_ERR_UNWILLING_TO_PERFORM;
goto done;
for (i = 0; i < msg->num_elements; i++) {
const struct ldb_message_element *el = &msg->elements[i];
- const struct ldb_attrib_handler *h;
+ const struct ldb_schema_attribute *a;
int flags = el->flags & LDB_FLAG_MOD_MASK;
char *attr;
char *mod;
goto done;
}
- h = ldb_attrib_handler(module->ldb, el->name);
+ a = ldb_schema_attribute_by_name(module->ldb, el->name);
switch (flags) {
struct ldb_val value;
/* Get a canonicalised copy of the data */
- h->canonicalise_fn(module->ldb, lsql_ac, &(el->values[j]), &value);
+ a->syntax->canonicalise_fn(module->ldb, lsql_ac, &(el->values[j]), &value);
if (value.data == NULL) {
ret = LDB_ERR_OTHER;
goto done;
struct ldb_val value;
/* Get a canonicalised copy of the data */
- h->canonicalise_fn(module->ldb, lsql_ac, &(el->values[j]), &value);
+ a->syntax->canonicalise_fn(module->ldb, lsql_ac, &(el->values[j]), &value);
if (value.data == NULL) {
ret = LDB_ERR_OTHER;
goto done;
int ret = LDB_SUCCESS;
- req->handle = init_handle(lsqlite3, module, req);
- if (req->handle == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
lsql_ac = talloc_get_type(req->handle->private_data, struct lsql_context);
req->handle->state = LDB_ASYNC_DONE;
req->handle->status = LDB_SUCCESS;
char *query;
int ret = LDB_SUCCESS;
- req->handle = init_handle(lsqlite3, module, req);
- if (req->handle == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
lsql_ac = talloc_get_type(req->handle->private_data, struct lsql_context);
req->handle->state = LDB_ASYNC_DONE;
req->handle->status = LDB_SUCCESS;
return LDB_ERR_OPERATIONS_ERROR;
}
-static int lsql_wait(struct ldb_handle *handle, enum ldb_wait_type type)
+static int lsql_run_request(struct ldb_module *module, struct ldb_request *req)
+{
+ switch (req->operation) {
+ case LDB_SEARCH:
+ return lsql_search(module, req);
+ break;
+ case LDB_ADD:
+ return lsql_add(module, req);
+ break;
+ case LDB_MODIFY:
+ return lsql_modify(module, req);
+ break;
+ case LDB_DELETE:
+ return lsql_delete(module, req);
+ break;
+ case LDB_RENAME:
+ return lsql_rename(module, req);
+ break;
+/* TODO:
+ case LDB_SEQUENCE_NUMBER:
+ return lsql_sequence_number(module, req);
+ break;
+ */
+ default:
+ return lsql_request(module, req);
+ break;
+ }
+
+ return LDB_ERR_OPERATIONS_ERROR;
+}
+
+static int lsql_handle_request(struct ldb_module *module, struct ldb_request *req)
{
- return handle->status;
+ struct lsql_context *ac;
+
+ if (check_critical_controls(req->controls)) {
+ return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
+ }
+
+ ac = talloc_zero(req, struct lsql_context);
+ if (ac == NULL) {
+ ldb_set_errstring(module->ldb, "Out of Memory");
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ac->module = module;
+ ac->req = req;
+
+ req->handle = ldb_handle_new(req, lsql_run_request, ac);
+ if (req->handle == NULL) {
+ talloc_free(ac);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ return LDB_SUCCESS;
}
/*
*/
static const struct ldb_module_ops lsqlite3_ops = {
.name = "sqlite",
- .search = lsql_search,
- .add = lsql_add,
- .modify = lsql_modify,
- .del = lsql_delete,
- .rename = lsql_rename,
- .request = lsql_request,
+ .search = lsql_handle_request,
+ .add = lsql_handle_request,
+ .modify = lsql_handle_request,
+ .del = lsql_handle_request,
+ .rename = lsql_handle_request,
+ .request = lsql_handle_request,
.start_transaction = lsql_start_trans,
.end_transaction = lsql_end_trans,
.del_transaction = lsql_del_trans,
- .wait = lsql_wait,
+ /* TODO: .sequence_number = lsql_handle_request */
};
/*
return -1;
}
-int ldb_sqlite3_init(void)
-{
- return ldb_register_backend("sqlite3", lsqlite3_connect);
-}
+const struct ldb_backend_ops ldb_sqlite3_backend_ops = {
+ .name = "sqlite3",
+ .connect_fn = lsqlite3_connect
+};