r4056: modified the access check code based on results from RAW-ACLS
authorAndrew Tridgell <tridge@samba.org>
Fri, 3 Dec 2004 13:04:10 +0000 (13:04 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:06:20 +0000 (13:06 -0500)
test. Also added generic mapping bits for pvfs. We don't pass RAW-ACLS
yet, but its close.
(This used to be commit c7cbd966d49a5345ea326732587555d209c531fc)

source4/libcli/security/access_check.c
source4/ntvfs/posix/pvfs_acl.c

index d8809aebc67caf92a30e648f7bf90c39d565fa39..7e70736d09e52955ae81a154f2c9916bb49a8690 100644 (file)
@@ -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;
 }
index c584ddc4e8d5f1b4aacfca548b9910acf7a1c486..6eb4c13804f2a352f0af8193deb559828e0bd569 100644 (file)
 #include "librpc/gen_ndr/ndr_xattr.h"
 
 
+/*
+  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
 */
@@ -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;