summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/libcli/security/access_check.c45
-rw-r--r--source4/ntvfs/posix/pvfs_acl.c41
2 files changed, 60 insertions, 26 deletions
diff --git a/source4/libcli/security/access_check.c b/source4/libcli/security/access_check.c
index d8809aebc6..7e70736d09 100644
--- a/source4/libcli/security/access_check.c
+++ b/source4/libcli/security/access_check.c
@@ -42,13 +42,16 @@ static BOOL sid_active_in_token(struct dom_sid *sid, struct nt_user_token *token
/*
perform a SEC_FLAG_MAXIMUM_ALLOWED access check
*/
-static NTSTATUS access_check_max_allowed(struct security_descriptor *sd,
- struct nt_user_token *token,
- uint32_t *access_granted)
+static uint32_t access_check_max_allowed(struct security_descriptor *sd,
+ struct nt_user_token *token)
{
uint32_t denied = 0, granted = 0;
- int i;
+ unsigned i;
+ if (sid_active_in_token(sd->owner_sid, token)) {
+ granted |= ~(SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL);
+ }
+
for (i = 0;i<sd->dacl->num_aces; i++) {
struct security_ace *ace = &sd->dacl->aces[i];
@@ -67,15 +70,7 @@ static NTSTATUS access_check_max_allowed(struct security_descriptor *sd,
}
}
- granted &= ~denied;
-
- if (granted == 0) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
- *access_granted = granted;
-
- return NT_STATUS_OK;
+ return granted & ~denied;
}
/*
@@ -89,16 +84,15 @@ NTSTATUS sec_access_check(struct security_descriptor *sd,
int i;
uint32_t bits_remaining;
- bits_remaining = access_desired;
-
- /* the owner always gets SEC_STD_WRITE_DAC & SEC_STD_READ_CONTROL */
- if (bits_remaining & (SEC_STD_WRITE_DAC | SEC_STD_READ_CONTROL)) {
- if (sid_active_in_token(sd->owner_sid, token)) {
- bits_remaining &=
- ~(SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL);
- }
+ /* handle the maximum allowed flag */
+ if (access_desired & SEC_FLAG_MAXIMUM_ALLOWED) {
+ access_desired |= access_check_max_allowed(sd, token);
+ access_desired &= ~SEC_FLAG_MAXIMUM_ALLOWED;
}
+ *access_granted = access_desired;
+ bits_remaining = access_desired;
+
#if 0
/* this is where we should check for the "system security" privilege, once we
move to the full security_token and not just the nt_user_token */
@@ -122,9 +116,10 @@ NTSTATUS sec_access_check(struct security_descriptor *sd,
return NT_STATUS_ACCESS_DENIED;
}
- /* handle the maximum allowed case separately */
- if (access_desired == SEC_FLAG_MAXIMUM_ALLOWED) {
- return access_check_max_allowed(sd, token, access_granted);
+ /* the owner always gets SEC_STD_WRITE_DAC & SEC_STD_READ_CONTROL */
+ if ((bits_remaining & (SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL)) &&
+ sid_active_in_token(sd->owner_sid, token)) {
+ bits_remaining &= ~(SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL);
}
/* check each ace in turn. */
@@ -156,7 +151,5 @@ NTSTATUS sec_access_check(struct security_descriptor *sd,
return NT_STATUS_ACCESS_DENIED;
}
- *access_granted = access_desired;
-
return NT_STATUS_OK;
}
diff --git a/source4/ntvfs/posix/pvfs_acl.c b/source4/ntvfs/posix/pvfs_acl.c
index c584ddc4e8..6eb4c13804 100644
--- a/source4/ntvfs/posix/pvfs_acl.c
+++ b/source4/ntvfs/posix/pvfs_acl.c
@@ -28,6 +28,38 @@
/*
+ map a single access_mask from generic to specific bits for files/dirs
+*/
+static uint32_t pvfs_translate_mask(uint32_t access_mask)
+{
+ if (access_mask & SEC_MASK_GENERIC) {
+ if (access_mask & SEC_GENERIC_READ) access_mask |= SEC_RIGHTS_FILE_READ;
+ if (access_mask & SEC_GENERIC_WRITE) access_mask |= SEC_RIGHTS_FILE_WRITE;
+ if (access_mask & SEC_GENERIC_EXECUTE) access_mask |= SEC_RIGHTS_FILE_EXECUTE;
+ if (access_mask & SEC_GENERIC_ALL) access_mask |= SEC_RIGHTS_FILE_ALL;
+ access_mask &= ~SEC_MASK_GENERIC;
+ }
+ return access_mask;
+}
+
+
+/*
+ map any generic access bits in the given acl
+ this relies on the fact that the mappings for files and directories
+ are the same
+*/
+static void pvfs_translate_generic_bits(struct security_acl *acl)
+{
+ unsigned i;
+
+ for (i=0;i<acl->num_aces;i++) {
+ struct security_ace *ace = &acl->aces[i];
+ ace->access_mask = pvfs_translate_mask(ace->access_mask);
+ }
+}
+
+
+/*
setup a default ACL for a file
*/
static NTSTATUS pvfs_default_acl(struct pvfs_state *pvfs,
@@ -222,9 +254,11 @@ NTSTATUS pvfs_acl_set(struct pvfs_state *pvfs,
}
if (secinfo_flags & SECINFO_DACL) {
sd->dacl = new_sd->dacl;
+ pvfs_translate_generic_bits(sd->dacl);
}
if (secinfo_flags & SECINFO_SACL) {
sd->sacl = new_sd->sacl;
+ pvfs_translate_generic_bits(sd->sacl);
}
status = pvfs_acl_save(pvfs, name, fd, acl);
@@ -343,8 +377,15 @@ NTSTATUS pvfs_access_check(struct pvfs_state *pvfs,
return NT_STATUS_INVALID_ACL;
}
+ /* expand the generic access bits to file specific bits */
+ *access_mask = pvfs_translate_mask(*access_mask);
+
+ /* check the acl against the required access mask */
status = sec_access_check(sd, token, *access_mask, access_mask);
+ /* this bit is always granted, even if not asked for */
+ *access_mask |= SEC_FILE_READ_ATTRIBUTE;
+
talloc_free(acl);
return status;