From a7ec946cedf29ad8a88fcd0b253468b61f369d86 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 16 Mar 2010 14:43:33 +1100 Subject: s4:dsdb/acl Reduce calls to dsdb_get_schema() and add memory context dsdb_get_schema() isn't a very cheap call, due to the use of LDB opaque pointers. We need to call it less, and instead pass it as a parameter where possible. This also changes to the new API with a talloc context. Andrew Bartlett --- source4/dsdb/samdb/ldb_modules/acl.c | 70 +++++++++++++++++++++++------------- 1 file changed, 46 insertions(+), 24 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/acl.c b/source4/dsdb/samdb/ldb_modules/acl.c index b0c1e2fa9e..e02270631f 100644 --- a/source4/dsdb/samdb/ldb_modules/acl.c +++ b/source4/dsdb/samdb/ldb_modules/acl.c @@ -61,6 +61,7 @@ struct acl_context { bool allowedChildClassesEffective; bool sDRightsEffective; const char * const *attrs; + struct dsdb_schema *schema; }; bool is_root_base_dn(struct ldb_context *ldb, struct ldb_dn *dn_to_check) @@ -196,17 +197,17 @@ done: } static const struct GUID *get_oc_guid_from_message(struct ldb_module *module, + const struct dsdb_schema *schema, struct ldb_message *msg) { struct ldb_message_element *oc_el; - struct ldb_context *ldb = ldb_module_get_ctx(module); oc_el = ldb_msg_find_element(msg, "objectClass"); if (!oc_el) { return NULL; } - return class_schemaid_guid_by_lDAPDisplayName(dsdb_get_schema(ldb), + return class_schemaid_guid_by_lDAPDisplayName(schema, (char *)oc_el->values[oc_el->num_values-1].data); } @@ -264,6 +265,7 @@ fail: } static int acl_check_access_on_class(struct ldb_module *module, + const struct dsdb_schema *schema, TALLOC_CTX *mem_ctx, struct security_descriptor *sd, struct dom_sid *rp_sid, @@ -271,13 +273,11 @@ static int acl_check_access_on_class(struct ldb_module *module, const char *class_name) { int ret; - struct ldb_context *ldb = ldb_module_get_ctx(module); NTSTATUS status; uint32_t access_granted; struct object_tree *root = NULL; struct object_tree *new_node = NULL; const struct GUID *guid; - const struct dsdb_schema *schema = dsdb_get_schema(ldb); TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); struct security_token *token = acl_user_token(module); if (class_name) { @@ -311,20 +311,21 @@ fail: } static int acl_allowedAttributes(struct ldb_module *module, + const struct dsdb_schema *schema, struct ldb_message *sd_msg, struct ldb_message *msg, struct acl_context *ac) { struct ldb_message_element *oc_el; struct ldb_context *ldb = ldb_module_get_ctx(module); - const struct dsdb_schema *schema = dsdb_get_schema(ldb); TALLOC_CTX *mem_ctx; const char **attr_list; int i, ret; /* If we don't have a schema yet, we can't do anything... */ if (schema == NULL) { - return LDB_SUCCESS; + ldb_asprintf_errstring(ldb, "cannot add allowedAttributes to %s because no schema is loaded", ldb_dn_get_linearized(msg->dn)); + return LDB_ERR_OPERATIONS_ERROR; } /* Must remove any existing attribute */ @@ -405,20 +406,20 @@ static int acl_allowedAttributes(struct ldb_module *module, } static int acl_childClasses(struct ldb_module *module, + const struct dsdb_schema *schema, struct ldb_message *sd_msg, struct ldb_message *msg, const char *attrName) { struct ldb_message_element *oc_el; struct ldb_message_element *allowedClasses; - struct ldb_context *ldb = ldb_module_get_ctx(module); - const struct dsdb_schema *schema = dsdb_get_schema(ldb); const struct dsdb_class *sclass; int i, j, ret; /* If we don't have a schema yet, we can't do anything... */ if (schema == NULL) { - return LDB_SUCCESS; + ldb_asprintf_errstring(ldb_module_get_ctx(module), "cannot add childClassesEffective to %s because no schema is loaded", ldb_dn_get_linearized(msg->dn)); + return LDB_ERR_OPERATIONS_ERROR; } /* Must remove any existing attribute, or else confusion reins */ @@ -458,14 +459,13 @@ static int acl_childClasses(struct ldb_module *module, } static int acl_childClassesEffective(struct ldb_module *module, + const struct dsdb_schema *schema, struct ldb_message *sd_msg, struct ldb_message *msg, struct acl_context *ac) { struct ldb_message_element *oc_el; struct ldb_message_element *allowedClasses = NULL; - struct ldb_context *ldb = ldb_module_get_ctx(module); - const struct dsdb_schema *schema = dsdb_get_schema(ldb); const struct dsdb_class *sclass; struct security_descriptor *sd; struct ldb_control *as_system = ldb_request_get_control(ac->req, @@ -478,12 +478,13 @@ static int acl_childClassesEffective(struct ldb_module *module, } if (ac->am_system || as_system) { - return acl_childClasses(module, sd_msg, msg, "allowedChildClassesEffective"); + return acl_childClasses(module, schema, sd_msg, msg, "allowedChildClassesEffective"); } /* If we don't have a schema yet, we can't do anything... */ if (schema == NULL) { - return LDB_SUCCESS; + ldb_asprintf_errstring(ldb_module_get_ctx(module), "cannot add allowedChildClassesEffective to %s because no schema is loaded", ldb_dn_get_linearized(msg->dn)); + return LDB_ERR_OPERATIONS_ERROR; } /* Must remove any existing attribute, or else confusion reins */ @@ -508,6 +509,7 @@ static int acl_childClassesEffective(struct ldb_module *module, for (j=0; sclass->possibleInferiors && sclass->possibleInferiors[j]; j++) { ret = acl_check_access_on_class(module, + schema, msg, sd, sid, @@ -613,6 +615,7 @@ static int acl_add(struct ldb_module *module, struct ldb_request *req) int ret; struct ldb_dn *parent = ldb_dn_get_parent(req, req->op.add.message->dn); struct ldb_context *ldb; + const struct dsdb_schema *schema; struct ldb_message_element *oc_el; const struct GUID *guid; struct ldb_control *as_system = ldb_request_get_control(req, LDB_CONTROL_AS_SYSTEM_OID); @@ -637,13 +640,18 @@ static int acl_add(struct ldb_module *module, struct ldb_request *req) return ldb_next_request(module, req); } + schema = dsdb_get_schema(ldb, req); + if (!schema) { + return LDB_ERR_OPERATIONS_ERROR; + } + oc_el = ldb_msg_find_element(req->op.add.message, "objectClass"); if (!oc_el || oc_el->num_values == 0) { DEBUG(10,("acl:operation error %s\n", ldb_dn_get_linearized(req->op.add.message->dn))); return ldb_module_done(req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR); } - guid = class_schemaid_guid_by_lDAPDisplayName(dsdb_get_schema(ldb), + guid = class_schemaid_guid_by_lDAPDisplayName(schema, (char *)oc_el->values[oc_el->num_values-1].data); ret = dsdb_module_check_access_on_dn(module, req, parent, SEC_ADS_CREATE_CHILD, guid); if (ret != LDB_SUCCESS) { @@ -656,7 +664,7 @@ static int acl_modify(struct ldb_module *module, struct ldb_request *req) { int ret; struct ldb_context *ldb = ldb_module_get_ctx(module); - const struct dsdb_schema *schema = dsdb_get_schema(ldb); + const struct dsdb_schema *schema; unsigned int i; bool modify_sd = false; const struct GUID *guid; @@ -698,6 +706,12 @@ static int acl_modify(struct ldb_module *module, struct ldb_request *req) return ret; } + schema = dsdb_get_schema(ldb, acl_res); + if (!schema) { + talloc_free(acl_res); + return LDB_ERR_OPERATIONS_ERROR; + } + ret = dsdb_get_sd_from_ldb_message(req, acl_res->msgs[0], &sd); if (ret != LDB_SUCCESS) { DEBUG(10, ("acl_modify: cannot get descriptor\n")); @@ -708,7 +722,7 @@ static int acl_modify(struct ldb_module *module, struct ldb_request *req) return LDB_SUCCESS; } - guid = get_oc_guid_from_message(module,acl_res->msgs[0]); + guid = get_oc_guid_from_message(module, schema, acl_res->msgs[0]); if (!guid) { DEBUG(10, ("acl_modify: cannot get guid\n")); goto fail; @@ -852,6 +866,7 @@ static int acl_rename(struct ldb_module *module, struct ldb_request *req) int ret; struct ldb_dn *oldparent = ldb_dn_get_parent(req, req->op.rename.olddn); struct ldb_dn *newparent = ldb_dn_get_parent(req, req->op.rename.newdn); + const struct dsdb_schema *schema; struct ldb_context *ldb; struct security_descriptor *sd = NULL; struct dom_sid *sid = NULL; @@ -893,13 +908,19 @@ static int acl_rename(struct ldb_module *module, struct ldb_request *req) return ret; } - guid = get_oc_guid_from_message(module,acl_res->msgs[0]); + schema = dsdb_get_schema(ldb, acl_res); + if (!schema) { + talloc_free(acl_res); + return LDB_ERR_OPERATIONS_ERROR; + } + + guid = get_oc_guid_from_message(module, schema, acl_res->msgs[0]); if (!insert_in_object_tree(tmp_ctx, guid, SEC_ADS_WRITE_PROP, &root, &new_node)) { return LDB_ERR_OPERATIONS_ERROR; }; - guid = attribute_schemaid_guid_by_lDAPDisplayName(dsdb_get_schema(ldb), + guid = attribute_schemaid_guid_by_lDAPDisplayName(schema, "name"); if (!insert_in_object_tree(tmp_ctx, guid, SEC_ADS_WRITE_PROP, &new_node, &new_node)) { @@ -910,7 +931,7 @@ static int acl_rename(struct ldb_module *module, struct ldb_request *req) if (rdn_name == NULL) { return LDB_ERR_OPERATIONS_ERROR; } - guid = attribute_schemaid_guid_by_lDAPDisplayName(dsdb_get_schema(ldb), + guid = attribute_schemaid_guid_by_lDAPDisplayName(schema, rdn_name); if (!insert_in_object_tree(tmp_ctx, guid, SEC_ADS_WRITE_PROP, &new_node, &new_node)) { @@ -965,7 +986,7 @@ static int acl_rename(struct ldb_module *module, struct ldb_request *req) tmp_ctx = talloc_new(req); root = NULL; new_node = NULL; - guid = get_oc_guid_from_message(module,acl_res->msgs[0]); + guid = get_oc_guid_from_message(module, schema, acl_res->msgs[0]); if (!guid) { DEBUG(10,("acl:renamed object has no object class\n")); return ldb_module_done(req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR); @@ -1036,27 +1057,27 @@ static int acl_search_callback(struct ldb_request *req, struct ldb_reply *ares) return ldb_module_done(ac->req, NULL, NULL, ret); } if (ac->allowedAttributes || ac->allowedAttributesEffective) { - ret = acl_allowedAttributes(ac->module, acl_res->msgs[0], ares->message, ac); + ret = acl_allowedAttributes(ac->module, ac->schema, acl_res->msgs[0], ares->message, ac); if (ret != LDB_SUCCESS) { return ldb_module_done(ac->req, NULL, NULL, ret); } } if (ac->allowedChildClasses) { - ret = acl_childClasses(ac->module, acl_res->msgs[0], + ret = acl_childClasses(ac->module, ac->schema, acl_res->msgs[0], ares->message, "allowedChildClasses"); if (ret != LDB_SUCCESS) { return ldb_module_done(ac->req, NULL, NULL, ret); } } if (ac->allowedChildClassesEffective) { - ret = acl_childClassesEffective(ac->module, + ret = acl_childClassesEffective(ac->module, ac->schema, acl_res->msgs[0], ares->message, ac); if (ret != LDB_SUCCESS) { return ldb_module_done(ac->req, NULL, NULL, ret); } } if (ac->sDRightsEffective) { - ret = acl_sDRightsEffective(ac->module, + ret = acl_sDRightsEffective(ac->module, acl_res->msgs[0], ares->message, ac); if (ret != LDB_SUCCESS) { return ldb_module_done(ac->req, NULL, NULL, ret); @@ -1108,6 +1129,7 @@ static int acl_search(struct ldb_module *module, struct ldb_request *req) ac->allowedChildClasses = ldb_attr_in_list(req->op.search.attrs, "allowedChildClasses"); ac->allowedChildClassesEffective = ldb_attr_in_list(req->op.search.attrs, "allowedChildClassesEffective"); ac->sDRightsEffective = ldb_attr_in_list(req->op.search.attrs, "sDRightsEffective"); + ac->schema = dsdb_get_schema(ldb, ac); /* replace any attributes in the parse tree that are private, so we don't allow a search for 'userPassword=penguin', -- cgit