summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/smbd/dosmode.c21
-rw-r--r--source3/smbd/posix_acls.c2
-rw-r--r--source3/smbd/proto.h1
3 files changed, 23 insertions, 1 deletions
diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c
index 0e45e88d8d..1ea4c686d5 100644
--- a/source3/smbd/dosmode.c
+++ b/source3/smbd/dosmode.c
@@ -798,6 +798,27 @@ int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname,
unixmode |= (smb_fname->st.st_ex_mode & (S_IWUSR|S_IWGRP|S_IWOTH));
}
+ /*
+ * From the chmod 2 man page:
+ *
+ * "If the calling process is not privileged, and the group of the file
+ * does not match the effective group ID of the process or one of its
+ * supplementary group IDs, the S_ISGID bit will be turned off, but
+ * this will not cause an error to be returned."
+ *
+ * Simply refuse to do the chmod in this case.
+ */
+
+ if (S_ISDIR(smb_fname->st.st_ex_mode) && (unixmode & S_ISGID) &&
+ geteuid() != sec_initial_uid() &&
+ !current_user_in_group(conn, smb_fname->st.st_ex_gid)) {
+ DEBUG(3,("file_set_dosmode: setgid bit cannot be "
+ "set for directory %s\n",
+ smb_fname_str_dbg(smb_fname)));
+ errno = EPERM;
+ return -1;
+ }
+
ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode);
if (ret == 0) {
if(!newfile || (lret != -1)) {
diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c
index 1d287160b1..9252ee639f 100644
--- a/source3/smbd/posix_acls.c
+++ b/source3/smbd/posix_acls.c
@@ -2656,7 +2656,7 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn,
Check if the current user group list contains a given group.
****************************************************************************/
-static bool current_user_in_group(connection_struct *conn, gid_t gid)
+bool current_user_in_group(connection_struct *conn, gid_t gid)
{
int i;
const struct security_unix_token *utok = get_current_utok(conn);
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index 9366ee6d89..f4b2e5ef59 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -684,6 +684,7 @@ uint32_t map_canon_ace_perms(int snum,
mode_t perms,
bool directory_ace);
NTSTATUS unpack_nt_owners(connection_struct *conn, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, const struct security_descriptor *psd);
+bool current_user_in_group(connection_struct *conn, gid_t gid);
SMB_ACL_T free_empty_sys_acl(connection_struct *conn, SMB_ACL_T the_acl);
NTSTATUS posix_fget_nt_acl(struct files_struct *fsp, uint32_t security_info,
struct security_descriptor **ppdesc);