1 /*
2  * Unix SMB/CIFS implementation.
3  * Util functions valid in the SMB1 server
4  *
5  * Copyright (C) Volker Lendecke 2019
6  * Copyright by the authors of the functions moved here eventually
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include "includes.h"
23 #include "smb1_utils.h"
24 #include "libcli/security/security.h"
25 
26 /****************************************************************************
27  Special FCB or DOS processing in the case of a sharing violation.
28  Try and find a duplicated file handle.
29 ****************************************************************************/
30 
fcb_or_dos_open(struct smb_request * req,const struct smb_filename * smb_fname,uint32_t access_mask,uint32_t create_options,uint32_t private_flags)31 struct files_struct *fcb_or_dos_open(
32 	struct smb_request *req,
33 	const struct smb_filename *smb_fname,
34 	uint32_t access_mask,
35 	uint32_t create_options,
36 	uint32_t private_flags)
37 {
38 	struct connection_struct *conn = req->conn;
39 	struct file_id id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
40 	struct files_struct *fsp = NULL, *new_fsp = NULL;
41 	NTSTATUS status;
42 
43 	if ((private_flags &
44 	     (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS|
45 	      NTCREATEX_OPTIONS_PRIVATE_DENY_FCB))
46 	    == 0) {
47 		return NULL;
48 	}
49 
50 	for(fsp = file_find_di_first(conn->sconn, id);
51 	    fsp != NULL;
52 	    fsp = file_find_di_next(fsp)) {
53 
54 		DBG_DEBUG("Checking file %s, fd = %d, vuid = %"PRIu64", "
55 			  "file_pid = %"PRIu16", "
56 			  "private_options = 0x%"PRIx32", "
57 			  "access_mask = 0x%"PRIx32"\n",
58 			  fsp_str_dbg(fsp),
59 			  fsp->fh->fd,
60 			  fsp->vuid,
61 			  fsp->file_pid,
62 			  fsp->fh->private_options,
63 			  fsp->access_mask);
64 
65 		if (fsp->fh->fd != -1 &&
66 		    fsp->vuid == req->vuid &&
67 		    fsp->file_pid == req->smbpid &&
68 		    (fsp->fh->private_options &
69 		     (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS |
70 		      NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) &&
71 		    (fsp->access_mask & FILE_WRITE_DATA) &&
72 		    strequal(fsp->fsp_name->base_name, smb_fname->base_name) &&
73 		    strequal(fsp->fsp_name->stream_name,
74 			     smb_fname->stream_name)) {
75 			DBG_DEBUG("file match\n");
76 			break;
77 		}
78 	}
79 
80 	if (fsp == NULL) {
81 		return NULL;
82 	}
83 
84 	/* quite an insane set of semantics ... */
85 	if (is_executable(smb_fname->base_name) &&
86 	    (fsp->fh->private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS)) {
87 		DBG_DEBUG("file fail due to is_executable.\n");
88 		return NULL;
89 	}
90 
91 	status = file_new(req, conn, &new_fsp);
92 	if (!NT_STATUS_IS_OK(status)) {
93 		DBG_DEBUG("file_new failed: %s\n", nt_errstr(status));
94 		return NULL;
95 	}
96 
97 	status = dup_file_fsp(
98 		req,
99 		fsp,
100 		access_mask,
101 		create_options,
102 		new_fsp);
103 
104 	if (!NT_STATUS_IS_OK(status)) {
105 		DBG_DEBUG("dup_file_fsp failed: %s\n", nt_errstr(status));
106 		file_free(req, new_fsp);
107 		return NULL;
108 	}
109 
110 	return new_fsp;
111 }
112