summaryrefslogtreecommitdiffstats
path: root/source3/modules/test_nfs4_acls.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 17:20:00 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 17:20:00 +0000
commit8daa83a594a2e98f39d764422bfbdbc62c9efd44 (patch)
tree4099e8021376c7d8c05bdf8503093d80e9c7bad0 /source3/modules/test_nfs4_acls.c
parentInitial commit. (diff)
downloadsamba-8daa83a594a2e98f39d764422bfbdbc62c9efd44.tar.xz
samba-8daa83a594a2e98f39d764422bfbdbc62c9efd44.zip
Adding upstream version 2:4.20.0+dfsg.upstream/2%4.20.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'source3/modules/test_nfs4_acls.c')
-rw-r--r--source3/modules/test_nfs4_acls.c1898
1 files changed, 1898 insertions, 0 deletions
diff --git a/source3/modules/test_nfs4_acls.c b/source3/modules/test_nfs4_acls.c
new file mode 100644
index 0000000..f47ff9b
--- /dev/null
+++ b/source3/modules/test_nfs4_acls.c
@@ -0,0 +1,1898 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "nfs4_acls.c"
+#include "librpc/gen_ndr/idmap.h"
+#include "idmap_cache.h"
+#include <cmocka.h>
+
+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, &params, 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, &params, 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, &params, 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, &params,
+ 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, &params, 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, &params,
+ 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, &params, 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, &params,
+ 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, &params, 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, &params, 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, &params,
+ 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 this 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, &params, 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, &params, 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, &params,
+ 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, &params,
+ 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);
+}
+
+static void test_dacl_to_nfs4_config_special(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_special,
+ .do_chown = true,
+ .acedup = e_dontcare,
+ .map_full_control = true,
+ };
+
+ /*
+ * global_sid_Creator_Owner or global_sid_Special_Group is NOT mapped
+ * to SMB_ACE4_ID_SPECIAL.
+ */
+ init_sec_ace(&dacl_aces[0], &global_sid_Creator_Owner,
+ SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_READ_DATA,
+ SEC_ACE_FLAG_OBJECT_INHERIT);
+ init_sec_ace(&dacl_aces[1], &global_sid_Creator_Group,
+ SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_FILE_WRITE_DATA,
+ SEC_ACE_FLAG_CONTAINER_INHERIT);
+ /*
+ * Anything that maps to owner or owning group with inheritance flags
+ * IS 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, &params, 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), 6);
+
+ 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->aceFlags, SMB_ACE4_FILE_INHERIT_ACE);
+ assert_int_equal(nfs4_ace->who.uid, 1003);
+ 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);
+ assert_int_equal(nfs4_ace->who.gid, 1004);
+ 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, SMB_ACE4_ID_SPECIAL);
+ assert_int_equal(nfs4_ace->who.special_id, SMB_ACE4_WHO_OWNER);
+ 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, SMB_ACE4_ID_SPECIAL);
+ assert_int_equal(nfs4_ace->aceFlags, SMB_ACE4_DIRECTORY_INHERIT_ACE|
+ SMB_ACE4_INHERIT_ONLY_ACE);
+ assert_int_equal(nfs4_ace->who.special_id, SMB_ACE4_WHO_OWNER);
+ 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, SMB_ACE4_ID_SPECIAL);
+ assert_int_equal(nfs4_ace->aceFlags, SMB_ACE4_IDENTIFIER_GROUP|
+ SMB_ACE4_FILE_INHERIT_ACE);
+ assert_int_equal(nfs4_ace->who.special_id, SMB_ACE4_WHO_GROUP);
+ 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, SMB_ACE4_ID_SPECIAL);
+ 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.special_id, SMB_ACE4_WHO_GROUP);
+ assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA);
+
+ assert_null(smb_next_ace4(nfs4_ace_container));
+
+ TALLOC_FREE(frame);
+}
+
+static void test_nfs4_to_dacl_config_special(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_special,
+ .do_chown = true,
+ .acedup = e_dontcare,
+ .map_full_control = true,
+ };
+
+ nfs4_acl = smb_create_smb4acl(frame);
+ assert_non_null(nfs4_acl);
+
+ /*
+ * In config mode special, this is not mapped to Creator Owner
+ */
+ 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 = SMB_ACE4_FILE_INHERIT_ACE,
+ .aceMask = SMB_ACE4_READ_DATA,
+ };
+ assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace));
+
+ /*
+ * In config mode special, this is not mapped to Creator Group
+ */
+ 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 = SMB_ACE4_DIRECTORY_INHERIT_ACE,
+ .aceMask = SMB_ACE4_WRITE_DATA,
+ };
+ assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace));
+
+ assert_true(smbacl4_nfs42win(frame, &params, nfs4_acl,
+ &sids[0], &sids[1], true,
+ &dacl_aces, &good_aces));
+
+ assert_int_equal(good_aces, 2);
+ assert_non_null(dacl_aces);
+
+ assert_int_equal(dacl_aces[0].type, SEC_ACE_TYPE_ACCESS_ALLOWED);
+ assert_int_equal(dacl_aces[0].flags, SEC_ACE_FLAG_OBJECT_INHERIT);
+ 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, SEC_ACE_FLAG_CONTAINER_INHERIT);
+ assert_int_equal(dacl_aces[1].access_mask, SEC_FILE_WRITE_DATA);
+ assert_true(dom_sid_equal(&dacl_aces[1].trustee, &sids[1]));
+
+ TALLOC_FREE(frame);
+}
+
+struct nfs_to_dacl_idmap_both {
+ uint32_t nfs4_flags;
+ uint32_t nfs4_id;
+ struct dom_sid *sid;
+};
+
+static void test_nfs4_to_dacl_idmap_type_both(void **state)
+{
+ struct dom_sid *sids = *state;
+ TALLOC_CTX *frame = talloc_stackframe();
+ int i;
+ struct nfs_to_dacl_idmap_both nfs_to_dacl_idmap_both[] = {
+ { 0, 1002, &sids[2] },
+ { SMB_ACE4_IDENTIFIER_GROUP, 1002, &sids[2] },
+ { 0, 1005, &sids[6] },
+ { SMB_ACE4_IDENTIFIER_GROUP, 1005, &sids[6] },
+ };
+
+ for (i = 0; i < ARRAY_SIZE(nfs_to_dacl_idmap_both); i++) {
+ struct SMB4ACL_T *nfs4_acl;
+ struct security_ace *dacl_aces;
+ SMB_ACE4PROP_T nfs4_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 = 0,
+ .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE,
+ .aceFlags = nfs_to_dacl_idmap_both[i].nfs4_flags,
+ .aceMask = SMB_ACE4_READ_DATA,
+ };
+
+ if (nfs_to_dacl_idmap_both[i].nfs4_flags &
+ SMB_ACE4_IDENTIFIER_GROUP) {
+ nfs4_ace.who.gid = nfs_to_dacl_idmap_both[i].nfs4_id;
+ } else {
+ nfs4_ace.who.uid = nfs_to_dacl_idmap_both[i].nfs4_id;
+ }
+ assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace));
+
+ assert_true(smbacl4_nfs42win(frame, &params, nfs4_acl,
+ &sids[2], &sids[2],
+ 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, SEC_FILE_READ_DATA);
+ assert_true(dom_sid_equal(&dacl_aces[0].trustee,
+ nfs_to_dacl_idmap_both[i].sid));
+ }
+
+ TALLOC_FREE(frame);
+}
+
+struct dacl_to_nfs4_idmap_both {
+ struct dom_sid *sid;
+ uint32_t dacl_flags;
+ uint32_t nfs4_flags;
+ uint32_t nfs4_ace_flags;
+ uint32_t nfs4_id;
+ int num_nfs4_aces;
+};
+
+/*
+ * IDMAP_TYPE_BOTH always creates group entries.
+ */
+static void test_dacl_to_nfs4_idmap_type_both(void **state)
+{
+ struct dom_sid *sids = *state;
+ TALLOC_CTX *frame = talloc_stackframe();
+ int i;
+
+ struct dacl_to_nfs4_idmap_both dacl_to_nfs4_idmap_both[] = {
+ { &sids[2], 0,
+ SMB_ACE4_ID_SPECIAL, SMB_ACE4_IDENTIFIER_GROUP, SMB_ACE4_WHO_GROUP,
+ 2 },
+ { &sids[2], SEC_ACE_FLAG_OBJECT_INHERIT,
+ 0, SMB_ACE4_IDENTIFIER_GROUP|SMB_ACE4_FILE_INHERIT_ACE, 1002,
+ 1 },
+ { &sids[6], 0,
+ 0, SMB_ACE4_IDENTIFIER_GROUP, 1005,
+ 1 },
+ { &sids[6], SEC_ACE_FLAG_OBJECT_INHERIT,
+ 0, SMB_ACE4_IDENTIFIER_GROUP|SMB_ACE4_FILE_INHERIT_ACE, 1005,
+ 1 },
+ };
+
+ for (i = 0; i < ARRAY_SIZE(dacl_to_nfs4_idmap_both); 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], dacl_to_nfs4_idmap_both[i].sid,
+ SEC_ACE_TYPE_ACCESS_ALLOWED,
+ SEC_FILE_READ_DATA,
+ dacl_to_nfs4_idmap_both[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, &params,
+ 1002, 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),
+ dacl_to_nfs4_idmap_both[i].num_nfs4_aces);
+
+ 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,
+ dacl_to_nfs4_idmap_both[i].nfs4_flags);
+ assert_int_equal(nfs4_ace->aceFlags,
+ dacl_to_nfs4_idmap_both[i].nfs4_ace_flags);
+ if (nfs4_ace->flags & SMB_ACE4_ID_SPECIAL) {
+ assert_int_equal(nfs4_ace->who.special_id,
+ dacl_to_nfs4_idmap_both[i].nfs4_id);
+ } else if (nfs4_ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) {
+ assert_int_equal(nfs4_ace->who.gid,
+ dacl_to_nfs4_idmap_both[i].nfs4_id);
+ } else {
+ assert_int_equal(nfs4_ace->who.uid,
+ dacl_to_nfs4_idmap_both[i].nfs4_id);
+ }
+ assert_int_equal(nfs4_ace->aceType,
+ SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE);
+ assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA);
+
+ if (dacl_to_nfs4_idmap_both[i].num_nfs4_aces == 2) {
+ 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,
+ dacl_to_nfs4_idmap_both[i].nfs4_flags);
+ assert_int_equal(nfs4_ace->aceFlags,
+ dacl_to_nfs4_idmap_both[i].nfs4_ace_flags &
+ ~SMB_ACE4_IDENTIFIER_GROUP);
+ if (nfs4_ace->flags & SMB_ACE4_ID_SPECIAL) {
+ assert_int_equal(nfs4_ace->who.special_id,
+ SMB_ACE4_WHO_OWNER);
+ } else {
+ assert_int_equal(nfs4_ace->who.uid,
+ dacl_to_nfs4_idmap_both[i].nfs4_id);
+ }
+ assert_int_equal(nfs4_ace->aceType,
+ SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE);
+ assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA);
+ }
+ }
+
+ TALLOC_FREE(frame);
+}
+
+static void test_nfs4_to_dacl_remove_duplicate(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_dontcare,
+ .map_full_control = true,
+ };
+
+ nfs4_acl = smb_create_smb4acl(frame);
+ assert_non_null(nfs4_acl);
+
+ nfs4_ace = (SMB_ACE4PROP_T) {
+ .flags = 0,
+ .who.uid = 1002,
+ .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE,
+ .aceFlags = SMB_ACE4_INHERITED_ACE,
+ .aceMask = SMB_ACE4_WRITE_DATA,
+ };
+ assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace));
+
+ nfs4_ace = (SMB_ACE4PROP_T) {
+ .flags = 0,
+ .who.gid = 1002,
+ .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE,
+ .aceFlags = SMB_ACE4_IDENTIFIER_GROUP|
+ SMB_ACE4_INHERITED_ACE,
+ .aceMask = SMB_ACE4_WRITE_DATA,
+ };
+ assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace));
+
+ nfs4_ace = (SMB_ACE4PROP_T) {
+ .flags = 0,
+ .who.gid = 1002,
+ .aceType = SMB_ACE4_ACCESS_DENIED_ACE_TYPE,
+ .aceFlags = SMB_ACE4_IDENTIFIER_GROUP|
+ SMB_ACE4_INHERITED_ACE,
+ .aceMask = SMB_ACE4_WRITE_DATA,
+ };
+ assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace));
+
+ nfs4_ace = (SMB_ACE4PROP_T) {
+ .flags = 0,
+ .who.gid = 1002,
+ .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE,
+ .aceFlags = SMB_ACE4_IDENTIFIER_GROUP|
+ SMB_ACE4_INHERITED_ACE,
+ .aceMask = SMB_ACE4_WRITE_DATA,
+ };
+ assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace));
+
+ assert_true(smbacl4_nfs42win(frame, &params, nfs4_acl,
+ &sids[0], &sids[1], true,
+ &dacl_aces, &good_aces));
+
+ assert_int_equal(good_aces, 2);
+ assert_non_null(dacl_aces);
+
+ assert_int_equal(dacl_aces[0].type, SEC_ACE_TYPE_ACCESS_ALLOWED);
+ assert_int_equal(dacl_aces[0].flags, SEC_ACE_FLAG_INHERITED_ACE);
+ assert_int_equal(dacl_aces[0].access_mask, SEC_FILE_WRITE_DATA);
+ assert_true(dom_sid_equal(&dacl_aces[0].trustee, &sids[2]));
+
+ assert_int_equal(dacl_aces[1].type, SEC_ACE_TYPE_ACCESS_DENIED);
+ assert_int_equal(dacl_aces[1].flags, SEC_ACE_FLAG_INHERITED_ACE);
+ assert_int_equal(dacl_aces[1].access_mask, SEC_FILE_WRITE_DATA);
+ assert_true(dom_sid_equal(&dacl_aces[1].trustee, &sids[2]));
+
+ 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_unit_test(test_dacl_to_nfs4_config_special),
+ cmocka_unit_test(test_nfs4_to_dacl_config_special),
+ cmocka_unit_test(test_nfs4_to_dacl_idmap_type_both),
+ cmocka_unit_test(test_dacl_to_nfs4_idmap_type_both),
+ cmocka_unit_test(test_nfs4_to_dacl_remove_duplicate),
+ };
+
+ 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);
+}