diff options
-rw-r--r-- | source3/param/loadparm.c | 4 | ||||
-rw-r--r-- | source3/smbd/dosmode.c | 17 | ||||
-rw-r--r-- | source3/smbd/nttrans.c | 4 | ||||
-rw-r--r-- | source3/smbd/posix_acls.c | 19 |
4 files changed, 28 insertions, 16 deletions
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 8043f8864d..0ddd6bb0c7 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -436,6 +436,7 @@ typedef struct BOOL bMap_acl_inherit; BOOL bAfs_Share; BOOL bEASupport; + BOOL bAclCheckPermissions; int iallocation_roundup_size; param_opt_struct *param_opt; @@ -563,6 +564,7 @@ static service sDefault = { False, /* bMap_acl_inherit */ False, /* bAfs_Share */ False, /* bEASupport */ + True, /* bAclCheckPermissions */ SMB_ROUNDUP_ALLOCATION_SIZE, /* iallocation_roundup_size */ NULL, /* Parametric options */ @@ -865,6 +867,7 @@ static struct parm_struct parm_table[] = { {"writeable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_HIDE}, {"writable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_HIDE}, + {"acl check permissions", P_BOOL, P_LOCAL, &sDefault.bAclCheckPermissions, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, {"create mask", P_OCTAL, P_LOCAL, &sDefault.iCreate_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, {"create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_mask, NULL, NULL, FLAG_HIDE}, {"force create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, @@ -1968,6 +1971,7 @@ FN_LOCAL_BOOL(_lp_use_sendfile, bUseSendfile) FN_LOCAL_BOOL(lp_profile_acls, bProfileAcls) FN_LOCAL_BOOL(lp_map_acl_inherit, bMap_acl_inherit) FN_LOCAL_BOOL(lp_afs_share, bAfs_Share) +FN_LOCAL_BOOL(lp_acl_check_permissions, bAclCheckPermissions) FN_LOCAL_INTEGER(lp_create_mask, iCreate_mask) FN_LOCAL_INTEGER(lp_force_create_mode, iCreate_force_mode) FN_LOCAL_INTEGER(lp_security_mask, iSecurity_mask) diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 3a0e81e5fe..65ea2807e7 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -116,13 +116,18 @@ mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname, BOOL c Change a unix mode to a dos mode. ****************************************************************************/ -uint32 dos_mode_from_sbuf(connection_struct *conn, SMB_STRUCT_STAT *sbuf) +uint32 dos_mode_from_sbuf(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf) { int result = 0; - if ((sbuf->st_mode & S_IWUSR) == 0) + if (lp_acl_check_permissions(SNUM(conn))) { + if (!can_write_to_file(conn, path, sbuf)) { + result |= aRONLY; + } + } else if ((sbuf->st_mode & S_IWUSR) == 0) { result |= aRONLY; - + } + if (MAP_ARCHIVE(conn) && ((sbuf->st_mode & S_IXUSR) != 0)) result |= aARCH; @@ -291,7 +296,7 @@ uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf) return result; } - result = dos_mode_from_sbuf(conn, sbuf); + result = dos_mode_from_sbuf(conn, path, sbuf); /* Now do any modifications that depend on the path name. */ /* hide files with a name starting with a . */ @@ -433,9 +438,11 @@ int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode, int file_utime(connection_struct *conn, const char *fname, struct utimbuf *times) { + SMB_STRUCT_STAT sbuf; int ret = -1; errno = 0; + ZERO_STRUCT(sbuf); if(SMB_VFS_UTIME(conn,fname, times) == 0) return 0; @@ -453,7 +460,7 @@ int file_utime(connection_struct *conn, const char *fname, struct utimbuf *times */ /* Check if we have write access. */ - if (can_write_to_file(conn, fname)) { + if (can_write_to_file(conn, fname, &sbuf)) { /* We are allowed to become root and change the filetime. */ become_root(); ret = SMB_VFS_UTIME(conn,fname, times); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index a37ae5548f..a0f94d616d 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -802,7 +802,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib if (desired_access & DELETE_ACCESS) { #else /* Setting FILE_SHARE_DELETE is the hint. */ - if ((share_access & FILE_SHARE_DELETE) && (desired_access & DELETE_ACCESS)) { + if (lp_acl_check_permissions(SNUM(conn)) && (share_access & FILE_SHARE_DELETE) && (desired_access & DELETE_ACCESS)) { #endif status = can_delete(conn, fname, file_attributes, bad_path, True); /* We're only going to fail here if it's access denied, as that's the @@ -1422,7 +1422,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o if (desired_access & DELETE_ACCESS) { #else /* Setting FILE_SHARE_DELETE is the hint. */ - if ((share_access & FILE_SHARE_DELETE) && (desired_access & DELETE_ACCESS)) { + if (lp_acl_check_permissions(SNUM(conn)) && (share_access & FILE_SHARE_DELETE) && (desired_access & DELETE_ACCESS)) { #endif status = can_delete(conn, fname, file_attributes, bad_path, True); /* We're only going to fail here if it's access denied, as that's the diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index b31e97c76f..b5052eec25 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -4006,9 +4006,8 @@ BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname) this to successfully check for ability to write for dos filetimes. ****************************************************************************/ -BOOL can_write_to_file(connection_struct *conn, const char *fname) +BOOL can_write_to_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf) { - SMB_STRUCT_STAT sbuf; int ret; if (!CAN_WRITE(conn)) { @@ -4020,22 +4019,24 @@ BOOL can_write_to_file(connection_struct *conn, const char *fname) return True; } - /* Get the file permission mask and owners. */ - if(SMB_VFS_STAT(conn, fname, &sbuf) != 0) { - return False; + if (!VALID_STAT(*psbuf)) { + /* Get the file permission mask and owners. */ + if(SMB_VFS_STAT(conn, fname, psbuf) != 0) { + return False; + } } /* Check primary owner write access. */ - if (current_user.uid == sbuf.st_uid) { - return (sbuf.st_mode & S_IWUSR) ? True : False; + if (current_user.uid == psbuf->st_uid) { + return (psbuf->st_mode & S_IWUSR) ? True : False; } /* Check group or explicit user acl entry write access. */ - ret = check_posix_acl_group_write(conn, fname, &sbuf); + ret = check_posix_acl_group_write(conn, fname, psbuf); if (ret == 0 || ret == 1) { return ret ? True : False; } /* Finally check other write access. */ - return (sbuf.st_mode & S_IWOTH) ? True : False; + return (psbuf->st_mode & S_IWOTH) ? True : False; } |