diff options
Diffstat (limited to 'source4')
-rw-r--r-- | source4/libcli/security/access_check.c | 45 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_acl.c | 41 |
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; |