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