📄 schema.c
字号:
/* 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) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -