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