diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/smbd/posix_acls.c | 48 |
1 files changed, 34 insertions, 14 deletions
diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index ffb1698394..91a3f5ed48 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3910,6 +3910,7 @@ static int check_posix_acl_group_write(connection_struct *conn, const char *fnam SMB_ACL_ENTRY_T entry; int i; BOOL seen_mask = False; + BOOL seen_owning_group = False; int ret = -1; gid_t cu_gid; @@ -3950,6 +3951,7 @@ static int check_posix_acl_group_write(connection_struct *conn, const char *fnam switch(tagtype) { case SMB_ACL_MASK: + seen_mask = True; if (!have_write) { /* We don't have any group or explicit user write permission. */ ret = -1; /* Allow caller to check "other" permissions. */ @@ -3957,7 +3959,6 @@ static int check_posix_acl_group_write(connection_struct *conn, const char *fnam refusing write due to mask.\n", fname)); goto done; } - seen_mask = True; break; case SMB_ACL_USER: { @@ -4019,8 +4020,16 @@ match on user %u -> %s.\n", fname, (unsigned int)*puid, ret ? "can write" : "can switch(tagtype) { case SMB_ACL_GROUP: + case SMB_ACL_GROUP_OBJ: { - gid_t *pgid = (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry); + gid_t *pgid = NULL; + + if (tagtype == SMB_ACL_GROUP) { + pgid = (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry); + } else { + seen_owning_group = True; + pgid = &psbuf->st_gid; + } if (pgid == NULL) { goto check_stat; } @@ -4059,24 +4068,35 @@ match on group %u -> can write.\n", fname, (unsigned int)cu_gid )); check_stat: - /* Do we match on the owning group entry ? */ /* - * Does it match the current effective group - * or supplementary groups ? + * We only check the S_IWGRP permissions if we haven't already + * seen an owning group SMB_ACL_GROUP_OBJ ace entry. If there is an + * SMB_ACL_GROUP_OBJ ace entry then the group bits in st_gid are + * the same as the SMB_ACL_MASK bits, not the SMB_ACL_GROUP_OBJ + * bits. Thanks to Marc Cousin <mcousin@sigma.fr> for pointing + * this out. JRA. */ - for (cu_gid = get_current_user_gid_first(&i); cu_gid != (gid_t)-1; - cu_gid = get_current_user_gid_next(&i)) { - if (cu_gid == psbuf->st_gid) { - ret = (psbuf->st_mode & S_IWGRP) ? 1 : 0; - DEBUG(10,("check_posix_acl_group_write: file %s \ + + if (!seen_owning_group) { + /* Do we match on the owning group entry ? */ + /* + * Does it match the current effective group + * or supplementary groups ? + */ + for (cu_gid = get_current_user_gid_first(&i); cu_gid != (gid_t)-1; + cu_gid = get_current_user_gid_next(&i)) { + if (cu_gid == psbuf->st_gid) { + ret = (psbuf->st_mode & S_IWGRP) ? 1 : 0; + DEBUG(10,("check_posix_acl_group_write: file %s \ match on owning group %u -> %s.\n", fname, (unsigned int)psbuf->st_gid, ret ? "can write" : "cannot write")); - break; + break; + } } - } - if (cu_gid == (gid_t)-1) { - DEBUG(10,("check_posix_acl_group_write: file %s \ + if (cu_gid == (gid_t)-1) { + DEBUG(10,("check_posix_acl_group_write: file %s \ failed to match on user or group in token (ret = %d).\n", fname, ret )); + } } done: |