From a530ba82adeac762012ef79304b8f364e5f584d4 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 9 Nov 2012 11:25:21 +0100 Subject: [PATCH 1/5] s4:dsdb/acl: fix search filter cleanup for password attributes We need to this when we're *not* system. Signed-off-by: Stefan Metzmacher --- source4/dsdb/samdb/ldb_modules/acl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source4/dsdb/samdb/ldb_modules/acl.c b/source4/dsdb/samdb/ldb_modules/acl.c index 843d17e..05926fb 100644 --- a/source4/dsdb/samdb/ldb_modules/acl.c +++ b/source4/dsdb/samdb/ldb_modules/acl.c @@ -1499,7 +1499,7 @@ static int acl_search(struct ldb_module *module, struct ldb_request *req) /* replace any attributes in the parse tree that are private, so we don't allow a search for 'userPassword=penguin', just as we would not allow that attribute to be returned */ - if (ac->am_system) { + if (!ac->am_system) { /* FIXME: We should copy the tree and keep the original unmodified. */ /* remove password attributes */ if (data && data->password_attrs) { -- 1.7.9.5 From e7097678076b292c0a9cd4499cfa02eac0a42b6a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 9 Nov 2012 11:23:47 +0100 Subject: [PATCH 2/5] s4:dsdb/acl: reorganize the logic flow in the password filtering checks This avoids some nesting levels and does early returns. Signed-off-by: Stefan Metzmacher --- source4/dsdb/samdb/ldb_modules/acl.c | 146 +++++++++++++++++++++------------- 1 file changed, 92 insertions(+), 54 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/acl.c b/source4/dsdb/samdb/ldb_modules/acl.c index 05926fb..60750b5 100644 --- a/source4/dsdb/samdb/ldb_modules/acl.c +++ b/source4/dsdb/samdb/ldb_modules/acl.c @@ -57,6 +57,8 @@ struct acl_context { struct ldb_module *module; struct ldb_request *req; bool am_system; + bool modify_search; + bool constructed_attrs; bool allowedAttributes; bool allowedAttributesEffective; bool allowedChildClasses; @@ -88,12 +90,11 @@ static int acl_module_init(struct ldb_module *module) return ldb_operr(ldb); } - data = talloc(module, struct acl_private); + data = talloc_zero(module, struct acl_private); if (data == NULL) { return ldb_oom(ldb); } - data->password_attrs = NULL; data->acl_perform = lpcfg_parm_bool(ldb_get_opaque(ldb, "loadparm"), NULL, "acl", "perform", false); ldb_module_set_private(module, data); @@ -1403,11 +1404,7 @@ static int acl_search_callback(struct ldb_request *req, struct ldb_reply *ares) switch (ares->type) { case LDB_REPLY_ENTRY: - if (ac->allowedAttributes - || ac->allowedChildClasses - || ac->allowedChildClassesEffective - || ac->allowedAttributesEffective - || ac->sDRightsEffective) { + if (ac->constructed_attrs) { ret = dsdb_module_search_dn(ac->module, ac, &acl_res, ares->message->dn, acl_attrs, DSDB_FLAG_NEXT_MODULE | @@ -1415,44 +1412,65 @@ static int acl_search_callback(struct ldb_request *req, struct ldb_reply *ares) if (ret != LDB_SUCCESS) { return ldb_module_done(ac->req, NULL, NULL, ret); } - if (ac->allowedAttributes || ac->allowedAttributesEffective) { - 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->allowedAttributes || ac->allowedAttributesEffective) { + 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, ac->schema, acl_res->msgs[0], - ares->message, "allowedChildClasses"); - if (ret != LDB_SUCCESS) { - return ldb_module_done(ac->req, NULL, NULL, ret); - } + } + + if (ac->allowedChildClasses) { + 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, ac->schema, - acl_res->msgs[0], ares->message, ac); - if (ret != LDB_SUCCESS) { - return ldb_module_done(ac->req, NULL, NULL, ret); - } + } + + if (ac->allowedChildClassesEffective) { + 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, - 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, + acl_res->msgs[0], + ares->message, ac); + if (ret != LDB_SUCCESS) { + return ldb_module_done(ac->req, NULL, NULL, ret); } } - if (data && data->password_attrs) { - if (!ac->am_system) { - for (i = 0; data->password_attrs[i]; i++) { - if ((!ac->userPassword) && - (ldb_attr_cmp(data->password_attrs[i], - "userPassword") == 0)) - continue; - ldb_msg_remove_attr(ares->message, data->password_attrs[i]); + if (data == NULL) { + return ldb_module_send_entry(ac->req, ares->message, + ares->controls); + } + + if (ac->am_system) { + return ldb_module_send_entry(ac->req, ares->message, + ares->controls); + } + + if (data->password_attrs != NULL) { + for (i = 0; data->password_attrs[i]; i++) { + if ((!ac->userPassword) && + (ldb_attr_cmp(data->password_attrs[i], + "userPassword") == 0)) + { + continue; } + + ldb_msg_remove_attr(ares->message, data->password_attrs[i]); } } return ldb_module_send_entry(ac->req, ares->message, ares->controls); @@ -1472,6 +1490,7 @@ static int acl_search(struct ldb_module *module, struct ldb_request *req) { struct ldb_context *ldb; struct acl_context *ac; + struct ldb_parse_tree *down_tree; struct ldb_request *down_req; struct acl_private *data; int ret; @@ -1488,6 +1507,8 @@ static int acl_search(struct ldb_module *module, struct ldb_request *req) ac->module = module; ac->req = req; ac->am_system = dsdb_module_am_system(module); + ac->constructed_attrs = false; + ac->modify_search = true; ac->allowedAttributes = ldb_attr_in_list(req->op.search.attrs, "allowedAttributes"); ac->allowedAttributesEffective = ldb_attr_in_list(req->op.search.attrs, "allowedAttributesEffective"); ac->allowedChildClasses = ldb_attr_in_list(req->op.search.attrs, "allowedChildClasses"); @@ -1496,30 +1517,47 @@ static int acl_search(struct ldb_module *module, struct ldb_request *req) ac->userPassword = dsdb_user_password_support(module, ac, req); 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', - just as we would not allow that attribute to be returned */ - if (!ac->am_system) { - /* FIXME: We should copy the tree and keep the original unmodified. */ - /* remove password attributes */ - if (data && data->password_attrs) { - for (i = 0; data->password_attrs[i]; i++) { - if ((!ac->userPassword) && - (ldb_attr_cmp(data->password_attrs[i], - "userPassword") == 0)) - continue; + ac->constructed_attrs |= ac->allowedAttributes; + ac->constructed_attrs |= ac->allowedChildClasses; + ac->constructed_attrs |= ac->allowedChildClassesEffective; + ac->constructed_attrs |= ac->allowedAttributesEffective; + ac->constructed_attrs |= ac->sDRightsEffective; - ldb_parse_tree_attr_replace(req->op.search.tree, - data->password_attrs[i], - "kludgeACLredactedattribute"); + if (data == NULL) { + ac->modify_search = false; + } + if (ac->am_system) { + ac->modify_search = false; + } + + if (!ac->constructed_attrs && !ac->modify_search) { + return ldb_next_request(module, req); + } + + down_tree = ldb_parse_tree_copy_shallow(ac, req->op.search.tree); + if (down_tree == NULL) { + return ldb_oom(ldb); + } + + if (!ac->am_system && data->password_attrs) { + for (i = 0; data->password_attrs[i]; i++) { + if ((!ac->userPassword) && + (ldb_attr_cmp(data->password_attrs[i], + "userPassword") == 0)) + { + continue; } + + ldb_parse_tree_attr_replace(down_tree, + data->password_attrs[i], + "kludgeACLredactedattribute"); } } ret = ldb_build_search_req_ex(&down_req, ldb, ac, req->op.search.base, req->op.search.scope, - req->op.search.tree, + down_tree, req->op.search.attrs, req->controls, ac, acl_search_callback, -- 1.7.9.5 From 0694a4dc8a109e3bd862f98fbd57a59939eb1d35 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 9 Nov 2012 17:05:44 +0100 Subject: [PATCH 3/5] s4:dsdb/acl: only give administrators access to attributes marked as confidential (bug #8620) The full fix will to implement and use the code of the read_acl module, but this is better than nothing for now. Signed-off-by: Stefan Metzmacher --- source4/dsdb/samdb/ldb_modules/acl.c | 87 ++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/source4/dsdb/samdb/ldb_modules/acl.c b/source4/dsdb/samdb/ldb_modules/acl.c index 60750b5..1a41ee2 100644 --- a/source4/dsdb/samdb/ldb_modules/acl.c +++ b/source4/dsdb/samdb/ldb_modules/acl.c @@ -51,12 +51,17 @@ struct extended_access_check_attribute { struct acl_private { bool acl_perform; const char **password_attrs; + void *cached_schema_ptr; + uint64_t cached_schema_metadata_usn; + uint64_t cached_schema_loaded_usn; + const char **confidential_attrs; }; struct acl_context { struct ldb_module *module; struct ldb_request *req; bool am_system; + bool am_administrator; bool modify_search; bool constructed_attrs; bool allowedAttributes; @@ -1377,6 +1382,55 @@ static int acl_rename(struct ldb_module *module, struct ldb_request *req) return ldb_next_request(module, req); } +static int acl_search_update_confidential_attrs(struct acl_context *ac, + struct acl_private *data) +{ + struct dsdb_attribute *a; + uint32_t n = 0; + + if ((ac->schema == data->cached_schema_ptr) && + (ac->schema->loaded_usn == data->cached_schema_loaded_usn) && + (ac->schema->metadata_usn == data->cached_schema_metadata_usn)) + { + return LDB_SUCCESS; + } + + data->cached_schema_ptr = NULL; + data->cached_schema_loaded_usn = 0; + data->cached_schema_metadata_usn = 0; + TALLOC_FREE(data->confidential_attrs); + + if (ac->schema == NULL) { + return LDB_SUCCESS; + } + + for (a = ac->schema->attributes; a; a = a->next) { + const char **attrs = data->confidential_attrs; + + if (!(a->searchFlags & SEARCH_FLAG_CONFIDENTIAL)) { + continue; + } + + attrs = talloc_realloc(data, attrs, const char *, n + 2); + if (attrs == NULL) { + TALLOC_FREE(data->confidential_attrs); + return ldb_module_oom(ac->module); + } + + attrs[n] = a->lDAPDisplayName; + attrs[n+1] = NULL; + n++; + + data->confidential_attrs = attrs; + } + + data->cached_schema_ptr = ac->schema; + data->cached_schema_loaded_usn = ac->schema->loaded_usn; + data->cached_schema_metadata_usn = ac->schema->metadata_usn; + + return LDB_SUCCESS; +} + static int acl_search_callback(struct ldb_request *req, struct ldb_reply *ares) { struct acl_context *ac; @@ -1473,6 +1527,24 @@ static int acl_search_callback(struct ldb_request *req, struct ldb_reply *ares) ldb_msg_remove_attr(ares->message, data->password_attrs[i]); } } + + if (ac->am_administrator) { + return ldb_module_send_entry(ac->req, ares->message, + ares->controls); + } + + ret = acl_search_update_confidential_attrs(ac, data); + if (ret != LDB_SUCCESS) { + return ret; + } + + if (data->confidential_attrs != NULL) { + for (i = 0; data->confidential_attrs[i]; i++) { + ldb_msg_remove_attr(ares->message, + data->confidential_attrs[i]); + } + } + return ldb_module_send_entry(ac->req, ares->message, ares->controls); case LDB_REPLY_REFERRAL: @@ -1507,6 +1579,7 @@ static int acl_search(struct ldb_module *module, struct ldb_request *req) ac->module = module; ac->req = req; ac->am_system = dsdb_module_am_system(module); + ac->am_administrator = dsdb_module_am_administrator(module); ac->constructed_attrs = false; ac->modify_search = true; ac->allowedAttributes = ldb_attr_in_list(req->op.search.attrs, "allowedAttributes"); @@ -1534,6 +1607,11 @@ static int acl_search(struct ldb_module *module, struct ldb_request *req) return ldb_next_request(module, req); } + ret = acl_search_update_confidential_attrs(ac, data); + if (ret != LDB_SUCCESS) { + return ret; + } + down_tree = ldb_parse_tree_copy_shallow(ac, req->op.search.tree); if (down_tree == NULL) { return ldb_oom(ldb); @@ -1553,6 +1631,15 @@ static int acl_search(struct ldb_module *module, struct ldb_request *req) "kludgeACLredactedattribute"); } } + + if (!ac->am_system && !ac->am_administrator && data->confidential_attrs) { + for (i = 0; data->confidential_attrs[i]; i++) { + ldb_parse_tree_attr_replace(down_tree, + data->confidential_attrs[i], + "kludgeACLredactedattribute"); + } + } + ret = ldb_build_search_req_ex(&down_req, ldb, ac, req->op.search.base, -- 1.7.9.5 From 7106be920fd8f680da91876b8ba95ffd97fbdb3f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 9 Nov 2012 17:22:44 +0100 Subject: [PATCH 4/5] s4:dsdb/acl_read: fix whitespace formatting errors Signed-off-by: Stefan Metzmacher --- source4/dsdb/samdb/ldb_modules/acl_read.c | 252 +++++++++++++++-------------- 1 file changed, 128 insertions(+), 124 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/acl_read.c b/source4/dsdb/samdb/ldb_modules/acl_read.c index 35a840e..8542163 100644 --- a/source4/dsdb/samdb/ldb_modules/acl_read.c +++ b/source4/dsdb/samdb/ldb_modules/acl_read.c @@ -55,7 +55,7 @@ struct aclread_private { }; static void aclread_mark_inaccesslible(struct ldb_message_element *el) { - el->flags |= LDB_FLAG_INTERNAL_INACCESSIBLE_ATTRIBUTE; + el->flags |= LDB_FLAG_INTERNAL_INACCESSIBLE_ATTRIBUTE; } static bool aclread_is_inaccessible(struct ldb_message_element *el) { @@ -64,44 +64,45 @@ static bool aclread_is_inaccessible(struct ldb_message_element *el) { static int aclread_callback(struct ldb_request *req, struct ldb_reply *ares) { - struct ldb_context *ldb; - struct aclread_context *ac; - struct ldb_message *ret_msg; - struct ldb_message *msg; - int ret, num_of_attrs = 0; - unsigned int i, k = 0; - struct security_descriptor *sd; - struct dom_sid *sid = NULL; - TALLOC_CTX *tmp_ctx; - uint32_t instanceType; + struct ldb_context *ldb; + struct aclread_context *ac; + struct ldb_message *ret_msg; + struct ldb_message *msg; + int ret, num_of_attrs = 0; + unsigned int i, k = 0; + struct security_descriptor *sd; + struct dom_sid *sid = NULL; + TALLOC_CTX *tmp_ctx; + uint32_t instanceType; - ac = talloc_get_type(req->context, struct aclread_context); - ldb = ldb_module_get_ctx(ac->module); - if (!ares) { - return ldb_module_done(ac->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR ); - } - if (ares->error != LDB_SUCCESS) { - return ldb_module_done(ac->req, ares->controls, - ares->response, ares->error); - } - tmp_ctx = talloc_new(ac); - switch (ares->type) { - case LDB_REPLY_ENTRY: - msg = ares->message; - ret = dsdb_get_sd_from_ldb_message(ldb, tmp_ctx, msg, &sd); - if (ret != LDB_SUCCESS || sd == NULL ) { - DEBUG(10, ("acl_read: cannot get descriptor\n")); - ret = LDB_ERR_OPERATIONS_ERROR; - goto fail; - } - sid = samdb_result_dom_sid(tmp_ctx, msg, "objectSid"); - /* get the object instance type */ - instanceType = ldb_msg_find_attr_as_uint(msg, + ac = talloc_get_type(req->context, struct aclread_context); + ldb = ldb_module_get_ctx(ac->module); + if (!ares) { + return ldb_module_done(ac->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR ); + } + if (ares->error != LDB_SUCCESS) { + return ldb_module_done(ac->req, ares->controls, + ares->response, ares->error); + } + tmp_ctx = talloc_new(ac); + switch (ares->type) { + case LDB_REPLY_ENTRY: + msg = ares->message; + ret = dsdb_get_sd_from_ldb_message(ldb, tmp_ctx, msg, &sd); + if (ret != LDB_SUCCESS || sd == NULL ) { + DEBUG(10, ("acl_read: cannot get descriptor\n")); + ret = LDB_ERR_OPERATIONS_ERROR; + goto fail; + } + sid = samdb_result_dom_sid(tmp_ctx, msg, "objectSid"); + /* get the object instance type */ + instanceType = ldb_msg_find_attr_as_uint(msg, "instanceType", 0); - if (!ldb_dn_is_null(msg->dn) && !(instanceType & INSTANCE_TYPE_IS_NC_HEAD)) - { + if (!ldb_dn_is_null(msg->dn) && !(instanceType & INSTANCE_TYPE_IS_NC_HEAD)) + { /* the object has a parent, so we have to check for visibility */ struct ldb_dn *parent_dn = ldb_dn_get_parent(tmp_ctx, msg->dn); + ret = dsdb_module_check_access_on_dn(ac->module, tmp_ctx, parent_dn, @@ -113,51 +114,52 @@ static int aclread_callback(struct ldb_request *req, struct ldb_reply *ares) } else if (ret != LDB_SUCCESS) { goto fail; } - } - /* for every element in the message check RP */ - for (i=0; i < msg->num_elements; i++) { - const struct dsdb_attribute *attr; - bool is_sd, is_objectsid, is_instancetype; - uint32_t access_mask; - attr = dsdb_attribute_by_lDAPDisplayName(ac->schema, - msg->elements[i].name); - if (!attr) { - DEBUG(2, ("acl_read: cannot find attribute %s in schema\n", + } + /* for every element in the message check RP */ + for (i=0; i < msg->num_elements; i++) { + const struct dsdb_attribute *attr; + bool is_sd, is_objectsid, is_instancetype; + uint32_t access_mask; + attr = dsdb_attribute_by_lDAPDisplayName(ac->schema, + msg->elements[i].name); + if (!attr) { + DEBUG(2, ("acl_read: cannot find attribute %s in schema\n", msg->elements[i].name)); - ret = LDB_ERR_OPERATIONS_ERROR; - goto fail; - } - is_sd = ldb_attr_cmp("nTSecurityDescriptor", + ret = LDB_ERR_OPERATIONS_ERROR; + goto fail; + } + is_sd = ldb_attr_cmp("nTSecurityDescriptor", msg->elements[i].name) == 0; - is_objectsid = ldb_attr_cmp("objectSid", - msg->elements[i].name) == 0; - is_instancetype = ldb_attr_cmp("instanceType", - msg->elements[i].name) == 0; - /* these attributes were added to perform access checks and must be removed */ - if (is_objectsid && ac->object_sid) { - aclread_mark_inaccesslible(&msg->elements[i]); - continue; - } - if (is_instancetype && ac->instance_type) { - aclread_mark_inaccesslible(&msg->elements[i]); - continue; - } - if (is_sd && ac->sd) { - aclread_mark_inaccesslible(&msg->elements[i]); - continue; - } - /* nTSecurityDescriptor is a special case */ - if (is_sd) { - access_mask = SEC_FLAG_SYSTEM_SECURITY|SEC_STD_READ_CONTROL; - } else { - access_mask = SEC_ADS_READ_PROP; - } - ret = acl_check_access_on_attribute(ac->module, - tmp_ctx, - sd, - sid, - access_mask, - attr); + is_objectsid = ldb_attr_cmp("objectSid", + msg->elements[i].name) == 0; + is_instancetype = ldb_attr_cmp("instanceType", + msg->elements[i].name) == 0; + /* these attributes were added to perform access checks and must be removed */ + if (is_objectsid && ac->object_sid) { + aclread_mark_inaccesslible(&msg->elements[i]); + continue; + } + if (is_instancetype && ac->instance_type) { + aclread_mark_inaccesslible(&msg->elements[i]); + continue; + } + if (is_sd && ac->sd) { + aclread_mark_inaccesslible(&msg->elements[i]); + continue; + } + /* nTSecurityDescriptor is a special case */ + if (is_sd) { + access_mask = SEC_FLAG_SYSTEM_SECURITY|SEC_STD_READ_CONTROL; + } else { + access_mask = SEC_ADS_READ_PROP; + } + + ret = acl_check_access_on_attribute(ac->module, + tmp_ctx, + sd, + sid, + access_mask, + attr); /* * Dirsync control needs the replpropertymetadata attribute @@ -166,8 +168,10 @@ static int aclread_callback(struct ldb_request *req, struct ldb_reply *ares) */ if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) { if (!ac->indirsync) { - /* do not return this entry if attribute is - part of the search filter */ + /* + * do not return this entry if attribute is + * part of the search filter + */ if (dsdb_attr_in_parse_tree(ac->req->op.search.tree, msg->elements[i].name)) { talloc_free(tmp_ctx); @@ -194,50 +198,50 @@ static int aclread_callback(struct ldb_request *req, struct ldb_reply *ares) } else if (ret != LDB_SUCCESS) { goto fail; } - } - for (i=0; i < msg->num_elements; i++) { - if (!aclread_is_inaccessible(&msg->elements[i])) { - num_of_attrs++; - } - } - /*create a new message to return*/ - ret_msg = ldb_msg_new(ac->req); - ret_msg->dn = msg->dn; - talloc_steal(ret_msg, msg->dn); - ret_msg->num_elements = num_of_attrs; - if (num_of_attrs > 0) { - ret_msg->elements = talloc_array(ret_msg, - struct ldb_message_element, - num_of_attrs); - if (ret_msg->elements == NULL) { - return ldb_oom(ldb); - } - for (i=0; i < msg->num_elements; i++) { - bool to_remove = aclread_is_inaccessible(&msg->elements[i]); - if (!to_remove) { - ret_msg->elements[k] = msg->elements[i]; - talloc_steal(ret_msg->elements, msg->elements[i].name); - talloc_steal(ret_msg->elements, msg->elements[i].values); - k++; - } - } - } else { - ret_msg->elements = NULL; - } - talloc_free(tmp_ctx); + } + for (i=0; i < msg->num_elements; i++) { + if (!aclread_is_inaccessible(&msg->elements[i])) { + num_of_attrs++; + } + } + /*create a new message to return*/ + ret_msg = ldb_msg_new(ac->req); + ret_msg->dn = msg->dn; + talloc_steal(ret_msg, msg->dn); + ret_msg->num_elements = num_of_attrs; + if (num_of_attrs > 0) { + ret_msg->elements = talloc_array(ret_msg, + struct ldb_message_element, + num_of_attrs); + if (ret_msg->elements == NULL) { + return ldb_oom(ldb); + } + for (i=0; i < msg->num_elements; i++) { + bool to_remove = aclread_is_inaccessible(&msg->elements[i]); + if (!to_remove) { + ret_msg->elements[k] = msg->elements[i]; + talloc_steal(ret_msg->elements, msg->elements[i].name); + talloc_steal(ret_msg->elements, msg->elements[i].values); + k++; + } + } + } else { + ret_msg->elements = NULL; + } + talloc_free(tmp_ctx); - return ldb_module_send_entry(ac->req, ret_msg, ares->controls); - case LDB_REPLY_REFERRAL: - return ldb_module_send_referral(ac->req, ares->referral); - case LDB_REPLY_DONE: - return ldb_module_done(ac->req, ares->controls, + return ldb_module_send_entry(ac->req, ret_msg, ares->controls); + case LDB_REPLY_REFERRAL: + return ldb_module_send_referral(ac->req, ares->referral); + case LDB_REPLY_DONE: + return ldb_module_done(ac->req, ares->controls, ares->response, LDB_SUCCESS); - } - return LDB_SUCCESS; + } + return LDB_SUCCESS; fail: - talloc_free(tmp_ctx); - return ldb_module_done(ac->req, NULL, NULL, ret); + talloc_free(tmp_ctx); + return ldb_module_done(ac->req, NULL, NULL, ret); } @@ -255,8 +259,8 @@ static int aclread_search(struct ldb_module *module, struct ldb_request *req) const char * const *attrs = NULL; uint32_t instanceType; static const char *acl_attrs[] = { - "instanceType", - NULL + "instanceType", + NULL }; ldb = ldb_module_get_ctx(module); @@ -282,10 +286,10 @@ static int aclread_search(struct ldb_module *module, struct ldb_request *req) DSDB_SEARCH_SHOW_DELETED, req); if (ret != LDB_SUCCESS) { return ldb_error(ldb, ret, - "acl_read: Error retrieving instanceType for base."); + "acl_read: Error retrieving instanceType for base."); } instanceType = ldb_msg_find_attr_as_uint(res->msgs[0], - "instanceType", 0); + "instanceType", 0); if (instanceType != 0 && !(instanceType & INSTANCE_TYPE_IS_NC_HEAD)) { /* the object has a parent, so we have to check for visibility */ -- 1.7.9.5 From ab7b4825e0dc3dab4c3a87dcb3a29c7f88594150 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 9 Nov 2012 17:23:53 +0100 Subject: [PATCH 5/5] s4:dsdb/acl_read: make sure confidential attributes require CONTROL_ACCESS (bug #8620) Signed-off-by: Stefan Metzmacher --- source4/dsdb/samdb/ldb_modules/acl_read.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source4/dsdb/samdb/ldb_modules/acl_read.c b/source4/dsdb/samdb/ldb_modules/acl_read.c index 8542163..e2a2d4c 100644 --- a/source4/dsdb/samdb/ldb_modules/acl_read.c +++ b/source4/dsdb/samdb/ldb_modules/acl_read.c @@ -154,6 +154,10 @@ static int aclread_callback(struct ldb_request *req, struct ldb_reply *ares) access_mask = SEC_ADS_READ_PROP; } + if (attr->searchFlags & SEARCH_FLAG_CONFIDENTIAL) { + access_mask |= SEC_ADS_CONTROL_ACCESS; + } + ret = acl_check_access_on_attribute(ac->module, tmp_ctx, sd, -- 1.7.9.5