summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libcli/security/access_check.c52
-rw-r--r--libcli/security/dom_sid.h1
-rw-r--r--libcli/security/util_sid.c2
3 files changed, 49 insertions, 6 deletions
diff --git a/libcli/security/access_check.c b/libcli/security/access_check.c
index d9f6293a46..7f08cb5ed8 100644
--- a/libcli/security/access_check.c
+++ b/libcli/security/access_check.c
@@ -159,6 +159,16 @@ NTSTATUS se_access_check(const struct security_descriptor *sd,
uint32_t i;
uint32_t bits_remaining;
uint32_t explicitly_denied_bits = 0;
+ /*
+ * Up until Windows Server 2008, owner always had these rights. Now
+ * we have to use Owner Rights perms if they are on the file.
+ *
+ * In addition we have to accumulate these bits and apply them
+ * correctly. See bug #8795
+ */
+ uint32_t owner_rights_allowed = 0;
+ uint32_t owner_rights_denied = 0;
+ bool owner_rights_default = true;
*access_granted = access_desired;
bits_remaining = access_desired;
@@ -178,12 +188,6 @@ NTSTATUS se_access_check(const struct security_descriptor *sd,
bits_remaining));
}
- /* the owner always gets SEC_STD_WRITE_DAC and SEC_STD_READ_CONTROL */
- if ((bits_remaining & (SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL)) &&
- security_token_has_sid(token, sd->owner_sid)) {
- bits_remaining &= ~(SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL);
- }
-
/* a NULL dacl allows access */
if ((sd->type & SEC_DESC_DACL_PRESENT) && sd->dacl == NULL) {
*access_granted = access_desired;
@@ -202,6 +206,26 @@ NTSTATUS se_access_check(const struct security_descriptor *sd,
continue;
}
+ /*
+ * We need the Owner Rights permissions to ensure we
+ * give or deny the correct permissions to the owner. Replace
+ * owner_rights with the perms here if it is present.
+ *
+ * We don't care if we are not the owner because that is taken
+ * care of below when we check if our token has the owner SID.
+ *
+ */
+ if (dom_sid_equal(&ace->trustee, &global_sid_Owner_Rights)) {
+ if (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED) {
+ owner_rights_allowed |= ace->access_mask;
+ owner_rights_default = false;
+ } else if (ace->type == SEC_ACE_TYPE_ACCESS_DENIED) {
+ owner_rights_denied |= ace->access_mask;
+ owner_rights_default = false;
+ }
+ continue;
+ }
+
if (!security_token_has_sid(token, &ace->trustee)) {
continue;
}
@@ -219,6 +243,22 @@ NTSTATUS se_access_check(const struct security_descriptor *sd,
}
}
+ /* The owner always gets owner rights as defined above. */
+ if (security_token_has_sid(token, sd->owner_sid)) {
+ if (owner_rights_default) {
+ /*
+ * Just remove them, no need to check if they are
+ * there.
+ */
+ bits_remaining &= ~(SEC_STD_WRITE_DAC |
+ SEC_STD_READ_CONTROL);
+ } else {
+ bits_remaining &= ~owner_rights_allowed;
+ bits_remaining |= owner_rights_denied;
+ }
+ }
+
+ /* Explicitly denied bits always override */
bits_remaining |= explicitly_denied_bits;
/*
diff --git a/libcli/security/dom_sid.h b/libcli/security/dom_sid.h
index df57bd1d9e..c4a417b64a 100644
--- a/libcli/security/dom_sid.h
+++ b/libcli/security/dom_sid.h
@@ -38,6 +38,7 @@ extern const struct dom_sid global_sid_Authenticated_Users;
extern const struct dom_sid global_sid_Network;
extern const struct dom_sid global_sid_Creator_Owner;
extern const struct dom_sid global_sid_Creator_Group;
+extern const struct dom_sid global_sid_Owner_Rights;
extern const struct dom_sid global_sid_Anonymous;
extern const struct dom_sid global_sid_Builtin;
extern const struct dom_sid global_sid_Builtin_Administrators;
diff --git a/libcli/security/util_sid.c b/libcli/security/util_sid.c
index f87d3ebe79..9a24a4ab8f 100644
--- a/libcli/security/util_sid.c
+++ b/libcli/security/util_sid.c
@@ -62,6 +62,8 @@ const struct dom_sid global_sid_Creator_Owner = /* Creator Owner */
{ 1, 1, {0,0,0,0,0,3}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
const struct dom_sid global_sid_Creator_Group = /* Creator Group */
{ 1, 1, {0,0,0,0,0,3}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
+const struct dom_sid global_sid_Owner_Rights = /* Owner Rights */
+{ 1, 1, {0,0,0,0,0,3}, {4,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
const struct dom_sid global_sid_Anonymous = /* Anonymous login */
{ 1, 1, {0,0,0,0,0,5}, {7,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
const struct dom_sid global_sid_Enterprise_DCs = /* Enterprise DCs */