diff options
author | Nadezhda Ivanova <nadezhda.ivanova@postpath.com> | 2009-12-17 17:25:11 +0200 |
---|---|---|
committer | Nadezhda Ivanova <nadezhda.ivanova@postpath.com> | 2009-12-17 17:25:11 +0200 |
commit | c0883fb4518570c85bf0a33ea0ce244f23c07c62 (patch) | |
tree | 0efb36221f487e0171d23e40216e385955c85a9c | |
parent | 619ad0c6ecf88a861ad1a1e1d5564bd1f91855cc (diff) | |
download | samba-c0883fb4518570c85bf0a33ea0ce244f23c07c62.tar.gz samba-c0883fb4518570c85bf0a33ea0ce244f23c07c62.tar.bz2 samba-c0883fb4518570c85bf0a33ea0ce244f23c07c62.zip |
Fixed incorrect checking of PRINCIPAL_SELF permissions.
If an ace has the PRINCIPAL_SELF as trustee, this sid has to be replaced with
the onjectSid of the object being checked. PRINCIPAL_SELF is the way to grant rights
to an account over itself.
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/acl.c | 97 | ||||
-rwxr-xr-x | source4/lib/ldb/tests/python/acl.py | 43 | ||||
-rw-r--r-- | source4/libcli/security/access_check.c | 15 |
3 files changed, 139 insertions, 16 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/acl.c b/source4/dsdb/samdb/ldb_modules/acl.c index dcd015b2a5..6cb50b2098 100644 --- a/source4/dsdb/samdb/ldb_modules/acl.c +++ b/source4/dsdb/samdb/ldb_modules/acl.c @@ -204,6 +204,33 @@ static const struct GUID *get_oc_guid_from_message(struct ldb_module *module, (char *)oc_el->values[oc_el->num_values-1].data); } +static int get_dom_sid_from_ldb_message(TALLOC_CTX *mem_ctx, + struct ldb_message *acl_res, + struct dom_sid **sid) +{ + struct ldb_message_element *sid_element; + enum ndr_err_code ndr_err; + + sid_element = ldb_msg_find_element(acl_res, "objectSid"); + if (!sid_element) { + *sid = NULL; + return LDB_SUCCESS; + } + *sid = talloc(mem_ctx, struct dom_sid); + if(!*sid) { + return LDB_ERR_OPERATIONS_ERROR; + } + ndr_err = ndr_pull_struct_blob(&sid_element->values[0], *sid, NULL, *sid, + (ndr_pull_flags_fn_t)ndr_pull_dom_sid); + + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + return LDB_ERR_OPERATIONS_ERROR; + } + + return LDB_SUCCESS; +} + + static void acl_debug(struct security_descriptor *sd, struct security_token *token, struct ldb_dn *dn, @@ -232,10 +259,12 @@ static int check_access_on_dn(struct ldb_module *module, struct ldb_context *ldb = ldb_module_get_ctx(module); struct ldb_result *acl_res; struct security_descriptor *sd = NULL; + struct dom_sid *sid = NULL; NTSTATUS status; uint32_t access_granted; static const char *acl_attrs[] = { "nTSecurityDescriptor", + "objectSid", NULL }; @@ -254,10 +283,16 @@ static int check_access_on_dn(struct ldb_module *module, if (!sd) { return LDB_SUCCESS; } + ret = get_dom_sid_from_ldb_message(mem_ctx, acl_res->msgs[0], &sid); + if (ret != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + status = sec_access_check_ds(sd, acl_user_token(module), access, &access_granted, - tree); + tree, + sid); if (!NT_STATUS_IS_OK(status)) { acl_debug(sd, acl_user_token(module), @@ -272,16 +307,15 @@ static int check_access_on_dn(struct ldb_module *module, static int acl_check_access_on_attribute(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct security_descriptor *sd, + struct dom_sid *rp_sid, uint32_t access, struct dsdb_attribute *attr) { 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 dsdb_schema *schema = dsdb_get_schema(ldb); TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); struct security_token *token = acl_user_token(module); if (attr) { @@ -310,7 +344,8 @@ static int acl_check_access_on_attribute(struct ldb_module *module, status = sec_access_check_ds(sd, token, access, &access_granted, - root); + root, + rp_sid); if (!NT_STATUS_IS_OK(status)) { ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; } @@ -325,6 +360,7 @@ fail: static int acl_check_access_on_class(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct security_descriptor *sd, + struct dom_sid *rp_sid, uint32_t access, const char *class_name) { @@ -355,7 +391,8 @@ static int acl_check_access_on_class(struct ldb_module *module, status = sec_access_check_ds(sd, token, access, &access_granted, - root); + root, + rp_sid); if (!NT_STATUS_IS_OK(status)) { ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; } @@ -373,8 +410,6 @@ static int acl_allowedAttributes(struct ldb_module *module, struct acl_context *ac) { struct ldb_message_element *oc_el; - struct ldb_message_element *allowedAttributes; - struct ldb_message_element *allowedAttributesEffective; struct ldb_context *ldb = ldb_module_get_ctx(module); const struct dsdb_schema *schema = dsdb_get_schema(ldb); TALLOC_CTX *mem_ctx; @@ -411,6 +446,7 @@ static int acl_allowedAttributes(struct ldb_module *module, } if (ac->allowedAttributesEffective) { struct security_descriptor *sd; + struct dom_sid *sid = NULL; ldb_msg_remove_attr(msg, "allowedAttributesEffective"); if (ac->user_type == SECURITY_SYSTEM) { for (i=0; attr_list && attr_list[i]; i++) { @@ -424,6 +460,11 @@ static int acl_allowedAttributes(struct ldb_module *module, if (ret != LDB_SUCCESS) { return ret; } + ret = get_dom_sid_from_ldb_message(mem_ctx, sd_msg, &sid); + + if (ret != LDB_SUCCESS) { + return ret; + } for (i=0; attr_list && attr_list[i]; i++) { struct dsdb_attribute *attr = dsdb_attribute_by_lDAPDisplayName(schema, attr_list[i]); @@ -439,6 +480,7 @@ static int acl_allowedAttributes(struct ldb_module *module, ret = acl_check_access_on_attribute(module, msg, sd, + sid, SEC_ADS_WRITE_PROP, attr); if (ret == LDB_SUCCESS) { @@ -517,6 +559,7 @@ static int acl_childClassesEffective(struct ldb_module *module, const struct dsdb_schema *schema = dsdb_get_schema(ldb); const struct dsdb_class *sclass; struct security_descriptor *sd; + struct dom_sid *sid = NULL; int i, j, ret; if (ac->user_type == SECURITY_SYSTEM) { @@ -536,7 +579,11 @@ static int acl_childClassesEffective(struct ldb_module *module, if (ret != LDB_SUCCESS) { return ret; } + ret = get_dom_sid_from_ldb_message(msg, sd_msg, &sid); + if (ret != LDB_SUCCESS) { + return ret; + } for (i=0; oc_el && i < oc_el->num_values; i++) { sclass = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &oc_el->values[i]); if (!sclass) { @@ -548,6 +595,7 @@ static int acl_childClassesEffective(struct ldb_module *module, ret = acl_check_access_on_class(module, msg, sd, + sid, SEC_ADS_CREATE_CHILD, sclass->possibleInferiors[j]); if (ret == LDB_SUCCESS) { @@ -587,6 +635,7 @@ static int acl_sDRightsEffective(struct ldb_module *module, struct ldb_message_element *rightsEffective; int ret; struct security_descriptor *sd; + struct dom_sid *sid = NULL; uint32_t flags = 0; /* Must remove any existing attribute, or else confusion reins */ @@ -604,10 +653,15 @@ static int acl_sDRightsEffective(struct ldb_module *module, if (ret != LDB_SUCCESS) { return ret; } + ret = get_dom_sid_from_ldb_message(msg, sd_msg, &sid); + if (ret != LDB_SUCCESS) { + return ret; + } ret = acl_check_access_on_attribute(module, msg, sd, + sid, SEC_STD_WRITE_OWNER, NULL); if (ret == LDB_SUCCESS) { @@ -616,6 +670,7 @@ static int acl_sDRightsEffective(struct ldb_module *module, ret = acl_check_access_on_attribute(module, msg, sd, + sid, SEC_STD_WRITE_DAC, NULL); if (ret == LDB_SUCCESS) { @@ -624,6 +679,7 @@ static int acl_sDRightsEffective(struct ldb_module *module, ret = acl_check_access_on_attribute(module, msg, sd, + sid, SEC_FLAG_SYSTEM_SECURITY, NULL); if (ret == LDB_SUCCESS) { @@ -695,10 +751,12 @@ static int acl_modify(struct ldb_module *module, struct ldb_request *req) NTSTATUS status; struct ldb_result *acl_res; struct security_descriptor *sd; + struct dom_sid *sid = NULL; TALLOC_CTX *tmp_ctx = talloc_new(req); static const char *acl_attrs[] = { "nTSecurityDescriptor", "objectClass", + "objectSid", NULL }; @@ -732,6 +790,11 @@ static int acl_modify(struct ldb_module *module, struct ldb_request *req) goto fail; } + ret = get_dom_sid_from_ldb_message(req, acl_res->msgs[0], &sid); + if (ret != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + if (!insert_in_object_tree(tmp_ctx, guid, SEC_ADS_WRITE_PROP, &root, &new_node)) { DEBUG(10, ("acl_modify: cannot add to object tree\n")); @@ -774,7 +837,8 @@ static int acl_modify(struct ldb_module *module, struct ldb_request *req) status = sec_access_check_ds(sd, acl_user_token(module), SEC_ADS_WRITE_PROP, &access_granted, - root); + root, + sid); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("Object %s nas no write property access\n", @@ -792,7 +856,8 @@ static int acl_modify(struct ldb_module *module, struct ldb_request *req) status = sec_access_check_ds(sd, acl_user_token(module), SEC_STD_WRITE_DAC, &access_granted, - NULL); + NULL, + sid); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("Object %s nas no write dacl access\n", @@ -860,6 +925,7 @@ static int acl_rename(struct ldb_module *module, struct ldb_request *req) struct ldb_dn *newparent = ldb_dn_get_parent(req, req->op.rename.newdn); struct ldb_context *ldb; struct security_descriptor *sd = NULL; + struct dom_sid *sid = NULL; struct ldb_result *acl_res; const struct GUID *guid; struct object_tree *root = NULL; @@ -870,6 +936,7 @@ static int acl_rename(struct ldb_module *module, struct ldb_request *req) static const char *acl_attrs[] = { "nTSecurityDescriptor", "objectClass", + "objectSid", NULL }; @@ -914,10 +981,16 @@ static int acl_rename(struct ldb_module *module, struct ldb_request *req) if (!sd) { return LDB_SUCCESS; } + ret = get_dom_sid_from_ldb_message(req, acl_res->msgs[0], &sid); + if (ret != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + status = sec_access_check_ds(sd, acl_user_token(module), SEC_ADS_WRITE_PROP, &access_granted, - root); + root, + sid); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("Object %s nas no wp on name\n", @@ -966,7 +1039,8 @@ static int acl_rename(struct ldb_module *module, struct ldb_request *req) status = sec_access_check_ds(sd, acl_user_token(module), SEC_STD_DELETE, &access_granted, - NULL); + NULL, + sid); if (NT_STATUS_IS_OK(status)) { return ldb_next_request(module, req); @@ -989,6 +1063,7 @@ static int acl_search_callback(struct ldb_request *req, struct ldb_reply *ares) static const char *acl_attrs[] = { "objectClass", "nTSecurityDescriptor", + "objectSid", NULL }; int ret, i; diff --git a/source4/lib/ldb/tests/python/acl.py b/source4/lib/ldb/tests/python/acl.py index ae35ddfb29..4544f60736 100755 --- a/source4/lib/ldb/tests/python/acl.py +++ b/source4/lib/ldb/tests/python/acl.py @@ -393,8 +393,6 @@ userAccountControl: %s""" % userAccountControl res = self.ldb_admin.search( self.base_dn, expression="(distinguishedName=%s,%s)" \ % ("CN=test_add_group1,OU=test_add_ou2,OU=test_add_ou1", self.base_dn) ) self.assertEqual( res, []) - -# ace is not inherited - filered out... def test_add_granted_user(self): """ 3 Testing OU with the rights of regular user granted the right 'Create User child objects' """ @@ -749,6 +747,47 @@ url: www.samba.org""" # This 'modify' operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS self.fail() + + def test_modify_u4(self): + """11 Grant WP to PRINCIPAL_SELF and test modify""" + # Creating acluser1 + if self.SAMBA: + self.delete_force(self.ldb_admin, self.get_user_dn("acluser3")) + self.create_user(self.ldb_admin, self.get_user_dn("acluser3")) + self.enable_account(self.get_user_dn("acluser3")) + # Test if we have any additional groups for user than default + if self.WIN: + res = self.ldb_admin.search( self.base_dn, expression="(distinguishedName=%s)" \ + % self.get_user_dn("acluser3") ) + try: + self.assertEqual( res[0]["memberOf"][0], "" ) + except KeyError: + pass + else: + self.fail() + # Create user connection that we will test with + ldb_user = self.get_ldb_connection("acluser3", "samba123@") + ldif = """ +dn: """ + self.get_user_dn("acluser3") + """ +changetype: modify +add: adminDescription +adminDescription: blah blah blah""" + try: + ldb_user.modify_ldif(ldif) + except LdbError, (num, _): + self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + else: + # This 'modify' operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS + self.fail() + + mod = "(OA;;WP;bf967919-0de6-11d0-a285-00aa003049e2;;PS)" + self.dacl_add_ace(self.get_user_dn("acluser3"), mod) + # Modify on attribute you have rights for + ldb_user.modify_ldif(ldif) + res = self.ldb_admin.search( self.base_dn, expression="(distinguishedName=%s)" \ + % self.get_user_dn("acluser3"), attrs=["adminDescription"] ) + self.assertEqual(res[0]["adminDescription"][0], "blah blah blah") + #enable these when we have search implemented def _test_search_u1(self): """See if can prohibit user to read another User object""" diff --git a/source4/libcli/security/access_check.c b/source4/libcli/security/access_check.c index fb78e0aa47..19fb160d58 100644 --- a/source4/libcli/security/access_check.c +++ b/source4/libcli/security/access_check.c @@ -180,12 +180,14 @@ NTSTATUS sec_access_check_ds(const struct security_descriptor *sd, const struct security_token *token, uint32_t access_desired, uint32_t *access_granted, - struct object_tree *tree) + struct object_tree *tree, + struct dom_sid *replace_sid) { int i; uint32_t bits_remaining; struct object_tree *node; const struct GUID *type; + struct dom_sid *ps_sid = dom_sid_parse_talloc(NULL, SID_NT_SELF); *access_granted = access_desired; bits_remaining = access_desired; @@ -228,13 +230,20 @@ NTSTATUS sec_access_check_ds(const struct security_descriptor *sd, /* check each ace in turn. */ for (i=0; bits_remaining && i < sd->dacl->num_aces; i++) { + struct dom_sid *trustee; struct security_ace *ace = &sd->dacl->aces[i]; if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) { continue; } - - if (!security_token_has_sid(token, &ace->trustee)) { + if (dom_sid_equal(&ace->trustee, ps_sid) && replace_sid) { + trustee = replace_sid; + } + else + { + trustee = &ace->trustee; + } + if (!security_token_has_sid(token, trustee)) { continue; } |