summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/param/loadparm.c4
-rw-r--r--source3/smbd/dosmode.c17
-rw-r--r--source3/smbd/nttrans.c4
-rw-r--r--source3/smbd/posix_acls.c19
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;
}