diff options
author | Jelmer Vernooij <jelmer@samba.org> | 2008-09-12 21:31:56 +0200 |
---|---|---|
committer | Jelmer Vernooij <jelmer@samba.org> | 2008-09-12 21:31:56 +0200 |
commit | 218a1c8a671ef84614b7b36bbb67ef4b3589c4dc (patch) | |
tree | 425c8e8fa733d8f39cb6531fea882521fee9011b /source4 | |
parent | fc23663f4b830709b65e03185a78ed917970b2b5 (diff) | |
parent | e4412a0470b18ea9e605f2afb00c23609102d59c (diff) | |
download | samba-218a1c8a671ef84614b7b36bbb67ef4b3589c4dc.tar.gz samba-218a1c8a671ef84614b7b36bbb67ef4b3589c4dc.tar.bz2 samba-218a1c8a671ef84614b7b36bbb67ef4b3589c4dc.zip |
Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into manpage
(This used to be commit eff27744d3dcb4f6bcdf9bd03583bb38634c398d)
Diffstat (limited to 'source4')
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/config.mk | 11 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/schema.c | 1230 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/schema_syntax.c | 469 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/schema_syntax.h | 71 | ||||
-rw-r--r-- | source4/dsdb/schema/schema_set.c | 36 | ||||
-rwxr-xr-x | source4/lib/ldb/tests/python/api.py | 62 | ||||
-rwxr-xr-x | source4/lib/ldb/tests/test-generic.sh | 2 |
7 files changed, 45 insertions, 1836 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/config.mk b/source4/dsdb/samdb/ldb_modules/config.mk index 830f7c9fa1..00e4f1af92 100644 --- a/source4/dsdb/samdb/ldb_modules/config.mk +++ b/source4/dsdb/samdb/ldb_modules/config.mk @@ -204,17 +204,6 @@ INIT_FUNCTION = LDB_MODULE(partition) ldb_partition_OBJ_FILES = $(dsdbsrcdir)/samdb/ldb_modules/partition.o ################################################ -# Start MODULE ldb_schema -[MODULE::ldb_schema] -SUBSYSTEM = LIBLDB -PRIVATE_DEPENDENCIES = LIBTALLOC LIBEVENTS LIBLDB -INIT_FUNCTION = LDB_MODULE(schema) -# End MODULE ldb_schema -################################################ - -ldb_schema_OBJ_FILES = $(addprefix $(dsdbsrcdir)/samdb/ldb_modules/, schema.o schema_syntax.o) - -################################################ # Start MODULE ldb_update_kt [MODULE::ldb_update_keytab] SUBSYSTEM = LIBLDB diff --git a/source4/dsdb/samdb/ldb_modules/schema.c b/source4/dsdb/samdb/ldb_modules/schema.c deleted file mode 100644 index f2c4d38305..0000000000 --- a/source4/dsdb/samdb/ldb_modules/schema.c +++ /dev/null @@ -1,1230 +0,0 @@ -/* - ldb database library - - Copyright (C) Simo Sorce 2004-2006 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -/* - * Name: ldb - * - * Component: ldb schema module - * - * Description: add schema check functionality - * - * Author: Simo Sorce - */ - -#include "includes.h" -#include "libcli/ldap/ldap.h" -#include "ldb/include/ldb_errors.h" -#include "ldb/include/ldb_private.h" -#include "lib/util/dlinklist.h" -#include "schema_syntax.h" - -/* Syntax-Table - - see ldap_server/devdocs/AD-syntaxes.txt -*/ - -enum schema_class_type { - SCHEMA_CT_88 = 0, - SCHEMA_CT_STRUCTURAL = 1, - SCHEMA_CT_ABSTRACT = 2, - SCHEMA_CT_AUXILIARY = 3 -}; - -struct schema_attribute { - char *OID; /* attributeID */ - char *name; /* lDAPDisplayName */ - enum schema_internal_syntax syntax; /* generated from attributeSyntax, oMSyntax, oMObjectClass */ - bool single; /* isSingleValued */ - int min; /* rangeLower */ - int max; /* rangeUpper */ - int systemflag; /* systemFlag */ - int searchflag; /* searchFlag */ - bool isdefunct; /* isDefunct */ -}; - -struct schema_class { - char *OID; /* governsID */ - char *name; /* lDAPDisplayName */ - enum schema_class_type type; /* objectClassCategory */ - bool systemOnly; /* systemOnly */ - bool isdefunct; /* isDefunct */ - int systemflag; /* systemFlag */ - char *defobjcat; /* defaultObjectCategory */ - struct schema_class *parent; /* subClassOf */ - struct schema_class **sysaux; /* systemAuxiliaryClass */ - struct schema_class **aux; /* auxiliaryClass */ - struct schema_class **sysposssup; /* systemPossSuperiors */ - struct schema_class **posssup; /* possSuperiors */ - struct schema_class **possinf; /* possibleInferiors */ - struct schema_attribute **sysmust; /* systemMustContain */ - struct schema_attribute **must; /* MustContain */ - struct schema_attribute **sysmay; /* systemMayContain */ - struct schema_attribute **may; /* MayContain */ -}; - -/* TODO: ditcontentrules */ - -struct schema_private_data { - struct ldb_dn *schema_dn; - struct schema_attribute **attrs; - struct schema_store *attrs_store; - int num_attributes; - struct schema_class **class; - struct schema_store *class_store; - int num_classes; -}; - -struct schema_class_dlist { - struct schema_class *class; - struct schema_class_dlist *prev; - struct schema_class_dlist *next; - enum schema_class_type role; -}; - -struct schema_context { - - enum sc_op { SC_ADD, SC_MOD, SC_DEL, SC_RENAME } op; - enum sc_step { SC_INIT, SC_ADD_CHECK_PARENT, SC_ADD_TEMP, SC_DEL_CHECK_CHILDREN } step; - - struct schema_private_data *data; - - struct ldb_module *module; - struct ldb_request *orig_req; - struct ldb_request *down_req; - - struct ldb_request *parent_req; - struct ldb_reply *parent_res; - - struct schema_class_dlist *class_list; - struct schema_class **sup_list; - struct schema_class **aux_list; -}; - -/* FIXME: I'd really like to use an hash table here */ -struct schema_link { - const char *name; - void *object; -}; - -struct schema_store { - struct schema_link *store; - int num_links; -}; - -static struct schema_store *schema_store_new(TALLOC_CTX *mem_ctx) -{ - struct schema_store *ht; - - ht = talloc(mem_ctx, struct schema_store); - if (!ht) return NULL; - - ht->store = NULL; - ht->num_links = 0; - - return ht; -} - -static int schema_store_add(struct schema_store *ht, const char *key, void *object) -{ - ht->store = talloc_realloc(ht, ht->store, struct schema_link, ht->num_links + 1); - if (!ht->store) return LDB_ERR_OPERATIONS_ERROR; - - ht->store[ht->num_links].name = key; - ht->store[ht->num_links].object = object; - - ht->num_links++; - - return LDB_SUCCESS; -} - -static void *schema_store_find(struct schema_store *ht, const char *key) -{ - int i; - - for (i = 0; i < ht->num_links; i++) { - if (strcasecmp(ht->store[i].name, key) == 0) { - return ht->store[i].object; - } - } - - return NULL; -} - -#define SCHEMA_CHECK_VALUE(mem, val, mod) \ - do { if (mem == val) { \ - ret = LDB_ERR_OPERATIONS_ERROR; \ - ldb_asprintf_errstring(mod->ldb, \ - "schema module: Memory allocation or attribute error on %s", #mem); \ - goto done; } } while(0) - -struct schema_class **schema_get_class_list(struct ldb_module *module, - struct schema_private_data *data, - struct ldb_message_element *el) -{ - struct schema_class **list; - int i; - - list = talloc_array(data, struct schema_class *, el->num_values + 1); - if (!list) { - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Out of Memory"); - return NULL; - } - - for (i = 0; i < el->num_values; i++) { - list[i] = (struct schema_class *)schema_store_find(data->class_store, - (char *)el->values[i].data); - if (!list[i]) { - ldb_debug_set(module->ldb, - LDB_DEBUG_ERROR, - "Class %s referenced but not found in schema\n", - (char *)el->values[i].data); - return NULL; - } - } - list[i] = NULL; - - return list; -} - -struct schema_attribute **schema_get_attrs_list(struct ldb_module *module, - struct schema_private_data *data, - struct ldb_message_element *el) -{ - struct schema_attribute **list; - int i; - - list = talloc_array(data, struct schema_attribute *, el->num_values + 1); - if (!list) { - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Out of Memory"); - return NULL; - } - - for (i = 0; i < el->num_values; i++) { - list[i] = (struct schema_attribute *)schema_store_find(data->attrs_store, - (char *)el->values[i].data); - if (!list[i]) { - ldb_debug_set(module->ldb, - LDB_DEBUG_ERROR, - "Attriobute %s referenced but not found in schema\n", - (char *)el->values[i].data); - return NULL; - } - } - list[i] = NULL; - - return list; -} - -static int schema_init_attrs(struct ldb_module *module, struct schema_private_data *data) -{ - static const char *schema_attrs[] = { "attributeID", - "lDAPDisplayName", - "attributeSyntax", - "oMSyntax", - "oMObjectClass", - "isSingleValued", - "rangeLower", - "rangeUpper", - "searchFlag", - "systemFlag", - "isDefunct", - NULL }; - struct ldb_result *res; - int ret, i; - - ret = ldb_search(module->ldb, - data->schema_dn, - LDB_SCOPE_SUBTREE, - "(objectClass=attributeSchema)", - schema_attrs, - &res); - - if (ret != LDB_SUCCESS) { - goto done; - } - - data->num_attributes = res->count; - data->attrs = talloc_array(data, struct schema_attribute *, res->count); - SCHEMA_CHECK_VALUE(data->attrs, NULL, module); - - data->attrs_store = schema_store_new(data); - SCHEMA_CHECK_VALUE(data->attrs_store, NULL, module); - - for (i = 0; i < res->count; i++) { - const char *tmp_single; - const char *attr_syntax; - uint32_t om_syntax; - const struct ldb_val *om_class; - - data->attrs[i] = talloc(data->attrs, struct schema_attribute); - SCHEMA_CHECK_VALUE(data->attrs[i], NULL, module); - - data->attrs[i]->OID = talloc_strdup(data->attrs[i], - ldb_msg_find_attr_as_string(res->msgs[i], "attributeID", NULL)); - SCHEMA_CHECK_VALUE(data->attrs[i]->OID, NULL, module); - - data->attrs[i]->name = talloc_strdup(data->attrs[i], - ldb_msg_find_attr_as_string(res->msgs[i], "lDAPDisplayName", NULL)); - SCHEMA_CHECK_VALUE(data->attrs[i]->name, NULL, module); - - /* once we have both the OID and the attribute name, add the pointer to the store */ - schema_store_add(data->attrs_store, data->attrs[i]->OID, data->attrs[i]); - schema_store_add(data->attrs_store, data->attrs[i]->name, data->attrs[i]); - - attr_syntax = ldb_msg_find_attr_as_string(res->msgs[i], "attributeSyntax", NULL); - SCHEMA_CHECK_VALUE(attr_syntax, NULL, module); - - om_syntax = ldb_msg_find_attr_as_uint(res->msgs[i], "oMSyntax", 0); - /* 0 is not a valid oMSyntax */ - SCHEMA_CHECK_VALUE(om_syntax, 0, module); - - om_class = ldb_msg_find_ldb_val(res->msgs[i], "oMObjectClass"); - - ret = map_schema_syntax(om_syntax, attr_syntax, om_class, &data->attrs[i]->syntax); - if (ret != LDB_SUCCESS) { - ldb_asprintf_errstring(module->ldb, - "schema module: invalid om syntax value on %s", - data->attrs[i]->name); - goto done; - } - - tmp_single = ldb_msg_find_attr_as_string(res->msgs[i], "isSingleValued", NULL); - SCHEMA_CHECK_VALUE(tmp_single, NULL, module); - if (strcmp(tmp_single, "TRUE") == 0) { - data->attrs[i]->single = 1; - } else { - data->attrs[i]->single = 0; - } - - /* the following are optional */ - data->attrs[i]->min = ldb_msg_find_attr_as_int(res->msgs[i], "rangeLower", INT_MIN); - data->attrs[i]->max = ldb_msg_find_attr_as_int(res->msgs[i], "rangeUpper", INT_MAX); - data->attrs[i]->systemflag = ldb_msg_find_attr_as_int(res->msgs[i], "systemFlag", 0); - data->attrs[i]->searchflag = ldb_msg_find_attr_as_int(res->msgs[i], "searchFlag", 0); - data->attrs[i]->isdefunct = ldb_msg_find_attr_as_bool(res->msgs[i], "isDefunct", false); - } - -done: - talloc_free(res); - return ret; -} - -static int schema_init_classes(struct ldb_module *module, struct schema_private_data *data) -{ - const char *schema_attrs[] = { "governsID", - "lDAPDisplayName", - "objectClassCategory", - "defaultObjectCategory", - "systemOnly", - "systemFlag", - "isDefunct", - "subClassOf", - "systemAuxiliaryClass", - "auxiliaryClass", - "systemPossSuperiors", - "possSuperiors", - "possibleInferiors", - "systemMustContain", - "MustContain", - "systemMayContain", - "MayContain", - NULL }; - struct ldb_result *res; - int ret, i; - - ret = ldb_search(module->ldb, - data->schema_dn, - LDB_SCOPE_SUBTREE, - "(objectClass=classSchema)", - schema_attrs, - &res); - - if (ret != LDB_SUCCESS) { - goto done; - } - - data->num_classes = res->count; - data->class = talloc_array(data, struct schema_class *, res->count); - SCHEMA_CHECK_VALUE(data->class, NULL, module); - - data->class_store = schema_store_new(data); - SCHEMA_CHECK_VALUE(data->class_store, NULL, module); - - for (i = 0; i < res->count; i++) { - struct ldb_message_element *el; - - data->class[i] = talloc(data->class, struct schema_class); - SCHEMA_CHECK_VALUE(data->class[i], NULL, module); - - data->class[i]->OID = talloc_strdup(data->class[i], - ldb_msg_find_attr_as_string(res->msgs[i], "governsID", NULL)); - SCHEMA_CHECK_VALUE(data->class[i]->OID, NULL, module); - - data->class[i]->name = talloc_strdup(data->class[i], - ldb_msg_find_attr_as_string(res->msgs[i], "lDAPDisplayName", NULL)); - SCHEMA_CHECK_VALUE(data->class[i]->name, NULL, module); - - /* once we have both the OID and the class name, add the pointer to the store */ - schema_store_add(data->class_store, data->class[i]->OID, data->class[i]); - schema_store_add(data->class_store, data->class[i]->name, data->class[i]); - - data->class[i]->type = ldb_msg_find_attr_as_int(res->msgs[i], "objectClassCategory", -1); - /* 0 should not be a valid value, but turn out it is so test with -1 */ - SCHEMA_CHECK_VALUE(data->class[i]->type, -1, module); - - data->class[i]->defobjcat = talloc_strdup(data->class[i], - ldb_msg_find_attr_as_string(res->msgs[i], - "defaultObjectCategory", NULL)); -/* SCHEMA_CHECK_VALUE(data->class[i]->defobjcat, NULL, module); -*/ - /* the following attributes are all optional */ - - data->class[i]->systemOnly = ldb_msg_find_attr_as_bool(res->msgs[i], "systemOnly", false); - data->class[i]->systemflag = ldb_msg_find_attr_as_int(res->msgs[i], "systemFlag", 0); - data->class[i]->isdefunct = ldb_msg_find_attr_as_bool(res->msgs[i], "isDefunct", false); - - /* attributes are loaded first, so we can just go an query the attributes repo */ - - el = ldb_msg_find_element(res->msgs[i], "systemMustContain"); - if (el) { - data->class[i]->sysmust = schema_get_attrs_list(module, data, el); - SCHEMA_CHECK_VALUE(data->class[i]->sysmust, NULL, module); - } - - el = ldb_msg_find_element(res->msgs[i], "MustContain"); - if (el) { - data->class[i]->must = schema_get_attrs_list(module, data, el); - SCHEMA_CHECK_VALUE(data->class[i]->must, NULL, module); - } - - el = ldb_msg_find_element(res->msgs[i], "systemMayContain"); - if (el) { - data->class[i]->sysmay = schema_get_attrs_list(module, data, el); - SCHEMA_CHECK_VALUE(data->class[i]->sysmay, NULL, module); - } - - el = ldb_msg_find_element(res->msgs[i], "MayContain"); - if (el) { - data->class[i]->may = schema_get_attrs_list(module, data, el); - SCHEMA_CHECK_VALUE(data->class[i]->may, NULL, module); - } - - } - - /* subClassOf, systemAuxiliaryClass, auxiliaryClass, systemPossSuperiors - * must be filled in a second loop, when all class objects are allocated - * or we may not find a class that has not yet been parsed */ - for (i = 0; i < res->count; i++) { - struct ldb_message_element *el; - const char *attr; - - /* this is single valued anyway */ - attr = ldb_msg_find_attr_as_string(res->msgs[i], "subClassOf", NULL); - SCHEMA_CHECK_VALUE(attr, NULL, module); - data->class[i]->parent = schema_store_find(data->class_store, attr); - SCHEMA_CHECK_VALUE(data->class[i]->parent, NULL, module); - - /* the following attributes are all optional */ - - data->class[i]->sysaux = NULL; - el = ldb_msg_find_element(res->msgs[i], "systemAuxiliaryClass"); - if (el) { - data->class[i]->sysaux = schema_get_class_list(module, data, el); - SCHEMA_CHECK_VALUE(data->class[i]->sysaux, NULL, module); - } - - data->class[i]->aux = NULL; - el = ldb_msg_find_element(res->msgs[i], "auxiliaryClass"); - if (el) { - data->class[i]->aux = schema_get_class_list(module, data, el); - SCHEMA_CHECK_VALUE(data->class[i]->aux, NULL, module); - } - - data->class[i]->sysposssup = NULL; - el = ldb_msg_find_element(res->msgs[i], "systemPossSuperiors"); - if (el) { - data->class[i]->sysposssup = schema_get_class_list(module, data, el); - SCHEMA_CHECK_VALUE(data->class[i]->sysposssup, NULL, module); - } - - data->class[i]->posssup = NULL; - el = ldb_msg_find_element(res->msgs[i], "possSuperiors"); - if (el) { - data->class[i]->posssup = schema_get_class_list(module, data, el); - SCHEMA_CHECK_VALUE(data->class[i]->posssup, NULL, module); - } - - data->class[i]->possinf = NULL; - el = ldb_msg_find_element(res->msgs[i], "possibleInferiors"); - if (el) { - data->class[i]->possinf = schema_get_class_list(module, data, el); - SCHEMA_CHECK_VALUE(data->class[i]->possinf, NULL, module); - } - } - -done: - talloc_free(res); - return ret; -} - -static struct ldb_handle *schema_init_handle(struct ldb_request *req, struct ldb_module *module, enum sc_op op) -{ - struct schema_context *sctx; - struct ldb_handle *h; - - h = talloc_zero(req, struct ldb_handle); - if (h == NULL) { - ldb_set_errstring(module->ldb, "Out of Memory"); - return NULL; - } - - h->module = module; - - sctx = talloc_zero(h, struct schema_context); - if (sctx == NULL) { - ldb_set_errstring(module->ldb, "Out of Memory"); - talloc_free(h); - return NULL; - } - - h->private_data = (void *)sctx; - - h->state = LDB_ASYNC_INIT; - h->status = LDB_SUCCESS; - - sctx->op = op; - sctx->step = SC_INIT; - sctx->data = module->private_data; - sctx->module = module; - sctx->orig_req = req; - - return h; -} - -static int schema_add_check_parent(struct ldb_context *ldb, void *context, struct ldb_reply *ares) -{ - struct schema_context *sctx; - - sctx = talloc_get_type(context, struct schema_context); - - /* we are interested only in the single reply (base search) we receive here */ - if (ares->type == LDB_REPLY_ENTRY) { - if (sctx->parent_res != NULL) { - ldb_set_errstring(ldb, "Too many results"); - talloc_free(ares); - return LDB_ERR_OPERATIONS_ERROR; - } - sctx->parent_res = talloc_steal(sctx, ares); - } else { - talloc_free(ares); - } - - return LDB_SUCCESS; -} - -static int schema_add_build_parent_req(struct schema_context *sctx) -{ - const char * const parent_attrs[] = { "objectClass", NULL }; - int ret; - - sctx->parent_req = talloc_zero(sctx, struct ldb_request); - if (sctx->parent_req == NULL) { - ldb_debug(sctx->module->ldb, LDB_DEBUG_ERROR, "Out of Memory!\n"); - return LDB_ERR_OPERATIONS_ERROR; - } - - sctx->parent_req->operation = LDB_SEARCH; - sctx->parent_req->op.search.scope = LDB_SCOPE_BASE; - sctx->parent_req->op.search.base = ldb_dn_get_parent(sctx->parent_req, sctx->orig_req->op.add.message->dn); - sctx->parent_req->op.search.tree = ldb_parse_tree(sctx->parent_req, "(objectClass=*)"); - sctx->parent_req->op.search.attrs = parent_attrs; - sctx->parent_req->controls = NULL; - sctx->parent_req->context = sctx; - sctx->parent_req->callback = schema_add_check_parent; - ret = ldb_set_timeout_from_prev_req(sctx->module->ldb, sctx->orig_req, sctx->parent_req); - - return ret; -} - -static struct schema_class_dlist *schema_add_get_dlist_entry_with_class(struct schema_class_dlist *list, struct schema_class *class) -{ - struct schema_class_dlist *temp; - - for (temp = list; temp && (temp->class != class); temp = temp->next) /* noop */ ; - return temp; -} - -static int schema_add_class_to_dlist(struct schema_class_dlist *list, struct schema_class *class, enum schema_class_type role) -{ - struct schema_class_dlist *entry; - struct schema_class_dlist *temp; - int ret; - - /* see if this class is usable */ - if (class->isdefunct) { - return LDB_ERR_NO_SUCH_ATTRIBUTE; - } - - /* see if this class already exist in the class list */ - if (schema_add_get_dlist_entry_with_class(list, class)) { - return LDB_SUCCESS; - } - - /* this is a new class go on and add to the list */ - entry = talloc_zero(list, struct schema_class_dlist); - if (!entry) return LDB_ERR_OPERATIONS_ERROR; - entry->class = class; - entry->role = class->type; - - /* If parent is top (list is guaranteed to start always with top) */ - if (class->parent == list->class) { - /* if the hierarchy role is structural try to add it just after top */ - if (role == SCHEMA_CT_STRUCTURAL) { - /* but check no other class at after top has a structural role */ - if (list->next && (list->next->role == SCHEMA_CT_STRUCTURAL)) { - return LDB_ERR_OBJECT_CLASS_VIOLATION; - } - DLIST_ADD_AFTER(list, entry, list); - } else { - DLIST_ADD_END(list, entry, struct schema_class_dlist *); - } - return LDB_SUCCESS; - } - - /* search if parent has already been added */ - temp = schema_add_get_dlist_entry_with_class(list->next, class->parent); - if (temp == NULL) { - ret = schema_add_class_to_dlist(list, class->parent, role); - if (ret != LDB_SUCCESS) { - return ret; - } - temp = schema_add_get_dlist_entry_with_class(list->next, class->parent); - } - if (!temp) { /* parent not found !? */ - return LDB_ERR_OPERATIONS_ERROR; - } - - DLIST_ADD_AFTER(list, entry, temp); - if (role == SCHEMA_CT_STRUCTURAL || role == SCHEMA_CT_AUXILIARY) { - temp = entry; - do { - temp->role = role; - temp = temp->prev; - /* stop when hierarchy base is met or when base class parent is top */ - } while (temp->class == temp->next->class->parent && - temp->next->class->parent != list->class); - - /* if we have not reached the head of the list - * and role is structural */ - if (temp != list && role == SCHEMA_CT_STRUCTURAL) { - struct schema_class_dlist *hfirst, *hlast; - - /* check if the list second entry is structural */ - if (list->next->role == SCHEMA_CT_STRUCTURAL) { - /* we have a confilict here */ - return LDB_ERR_OBJECT_CLASS_VIOLATION; - } - /* we have to move this hierarchy of classes - * so that the base of the structural hierarchy is right after top */ - - hfirst = temp->next; - hlast = entry; - /* now hfirst - hlast are the boundaries of the structural hierarchy */ - - /* extract the structural hierachy from the list */ - hfirst->prev->next = hlast->next; - if (hlast->next) hlast->next->prev = hfirst->prev; - - /* insert the structural hierarchy just after top */ - list->next->prev = hlast; - hlast->next = list->next; - list->next = hfirst; - hfirst->prev = list; - } - } - - return LDB_SUCCESS; -} - -/* merge source list into dest list and remove duplicates */ -static int schema_merge_class_list(TALLOC_CTX *mem_ctx, struct schema_class ***dest, struct schema_class **source) -{ - struct schema_class **list = *dest; - int i, j, n, f; - - n = 0; - if (list) for (n = 0; list[n]; n++) /* noop */ ; - f = n; - - for (i = 0; source[i]; i++) { - for (j = 0; j < f; j++) { - if (list[j] == source[i]) { - break; - } - } - if (j < f) { /* duplicate found */ - continue; - } - - list = talloc_realloc(mem_ctx, list, struct schema_class *, n + 2); - if (!list) { - return LDB_ERR_OPERATIONS_ERROR; - } - list[n] = source[i]; - n++; - list[n] = NULL; - } - - *dest = list; - - return LDB_SUCCESS; -} - -/* validate and modify the objectclass attribute to sort and add parents */ -static int schema_add_build_objectclass_list(struct schema_context *sctx) -{ - struct schema_class_dlist *temp; - struct ldb_message_element * el; - struct schema_class *class; - int ret, i, an; - - /* First of all initialize list, it must start with class top */ - sctx->class_list = talloc_zero(sctx, struct schema_class_dlist); - if (!sctx->class_list) return LDB_ERR_OPERATIONS_ERROR; - - sctx->class_list->class = schema_store_find(sctx->data->class_store, "top"); - if (!sctx->class_list->class) return LDB_ERR_OPERATIONS_ERROR; - - el = ldb_msg_find_element(sctx->orig_req->op.add.message, "objectClass"); - if (!el) { - return LDB_ERR_OBJECT_CLASS_VIOLATION; - } - - for (i = 0; i < el->num_values; i++) { - - class = schema_store_find(sctx->data->class_store, (char *)el->values[i].data); - if (!class) { - return LDB_ERR_NO_SUCH_ATTRIBUTE; - } - - ret = schema_add_class_to_dlist(sctx->class_list, class, class->type); - if (ret != LDB_SUCCESS) { - return ret; - } - } - - /* now check if there is any class role that is still not STRUCTURAL or AUXILIARY */ - /* build also the auxiliary class list and the possible superiors list */ - temp = sctx->class_list->next; /* top is special, skip it */ - an = 0; - - while (temp) { - if (temp->role == SCHEMA_CT_ABSTRACT || temp->role == SCHEMA_CT_88) { - return LDB_ERR_OBJECT_CLASS_VIOLATION; - } - if (temp->class->sysaux) { - ret = schema_merge_class_list(sctx, &sctx->aux_list, temp->class->sysaux); - if (ret != LDB_SUCCESS) { - return LDB_ERR_OPERATIONS_ERROR; - } - } - if (temp->class->aux) { - ret = schema_merge_class_list(sctx, &sctx->aux_list, temp->class->aux); - if (ret != LDB_SUCCESS) { - return LDB_ERR_OPERATIONS_ERROR; - } - } - if (temp->class->sysposssup) { - ret = schema_merge_class_list(sctx, &sctx->sup_list, temp->class->sysposssup); - if (ret != LDB_SUCCESS) { - return LDB_ERR_OPERATIONS_ERROR; - } - } - if (temp->class->posssup) { - ret = schema_merge_class_list(sctx, &sctx->sup_list, temp->class->posssup); - if (ret != LDB_SUCCESS) { - return LDB_ERR_OPERATIONS_ERROR; - } - } - temp = temp->next; - } - - /* complete sup_list with material from the aux classes */ - for (i = 0; sctx->aux_list && sctx->aux_list[i]; i++) { - if (sctx->aux_list[i]->sysposssup) { - ret = schema_merge_class_list(sctx, &sctx->sup_list, sctx->aux_list[i]->sysposssup); - if (ret != LDB_SUCCESS) { - return LDB_ERR_OPERATIONS_ERROR; - } - } - if (sctx->aux_list[i]->posssup) { - ret = schema_merge_class_list(sctx, &sctx->sup_list, sctx->aux_list[i]->posssup); - if (ret != LDB_SUCCESS) { - return LDB_ERR_OPERATIONS_ERROR; - } - } - } - - if (!sctx->sup_list) return LDB_ERR_NAMING_VIOLATION; - - return LDB_SUCCESS; -} - -static int schema_add_check_container_constraints(struct schema_context *sctx) -{ - struct schema_class **parent_possinf = NULL; - struct schema_class **parent_classes; - struct schema_class_dlist *temp; - struct ldb_message_element *el; - int i, j, ret; - - el = ldb_msg_find_element(sctx->parent_res->message, "objectClass"); - if (!el) { - /* what the .. */ - return LDB_ERR_OPERATIONS_ERROR; - } - - parent_classes = talloc_array(sctx, struct schema_class *, el->num_values + 1); - - for (i = 0; i < el->num_values; i++) { - - parent_classes[i] = schema_store_find(sctx->data->class_store, (const char *)el->values[i].data); - if (!parent_classes[i]) { /* should not be possible */ - return LDB_ERR_OPERATIONS_ERROR; - } - - if (parent_classes[i]->possinf) { - ret = schema_merge_class_list(sctx, &parent_possinf, parent_classes[i]->possinf); - if (ret != LDB_SUCCESS) { - return LDB_ERR_OPERATIONS_ERROR; - } - } - - /* check also embedded auxiliary classes possinf */ - for (j = 0; parent_classes[i]->sysaux && parent_classes[i]->sysaux[j]; j++) { - if (parent_classes[i]->sysaux[j]->possinf) { - ret = schema_merge_class_list(sctx, &parent_possinf, parent_classes[i]->sysaux[j]->possinf); - if (ret != LDB_SUCCESS) { - return LDB_ERR_OPERATIONS_ERROR; - } - } - } - for (j = 0; parent_classes[i]->aux && parent_classes[i]->aux[j]; j++) { - if (parent_classes[i]->aux[j]->possinf) { - ret = schema_merge_class_list(sctx, &parent_possinf, parent_classes[i]->aux[j]->possinf); - if (ret != LDB_SUCCESS) { - return LDB_ERR_OPERATIONS_ERROR; - } - } - } - } - - /* foreach parent objectclass, - * check parent possible inferiors match all of the child objectclasses - * and that - * poss Superiors of the child objectclasses mathes one of the parent classes - */ - - temp = sctx->class_list->next; /* skip top it is special */ - while (temp) { - - for (i = 0; parent_possinf[i]; i++) { - if (temp->class == parent_possinf[i]) { - break; - } - } - if (parent_possinf[i] == NULL) { - /* class not found in possible inferiors */ - return LDB_ERR_NAMING_VIOLATION; - } - - temp = temp->next; - } - - for (i = 0; parent_classes[i]; i++) { - for (j = 0; sctx->sup_list[j]; j++) { - if (sctx->sup_list[j] == parent_classes[i]) { - break; - } - } - if (sctx->sup_list[j]) { /* possible Superiors match one of the parent classes */ - return LDB_SUCCESS; - } - } - - /* no parent classes matched superiors */ - return LDB_ERR_NAMING_VIOLATION; -} - -static int schema_add_build_down_req(struct schema_context *sctx) -{ - struct schema_class_dlist *temp; - struct ldb_message *msg; - int ret; - - sctx->down_req = talloc(sctx, struct ldb_request); - if (!sctx->down_req) { - ldb_set_errstring(sctx->module->ldb, "Out of memory!"); - return LDB_ERR_OPERATIONS_ERROR; - } - - *(sctx->down_req) = *(sctx->orig_req); /* copy the request */ - msg = ldb_msg_copy_shallow(sctx->down_req, sctx->orig_req->op.add.message); - if (!msg) { - ldb_set_errstring(sctx->module->ldb, "Out of memory!"); - return LDB_ERR_OPERATIONS_ERROR; - } - - /* rebuild the objectclass list */ - ldb_msg_remove_attr(msg, "objectClass"); - ret = ldb_msg_add_empty(msg, "objectClass", 0, NULL); - if (ret != LDB_SUCCESS) { - return ret; - } - - /* Add the complete list of classes back to the message */ - for (temp = sctx->class_list; temp; temp = temp->next) { - ret = ldb_msg_add_string(msg, "objectClass", temp->class->name); - if (ret != LDB_SUCCESS) { - return ret; - } - } - - /* objectCategory can be set only by the system */ - if (ldb_msg_find_element(msg, "objectCategory")) { - return LDB_ERR_CONSTRAINT_VIOLATION; - } - - /* the OC is mandatory, every class defines it */ - /* use the one defined in the structural class that defines the object */ - for (temp = sctx->class_list->next; temp; temp = temp->next) { - if (!temp->next) break; - if (temp->next->role != SCHEMA_CT_STRUCTURAL) break; - } -/* oc = talloc_strdup(msg, temp->class->defobjcat); - ret = ldb_msg_add_string(msg, "objectCategory", oc); -*/ - sctx->down_req->op.add.message = msg; - - return LDB_SUCCESS; -} - -static int schema_check_attributes_syntax(struct schema_context *sctx) -{ - struct ldb_message *msg; - struct schema_attribute *attr; - int i, ret; - - msg = sctx->orig_req->op.add.message; - for (i = 0; i < msg->num_elements; i++) { - attr = schema_store_find(sctx->data->attrs_store, msg->elements[i].name); - if (attr == NULL) { - return LDB_ERR_NO_SUCH_ATTRIBUTE; - } - ret = schema_validate(sctx->module->ldb, &msg->elements[i], attr->syntax, attr->single, attr->min, attr->max); - if (ret != LDB_SUCCESS) { - return ret; - } - } - - return LDB_SUCCESS; -} - -static int schema_add_continue(struct ldb_handle *h) -{ - struct schema_context *sctx; - int ret; - - sctx = talloc_get_type(h->private_data, struct schema_context); - - switch (sctx->step) { - case SC_INIT: - - /* First of all check that a parent exists for this entry */ - ret = schema_add_build_parent_req(sctx); - if (ret != LDB_SUCCESS) { - break; - } - - sctx->step = SC_ADD_CHECK_PARENT; - return ldb_next_request(sctx->module, sctx->parent_req); - - case SC_ADD_CHECK_PARENT: - - /* parent search done, check result and go on */ - if (sctx->parent_res == NULL) { - /* we must have a parent */ - ret = LDB_ERR_NO_SUCH_OBJECT; - break; - } - - /* Check objectclasses are ok */ - ret = schema_add_build_objectclass_list(sctx); - if (ret != LDB_SUCCESS) { - break; - } - - /* check the parent is of the right type for this object */ - ret = schema_add_check_container_constraints(sctx); - if (ret != LDB_SUCCESS) { - break; - } - - /* check attributes syntax */ - - ret = schema_check_attributes_syntax(sctx); - if (ret != LDB_SUCCESS) { - break; - } - - ret = schema_add_build_down_req(sctx); - if (ret != LDB_SUCCESS) { - break; - } - sctx->step = SC_ADD_TEMP; - - return ldb_next_request(sctx->module, sctx->down_req); - - default: - ret = LDB_ERR_OPERATIONS_ERROR; - break; - } - - /* this is reached only in case of error */ - /* FIXME: fire an async reply ? */ - h->status = ret; - h->state = LDB_ASYNC_DONE; - return ret; -} - -static int schema_add(struct ldb_module *module, struct ldb_request *req) -{ - struct schema_context *sctx; - struct ldb_handle *h; - - if (ldb_dn_is_special(req->op.add.message->dn)) { /* do not manipulate our control entries */ - return ldb_next_request(module, req); - } - - h = schema_init_handle(req, module, SC_ADD); - if (!h) { - return LDB_ERR_OPERATIONS_ERROR; - } - - sctx = talloc_get_type(h->private_data, struct schema_context); - sctx->orig_req->handle = h; - return schema_add_continue(h); -} - - -static int schema_modify(struct ldb_module *module, struct ldb_request *req) -{ - if (ldb_dn_is_special(req->op.mod.message->dn)) { /* do not manipulate our control entries */ - return ldb_next_request(module, req); - } - - return ldb_next_request(module, req); -} - -static int schema_delete(struct ldb_module *module, struct ldb_request *req) -{ - if (ldb_dn_is_special(req->op.del.dn)) { /* do not manipulate our control entries */ - return ldb_next_request(module, req); - } - - /* First of all check no children exists for this entry */ - - return ldb_next_request(module, req); -} - -static int schema_rename(struct ldb_module *module, struct ldb_request *req) -{ - if (ldb_dn_is_special(req->op.rename.olddn) && - ldb_dn_is_special(req->op.rename.newdn)) { /* do not manipulate our control entries */ - return ldb_next_request(module, req); - } - - return ldb_next_request(module, req); -} - -static int schema_wait_loop(struct ldb_handle *handle) { - struct schema_context *sctx; - int ret; - - if (!handle || !handle->private_data) { - return LDB_ERR_OPERATIONS_ERROR; - } - - if (handle->state == LDB_ASYNC_DONE) { - return handle->status; - } - - handle->state = LDB_ASYNC_PENDING; - handle->status = LDB_SUCCESS; - - sctx = talloc_get_type(handle->private_data, struct schema_context); - - switch (sctx->step) { - case SC_ADD_CHECK_PARENT: - ret = ldb_wait(sctx->parent_req->handle, LDB_WAIT_NONE); - - if (ret != LDB_SUCCESS) { - handle->status = ret; - goto done; - } - if (sctx->parent_req->handle->status != LDB_SUCCESS) { - handle->status = sctx->parent_req->handle->status; - goto done; - } - - if (sctx->parent_req->handle->state != LDB_ASYNC_DONE) { - return LDB_SUCCESS; - } - - return schema_add_continue(handle); - - case SC_ADD_TEMP: - ret = ldb_wait(sctx->down_req->handle, LDB_WAIT_NONE); - - if (ret != LDB_SUCCESS) { - handle->status = ret; - goto done; - } - if (sctx->down_req->handle->status != LDB_SUCCESS) { - handle->status = sctx->down_req->handle->status; - goto done; - } - - if (sctx->down_req->handle->state != LDB_ASYNC_DONE) { - return LDB_SUCCESS; - } - - break; - - default: - ret = LDB_ERR_OPERATIONS_ERROR; - goto done; - } - - ret = LDB_SUCCESS; - -done: - handle->state = LDB_ASYNC_DONE; - return ret; -} - -static int schema_wait_all(struct ldb_handle *handle) { - - int ret; - - while (handle->state != LDB_ASYNC_DONE) { - ret = schema_wait_loop(handle); - if (ret != LDB_SUCCESS) { - return ret; - } - } - - return handle->status; -} - -static int schema_wait(struct ldb_handle *handle, enum ldb_wait_type type) -{ - if (type == LDB_WAIT_ALL) { - return schema_wait_all(handle); - } else { - return schema_wait_loop(handle); - } -} - -static int schema_init(struct ldb_module *module) -{ - static const char *schema_attrs[] = { "schemaNamingContext", NULL }; - struct schema_private_data *data; - struct ldb_result *res; - int ret; - - /* need to let the partition module to register first */ - ret = ldb_next_init(module); - if (ret != LDB_SUCCESS) { - return ret; - } - - data = ldb_get_opaque(module->ldb, "schema_instance"); - if (data) { - module->private_data = data; - return LDB_SUCCESS; - } - - data = talloc_zero(module->ldb, struct schema_private_data); - if (data == NULL) { - return LDB_ERR_OPERATIONS_ERROR; - } - - /* find the schema partition */ - ret = ldb_search(module->ldb, - ldb_dn_new(module, module->ldb, NULL), - LDB_SCOPE_BASE, - "(objectClass=*)", - schema_attrs, - &res); - - if (res->count != 1) { - /* FIXME: return a clear error string */ - talloc_free(data); - talloc_free(res); - return LDB_ERR_OPERATIONS_ERROR; - } - - data->schema_dn = ldb_msg_find_attr_as_dn(module->ldb, data, res->msgs[0], "schemaNamingContext"); - if (data->schema_dn == NULL) { - /* FIXME: return a clear error string */ - talloc_free(data); - talloc_free(res); - return LDB_ERR_OPERATIONS_ERROR; - } - - talloc_free(res); - - ret = schema_init_attrs(module, data); - if (ret != LDB_SUCCESS) { - talloc_free(data); - return ret; - } - - ret = schema_init_classes(module, data); - if (ret != LDB_SUCCESS) { - talloc_free(data); - return ret; - } - - module->private_data = data; - ldb_set_opaque(module->ldb, "schema_instance", data); - - return LDB_SUCCESS; -} - -_PUBLIC_ const struct ldb_module_ops ldb_schema_module_ops = { - .name = "schema", - .init_context = schema_init, - .add = schema_add, - .modify = schema_modify, - .del = schema_delete, - .rename = schema_rename, - .wait = schema_wait -}; diff --git a/source4/dsdb/samdb/ldb_modules/schema_syntax.c b/source4/dsdb/samdb/ldb_modules/schema_syntax.c deleted file mode 100644 index ab9f32c913..0000000000 --- a/source4/dsdb/samdb/ldb_modules/schema_syntax.c +++ /dev/null @@ -1,469 +0,0 @@ -/* - ldb database library - - Copyright (C) Simo Sorce 2004-2006 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -/* - * Name: ldb - * - * Component: ldb schema module - * - * Description: add schema syntax functionality - * - * Author: Simo Sorce - */ - -#include "includes.h" -#include "ldb/include/ldb.h" -#include "ldb/include/ldb_errors.h" -#include "schema_syntax.h" - -int map_schema_syntax(uint32_t om_syntax, const char *attr_syntax, const struct ldb_val *om_class, enum schema_internal_syntax *syntax) -{ - int ret; - - ret = LDB_SUCCESS; - - switch(om_syntax) { - case 1: - *syntax = SCHEMA_AS_BOOLEAN; - break; - case 2: - *syntax = SCHEMA_AS_INTEGER; - break; - case 4: - if (strcmp(attr_syntax, "2.5.5.10") == 0) { - *syntax = SCHEMA_AS_OCTET_STRING; - break; - } - if (strcmp(attr_syntax, "2.5.5.17") == 0) { - *syntax = SCHEMA_AS_SID; - break; - } - ret = LDB_ERR_OPERATIONS_ERROR; - break; - case 6: - *syntax = SCHEMA_AS_OID; - break; - case 10: - *syntax = SCHEMA_AS_ENUMERATION; - break; - case 18: - *syntax = SCHEMA_AS_NUMERIC_STRING; - break; - case 19: - *syntax = SCHEMA_AS_PRINTABLE_STRING; - break; - case 20: - *syntax = SCHEMA_AS_CASE_IGNORE_STRING; - break; - case 22: - *syntax = SCHEMA_AS_IA5_STRING; - break; - case 23: - *syntax = SCHEMA_AS_UTC_TIME; - break; - case 24: - *syntax = SCHEMA_AS_GENERALIZED_TIME; - break; - case 27: - *syntax = SCHEMA_AS_CASE_SENSITIVE_STRING; - break; - case 64: - *syntax = SCHEMA_AS_DIRECTORY_STRING; - break; - case 65: - *syntax = SCHEMA_AS_LARGE_INTEGER; - break; - case 66: - *syntax = SCHEMA_AS_OBJECT_SECURITY_DESCRIPTOR; - break; - case 127: - if (!om_class) { - ret = LDB_ERR_OPERATIONS_ERROR; - break; - } - - if (memcmp(om_class->data, "\x2b\x0c\x02\x87\x73\x1c\x00\x85\x4a\x00", MIN(om_class->length, 10)) == 0) { - *syntax = SCHEMA_AS_DN; - break; - } - if (memcmp(om_class->data, "\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0b", MIN(om_class->length, 10)) == 0) { - *syntax = SCHEMA_AS_DN_BINARY; - break; - } - if (memcmp(om_class->data, "\x56\x06\x01\x02\x05\x0b\x1d\x00\x00\x00", MIN(om_class->length, 10)) == 0) { - *syntax = SCHEMA_AS_OR_NAME; - break; - } - if (memcmp(om_class->data, "\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x06", MIN(om_class->length, 10)) == 0) { - *syntax = SCHEMA_AS_REPLICA_LINK; - break; - } - if (memcmp(om_class->data, "\x2b\x0c\x02\x87\x73\x1c\x00\x85\x5c\x00", MIN(om_class->length, 10)) == 0) { - *syntax = SCHEMA_AS_PRESENTATION_ADDRESS; - break; - } - if (memcmp(om_class->data, "\x2b\x0c\x02\x87\x73\x1c\x00\x85\x3e\x00", MIN(om_class->length, 10)) == 0) { - *syntax = SCHEMA_AS_ACCESS_POINT; - break; - } - if (memcmp(om_class->data, "\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0c", MIN(om_class->length, 10)) == 0) { - *syntax = SCHEMA_AS_DN_STRING; - break; - } - /* not found will error in default: */ - default: - ret = LDB_ERR_OPERATIONS_ERROR; - } - - return ret; -} - -static int schema_validate_boolean(struct ldb_context *ldb, struct ldb_val *val, int min, int max) -{ - - if ((strncmp("TRUE", (const char *)val->data, val->length) != 0) && - (strncmp("FALSE", (const char *)val->data, val->length) != 0)) { - return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; - } - - return LDB_SUCCESS; -} - -static int schema_validate_integer(struct ldb_context *ldb, struct ldb_val *val, int min, int max) -{ - int value; - char *endptr; - - errno = 0; - value = strtol((const char *)val->data, &endptr, 0); - if (errno) return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; - if (endptr[0] != '\0') return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; - if ((min > INT_MIN) && (value < min)) return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; - if ((max < INT_MAX) && (value > max)) return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; - - return LDB_SUCCESS; -} - -static int schema_validate_binary_blob(struct ldb_context *ldb, struct ldb_val *val, int min, int max) -{ - /* is there anythign we should check in a binary blob ? */ - return LDB_SUCCESS; -} - -static int schema_validate_sid(struct ldb_context *ldb, struct ldb_val *val, int min, int max) -{ - /* TODO: validate binary form of objectSid */ - return LDB_SUCCESS; -} - -static int schema_validate_oid(struct ldb_context *ldb, struct ldb_val *val, int min, int max) -{ - if (strspn((const char *)val->data, "0123456789.") != val->length) - return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; - - return LDB_SUCCESS; -} - -static int schema_validate_numeric_string(struct ldb_context *ldb, struct ldb_val *val, int min, int max) -{ - if (strspn((const char *)val->data, "0123456789") != val->length) - return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; - - return LDB_SUCCESS; -} - -static int schema_validate_printable_string(struct ldb_context *ldb, struct ldb_val *val, int min, int max) -{ - /* TODO: find out what constitutes the printable character set */ - return LDB_SUCCESS; -} - -static int schema_validate_teletext_string(struct ldb_context *ldb, struct ldb_val *val, int min, int max) -{ - /* TODO: find out what constitutes the teletext character set */ - return LDB_SUCCESS; -} - -static int schema_validate_ia5_string(struct ldb_context *ldb, struct ldb_val *val, int min, int max) -{ - /* TODO: find out what constitutes the IA5 character set */ - return LDB_SUCCESS; -} - -static int schema_validate_utc_time(struct ldb_context *ldb, struct ldb_val *val, int min, int max) -{ - /* TODO: validate syntax of UTC Time string */ - return LDB_SUCCESS; -} - -static int schema_validate_generalized_time(struct ldb_context *ldb, struct ldb_val *val, int min, int max) -{ - /* TODO: validate syntax of Generalized Time string */ - return LDB_SUCCESS; -} - -/* NOTE: not a single attribute has this syntax in the basic w2k3 schema */ -static int schema_validate_sensitive_string(struct ldb_context *ldb, struct ldb_val *val, int min, int max) -{ - /* TODO: find out what constitutes a "case sensitive string" */ - return LDB_SUCCESS; -} - -static int schema_validate_unicode_string(struct ldb_context *ldb, struct ldb_val *val, int min, int max) -{ - /* TODO: validate utf8 string */ - return LDB_SUCCESS; -} - -static int schema_validate_large_integer(struct ldb_context *ldb, struct ldb_val *val, int min, int max) -{ - /* TODO: validate large integer/interval */ - return LDB_SUCCESS; -} - -static int schema_validate_object_sd(struct ldb_context *ldb, struct ldb_val *val, int min, int max) -{ - /* TODO: validate object Security Descriptor */ - return LDB_SUCCESS; -} - -static int schema_validate_dn(struct ldb_context *ldb, struct ldb_val *val, int min, int max) -{ - struct ldb_dn *dn; - int ret = LDB_SUCCESS; - - dn = ldb_dn_from_ldb_val(ldb, ldb, val); - if ( ! ldb_dn_validate(dn)) { - ret = LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; - } - - talloc_free(dn); - return ret; -} - -static int schema_validate_binary_plus_dn(struct ldb_context *ldb, struct ldb_val *val, int min, int max) -{ - int ret = LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; - TALLOC_CTX *memctx; - struct ldb_dn *dn; - char *str, *p; - char *endptr; - int num; - - memctx = talloc_new(NULL); - if (!memctx) return LDB_ERR_OPERATIONS_ERROR; - - str = talloc_strdup(memctx, (const char *)val->data); - if (!str) { - ret = LDB_ERR_OPERATIONS_ERROR; - goto done; - } - if (strncasecmp(str, "B:", 2) != 0) { - goto done; - } - - /* point at the number of chars in the string */ - str = strchr(&str[2], ':'); - if (!str) { - goto done; - } - str++; - - errno = 0; - num = strtol(str, &endptr, 0); - if (errno) return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; - if (endptr[0] != ':') return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; - if ((min > INT_MIN) && (num < min)) return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; - if ((max < INT_MAX) && (num > max)) return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; - - /* point at the string */ - str = strchr(str, ':'); - if (!str) { - goto done; - } - str++; - - /* terminate the string */ - p = strchr(str, ':'); - if (!p) { - goto done; - } - *p = '\0'; - - if (strlen(str) != 2*num) { - goto done; - } - - str = p + 1; - - dn = ldb_dn_new(memctx, ldb, str); - if (ldb_dn_validate(dn)) { - ret = LDB_SUCCESS; - } - -done: - talloc_free(memctx); - return ret; -} - -static int schema_validate_x400_or_name(struct ldb_context *ldb, struct ldb_val *val, int min, int max) -{ - /* TODO: find out what is the syntax of an X400 OR NAME */ - return LDB_SUCCESS; -} - -static int schema_validate_presentation_address(struct ldb_context *ldb, struct ldb_val *val, int min, int max) -{ - /* TODO: find out what is the syntax of a presentation address */ - return LDB_SUCCESS; -} - -static int schema_validate_x400_access_point(struct ldb_context *ldb, struct ldb_val *val, int min, int max) -{ - /* TODO: find out what is the syntax of an X400 Access Point */ - return LDB_SUCCESS; -} - -/* NOTE: seem there isn't a single attribute defined like this in the base w2k3 schema */ -static int schema_validate_string_plus_dn(struct ldb_context *ldb, struct ldb_val *val, int min, int max) -{ - int ret = LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; - TALLOC_CTX *memctx; - struct ldb_dn *dn; - char *str, *p; - char *endptr; - int num; - - memctx = talloc_new(NULL); - if (!memctx) return LDB_ERR_OPERATIONS_ERROR; - - str = talloc_strdup(memctx, (const char *)val->data); - if (!str) { - ret = LDB_ERR_OPERATIONS_ERROR; - goto done; - } - if (strncasecmp(str, "S:", 2) != 0) { - goto done; - } - - /* point at the number of chars in the string */ - str = strchr(&str[2], ':'); - if (!str) { - goto done; - } - str++; - - errno = 0; - num = strtol(str, &endptr, 0); - if (errno) return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; - if (endptr[0] != ':') return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; - if ((min > INT_MIN) && (num < min)) return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; - if ((max < INT_MAX) && (num > max)) return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; - - /* point at the string */ - str = strchr(str, ':'); - if (!str) { - goto done; - } - str++; - - /* terminate the string */ - p = strchr(str, ':'); - if (!p) { - goto done; - } - *p = '\0'; - - if (strlen(str) != num) { - goto done; - } - - str = p + 1; - - dn = ldb_dn_new(memctx, ldb, str); - if (ldb_dn_validate(dn)) { - ret = LDB_SUCCESS; - } - -done: - talloc_free(memctx); - return ret; -} - -struct schema_syntax_validator { - enum schema_internal_syntax type; - int (*validate)(struct ldb_context *ldb, struct ldb_val *, int, int); -}; - -struct schema_syntax_validator schema_syntax_validators[] = { - { SCHEMA_AS_BOOLEAN, schema_validate_boolean }, - { SCHEMA_AS_INTEGER, schema_validate_integer }, - { SCHEMA_AS_OCTET_STRING, schema_validate_binary_blob }, - { SCHEMA_AS_SID, schema_validate_sid }, - { SCHEMA_AS_OID, schema_validate_oid }, - { SCHEMA_AS_ENUMERATION, schema_validate_integer }, - { SCHEMA_AS_NUMERIC_STRING, schema_validate_numeric_string }, - { SCHEMA_AS_PRINTABLE_STRING, schema_validate_printable_string }, - { SCHEMA_AS_CASE_IGNORE_STRING, schema_validate_teletext_string }, - { SCHEMA_AS_IA5_STRING, schema_validate_ia5_string }, - { SCHEMA_AS_UTC_TIME, schema_validate_utc_time }, - { SCHEMA_AS_GENERALIZED_TIME, schema_validate_generalized_time }, - { SCHEMA_AS_CASE_SENSITIVE_STRING, schema_validate_sensitive_string }, - { SCHEMA_AS_DIRECTORY_STRING, schema_validate_unicode_string }, - { SCHEMA_AS_LARGE_INTEGER, schema_validate_large_integer }, - { SCHEMA_AS_OBJECT_SECURITY_DESCRIPTOR, schema_validate_object_sd }, - { SCHEMA_AS_DN, schema_validate_dn }, - { SCHEMA_AS_DN_BINARY, schema_validate_binary_plus_dn }, - { SCHEMA_AS_OR_NAME, schema_validate_x400_or_name }, - { SCHEMA_AS_REPLICA_LINK, schema_validate_binary_blob }, - { SCHEMA_AS_PRESENTATION_ADDRESS, schema_validate_presentation_address }, /* see rfc1278 ? */ - { SCHEMA_AS_ACCESS_POINT, schema_validate_x400_access_point }, - { SCHEMA_AS_DN_STRING, schema_validate_string_plus_dn }, - { -1, NULL } -}; - -int schema_validate(struct ldb_context *ldb, - struct ldb_message_element *el, - enum schema_internal_syntax type, - bool single, int min, int max) -{ - struct schema_syntax_validator *v; - int i, ret; - - if (single && (el->num_values > 1)) { - return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; - } - - for (i = 0; schema_syntax_validators[i].type != 0; i++) { - if (schema_syntax_validators[i].type == type) - break; - } - if (schema_syntax_validators[i].type == 0) { - return LDB_ERR_OPERATIONS_ERROR; - } - v = &schema_syntax_validators[i]; - - for (i = 0; i < el->num_values; i++) { - ret = v->validate(ldb, &el->values[i], min, max); - } - - return LDB_SUCCESS; -} - - diff --git a/source4/dsdb/samdb/ldb_modules/schema_syntax.h b/source4/dsdb/samdb/ldb_modules/schema_syntax.h deleted file mode 100644 index 37f7584d41..0000000000 --- a/source4/dsdb/samdb/ldb_modules/schema_syntax.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - ldb database library - - Copyright (C) Simo Sorce 2004-2006 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -/* - * Name: ldb - * - * Component: ldb schema module - * - * Description: add schema syntax functionality - * - * Author: Simo Sorce - */ - - -/* Syntax-Table - - see ldap_server/devdocs/AD-syntaxes.txt -*/ - -enum schema_internal_syntax { - SCHEMA_AS_BOOLEAN = 1, - SCHEMA_AS_INTEGER = 2, - SCHEMA_AS_OCTET_STRING = 3, - SCHEMA_AS_SID = 4, - SCHEMA_AS_OID = 5, - SCHEMA_AS_ENUMERATION = 6, - SCHEMA_AS_NUMERIC_STRING = 7, - SCHEMA_AS_PRINTABLE_STRING = 8, - SCHEMA_AS_CASE_IGNORE_STRING = 9, - SCHEMA_AS_IA5_STRING = 10, - SCHEMA_AS_UTC_TIME = 11, - SCHEMA_AS_GENERALIZED_TIME = 12, - SCHEMA_AS_CASE_SENSITIVE_STRING = 13, - SCHEMA_AS_DIRECTORY_STRING = 14, - SCHEMA_AS_LARGE_INTEGER = 15, - SCHEMA_AS_OBJECT_SECURITY_DESCRIPTOR = 16, - SCHEMA_AS_DN = 17, - SCHEMA_AS_DN_BINARY = 18, - SCHEMA_AS_OR_NAME = 19, - SCHEMA_AS_REPLICA_LINK = 20, - SCHEMA_AS_PRESENTATION_ADDRESS = 21, - SCHEMA_AS_ACCESS_POINT = 22, - SCHEMA_AS_DN_STRING = 23 -}; - -int map_schema_syntax(uint32_t om_syntax, - const char *attr_syntax, - const struct ldb_val *om_class, - enum schema_internal_syntax *syntax); - -int schema_validate(struct ldb_context *ldb, - struct ldb_message_element *el, - enum schema_internal_syntax type, - bool single, int min, int max); - diff --git a/source4/dsdb/schema/schema_set.c b/source4/dsdb/schema/schema_set.c index 3f5ddd8446..2303b88a05 100644 --- a/source4/dsdb/schema/schema_set.c +++ b/source4/dsdb/schema/schema_set.c @@ -79,13 +79,13 @@ static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schem ret = ldb_msg_add_string(msg, attr->lDAPDisplayName, "CASE_INSENSITIVE"); } if (ret != LDB_SUCCESS) { - return ret; + break; } if (attr->searchFlags & SEARCH_FLAG_ATTINDEX) { ret = ldb_msg_add_string(msg_idx, "@IDXATTR", attr->lDAPDisplayName); if (ret != LDB_SUCCESS) { - return ret; + break; } } @@ -105,11 +105,11 @@ static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schem } if (ret != LDB_SUCCESS) { - return ret; + break; } } - if (!write_attributes) { + if (!write_attributes || ret != LDB_SUCCESS) { talloc_free(mem_ctx); return ret; } @@ -120,19 +120,13 @@ static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schem if (ret == LDB_ERR_NO_SUCH_OBJECT) { ret = ldb_add(ldb, msg); } else if (ret != LDB_SUCCESS) { - talloc_free(mem_ctx); - return ret; + } else if (res->count != 1) { + ret = ldb_add(ldb, msg); } else { - - if (res->count != 1) { - talloc_free(mem_ctx); - return LDB_ERR_NO_SUCH_OBJECT; - } - ret = LDB_SUCCESS; /* Annoyingly added to our search results */ ldb_msg_remove_attr(res->msgs[0], "distinguishedName"); - + mod_msg = ldb_msg_diff(ldb, res->msgs[0], msg); if (mod_msg->num_elements > 0) { ret = ldb_modify(ldb, mod_msg); @@ -141,10 +135,11 @@ static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schem if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) { /* We might be on a read-only DB */ + ret = LDB_SUCCESS; + } + if (ret != LDB_SUCCESS) { talloc_free(mem_ctx); return ret; - } else if (ret != LDB_SUCCESS) { - return ret; } /* Now write out the indexs, as found in the schema (if they have changed) */ @@ -153,14 +148,10 @@ static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schem if (ret == LDB_ERR_NO_SUCH_OBJECT) { ret = ldb_add(ldb, msg_idx); } else if (ret != LDB_SUCCESS) { - talloc_free(mem_ctx); - return ret; + } else if (res->count != 1) { + ret = ldb_add(ldb, msg_idx); } else { - if (res_idx->count != 1) { - talloc_free(mem_ctx); - return LDB_ERR_NO_SUCH_OBJECT; - } - + ret = LDB_SUCCESS; /* Annoyingly added to our search results */ ldb_msg_remove_attr(res_idx->msgs[0], "distinguishedName"); @@ -171,7 +162,6 @@ static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schem } if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) { /* We might be on a read-only DB */ - talloc_free(mem_ctx); ret = LDB_SUCCESS; } talloc_free(mem_ctx); diff --git a/source4/lib/ldb/tests/python/api.py b/source4/lib/ldb/tests/python/api.py index 1ae3fde744..99ad1a9e66 100755 --- a/source4/lib/ldb/tests/python/api.py +++ b/source4/lib/ldb/tests/python/api.py @@ -27,14 +27,14 @@ class NoContextTests(unittest.TestCase): class SimpleLdb(unittest.TestCase): def test_connect(self): - ldb.Ldb("foo.tdb") + ldb.Ldb("foo.ldb") def test_connect_none(self): ldb.Ldb() def test_connect_later(self): x = ldb.Ldb() - x.connect("foo.tdb") + x.connect("foo.ldb") def test_repr(self): x = ldb.Ldb() @@ -49,19 +49,19 @@ class SimpleLdb(unittest.TestCase): x.set_modules_dir("/tmp") def test_search(self): - l = ldb.Ldb("foo.tdb") + l = ldb.Ldb("foo.ldb") self.assertEquals(len(l.search()), 1) def test_search_controls(self): - l = ldb.Ldb("foo.tdb") - self.assertEquals(len(l.search(controls=["paged_results:1:5"])), 1) + l = ldb.Ldb("foo.ldb") + self.assertEquals(len(l.search(controls=["paged_results:0:5"])), 1) def test_search_attrs(self): - l = ldb.Ldb("foo.tdb") + l = ldb.Ldb("foo.ldb") self.assertEquals(len(l.search(ldb.Dn(l, ""), ldb.SCOPE_SUBTREE, "(dc=*)", ["dc"])), 0) def test_search_string_dn(self): - l = ldb.Ldb("foo.tdb") + l = ldb.Ldb("foo.ldb") self.assertEquals(len(l.search("", ldb.SCOPE_SUBTREE, "(dc=*)", ["dc"])), 0) def test_search_attr_string(self): @@ -69,29 +69,29 @@ class SimpleLdb(unittest.TestCase): self.assertRaises(TypeError, l.search, attrs="dc") def test_opaque(self): - l = ldb.Ldb("foo.tdb") + l = ldb.Ldb("foo.ldb") l.set_opaque("my_opaque", l) self.assertTrue(l.get_opaque("my_opaque") is not None) self.assertEquals(None, l.get_opaque("unknown")) def test_parse_control_strings(self): - l = ldb.Ldb("foo.tdb") + l = ldb.Ldb("foo.ldb") self.assertRaises(ldb.LdbError, l.parse_control_strings, ["foo", "bar"]) - self.assertTrue(l.parse_control_strings(["paged_results:1:5"]) is not None) + self.assertTrue(l.parse_control_strings(["paged_results:0:5"]) is not None) def test_search_scope_base(self): - l = ldb.Ldb("foo.tdb") + l = ldb.Ldb("foo.ldb") self.assertEquals(len(l.search(ldb.Dn(l, "dc=foo"), ldb.SCOPE_ONELEVEL)), 0) def test_delete(self): - l = ldb.Ldb("foo.tdb") + l = ldb.Ldb("foo.ldb") self.assertRaises(ldb.LdbError, lambda: l.delete(ldb.Dn(l, "dc=foo"))) def test_contains(self): - l = ldb.Ldb("foo.tdb") + l = ldb.Ldb("foo.ldb") self.assertFalse(ldb.Dn(l, "dc=foo") in l) - l = ldb.Ldb("foo.tdb") + l = ldb.Ldb("foo.ldb") m = ldb.Message() m.dn = ldb.Dn(l, "dc=foo") m["b"] = ["a"] @@ -102,23 +102,23 @@ class SimpleLdb(unittest.TestCase): l.delete(m.dn) def test_get_config_basedn(self): - l = ldb.Ldb("foo.tdb") + l = ldb.Ldb("foo.ldb") self.assertEquals(None, l.get_config_basedn()) def test_get_root_basedn(self): - l = ldb.Ldb("foo.tdb") + l = ldb.Ldb("foo.ldb") self.assertEquals(None, l.get_root_basedn()) def test_get_schema_basedn(self): - l = ldb.Ldb("foo.tdb") + l = ldb.Ldb("foo.ldb") self.assertEquals(None, l.get_schema_basedn()) def test_get_default_basedn(self): - l = ldb.Ldb("foo.tdb") + l = ldb.Ldb("foo.ldb") self.assertEquals(None, l.get_default_basedn()) def test_add(self): - l = ldb.Ldb("foo.tdb") + l = ldb.Ldb("foo.ldb") m = ldb.Message() m.dn = ldb.Dn(l, "dc=foo") m["bla"] = "bla" @@ -130,7 +130,7 @@ class SimpleLdb(unittest.TestCase): l.delete(ldb.Dn(l, "dc=foo")) def test_add_dict(self): - l = ldb.Ldb("foo.tdb") + l = ldb.Ldb("foo.ldb") m = {"dn": ldb.Dn(l, "dc=foo"), "bla": "bla"} self.assertEquals(len(l.search()), 1) @@ -141,7 +141,7 @@ class SimpleLdb(unittest.TestCase): l.delete(ldb.Dn(l, "dc=foo")) def test_add_dict_string_dn(self): - l = ldb.Ldb("foo.tdb") + l = ldb.Ldb("foo.ldb") m = {"dn": "dc=foo", "bla": "bla"} self.assertEquals(len(l.search()), 1) l.add(m) @@ -151,7 +151,7 @@ class SimpleLdb(unittest.TestCase): l.delete(ldb.Dn(l, "dc=foo")) def test_rename(self): - l = ldb.Ldb("foo.tdb") + l = ldb.Ldb("foo.ldb") m = ldb.Message() m.dn = ldb.Dn(l, "dc=foo") m["bla"] = "bla" @@ -164,7 +164,7 @@ class SimpleLdb(unittest.TestCase): l.delete(ldb.Dn(l, "dc=bar")) def test_rename_string_dns(self): - l = ldb.Ldb("foo.tdb") + l = ldb.Ldb("foo.ldb") m = ldb.Message() m.dn = ldb.Dn(l, "dc=foo") m["bla"] = "bla" @@ -177,7 +177,7 @@ class SimpleLdb(unittest.TestCase): l.delete(ldb.Dn(l, "dc=bar")) def test_modify_delete(self): - l = ldb.Ldb("foo.tdb") + l = ldb.Ldb("foo.ldb") m = ldb.Message() m.dn = ldb.Dn(l, "dc=modifydelete") m["bla"] = ["1234"] @@ -195,7 +195,7 @@ class SimpleLdb(unittest.TestCase): l.delete(ldb.Dn(l, "dc=modifydelete")) def test_modify_add(self): - l = ldb.Ldb("foo.tdb") + l = ldb.Ldb("foo.ldb") m = ldb.Message() m.dn = ldb.Dn(l, "dc=add") m["bla"] = ["1234"] @@ -212,7 +212,7 @@ class SimpleLdb(unittest.TestCase): l.delete(ldb.Dn(l, "dc=add")) def test_modify_modify(self): - l = ldb.Ldb("foo.tdb") + l = ldb.Ldb("foo.ldb") m = ldb.Message() m.dn = ldb.Dn(l, "dc=modify2") m["bla"] = ["1234", "456"] @@ -229,7 +229,7 @@ class SimpleLdb(unittest.TestCase): l.delete(ldb.Dn(l, "dc=modify2")) def test_transaction_commit(self): - l = ldb.Ldb("foo.tdb") + l = ldb.Ldb("foo.ldb") l.transaction_start() m = ldb.Message(ldb.Dn(l, "dc=foo")) m["foo"] = ["bar"] @@ -238,7 +238,7 @@ class SimpleLdb(unittest.TestCase): l.delete(m.dn) def test_transaction_cancel(self): - l = ldb.Ldb("foo.tdb") + l = ldb.Ldb("foo.ldb") l.transaction_start() m = ldb.Message(ldb.Dn(l, "dc=foo")) m["foo"] = ["bar"] @@ -249,13 +249,13 @@ class SimpleLdb(unittest.TestCase): def test_set_debug(self): def my_report_fn(level, text): pass - l = ldb.Ldb("foo.tdb") + l = ldb.Ldb("foo.ldb") l.set_debug(my_report_fn) class DnTests(unittest.TestCase): def setUp(self): - self.ldb = ldb.Ldb("foo.tdb") + self.ldb = ldb.Ldb("foo.ldb") def test_eq_str(self): x = ldb.Dn(self.ldb, "dc=foo,bar=bloe") @@ -402,7 +402,7 @@ class LdbMsgTests(unittest.TestCase): self.assertEquals(["dn", "foo", "bar"], self.msg.keys()) def test_dn(self): - self.msg.dn = ldb.Dn(ldb.Ldb("foo.tdb"), "@BASEINFO") + self.msg.dn = ldb.Dn(ldb.Ldb("foo.ldb"), "@BASEINFO") self.assertEquals("@BASEINFO", self.msg.dn.__str__()) def test_get_dn(self): diff --git a/source4/lib/ldb/tests/test-generic.sh b/source4/lib/ldb/tests/test-generic.sh index 14337cc135..50b5ff99a0 100755 --- a/source4/lib/ldb/tests/test-generic.sh +++ b/source4/lib/ldb/tests/test-generic.sh @@ -103,7 +103,7 @@ fi count=`$VALGRIND ldbsearch '(cn<=t)' cn | grep '^dn' | wc -l` if [ $count != 13 ]; then echo returned $count records - expected 13 - echo "this fails on opsnLdap ..." + echo "this fails on openLdap ..." fi checkcount() { |