From 98223359b8f5fcd374cbf5cc8c8c393b622e4db4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 18 May 2021 12:11:46 -0700 Subject: [PATCH 1/2] s3: torture: Add test for bug 14708 - POSIX default ACL not mapped into returned Windows ACL for directory handles. Knownfail for now. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14708 Signed-off-by: Jeremy Allison --- selftest/knownfail.d/posix_dir_default_acl | 2 + source3/selftest/tests.py | 1 + source3/torture/proto.h | 1 + source3/torture/test_posix.c | 260 +++++++++++++++++++++ source3/torture/torture.c | 4 + source3/wscript_build | 2 + 6 files changed, 270 insertions(+) create mode 100644 selftest/knownfail.d/posix_dir_default_acl diff --git a/selftest/knownfail.d/posix_dir_default_acl b/selftest/knownfail.d/posix_dir_default_acl new file mode 100644 index 00000000000..5c8a5d9af4e --- /dev/null +++ b/selftest/knownfail.d/posix_dir_default_acl @@ -0,0 +1,2 @@ +^samba3.smbtorture_s3.plain.POSIX-DIR-DEFAULT-ACL.smbtorture\(nt4_dc_smb1\) +^samba3.smbtorture_s3.crypt.POSIX-DIR-DEFAULT-ACL.smbtorture\(nt4_dc_smb1\) diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index 11d0a41bda9..20a0e63bed7 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -264,6 +264,7 @@ posix_tests = ["POSIX", "POSIX-APPEND", "POSIX-SYMLINK-ACL", "POSIX-SYMLINK-EA", "POSIX-STAT", "POSIX-SYMLINK-PARENT", "POSIX-SYMLINK-CHMOD", + "POSIX-DIR-DEFAULT-ACL", ] for t in posix_tests: diff --git a/source3/torture/proto.h b/source3/torture/proto.h index 57b1b5fea13..bc2d8c7b3f2 100644 --- a/source3/torture/proto.h +++ b/source3/torture/proto.h @@ -91,6 +91,7 @@ bool run_posix_readlink_test(int dummy); bool run_posix_stat_test(int dummy); bool run_posix_symlink_parent_test(int dummy); bool run_posix_symlink_chmod_test(int dummy); +bool run_posix_dir_default_acl_test(int dummy); bool run_case_insensitive_create(int dummy); bool run_nbench2(int dummy); diff --git a/source3/torture/test_posix.c b/source3/torture/test_posix.c index 33a28866f9f..5416f08aba4 100644 --- a/source3/torture/test_posix.c +++ b/source3/torture/test_posix.c @@ -23,6 +23,7 @@ #include "libsmb/clirap.h" #include "libsmb/proto.h" #include "../libcli/smb/smbXcli_base.h" +#include "util_sd.h" extern struct cli_credentials *torture_creds; extern fstring host, workgroup, share, password, username, myname; @@ -1049,3 +1050,262 @@ out: TALLOC_FREE(frame); return correct; } + +/* + Ensure we get an ACL containing OI|IO ACE entries + after we add a default POSIX ACL to a directory. + This will only ever be an SMB1 test as it depends + on POSIX ACL semantics. + */ +bool run_posix_dir_default_acl_test(int dummy) +{ + TALLOC_CTX *frame = NULL; + struct cli_state *cli_unix = NULL; + NTSTATUS status; + uint16_t fnum = (uint16_t)-1; + const char *dname = "dir_with_default_acl"; + bool correct = false; + SMB_STRUCT_STAT sbuf; + size_t acl_size = 0; + char *aclbuf = NULL; + size_t num_file_acls = 0; + size_t num_dir_acls = 0; + size_t expected_buflen; + uint8_t def_acl[SMB_POSIX_ACL_HEADER_SIZE + + 5*SMB_POSIX_ACL_ENTRY_SIZE] = {0}; + uint8_t *p = NULL; + uint32_t i = 0; + struct security_descriptor *sd = NULL; + bool got_inherit = false; + + frame = talloc_stackframe(); + + printf("Starting POSIX-DIR-DEFAULT-ACL test\n"); + + if (!torture_open_connection(&cli_unix, 0)) { + TALLOC_FREE(frame); + return false; + } + + torture_conn_set_sockopt(cli_unix); + + status = torture_setup_unix_extensions(cli_unix); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return false; + } + + /* Start with a clean slate. */ + cli_posix_unlink(cli_unix, dname); + cli_posix_rmdir(cli_unix, dname); + + status = cli_posix_mkdir(cli_unix, dname, 0777); + if (!NT_STATUS_IS_OK(status)) { + printf("cli_posix_mkdir of %s failed error %s\n", + dname, + nt_errstr(status)); + goto out; + } + + /* Do a posix stat to get the owner. */ + status = cli_posix_stat(cli_unix, dname, &sbuf); + if (!NT_STATUS_IS_OK(status)) { + printf("cli_posix_stat of %s failed %s\n", + dname, + nt_errstr(status)); + goto out; + } + + /* Get the ACL on the directory. */ + status = cli_posix_getacl(cli_unix, dname, frame, &acl_size, &aclbuf); + if (!NT_STATUS_IS_OK(status)) { + printf("cli_posix_getacl on %s failed %s\n", + dname, + nt_errstr(status)); + goto out; + } + + if (acl_size < 6 || SVAL(aclbuf,0) != SMB_POSIX_ACL_VERSION) { + printf("%s, unknown POSIX acl version %u.\n", + dname, + (unsigned int)CVAL(aclbuf,0) ); + goto out; + } + + num_file_acls = SVAL(aclbuf,2); + num_dir_acls = SVAL(aclbuf,4); + + /* + * No overflow check, num_*_acls comes from a 16-bit value, + * and we expect expected_buflen (size_t) to be of at least 32 + * bit. + */ + expected_buflen = SMB_POSIX_ACL_HEADER_SIZE + + SMB_POSIX_ACL_ENTRY_SIZE*(num_file_acls+num_dir_acls); + + if (acl_size != expected_buflen) { + printf("%s, incorrect POSIX acl buffer size " + "(should be %zu, was %zu).\n", + dname, + expected_buflen, + acl_size); + goto out; + } + + if (num_dir_acls != 0) { + printf("%s, POSIX default acl already exists" + "(should be 0, was %zu).\n", + dname, + num_dir_acls); + goto out; + } + + /* + * Get the Windows ACL on the directory. + * Make sure there are no inheritable entries. + */ + status = cli_ntcreate(cli_unix, + dname, + 0, + SEC_STD_READ_CONTROL, + 0, + FILE_SHARE_READ| + FILE_SHARE_WRITE| + FILE_SHARE_DELETE, + FILE_OPEN, + FILE_DIRECTORY_FILE, + 0x0, + &fnum, + NULL); + if (!NT_STATUS_IS_OK(status)) { + printf("Failed to open directory %s: %s\n", + dname, + nt_errstr(status)); + goto out; + } + + status = cli_query_security_descriptor(cli_unix, + fnum, + SECINFO_DACL, + frame, + &sd); + if (!NT_STATUS_IS_OK(status)) { + printf("Failed to get security descriptor on directory %s: %s\n", + dname, + nt_errstr(status)); + goto out; + } + + for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) { + struct security_ace *ace = &sd->dacl->aces[i]; + if (ace->flags & (SEC_ACE_FLAG_OBJECT_INHERIT| + SEC_ACE_FLAG_CONTAINER_INHERIT)) { + printf("security descritor on directory %s already " + "contains inheritance flags\n", + dname); + sec_desc_print(NULL, stdout, sd, true); + goto out; + } + } + + TALLOC_FREE(sd); + + /* Construct a new default ACL. */ + SSVAL(def_acl,0,SMB_POSIX_ACL_VERSION); + SSVAL(def_acl,2,SMB_POSIX_IGNORE_ACE_ENTRIES); + SSVAL(def_acl,4,5); /* num_dir_acls. */ + + p = def_acl + SMB_POSIX_ACL_HEADER_SIZE; + + /* USER_OBJ. */ + SCVAL(p,0,SMB_POSIX_ACL_USER_OBJ); /* tagtype. */ + SCVAL(p,1,SMB_POSIX_ACL_READ|SMB_POSIX_ACL_WRITE|SMB_POSIX_ACL_EXECUTE); + p += SMB_POSIX_ACL_ENTRY_SIZE; + + /* GROUP_OBJ. */ + SCVAL(p,0,SMB_POSIX_ACL_GROUP_OBJ); /* tagtype. */ + SCVAL(p,1,SMB_POSIX_ACL_READ|SMB_POSIX_ACL_WRITE|SMB_POSIX_ACL_EXECUTE); + p += SMB_POSIX_ACL_ENTRY_SIZE; + + /* OTHER. */ + SCVAL(p,0,SMB_POSIX_ACL_OTHER); /* tagtype. */ + SCVAL(p,1,SMB_POSIX_ACL_READ|SMB_POSIX_ACL_WRITE|SMB_POSIX_ACL_EXECUTE); + p += SMB_POSIX_ACL_ENTRY_SIZE; + + /* Explicit user. */ + SCVAL(p,0,SMB_POSIX_ACL_USER); /* tagtype. */ + SCVAL(p,1,SMB_POSIX_ACL_READ|SMB_POSIX_ACL_WRITE|SMB_POSIX_ACL_EXECUTE); + SIVAL(p,2,sbuf.st_ex_uid); + p += SMB_POSIX_ACL_ENTRY_SIZE; + + /* MASK. */ + SCVAL(p,0,SMB_POSIX_ACL_MASK); /* tagtype. */ + SCVAL(p,1,SMB_POSIX_ACL_READ|SMB_POSIX_ACL_WRITE|SMB_POSIX_ACL_EXECUTE); + p += SMB_POSIX_ACL_ENTRY_SIZE; + + /* Set the POSIX default ACL. */ + status = cli_posix_setacl(cli_unix, dname, def_acl, sizeof(def_acl)); + if (!NT_STATUS_IS_OK(status)) { + printf("cli_posix_setacl on %s failed %s\n", + dname, + nt_errstr(status)); + goto out; + } + + /* + * Get the Windows ACL on the directory again. + * Now there should be inheritable entries. + */ + + status = cli_query_security_descriptor(cli_unix, + fnum, + SECINFO_DACL, + frame, + &sd); + if (!NT_STATUS_IS_OK(status)) { + printf("Failed (2) to get security descriptor " + "on directory %s: %s\n", + dname, + nt_errstr(status)); + goto out; + } + + for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) { + struct security_ace *ace = &sd->dacl->aces[i]; + if (ace->flags & (SEC_ACE_FLAG_OBJECT_INHERIT| + SEC_ACE_FLAG_CONTAINER_INHERIT)) { + got_inherit = true; + break; + } + } + + if (!got_inherit) { + printf("security descritor on directory %s does not " + "contain inheritance flags\n", + dname); + sec_desc_print(NULL, stdout, sd, true); + goto out; + } + + cli_close(cli_unix, fnum); + fnum = (uint16_t)-1; + printf("POSIX-DIR-DEFAULT-ACL test passed\n"); + correct = true; + +out: + + TALLOC_FREE(sd); + + if (fnum != (uint16_t)-1) { + cli_close(cli_unix, fnum); + } + cli_posix_unlink(cli_unix, dname); + cli_posix_rmdir(cli_unix, dname); + + if (!torture_close_connection(cli_unix)) { + correct = false; + } + + TALLOC_FREE(frame); + return correct; +} diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 68e2cd2ba20..06bb44943e6 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -14955,6 +14955,10 @@ static struct { .name = "POSIX-SYMLINK-CHMOD", .fn = run_posix_symlink_chmod_test, }, + { + .name = "POSIX-DIR-DEFAULT-ACL", + .fn = run_posix_dir_default_acl_test, + }, { .name = "WINDOWS-BAD-SYMLINK", .fn = run_symlink_open_test, diff --git a/source3/wscript_build b/source3/wscript_build index 4703d5baff4..d0fda816f56 100644 --- a/source3/wscript_build +++ b/source3/wscript_build @@ -1225,6 +1225,7 @@ bld.SAMBA3_BINARY('smbtorture' + bld.env.suffix3, torture/test_idmap_cache.c torture/test_hidenewfiles.c torture/test_readdir_timestamp.c + lib/util_sd.c ''' + TORTURE3_ADDITIONAL_SOURCE, deps=''' talloc @@ -1238,6 +1239,7 @@ bld.SAMBA3_BINARY('smbtorture' + bld.env.suffix3, NDR_OPEN_FILES idmap IDMAP_TDB_COMMON + libcli_lsa3 samba-cluster-support ''', cflags='-DWINBINDD_SOCKET_DIR=\"%s\"' % bld.env.WINBINDD_SOCKET_DIR, -- 2.27.0 From f7c55ad99b8cb44546ff585fa8defd5038ee7b31 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 17 May 2021 15:34:55 -0700 Subject: [PATCH 2/2] s3: smbd: Ensure POSIX default ACL is mapped into returned Windows ACL for directory handles. Remove knownfail. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14708 Signed-off-by: Jeremy Allison --- selftest/knownfail.d/posix_dir_default_acl | 2 -- source3/smbd/posix_acls.c | 12 +++++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) delete mode 100644 selftest/knownfail.d/posix_dir_default_acl diff --git a/selftest/knownfail.d/posix_dir_default_acl b/selftest/knownfail.d/posix_dir_default_acl deleted file mode 100644 index 5c8a5d9af4e..00000000000 --- a/selftest/knownfail.d/posix_dir_default_acl +++ /dev/null @@ -1,2 +0,0 @@ -^samba3.smbtorture_s3.plain.POSIX-DIR-DEFAULT-ACL.smbtorture\(nt4_dc_smb1\) -^samba3.smbtorture_s3.crypt.POSIX-DIR-DEFAULT-ACL.smbtorture\(nt4_dc_smb1\) diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index c3e00fa2475..489a4695ba1 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3426,6 +3426,7 @@ NTSTATUS posix_fget_nt_acl(struct files_struct *fsp, uint32_t security_info, { SMB_STRUCT_STAT sbuf; SMB_ACL_T posix_acl = NULL; + SMB_ACL_T def_acl = NULL; struct pai_val *pal; TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status; @@ -3444,10 +3445,19 @@ NTSTATUS posix_fget_nt_acl(struct files_struct *fsp, uint32_t security_info, /* Get the ACL from the fd. */ posix_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, frame); + /* If it's a directory get the default POSIX ACL. */ + if(fsp->fsp_flags.is_directory) { + def_acl = SMB_VFS_SYS_ACL_GET_FILE(fsp->conn, + fsp->fsp_name, + SMB_ACL_TYPE_DEFAULT, + frame); + def_acl = free_empty_sys_acl(fsp->conn, def_acl); + } + pal = fload_inherited_info(fsp); status = posix_get_nt_acl_common(fsp->conn, fsp->fsp_name->base_name, - &sbuf, pal, posix_acl, NULL, + &sbuf, pal, posix_acl, def_acl, security_info, mem_ctx, ppdesc); TALLOC_FREE(frame); return status; -- 2.27.0