Line data Source code
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 "smbd/smbd.h"
24 : #include "smbd/globals.h"
25 : #include "libcli/security/security.h"
26 : #include "lib/util/sys_rw_data.h"
27 : #include "smbd/fd_handle.h"
28 :
29 : /****************************************************************************
30 : Special FCB or DOS processing in the case of a sharing violation.
31 : Try and find a duplicated file handle.
32 : ****************************************************************************/
33 :
34 4425 : struct files_struct *fcb_or_dos_open(
35 : struct smb_request *req,
36 : const struct smb_filename *smb_fname,
37 : uint32_t access_mask,
38 : uint32_t create_options,
39 : uint32_t private_flags)
40 : {
41 4425 : struct connection_struct *conn = req->conn;
42 4425 : struct file_id id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
43 4425 : struct files_struct *fsp = NULL, *new_fsp = NULL;
44 9 : NTSTATUS status;
45 :
46 4425 : if ((private_flags &
47 : (NTCREATEX_FLAG_DENY_DOS|
48 : NTCREATEX_FLAG_DENY_FCB))
49 : == 0) {
50 2976 : return NULL;
51 : }
52 :
53 1441 : for(fsp = file_find_di_first(conn->sconn, id, true);
54 1981 : fsp != NULL;
55 540 : fsp = file_find_di_next(fsp, true)) {
56 :
57 677 : DBG_DEBUG("Checking file %s, fd = %d, vuid = %"PRIu64", "
58 : "file_pid = %"PRIu16", "
59 : "private_options = 0x%"PRIx32", "
60 : "access_mask = 0x%"PRIx32"\n",
61 : fsp_str_dbg(fsp),
62 : fsp_get_pathref_fd(fsp),
63 : fsp->vuid,
64 : fsp->file_pid,
65 : fh_get_private_options(fsp->fh),
66 : fsp->access_mask);
67 :
68 677 : if (fsp_get_pathref_fd(fsp) != -1 &&
69 677 : fsp->vuid == req->vuid &&
70 677 : fsp->file_pid == req->smbpid &&
71 677 : (fh_get_private_options(fsp->fh) &
72 : (NTCREATEX_FLAG_DENY_DOS |
73 169 : NTCREATEX_FLAG_DENY_FCB)) &&
74 306 : (fsp->access_mask & FILE_WRITE_DATA) &&
75 274 : strequal(fsp->fsp_name->base_name, smb_fname->base_name) &&
76 137 : strequal(fsp->fsp_name->stream_name,
77 137 : smb_fname->stream_name)) {
78 137 : DBG_DEBUG("file match\n");
79 136 : break;
80 : }
81 : }
82 :
83 1441 : if (fsp == NULL) {
84 1304 : return NULL;
85 : }
86 :
87 : /* quite an insane set of semantics ... */
88 137 : if (is_executable(smb_fname->base_name) &&
89 60 : (fh_get_private_options(fsp->fh) & NTCREATEX_FLAG_DENY_DOS)) {
90 24 : DBG_DEBUG("file fail due to is_executable.\n");
91 24 : return NULL;
92 : }
93 :
94 113 : status = file_new(req, conn, &new_fsp);
95 113 : if (!NT_STATUS_IS_OK(status)) {
96 0 : DBG_DEBUG("file_new failed: %s\n", nt_errstr(status));
97 0 : return NULL;
98 : }
99 :
100 113 : status = dup_file_fsp(fsp, access_mask, new_fsp);
101 :
102 113 : if (!NT_STATUS_IS_OK(status)) {
103 0 : DBG_DEBUG("dup_file_fsp failed: %s\n", nt_errstr(status));
104 0 : file_free(req, new_fsp);
105 0 : return NULL;
106 : }
107 :
108 113 : return new_fsp;
109 : }
110 :
111 : /****************************************************************************
112 : Send a keepalive packet (rfc1002).
113 : ****************************************************************************/
114 :
115 0 : bool send_keepalive(int client)
116 : {
117 0 : unsigned char buf[4];
118 :
119 0 : buf[0] = NBSSkeepalive;
120 0 : buf[1] = buf[2] = buf[3] = 0;
121 :
122 0 : return(write_data(client,(char *)buf,4) == 4);
123 : }
124 :
125 : /*******************************************************************
126 : Add a string to the end of a smb_buf, adjusting bcc and smb_len.
127 : Return the bytes added
128 : ********************************************************************/
129 :
130 54610 : ssize_t message_push_string(uint8_t **outbuf, const char *str, int flags)
131 : {
132 54610 : size_t buf_size = smb_len(*outbuf) + 4;
133 677 : size_t grow_size;
134 54610 : size_t result = 0;
135 677 : uint8_t *tmp;
136 677 : NTSTATUS status;
137 :
138 : /*
139 : * We need to over-allocate, now knowing what srvstr_push will
140 : * actually use. This is very generous by incorporating potential
141 : * padding, the terminating 0 and at most 4 chars per UTF-16 code
142 : * point.
143 : */
144 54610 : grow_size = (strlen(str) + 2) * 4;
145 :
146 54610 : if (!(tmp = talloc_realloc(NULL, *outbuf, uint8_t,
147 : buf_size + grow_size))) {
148 0 : DEBUG(0, ("talloc failed\n"));
149 0 : return -1;
150 : }
151 :
152 54610 : status = srvstr_push((char *)tmp, SVAL(tmp, smb_flg2),
153 : tmp + buf_size, str, grow_size, flags, &result);
154 :
155 54610 : if (!NT_STATUS_IS_OK(status)) {
156 0 : DEBUG(0, ("srvstr_push failed\n"));
157 0 : return -1;
158 : }
159 :
160 : /*
161 : * Ensure we clear out the extra data we have
162 : * grown the buffer by, but not written to.
163 : */
164 54610 : if (buf_size + result < buf_size) {
165 0 : return -1;
166 : }
167 54610 : if (grow_size < result) {
168 0 : return -1;
169 : }
170 :
171 54610 : memset(tmp + buf_size + result, '\0', grow_size - result);
172 :
173 54610 : set_message_bcc((char *)tmp, smb_buflen(tmp) + result);
174 :
175 54610 : *outbuf = tmp;
176 :
177 54610 : return result;
178 : }
179 :
180 : /*
181 : * Deal with the SMB1 semantics of sending a pathname with a
182 : * wildcard as the terminal component for a SMB1search or
183 : * trans2 findfirst.
184 : */
185 :
186 8912 : NTSTATUS filename_convert_smb1_search_path(TALLOC_CTX *ctx,
187 : connection_struct *conn,
188 : char *name_in,
189 : uint32_t ucf_flags,
190 : struct files_struct **_dirfsp,
191 : struct smb_filename **_smb_fname_out,
192 : char **_mask_out)
193 : {
194 175 : NTSTATUS status;
195 8912 : char *p = NULL;
196 8912 : char *mask = NULL;
197 8912 : struct smb_filename *smb_fname = NULL;
198 8912 : NTTIME twrp = 0;
199 :
200 8912 : *_smb_fname_out = NULL;
201 8912 : *_dirfsp = NULL;
202 8912 : *_mask_out = NULL;
203 :
204 8912 : DBG_DEBUG("name_in: %s\n", name_in);
205 :
206 8912 : if (ucf_flags & UCF_GMT_PATHNAME) {
207 68 : extract_snapshot_token(name_in, &twrp);
208 68 : ucf_flags &= ~UCF_GMT_PATHNAME;
209 : }
210 :
211 : /* Get the original lcomp. */
212 8912 : mask = get_original_lcomp(ctx, conn, name_in, ucf_flags);
213 8912 : if (mask == NULL) {
214 0 : return NT_STATUS_NO_MEMORY;
215 : }
216 :
217 8912 : if (mask[0] == '\0') {
218 : /* Windows and OS/2 systems treat search on the root as * */
219 6 : TALLOC_FREE(mask);
220 6 : mask = talloc_strdup(ctx, "*");
221 6 : if (mask == NULL) {
222 0 : return NT_STATUS_NO_MEMORY;
223 : }
224 : }
225 :
226 8912 : DBG_DEBUG("mask = %s\n", mask);
227 :
228 : /*
229 : * Remove the terminal component so
230 : * filename_convert_dirfsp never sees the mask.
231 : */
232 8912 : p = strrchr_m(name_in, '/');
233 8912 : if (p == NULL) {
234 : /* filename_convert_dirfsp handles a '\0' name. */
235 1258 : name_in[0] = '\0';
236 : } else {
237 7654 : *p = '\0';
238 : }
239 :
240 8912 : DBG_DEBUG("For filename_convert_dirfsp: name_in = %s\n", name_in);
241 :
242 : /* Convert the parent directory path. */
243 8912 : status = filename_convert_dirfsp(ctx,
244 : conn,
245 : name_in,
246 : ucf_flags,
247 : twrp,
248 : _dirfsp,
249 : &smb_fname);
250 :
251 8912 : if (!NT_STATUS_IS_OK(status)) {
252 114 : DBG_DEBUG("filename_convert error for %s: %s\n",
253 : name_in,
254 : nt_errstr(status));
255 : }
256 :
257 8912 : *_smb_fname_out = talloc_move(ctx, &smb_fname);
258 8912 : *_mask_out = talloc_move(ctx, &mask);
259 :
260 8912 : return status;
261 : }
|