Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : Core SMB2 server
4 :
5 : Copyright (C) Stefan Metzmacher 2009
6 : Copyright (C) Jeremy Allison 2010
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 "printing.h"
24 : #include "smbd/smbd.h"
25 : #include "smbd/globals.h"
26 : #include "smbd/smbXsrv_open.h"
27 : #include "../libcli/smb/smb_common.h"
28 : #include "../librpc/gen_ndr/ndr_security.h"
29 : #include "../librpc/gen_ndr/ndr_smb2_lease_struct.h"
30 : #include "../librpc/gen_ndr/ndr_smb3posix.h"
31 : #include "../lib/util/tevent_ntstatus.h"
32 : #include "messages.h"
33 : #include "lib/util_ea.h"
34 : #include "source3/passdb/lookup_sid.h"
35 : #include "source3/modules/util_reparse.h"
36 :
37 : #undef DBGC_CLASS
38 : #define DBGC_CLASS DBGC_SMB2
39 :
40 459295 : int map_smb2_oplock_levels_to_samba(uint8_t in_oplock_level)
41 : {
42 459295 : switch(in_oplock_level) {
43 456186 : case SMB2_OPLOCK_LEVEL_NONE:
44 456186 : return NO_OPLOCK;
45 234 : case SMB2_OPLOCK_LEVEL_II:
46 234 : return LEVEL_II_OPLOCK;
47 192 : case SMB2_OPLOCK_LEVEL_EXCLUSIVE:
48 192 : return EXCLUSIVE_OPLOCK;
49 1385 : case SMB2_OPLOCK_LEVEL_BATCH:
50 1385 : return BATCH_OPLOCK;
51 1084 : case SMB2_OPLOCK_LEVEL_LEASE:
52 1084 : return LEASE_OPLOCK;
53 0 : default:
54 0 : DEBUG(2,("map_smb2_oplock_levels_to_samba: "
55 : "unknown level %u\n",
56 : (unsigned int)in_oplock_level));
57 0 : return NO_OPLOCK;
58 : }
59 : }
60 :
61 371012 : static uint8_t map_samba_oplock_levels_to_smb2(int oplock_type)
62 : {
63 371012 : if (BATCH_OPLOCK_TYPE(oplock_type)) {
64 1124 : return SMB2_OPLOCK_LEVEL_BATCH;
65 369767 : } else if (EXCLUSIVE_OPLOCK_TYPE(oplock_type)) {
66 139 : return SMB2_OPLOCK_LEVEL_EXCLUSIVE;
67 369628 : } else if (oplock_type == LEVEL_II_OPLOCK) {
68 208 : return SMB2_OPLOCK_LEVEL_II;
69 369420 : } else if (oplock_type == LEASE_OPLOCK) {
70 1012 : return SMB2_OPLOCK_LEVEL_LEASE;
71 : } else {
72 368408 : return SMB2_OPLOCK_LEVEL_NONE;
73 : }
74 : }
75 :
76 : /*
77 : MS-FSA 2.1.5.1 Server Requests an Open of a File
78 : Trailing '/' or '\\' checker.
79 : Must be done before the filename parser removes any
80 : trailing characters. If we decide to add this to SMB1
81 : NTCreate processing we can make this public.
82 :
83 : Note this is Windows pathname processing only. When
84 : POSIX pathnames are added to SMB2 this will not apply.
85 : */
86 :
87 464859 : static NTSTATUS windows_name_trailing_check(const char *name,
88 : uint32_t create_options)
89 : {
90 464859 : size_t name_len = strlen(name);
91 335 : char trail_c;
92 :
93 464859 : if (name_len <= 1) {
94 28412 : return NT_STATUS_OK;
95 : }
96 :
97 436447 : trail_c = name[name_len-1];
98 :
99 : /*
100 : * Trailing '/' is always invalid.
101 : */
102 436447 : if (trail_c == '/') {
103 8 : return NT_STATUS_OBJECT_NAME_INVALID;
104 : }
105 :
106 436439 : if (create_options & FILE_NON_DIRECTORY_FILE) {
107 233903 : if (trail_c == '\\') {
108 4 : return NT_STATUS_OBJECT_NAME_INVALID;
109 : }
110 : }
111 436435 : return NT_STATUS_OK;
112 : }
113 :
114 : static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
115 : struct tevent_context *ev,
116 : struct smbd_smb2_request *smb2req,
117 : uint8_t in_oplock_level,
118 : uint32_t in_impersonation_level,
119 : uint32_t in_desired_access,
120 : uint32_t in_file_attributes,
121 : uint32_t in_share_access,
122 : uint32_t in_create_disposition,
123 : uint32_t _in_create_options,
124 : const char *in_name,
125 : struct smb2_create_blobs in_context_blobs);
126 : static NTSTATUS smbd_smb2_create_recv(struct tevent_req *req,
127 : TALLOC_CTX *mem_ctx,
128 : uint8_t *out_oplock_level,
129 : uint32_t *out_create_action,
130 : struct timespec *out_creation_ts,
131 : struct timespec *out_last_access_ts,
132 : struct timespec *out_last_write_ts,
133 : struct timespec *out_change_ts,
134 : uint64_t *out_allocation_size,
135 : uint64_t *out_end_of_file,
136 : uint32_t *out_file_attributes,
137 : uint64_t *out_file_id_persistent,
138 : uint64_t *out_file_id_volatile,
139 : struct smb2_create_blobs *out_context_blobs);
140 :
141 : static void smbd_smb2_request_create_done(struct tevent_req *tsubreq);
142 482073 : NTSTATUS smbd_smb2_request_process_create(struct smbd_smb2_request *smb2req)
143 : {
144 955 : const uint8_t *inbody;
145 955 : const struct iovec *indyniov;
146 955 : uint8_t in_oplock_level;
147 955 : uint32_t in_impersonation_level;
148 955 : uint32_t in_desired_access;
149 955 : uint32_t in_file_attributes;
150 955 : uint32_t in_share_access;
151 955 : uint32_t in_create_disposition;
152 955 : uint32_t in_create_options;
153 955 : uint16_t in_name_offset;
154 955 : uint16_t in_name_length;
155 955 : DATA_BLOB in_name_buffer;
156 955 : char *in_name_string;
157 955 : size_t in_name_string_size;
158 482073 : uint32_t name_offset = 0;
159 482073 : uint32_t name_available_length = 0;
160 955 : uint32_t in_context_offset;
161 955 : uint32_t in_context_length;
162 955 : DATA_BLOB in_context_buffer;
163 955 : struct smb2_create_blobs in_context_blobs;
164 482073 : uint32_t context_offset = 0;
165 482073 : uint32_t context_available_length = 0;
166 955 : uint32_t dyn_offset;
167 955 : NTSTATUS status;
168 955 : bool ok;
169 955 : struct tevent_req *tsubreq;
170 :
171 482073 : status = smbd_smb2_request_verify_sizes(smb2req, 0x39);
172 482073 : if (!NT_STATUS_IS_OK(status)) {
173 0 : return smbd_smb2_request_error(smb2req, status);
174 : }
175 482073 : inbody = SMBD_SMB2_IN_BODY_PTR(smb2req);
176 :
177 482073 : in_oplock_level = CVAL(inbody, 0x03);
178 482073 : in_impersonation_level = IVAL(inbody, 0x04);
179 482073 : in_desired_access = IVAL(inbody, 0x18);
180 482073 : in_file_attributes = IVAL(inbody, 0x1C);
181 482073 : in_share_access = IVAL(inbody, 0x20);
182 482073 : in_create_disposition = IVAL(inbody, 0x24);
183 482073 : in_create_options = IVAL(inbody, 0x28);
184 482073 : in_name_offset = SVAL(inbody, 0x2C);
185 482073 : in_name_length = SVAL(inbody, 0x2E);
186 482073 : in_context_offset = IVAL(inbody, 0x30);
187 482073 : in_context_length = IVAL(inbody, 0x34);
188 :
189 : /*
190 : * First check if the dynamic name and context buffers
191 : * are correctly specified.
192 : *
193 : * Note: That we don't check if the name and context buffers
194 : * overlap
195 : */
196 :
197 482073 : dyn_offset = SMB2_HDR_BODY + SMBD_SMB2_IN_BODY_LEN(smb2req);
198 :
199 482073 : if (in_name_offset == 0 && in_name_length == 0) {
200 : /* This is ok */
201 0 : name_offset = 0;
202 482073 : } else if (in_name_offset < dyn_offset) {
203 0 : return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
204 : } else {
205 482073 : name_offset = in_name_offset - dyn_offset;
206 : }
207 :
208 482073 : indyniov = SMBD_SMB2_IN_DYN_IOV(smb2req);
209 :
210 482073 : if (name_offset > indyniov->iov_len) {
211 0 : return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
212 : }
213 :
214 482073 : name_available_length = indyniov->iov_len - name_offset;
215 :
216 482073 : if (in_name_length > name_available_length) {
217 0 : return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
218 : }
219 :
220 482073 : in_name_buffer.data = (uint8_t *)indyniov->iov_base + name_offset;
221 482073 : in_name_buffer.length = in_name_length;
222 :
223 482073 : if (in_context_offset == 0 && in_context_length == 0) {
224 : /* This is ok */
225 473288 : context_offset = 0;
226 7830 : } else if (in_context_offset < dyn_offset) {
227 0 : return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
228 : } else {
229 7830 : context_offset = in_context_offset - dyn_offset;
230 : }
231 :
232 482073 : if (context_offset > indyniov->iov_len) {
233 0 : return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
234 : }
235 :
236 482073 : context_available_length = indyniov->iov_len - context_offset;
237 :
238 482073 : if (in_context_length > context_available_length) {
239 0 : return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
240 : }
241 :
242 482073 : in_context_buffer.data = (uint8_t *)indyniov->iov_base +
243 : context_offset;
244 482073 : in_context_buffer.length = in_context_length;
245 :
246 : /*
247 : * Now interpret the name and context buffers
248 : */
249 :
250 482073 : ok = convert_string_talloc(smb2req, CH_UTF16, CH_UNIX,
251 481118 : in_name_buffer.data,
252 : in_name_buffer.length,
253 : &in_name_string,
254 : &in_name_string_size);
255 482073 : if (!ok) {
256 0 : return smbd_smb2_request_error(smb2req, NT_STATUS_ILLEGAL_CHARACTER);
257 : }
258 :
259 482073 : if (in_name_buffer.length == 0) {
260 27954 : in_name_string_size = 0;
261 : }
262 :
263 482073 : if (strlen(in_name_string) != in_name_string_size) {
264 0 : return smbd_smb2_request_error(smb2req, NT_STATUS_OBJECT_NAME_INVALID);
265 : }
266 :
267 482073 : ZERO_STRUCT(in_context_blobs);
268 482073 : status = smb2_create_blob_parse(smb2req, in_context_buffer, &in_context_blobs);
269 482073 : if (!NT_STATUS_IS_OK(status)) {
270 0 : return smbd_smb2_request_error(smb2req, status);
271 : }
272 :
273 482073 : if (CHECK_DEBUGLVL(DBGLVL_DEBUG)) {
274 0 : char *str = talloc_asprintf(
275 0 : talloc_tos(),
276 : "\nGot %"PRIu32" create blobs\n",
277 : in_context_blobs.num_blobs);
278 0 : uint32_t i;
279 :
280 0 : for (i=0; i<in_context_blobs.num_blobs; i++) {
281 0 : struct smb2_create_blob *b =
282 0 : &in_context_blobs.blobs[i];
283 0 : talloc_asprintf_addbuf(&str, "[%"PRIu32"]\n", i);
284 0 : dump_data_addbuf(
285 0 : (uint8_t *)b->tag, strlen(b->tag), &str);
286 0 : dump_data_addbuf(
287 0 : b->data.data, b->data.length, &str);
288 : }
289 0 : DBG_DEBUG("%s", str);
290 0 : TALLOC_FREE(str);
291 : }
292 :
293 483028 : tsubreq = smbd_smb2_create_send(smb2req,
294 482073 : smb2req->sconn->ev_ctx,
295 : smb2req,
296 : in_oplock_level,
297 : in_impersonation_level,
298 : in_desired_access,
299 : in_file_attributes,
300 : in_share_access,
301 : in_create_disposition,
302 : in_create_options,
303 : in_name_string,
304 : in_context_blobs);
305 482073 : if (tsubreq == NULL) {
306 0 : smb2req->subreq = NULL;
307 0 : return smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
308 : }
309 482073 : tevent_req_set_callback(tsubreq, smbd_smb2_request_create_done, smb2req);
310 :
311 482073 : return smbd_smb2_request_pending_queue(smb2req, tsubreq, 500);
312 : }
313 :
314 106438 : static uint64_t get_mid_from_smb2req(struct smbd_smb2_request *smb2req)
315 : {
316 106438 : uint8_t *reqhdr = SMBD_SMB2_OUT_HDR_PTR(smb2req);
317 106438 : return BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
318 : }
319 :
320 481681 : static void smbd_smb2_request_create_done(struct tevent_req *tsubreq)
321 : {
322 481681 : struct smbd_smb2_request *smb2req = tevent_req_callback_data(tsubreq,
323 : struct smbd_smb2_request);
324 955 : DATA_BLOB outbody;
325 955 : DATA_BLOB outdyn;
326 481681 : uint8_t out_oplock_level = 0;
327 481681 : uint32_t out_create_action = 0;
328 481681 : connection_struct *conn = smb2req->tcon->compat;
329 481681 : struct timespec out_creation_ts = { 0, };
330 481681 : struct timespec out_last_access_ts = { 0, };
331 481681 : struct timespec out_last_write_ts = { 0, };
332 481681 : struct timespec out_change_ts = { 0, };
333 481681 : uint64_t out_allocation_size = 0;
334 481681 : uint64_t out_end_of_file = 0;
335 481681 : uint32_t out_file_attributes = 0;
336 481681 : uint64_t out_file_id_persistent = 0;
337 481681 : uint64_t out_file_id_volatile = 0;
338 955 : struct smb2_create_blobs out_context_blobs;
339 955 : DATA_BLOB out_context_buffer;
340 481681 : uint16_t out_context_buffer_offset = 0;
341 955 : NTSTATUS status;
342 955 : NTSTATUS error; /* transport error */
343 :
344 481681 : status = smbd_smb2_create_recv(tsubreq,
345 : smb2req,
346 : &out_oplock_level,
347 : &out_create_action,
348 : &out_creation_ts,
349 : &out_last_access_ts,
350 : &out_last_write_ts,
351 : &out_change_ts,
352 : &out_allocation_size,
353 : &out_end_of_file,
354 : &out_file_attributes,
355 : &out_file_id_persistent,
356 : &out_file_id_volatile,
357 : &out_context_blobs);
358 481681 : if (!NT_STATUS_IS_OK(status)) {
359 110621 : if (smbd_smb2_is_compound(smb2req)) {
360 18 : smb2req->compound_create_err = status;
361 : }
362 110621 : error = smbd_smb2_request_error(smb2req, status);
363 110621 : if (!NT_STATUS_IS_OK(error)) {
364 0 : smbd_server_connection_terminate(smb2req->xconn,
365 : nt_errstr(error));
366 110621 : return;
367 : }
368 110459 : return;
369 : }
370 :
371 371060 : status = smb2_create_blob_push(smb2req, &out_context_buffer, out_context_blobs);
372 371060 : if (!NT_STATUS_IS_OK(status)) {
373 0 : error = smbd_smb2_request_error(smb2req, status);
374 0 : if (!NT_STATUS_IS_OK(error)) {
375 0 : smbd_server_connection_terminate(smb2req->xconn,
376 : nt_errstr(error));
377 0 : return;
378 : }
379 0 : return;
380 : }
381 :
382 371060 : if (out_context_buffer.length > 0) {
383 3726 : out_context_buffer_offset = SMB2_HDR_BODY + 0x58;
384 : }
385 :
386 371060 : outbody = smbd_smb2_generate_outbody(smb2req, 0x58);
387 371060 : if (outbody.data == NULL) {
388 0 : error = smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
389 0 : if (!NT_STATUS_IS_OK(error)) {
390 0 : smbd_server_connection_terminate(smb2req->xconn,
391 : nt_errstr(error));
392 0 : return;
393 : }
394 0 : return;
395 : }
396 :
397 371060 : SSVAL(outbody.data, 0x00, 0x58 + 1); /* struct size */
398 371060 : SCVAL(outbody.data, 0x02,
399 : out_oplock_level); /* oplock level */
400 371060 : SCVAL(outbody.data, 0x03, 0); /* reserved */
401 371060 : SIVAL(outbody.data, 0x04,
402 : out_create_action); /* create action */
403 371060 : put_long_date_full_timespec(conn->ts_res,
404 370267 : (char *)outbody.data + 0x08,
405 : &out_creation_ts); /* creation time */
406 371060 : put_long_date_full_timespec(conn->ts_res,
407 370267 : (char *)outbody.data + 0x10,
408 : &out_last_access_ts); /* last access time */
409 371060 : put_long_date_full_timespec(conn->ts_res,
410 370267 : (char *)outbody.data + 0x18,
411 : &out_last_write_ts); /* last write time */
412 371060 : put_long_date_full_timespec(conn->ts_res,
413 370267 : (char *)outbody.data + 0x20,
414 : &out_change_ts); /* change time */
415 371060 : SBVAL(outbody.data, 0x28,
416 : out_allocation_size); /* allocation size */
417 371060 : SBVAL(outbody.data, 0x30,
418 : out_end_of_file); /* end of file */
419 371060 : SIVAL(outbody.data, 0x38,
420 : out_file_attributes); /* file attributes */
421 371060 : SIVAL(outbody.data, 0x3C, 0); /* reserved */
422 371060 : SBVAL(outbody.data, 0x40,
423 : out_file_id_persistent); /* file id (persistent) */
424 371060 : SBVAL(outbody.data, 0x48,
425 : out_file_id_volatile); /* file id (volatile) */
426 371060 : SIVAL(outbody.data, 0x50,
427 : out_context_buffer_offset); /* create contexts offset */
428 371060 : SIVAL(outbody.data, 0x54,
429 : out_context_buffer.length); /* create contexts length */
430 :
431 371060 : outdyn = out_context_buffer;
432 :
433 371060 : error = smbd_smb2_request_done(smb2req, outbody, &outdyn);
434 371060 : if (!NT_STATUS_IS_OK(error)) {
435 4 : smbd_server_connection_terminate(smb2req->xconn,
436 : nt_errstr(error));
437 0 : return;
438 : }
439 : }
440 :
441 1154 : static bool smb2_lease_key_valid(const struct smb2_lease_key *key)
442 : {
443 1154 : return ((key->data[0] != 0) || (key->data[1] != 0));
444 : }
445 :
446 130 : static NTSTATUS smbd_smb2_create_durable_lease_check(struct smb_request *smb1req,
447 : const char *requested_filename, const struct files_struct *fsp,
448 : const struct smb2_lease *lease_ptr)
449 : {
450 130 : struct files_struct *dirfsp = NULL;
451 130 : char *filename = NULL;
452 130 : struct smb_filename *smb_fname = NULL;
453 0 : uint32_t ucf_flags;
454 130 : NTTIME twrp = fsp->fsp_name->twrp;
455 0 : NTSTATUS status;
456 130 : bool is_dfs = (smb1req->flags2 & FLAGS2_DFS_PATHNAMES);
457 130 : bool is_posix = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
458 :
459 130 : if (lease_ptr == NULL) {
460 90 : if (fsp->oplock_type != LEASE_OPLOCK) {
461 78 : return NT_STATUS_OK;
462 : }
463 12 : DEBUG(10, ("Reopened file has lease, but no lease "
464 : "requested\n"));
465 12 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
466 : }
467 :
468 40 : if (fsp->oplock_type != LEASE_OPLOCK) {
469 0 : DEBUG(10, ("Lease requested, but reopened file has no "
470 : "lease\n"));
471 0 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
472 : }
473 :
474 40 : if (!smb2_lease_key_equal(&lease_ptr->lease_key,
475 40 : &fsp->lease->lease.lease_key)) {
476 8 : DEBUG(10, ("Different lease key requested than found "
477 : "in reopened file\n"));
478 8 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
479 : }
480 :
481 32 : if (is_dfs) {
482 0 : const char *non_dfs_requested_filename = NULL;
483 : /*
484 : * With a DFS flag set, remove any DFS prefix
485 : * before further processing.
486 : */
487 0 : status = smb2_strip_dfs_path(requested_filename,
488 : &non_dfs_requested_filename);
489 0 : if (!NT_STATUS_IS_OK(status)) {
490 0 : return status;
491 : }
492 : /*
493 : * TODO: Note for dealing with reparse point errors.
494 : * We will need to remember and store the number of characters
495 : * we have removed here, which is
496 : * (requested_filename - non_dfs_requested_filename)
497 : * in order to correctly report how many characters we
498 : * have removed before hitting the reparse point.
499 : * This will be a patch needed once we properly
500 : * deal with reparse points later.
501 : */
502 0 : requested_filename = non_dfs_requested_filename;
503 : /*
504 : * Now we're no longer dealing with a DFS path, so
505 : * remove the flag.
506 : */
507 0 : smb1req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
508 0 : is_dfs = false;
509 : }
510 :
511 32 : filename = talloc_strdup(talloc_tos(), requested_filename);
512 32 : if (filename == NULL) {
513 0 : return NT_STATUS_NO_MEMORY;
514 : }
515 :
516 : /* This also converts '\' to '/' */
517 32 : status = check_path_syntax(filename, is_posix);
518 32 : if (!NT_STATUS_IS_OK(status)) {
519 0 : TALLOC_FREE(filename);
520 0 : return status;
521 : }
522 :
523 32 : ucf_flags = filename_create_ucf_flags(smb1req, FILE_OPEN);
524 32 : status = filename_convert_dirfsp(talloc_tos(),
525 32 : fsp->conn,
526 : filename,
527 : ucf_flags,
528 : twrp,
529 : &dirfsp,
530 : &smb_fname);
531 32 : TALLOC_FREE(filename);
532 32 : if (!NT_STATUS_IS_OK(status)) {
533 0 : DEBUG(10, ("filename_convert returned %s\n",
534 : nt_errstr(status)));
535 0 : return status;
536 : }
537 :
538 32 : if (!strequal(fsp->fsp_name->base_name, smb_fname->base_name)) {
539 8 : DEBUG(10, ("Lease requested for file %s, reopened file "
540 : "is named %s\n", smb_fname->base_name,
541 : fsp->fsp_name->base_name));
542 8 : TALLOC_FREE(smb_fname);
543 8 : return NT_STATUS_INVALID_PARAMETER;
544 : }
545 :
546 24 : TALLOC_FREE(smb_fname);
547 :
548 24 : return NT_STATUS_OK;
549 : }
550 :
551 : struct smbd_smb2_create_state {
552 : struct tevent_context *ev;
553 : struct smbd_smb2_request *smb2req;
554 : struct GUID req_guid;
555 : struct smb_request *smb1req;
556 : bool open_was_deferred;
557 : struct tevent_immediate *im;
558 : struct timeval request_time;
559 : struct file_id id;
560 : struct deferred_open_record *open_rec;
561 : files_struct *result;
562 : bool replay_operation;
563 : uint8_t in_oplock_level;
564 : uint32_t in_create_disposition;
565 : uint32_t in_create_options;
566 : int requested_oplock_level;
567 : int info;
568 : char *fname;
569 : struct ea_list *ea_list;
570 : NTTIME max_access_time;
571 : struct security_descriptor *sec_desc;
572 : uint64_t allocation_size;
573 : struct GUID _create_guid;
574 : struct GUID *create_guid;
575 : struct GUID _purge_create_guid;
576 : struct GUID *purge_create_guid;
577 : bool update_open;
578 : bool durable_requested;
579 : uint32_t durable_timeout_msec;
580 : bool do_durable_reconnect;
581 : uint64_t persistent_id;
582 : struct smb2_lease lease;
583 : struct smb2_lease *lease_ptr;
584 : ssize_t lease_len;
585 : bool need_replay_cache;
586 : struct smbXsrv_open *op;
587 : NTTIME twrp_time;
588 :
589 : struct smb2_create_blob *dhnc;
590 : struct smb2_create_blob *dh2c;
591 : struct smb2_create_blob *dhnq;
592 : struct smb2_create_blob *dh2q;
593 : struct smb2_create_blob *rqls;
594 : struct smb2_create_blob *exta;
595 : struct smb2_create_blob *mxac;
596 : struct smb2_create_blob *secd;
597 : struct smb2_create_blob *alsi;
598 : struct smb2_create_blob *twrp;
599 : struct smb2_create_blob *qfid;
600 : struct smb2_create_blob *posx;
601 : struct smb2_create_blob *svhdx;
602 :
603 : uint8_t out_oplock_level;
604 : uint32_t out_create_action;
605 : struct timespec out_creation_ts;
606 : struct timespec out_last_access_ts;
607 : struct timespec out_last_write_ts;
608 : struct timespec out_change_ts;
609 : uint64_t out_allocation_size;
610 : uint64_t out_end_of_file;
611 : uint32_t out_file_attributes;
612 : uint64_t out_file_id_persistent;
613 : uint64_t out_file_id_volatile;
614 : struct smb2_create_blobs *out_context_blobs;
615 : };
616 :
617 : static void smbd_smb2_create_purge_replay_cache(struct tevent_req *req,
618 : const char *caller_func);
619 :
620 963754 : static void smbd_smb2_create_cleanup(struct tevent_req *req,
621 : enum tevent_req_state req_state)
622 : {
623 963754 : smbd_smb2_create_purge_replay_cache(req, __func__);
624 963754 : }
625 :
626 482069 : static NTSTATUS smbd_smb2_create_fetch_create_ctx(
627 : struct tevent_req *req,
628 : struct smb2_create_blobs *in_context_blobs)
629 : {
630 482069 : struct smbd_smb2_create_state *state = tevent_req_data(
631 : req, struct smbd_smb2_create_state);
632 482069 : struct smbd_smb2_request *smb2req = state->smb2req;
633 482069 : struct smbXsrv_connection *xconn = smb2req->xconn;
634 :
635 482069 : state->dhnq = smb2_create_blob_find(in_context_blobs,
636 : SMB2_CREATE_TAG_DHNQ);
637 482069 : state->dhnc = smb2_create_blob_find(in_context_blobs,
638 : SMB2_CREATE_TAG_DHNC);
639 482069 : state->dh2q = smb2_create_blob_find(in_context_blobs,
640 : SMB2_CREATE_TAG_DH2Q);
641 482069 : state->dh2c = smb2_create_blob_find(in_context_blobs,
642 : SMB2_CREATE_TAG_DH2C);
643 482069 : if (xconn->smb2.server.capabilities & SMB2_CAP_LEASING) {
644 321284 : state->rqls = smb2_create_blob_find(in_context_blobs,
645 : SMB2_CREATE_TAG_RQLS);
646 : }
647 :
648 482069 : if (((state->dhnc != NULL) && (state->dh2c != NULL)) ||
649 481110 : ((state->dhnc != NULL) && (state->dh2q != NULL)) ||
650 482061 : ((state->dh2c != NULL) && (state->dhnq != NULL)) ||
651 482057 : ((state->dh2q != NULL) && (state->dh2c != NULL)))
652 : {
653 : /* not both are allowed at the same time */
654 16 : return NT_STATUS_INVALID_PARAMETER;
655 : }
656 :
657 482053 : if (state->dhnc != NULL) {
658 0 : uint32_t num_blobs_allowed;
659 :
660 118 : if (state->dhnc->data.length != 16) {
661 0 : return NT_STATUS_INVALID_PARAMETER;
662 : }
663 :
664 : /*
665 : * According to MS-SMB2: 3.3.5.9.7, "Handling the
666 : * SMB2_CREATE_DURABLE_HANDLE_RECONNECT Create Context",
667 : * we should ignore an additional dhnq blob, but fail
668 : * the request (with status OBJECT_NAME_NOT_FOUND) if
669 : * any other extra create blob has been provided.
670 : *
671 : * (Note that the cases of an additional dh2q or dh2c blob
672 : * which require a different error code, have been treated
673 : * above.)
674 : */
675 :
676 118 : if (state->dhnq != NULL) {
677 4 : num_blobs_allowed = 2;
678 : } else {
679 114 : num_blobs_allowed = 1;
680 : }
681 :
682 118 : if (state->rqls != NULL) {
683 24 : num_blobs_allowed += 1;
684 : }
685 :
686 118 : if (in_context_blobs->num_blobs != num_blobs_allowed) {
687 6 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
688 : }
689 : }
690 :
691 482047 : if (state->dh2c!= NULL) {
692 0 : uint32_t num_blobs_allowed;
693 :
694 102 : if (state->dh2c->data.length != 36) {
695 0 : return NT_STATUS_INVALID_PARAMETER;
696 : }
697 :
698 : /*
699 : * According to MS-SMB2: 3.3.5.9.12, "Handling the
700 : * SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 Create Context",
701 : * we should fail the request with status
702 : * OBJECT_NAME_NOT_FOUND if any other create blob has been
703 : * provided.
704 : *
705 : * (Note that the cases of an additional dhnq, dhnc or dh2q
706 : * blob which require a different error code, have been
707 : * treated above.)
708 : */
709 :
710 102 : num_blobs_allowed = 1;
711 :
712 102 : if (state->rqls != NULL) {
713 28 : num_blobs_allowed += 1;
714 : }
715 :
716 102 : if (in_context_blobs->num_blobs != num_blobs_allowed) {
717 6 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
718 : }
719 : }
720 :
721 482041 : state->exta = smb2_create_blob_find(in_context_blobs,
722 : SMB2_CREATE_TAG_EXTA);
723 482041 : state->mxac = smb2_create_blob_find(in_context_blobs,
724 : SMB2_CREATE_TAG_MXAC);
725 482041 : state->secd = smb2_create_blob_find(in_context_blobs,
726 : SMB2_CREATE_TAG_SECD);
727 482041 : state->alsi = smb2_create_blob_find(in_context_blobs,
728 : SMB2_CREATE_TAG_ALSI);
729 482041 : state->twrp = smb2_create_blob_find(in_context_blobs,
730 : SMB2_CREATE_TAG_TWRP);
731 482041 : state->qfid = smb2_create_blob_find(in_context_blobs,
732 : SMB2_CREATE_TAG_QFID);
733 482041 : if (xconn->protocol >= PROTOCOL_SMB3_02) {
734 : /*
735 : * This was introduced with SMB3_02
736 : */
737 473014 : state->svhdx = smb2_create_blob_find(
738 : in_context_blobs, SVHDX_OPEN_DEVICE_CONTEXT);
739 : }
740 503899 : if (xconn->smb2.server.posix_extensions_negotiated &&
741 21858 : lp_smb3_unix_extensions(SNUM(state->smb1req->conn)))
742 : {
743 : /*
744 : * Negprot only allowed this for proto>=3.11
745 : */
746 21858 : SMB_ASSERT(xconn->protocol >= PROTOCOL_SMB3_11);
747 :
748 21858 : state->posx = smb2_create_blob_find(
749 : in_context_blobs, SMB2_CREATE_TAG_POSIX);
750 : /*
751 : * Setting the bool below will cause
752 : * ucf_flags_from_smb_request() to
753 : * return UCF_POSIX_PATHNAMES in ucf_flags.
754 : */
755 21858 : state->smb1req->posix_pathnames = (state->posx != NULL);
756 : }
757 :
758 482041 : return NT_STATUS_OK;
759 : }
760 :
761 : static void smbd_smb2_create_before_exec(struct tevent_req *req);
762 : static void smbd_smb2_create_after_exec(struct tevent_req *req);
763 : static void smbd_smb2_create_finish(struct tevent_req *req);
764 :
765 482073 : static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
766 : struct tevent_context *ev,
767 : struct smbd_smb2_request *smb2req,
768 : uint8_t in_oplock_level,
769 : uint32_t in_impersonation_level,
770 : uint32_t in_desired_access,
771 : uint32_t in_file_attributes,
772 : uint32_t in_share_access,
773 : uint32_t in_create_disposition,
774 : uint32_t _in_create_options,
775 : const char *in_name,
776 : struct smb2_create_blobs in_context_blobs)
777 : {
778 482073 : struct tevent_req *req = NULL;
779 482073 : struct smbd_smb2_create_state *state = NULL;
780 955 : NTSTATUS status;
781 482073 : struct smb_request *smb1req = NULL;
782 482073 : struct files_struct *dirfsp = NULL;
783 482073 : struct smb_filename *smb_fname = NULL;
784 955 : uint32_t ucf_flags;
785 482073 : bool is_dfs = false;
786 482073 : bool is_posix = false;
787 :
788 482073 : req = tevent_req_create(mem_ctx, &state,
789 : struct smbd_smb2_create_state);
790 482073 : if (req == NULL) {
791 0 : return NULL;
792 : }
793 482073 : *state = (struct smbd_smb2_create_state) {
794 : .ev = ev,
795 : .smb2req = smb2req,
796 : .in_oplock_level = in_oplock_level,
797 : .in_create_disposition = in_create_disposition,
798 : .in_create_options = _in_create_options,
799 : };
800 :
801 482073 : smb1req = smbd_smb2_fake_smb_request(smb2req, NULL);
802 482073 : if (tevent_req_nomem(smb1req, req)) {
803 0 : return tevent_req_post(req, state->ev);
804 : }
805 482073 : state->smb1req = smb1req;
806 :
807 482073 : state->req_guid = smbd_request_guid(smb1req, 0);
808 :
809 482073 : tevent_req_set_cleanup_fn(req, smbd_smb2_create_cleanup);
810 :
811 482073 : if (smb2req->subreq == NULL) {
812 481745 : DBG_DEBUG("name [%s]\n", in_name);
813 : } else {
814 328 : struct smbd_smb2_create_state *old_state = tevent_req_data(
815 : smb2req->subreq, struct smbd_smb2_create_state);
816 :
817 328 : DBG_DEBUG("reentrant for file %s\n", in_name);
818 :
819 328 : state->id = old_state->id;
820 328 : state->request_time = old_state->request_time;
821 328 : state->open_rec = talloc_move(state, &old_state->open_rec);
822 328 : state->open_was_deferred = old_state->open_was_deferred;
823 328 : state->_purge_create_guid = old_state->_purge_create_guid;
824 328 : state->purge_create_guid = old_state->purge_create_guid;
825 328 : old_state->purge_create_guid = NULL;
826 : }
827 :
828 482073 : TALLOC_FREE(smb2req->subreq);
829 482073 : smb2req->subreq = req;
830 :
831 482073 : if (lp_fake_oplocks(SNUM(smb2req->tcon->compat))) {
832 0 : state->requested_oplock_level = SMB2_OPLOCK_LEVEL_NONE;
833 : } else {
834 482073 : state->requested_oplock_level = state->in_oplock_level;
835 : }
836 :
837 : /* these are ignored for SMB2 */
838 482073 : state->in_create_options &= ~(0x10); /* NTCREATEX_OPTIONS_SYNC_ALERT */
839 482073 : state->in_create_options &= ~(0x20); /* NTCREATEX_OPTIONS_ASYNC_ALERT */
840 :
841 482073 : in_file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS;
842 :
843 482073 : is_dfs = (smb1req->flags2 & FLAGS2_DFS_PATHNAMES);
844 482073 : if (is_dfs) {
845 13556 : const char *non_dfs_in_name = NULL;
846 : /*
847 : * With a DFS flag set, remove any DFS prefix
848 : * before further processing.
849 : */
850 13556 : status = smb2_strip_dfs_path(in_name, &non_dfs_in_name);
851 13556 : if (!NT_STATUS_IS_OK(status)) {
852 4 : tevent_req_nterror(req, status);
853 4 : return tevent_req_post(req, state->ev);
854 : }
855 : /*
856 : * TODO: Note for dealing with reparse point errors.
857 : * We will need to remember and store the number of characters
858 : * we have removed here, which is (non_dfs_in_name - in_name)
859 : * in order to correctly report how many characters we
860 : * have removed before hitting the reparse point.
861 : * This will be a patch needed once we properly
862 : * deal with reparse points later.
863 : */
864 13552 : in_name = non_dfs_in_name;
865 : /*
866 : * Now we're no longer dealing with a DFS path, so
867 : * remove the flag.
868 : */
869 13552 : smb1req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
870 13552 : is_dfs = false;
871 : }
872 :
873 482069 : state->fname = talloc_strdup(state, in_name);
874 482069 : if (tevent_req_nomem(state->fname, req)) {
875 0 : return tevent_req_post(req, state->ev);
876 : }
877 :
878 482069 : state->out_context_blobs = talloc_zero(state, struct smb2_create_blobs);
879 482069 : if (tevent_req_nomem(state->out_context_blobs, req)) {
880 0 : return tevent_req_post(req, state->ev);
881 : }
882 :
883 482069 : status = smbd_smb2_create_fetch_create_ctx(req, &in_context_blobs);
884 482069 : if (tevent_req_nterror(req, status)) {
885 28 : return tevent_req_post(req, state->ev);
886 : }
887 :
888 482041 : if (IS_IPC(smb1req->conn)) {
889 17156 : const char *pipe_name = in_name;
890 :
891 17156 : if (state->dhnc != NULL || state->dh2c != NULL) {
892 : /* durable handles are not supported on IPC$ */
893 0 : tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
894 0 : return tevent_req_post(req, state->ev);
895 : }
896 :
897 17156 : if (!lp_nt_pipe_support()) {
898 0 : tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
899 0 : return tevent_req_post(req, state->ev);
900 : }
901 :
902 17156 : status = open_np_file(smb1req, pipe_name, &state->result);
903 17156 : if (tevent_req_nterror(req, status)) {
904 119 : return tevent_req_post(req, state->ev);
905 : }
906 17037 : state->info = FILE_WAS_OPENED;
907 :
908 17037 : smbd_smb2_create_finish(req);
909 17037 : return req;
910 : }
911 :
912 464885 : if (CAN_PRINT(smb1req->conn)) {
913 26 : if (state->dhnc != NULL || state->dh2c != NULL) {
914 : /* durable handles are not supported on printers */
915 0 : tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
916 0 : return tevent_req_post(req, state->ev);
917 : }
918 :
919 26 : status = file_new(smb1req, smb1req->conn, &state->result);
920 26 : if (tevent_req_nterror(req, status)) {
921 0 : return tevent_req_post(req, state->ev);
922 : }
923 :
924 26 : status = print_spool_open(state->result, in_name,
925 : smb1req->vuid);
926 26 : if (tevent_req_nterror(req, status)) {
927 0 : file_free(smb1req, state->result);
928 0 : return tevent_req_post(req, state->ev);
929 : }
930 26 : state->info = FILE_WAS_CREATED;
931 :
932 26 : smbd_smb2_create_finish(req);
933 26 : return req;
934 : }
935 :
936 : /* Check for trailing slash specific directory handling. */
937 464859 : status = windows_name_trailing_check(state->fname,
938 464859 : state->in_create_options);
939 464859 : if (tevent_req_nterror(req, status)) {
940 12 : return tevent_req_post(req, state->ev);
941 : }
942 :
943 464847 : smbd_smb2_create_before_exec(req);
944 464847 : if (!tevent_req_is_in_progress(req)) {
945 162 : return tevent_req_post(req, state->ev);
946 : }
947 :
948 464685 : DBG_DEBUG("open execution phase\n");
949 :
950 : /*
951 : * For the backend file open procedure, there are
952 : * three possible modes: replay operation (in which case
953 : * there is nothing else to do), durable_reconnect or
954 : * new open.
955 : */
956 464685 : if (state->replay_operation) {
957 66 : state->result = state->op->compat;
958 66 : state->result->op = state->op;
959 66 : state->update_open = false;
960 66 : state->info = state->op->create_action;
961 :
962 66 : smbd_smb2_create_after_exec(req);
963 66 : if (!tevent_req_is_in_progress(req)) {
964 0 : return tevent_req_post(req, state->ev);
965 : }
966 :
967 66 : smbd_smb2_create_finish(req);
968 66 : return req;
969 : }
970 :
971 464619 : if (state->do_durable_reconnect) {
972 208 : DATA_BLOB new_cookie = data_blob_null;
973 208 : NTTIME now = timeval_to_nttime(&smb2req->request_time);
974 :
975 208 : status = smb2srv_open_recreate(smb2req->xconn,
976 208 : smb1req->conn->session_info,
977 208 : state->persistent_id,
978 208 : state->create_guid,
979 : now,
980 208 : &state->op);
981 208 : if (tevent_req_nterror(req, status)) {
982 50 : DBG_NOTICE("smb2srv_open_recreate failed: %s\n",
983 : nt_errstr(status));
984 50 : return tevent_req_post(req, state->ev);
985 : }
986 :
987 158 : DBG_DEBUG("%s to recreate durable handle\n",
988 : state->op->global->durable ? "succeeded" : "failed");
989 :
990 158 : if (!state->op->global->durable) {
991 0 : talloc_free(state->op);
992 0 : tevent_req_nterror(req,
993 : NT_STATUS_OBJECT_NAME_NOT_FOUND);
994 0 : return tevent_req_post(req, state->ev);
995 : }
996 :
997 158 : status = SMB_VFS_DURABLE_RECONNECT(smb1req->conn,
998 : smb1req,
999 : state->op, /* smbXsrv_open input */
1000 : state->op->global->backend_cookie,
1001 : state->op, /* TALLOC_CTX */
1002 : &state->result,
1003 : &new_cookie);
1004 158 : if (!NT_STATUS_IS_OK(status)) {
1005 0 : NTSTATUS return_status;
1006 :
1007 28 : return_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
1008 :
1009 28 : DBG_NOTICE("durable_reconnect failed: %s => %s\n",
1010 : nt_errstr(status),
1011 : nt_errstr(return_status));
1012 :
1013 28 : tevent_req_nterror(req, return_status);
1014 28 : return tevent_req_post(req, state->ev);
1015 : }
1016 :
1017 130 : DBG_DEBUG("oplock_type=%u, lease_ptr==%p\n",
1018 : (unsigned)state->result->oplock_type, state->lease_ptr);
1019 :
1020 130 : status = smbd_smb2_create_durable_lease_check(
1021 130 : smb1req, state->fname, state->result, state->lease_ptr);
1022 130 : if (tevent_req_nterror(req, status)) {
1023 28 : close_file_free(
1024 28 : smb1req, &state->result, SHUTDOWN_CLOSE);
1025 28 : return tevent_req_post(req, state->ev);
1026 : }
1027 :
1028 102 : data_blob_free(&state->op->global->backend_cookie);
1029 102 : state->op->global->backend_cookie = new_cookie;
1030 :
1031 102 : state->op->status = NT_STATUS_OK;
1032 102 : state->op->global->disconnect_time = 0;
1033 :
1034 : /* save the timeout for later update */
1035 102 : state->durable_timeout_msec = state->op->global->durable_timeout_msec;
1036 :
1037 102 : state->update_open = true;
1038 :
1039 102 : state->info = FILE_WAS_OPENED;
1040 :
1041 102 : smbd_smb2_create_after_exec(req);
1042 102 : if (!tevent_req_is_in_progress(req)) {
1043 0 : return tevent_req_post(req, state->ev);
1044 : }
1045 :
1046 102 : smbd_smb2_create_finish(req);
1047 102 : return req;
1048 : }
1049 :
1050 464411 : if (state->requested_oplock_level == SMB2_OPLOCK_LEVEL_LEASE) {
1051 1102 : if (state->lease_ptr == NULL) {
1052 18 : state->requested_oplock_level = SMB2_OPLOCK_LEVEL_NONE;
1053 : }
1054 : } else {
1055 463309 : state->lease_ptr = NULL;
1056 : }
1057 :
1058 464411 : is_posix = (state->posx != NULL);
1059 :
1060 : /* convert '\\' into '/' */
1061 464411 : status = check_path_syntax(state->fname, is_posix);
1062 464411 : if (tevent_req_nterror(req, status)) {
1063 60 : return tevent_req_post(req, state->ev);
1064 : }
1065 :
1066 464686 : ucf_flags = filename_create_ucf_flags(
1067 464351 : smb1req, state->in_create_disposition);
1068 :
1069 464686 : status = filename_convert_dirfsp(
1070 : req,
1071 : smb1req->conn,
1072 464351 : state->fname,
1073 : ucf_flags,
1074 464351 : state->twrp_time,
1075 : &dirfsp,
1076 : &smb_fname);
1077 464351 : if (tevent_req_nterror(req, status)) {
1078 5172 : return tevent_req_post(req, state->ev);
1079 : }
1080 :
1081 : /*
1082 : * MS-SMB2: 2.2.13 SMB2 CREATE Request
1083 : * ImpersonationLevel ... MUST contain one of the
1084 : * following values. The server MUST validate this
1085 : * field, but otherwise ignore it.
1086 : *
1087 : * NB. The source4/torture/smb2/durable_open.c test
1088 : * shows this check is only done on real opens, not
1089 : * on durable handle-reopens.
1090 : */
1091 :
1092 459179 : if (in_impersonation_level >
1093 : SMB2_IMPERSONATION_DELEGATE) {
1094 5 : tevent_req_nterror(req,
1095 : NT_STATUS_BAD_IMPERSONATION_LEVEL);
1096 5 : return tevent_req_post(req, state->ev);
1097 : }
1098 :
1099 : /*
1100 : * We know we're going to do a local open, so now
1101 : * we must be protocol strict. JRA.
1102 : *
1103 : * MS-SMB2: 3.3.5.9 - Receiving an SMB2 CREATE Request
1104 : * If the file name length is greater than zero and the
1105 : * first character is a path separator character, the
1106 : * server MUST fail the request with
1107 : * STATUS_INVALID_PARAMETER.
1108 : */
1109 459174 : if (in_name[0] == '/') {
1110 : /* Names starting with '/' are never allowed. */
1111 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1112 0 : return tevent_req_post(req, ev);
1113 : }
1114 459174 : if (!is_posix && (in_name[0] == '\\')) {
1115 : /*
1116 : * Windows names starting with '\' are not allowed.
1117 : */
1118 5 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1119 5 : return tevent_req_post(req, ev);
1120 : }
1121 :
1122 459169 : status = SMB_VFS_CREATE_FILE(smb1req->conn,
1123 : smb1req,
1124 : dirfsp,
1125 : smb_fname,
1126 : in_desired_access,
1127 : in_share_access,
1128 : state->in_create_disposition,
1129 : state->in_create_options,
1130 : in_file_attributes,
1131 : map_smb2_oplock_levels_to_samba(
1132 : state->requested_oplock_level),
1133 : state->lease_ptr,
1134 : state->allocation_size,
1135 : 0, /* private_flags */
1136 : state->sec_desc,
1137 : state->ea_list,
1138 : &state->result,
1139 : &state->info,
1140 : &in_context_blobs,
1141 : state->out_context_blobs);
1142 459169 : if (NT_STATUS_IS_OK(status) &&
1143 353829 : !(state->in_create_options & FILE_OPEN_REPARSE_POINT))
1144 : {
1145 :
1146 328163 : mode_t mode = state->result->fsp_name->st.st_ex_mode;
1147 :
1148 328163 : if (!(S_ISREG(mode) || S_ISDIR(mode))) {
1149 : /*
1150 : * Only open files and dirs without
1151 : * FILE_OPEN_REPARSE_POINT
1152 : */
1153 0 : close_file_free(smb1req, &state->result, ERROR_CLOSE);
1154 0 : status = NT_STATUS_IO_REPARSE_TAG_NOT_HANDLED;
1155 : }
1156 : }
1157 459169 : if (!NT_STATUS_IS_OK(status)) {
1158 105340 : if (open_was_deferred(smb1req->xconn, smb1req->mid)) {
1159 396 : SMBPROFILE_IOBYTES_ASYNC_SET_IDLE(smb2req->profile);
1160 396 : return req;
1161 : }
1162 104944 : tevent_req_nterror(req, status);
1163 104944 : return tevent_req_post(req, state->ev);
1164 : }
1165 353829 : state->op = state->result->op;
1166 :
1167 353829 : smbd_smb2_create_after_exec(req);
1168 353829 : if (!tevent_req_is_in_progress(req)) {
1169 0 : return tevent_req_post(req, state->ev);
1170 : }
1171 :
1172 353829 : smbd_smb2_create_finish(req);
1173 353829 : return req;
1174 : }
1175 :
1176 963754 : static void smbd_smb2_create_purge_replay_cache(struct tevent_req *req,
1177 : const char *caller_func)
1178 : {
1179 963754 : struct smbd_smb2_create_state *state = tevent_req_data(
1180 : req, struct smbd_smb2_create_state);
1181 1910 : NTSTATUS status;
1182 :
1183 963754 : if (state->purge_create_guid == NULL) {
1184 963676 : return;
1185 : }
1186 :
1187 78 : status = smbXsrv_open_purge_replay_cache(state->smb2req->xconn->client,
1188 78 : state->purge_create_guid);
1189 78 : if (!NT_STATUS_IS_OK(status)) {
1190 0 : struct GUID_txt_buf buf;
1191 :
1192 0 : D_ERR("%s: smbXsrv_open_purge_replay_cache(%s) %s\n",
1193 : caller_func,
1194 : GUID_buf_string(state->purge_create_guid, &buf),
1195 : nt_errstr(status));
1196 : }
1197 :
1198 78 : state->purge_create_guid = NULL;
1199 : }
1200 :
1201 464847 : static void smbd_smb2_create_before_exec(struct tevent_req *req)
1202 : {
1203 464847 : struct smbd_smb2_create_state *state = tevent_req_data(
1204 : req, struct smbd_smb2_create_state);
1205 464847 : struct smbd_smb2_request *smb2req = state->smb2req;
1206 335 : NTSTATUS status;
1207 :
1208 464847 : if (state->exta != NULL) {
1209 225 : if (!lp_ea_support(SNUM(smb2req->tcon->compat))) {
1210 0 : tevent_req_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1211 0 : return;
1212 : }
1213 :
1214 450 : state->ea_list = read_nttrans_ea_list(
1215 : state,
1216 225 : (const char *)state->exta->data.data,
1217 225 : state->exta->data.length);
1218 225 : if (state->ea_list == NULL) {
1219 0 : DEBUG(10,("smbd_smb2_create_send: read_ea_name_list failed.\n"));
1220 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1221 0 : return;
1222 : }
1223 :
1224 450 : if ((state->posx == NULL) &&
1225 225 : ea_list_has_invalid_name(state->ea_list)) {
1226 0 : tevent_req_nterror(req, STATUS_INVALID_EA_NAME);
1227 0 : return;
1228 : }
1229 : }
1230 :
1231 464847 : if (state->mxac != NULL) {
1232 33 : if (state->mxac->data.length == 0) {
1233 33 : state->max_access_time = 0;
1234 0 : } else if (state->mxac->data.length == 8) {
1235 0 : state->max_access_time = BVAL(state->mxac->data.data, 0);
1236 : } else {
1237 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1238 0 : return;
1239 : }
1240 : }
1241 :
1242 464847 : if (state->secd != NULL) {
1243 0 : enum ndr_err_code ndr_err;
1244 :
1245 89 : state->sec_desc = talloc_zero(state, struct security_descriptor);
1246 89 : if (tevent_req_nomem(state->sec_desc, req)) {
1247 0 : return;
1248 : }
1249 :
1250 89 : ndr_err = ndr_pull_struct_blob(&state->secd->data,
1251 89 : state->sec_desc, state->sec_desc,
1252 : (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
1253 89 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1254 0 : DEBUG(2,("ndr_pull_security_descriptor failed: %s\n",
1255 : ndr_errstr(ndr_err)));
1256 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1257 0 : return;
1258 : }
1259 : }
1260 :
1261 464847 : if (state->dhnq != NULL) {
1262 317 : if (state->dhnq->data.length != 16) {
1263 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1264 0 : return;
1265 : }
1266 :
1267 317 : if (state->dh2q != NULL) {
1268 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1269 0 : return;
1270 : }
1271 :
1272 : /*
1273 : * durable handle request is processed below.
1274 : */
1275 317 : state->durable_requested = true;
1276 : /*
1277 : * Set the timeout to 16 mins.
1278 : *
1279 : * TODO: test this against Windows 2012
1280 : * as the default for durable v2 is 1 min.
1281 : */
1282 317 : state->durable_timeout_msec = (16*60*1000);
1283 : }
1284 :
1285 464847 : if (state->dh2q != NULL) {
1286 1116 : const uint8_t *p = state->dh2q->data.data;
1287 1116 : NTTIME now = timeval_to_nttime(&smb2req->request_time);
1288 1116 : uint32_t durable_v2_timeout = 0;
1289 0 : DATA_BLOB create_guid_blob;
1290 0 : const uint8_t *hdr;
1291 0 : uint32_t flags;
1292 :
1293 1116 : if (state->dh2q->data.length != 32) {
1294 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1295 0 : return;
1296 : }
1297 :
1298 1116 : if (state->dhnq != NULL) {
1299 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1300 0 : return;
1301 : }
1302 :
1303 1116 : durable_v2_timeout = IVAL(p, 0);
1304 1116 : create_guid_blob = data_blob_const(p + 16, 16);
1305 :
1306 1116 : status = GUID_from_ndr_blob(&create_guid_blob,
1307 : &state->_create_guid);
1308 1116 : if (tevent_req_nterror(req, status)) {
1309 0 : return;
1310 : }
1311 1116 : state->create_guid = &state->_create_guid;
1312 :
1313 : /*
1314 : * we need to store the create_guid later
1315 : */
1316 1116 : state->update_open = true;
1317 :
1318 : /*
1319 : * And we need to create a cache for replaying the
1320 : * create.
1321 : */
1322 1116 : state->need_replay_cache = true;
1323 :
1324 : /*
1325 : * durable handle v2 request processed below
1326 : */
1327 1116 : state->durable_requested = true;
1328 1116 : state->durable_timeout_msec = MIN(durable_v2_timeout, 300*1000);
1329 1116 : if (state->durable_timeout_msec == 0) {
1330 : /*
1331 : * Set the timeout to 1 min as default.
1332 : *
1333 : * This matches Windows 2012.
1334 : */
1335 422 : state->durable_timeout_msec = (60*1000);
1336 : }
1337 :
1338 : /*
1339 : * Check for replay operation.
1340 : * Only consider it when we have dh2q.
1341 : * If we do not have a replay operation, verify that
1342 : * the create_guid is not cached for replay.
1343 : */
1344 1116 : hdr = SMBD_SMB2_IN_HDR_PTR(smb2req);
1345 1116 : flags = IVAL(hdr, SMB2_HDR_FLAGS);
1346 1116 : state->replay_operation =
1347 1116 : flags & SMB2_HDR_FLAG_REPLAY_OPERATION;
1348 :
1349 1116 : status = smb2srv_open_lookup_replay_cache(smb2req->xconn,
1350 : state->req_guid,
1351 1116 : *state->create_guid,
1352 1116 : state->fname,
1353 : now,
1354 : &state->op);
1355 1116 : if (NT_STATUS_EQUAL(status, NT_STATUS_FWP_RESERVED)) {
1356 : /*
1357 : * We've reserved the replay_cache record
1358 : * for ourself, indicating we're still
1359 : * in progress.
1360 : *
1361 : * It means the smbd_smb2_create_cleanup()
1362 : * may need to call smbXsrv_open_purge_replay_cache()
1363 : * in order to cleanup.
1364 : */
1365 890 : SMB_ASSERT(state->op == NULL);
1366 890 : state->_purge_create_guid = state->_create_guid;
1367 890 : state->purge_create_guid = &state->_purge_create_guid;
1368 890 : status = NT_STATUS_OK;
1369 890 : state->replay_operation = false;
1370 226 : } else if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_NOT_AVAILABLE)) {
1371 152 : tevent_req_nterror(req, status);
1372 156 : return;
1373 74 : } else if (tevent_req_nterror(req, status)) {
1374 0 : DBG_WARNING("smb2srv_open_lookup_replay_cache "
1375 : "failed: %s\n", nt_errstr(status));
1376 0 : return;
1377 74 : } else if (!state->replay_operation) {
1378 : /*
1379 : * If a create without replay operation flag
1380 : * is sent but with a create_guid that is
1381 : * currently in the replay cache -- fail.
1382 : */
1383 4 : status = NT_STATUS_DUPLICATE_OBJECTID;
1384 4 : (void)tevent_req_nterror(req, status);
1385 4 : return;
1386 : }
1387 : }
1388 :
1389 464691 : if (state->dhnc != NULL) {
1390 112 : state->persistent_id = BVAL(state->dhnc->data.data, 0);
1391 112 : state->do_durable_reconnect = true;
1392 : }
1393 :
1394 464691 : if (state->dh2c != NULL) {
1395 96 : const uint8_t *p = state->dh2c->data.data;
1396 0 : DATA_BLOB create_guid_blob;
1397 :
1398 96 : state->persistent_id = BVAL(p, 0);
1399 96 : create_guid_blob = data_blob_const(p + 16, 16);
1400 :
1401 96 : status = GUID_from_ndr_blob(&create_guid_blob,
1402 : &state->_create_guid);
1403 96 : if (tevent_req_nterror(req, status)) {
1404 0 : return;
1405 : }
1406 :
1407 96 : state->create_guid = &state->_create_guid;
1408 96 : state->do_durable_reconnect = true;
1409 : }
1410 :
1411 464691 : if (state->alsi != NULL) {
1412 139 : if (state->alsi->data.length != 8) {
1413 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1414 0 : return;
1415 : }
1416 139 : state->allocation_size = BVAL(state->alsi->data.data, 0);
1417 : }
1418 :
1419 464691 : if (state->twrp != NULL) {
1420 2677 : if (state->twrp->data.length != 8) {
1421 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1422 0 : return;
1423 : }
1424 :
1425 2677 : state->twrp_time = BVAL(state->twrp->data.data, 0);
1426 : }
1427 :
1428 464691 : if (state->qfid != NULL) {
1429 38 : if (state->qfid->data.length != 0) {
1430 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1431 0 : return;
1432 : }
1433 : }
1434 :
1435 464691 : if (state->rqls != NULL) {
1436 1154 : ssize_t lease_len = -1;
1437 :
1438 1154 : lease_len = smb2_lease_pull(state->rqls->data.data,
1439 1154 : state->rqls->data.length,
1440 : &state->lease);
1441 1154 : if (lease_len == -1) {
1442 0 : tevent_req_nterror(
1443 : req, NT_STATUS_INVALID_PARAMETER);
1444 0 : return;
1445 : }
1446 1154 : state->lease_ptr = &state->lease;
1447 :
1448 1154 : if (DEBUGLEVEL >= 10) {
1449 0 : DEBUG(10, ("Got lease request size %d\n",
1450 : (int)lease_len));
1451 0 : NDR_PRINT_DEBUG(smb2_lease, state->lease_ptr);
1452 : }
1453 :
1454 1154 : if (!smb2_lease_key_valid(&state->lease.lease_key)) {
1455 0 : state->lease_ptr = NULL;
1456 0 : state->requested_oplock_level = SMB2_OPLOCK_LEVEL_NONE;
1457 : }
1458 :
1459 1154 : if ((smb2req->xconn->protocol < PROTOCOL_SMB3_00) &&
1460 0 : (state->lease.lease_version != 1))
1461 : {
1462 0 : DEBUG(10, ("v2 lease key only for SMB3\n"));
1463 0 : state->lease_ptr = NULL;
1464 : }
1465 :
1466 : /*
1467 : * Replay with a lease is only allowed if the
1468 : * established open carries a lease with the
1469 : * same lease key.
1470 : */
1471 1154 : if (state->replay_operation) {
1472 18 : struct smb2_lease *op_ls =
1473 18 : &state->op->compat->lease->lease;
1474 18 : int op_oplock = state->op->compat->oplock_type;
1475 :
1476 18 : if (map_samba_oplock_levels_to_smb2(op_oplock)
1477 : != SMB2_OPLOCK_LEVEL_LEASE)
1478 : {
1479 2 : status = NT_STATUS_ACCESS_DENIED;
1480 2 : (void)tevent_req_nterror(req, status);
1481 2 : return;
1482 : }
1483 16 : if (!smb2_lease_key_equal(&state->lease.lease_key,
1484 16 : &op_ls->lease_key))
1485 : {
1486 2 : status = NT_STATUS_ACCESS_DENIED;
1487 2 : (void)tevent_req_nterror(req, status);
1488 2 : return;
1489 : }
1490 : }
1491 : }
1492 :
1493 464687 : if (state->posx != NULL) {
1494 2152 : if (state->posx->data.length != 4) {
1495 2 : DBG_DEBUG("Got %zu bytes POSX cctx, expected 4\n",
1496 : state->posx->data.length);
1497 2 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1498 2 : return;
1499 : }
1500 : }
1501 : }
1502 :
1503 353997 : static void smbd_smb2_create_after_exec(struct tevent_req *req)
1504 : {
1505 353997 : struct smbd_smb2_create_state *state = tevent_req_data(
1506 : req, struct smbd_smb2_create_state);
1507 353997 : connection_struct *conn = state->result->conn;
1508 173 : NTSTATUS status;
1509 :
1510 : /*
1511 : * here we have op == result->op
1512 : */
1513 :
1514 353997 : DBG_DEBUG("response construction phase\n");
1515 :
1516 353997 : state->out_file_attributes = fdos_mode(state->result);
1517 :
1518 353997 : if (state->mxac != NULL) {
1519 0 : NTTIME last_write_time;
1520 :
1521 28 : last_write_time = full_timespec_to_nt_time(
1522 28 : &state->result->fsp_name->st.st_ex_mtime);
1523 28 : if (last_write_time != state->max_access_time) {
1524 0 : uint8_t p[8];
1525 0 : uint32_t max_access_granted;
1526 28 : DATA_BLOB blob = data_blob_const(p, sizeof(p));
1527 :
1528 28 : status = smbd_calculate_access_mask_fsp(
1529 : conn->cwd_fsp,
1530 28 : state->result,
1531 : false,
1532 : SEC_FLAG_MAXIMUM_ALLOWED,
1533 : &max_access_granted);
1534 :
1535 28 : SIVAL(p, 0, NT_STATUS_V(status));
1536 28 : SIVAL(p, 4, max_access_granted);
1537 :
1538 28 : status = smb2_create_blob_add(
1539 28 : state->out_context_blobs,
1540 : state->out_context_blobs,
1541 : SMB2_CREATE_TAG_MXAC,
1542 : blob);
1543 28 : if (!NT_STATUS_IS_OK(status)) {
1544 0 : goto fail;
1545 : }
1546 : }
1547 : }
1548 :
1549 353997 : if (!state->replay_operation && state->durable_requested &&
1550 1050 : (fsp_lease_type(state->result) & SMB2_LEASE_HANDLE))
1551 : {
1552 550 : status = SMB_VFS_DURABLE_COOKIE(
1553 : state->result,
1554 : state->op,
1555 : &state->op->global->backend_cookie);
1556 550 : if (!NT_STATUS_IS_OK(status)) {
1557 0 : state->op->global->backend_cookie = data_blob_null;
1558 : }
1559 : }
1560 353997 : if (!state->replay_operation && state->op->global->backend_cookie.length > 0)
1561 : {
1562 648 : state->update_open = true;
1563 :
1564 648 : state->op->global->durable = true;
1565 648 : state->op->global->durable_timeout_msec = state->durable_timeout_msec;
1566 : }
1567 :
1568 353997 : if (state->update_open) {
1569 990 : state->op->global->create_guid = state->_create_guid;
1570 990 : if (state->need_replay_cache) {
1571 738 : state->op->flags |= SMBXSRV_OPEN_NEED_REPLAY_CACHE;
1572 : }
1573 :
1574 990 : status = smbXsrv_open_update(state->op);
1575 990 : DEBUG(10, ("smb2_create_send: smbXsrv_open_update "
1576 : "returned %s\n",
1577 : nt_errstr(status)));
1578 990 : if (!NT_STATUS_IS_OK(status)) {
1579 0 : goto fail;
1580 : }
1581 :
1582 : /*
1583 : * We should not purge the replay cache anymore
1584 : * as it's attached to the smbXsrv_open record now.
1585 : */
1586 990 : state->purge_create_guid = NULL;
1587 : }
1588 :
1589 353997 : if (state->dhnq != NULL && state->op->global->durable) {
1590 154 : uint8_t p[8] = { 0, };
1591 154 : DATA_BLOB blob = data_blob_const(p, sizeof(p));
1592 :
1593 154 : status = smb2_create_blob_add(state->out_context_blobs,
1594 : state->out_context_blobs,
1595 : SMB2_CREATE_TAG_DHNQ,
1596 : blob);
1597 154 : if (!NT_STATUS_IS_OK(status)) {
1598 0 : goto fail;
1599 : }
1600 : }
1601 :
1602 353997 : if (state->dh2q != NULL && state->op->global->durable &&
1603 : /*
1604 : * For replay operations, we return the dh2q blob
1605 : * in the case of oplocks not based on the state of
1606 : * the open, but on whether it could have been granted
1607 : * for the request data. In the case of leases instead,
1608 : * the state of the open is used...
1609 : */
1610 442 : (!state->replay_operation ||
1611 46 : state->in_oplock_level == SMB2_OPLOCK_LEVEL_BATCH ||
1612 18 : state->in_oplock_level == SMB2_OPLOCK_LEVEL_LEASE))
1613 : {
1614 438 : uint8_t p[8] = { 0, };
1615 438 : DATA_BLOB blob = data_blob_const(p, sizeof(p));
1616 438 : uint32_t durable_v2_response_flags = 0;
1617 :
1618 438 : SIVAL(p, 0, state->op->global->durable_timeout_msec);
1619 438 : SIVAL(p, 4, durable_v2_response_flags);
1620 :
1621 438 : status = smb2_create_blob_add(state->out_context_blobs,
1622 : state->out_context_blobs,
1623 : SMB2_CREATE_TAG_DH2Q,
1624 : blob);
1625 438 : if (!NT_STATUS_IS_OK(status)) {
1626 0 : goto fail;
1627 : }
1628 : }
1629 :
1630 353997 : if (state->qfid != NULL) {
1631 0 : uint8_t p[32];
1632 76 : SMB_STRUCT_STAT *base_sp = state->result->base_fsp ?
1633 38 : &state->result->base_fsp->fsp_name->st :
1634 22 : &state->result->fsp_name->st;
1635 38 : uint64_t file_id = SMB_VFS_FS_FILE_ID(conn, base_sp);
1636 38 : DATA_BLOB blob = data_blob_const(p, sizeof(p));
1637 :
1638 38 : ZERO_STRUCT(p);
1639 :
1640 : /* From conversations with Microsoft engineers at
1641 : the MS plugfest. The first 8 bytes are the "volume index"
1642 : == inode, the second 8 bytes are the "volume id",
1643 : == dev. This will be updated in the SMB2 doc. */
1644 38 : SBVAL(p, 0, file_id);
1645 38 : SIVAL(p, 8, base_sp->st_ex_dev);/* FileIndexHigh */
1646 :
1647 38 : status = smb2_create_blob_add(state->out_context_blobs,
1648 : state->out_context_blobs,
1649 : SMB2_CREATE_TAG_QFID,
1650 : blob);
1651 38 : if (!NT_STATUS_IS_OK(status)) {
1652 0 : goto fail;
1653 : }
1654 : }
1655 :
1656 353997 : if ((state->rqls != NULL) && (state->result->oplock_type == LEASE_OPLOCK)) {
1657 0 : uint8_t buf[52];
1658 0 : struct smb2_lease lease;
1659 0 : size_t lease_len;
1660 :
1661 1010 : lease = state->result->lease->lease;
1662 :
1663 1010 : lease_len = sizeof(buf);
1664 1010 : if (lease.lease_version == 1) {
1665 878 : lease_len = 32;
1666 : }
1667 :
1668 1010 : if (!smb2_lease_push(&lease, buf, lease_len)) {
1669 0 : status = NT_STATUS_INTERNAL_ERROR;
1670 0 : goto fail;
1671 : }
1672 :
1673 1010 : status = smb2_create_blob_add(
1674 : state, state->out_context_blobs,
1675 : SMB2_CREATE_TAG_RQLS,
1676 : data_blob_const(buf, lease_len));
1677 1010 : if (!NT_STATUS_IS_OK(status)) {
1678 0 : goto fail;
1679 : }
1680 : }
1681 :
1682 353997 : if (state->posx != NULL) {
1683 2146 : struct stat_ex *psbuf = &state->result->fsp_name->st;
1684 4292 : struct smb3_posix_cc_info cc = {
1685 2146 : .nlinks = psbuf->st_ex_nlink,
1686 2146 : .posix_perms = unix_perms_to_wire(psbuf->st_ex_mode &
1687 : ~S_IFMT),
1688 : };
1689 0 : uint8_t buf[sizeof(struct smb3_posix_cc_info)];
1690 2146 : struct ndr_push ndr = {
1691 : .data = buf,
1692 : .alloc_size = sizeof(buf),
1693 : .fixed_buf_size = true,
1694 : };
1695 0 : enum ndr_err_code ndr_err;
1696 :
1697 2146 : uid_to_sid(&cc.owner, psbuf->st_ex_uid);
1698 2146 : gid_to_sid(&cc.group, psbuf->st_ex_gid);
1699 :
1700 2146 : (void)fsctl_get_reparse_tag(state->result, &cc.reparse_tag);
1701 :
1702 0 : ndr_err =
1703 2146 : ndr_push_smb3_posix_cc_info(&ndr,
1704 : NDR_SCALARS | NDR_BUFFERS,
1705 : &cc);
1706 2146 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1707 0 : status = NT_STATUS_INSUFFICIENT_RESOURCES;
1708 0 : goto fail;
1709 : }
1710 :
1711 2146 : status = smb2_create_blob_add(state->out_context_blobs,
1712 : state->out_context_blobs,
1713 : SMB2_CREATE_TAG_POSIX,
1714 2146 : (DATA_BLOB){
1715 : .data = buf,
1716 2146 : .length = ndr.offset,
1717 : });
1718 2146 : if (!NT_STATUS_IS_OK(status)) {
1719 0 : goto fail;
1720 : }
1721 : }
1722 :
1723 353997 : return;
1724 :
1725 0 : fail:
1726 0 : close_file_free(state->smb1req, &state->result, ERROR_CLOSE);
1727 0 : tevent_req_nterror(req, status);
1728 : }
1729 :
1730 371060 : static void smbd_smb2_create_finish(struct tevent_req *req)
1731 : {
1732 371060 : struct smbd_smb2_create_state *state = tevent_req_data(
1733 : req, struct smbd_smb2_create_state);
1734 371060 : struct smbd_smb2_request *smb2req = state->smb2req;
1735 371060 : struct smb_request *smb1req = state->smb1req;
1736 371060 : files_struct *result = state->result;
1737 :
1738 371060 : smb2req->compat_chain_fsp = smb1req->chain_fsp;
1739 :
1740 371060 : if (state->replay_operation) {
1741 66 : state->out_oplock_level = state->in_oplock_level;
1742 370994 : } else if (lp_fake_oplocks(SNUM(smb2req->tcon->compat))) {
1743 0 : state->out_oplock_level = state->in_oplock_level;
1744 : } else {
1745 371666 : state->out_oplock_level = map_samba_oplock_levels_to_smb2(result->oplock_type);
1746 : }
1747 :
1748 371060 : if ((state->in_create_disposition == FILE_SUPERSEDE)
1749 128 : && (state->info == FILE_WAS_OVERWRITTEN)) {
1750 21 : state->out_create_action = FILE_WAS_SUPERSEDED;
1751 : } else {
1752 371039 : state->out_create_action = state->info;
1753 : }
1754 371060 : result->op->create_action = state->out_create_action;
1755 :
1756 371060 : state->out_creation_ts = get_create_timespec(smb1req->conn,
1757 371060 : result, result->fsp_name);
1758 371060 : state->out_last_access_ts = result->fsp_name->st.st_ex_atime;
1759 371060 : state->out_last_write_ts = result->fsp_name->st.st_ex_mtime;
1760 371060 : state->out_change_ts = get_change_timespec(smb1req->conn,
1761 370267 : result, result->fsp_name);
1762 :
1763 371060 : if (lp_dos_filetime_resolution(SNUM(smb2req->tcon->compat))) {
1764 0 : dos_filetime_timespec(&state->out_creation_ts);
1765 0 : dos_filetime_timespec(&state->out_last_access_ts);
1766 0 : dos_filetime_timespec(&state->out_last_write_ts);
1767 0 : dos_filetime_timespec(&state->out_change_ts);
1768 : }
1769 :
1770 371853 : state->out_allocation_size =
1771 371060 : SMB_VFS_GET_ALLOC_SIZE(smb1req->conn, result,
1772 : &(result->fsp_name->st));
1773 371060 : state->out_end_of_file = result->fsp_name->st.st_ex_size;
1774 371060 : if (state->out_file_attributes == 0) {
1775 17063 : state->out_file_attributes = FILE_ATTRIBUTE_NORMAL;
1776 : }
1777 371060 : state->out_file_id_persistent = result->op->global->open_persistent_id;
1778 371060 : state->out_file_id_volatile = result->op->global->open_volatile_id;
1779 :
1780 371060 : DBG_DEBUG("%s - %s\n", fsp_str_dbg(result), fsp_fnum_dbg(result));
1781 :
1782 371060 : tevent_req_done(req);
1783 371060 : tevent_req_post(req, state->ev);
1784 371060 : }
1785 :
1786 481681 : static NTSTATUS smbd_smb2_create_recv(struct tevent_req *req,
1787 : TALLOC_CTX *mem_ctx,
1788 : uint8_t *out_oplock_level,
1789 : uint32_t *out_create_action,
1790 : struct timespec *out_creation_ts,
1791 : struct timespec *out_last_access_ts,
1792 : struct timespec *out_last_write_ts,
1793 : struct timespec *out_change_ts,
1794 : uint64_t *out_allocation_size,
1795 : uint64_t *out_end_of_file,
1796 : uint32_t *out_file_attributes,
1797 : uint64_t *out_file_id_persistent,
1798 : uint64_t *out_file_id_volatile,
1799 : struct smb2_create_blobs *out_context_blobs)
1800 : {
1801 955 : NTSTATUS status;
1802 481681 : struct smbd_smb2_create_state *state = tevent_req_data(req,
1803 : struct smbd_smb2_create_state);
1804 :
1805 481681 : if (tevent_req_is_nterror(req, &status)) {
1806 110621 : tevent_req_received(req);
1807 110621 : return status;
1808 : }
1809 :
1810 371060 : *out_oplock_level = state->out_oplock_level;
1811 371060 : *out_create_action = state->out_create_action;
1812 371060 : *out_creation_ts = state->out_creation_ts;
1813 371060 : *out_last_access_ts = state->out_last_access_ts;
1814 371060 : *out_last_write_ts = state->out_last_write_ts;
1815 371060 : *out_change_ts = state->out_change_ts;
1816 371060 : *out_allocation_size = state->out_allocation_size;
1817 371060 : *out_end_of_file = state->out_end_of_file;
1818 371060 : *out_file_attributes = state->out_file_attributes;
1819 371060 : *out_file_id_persistent = state->out_file_id_persistent;
1820 371060 : *out_file_id_volatile = state->out_file_id_volatile;
1821 371060 : *out_context_blobs = *(state->out_context_blobs);
1822 :
1823 371060 : talloc_steal(mem_ctx, state->out_context_blobs->blobs);
1824 :
1825 371060 : tevent_req_received(req);
1826 371060 : return NT_STATUS_OK;
1827 : }
1828 :
1829 : /*********************************************************
1830 : Code for dealing with deferred opens.
1831 : *********************************************************/
1832 :
1833 885007 : bool get_deferred_open_message_state_smb2(struct smbd_smb2_request *smb2req,
1834 : struct timeval *p_request_time,
1835 : struct deferred_open_record **open_rec)
1836 : {
1837 885007 : struct smbd_smb2_create_state *state = NULL;
1838 885007 : struct tevent_req *req = NULL;
1839 :
1840 885007 : if (!smb2req) {
1841 0 : return false;
1842 : }
1843 885007 : req = smb2req->subreq;
1844 885007 : if (!req) {
1845 0 : return false;
1846 : }
1847 885007 : state = tevent_req_data(req, struct smbd_smb2_create_state);
1848 885007 : if (!state) {
1849 0 : return false;
1850 : }
1851 885007 : if (!state->open_was_deferred) {
1852 883689 : return false;
1853 : }
1854 656 : if (p_request_time) {
1855 328 : *p_request_time = state->request_time;
1856 : }
1857 656 : if (open_rec != NULL) {
1858 328 : *open_rec = state->open_rec;
1859 : }
1860 656 : return true;
1861 : }
1862 :
1863 : /*********************************************************
1864 : Re-process this call early - requested by message or
1865 : close.
1866 : *********************************************************/
1867 :
1868 106012 : static struct smbd_smb2_request *find_open_smb2req(
1869 : struct smbXsrv_connection *xconn, uint64_t mid)
1870 : {
1871 162 : struct smbd_smb2_request *smb2req;
1872 :
1873 106090 : for (smb2req = xconn->smb2.requests; smb2req; smb2req = smb2req->next) {
1874 162 : uint64_t message_id;
1875 106090 : if (smb2req->subreq == NULL) {
1876 : /* This message has been processed. */
1877 0 : continue;
1878 : }
1879 106090 : if (!tevent_req_is_in_progress(smb2req->subreq)) {
1880 : /* This message has been processed. */
1881 0 : continue;
1882 : }
1883 106090 : message_id = get_mid_from_smb2req(smb2req);
1884 106090 : if (message_id == mid) {
1885 106012 : return smb2req;
1886 : }
1887 : }
1888 0 : return NULL;
1889 : }
1890 :
1891 105340 : bool open_was_deferred_smb2(struct smbXsrv_connection *xconn, uint64_t mid)
1892 : {
1893 105340 : struct smbd_smb2_create_state *state = NULL;
1894 162 : struct smbd_smb2_request *smb2req;
1895 :
1896 105340 : smb2req = find_open_smb2req(xconn, mid);
1897 :
1898 105340 : if (!smb2req) {
1899 0 : DEBUG(10,("open_was_deferred_smb2: mid %llu smb2req == NULL\n",
1900 : (unsigned long long)mid));
1901 0 : return false;
1902 : }
1903 105340 : if (!smb2req->subreq) {
1904 0 : return false;
1905 : }
1906 105340 : if (!tevent_req_is_in_progress(smb2req->subreq)) {
1907 0 : return false;
1908 : }
1909 105340 : state = tevent_req_data(smb2req->subreq,
1910 : struct smbd_smb2_create_state);
1911 105340 : if (!state) {
1912 0 : return false;
1913 : }
1914 : /* It's not in progress if there's no timeout event. */
1915 105340 : if (!state->open_was_deferred) {
1916 104782 : return false;
1917 : }
1918 :
1919 396 : DEBUG(10,("open_was_deferred_smb2: mid = %llu\n",
1920 : (unsigned long long)mid));
1921 :
1922 396 : return true;
1923 : }
1924 :
1925 332 : static void remove_deferred_open_message_smb2_internal(struct smbd_smb2_request *smb2req,
1926 : uint64_t mid)
1927 : {
1928 332 : struct smbd_smb2_create_state *state = NULL;
1929 :
1930 332 : if (!smb2req->subreq) {
1931 0 : return;
1932 : }
1933 332 : if (!tevent_req_is_in_progress(smb2req->subreq)) {
1934 0 : return;
1935 : }
1936 332 : state = tevent_req_data(smb2req->subreq,
1937 : struct smbd_smb2_create_state);
1938 332 : if (!state) {
1939 0 : return;
1940 : }
1941 :
1942 332 : DEBUG(10,("remove_deferred_open_message_smb2_internal: "
1943 : "mid %llu\n",
1944 : (unsigned long long)mid ));
1945 :
1946 332 : state->open_was_deferred = false;
1947 : /* Ensure we don't have any outstanding immediate event. */
1948 332 : TALLOC_FREE(state->im);
1949 332 : TALLOC_FREE(state->open_rec);
1950 : }
1951 :
1952 328 : void remove_deferred_open_message_smb2(
1953 : struct smbXsrv_connection *xconn, uint64_t mid)
1954 : {
1955 0 : struct smbd_smb2_request *smb2req;
1956 :
1957 328 : smb2req = find_open_smb2req(xconn, mid);
1958 :
1959 328 : if (!smb2req) {
1960 0 : DEBUG(10,("remove_deferred_open_message_smb2: "
1961 : "can't find mid %llu\n",
1962 : (unsigned long long)mid ));
1963 0 : return;
1964 : }
1965 328 : remove_deferred_open_message_smb2_internal(smb2req, mid);
1966 : }
1967 :
1968 344 : static void smbd_smb2_create_request_dispatch_immediate(struct tevent_context *ctx,
1969 : struct tevent_immediate *im,
1970 : void *private_data)
1971 : {
1972 344 : struct smbd_smb2_request *smb2req = talloc_get_type_abort(private_data,
1973 : struct smbd_smb2_request);
1974 344 : uint64_t mid = get_mid_from_smb2req(smb2req);
1975 0 : NTSTATUS status;
1976 :
1977 344 : DEBUG(10,("smbd_smb2_create_request_dispatch_immediate: "
1978 : "re-dispatching mid %llu\n",
1979 : (unsigned long long)mid ));
1980 :
1981 344 : status = smbd_smb2_request_dispatch(smb2req);
1982 344 : if (!NT_STATUS_IS_OK(status)) {
1983 0 : smbd_server_connection_terminate(smb2req->xconn,
1984 : nt_errstr(status));
1985 0 : return;
1986 : }
1987 : }
1988 :
1989 344 : bool schedule_deferred_open_message_smb2(
1990 : struct smbXsrv_connection *xconn, uint64_t mid)
1991 : {
1992 344 : struct smbd_smb2_create_state *state = NULL;
1993 0 : struct smbd_smb2_request *smb2req;
1994 :
1995 344 : smb2req = find_open_smb2req(xconn, mid);
1996 :
1997 344 : if (!smb2req) {
1998 0 : DEBUG(10,("schedule_deferred_open_message_smb2: "
1999 : "can't find mid %llu\n",
2000 : (unsigned long long)mid ));
2001 0 : return false;
2002 : }
2003 344 : if (!smb2req->subreq) {
2004 0 : return false;
2005 : }
2006 344 : if (!tevent_req_is_in_progress(smb2req->subreq)) {
2007 0 : return false;
2008 : }
2009 344 : state = tevent_req_data(smb2req->subreq,
2010 : struct smbd_smb2_create_state);
2011 344 : if (!state) {
2012 0 : return false;
2013 : }
2014 :
2015 : /* Ensure we don't have any outstanding immediate event. */
2016 344 : TALLOC_FREE(state->im);
2017 :
2018 : /*
2019 : * This is subtle. We must null out the callback
2020 : * before rescheduling, else the first call to
2021 : * tevent_req_nterror() causes the _receive()
2022 : * function to be called, this causing tevent_req_post()
2023 : * to crash.
2024 : */
2025 344 : tevent_req_set_callback(smb2req->subreq, NULL, NULL);
2026 :
2027 344 : state->im = tevent_create_immediate(smb2req);
2028 344 : if (!state->im) {
2029 0 : smbd_server_connection_terminate(smb2req->xconn,
2030 : nt_errstr(NT_STATUS_NO_MEMORY));
2031 0 : return false;
2032 : }
2033 :
2034 344 : DEBUG(10,("schedule_deferred_open_message_smb2: "
2035 : "re-processing mid %llu\n",
2036 : (unsigned long long)mid ));
2037 :
2038 344 : tevent_schedule_immediate(state->im,
2039 : smb2req->sconn->ev_ctx,
2040 : smbd_smb2_create_request_dispatch_immediate,
2041 0 : smb2req);
2042 :
2043 344 : return true;
2044 : }
2045 :
2046 4 : static bool smbd_smb2_create_cancel(struct tevent_req *req)
2047 : {
2048 4 : struct smbd_smb2_request *smb2req = NULL;
2049 4 : struct smbd_smb2_create_state *state = tevent_req_data(req,
2050 : struct smbd_smb2_create_state);
2051 0 : uint64_t mid;
2052 :
2053 4 : if (!state) {
2054 0 : return false;
2055 : }
2056 :
2057 4 : if (!state->smb2req) {
2058 0 : return false;
2059 : }
2060 :
2061 4 : smb2req = state->smb2req;
2062 4 : mid = get_mid_from_smb2req(smb2req);
2063 :
2064 4 : if (is_deferred_open_async(state->open_rec)) {
2065 : /* Can't cancel an async create. */
2066 0 : return false;
2067 : }
2068 :
2069 4 : remove_deferred_open_message_smb2_internal(smb2req, mid);
2070 :
2071 4 : tevent_req_defer_callback(req, smb2req->sconn->ev_ctx);
2072 4 : tevent_req_nterror(req, NT_STATUS_CANCELLED);
2073 4 : return true;
2074 : }
2075 :
2076 396 : bool push_deferred_open_message_smb2(struct smbd_smb2_request *smb2req,
2077 : struct timeval request_time,
2078 : struct timeval timeout,
2079 : struct file_id id,
2080 : struct deferred_open_record *open_rec)
2081 : {
2082 396 : struct tevent_req *req = NULL;
2083 396 : struct smbd_smb2_create_state *state = NULL;
2084 0 : struct timeval end_time;
2085 :
2086 396 : if (!smb2req) {
2087 0 : return false;
2088 : }
2089 396 : req = smb2req->subreq;
2090 396 : if (!req) {
2091 0 : return false;
2092 : }
2093 396 : state = tevent_req_data(req, struct smbd_smb2_create_state);
2094 396 : if (!state) {
2095 0 : return false;
2096 : }
2097 396 : state->id = id;
2098 396 : state->request_time = request_time;
2099 396 : state->open_rec = talloc_move(state, &open_rec);
2100 :
2101 : /* Re-schedule us to retry on timer expiry. */
2102 396 : end_time = timeval_sum(&request_time, &timeout);
2103 :
2104 396 : DEBUG(10,("push_deferred_open_message_smb2: "
2105 : "timeout at %s\n",
2106 : timeval_string(talloc_tos(),
2107 : &end_time,
2108 : true) ));
2109 :
2110 396 : state->open_was_deferred = true;
2111 :
2112 : /* allow this request to be canceled */
2113 396 : tevent_req_set_cancel_fn(req, smbd_smb2_create_cancel);
2114 :
2115 396 : return true;
2116 : }
|