/*
- casefold a dn. We need to uppercase the attribute names, and the
- attribute values of case insensitive attributes. We also need to remove
- extraneous spaces between elements
+ callback function used in call to ldb_dn_fold() for determining whether an
+ attribute type requires case folding.
*/
-static char *ltdb_dn_fold(struct ldb_module *module, const char *dn)
+static int ltdb_case_fold_attr_required(void * user_data, char *attr)
{
- const char *dn_orig = dn;
- struct ldb_context *ldb = module->ldb;
- TALLOC_CTX *tmp_ctx = talloc_new(ldb);
- char *ret;
- size_t len;
-
- ret = talloc_strdup(tmp_ctx, "");
- if (ret == NULL) goto failed;
-
- while ((len = strcspn(dn, ",")) > 0) {
- char *p = strchr(dn, '=');
- char *attr, *value;
- int flags;
-
- if (p == NULL || (p-dn) > len) goto failed;
-
- attr = talloc_strndup(tmp_ctx, dn, p-dn);
- if (attr == NULL) goto failed;
-
- /* trim spaces from the attribute name */
- while (' ' == *attr) attr++;
- while (' ' == attr[strlen(attr)-1]) {
- attr[strlen(attr)-1] = 0;
- }
- if (*attr == 0) goto failed;
-
- value = talloc_strndup(tmp_ctx, p+1, len-(p+1-dn));
- if (value == NULL) goto failed;
+ struct ldb_module *module = talloc_get_type(user_data, struct ldb_module);
- /* trim spaces from the value */
- while (' ' == *value) value++;
- while (' ' == value[strlen(value)-1]) {
- value[strlen(value)-1] = 0;
- }
- if (*value == 0) goto failed;
-
- flags = ltdb_attribute_flags(module, attr);
-
- attr = ldb_casefold(ldb, attr);
- if (attr == NULL) goto failed;
- talloc_steal(tmp_ctx, attr);
-
- if (flags & LTDB_FLAG_CASE_INSENSITIVE) {
- value = ldb_casefold(ldb, value);
- if (value == NULL) goto failed;
- talloc_steal(tmp_ctx, value);
- }
-
- if (dn[len] == ',') {
- ret = talloc_asprintf_append(ret, "%s=%s,", attr, value);
- } else {
- ret = talloc_asprintf_append(ret, "%s=%s", attr, value);
- }
- if (ret == NULL) goto failed;
-
- dn += len;
- if (*dn == ',') dn++;
- }
-
- talloc_steal(ldb, ret);
- talloc_free(tmp_ctx);
- return ret;
-
-failed:
- talloc_free(tmp_ctx);
- return ldb_casefold(ldb, dn_orig);
+ return ltdb_attribute_flags(module, attr) & LTDB_FLAG_CASE_INSENSITIVE;
}
/*
}
talloc_free(attr_name);
} else {
- dn_folded = ltdb_dn_fold(module, dn);
+ dn_folded = ldb_dn_fold(module->ldb, dn,
+ module, ltdb_case_fold_attr_required);
}
if (!dn_folded) {
return 0;
}
+/*
+ check special dn's have valid attributes
+ currently only @ATTRIBUTES is checked
+*/
+int ltdb_check_special_dn(struct ldb_module *module, const struct ldb_message *msg)
+{
+ struct ltdb_private *ltdb = module->private_data;
+ int i, j;
+
+ if (strcmp(msg->dn, LTDB_ATTRIBUTES) != 0) {
+ return 0;
+ }
+
+ /* we have @ATTRIBUTES, let's check attributes are fine */
+ /* should we check that we deny multivalued attributes ? */
+ for (i = 0; i < msg->num_elements; i++) {
+ for (j = 0; j < msg->elements[i].num_values; j++) {
+ if (ltdb_check_at_attributes_values(&msg->elements[i].values[j]) != 0) {
+ ltdb->last_err_string = "Invalid attribute value in an @ATTRIBUTES entry";
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
/*
we've made a modification to a dn - possibly reindex and
ltdb->last_err_string = NULL;
+ ret = ltdb_check_special_dn(module, msg);
+ if (ret != 0) {
+ return ret;
+ }
+
if (ltdb_lock(module, LDBLOCK) != 0) {
return -1;
}
ltdb_unlock(module, LDBLOCK);
return -1;
}
-
+
ret = ltdb_store(module, msg, TDB_INSERT);
if (ret == 0) {
ltdb->last_err_string = NULL;
+ ret = ltdb_check_special_dn(module, msg);
+ if (ret != 0) {
+ return ret;
+ }
+
if (ltdb_lock(module, LDBLOCK) != 0) {
return -1;
}
return -1;
}
+ if (ltdb_cache_load(module) != 0) {
+ ltdb_unlock(module, LDBLOCK);
+ return -1;
+ }
+
msg = talloc(module, struct ldb_message);
if (msg == NULL) {
goto failed;
static const struct ldb_module_ops ltdb_ops = {
- "tdb",
- ltdb_search,
- ltdb_add,
- ltdb_modify,
- ltdb_delete,
- ltdb_rename,
- ltdb_lock,
- ltdb_unlock,
- ltdb_errstring
+ .name = "tdb",
+ .search = ltdb_search,
+ .search_bytree = ltdb_search_bytree,
+ .add_record = ltdb_add,
+ .modify_record = ltdb_modify,
+ .delete_record = ltdb_delete,
+ .rename_record = ltdb_rename,
+ .named_lock = ltdb_lock,
+ .named_unlock = ltdb_unlock,
+ .errstring = ltdb_errstring
};
/*
connect to the database
*/
-struct ldb_context *ltdb_connect(const char *url,
- unsigned int flags,
- const char *options[])
+int ltdb_connect(struct ldb_context *ldb, const char *url,
+ unsigned int flags, const char *options[])
{
const char *path;
int tdb_flags, open_flags;
struct ltdb_private *ltdb;
TDB_CONTEXT *tdb;
- struct ldb_context *ldb;
-
- ldb = talloc_zero(NULL, struct ldb_context);
- if (!ldb) {
- errno = ENOMEM;
- return NULL;
- }
/* parse the url */
if (strchr(url, ':')) {
if (strncmp(url, "tdb://", 6) != 0) {
- errno = EINVAL;
- talloc_free(ldb);
- return NULL;
+ ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid tdb URL '%s'", url);
+ return -1;
}
path = url+6;
} else {
/* note that we use quite a large default hash size */
tdb = tdb_open(path, 10000, tdb_flags, open_flags, 0666);
if (!tdb) {
- talloc_free(ldb);
- return NULL;
+ ldb_debug(ldb, LDB_DEBUG_ERROR, "Unable to open tdb '%s'", path);
+ return -1;
}
ltdb = talloc_zero(ldb, struct ltdb_private);
if (!ltdb) {
tdb_close(tdb);
- talloc_free(ldb);
- errno = ENOMEM;
- return NULL;
+ ldb_oom(ldb);
+ return -1;
}
ltdb->tdb = tdb;
ldb->modules = talloc(ldb, struct ldb_module);
if (!ldb->modules) {
- talloc_free(ldb);
- errno = ENOMEM;
- return NULL;
+ ldb_oom(ldb);
+ talloc_free(ltdb);
+ return -1;
}
ldb->modules->ldb = ldb;
ldb->modules->prev = ldb->modules->next = NULL;
ldb->modules->private_data = ltdb;
ldb->modules->ops = <db_ops;
- return ldb;
+ return 0;
}