summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2019-07-05 09:52:43 +0200
committerRalph Boehme <slow@samba.org>2019-07-08 16:22:37 +0000
commit32766db210426d92948a7d81d923f9d669ff3ed6 (patch)
tree2234328fdb36c1855c8c79ba40b6c63ab8edcda9
parentb16f7113ebfe324b847f136912d24a25b983aae5 (diff)
downloadsamba-32766db210426d92948a7d81d923f9d669ff3ed6.tar.gz
smbd: Move fcb_or_dos_open() out of open_file_ntcreate()
This is SMB1-only and pre-ntcreate with only 3 callers that look at NTCREATEX_OPTIONS_PRIVATE_DENY_[DOS|FCB]. It is a bit less efficient if it kicks in (we have to recreate the fsp), but SMB1 is less and less popular, and this particular share mode combination from the open&x family of calls might not be worth optimizing for. This adds smb1_utils.[ch] as a kitchen sink for functions that can go away once we drop SMB1. Signed-off-by: Volker Lendecke <vl@samba.org> Reviewed-by: Stefan Metzmacher <metze@samba.org>
-rw-r--r--source3/smbd/open.c99
-rw-r--r--source3/smbd/reply.c40
-rw-r--r--source3/smbd/smb1_utils.c113
-rw-r--r--source3/smbd/smb1_utils.h37
-rw-r--r--source3/smbd/trans2.c21
-rw-r--r--source3/wscript_build1
6 files changed, 207 insertions, 104 deletions
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index ef73aa219ea..2ee4a2c4fca 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -21,6 +21,7 @@
*/
#include "includes.h"
+#include "smb1_utils.h"
#include "system/filesys.h"
#include "lib/util/server_id.h"
#include "printing.h"
@@ -2608,69 +2609,6 @@ static bool open_match_attributes(connection_struct *conn,
return True;
}
-/****************************************************************************
- Special FCB or DOS processing in the case of a sharing violation.
- Try and find a duplicated file handle.
-****************************************************************************/
-
-static NTSTATUS fcb_or_dos_open(struct smb_request *req,
- connection_struct *conn,
- files_struct *fsp_to_dup_into,
- const struct smb_filename *smb_fname,
- struct file_id id,
- uint16_t file_pid,
- uint64_t vuid,
- uint32_t access_mask,
- uint32_t share_access,
- uint32_t create_options)
-{
- files_struct *fsp;
-
- DEBUG(5,("fcb_or_dos_open: attempting old open semantics for "
- "file %s.\n", smb_fname_str_dbg(smb_fname)));
-
- for(fsp = file_find_di_first(conn->sconn, id); fsp;
- fsp = file_find_di_next(fsp)) {
-
- DEBUG(10,("fcb_or_dos_open: checking file %s, fd = %d, "
- "vuid = %llu, file_pid = %u, private_options = 0x%x "
- "access_mask = 0x%x\n", fsp_str_dbg(fsp),
- fsp->fh->fd, (unsigned long long)fsp->vuid,
- (unsigned int)fsp->file_pid,
- (unsigned int)fsp->fh->private_options,
- (unsigned int)fsp->access_mask ));
-
- if (fsp != fsp_to_dup_into &&
- fsp->fh->fd != -1 &&
- fsp->vuid == vuid &&
- fsp->file_pid == file_pid &&
- (fsp->fh->private_options & (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS |
- NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) &&
- (fsp->access_mask & FILE_WRITE_DATA) &&
- strequal(fsp->fsp_name->base_name, smb_fname->base_name) &&
- strequal(fsp->fsp_name->stream_name,
- smb_fname->stream_name)) {
- DEBUG(10,("fcb_or_dos_open: file match\n"));
- break;
- }
- }
-
- if (!fsp) {
- return NT_STATUS_NOT_FOUND;
- }
-
- /* quite an insane set of semantics ... */
- if (is_executable(smb_fname->base_name) &&
- (fsp->fh->private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS)) {
- DEBUG(10,("fcb_or_dos_open: file fail due to is_executable.\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- /* We need to duplicate this fsp. */
- return dup_file_fsp(req, fsp, access_mask, share_access,
- create_options, fsp_to_dup_into);
-}
-
static void schedule_defer_open(struct share_mode_lock *lck,
struct file_id id,
struct timeval request_time,
@@ -3547,41 +3485,6 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
SMB_ASSERT(NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION));
- /* Check if this can be done with the deny_dos and fcb
- * calls. */
- if (private_flags &
- (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS|
- NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) {
- if (req == NULL) {
- DEBUG(0, ("DOS open without an SMB "
- "request!\n"));
- TALLOC_FREE(lck);
- fd_close(fsp);
- return NT_STATUS_INTERNAL_ERROR;
- }
-
- /* Use the client requested access mask here,
- * not the one we open with. */
- status = fcb_or_dos_open(req,
- conn,
- fsp,
- smb_fname,
- id,
- req->smbpid,
- req->vuid,
- access_mask,
- share_access,
- create_options);
-
- if (NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(lck);
- if (pinfo) {
- *pinfo = FILE_WAS_OPENED;
- }
- return NT_STATUS_OK;
- }
- }
-
/*
* This next line is a subtlety we need for
* MS-Access. If a file open will fail due to share
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 87729b23a83..2622681a2da 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -45,6 +45,7 @@
#include "libcli/smb/smb_signing.h"
#include "lib/util/sys_rw_data.h"
#include "librpc/gen_ndr/open_files.h"
+#include "smb1_utils.h"
/****************************************************************************
Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
@@ -2219,8 +2220,23 @@ void reply_open(struct smb_request *req)
/* We have re-scheduled this call. */
goto out;
}
- reply_openerror(req, status);
- goto out;
+
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
+ reply_openerror(req, status);
+ goto out;
+ }
+
+ fsp = fcb_or_dos_open(
+ req,
+ smb_fname,
+ access_mask,
+ share_mode,
+ create_options,
+ private_flags);
+ if (fsp == NULL) {
+ reply_openerror(req, status);
+ goto out;
+ }
}
/* Ensure we're pointing at the correct stat struct. */
@@ -2392,8 +2408,24 @@ void reply_open_and_X(struct smb_request *req)
/* We have re-scheduled this call. */
goto out;
}
- reply_openerror(req, status);
- goto out;
+
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
+ reply_openerror(req, status);
+ goto out;
+ }
+
+ fsp = fcb_or_dos_open(
+ req,
+ smb_fname,
+ access_mask,
+ share_mode,
+ create_options,
+ private_flags);
+ if (fsp == NULL) {
+ reply_openerror(req, status);
+ goto out;
+ }
+ smb_action = FILE_WAS_OPENED;
}
/* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
diff --git a/source3/smbd/smb1_utils.c b/source3/smbd/smb1_utils.c
new file mode 100644
index 00000000000..8a7e66e2ae3
--- /dev/null
+++ b/source3/smbd/smb1_utils.c
@@ -0,0 +1,113 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Util functions valid in the SMB1 server
+ *
+ * Copyright (C) Volker Lendecke 2019
+ * Copyright by the authors of the functions moved here eventually
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+#include "smb1_utils.h"
+#include "libcli/security/security.h"
+
+/****************************************************************************
+ Special FCB or DOS processing in the case of a sharing violation.
+ Try and find a duplicated file handle.
+****************************************************************************/
+
+struct files_struct *fcb_or_dos_open(
+ struct smb_request *req,
+ const struct smb_filename *smb_fname,
+ uint32_t access_mask,
+ uint32_t share_access,
+ uint32_t create_options,
+ uint32_t private_flags)
+{
+ struct connection_struct *conn = req->conn;
+ struct file_id id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
+ struct files_struct *fsp = NULL, *new_fsp = NULL;
+ NTSTATUS status;
+
+ if ((private_flags &
+ (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS|
+ NTCREATEX_OPTIONS_PRIVATE_DENY_FCB))
+ == 0) {
+ return NULL;
+ }
+
+ for(fsp = file_find_di_first(conn->sconn, id);
+ fsp != NULL;
+ fsp = file_find_di_next(fsp)) {
+
+ DBG_DEBUG("Checking file %s, fd = %d, vuid = %"PRIu64", "
+ "file_pid = %"PRIu16", "
+ "private_options = 0x%"PRIx32", "
+ "access_mask = 0x%"PRIx32"\n",
+ fsp_str_dbg(fsp),
+ fsp->fh->fd,
+ fsp->vuid,
+ fsp->file_pid,
+ fsp->fh->private_options,
+ fsp->access_mask);
+
+ if (fsp->fh->fd != -1 &&
+ fsp->vuid == req->vuid &&
+ fsp->file_pid == req->smbpid &&
+ (fsp->fh->private_options &
+ (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS |
+ NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) &&
+ (fsp->access_mask & FILE_WRITE_DATA) &&
+ strequal(fsp->fsp_name->base_name, smb_fname->base_name) &&
+ strequal(fsp->fsp_name->stream_name,
+ smb_fname->stream_name)) {
+ DBG_DEBUG("file match\n");
+ break;
+ }
+ }
+
+ if (fsp == NULL) {
+ return NULL;
+ }
+
+ /* quite an insane set of semantics ... */
+ if (is_executable(smb_fname->base_name) &&
+ (fsp->fh->private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS)) {
+ DBG_DEBUG("file fail due to is_executable.\n");
+ return NULL;
+ }
+
+ status = file_new(req, conn, &new_fsp);
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_DEBUG("file_new failed: %s\n", nt_errstr(status));
+ return NULL;
+ }
+
+ status = dup_file_fsp(
+ req,
+ fsp,
+ access_mask,
+ share_access,
+ create_options,
+ new_fsp);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_DEBUG("dup_file_fsp failed: %s\n", nt_errstr(status));
+ file_free(req, new_fsp);
+ return NULL;
+ }
+
+ return new_fsp;
+}
diff --git a/source3/smbd/smb1_utils.h b/source3/smbd/smb1_utils.h
new file mode 100644
index 00000000000..719eb3eb3a2
--- /dev/null
+++ b/source3/smbd/smb1_utils.h
@@ -0,0 +1,37 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Util functions valid in the SMB1 server
+ *
+ * Copyright (C) Volker Lendecke 2019
+ * Copyright by the authors of the functions moved here eventually
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __SMBD_SMB1_UTILS_H__
+#define __SMBD_SMB1_UTILS_H__
+
+#include "includes.h"
+#include "vfs.h"
+#include "proto.h"
+
+struct files_struct *fcb_or_dos_open(
+ struct smb_request *req,
+ const struct smb_filename *smb_fname,
+ uint32_t access_mask,
+ uint32_t share_access,
+ uint32_t create_options,
+ uint32_t private_flags);
+
+#endif
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 4342b03a8c9..5b99240e9e8 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -41,6 +41,7 @@
#include "lib/util_ea.h"
#include "lib/readdir_attr.h"
#include "messages.h"
+#include "smb1_utils.h"
#define DIR_ENTRY_SAFETY_MARGIN 4096
@@ -1440,8 +1441,24 @@ static void call_trans2open(connection_struct *conn,
/* We have re-scheduled this call. */
goto out;
}
- reply_openerror(req, status);
- goto out;
+
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
+ reply_openerror(req, status);
+ goto out;
+ }
+
+ fsp = fcb_or_dos_open(
+ req,
+ smb_fname,
+ access_mask,
+ share_mode,
+ create_options,
+ private_flags);
+ if (fsp == NULL) {
+ reply_openerror(req, status);
+ goto out;
+ }
+ smb_action = FILE_WAS_OPENED;
}
size = get_file_size_stat(&smb_fname->st);
diff --git a/source3/wscript_build b/source3/wscript_build
index 7d44071225e..aa3c7175202 100644
--- a/source3/wscript_build
+++ b/source3/wscript_build
@@ -718,6 +718,7 @@ bld.SAMBA3_LIBRARY('smbd_base',
smbd/notify.c
smbd/notify_msg.c
smbd/build_options.c
+ smbd/smb1_utils.c
''' + NOTIFY_SOURCES,
deps='''
talloc