/*
ldb database library
- Copyright (C) Simo Sorce 2004
+ Copyright (C) Simo Sorce 2004-2005
** NOTE! The following LGPL license applies to the ldb
** library. This does NOT imply that all of Samba is released
#include "includes.h"
#include "ldb/include/ldb.h"
+#include "ldb/include/ldb_errors.h"
#include "ldb/include/ldb_private.h"
#define SCHEMA_FLAG_RESET 0
check there's only one structrual class (or a chain of structural classes)
*/
-struct private_data {
- const char *error_string;
-};
-
struct schema_attribute {
int flags;
char *name;
struct schema_attribute_list optional_attrs;
};
-/* This function embedds the knowledge of aliased names.
- Currently it handles only dn vs distinguishedNAme as a special case as AD
- only have this special alias case, in future we should read the schema
- to find out which names have an alias and check for them */
-static int schema_attr_cmp(const char *attr1, const char *attr2)
-{
- int ret;
-
- ret = ldb_attr_cmp(attr1, attr2);
- if (ret != 0) {
- if ((ldb_attr_cmp("dn", attr1) == 0) &&
- (ldb_attr_cmp("distinguishedName", attr2) == 0)) {
- return 0;
- }
- if ((ldb_attr_cmp("dn", attr2) == 0) &&
- (ldb_attr_cmp("distinguishedName", attr1) == 0)) {
- return 0;
- }
- }
- return ret;
-}
-
static struct schema_attribute *schema_find_attribute(struct schema_attribute_list *list, const char *attr_name)
{
unsigned int i;
objectclasses go in the objectclasses structure */
static int get_msg_attributes(struct schema_structures *ss, const struct ldb_message *msg, int flag_mask)
{
- int i, j, k, l;
+ int i, j, anum, cnum;
ss->entry_attrs.attr = talloc_realloc(ss, ss->entry_attrs.attr,
struct schema_attribute,
return -1;
}
- for (i = 0, j = ss->entry_attrs.num; i < msg->num_elements; i++) {
+ for (i = 0, anum = ss->entry_attrs.num; i < msg->num_elements; i++) {
- if (schema_attr_cmp(msg->elements[i].name, "objectclass") == 0) {
+ if (ldb_attr_cmp(msg->elements[i].name, "objectclass") == 0) {
ss->objectclasses.attr = talloc_realloc(ss, ss->objectclasses.attr,
struct schema_attribute,
return -1;
}
- for (k = 0, l = ss->objectclasses.num; k < msg->elements[i].num_values; k++) {
- ss->objectclasses.attr[l].name = msg->elements[i].values[k].data;
- ss->objectclasses.attr[l].flags = msg->elements[i].flags & flag_mask;
- l++;
+ for (j = 0, cnum = ss->objectclasses.num; j < msg->elements[i].num_values; j++) {
+ ss->objectclasses.attr[cnum+j].name = (char *)msg->elements[i].values[j].data;
+ ss->objectclasses.attr[cnum+j].flags = msg->elements[i].flags & flag_mask;
}
ss->objectclasses.num += msg->elements[i].num_values;
}
- ss->entry_attrs.attr[j].flags = msg->elements[i].flags & flag_mask;
- ss->entry_attrs.attr[j].name = talloc_reference(ss->entry_attrs.attr,
+ /* TODO: Check for proper attribute Syntax ! */
+
+ ss->entry_attrs.attr[anum+i].flags = msg->elements[i].flags & flag_mask;
+ ss->entry_attrs.attr[anum+i].name = talloc_reference(ss->entry_attrs.attr,
msg->elements[i].name);
- if (ss->entry_attrs.attr[j].name == NULL) {
+ if (ss->entry_attrs.attr[anum+i].name == NULL) {
return -1;
}
- j++;
}
ss->entry_attrs.num += msg->num_elements;
return 0;
}
-static int get_entry_attributes(struct ldb_context *ldb, const char *dn, struct schema_structures *ss)
+static int get_entry_attributes(struct ldb_context *ldb, const struct ldb_dn *dn, struct schema_structures *ss)
{
- char *filter = talloc_asprintf(ss, "dn=%s", dn);
- struct ldb_message **srch;
+ struct ldb_result *srch;
int ret;
- ret = ldb_search(ldb, NULL, LDB_SCOPE_SUBTREE, filter, NULL, &srch);
+ ret = ldb_search(ldb, dn, LDB_SCOPE_BASE, NULL, NULL, &srch);
if (ret != 1) {
return ret;
}
talloc_steal(ss, srch);
/* set flags to 0 as flags on search have undefined values */
- ret = get_msg_attributes(ss, *srch, 0);
+ ret = get_msg_attributes(ss, *(srch->msgs), 0);
if (ret != 0) {
- ldb_search_free(ldb, srch);
+ talloc_free(srch);
return ret;
}
for (c = 0; c < list->num; c++) {
len = strlen(list->attr[c].name);
if (len == el->values[i].length) {
- if (schema_attr_cmp(list->attr[c].name, el->values[i].data) == 0) {
+ if (ldb_attr_cmp(list->attr[c].name,
+ (char *)el->values[i].data) == 0) {
found = 1;
break;
}
}
}
if (!found) {
- list->attr[j + list->num].name = el->values[i].data;
+ list->attr[j + list->num].name = (char *)el->values[i].data;
list->attr[j + list->num].flags = flags;
j++;
}
recursively get parent objectlasses attributes */
static int get_attr_list_recursive(struct ldb_module *module, struct schema_structures *schema_struct)
{
- struct private_data *data = (struct private_data *)module->private_data;
- struct ldb_message **srch;
+ struct ldb_result *srch;
int i, j;
int ret;
talloc_steal(schema_struct, srch);
if (ret <= 0) {
- /* Schema DB Error: Error occurred retrieving Object Class Description */
- ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Error retrieving Objectclass %s.\n", schema_struct->objectclasses.attr[i].name);
- data->error_string = "Internal error. Error retrieving schema objectclass";
+ /* Schema DB Error: Error occurred retrieving
+ Object Class Description */
+ ldb_debug_set(module->ldb, LDB_DEBUG_ERROR,
+ "Error retrieving Objectclass %s.\n",
+ schema_struct->objectclasses.attr[i].name);
return -1;
}
if (ret > 1) {
/* Schema DB Error: Too Many Records */
- ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Too many records found retrieving Objectclass %s.\n", schema_struct->objectclasses.attr[i].name);
- data->error_string = "Internal error. Too many records searching for schema objectclass";
+ ldb_debug_set(module->ldb, LDB_DEBUG_ERROR,
+ "Too many records found retrieving Objectclass %s.\n",
+ schema_struct->objectclasses.attr[i].name);
return -1;
}
/* Add inherited classes eliminating duplicates */
/* fill in required_attrs and optional_attrs attribute lists */
- for (j = 0; j < (*srch)->num_elements; j++) {
+ for (j = 0; j < srch->msgs[0]->num_elements; j++) {
int is_aux, is_class;
is_aux = 0;
is_class = 0;
- if (schema_attr_cmp((*srch)->elements[j].name, "systemAuxiliaryclass") == 0) {
+ if (ldb_attr_cmp(srch->msgs[0]->elements[j].name, "systemAuxiliaryclass") == 0) {
is_aux = SCHEMA_FLAG_AUXILIARY;
is_class = 1;
}
- if (schema_attr_cmp((*srch)->elements[j].name, "subClassOf") == 0) {
+ if (ldb_attr_cmp(srch->msgs[0]->elements[j].name, "auxiliaryClass") == 0) {
+ is_aux = SCHEMA_FLAG_AUXILIARY;
+ is_class = 1;
+ }
+ if (ldb_attr_cmp(srch->msgs[0]->elements[j].name, "subClassOf") == 0) {
is_class = 1;
}
if (add_attribute_uniq(schema_struct,
&schema_struct->objectclasses,
is_aux,
- &(*srch)->elements[j]) != 0) {
+ &srch->msgs[0]->elements[j]) != 0) {
return -1;
}
} else {
- if (schema_attr_cmp((*srch)->elements[j].name, "mustContain") == 0 ||
- schema_attr_cmp((*srch)->elements[j].name, "SystemMustContain") == 0) {
+ if (ldb_attr_cmp(srch->msgs[0]->elements[j].name, "mustContain") == 0 ||
+ ldb_attr_cmp(srch->msgs[0]->elements[j].name, "SystemMustContain") == 0) {
if (add_attribute_uniq(schema_struct,
&schema_struct->required_attrs,
SCHEMA_FLAG_RESET,
- &(*srch)->elements[j]) != 0) {
+ &srch->msgs[0]->elements[j]) != 0) {
return -1;
}
}
- if (schema_attr_cmp((*srch)->elements[j].name, "mayContain") == 0 ||
- schema_attr_cmp((*srch)->elements[j].name, "SystemMayContain") == 0) {
+ if (ldb_attr_cmp(srch->msgs[0]->elements[j].name, "mayContain") == 0 ||
+ ldb_attr_cmp(srch->msgs[0]->elements[j].name, "SystemMayContain") == 0) {
if (add_attribute_uniq(schema_struct,
&schema_struct->optional_attrs,
SCHEMA_FLAG_RESET,
- &(*srch)->elements[j]) != 0) {
+ &srch->msgs[0]->elements[j]) != 0) {
return -1;
}
}
return 0;
}
-/* search */
-static int schema_search(struct ldb_module *module, const char *base,
- enum ldb_scope scope, const char *expression,
- const char * const *attrs, struct ldb_message ***res)
-{
- return ldb_next_search(module, base, scope, expression, attrs, res);
-}
-
-/* search_free */
-static int schema_search_free(struct ldb_module *module, struct ldb_message **res)
-{
- return ldb_next_search_free(module, res);
-}
-
/* add_record */
-static int schema_add_record(struct ldb_module *module, const struct ldb_message *msg)
+static int schema_add(struct ldb_module *module, struct ldb_request *req)
{
- struct private_data *data = (struct private_data *)module->private_data;
+ const struct ldb_message *msg = req->op.add.message;
struct schema_structures *entry_structs;
unsigned int i;
int ret;
Free all structures and commit the change
*/
- if (msg->dn[0] == '@') { /* do not check on our control entries */
- return ldb_next_add_record(module, msg);
+ /* do not check on our control entries */
+ if (ldb_dn_is_special(msg->dn)) {
+ return ldb_next_request(module, req);
}
+ /* TODO: check parent exists */
+
entry_structs = talloc_zero(module, struct schema_structures);
if (!entry_structs) {
return -1;
entry_structs->required_attrs.attr[i].name);
if (attr == NULL) { /* not found */
- ldb_debug(module->ldb, LDB_DEBUG_ERROR,
- "The required_attrs attribute %s is missing.\n",
- entry_structs->required_attrs.attr[i].name);
-
- data->error_string = "Objectclass violation, a required attribute is missing";
+ ldb_debug_set(module->ldb, LDB_DEBUG_ERROR,
+ "The required_attrs attribute %s is missing.\n",
+ entry_structs->required_attrs.attr[i].name);
talloc_free(entry_structs);
- return -1;
+ return LDB_ERR_OBJECT_CLASS_VIOLATION;
}
/* mark the attribute as checked */
entry_structs->entry_attrs.attr[i].name);
if (attr == NULL) { /* not found */
- ldb_debug(module->ldb, LDB_DEBUG_ERROR,
- "The attribute %s is not referenced by any objectclass.\n",
- entry_structs->entry_attrs.attr[i].name);
-
- data->error_string = "Objectclass violation, an invalid attribute name was found";
+ ldb_debug_set(module->ldb, LDB_DEBUG_ERROR,
+ "The attribute %s is not referenced by any objectclass.\n",
+ entry_structs->entry_attrs.attr[i].name);
talloc_free(entry_structs);
- return -1;
+ return LDB_ERR_OBJECT_CLASS_VIOLATION;
}
}
}
talloc_free(entry_structs);
- return ldb_next_add_record(module, msg);
+ return ldb_next_request(module, req);
}
/* modify_record */
-static int schema_modify_record(struct ldb_module *module, const struct ldb_message *msg)
+static int schema_modify(struct ldb_module *module, struct ldb_request *req)
{
- struct private_data *data = (struct private_data *)module->private_data;
+ const struct ldb_message *msg = req->op.mod.message;
struct schema_structures *entry_structs;
unsigned int i;
int ret;
Free all structures and commit the change.
*/
- if (msg->dn[0] == '@') { /* do not check on our control entries */
- return ldb_next_modify_record(module, msg);
+ /* do not check on our control entries */
+ if (ldb_dn_is_special(msg->dn)) {
+ return ldb_next_request(module, req);
}
/* allocate object structs */
entry_structs->required_attrs.attr[i].name);
if (attr == NULL) { /* not found */
- ldb_debug(module->ldb, LDB_DEBUG_ERROR,
- "The required_attrs attribute %s is missing.\n",
- entry_structs->required_attrs.attr[i].name);
-
- data->error_string = "Objectclass violation, a required attribute is missing";
+ ldb_debug_set(module->ldb, LDB_DEBUG_ERROR,
+ "The required_attrs attribute %s is missing.\n",
+ entry_structs->required_attrs.attr[i].name);
talloc_free(entry_structs);
- return -1;
+ return LDB_ERR_OBJECT_CLASS_VIOLATION;
}
/* check we are not trying to delete a required attribute */
/* TODO: consider multivalued attrs */
if ((attr->flags & SCHEMA_FLAG_MOD_DELETE) != 0) {
- ldb_debug(module->ldb, LDB_DEBUG_ERROR,
- "Trying to delete the required attribute %s.\n",
- attr->name);
-
- data->error_string = "Objectclass violation, a required attribute cannot be removed";
+ ldb_debug_set(module->ldb, LDB_DEBUG_ERROR,
+ "Trying to delete the required attribute %s.\n",
+ attr->name);
talloc_free(entry_structs);
- return -1;
+ return LDB_ERR_OBJECT_CLASS_VIOLATION;
}
/* mark the attribute as checked */
entry_structs->entry_attrs.attr[i].name);
if (attr == NULL) { /* not found */
- ldb_debug(module->ldb, LDB_DEBUG_ERROR,
- "The attribute %s is not referenced by any objectclass.\n",
- entry_structs->entry_attrs.attr[i].name);
-
- data->error_string = "Objectclass violation, an invalid attribute name was found";
+ ldb_debug_set(module->ldb, LDB_DEBUG_ERROR,
+ "The attribute %s is not referenced by any objectclass.\n",
+ entry_structs->entry_attrs.attr[i].name);
talloc_free(entry_structs);
- return -1;
+ return LDB_ERR_OBJECT_CLASS_VIOLATION;
}
}
}
talloc_free(entry_structs);
- return ldb_next_modify_record(module, msg);
-}
-
-/* delete_record */
-static int schema_delete_record(struct ldb_module *module, const char *dn)
-{
-/* struct private_data *data = (struct private_data *)module->private_data; */
- return ldb_next_delete_record(module, dn);
+ return ldb_next_request(module, req);
}
-/* rename_record */
-static int schema_rename_record(struct ldb_module *module, const char *olddn, const char *newdn)
+static int schema_request(struct ldb_module *module, struct ldb_request *req)
{
- return ldb_next_rename_record(module, olddn, newdn);
-}
-
-static int schema_named_lock(struct ldb_module *module, const char *name) {
- return ldb_next_named_lock(module, name);
-}
+ switch (req->operation) {
-static int schema_named_unlock(struct ldb_module *module, const char *name) {
- return ldb_next_named_unlock(module, name);
-}
+ case LDB_REQ_ADD:
+ return schema_add(module, req);
-/* return extended error information */
-static const char *schema_errstring(struct ldb_module *module)
-{
- struct private_data *data = (struct private_data *)module->private_data;
+ case LDB_REQ_MODIFY:
+ return schema_modify(module, req);
- if (data->error_string) {
- const char *error;
+ default:
+ return ldb_next_request(module, req);
- error = data->error_string;
- data->error_string = NULL;
- return error;
}
-
- return ldb_next_errstring(module);
-}
-
-static int schema_destructor(void *module_ctx)
-{
-/* struct ldb_module *ctx = module_ctx; */
- /* put your clean-up functions here */
- return 0;
}
static const struct ldb_module_ops schema_ops = {
- "schema",
- schema_search,
- schema_search_free,
- schema_add_record,
- schema_modify_record,
- schema_delete_record,
- schema_rename_record,
- schema_named_lock,
- schema_named_unlock,
- schema_errstring,
+ .name = "schema",
+ .request = schema_request
};
-#ifdef HAVE_DLOPEN_DISABLED
-struct ldb_module *init_module(struct ldb_context *ldb, const char *options[])
-#else
struct ldb_module *schema_module_init(struct ldb_context *ldb, const char *options[])
-#endif
{
struct ldb_module *ctx;
- struct private_data *data;
ctx = talloc(ldb, struct ldb_module);
if (!ctx) {
return NULL;
}
- data = talloc(ctx, struct private_data);
- if (data == NULL) {
- talloc_free(ctx);
- return NULL;
- }
-
- data->error_string = NULL;
- ctx->private_data = data;
+ ctx->private_data = NULL;
ctx->ldb = ldb;
ctx->prev = ctx->next = NULL;
ctx->ops = &schema_ops;
- talloc_set_destructor (ctx, schema_destructor);
-
return ctx;
}