From b419df1de48609086c7460fdb5d8a20d119e47ee Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Thu, 10 Dec 2009 01:31:53 +1000 Subject: [PATCH] server: Include user groups in file mode calculation when user is file owner. --- server/change.c | 2 +- server/file.c | 27 +++++++++++++++++++++++++-- server/security.h | 1 + server/token.c | 2 +- 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/server/change.c b/server/change.c index 11b4729436a..9a1a02d095d 100644 --- a/server/change.c +++ b/server/change.c @@ -373,7 +373,7 @@ static int dir_set_sd( struct object *obj, const struct security_descriptor *sd, if (set_info & DACL_SECURITY_INFORMATION) { /* keep the bits that we don't map to access rights in the ACL */ - mode = st.st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXG); + mode = st.st_mode & (S_ISUID|S_ISGID|S_ISVTX); mode |= sd_to_mode( sd, owner ); if (((st.st_mode ^ mode) & (S_IRWXU|S_IRWXG|S_IRWXO)) && fchmod( unix_fd, mode ) == -1) diff --git a/server/file.c b/server/file.c index 5db64cdf8cc..15cc34bd29d 100644 --- a/server/file.c +++ b/server/file.c @@ -447,6 +447,7 @@ mode_t sd_to_mode( const struct security_descriptor *sd, const SID *owner ) mode_t denied_mode = 0; int present; const ACL *dacl = sd_get_dacl( sd, &present ); + const SID *user = token_get_user( current->process->token ); if (present && dacl) { const ACE_HEADER *ace = (const ACE_HEADER *)(dacl + 1); @@ -484,6 +485,17 @@ mode_t sd_to_mode( const struct security_descriptor *sd, const SID *owner ) if (access & FILE_EXECUTE) denied_mode |= S_IXUSR; } + else if ((security_equal_sid( user, owner ) && + token_sid_present( current->process->token, sid, TRUE ))) + { + unsigned int access = generic_file_map_access( ad_ace->Mask ); + if (access & FILE_READ_DATA) + denied_mode |= S_IRUSR|S_IRGRP; + if (access & FILE_WRITE_DATA) + denied_mode |= S_IWUSR|S_IWGRP; + if (access & FILE_EXECUTE) + denied_mode |= S_IXUSR|S_IXGRP; + } break; case ACCESS_ALLOWED_ACE_TYPE: aa_ace = (const ACCESS_ALLOWED_ACE *)ace; @@ -508,13 +520,24 @@ mode_t sd_to_mode( const struct security_descriptor *sd, const SID *owner ) if (access & FILE_EXECUTE) new_mode |= S_IXUSR; } + else if ((security_equal_sid( user, owner ) && + token_sid_present( current->process->token, sid, FALSE ))) + { + unsigned int access = generic_file_map_access( ad_ace->Mask ); + if (access & FILE_READ_DATA) + new_mode |= S_IRUSR|S_IRGRP; + if (access & FILE_WRITE_DATA) + new_mode |= S_IWUSR|S_IWGRP; + if (access & FILE_EXECUTE) + new_mode |= S_IXUSR|S_IXGRP; + } break; } } } else /* no ACL means full access rights to anyone */ - new_mode = S_IRWXU | S_IRWXO; + new_mode = S_IRWXU | S_IRWXG | S_IRWXO; return new_mode & ~denied_mode; } @@ -557,7 +580,7 @@ static int file_set_sd( struct object *obj, const struct security_descriptor *sd if (set_info & DACL_SECURITY_INFORMATION) { /* keep the bits that we don't map to access rights in the ACL */ - mode = st.st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXG); + mode = st.st_mode & (S_ISUID|S_ISGID|S_ISVTX); mode |= sd_to_mode( sd, owner ); if (((st.st_mode ^ mode) & (S_IRWXU|S_IRWXG|S_IRWXO)) && fchmod( unix_fd, mode ) == -1) diff --git a/server/security.h b/server/security.h index 39b1d2f72ff..33cf5da3cf0 100644 --- a/server/security.h +++ b/server/security.h @@ -55,6 +55,7 @@ extern int token_check_privileges( struct token *token, int all_required, extern const ACL *token_get_default_dacl( struct token *token ); extern const SID *token_get_user( struct token *token ); extern const SID *token_get_primary_group( struct token *token ); +extern int token_sid_present( struct token *token, const SID *sid, int deny); static inline const ACE_HEADER *ace_next( const ACE_HEADER *ace ) { diff --git a/server/token.c b/server/token.c index 4c45d50ac77..69ffab79090 100644 --- a/server/token.c +++ b/server/token.c @@ -776,7 +776,7 @@ int token_check_privileges( struct token *token, int all_required, return (enabled_count > 0); } -static int token_sid_present( struct token *token, const SID *sid, int deny ) +int token_sid_present( struct token *token, const SID *sid, int deny ) { struct group *group;