[PATCH] Fix se_access_check() to correctly processes owner rights (S-1-3-4) DENY ace entries.
Jeremy Allison
jra at samba.org
Fri Dec 9 00:10:56 UTC 2016
On Thu, Dec 08, 2016 at 11:47:33AM -0800, Jeremy Allison wrote:
> Follows from the samba-technical conversation I was
> having with Shilpa K <shilpa.krishnareddy at gmail.com>.
>
> When processing DENY ACE entries for owner rights SIDs (S-1-3-4)
> the current code OR's in the deny access mask bits without taking
> into account if they were being requested in the requested access mask.
>
> E.g. The current logic has:
>
> An ACL containining:
>
> [0] SID: S-1-3-4
> TYPE: DENY
> MASK: DENY_WRITE
> [1] SID: S-1-3-4
> TYPE: ALLOW
> MASK: ALLOW_ALL
>
> prohibits an open request by the owner for READ_FILE - even though this is explicitly allowed.
>
> Fix and regression test (that passes against Win2K12) included.
>
> Please review and push if happy,
Slightly updated version with fixed commit message in
patch #1, and updated test in patch #2 (now checks
that asking for WRITE_DATA is correctly rejected
as well as checking READ_DATA succeeds).
Please review and push if happy,
Jeremy.
-------------- next part --------------
From 0fccc2b0450744b750586b2cff15602cc4248bef Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Thu, 8 Dec 2016 10:40:18 -0800
Subject: [PATCH 1/2] lib: security: se_access_check() incorrectly processes
owner rights (S-1-3-4) DENY ace entries
Reported and proposed fix by Shilpa K <shilpa.krishnareddy at gmail.com>.
When processing DENY ACE entries for owner rights SIDs (S-1-3-4) the code OR's in the deny access
mask bits without taking into account if they were being requested in the requested access mask.
E.g. The current logic has:
An ACL containining:
[0] SID: S-1-3-4
TYPE: DENY
MASK: WRITE_DATA
[1] SID: S-1-3-4
TYPE: ALLOW
MASK: ALLOW_ALL
prohibits an open request by the owner for READ_DATA - even though this is explicitly allowed.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12466
Signed-off-by: Jeremy Allison <jra at samba.org>
---
libcli/security/access_check.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/libcli/security/access_check.c b/libcli/security/access_check.c
index 2be5928..6b247f1 100644
--- a/libcli/security/access_check.c
+++ b/libcli/security/access_check.c
@@ -257,7 +257,11 @@ NTSTATUS se_access_check(const struct security_descriptor *sd,
SEC_STD_READ_CONTROL);
} else {
bits_remaining &= ~owner_rights_allowed;
- bits_remaining |= owner_rights_denied;
+ /*
+ * Only add back in bits that were explicitly
+ * requested.
+ */
+ bits_remaining |= (owner_rights_denied & access_desired);
}
}
--
2.8.0.rc3.226.g39d4020
From 71c635fa8814ba496e549e7c6dbbe6c0106f01d6 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Thu, 8 Dec 2016 10:40:27 -0800
Subject: [PATCH 2/2] s3: torture: Adds regression test case for
se_access_check() owner rights issue.
This test passes against Win2K12 but fails against smbd
without the previous commit.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12466
Signed-off-by: Jeremy Allison <jra at samba.org>
---
selftest/skip | 1 +
source3/selftest/tests.py | 2 +-
source3/torture/torture.c | 162 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 164 insertions(+), 1 deletion(-)
diff --git a/selftest/skip b/selftest/skip
index 0893962..1e6d311 100644
--- a/selftest/skip
+++ b/selftest/skip
@@ -49,6 +49,7 @@
^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).POSIX-OFD-LOCK # Fails against the s4 ntvfs server
^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).POSIX-STREAM-DELETE # Fails against the s4 ntvfs server
^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).RENAME-ACCESS # Fails against the s4 ntvfs server
+^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).OWNER-RIGHTS # Don't test against the s4 ntvfs server anymore
^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).PIDHIGH # Fails against the s4 ntvfs server
^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).NTTRANS-FSCTL # Fails against the s4 ntvfs server
^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).SMB2-NEGPROT # Fails against the s4 ntvfs server
diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index a678c77..d9d32cc 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -49,7 +49,7 @@ tests = ["FDPASS", "LOCK1", "LOCK2", "LOCK3", "LOCK4", "LOCK5", "LOCK6", "LOCK7"
"OPLOCK1", "OPLOCK2", "OPLOCK4", "STREAMERROR",
"DIR", "DIR1", "DIR-CREATETIME", "TCON", "TCONDEV", "RW1", "RW2", "RW3", "LARGE_READX", "RW-SIGNING",
"OPEN", "XCOPY", "RENAME", "DELETE", "DELETE-LN", "WILDDELETE", "PROPERTIES", "W2K",
- "TCON2", "IOCTL", "CHKPATH", "FDSESS", "CHAIN1", "CHAIN2",
+ "TCON2", "IOCTL", "CHKPATH", "FDSESS", "CHAIN1", "CHAIN2", "OWNER-RIGHTS",
"CHAIN3", "PIDHIGH",
"GETADDRINFO", "UID-REGRESSION-TEST", "SHORTNAME-TEST",
"CASE-INSENSITIVE-CREATE", "SMB2-BASIC", "NTTRANS-FSCTL", "SMB2-NEGPROT",
diff --git a/source3/torture/torture.c b/source3/torture/torture.c
index ba50462..056e268 100644
--- a/source3/torture/torture.c
+++ b/source3/torture/torture.c
@@ -5086,6 +5086,167 @@ static bool run_rename_access(int dummy)
return false;
}
+/*
+ Test owner rights ACE.
+ */
+static bool run_owner_rights(int dummy)
+{
+ static struct cli_state *cli = NULL;
+ const char *fname = "owner_rights.txt";
+ uint16_t fnum = (uint16_t)-1;
+ struct security_descriptor *sd = NULL;
+ struct security_descriptor *newsd = NULL;
+ NTSTATUS status;
+ TALLOC_CTX *frame = NULL;
+
+ frame = talloc_stackframe();
+ printf("starting owner rights test\n");
+
+ /* Windows connection. */
+ if (!torture_open_connection(&cli, 0)) {
+ goto fail;
+ }
+
+ smbXcli_conn_set_sockopt(cli->conn, sockops);
+
+ /* Start with a clean slate. */
+ cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+
+ /* Create the test file. */
+ /* Now try and open for read and write-dac. */
+ status = cli_ntcreate(cli,
+ fname,
+ 0,
+ GENERIC_ALL_ACCESS,
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ|FILE_SHARE_WRITE|
+ FILE_SHARE_DELETE,
+ FILE_CREATE,
+ 0,
+ 0,
+ &fnum,
+ NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("Create of %s - %s\n", fname, nt_errstr(status));
+ goto fail;
+ }
+
+ /* Get the original SD. */
+ status = cli_query_secdesc(cli,
+ fnum,
+ frame,
+ &sd);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("cli_query_secdesc failed for %s (%s)\n",
+ fname, nt_errstr(status));
+ goto fail;
+ }
+
+ /*
+ * Add an "owner-rights ACE denying WRITE_DATA,
+ * and an "owner-rights ACE allowing everything else.
+ */
+
+ newsd = security_descriptor_dacl_create(frame,
+ 0,
+ NULL,
+ NULL,
+ SID_OWNER_RIGHTS,
+ SEC_ACE_TYPE_ACCESS_DENIED,
+ FILE_WRITE_DATA,
+ 0,
+ SID_OWNER_RIGHTS,
+ SEC_ACE_TYPE_ACCESS_ALLOWED,
+ SEC_RIGHTS_FILE_ALL & ~FILE_WRITE_DATA,
+ 0,
+ NULL);
+ if (newsd == NULL) {
+ goto fail;
+ }
+ sd->dacl = security_acl_concatenate(frame,
+ newsd->dacl,
+ sd->dacl);
+ if (sd->dacl == NULL) {
+ goto fail;
+ }
+ status = cli_set_secdesc(cli, fnum, sd);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("cli_set_secdesc failed for %s (%s)\n",
+ fname, nt_errstr(status));
+ goto fail;
+ }
+ status = cli_close(cli, fnum);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("close failed for %s (%s)\n",
+ fname, nt_errstr(status));
+ goto fail;
+ }
+ fnum = (uint16_t)-1;
+
+ /* Try and open for FILE_WRITE_DATA */
+ status = cli_ntcreate(cli,
+ fname,
+ 0,
+ FILE_WRITE_DATA,
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ|FILE_SHARE_WRITE|
+ FILE_SHARE_DELETE,
+ FILE_OPEN,
+ 0,
+ 0,
+ &fnum,
+ NULL);
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+ printf("Open of %s - %s\n", fname, nt_errstr(status));
+ goto fail;
+ }
+
+ /* Now try and open for FILE_READ_DATA */
+ status = cli_ntcreate(cli,
+ fname,
+ 0,
+ FILE_READ_DATA,
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ|FILE_SHARE_WRITE|
+ FILE_SHARE_DELETE,
+ FILE_OPEN,
+ 0,
+ 0,
+ &fnum,
+ NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("Open of %s - %s\n", fname, nt_errstr(status));
+ goto fail;
+ }
+
+ status = cli_close(cli, fnum);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("close failed for %s (%s)\n",
+ fname, nt_errstr(status));
+ goto fail;
+ }
+
+ cli_unlink(cli, fname,
+ FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+
+ TALLOC_FREE(frame);
+ return true;
+
+ fail:
+
+ if (cli) {
+ if (fnum != -1) {
+ cli_close(cli, fnum);
+ }
+ cli_unlink(cli, fname,
+ FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+ torture_close_connection(cli);
+ }
+
+ TALLOC_FREE(frame);
+ return false;
+}
+
static bool run_pipe_number(int dummy)
{
struct cli_state *cli1;
@@ -10645,6 +10806,7 @@ static struct {
{"XCOPY", run_xcopy, 0},
{"RENAME", run_rename, 0},
{"RENAME-ACCESS", run_rename_access, 0},
+ {"OWNER-RIGHTS", run_owner_rights, 0},
{"DELETE", run_deletetest, 0},
{"WILDDELETE", run_wild_deletetest, 0},
{"DELETE-LN", run_deletetest_ln, 0},
--
2.8.0.rc3.226.g39d4020
More information about the samba-technical
mailing list