summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/dosmode.c20
-rw-r--r--source3/smbd/filename.c13
-rw-r--r--source3/smbd/open.c6
-rw-r--r--source3/smbd/trans2.c14
4 files changed, 31 insertions, 22 deletions
diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c
index 6468544748..eeed76329c 100644
--- a/source3/smbd/dosmode.c
+++ b/source3/smbd/dosmode.c
@@ -379,7 +379,7 @@ int dos_attributes_to_stat_dos_flags(uint32_t dosmode)
}
/****************************************************************************
- Gets DOS attributes, accessed via st_flags in the stat struct.
+ Gets DOS attributes, accessed via st_ex_flags in the stat struct.
****************************************************************************/
static bool get_stat_dos_flags(connection_struct *conn,
@@ -396,15 +396,15 @@ static bool get_stat_dos_flags(connection_struct *conn,
DEBUG(5, ("Getting stat dos attributes for %s.\n", fname));
- if (sbuf->st_flags & UF_DOS_ARCHIVE)
+ if (sbuf->st_ex_flags & UF_DOS_ARCHIVE)
*dosmode |= aARCH;
- if (sbuf->st_flags & UF_DOS_HIDDEN)
+ if (sbuf->st_ex_flags & UF_DOS_HIDDEN)
*dosmode |= aHIDDEN;
- if (sbuf->st_flags & UF_DOS_RO)
+ if (sbuf->st_ex_flags & UF_DOS_RO)
*dosmode |= aRONLY;
- if (sbuf->st_flags & UF_DOS_SYSTEM)
+ if (sbuf->st_ex_flags & UF_DOS_SYSTEM)
*dosmode |= aSYSTEM;
- if (sbuf->st_flags & UF_DOS_NOINDEX)
+ if (sbuf->st_ex_flags & UF_DOS_NOINDEX)
*dosmode |= FILE_ATTRIBUTE_NONINDEXED;
if (S_ISDIR(sbuf->st_ex_mode))
*dosmode |= aDIR;
@@ -416,7 +416,7 @@ static bool get_stat_dos_flags(connection_struct *conn,
}
/****************************************************************************
- Sets DOS attributes, stored in st_flags of the inode.
+ Sets DOS attributes, stored in st_ex_flags of the inode.
****************************************************************************/
static bool set_stat_dos_flags(connection_struct *conn,
@@ -439,15 +439,15 @@ static bool set_stat_dos_flags(connection_struct *conn,
DEBUG(5, ("Setting stat dos attributes for %s.\n", fname));
- new_flags = (sbuf->st_flags & ~UF_DOS_FLAGS) |
+ new_flags = (sbuf->st_ex_flags & ~UF_DOS_FLAGS) |
dos_attributes_to_stat_dos_flags(dosmode);
/* Return early if no flags changed. */
- if (new_flags == sbuf->st_flags)
+ if (new_flags == sbuf->st_ex_flags)
return true;
DEBUG(5, ("Setting stat dos attributes=0x%x, prev=0x%x\n", new_flags,
- sbuf->st_flags));
+ sbuf->st_ex_flags));
/* Set new flags with chflags. */
error = SMB_VFS_CHFLAGS(conn, fname, new_flags);
diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c
index 72b4ab7aa6..059dca29c8 100644
--- a/source3/smbd/filename.c
+++ b/source3/smbd/filename.c
@@ -513,8 +513,14 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
goto fail;
}
- /* ENOENT is the only valid error here. */
- if ((errno != 0) && (errno != ENOENT)) {
+ /*
+ * ENOENT/EACCESS are the only valid errors
+ * here. EACCESS needs handling here for
+ * "dropboxes", i.e. directories where users
+ * can only put stuff with permission -wx.
+ */
+ if ((errno != 0) && (errno != ENOENT)
+ && (errno != EACCES)) {
/*
* ENOTDIR and ELOOP both map to
* NT_STATUS_OBJECT_PATH_NOT_FOUND
@@ -524,8 +530,7 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
errno == ELOOP) {
result =
NT_STATUS_OBJECT_PATH_NOT_FOUND;
- }
- else {
+ } else {
result =
map_nt_error_from_unix(errno);
}
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index c1b29f68f3..fdfa99953f 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -346,7 +346,7 @@ static NTSTATUS open_file(files_struct *fsp,
if (!CAN_WRITE(conn)) {
/* It's a read-only share - fail if we wanted to write. */
- if(accmode != O_RDONLY) {
+ if(accmode != O_RDONLY || (flags & O_TRUNC) || (flags & O_APPEND)) {
DEBUG(3,("Permission denied opening %s\n", path));
return NT_STATUS_ACCESS_DENIED;
} else if(flags & O_CREAT) {
@@ -354,8 +354,8 @@ static NTSTATUS open_file(files_struct *fsp,
O_CREAT doesn't create the file if we have write
access into the directory.
*/
- flags &= ~O_CREAT;
- local_flags &= ~O_CREAT;
+ flags &= ~(O_CREAT|O_EXCL);
+ local_flags &= ~(O_CREAT|O_EXCL);
}
}
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 1d95c207ba..d11bf088e0 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -6870,16 +6870,20 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
}
}
- if (!CAN_WRITE(conn)) {
- reply_doserror(req, ERRSRV, ERRaccess);
- return;
- }
-
if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
reply_nterror(req, NT_STATUS_INVALID_LEVEL);
return;
}
+ if (!CAN_WRITE(conn)) {
+ /* Allow POSIX opens. The open path will deny
+ * any non-readonly opens. */
+ if (info_level != SMB_POSIX_PATH_OPEN) {
+ reply_doserror(req, ERRSRV, ERRaccess);
+ return;
+ }
+ }
+
DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));