summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/proto.h3
-rw-r--r--source3/smbd/dir.c39
-rw-r--r--source3/smbd/dosmode.c28
-rw-r--r--source3/smbd/file_access.c19
-rw-r--r--source3/smbd/nttrans.c4
-rw-r--r--source3/smbd/posix_acls.c14
6 files changed, 64 insertions, 43 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h
index f685152de8..731934d714 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -6268,7 +6268,8 @@ bool can_delete_file_in_directory(connection_struct *conn,
bool can_access_file_data(connection_struct *conn,
const struct smb_filename *smb_fname,
uint32 access_mask);
-bool can_write_to_file(connection_struct *conn, const char *fname, const SMB_STRUCT_STAT *psbuf);
+bool can_write_to_file(connection_struct *conn,
+ const struct smb_filename *smb_fname);
bool directory_has_default_acl(connection_struct *conn, const char *fname);
/* The following definitions come from smbd/fileio.c */
diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
index aff30a6967..723fb6fd6f 100644
--- a/source3/smbd/dir.c
+++ b/source3/smbd/dir.c
@@ -1007,7 +1007,8 @@ static bool user_can_read_file(connection_struct *conn,
use it for anything security sensitive.
********************************************************************/
-static bool user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
+static bool user_can_write_file(connection_struct *conn,
+ const struct smb_filename *smb_fname)
{
/*
* If user is a member of the Admin group
@@ -1018,22 +1019,23 @@ static bool user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_
return True;
}
- SMB_ASSERT(VALID_STAT(*pst));
+ SMB_ASSERT(VALID_STAT(smb_fname->st));
/* Pseudo-open the file */
- if(S_ISDIR(pst->st_ex_mode)) {
+ if(S_ISDIR(smb_fname->st.st_ex_mode)) {
return True;
}
- return can_write_to_file(conn, name, pst);
+ return can_write_to_file(conn, smb_fname);
}
/*******************************************************************
Is a file a "special" type ?
********************************************************************/
-static bool file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
+static bool file_is_special(connection_struct *conn,
+ const struct smb_filename *smb_fname)
{
/*
* If user is a member of the Admin group
@@ -1043,9 +1045,11 @@ static bool file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT
if (conn->admin_user)
return False;
- SMB_ASSERT(VALID_STAT(*pst));
+ SMB_ASSERT(VALID_STAT(smb_fname->st));
- if (S_ISREG(pst->st_ex_mode) || S_ISDIR(pst->st_ex_mode) || S_ISLNK(pst->st_ex_mode))
+ if (S_ISREG(smb_fname->st.st_ex_mode) ||
+ S_ISDIR(smb_fname->st.st_ex_mode) ||
+ S_ISLNK(smb_fname->st.st_ex_mode))
return False;
return True;
@@ -1094,7 +1098,7 @@ bool is_visible_file(connection_struct *conn, const char *dir_path,
/* Create an smb_filename with stream_name == NULL. */
status = create_synthetic_smb_fname(talloc_tos(), entry, NULL,
- NULL, &smb_fname_base);
+ pst, &smb_fname_base);
if (!NT_STATUS_IS_OK(status)) {
ret = false;
goto out;
@@ -1104,15 +1108,15 @@ bool is_visible_file(connection_struct *conn, const char *dir_path,
* the configuration options. We succeed, on the basis that the
* checks *might* have passed if the file was present.
*/
- if (!VALID_STAT(*pst) &&
- (SMB_VFS_STAT(conn, smb_fname_base) != 0))
- {
- ret = true;
- goto out;
+ if (!VALID_STAT(*pst)) {
+ if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
+ ret = true;
+ goto out;
+ } else {
+ *pst = smb_fname_base->st;
+ }
}
- *pst = smb_fname_base->st;
-
/* Honour _hide unreadable_ option */
if (hide_unreadable &&
!user_can_read_file(conn, smb_fname_base)) {
@@ -1122,14 +1126,15 @@ bool is_visible_file(connection_struct *conn, const char *dir_path,
goto out;
}
/* Honour _hide unwriteable_ option */
- if (hide_unwriteable && !user_can_write_file(conn, entry, pst)) {
+ if (hide_unwriteable && !user_can_write_file(conn,
+ smb_fname_base)) {
DEBUG(10,("is_visible_file: file %s is unwritable.\n",
entry ));
ret = false;
goto out;
}
/* Honour _hide_special_ option */
- if (hide_special && file_is_special(conn, entry, pst)) {
+ if (hide_special && file_is_special(conn, smb_fname_base)) {
DEBUG(10,("is_visible_file: file %s is special.\n",
entry ));
ret = false;
diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c
index afebb9efd0..26d3320a4c 100644
--- a/source3/smbd/dosmode.c
+++ b/source3/smbd/dosmode.c
@@ -151,10 +151,18 @@ static uint32 dos_mode_from_sbuf(connection_struct *conn, const char *path, cons
result |= aRONLY;
}
} else if (ro_opts == MAP_READONLY_PERMISSIONS) {
- /* Check actual permissions for read-only. */
- if (!can_write_to_file(conn, path, sbuf)) {
- result |= aRONLY;
+ struct smb_filename *smb_fname = NULL;
+ NTSTATUS status;
+
+ status = create_synthetic_smb_fname_split(talloc_tos(), path,
+ sbuf, &smb_fname);
+ if (NT_STATUS_IS_OK(status)) {
+ /* Check actual permissions for read-only. */
+ if (!can_write_to_file(conn, smb_fname)) {
+ result |= aRONLY;
+ }
}
+ TALLOC_FREE(smb_fname);
} /* Else never set the readonly bit. */
if (MAP_ARCHIVE(conn) && ((sbuf->st_ex_mode & S_IXUSR) != 0))
@@ -712,11 +720,11 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
int file_ntimes(connection_struct *conn, const char *fname,
struct smb_file_time *ft)
{
- SMB_STRUCT_STAT sbuf;
+ struct smb_filename *smb_fname = NULL;
+ NTSTATUS status;
int ret = -1;
errno = 0;
- ZERO_STRUCT(sbuf);
DEBUG(6, ("file_ntime: actime: %s",
time_to_asc(convert_timespec_to_time_t(ft->atime))));
@@ -754,13 +762,21 @@ int file_ntimes(connection_struct *conn, const char *fname,
(as DOS does).
*/
+ status = create_synthetic_smb_fname_split(talloc_tos(), fname, NULL,
+ &smb_fname);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return -1;
+ }
+
/* Check if we have write access. */
- if (can_write_to_file(conn, fname, &sbuf)) {
+ if (can_write_to_file(conn, smb_fname)) {
/* We are allowed to become root and change the filetime. */
become_root();
ret = SMB_VFS_NTIMES(conn, fname, ft);
unbecome_root();
}
+ TALLOC_FREE(smb_fname);
return ret;
}
diff --git a/source3/smbd/file_access.c b/source3/smbd/file_access.c
index 87d45c5e7f..d8fee1db06 100644
--- a/source3/smbd/file_access.c
+++ b/source3/smbd/file_access.c
@@ -232,23 +232,10 @@ bool can_access_file_data(connection_struct *conn,
Note this doesn't take into account share write permissions.
****************************************************************************/
-bool can_write_to_file(connection_struct *conn, const char *fname, const SMB_STRUCT_STAT *psbuf)
+bool can_write_to_file(connection_struct *conn,
+ const struct smb_filename *smb_fname)
{
- struct smb_filename *smb_fname;
- NTSTATUS status;
- bool ret;
-
- status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
- &smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- return false;
- }
-
- ret = can_access_file_data(conn, smb_fname, FILE_WRITE_DATA);
-
- TALLOC_FREE(smb_fname);
-
- return ret;
+ return can_access_file_data(conn, smb_fname, FILE_WRITE_DATA);
}
/****************************************************************************
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index 560b844a56..04767bf559 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -673,7 +673,7 @@ void reply_ntcreate_and_X(struct smb_request *req)
uint32 perms = 0;
p += 25;
if (fsp->is_directory ||
- can_write_to_file(conn, fsp->fsp_name, &smb_fname->st)) {
+ can_write_to_file(conn, smb_fname)) {
perms = FILE_GENERIC_ALL;
} else {
perms = FILE_GENERIC_READ|FILE_EXECUTE;
@@ -1155,7 +1155,7 @@ static void call_nt_transact_create(connection_struct *conn,
uint32 perms = 0;
p += 25;
if (fsp->is_directory ||
- can_write_to_file(conn, fsp->fsp_name, &smb_fname->st)) {
+ can_write_to_file(conn, smb_fname)) {
perms = FILE_GENERIC_ALL;
} else {
perms = FILE_GENERIC_READ|FILE_EXECUTE;
diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c
index 437112c751..627ca2e171 100644
--- a/source3/smbd/posix_acls.c
+++ b/source3/smbd/posix_acls.c
@@ -2550,6 +2550,9 @@ static bool acl_group_override(connection_struct *conn,
const SMB_STRUCT_STAT *psbuf,
const char *fname)
{
+ struct smb_filename *smb_fname = NULL;
+ NTSTATUS status;
+
if ((errno != EPERM) && (errno != EACCES)) {
return false;
}
@@ -2560,11 +2563,20 @@ static bool acl_group_override(connection_struct *conn,
return true;
}
+ status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
+ &smb_fname);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return false;
+ }
+
/* user has writeable permission */
if (lp_dos_filemode(SNUM(conn)) &&
- can_write_to_file(conn, fname, psbuf)) {
+ can_write_to_file(conn, smb_fname)) {
+ TALLOC_FREE(smb_fname);
return true;
}
+ TALLOC_FREE(smb_fname);
return false;
}