/* * Unix SMB/CIFS implementation. * * Unit test for NFS4 ACL handling * * Copyright (C) Christof Schmitt 2019 * * 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 . */ #include "nfs4_acls.c" #include "librpc/gen_ndr/idmap.h" #include "idmap_cache.h" #include struct test_sids { const char *sid_str; struct unixid unix_id; } test_sids[] = { { "S-1-5-2-123-456-789-100", { 1000, ID_TYPE_UID }}, { "S-1-5-2-123-456-789-101", { 1001, ID_TYPE_GID }}, { "S-1-5-2-123-456-789-102", { 1002, ID_TYPE_BOTH }}, { SID_CREATOR_OWNER, { 1003, ID_TYPE_UID }}, { SID_CREATOR_GROUP, { 1004, ID_TYPE_GID }}, { "S-1-5-2-123-456-789-103", { 1000, ID_TYPE_GID }}, { "S-1-5-2-123-456-789-104", { 1005, ID_TYPE_BOTH }}, { "S-1-5-2-123-456-789-105", { 1006, ID_TYPE_BOTH }}, { "S-1-5-2-123-456-789-106", { 1007, ID_TYPE_BOTH }}, }; static int group_setup(void **state) { struct dom_sid *sids = NULL; int i; sids = talloc_array(NULL, struct dom_sid, ARRAY_SIZE(test_sids)); assert_non_null(sids); for (i = 0; i < ARRAY_SIZE(test_sids); i++) { assert_true(dom_sid_parse(test_sids[i].sid_str, &sids[i])); idmap_cache_set_sid2unixid(&sids[i], &test_sids[i].unix_id); } *state = sids; return 0; } static int group_teardown(void **state) { struct dom_sid *sids = *state; int i; for (i = 0; i < ARRAY_SIZE(test_sids); i++) { assert_true(idmap_cache_del_sid(&sids[i])); } TALLOC_FREE(sids); *state = NULL; return 0; } /* * Run this as first test to verify that the id mappings used by other * tests are available in the cache. */ static void test_cached_id_mappings(void **state) { struct dom_sid *sids = *state; int i; for (i = 0; i < ARRAY_SIZE(test_sids); i++) { struct dom_sid *sid = &sids[i]; struct unixid *unix_id = &test_sids[i].unix_id; uid_t uid; gid_t gid; switch(unix_id->type) { case ID_TYPE_UID: assert_true(sid_to_uid(sid, &uid)); assert_int_equal(uid, unix_id->id); assert_false(sid_to_gid(sid, &gid)); break; case ID_TYPE_GID: assert_false(sid_to_uid(sid, &uid)); assert_true(sid_to_gid(sid, &gid)); assert_int_equal(gid, unix_id->id); break; case ID_TYPE_BOTH: assert_true(sid_to_uid(sid, &uid)); assert_int_equal(uid, unix_id->id); assert_true(sid_to_gid(sid, &gid)); assert_int_equal(gid, unix_id->id); break; default: fail_msg("Unknown id type %d\n", unix_id->type); break; } } } static void test_empty_nfs4_to_dacl(void **state) { struct dom_sid *sids = *state; TALLOC_CTX *frame = talloc_stackframe(); struct SMB4ACL_T *nfs4_acl; struct security_ace *dacl_aces; int good_aces; struct smbacl4_vfs_params params = { .mode = e_simple, .do_chown = true, .acedup = e_merge, .map_full_control = true, }; nfs4_acl = smb_create_smb4acl(frame); assert_non_null(nfs4_acl); assert_true(smbacl4_nfs42win(frame, ¶ms, nfs4_acl, &sids[0], &sids[1], false, &dacl_aces, &good_aces)); assert_int_equal(good_aces, 0); assert_null(dacl_aces); TALLOC_FREE(frame); } static void test_empty_dacl_to_nfs4(void **state) { TALLOC_CTX *frame = talloc_stackframe(); struct SMB4ACL_T *nfs4_acl; struct security_acl *dacl; struct smbacl4_vfs_params params = { .mode = e_simple, .do_chown = true, .acedup = e_merge, .map_full_control = true, }; dacl = make_sec_acl(frame, SECURITY_ACL_REVISION_ADS, 0, NULL); assert_non_null(dacl); nfs4_acl = smbacl4_win2nfs4(frame, false, dacl, ¶ms, 1001, 1002); assert_non_null(nfs4_acl); assert_int_equal(smbacl4_get_controlflags(nfs4_acl), SEC_DESC_SELF_RELATIVE); assert_int_equal(smb_get_naces(nfs4_acl), 0); assert_null(smb_first_ace4(nfs4_acl)); } struct ace_dacl_type_mapping { uint32_t nfs4_type; enum security_ace_type dacl_type; } ace_dacl_type_mapping[] = { { SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, SEC_ACE_TYPE_ACCESS_ALLOWED }, { SMB_ACE4_ACCESS_DENIED_ACE_TYPE, SEC_ACE_TYPE_ACCESS_DENIED }, }; static void test_acl_type_nfs4_to_dacl(void **state) { struct dom_sid *sids = *state; TALLOC_CTX *frame = talloc_stackframe(); int i; for (i = 0; i < ARRAY_SIZE(ace_dacl_type_mapping); i++) { struct SMB4ACL_T *nfs4_acl; SMB_ACE4PROP_T nfs4_ace; struct security_ace *dacl_aces; int good_aces; struct smbacl4_vfs_params params = { .mode = e_simple, .do_chown = true, .acedup = e_merge, .map_full_control = true, }; nfs4_acl = smb_create_smb4acl(frame); assert_non_null(nfs4_acl); nfs4_ace = (SMB_ACE4PROP_T) { .flags = 0, .who.uid = 1000, .aceType = ace_dacl_type_mapping[i].nfs4_type, .aceFlags = 0, .aceMask = SMB_ACE4_READ_DATA, }; assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); assert_true(smbacl4_nfs42win(frame, ¶ms, nfs4_acl, &sids[2], &sids[3], false, &dacl_aces, &good_aces)); assert_int_equal(good_aces, 1); assert_non_null(dacl_aces); assert_int_equal(dacl_aces[0].type, ace_dacl_type_mapping[i].dacl_type); assert_int_equal(dacl_aces[0].flags, 0); assert_int_equal(dacl_aces[0].access_mask, SEC_FILE_READ_DATA); assert_true(dom_sid_equal(&dacl_aces[0].trustee, &sids[0])); } TALLOC_FREE(frame); } static void test_acl_type_dacl_to_nfs4(void **state) { struct dom_sid *sids = *state; TALLOC_CTX *frame = talloc_stackframe(); int i; for (i = 0; i < ARRAY_SIZE(ace_dacl_type_mapping); i++) { struct SMB4ACL_T *nfs4_acl; struct SMB4ACE_T *nfs4_ace_container; SMB_ACE4PROP_T *nfs4_ace; struct security_ace dacl_aces[1]; struct security_acl *dacl; struct smbacl4_vfs_params params = { .mode = e_simple, .do_chown = true, .acedup = e_merge, .map_full_control = true, }; init_sec_ace(&dacl_aces[0], &sids[0], ace_dacl_type_mapping[i].dacl_type, SEC_FILE_READ_DATA, 0); dacl = make_sec_acl(frame, SECURITY_ACL_REVISION_ADS, ARRAY_SIZE(dacl_aces), dacl_aces); assert_non_null(dacl); nfs4_acl = smbacl4_win2nfs4(frame, false, dacl, ¶ms, 101, 102); assert_non_null(nfs4_acl); assert_int_equal(smbacl4_get_controlflags(nfs4_acl), SEC_DESC_SELF_RELATIVE); assert_int_equal(smb_get_naces(nfs4_acl), 1); nfs4_ace_container = smb_first_ace4(nfs4_acl); assert_non_null(nfs4_ace_container); assert_null(smb_next_ace4(nfs4_ace_container)); nfs4_ace = smb_get_ace4(nfs4_ace_container); assert_int_equal(nfs4_ace->flags, 0); assert_int_equal(nfs4_ace->who.uid, 1000); assert_int_equal(nfs4_ace->aceFlags, 0); assert_int_equal(nfs4_ace->aceType, ace_dacl_type_mapping[i].nfs4_type); assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA); } TALLOC_FREE(frame); } struct ace_flag_mapping_nfs4_to_dacl { bool is_directory; uint32_t nfs4_flag; uint32_t dacl_flag; } ace_flags_nfs4_to_dacl[] = { { true, SMB_ACE4_FILE_INHERIT_ACE, SEC_ACE_FLAG_OBJECT_INHERIT }, { false, SMB_ACE4_FILE_INHERIT_ACE, 0 }, { true, SMB_ACE4_DIRECTORY_INHERIT_ACE, SEC_ACE_FLAG_CONTAINER_INHERIT }, { false, SMB_ACE4_DIRECTORY_INHERIT_ACE, 0 }, { true, SMB_ACE4_NO_PROPAGATE_INHERIT_ACE, SEC_ACE_FLAG_NO_PROPAGATE_INHERIT }, { false, SMB_ACE4_NO_PROPAGATE_INHERIT_ACE, SEC_ACE_FLAG_NO_PROPAGATE_INHERIT }, { true, SMB_ACE4_INHERIT_ONLY_ACE, SEC_ACE_FLAG_INHERIT_ONLY }, { false, SMB_ACE4_INHERIT_ONLY_ACE, SEC_ACE_FLAG_INHERIT_ONLY }, { true, SMB_ACE4_SUCCESSFUL_ACCESS_ACE_FLAG, 0 }, { false, SMB_ACE4_SUCCESSFUL_ACCESS_ACE_FLAG, 0 }, { true, SMB_ACE4_FAILED_ACCESS_ACE_FLAG, 0 }, { false, SMB_ACE4_FAILED_ACCESS_ACE_FLAG, 0 }, { true, SMB_ACE4_INHERITED_ACE, SEC_ACE_FLAG_INHERITED_ACE }, { false, SMB_ACE4_INHERITED_ACE, SEC_ACE_FLAG_INHERITED_ACE }, }; static void test_ace_flags_nfs4_to_dacl(void **state) { struct dom_sid *sids = *state; TALLOC_CTX *frame = talloc_stackframe(); SMB_ACE4PROP_T nfs4_ace; int i; for (i = 0; i < ARRAY_SIZE(ace_flags_nfs4_to_dacl); i++) { struct SMB4ACL_T *nfs4_acl; bool is_directory; struct security_ace *dacl_aces; int good_aces; struct smbacl4_vfs_params params = { .mode = e_simple, .do_chown = true, .acedup = e_merge, .map_full_control = true, }; nfs4_acl = smb_create_smb4acl(frame); assert_non_null(nfs4_acl); nfs4_ace = (SMB_ACE4PROP_T) { .flags = 0, .who.uid = 1000, .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, .aceFlags = ace_flags_nfs4_to_dacl[i].nfs4_flag, .aceMask = SMB_ACE4_READ_DATA, }; assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); is_directory = ace_flags_nfs4_to_dacl[i].is_directory; assert_true(smbacl4_nfs42win(frame, ¶ms, nfs4_acl, &sids[2], &sids[3], is_directory, &dacl_aces, &good_aces)); assert_int_equal(good_aces, 1); assert_non_null(dacl_aces); assert_int_equal(dacl_aces[0].type, SEC_ACE_TYPE_ACCESS_ALLOWED); assert_int_equal(dacl_aces[0].flags, ace_flags_nfs4_to_dacl[i].dacl_flag); assert_int_equal(dacl_aces[0].access_mask, SEC_FILE_READ_DATA); assert_true(dom_sid_equal(&dacl_aces[0].trustee, &sids[0])); } TALLOC_FREE(frame); } struct ace_flag_mapping_dacl_to_nfs4 { bool is_directory; uint32_t dacl_flag; uint32_t nfs4_flag; } ace_flags_dacl_to_nfs4[] = { { true, SEC_ACE_FLAG_OBJECT_INHERIT, SMB_ACE4_FILE_INHERIT_ACE }, { false, SEC_ACE_FLAG_OBJECT_INHERIT, 0 }, { true, SEC_ACE_FLAG_CONTAINER_INHERIT, SMB_ACE4_DIRECTORY_INHERIT_ACE }, { false, SEC_ACE_FLAG_CONTAINER_INHERIT, 0 }, { true, SEC_ACE_FLAG_NO_PROPAGATE_INHERIT, SMB_ACE4_NO_PROPAGATE_INHERIT_ACE }, { false, SEC_ACE_FLAG_NO_PROPAGATE_INHERIT, 0 }, { true, SEC_ACE_FLAG_INHERIT_ONLY, SMB_ACE4_INHERIT_ONLY_ACE }, { false, SEC_ACE_FLAG_INHERIT_ONLY, 0 }, { true, SEC_ACE_FLAG_INHERITED_ACE, SMB_ACE4_INHERITED_ACE }, { false, SEC_ACE_FLAG_INHERITED_ACE, SMB_ACE4_INHERITED_ACE }, { true, SEC_ACE_FLAG_SUCCESSFUL_ACCESS, 0 }, { false, SEC_ACE_FLAG_SUCCESSFUL_ACCESS, 0 }, { true, SEC_ACE_FLAG_FAILED_ACCESS, 0 }, { false, SEC_ACE_FLAG_FAILED_ACCESS, 0 }, }; static void test_ace_flags_dacl_to_nfs4(void **state) { struct dom_sid *sids = *state; TALLOC_CTX *frame = talloc_stackframe(); int i; for (i = 0; i < ARRAY_SIZE(ace_flags_dacl_to_nfs4); i++) { struct SMB4ACL_T *nfs4_acl; struct SMB4ACE_T *nfs4_ace_container; SMB_ACE4PROP_T *nfs4_ace; bool is_directory; struct security_ace dacl_aces[1]; struct security_acl *dacl; struct smbacl4_vfs_params params = { .mode = e_simple, .do_chown = true, .acedup = e_merge, .map_full_control = true, }; init_sec_ace(&dacl_aces[0], &sids[0], SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, ace_flags_dacl_to_nfs4[i].dacl_flag); dacl = make_sec_acl(frame, SECURITY_ACL_REVISION_ADS, ARRAY_SIZE(dacl_aces), dacl_aces); assert_non_null(dacl); is_directory = ace_flags_dacl_to_nfs4[i].is_directory; nfs4_acl = smbacl4_win2nfs4(frame, is_directory, dacl, ¶ms, 101, 102); assert_non_null(nfs4_acl); assert_int_equal(smbacl4_get_controlflags(nfs4_acl), SEC_DESC_SELF_RELATIVE); assert_int_equal(smb_get_naces(nfs4_acl), 1); nfs4_ace_container = smb_first_ace4(nfs4_acl); assert_non_null(nfs4_ace_container); assert_null(smb_next_ace4(nfs4_ace_container)); nfs4_ace = smb_get_ace4(nfs4_ace_container); assert_int_equal(nfs4_ace->flags, 0); assert_int_equal(nfs4_ace->who.uid, 1000); assert_int_equal(nfs4_ace->aceFlags, ace_flags_dacl_to_nfs4[i].nfs4_flag); assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA); } TALLOC_FREE(frame); } struct ace_perm_mapping { uint32_t nfs4_perm; uint32_t dacl_perm; } perm_table_nfs4_to_dacl[] = { { SMB_ACE4_READ_DATA, SEC_FILE_READ_DATA }, { SMB_ACE4_LIST_DIRECTORY, SEC_DIR_LIST }, { SMB_ACE4_WRITE_DATA, SEC_FILE_WRITE_DATA }, { SMB_ACE4_ADD_FILE, SEC_DIR_ADD_FILE }, { SMB_ACE4_APPEND_DATA, SEC_FILE_APPEND_DATA }, { SMB_ACE4_ADD_SUBDIRECTORY, SEC_DIR_ADD_SUBDIR, }, { SMB_ACE4_READ_NAMED_ATTRS, SEC_FILE_READ_EA }, { SMB_ACE4_READ_NAMED_ATTRS, SEC_DIR_READ_EA }, { SMB_ACE4_WRITE_NAMED_ATTRS, SEC_FILE_WRITE_EA }, { SMB_ACE4_WRITE_NAMED_ATTRS, SEC_DIR_WRITE_EA }, { SMB_ACE4_EXECUTE, SEC_FILE_EXECUTE }, { SMB_ACE4_EXECUTE, SEC_DIR_TRAVERSE }, { SMB_ACE4_DELETE_CHILD, SEC_DIR_DELETE_CHILD }, { SMB_ACE4_READ_ATTRIBUTES, SEC_FILE_READ_ATTRIBUTE }, { SMB_ACE4_READ_ATTRIBUTES, SEC_DIR_READ_ATTRIBUTE }, { SMB_ACE4_WRITE_ATTRIBUTES, SEC_FILE_WRITE_ATTRIBUTE }, { SMB_ACE4_WRITE_ATTRIBUTES, SEC_DIR_WRITE_ATTRIBUTE }, { SMB_ACE4_DELETE, SEC_STD_DELETE }, { SMB_ACE4_READ_ACL, SEC_STD_READ_CONTROL }, { SMB_ACE4_WRITE_ACL, SEC_STD_WRITE_DAC, }, { SMB_ACE4_WRITE_OWNER, SEC_STD_WRITE_OWNER }, { SMB_ACE4_SYNCHRONIZE, SEC_STD_SYNCHRONIZE }, }; static void test_nfs4_permissions_to_dacl(void **state) { struct dom_sid *sids = *state; TALLOC_CTX *frame = talloc_stackframe(); int i; for (i = 0; i < ARRAY_SIZE(perm_table_nfs4_to_dacl); i++) { struct SMB4ACL_T *nfs4_acl; SMB_ACE4PROP_T nfs4_ace; struct security_ace *dacl_aces; int good_aces; struct smbacl4_vfs_params params = { .mode = e_simple, .do_chown = true, .acedup = e_merge, .map_full_control = true, }; nfs4_acl = smb_create_smb4acl(frame); assert_non_null(nfs4_acl); nfs4_ace = (SMB_ACE4PROP_T) { .flags = 0, .who.uid = 1000, .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, .aceFlags = 0, .aceMask = perm_table_nfs4_to_dacl[i].nfs4_perm, }; assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); assert_true(smbacl4_nfs42win(frame, ¶ms, nfs4_acl, &sids[0], &sids[1], false, &dacl_aces, &good_aces)); assert_int_equal(good_aces, 1); assert_non_null(dacl_aces); assert_int_equal(dacl_aces[0].type, SEC_ACE_TYPE_ACCESS_ALLOWED); assert_int_equal(dacl_aces[0].flags, 0); assert_int_equal(dacl_aces[0].access_mask, perm_table_nfs4_to_dacl[i].dacl_perm); assert_true(dom_sid_equal(&dacl_aces[0].trustee, &sids[0])); } TALLOC_FREE(frame); } struct ace_perm_mapping_dacl_to_nfs4 { uint32_t dacl_perm; uint32_t nfs4_perm; } perm_table_dacl_to_nfs4[] = { { SEC_FILE_READ_DATA, SMB_ACE4_READ_DATA, }, { SEC_DIR_LIST, SMB_ACE4_LIST_DIRECTORY, }, { SEC_FILE_WRITE_DATA, SMB_ACE4_WRITE_DATA, }, { SEC_DIR_ADD_FILE, SMB_ACE4_ADD_FILE, }, { SEC_FILE_APPEND_DATA, SMB_ACE4_APPEND_DATA, }, { SEC_DIR_ADD_SUBDIR, SMB_ACE4_ADD_SUBDIRECTORY, }, { SEC_FILE_READ_EA, SMB_ACE4_READ_NAMED_ATTRS, }, { SEC_DIR_READ_EA, SMB_ACE4_READ_NAMED_ATTRS, }, { SEC_FILE_WRITE_EA, SMB_ACE4_WRITE_NAMED_ATTRS, }, { SEC_DIR_WRITE_EA, SMB_ACE4_WRITE_NAMED_ATTRS, }, { SEC_FILE_EXECUTE, SMB_ACE4_EXECUTE, }, { SEC_DIR_TRAVERSE, SMB_ACE4_EXECUTE, }, { SEC_DIR_DELETE_CHILD, SMB_ACE4_DELETE_CHILD, }, { SEC_FILE_READ_ATTRIBUTE, SMB_ACE4_READ_ATTRIBUTES, }, { SEC_DIR_READ_ATTRIBUTE, SMB_ACE4_READ_ATTRIBUTES, }, { SEC_FILE_WRITE_ATTRIBUTE, SMB_ACE4_WRITE_ATTRIBUTES, }, { SEC_DIR_WRITE_ATTRIBUTE, SMB_ACE4_WRITE_ATTRIBUTES, }, { SEC_STD_DELETE, SMB_ACE4_DELETE, }, { SEC_STD_READ_CONTROL, SMB_ACE4_READ_ACL, }, { SEC_STD_WRITE_DAC, SMB_ACE4_WRITE_ACL, }, { SEC_STD_WRITE_OWNER, SMB_ACE4_WRITE_OWNER, }, { SEC_STD_SYNCHRONIZE, SMB_ACE4_SYNCHRONIZE, }, { SEC_GENERIC_READ, SMB_ACE4_READ_ACL| SMB_ACE4_READ_DATA| SMB_ACE4_READ_ATTRIBUTES| SMB_ACE4_READ_NAMED_ATTRS| SMB_ACE4_SYNCHRONIZE }, { SEC_GENERIC_WRITE, SMB_ACE4_WRITE_ACL| SMB_ACE4_WRITE_DATA| SMB_ACE4_WRITE_ATTRIBUTES| SMB_ACE4_WRITE_NAMED_ATTRS| SMB_ACE4_SYNCHRONIZE }, { SEC_GENERIC_EXECUTE, SMB_ACE4_READ_ACL| SMB_ACE4_READ_ATTRIBUTES| SMB_ACE4_EXECUTE| SMB_ACE4_SYNCHRONIZE }, { SEC_GENERIC_ALL, SMB_ACE4_DELETE| SMB_ACE4_READ_ACL| SMB_ACE4_WRITE_ACL| SMB_ACE4_WRITE_OWNER| SMB_ACE4_SYNCHRONIZE| SMB_ACE4_WRITE_ATTRIBUTES| SMB_ACE4_READ_ATTRIBUTES| SMB_ACE4_EXECUTE| SMB_ACE4_READ_NAMED_ATTRS| SMB_ACE4_WRITE_NAMED_ATTRS| SMB_ACE4_WRITE_DATA| SMB_ACE4_APPEND_DATA| SMB_ACE4_READ_DATA| SMB_ACE4_DELETE_CHILD }, }; static void test_dacl_permissions_to_nfs4(void **state) { struct dom_sid *sids = *state; TALLOC_CTX *frame = talloc_stackframe(); int i; for (i = 0; i < ARRAY_SIZE(perm_table_nfs4_to_dacl); i++) { struct SMB4ACL_T *nfs4_acl; struct SMB4ACE_T *nfs4_ace_container; SMB_ACE4PROP_T *nfs4_ace; struct smbacl4_vfs_params params = { .mode = e_simple, .do_chown = true, .acedup = e_merge, .map_full_control = true, }; struct security_ace dacl_aces[1]; struct security_acl *dacl; init_sec_ace(&dacl_aces[0], &sids[0], SEC_ACE_TYPE_ACCESS_ALLOWED, perm_table_dacl_to_nfs4[i].dacl_perm, 0); dacl = make_sec_acl(frame, SECURITY_ACL_REVISION_ADS, ARRAY_SIZE(dacl_aces), dacl_aces); assert_non_null(dacl); nfs4_acl = smbacl4_win2nfs4(frame, false, dacl, ¶ms, 101, 102); assert_non_null(nfs4_acl); assert_int_equal(smbacl4_get_controlflags(nfs4_acl), SEC_DESC_SELF_RELATIVE); assert_int_equal(smb_get_naces(nfs4_acl), 1); nfs4_ace_container = smb_first_ace4(nfs4_acl); assert_non_null(nfs4_ace_container); assert_null(smb_next_ace4(nfs4_ace_container)); nfs4_ace = smb_get_ace4(nfs4_ace_container); assert_int_equal(nfs4_ace->flags, 0); assert_int_equal(nfs4_ace->who.uid, 1000); assert_int_equal(nfs4_ace->aceFlags, 0); assert_int_equal(nfs4_ace->aceMask, perm_table_dacl_to_nfs4[i].nfs4_perm); } TALLOC_FREE(frame); } /* * Create NFS4 ACL with all possible "special" entries. Verify that * the ones that should be mapped to a DACL are mapped and the other * ones are ignored. */ static void test_special_nfs4_to_dacl(void **state) { struct dom_sid *sids = *state; TALLOC_CTX *frame = talloc_stackframe(); struct SMB4ACL_T *nfs4_acl; SMB_ACE4PROP_T nfs4_ace; struct security_ace *dacl_aces; int good_aces; struct smbacl4_vfs_params params = { .mode = e_simple, .do_chown = true, .acedup = e_merge, .map_full_control = true, }; nfs4_acl = smb_create_smb4acl(frame); assert_non_null(nfs4_acl); nfs4_ace = (SMB_ACE4PROP_T) { .flags = SMB_ACE4_ID_SPECIAL, .who.special_id = SMB_ACE4_WHO_OWNER, .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, .aceFlags = 0, .aceMask = SMB_ACE4_READ_DATA, }; assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); nfs4_ace = (SMB_ACE4PROP_T) { .flags = SMB_ACE4_ID_SPECIAL, .who.special_id = SMB_ACE4_WHO_GROUP, .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, .aceFlags = 0, .aceMask = SMB_ACE4_WRITE_DATA, }; assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); nfs4_ace = (SMB_ACE4PROP_T) { .flags = SMB_ACE4_ID_SPECIAL, .who.special_id = SMB_ACE4_WHO_EVERYONE, .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, .aceFlags = 0, .aceMask = SMB_ACE4_APPEND_DATA, }; assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); nfs4_ace = (SMB_ACE4PROP_T) { .flags = SMB_ACE4_ID_SPECIAL, .who.special_id = SMB_ACE4_WHO_INTERACTIVE, .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, .aceFlags = 0, .aceMask = SMB_ACE4_READ_NAMED_ATTRS, }; assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); nfs4_ace = (SMB_ACE4PROP_T) { .flags = SMB_ACE4_ID_SPECIAL, .who.special_id = SMB_ACE4_WHO_NETWORK, .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, .aceFlags = 0, .aceMask = SMB_ACE4_WRITE_NAMED_ATTRS, }; assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); nfs4_ace = (SMB_ACE4PROP_T) { .flags = SMB_ACE4_ID_SPECIAL, .who.special_id = SMB_ACE4_WHO_DIALUP, .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, .aceFlags = 0, .aceMask = SMB_ACE4_EXECUTE, }; assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); nfs4_ace = (SMB_ACE4PROP_T) { .flags = SMB_ACE4_ID_SPECIAL, .who.special_id = SMB_ACE4_WHO_BATCH, .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, .aceFlags = 0, .aceMask = SMB_ACE4_READ_ATTRIBUTES, }; assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); nfs4_ace = (SMB_ACE4PROP_T) { .flags = SMB_ACE4_ID_SPECIAL, .who.special_id = SMB_ACE4_WHO_ANONYMOUS, .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, .aceFlags = 0, .aceMask = SMB_ACE4_WRITE_ATTRIBUTES, }; assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); nfs4_ace = (SMB_ACE4PROP_T) { .flags = SMB_ACE4_ID_SPECIAL, .who.special_id = SMB_ACE4_WHO_AUTHENTICATED, .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, .aceFlags = 0, .aceMask = SMB_ACE4_READ_ACL, }; assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); nfs4_ace = (SMB_ACE4PROP_T) { .flags = SMB_ACE4_ID_SPECIAL, .who.special_id = SMB_ACE4_WHO_SERVICE, .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, .aceFlags = 0, .aceMask = SMB_ACE4_WRITE_ACL, }; assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); assert_true(smbacl4_nfs42win(frame, ¶ms, nfs4_acl, &sids[0], &sids[1], false, &dacl_aces, &good_aces)); assert_int_equal(good_aces, 3); assert_non_null(dacl_aces); assert_int_equal(dacl_aces[0].type, SEC_ACE_TYPE_ACCESS_ALLOWED); assert_int_equal(dacl_aces[0].flags, 0); assert_int_equal(dacl_aces[0].access_mask, SEC_FILE_READ_DATA); assert_true(dom_sid_equal(&dacl_aces[0].trustee, &sids[0])); assert_int_equal(dacl_aces[1].type, SEC_ACE_TYPE_ACCESS_ALLOWED); assert_int_equal(dacl_aces[1].flags, 0); assert_int_equal(dacl_aces[1].access_mask, SEC_FILE_WRITE_DATA); assert_true(dom_sid_equal(&dacl_aces[1].trustee, &sids[1])); assert_int_equal(dacl_aces[2].type, SEC_ACE_TYPE_ACCESS_ALLOWED); assert_int_equal(dacl_aces[2].flags, 0); assert_int_equal(dacl_aces[2].access_mask, SEC_FILE_APPEND_DATA); assert_true(dom_sid_equal(&dacl_aces[2].trustee, &global_sid_World)); TALLOC_FREE(frame); } static void test_dacl_to_special_nfs4(void **state) { struct dom_sid *sids = *state; TALLOC_CTX *frame = talloc_stackframe(); struct SMB4ACL_T *nfs4_acl; struct SMB4ACE_T *nfs4_ace_container; SMB_ACE4PROP_T *nfs4_ace; struct security_ace dacl_aces[6]; struct security_acl *dacl; struct smbacl4_vfs_params params = { .mode = e_simple, .do_chown = true, .acedup = e_dontcare, .map_full_control = true, }; /* * global_Sid_World is mapped to EVERYONE. */ init_sec_ace(&dacl_aces[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_WRITE_DATA, 0); /* * global_sid_Unix_NFS is ignored. */ init_sec_ace(&dacl_aces[1], &global_sid_Unix_NFS, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, 0); /* * Anything that maps to owner or owning group with inheritance flags * is NOT mapped to special owner or special group. */ init_sec_ace(&dacl_aces[2], &sids[0], SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, SEC_ACE_FLAG_OBJECT_INHERIT); init_sec_ace(&dacl_aces[3], &sids[0], SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); init_sec_ace(&dacl_aces[4], &sids[1], SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, SEC_ACE_FLAG_OBJECT_INHERIT); init_sec_ace(&dacl_aces[5], &sids[1], SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); dacl = make_sec_acl(frame, SECURITY_ACL_REVISION_ADS, ARRAY_SIZE(dacl_aces), dacl_aces); assert_non_null(dacl); nfs4_acl = smbacl4_win2nfs4(frame, true, dacl, ¶ms, 1000, 1001); assert_non_null(nfs4_acl); assert_int_equal(smbacl4_get_controlflags(nfs4_acl), SEC_DESC_SELF_RELATIVE); assert_int_equal(smb_get_naces(nfs4_acl), 5); nfs4_ace_container = smb_first_ace4(nfs4_acl); assert_non_null(nfs4_ace_container); nfs4_ace = smb_get_ace4(nfs4_ace_container); assert_int_equal(nfs4_ace->flags, SMB_ACE4_ID_SPECIAL); assert_int_equal(nfs4_ace->who.special_id, SMB_ACE4_WHO_EVERYONE); assert_int_equal(nfs4_ace->aceFlags, 0); assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_WRITE_DATA); nfs4_ace_container = smb_next_ace4(nfs4_ace_container); assert_non_null(nfs4_ace_container); nfs4_ace = smb_get_ace4(nfs4_ace_container); assert_int_equal(nfs4_ace->flags, 0); assert_int_equal(nfs4_ace->who.uid, 1000); assert_int_equal(nfs4_ace->aceFlags, SMB_ACE4_FILE_INHERIT_ACE); assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA); nfs4_ace_container = smb_next_ace4(nfs4_ace_container); assert_non_null(nfs4_ace_container); nfs4_ace = smb_get_ace4(nfs4_ace_container); assert_int_equal(nfs4_ace->flags, 0); assert_int_equal(nfs4_ace->who.uid, 1000); assert_int_equal(nfs4_ace->aceFlags, SMB_ACE4_DIRECTORY_INHERIT_ACE| SMB_ACE4_INHERIT_ONLY_ACE); assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA); nfs4_ace_container = smb_next_ace4(nfs4_ace_container); assert_non_null(nfs4_ace_container); nfs4_ace = smb_get_ace4(nfs4_ace_container); assert_int_equal(nfs4_ace->flags, 0); assert_int_equal(nfs4_ace->aceFlags, SMB_ACE4_IDENTIFIER_GROUP| SMB_ACE4_FILE_INHERIT_ACE); assert_int_equal(nfs4_ace->who.gid, 1001); assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA); nfs4_ace_container = smb_next_ace4(nfs4_ace_container); assert_non_null(nfs4_ace_container); nfs4_ace = smb_get_ace4(nfs4_ace_container); assert_int_equal(nfs4_ace->flags, 0); assert_int_equal(nfs4_ace->aceFlags, SMB_ACE4_IDENTIFIER_GROUP| SMB_ACE4_DIRECTORY_INHERIT_ACE| SMB_ACE4_INHERIT_ONLY_ACE); assert_int_equal(nfs4_ace->who.gid, 1001); assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA); assert_null(smb_next_ace4(nfs4_ace_container)); TALLOC_FREE(frame); } struct creator_ace_flags { uint32_t dacl_flags; uint32_t nfs4_flags; } creator_ace_flags[] = { { 0, 0 }, { SEC_ACE_FLAG_INHERIT_ONLY, 0 }, { SEC_ACE_FLAG_CONTAINER_INHERIT, SMB_ACE4_DIRECTORY_INHERIT_ACE| SMB_ACE4_INHERIT_ONLY_ACE }, { SEC_ACE_FLAG_CONTAINER_INHERIT| SEC_ACE_FLAG_INHERIT_ONLY, SMB_ACE4_DIRECTORY_INHERIT_ACE| SMB_ACE4_INHERIT_ONLY_ACE }, { SEC_ACE_FLAG_OBJECT_INHERIT, SMB_ACE4_FILE_INHERIT_ACE| SMB_ACE4_INHERIT_ONLY_ACE }, { SEC_ACE_FLAG_OBJECT_INHERIT| SEC_ACE_FLAG_INHERIT_ONLY, SMB_ACE4_FILE_INHERIT_ACE| SMB_ACE4_INHERIT_ONLY_ACE }, { SEC_ACE_FLAG_CONTAINER_INHERIT| SEC_ACE_FLAG_OBJECT_INHERIT, SMB_ACE4_DIRECTORY_INHERIT_ACE| SMB_ACE4_FILE_INHERIT_ACE| SMB_ACE4_INHERIT_ONLY_ACE }, { SEC_ACE_FLAG_CONTAINER_INHERIT| SEC_ACE_FLAG_OBJECT_INHERIT| SEC_ACE_FLAG_INHERIT_ONLY, SMB_ACE4_DIRECTORY_INHERIT_ACE| SMB_ACE4_FILE_INHERIT_ACE| SMB_ACE4_INHERIT_ONLY_ACE }, }; static void test_dacl_creator_to_nfs4(void **state) { TALLOC_CTX *frame = talloc_stackframe(); int i; for (i = 0; i < ARRAY_SIZE(creator_ace_flags); i++) { struct SMB4ACL_T *nfs4_acl; struct SMB4ACE_T *nfs4_ace_container; SMB_ACE4PROP_T *nfs4_ace; struct security_ace dacl_aces[2]; struct security_acl *dacl; struct smbacl4_vfs_params params = { .mode = e_simple, .do_chown = true, .acedup = e_merge, .map_full_control = true, }; init_sec_ace(&dacl_aces[0], &global_sid_Creator_Owner, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, creator_ace_flags[i].dacl_flags); init_sec_ace(&dacl_aces[1], &global_sid_Creator_Group, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, creator_ace_flags[i].dacl_flags); dacl = make_sec_acl(frame, SECURITY_ACL_REVISION_ADS, ARRAY_SIZE(dacl_aces), dacl_aces); assert_non_null(dacl); nfs4_acl = smbacl4_win2nfs4(frame, true, dacl, ¶ms, 101, 102); assert_non_null(nfs4_acl); assert_int_equal(smbacl4_get_controlflags(nfs4_acl), SEC_DESC_SELF_RELATIVE); if (creator_ace_flags[i].nfs4_flags == 0) { /* * CREATOR OWNER and CREATOR GROUP not mapped * in thise case. */ assert_null(smb_first_ace4(nfs4_acl)); } else { assert_int_equal(smb_get_naces(nfs4_acl), 2); nfs4_ace_container = smb_first_ace4(nfs4_acl); assert_non_null(nfs4_ace_container); nfs4_ace = smb_get_ace4(nfs4_ace_container); assert_non_null(nfs4_ace); assert_int_equal(nfs4_ace->flags, SMB_ACE4_ID_SPECIAL); assert_int_equal(nfs4_ace->who.special_id, SMB_ACE4_WHO_OWNER); assert_int_equal(nfs4_ace->aceFlags, creator_ace_flags[i].nfs4_flags); assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA); nfs4_ace_container = smb_next_ace4(nfs4_ace_container); assert_non_null(nfs4_ace_container); assert_null(smb_next_ace4(nfs4_ace_container)); nfs4_ace = smb_get_ace4(nfs4_ace_container); assert_non_null(nfs4_ace); assert_int_equal(nfs4_ace->flags, SMB_ACE4_ID_SPECIAL); assert_int_equal(nfs4_ace->who.special_id, SMB_ACE4_WHO_GROUP); assert_int_equal(nfs4_ace->aceFlags, creator_ace_flags[i].nfs4_flags); assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA); } } TALLOC_FREE(frame); } struct creator_owner_nfs4_to_dacl { uint32_t special_id; uint32_t nfs4_ace_flags; uint32_t dacl_ace_flags; } creator_owner_nfs4_to_dacl[] = { { SMB_ACE4_WHO_OWNER, SMB_ACE4_FILE_INHERIT_ACE, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY }, { SMB_ACE4_WHO_OWNER, SMB_ACE4_DIRECTORY_INHERIT_ACE, SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY }, { SMB_ACE4_WHO_OWNER, SMB_ACE4_FILE_INHERIT_ACE|SMB_ACE4_DIRECTORY_INHERIT_ACE, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT| SEC_ACE_FLAG_INHERIT_ONLY }, { SMB_ACE4_WHO_GROUP, SMB_ACE4_FILE_INHERIT_ACE, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY }, { SMB_ACE4_WHO_GROUP, SMB_ACE4_DIRECTORY_INHERIT_ACE, SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY }, { SMB_ACE4_WHO_GROUP, SMB_ACE4_FILE_INHERIT_ACE|SMB_ACE4_DIRECTORY_INHERIT_ACE, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT| SEC_ACE_FLAG_INHERIT_ONLY }, }; static void test_nfs4_to_dacl_creator(void **state) { struct dom_sid *sids = *state; TALLOC_CTX *frame = talloc_stackframe(); int i; for (i = 0; i < ARRAY_SIZE(creator_owner_nfs4_to_dacl); i++) { struct SMB4ACL_T *nfs4_acl; SMB_ACE4PROP_T nfs4_ace; struct security_ace *dacl_aces, *creator_dacl_ace; int good_aces; struct smbacl4_vfs_params params = { .mode = e_simple, .do_chown = true, .acedup = e_merge, .map_full_control = true, }; nfs4_acl = smb_create_smb4acl(frame); assert_non_null(nfs4_acl); nfs4_ace = (SMB_ACE4PROP_T) { .flags = SMB_ACE4_ID_SPECIAL, .who.special_id = creator_owner_nfs4_to_dacl[i].special_id, .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, .aceFlags = creator_owner_nfs4_to_dacl[i].nfs4_ace_flags, .aceMask = SMB_ACE4_READ_DATA, }; assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); assert_true(smbacl4_nfs42win(frame, ¶ms, nfs4_acl, &sids[0], &sids[1], true, &dacl_aces, &good_aces)); assert_non_null(dacl_aces); if (creator_owner_nfs4_to_dacl[i].nfs4_ace_flags & SMB_ACE4_INHERIT_ONLY_ACE) { /* * Only one ACE entry for the CREATOR ACE entry. */ assert_int_equal(good_aces, 1); creator_dacl_ace = &dacl_aces[0]; } else { /* * This creates an additional ACE entry for * the permissions on the current object. */ assert_int_equal(good_aces, 2); assert_int_equal(dacl_aces[0].type, SEC_ACE_TYPE_ACCESS_ALLOWED); assert_int_equal(dacl_aces[0].flags, 0); assert_int_equal(dacl_aces[0].access_mask, SEC_FILE_READ_DATA); if (creator_owner_nfs4_to_dacl[i].special_id == SMB_ACE4_WHO_OWNER) { assert_true(dom_sid_equal(&dacl_aces[0].trustee, &sids[0])); } if (creator_owner_nfs4_to_dacl[i].special_id == SMB_ACE4_WHO_GROUP) { assert_true(dom_sid_equal(&dacl_aces[0].trustee, &sids[1])); } creator_dacl_ace = &dacl_aces[1]; } assert_int_equal(creator_dacl_ace->type, SEC_ACE_TYPE_ACCESS_ALLOWED); assert_int_equal(creator_dacl_ace->flags, creator_owner_nfs4_to_dacl[i].dacl_ace_flags); assert_int_equal(creator_dacl_ace->access_mask, SEC_FILE_READ_DATA); if (creator_owner_nfs4_to_dacl[i].special_id == SMB_ACE4_WHO_OWNER) { assert_true(dom_sid_equal(&creator_dacl_ace->trustee, &global_sid_Creator_Owner)); } if (creator_owner_nfs4_to_dacl[i].special_id == SMB_ACE4_WHO_GROUP) { assert_true(dom_sid_equal(&creator_dacl_ace->trustee, &global_sid_Creator_Group)); } } TALLOC_FREE(frame); } struct nfs4_to_dacl_map_full_control{ bool is_dir; bool config; bool delete_child_added; } nfs4_to_dacl_full_control[] = { { true, true, false }, { true, false, false }, { false, true, true }, { false, false, false }, }; static void test_full_control_nfs4_to_dacl(void **state) { struct dom_sid *sids = *state; TALLOC_CTX *frame = talloc_stackframe(); int i; for (i = 0; i < ARRAY_SIZE(nfs4_to_dacl_full_control); i++) { struct SMB4ACL_T *nfs4_acl; SMB_ACE4PROP_T nfs4_ace; struct security_ace *dacl_aces; int good_aces; struct smbacl4_vfs_params params = { .mode = e_simple, .do_chown = true, .acedup = e_merge, .map_full_control = nfs4_to_dacl_full_control[i].config, }; const uint32_t nfs4_ace_mask_except_deletes = SMB_ACE4_READ_DATA|SMB_ACE4_WRITE_DATA| SMB_ACE4_APPEND_DATA|SMB_ACE4_READ_NAMED_ATTRS| SMB_ACE4_WRITE_NAMED_ATTRS|SMB_ACE4_EXECUTE| SMB_ACE4_READ_ATTRIBUTES|SMB_ACE4_WRITE_ATTRIBUTES| SMB_ACE4_READ_ACL|SMB_ACE4_WRITE_ACL| SMB_ACE4_WRITE_OWNER|SMB_ACE4_SYNCHRONIZE; const uint32_t dacl_ace_mask_except_deletes = SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA| SEC_FILE_APPEND_DATA|SEC_FILE_READ_EA| SEC_FILE_WRITE_EA|SEC_FILE_EXECUTE| SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE| SEC_STD_READ_CONTROL|SEC_STD_WRITE_DAC| SEC_STD_WRITE_OWNER|SEC_STD_SYNCHRONIZE; nfs4_acl = smb_create_smb4acl(frame); assert_non_null(nfs4_acl); nfs4_ace = (SMB_ACE4PROP_T) { .flags = 0, .who.uid = 1000, .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE, .aceFlags = 0, .aceMask = nfs4_ace_mask_except_deletes, }; assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace)); assert_true( smbacl4_nfs42win(frame, ¶ms, nfs4_acl, &sids[0], &sids[1], nfs4_to_dacl_full_control[i].is_dir, &dacl_aces, &good_aces)); assert_int_equal(good_aces, 1); assert_non_null(dacl_aces); assert_int_equal(dacl_aces[0].type, SEC_ACE_TYPE_ACCESS_ALLOWED); assert_int_equal(dacl_aces[0].flags, 0); assert_true(dom_sid_equal(&dacl_aces[0].trustee, &sids[0])); if (nfs4_to_dacl_full_control[i].delete_child_added) { assert_int_equal(dacl_aces[0].access_mask, dacl_ace_mask_except_deletes| SEC_DIR_DELETE_CHILD); } else { assert_int_equal(dacl_aces[0].access_mask, dacl_ace_mask_except_deletes); } } TALLOC_FREE(frame); } struct acedup_settings { enum smbacl4_acedup_enum setting; } acedup_settings[] = { { e_dontcare }, { e_reject }, { e_ignore }, { e_merge }, }; static void test_dacl_to_nfs4_acedup_settings(void **state) { struct dom_sid *sids = *state; TALLOC_CTX *frame = talloc_stackframe(); int i; for (i = 0; i < ARRAY_SIZE(acedup_settings); i++) { struct SMB4ACL_T *nfs4_acl; struct SMB4ACE_T *nfs4_ace_container; SMB_ACE4PROP_T *nfs4_ace; struct security_ace dacl_aces[2]; struct security_acl *dacl; struct smbacl4_vfs_params params = { .mode = e_simple, .do_chown = true, .acedup = acedup_settings[i].setting, .map_full_control = true, }; init_sec_ace(&dacl_aces[0], &sids[0], SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, SEC_ACE_FLAG_OBJECT_INHERIT); init_sec_ace(&dacl_aces[1], &sids[0], SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_WRITE_DATA, SEC_ACE_FLAG_OBJECT_INHERIT); dacl = make_sec_acl(frame, SECURITY_ACL_REVISION_ADS, ARRAY_SIZE(dacl_aces), dacl_aces); assert_non_null(dacl); nfs4_acl = smbacl4_win2nfs4(frame, true, dacl, ¶ms, 101, 102); switch(params.acedup) { case e_dontcare: assert_non_null(nfs4_acl); assert_int_equal(smbacl4_get_controlflags(nfs4_acl), SEC_DESC_SELF_RELATIVE); assert_int_equal(smb_get_naces(nfs4_acl), 2); nfs4_ace_container = smb_first_ace4(nfs4_acl); assert_non_null(nfs4_ace_container); nfs4_ace = smb_get_ace4(nfs4_ace_container); assert_int_equal(nfs4_ace->flags, 0); assert_int_equal(nfs4_ace->who.uid, 1000); assert_int_equal(nfs4_ace->aceFlags, SMB_ACE4_FILE_INHERIT_ACE); assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA); nfs4_ace_container = smb_next_ace4(nfs4_ace_container); assert_non_null(nfs4_ace_container); assert_null(smb_next_ace4(nfs4_ace_container)); nfs4_ace = smb_get_ace4(nfs4_ace_container); assert_int_equal(nfs4_ace->flags, 0); assert_int_equal(nfs4_ace->who.uid, 1000); assert_int_equal(nfs4_ace->aceFlags, SMB_ACE4_FILE_INHERIT_ACE); assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_WRITE_DATA); break; case e_reject: assert_null(nfs4_acl); assert_int_equal(errno, EINVAL); break; case e_ignore: assert_non_null(nfs4_acl); assert_int_equal(smbacl4_get_controlflags(nfs4_acl), SEC_DESC_SELF_RELATIVE); assert_int_equal(smb_get_naces(nfs4_acl), 1); nfs4_ace_container = smb_first_ace4(nfs4_acl); assert_non_null(nfs4_ace_container); assert_null(smb_next_ace4(nfs4_ace_container)); nfs4_ace = smb_get_ace4(nfs4_ace_container); assert_int_equal(nfs4_ace->flags, 0); assert_int_equal(nfs4_ace->who.uid, 1000); assert_int_equal(nfs4_ace->aceFlags, SMB_ACE4_FILE_INHERIT_ACE); assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA); break; case e_merge: assert_non_null(nfs4_acl); assert_int_equal(smbacl4_get_controlflags(nfs4_acl), SEC_DESC_SELF_RELATIVE); assert_int_equal(smb_get_naces(nfs4_acl), 1); nfs4_ace_container = smb_first_ace4(nfs4_acl); assert_non_null(nfs4_ace_container); assert_null(smb_next_ace4(nfs4_ace_container)); nfs4_ace = smb_get_ace4(nfs4_ace_container); assert_int_equal(nfs4_ace->flags, 0); assert_int_equal(nfs4_ace->who.uid, 1000); assert_int_equal(nfs4_ace->aceFlags, SMB_ACE4_FILE_INHERIT_ACE); assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA| SMB_ACE4_WRITE_DATA); break; default: fail_msg("Unexpected value for acedup: %d\n", params.acedup); }; } TALLOC_FREE(frame); } struct acedup_match { int sid_idx1; enum security_ace_type type1; uint32_t ace_mask1; uint8_t flag1; int sid_idx2; enum security_ace_type type2; uint32_t ace_mask2; uint8_t flag2; bool match; } acedup_match[] = { { 0, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, SEC_ACE_FLAG_OBJECT_INHERIT, 0, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, SEC_ACE_FLAG_OBJECT_INHERIT, true }, { 0, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, SEC_ACE_FLAG_OBJECT_INHERIT, 1, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, SEC_ACE_FLAG_OBJECT_INHERIT, false }, { 0, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, SEC_ACE_FLAG_OBJECT_INHERIT, 0, SEC_ACE_TYPE_ACCESS_DENIED, SEC_FILE_READ_DATA, SEC_ACE_FLAG_OBJECT_INHERIT, false }, { 0, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, SEC_ACE_FLAG_OBJECT_INHERIT, 0, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_WRITE_DATA, SEC_ACE_FLAG_OBJECT_INHERIT, true }, { 0, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, SEC_ACE_FLAG_OBJECT_INHERIT, 0, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, SEC_ACE_FLAG_CONTAINER_INHERIT, false }, { 0, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, SEC_ACE_FLAG_OBJECT_INHERIT, 5, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA, SEC_ACE_FLAG_OBJECT_INHERIT, false }, }; static void test_dacl_to_nfs4_acedup_match(void **state) { struct dom_sid *sids = *state; TALLOC_CTX *frame = talloc_stackframe(); int i; for (i = 0; i < ARRAY_SIZE(acedup_match); i++) { struct SMB4ACL_T *nfs4_acl; struct SMB4ACE_T *nfs4_ace_container; SMB_ACE4PROP_T *nfs4_ace; struct security_ace dacl_aces[2]; struct security_acl *dacl; struct smbacl4_vfs_params params = { .mode = e_simple, .do_chown = true, .acedup = e_ignore, .map_full_control = true, }; init_sec_ace(&dacl_aces[0], &sids[acedup_match[i].sid_idx1], acedup_match[i].type1, acedup_match[i].ace_mask1, acedup_match[i].flag1); init_sec_ace(&dacl_aces[1], &sids[acedup_match[i].sid_idx2], acedup_match[i].type2, acedup_match[i].ace_mask2, acedup_match[i].flag2); dacl = make_sec_acl(frame, SECURITY_ACL_REVISION_ADS, ARRAY_SIZE(dacl_aces), dacl_aces); assert_non_null(dacl); nfs4_acl = smbacl4_win2nfs4(frame, true, dacl, ¶ms, 101, 102); assert_non_null(nfs4_acl); assert_int_equal(smbacl4_get_controlflags(nfs4_acl), SEC_DESC_SELF_RELATIVE); if (acedup_match[i].match) { assert_int_equal(smb_get_naces(nfs4_acl), 1); nfs4_ace_container = smb_first_ace4(nfs4_acl); assert_non_null(nfs4_ace_container); assert_null(smb_next_ace4(nfs4_ace_container)); nfs4_ace = smb_get_ace4(nfs4_ace_container); assert_int_equal(nfs4_ace->flags, 0); assert_int_equal(nfs4_ace->who.uid, 1000); assert_int_equal(nfs4_ace->aceFlags, SMB_ACE4_FILE_INHERIT_ACE); assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA); } else { assert_int_equal(smb_get_naces(nfs4_acl), 2); nfs4_ace_container = smb_first_ace4(nfs4_acl); assert_non_null(nfs4_ace_container); nfs4_ace = smb_get_ace4(nfs4_ace_container); assert_int_equal(nfs4_ace->flags, 0); assert_int_equal(nfs4_ace->who.uid, 1000); assert_int_equal(nfs4_ace->aceFlags, SMB_ACE4_FILE_INHERIT_ACE); assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA); nfs4_ace_container = smb_next_ace4(nfs4_ace_container); assert_non_null(nfs4_ace_container); assert_null(smb_next_ace4(nfs4_ace_container)); nfs4_ace = smb_get_ace4(nfs4_ace_container); assert_int_equal(nfs4_ace->flags, 0); } } TALLOC_FREE(frame); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(test_cached_id_mappings), cmocka_unit_test(test_empty_nfs4_to_dacl), cmocka_unit_test(test_empty_dacl_to_nfs4), cmocka_unit_test(test_acl_type_nfs4_to_dacl), cmocka_unit_test(test_acl_type_dacl_to_nfs4), cmocka_unit_test(test_ace_flags_nfs4_to_dacl), cmocka_unit_test(test_ace_flags_dacl_to_nfs4), cmocka_unit_test(test_nfs4_permissions_to_dacl), cmocka_unit_test(test_dacl_permissions_to_nfs4), cmocka_unit_test(test_special_nfs4_to_dacl), cmocka_unit_test(test_dacl_to_special_nfs4), cmocka_unit_test(test_dacl_creator_to_nfs4), cmocka_unit_test(test_nfs4_to_dacl_creator), cmocka_unit_test(test_full_control_nfs4_to_dacl), cmocka_unit_test(test_dacl_to_nfs4_acedup_settings), cmocka_unit_test(test_dacl_to_nfs4_acedup_match), }; cmocka_set_message_output(CM_OUTPUT_SUBUNIT); if (argc != 2) { print_error("Usage: %s smb.conf\n", argv[0]); exit(1); } /* * Initialize enough of the Samba internals to have the * mappings tests work. */ talloc_stackframe(); lp_load_global(argv[1]); return cmocka_run_group_tests(tests, group_setup, group_teardown); }