2 Unix SMB/CIFS implementation.
5 Copyright (C) Stefan Metzmacher 2009
6 Copyright (C) Jeremy Allison 2010
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.
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.
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/>.
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
26 #include "../libcli/smb/smb_common.h"
27 #include "../librpc/gen_ndr/ndr_security.h"
28 #include "../librpc/gen_ndr/ndr_smb2_lease_struct.h"
29 #include "../lib/util/tevent_ntstatus.h"
33 #define DBGC_CLASS DBGC_SMB2
35 int map_smb2_oplock_levels_to_samba(uint8_t in_oplock_level)
37 switch(in_oplock_level) {
38 case SMB2_OPLOCK_LEVEL_NONE:
40 case SMB2_OPLOCK_LEVEL_II:
41 return LEVEL_II_OPLOCK;
42 case SMB2_OPLOCK_LEVEL_EXCLUSIVE:
43 return EXCLUSIVE_OPLOCK;
44 case SMB2_OPLOCK_LEVEL_BATCH:
46 case SMB2_OPLOCK_LEVEL_LEASE:
49 DEBUG(2,("map_smb2_oplock_levels_to_samba: "
51 (unsigned int)in_oplock_level));
56 static uint8_t map_samba_oplock_levels_to_smb2(int oplock_type)
58 if (BATCH_OPLOCK_TYPE(oplock_type)) {
59 return SMB2_OPLOCK_LEVEL_BATCH;
60 } else if (EXCLUSIVE_OPLOCK_TYPE(oplock_type)) {
61 return SMB2_OPLOCK_LEVEL_EXCLUSIVE;
62 } else if (oplock_type == LEVEL_II_OPLOCK) {
63 return SMB2_OPLOCK_LEVEL_II;
64 } else if (oplock_type == LEASE_OPLOCK) {
65 return SMB2_OPLOCK_LEVEL_LEASE;
67 return SMB2_OPLOCK_LEVEL_NONE;
72 MS-FSA 2.1.5.1 Server Requests an Open of a File
73 Trailing '/' or '\\' checker.
74 Must be done before the filename parser removes any
75 trailing characters. If we decide to add this to SMB1
76 NTCreate processing we can make this public.
78 Note this is Windows pathname processing only. When
79 POSIX pathnames are added to SMB2 this will not apply.
82 static NTSTATUS windows_name_trailing_check(const char *name,
83 uint32_t create_options)
85 size_t name_len = strlen(name);
92 trail_c = name[name_len-1];
95 * Trailing '/' is always invalid.
98 return NT_STATUS_OBJECT_NAME_INVALID;
101 if (create_options & FILE_NON_DIRECTORY_FILE) {
102 if (trail_c == '\\') {
103 return NT_STATUS_OBJECT_NAME_INVALID;
109 static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
110 struct tevent_context *ev,
111 struct smbd_smb2_request *smb2req,
112 uint8_t in_oplock_level,
113 uint32_t in_impersonation_level,
114 uint32_t in_desired_access,
115 uint32_t in_file_attributes,
116 uint32_t in_share_access,
117 uint32_t in_create_disposition,
118 uint32_t in_create_options,
120 struct smb2_create_blobs in_context_blobs);
121 static NTSTATUS smbd_smb2_create_recv(struct tevent_req *req,
123 uint8_t *out_oplock_level,
124 uint32_t *out_create_action,
125 struct timespec *out_creation_ts,
126 struct timespec *out_last_access_ts,
127 struct timespec *out_last_write_ts,
128 struct timespec *out_change_ts,
129 uint64_t *out_allocation_size,
130 uint64_t *out_end_of_file,
131 uint32_t *out_file_attributes,
132 uint64_t *out_file_id_persistent,
133 uint64_t *out_file_id_volatile,
134 struct smb2_create_blobs *out_context_blobs);
136 static void smbd_smb2_request_create_done(struct tevent_req *tsubreq);
137 NTSTATUS smbd_smb2_request_process_create(struct smbd_smb2_request *smb2req)
139 const uint8_t *inbody;
140 const struct iovec *indyniov;
141 uint8_t in_oplock_level;
142 uint32_t in_impersonation_level;
143 uint32_t in_desired_access;
144 uint32_t in_file_attributes;
145 uint32_t in_share_access;
146 uint32_t in_create_disposition;
147 uint32_t in_create_options;
148 uint16_t in_name_offset;
149 uint16_t in_name_length;
150 DATA_BLOB in_name_buffer;
151 char *in_name_string;
152 size_t in_name_string_size;
153 uint32_t name_offset = 0;
154 uint32_t name_available_length = 0;
155 uint32_t in_context_offset;
156 uint32_t in_context_length;
157 DATA_BLOB in_context_buffer;
158 struct smb2_create_blobs in_context_blobs;
159 uint32_t context_offset = 0;
160 uint32_t context_available_length = 0;
164 struct tevent_req *tsubreq;
166 status = smbd_smb2_request_verify_sizes(smb2req, 0x39);
167 if (!NT_STATUS_IS_OK(status)) {
168 return smbd_smb2_request_error(smb2req, status);
170 inbody = SMBD_SMB2_IN_BODY_PTR(smb2req);
172 in_oplock_level = CVAL(inbody, 0x03);
173 in_impersonation_level = IVAL(inbody, 0x04);
174 in_desired_access = IVAL(inbody, 0x18);
175 in_file_attributes = IVAL(inbody, 0x1C);
176 in_share_access = IVAL(inbody, 0x20);
177 in_create_disposition = IVAL(inbody, 0x24);
178 in_create_options = IVAL(inbody, 0x28);
179 in_name_offset = SVAL(inbody, 0x2C);
180 in_name_length = SVAL(inbody, 0x2E);
181 in_context_offset = IVAL(inbody, 0x30);
182 in_context_length = IVAL(inbody, 0x34);
185 * First check if the dynamic name and context buffers
186 * are correctly specified.
188 * Note: That we don't check if the name and context buffers
192 dyn_offset = SMB2_HDR_BODY + SMBD_SMB2_IN_BODY_LEN(smb2req);
194 if (in_name_offset == 0 && in_name_length == 0) {
197 } else if (in_name_offset < dyn_offset) {
198 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
200 name_offset = in_name_offset - dyn_offset;
203 indyniov = SMBD_SMB2_IN_DYN_IOV(smb2req);
205 if (name_offset > indyniov->iov_len) {
206 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
209 name_available_length = indyniov->iov_len - name_offset;
211 if (in_name_length > name_available_length) {
212 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
215 in_name_buffer.data = (uint8_t *)indyniov->iov_base + name_offset;
216 in_name_buffer.length = in_name_length;
218 if (in_context_offset == 0 && in_context_length == 0) {
221 } else if (in_context_offset < dyn_offset) {
222 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
224 context_offset = in_context_offset - dyn_offset;
227 if (context_offset > indyniov->iov_len) {
228 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
231 context_available_length = indyniov->iov_len - context_offset;
233 if (in_context_length > context_available_length) {
234 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
237 in_context_buffer.data = (uint8_t *)indyniov->iov_base +
239 in_context_buffer.length = in_context_length;
242 * Now interpret the name and context buffers
245 ok = convert_string_talloc(smb2req, CH_UTF16, CH_UNIX,
247 in_name_buffer.length,
249 &in_name_string_size);
251 return smbd_smb2_request_error(smb2req, NT_STATUS_ILLEGAL_CHARACTER);
254 if (in_name_buffer.length == 0) {
255 in_name_string_size = 0;
258 if (strlen(in_name_string) != in_name_string_size) {
259 return smbd_smb2_request_error(smb2req, NT_STATUS_OBJECT_NAME_INVALID);
262 ZERO_STRUCT(in_context_blobs);
263 status = smb2_create_blob_parse(smb2req, in_context_buffer, &in_context_blobs);
264 if (!NT_STATUS_IS_OK(status)) {
265 return smbd_smb2_request_error(smb2req, status);
268 tsubreq = smbd_smb2_create_send(smb2req,
269 smb2req->sconn->ev_ctx,
272 in_impersonation_level,
276 in_create_disposition,
280 if (tsubreq == NULL) {
281 smb2req->subreq = NULL;
282 return smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
284 tevent_req_set_callback(tsubreq, smbd_smb2_request_create_done, smb2req);
286 return smbd_smb2_request_pending_queue(smb2req, tsubreq, 500);
289 static uint64_t get_mid_from_smb2req(struct smbd_smb2_request *smb2req)
291 uint8_t *reqhdr = SMBD_SMB2_OUT_HDR_PTR(smb2req);
292 return BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
295 static void smbd_smb2_request_create_done(struct tevent_req *tsubreq)
297 struct smbd_smb2_request *smb2req = tevent_req_callback_data(tsubreq,
298 struct smbd_smb2_request);
301 uint8_t out_oplock_level = 0;
302 uint32_t out_create_action = 0;
303 connection_struct *conn = smb2req->tcon->compat;
304 struct timespec out_creation_ts = { 0, };
305 struct timespec out_last_access_ts = { 0, };
306 struct timespec out_last_write_ts = { 0, };
307 struct timespec out_change_ts = { 0, };
308 uint64_t out_allocation_size = 0;
309 uint64_t out_end_of_file = 0;
310 uint32_t out_file_attributes = 0;
311 uint64_t out_file_id_persistent = 0;
312 uint64_t out_file_id_volatile = 0;
313 struct smb2_create_blobs out_context_blobs;
314 DATA_BLOB out_context_buffer;
315 uint16_t out_context_buffer_offset = 0;
317 NTSTATUS error; /* transport error */
319 status = smbd_smb2_create_recv(tsubreq,
327 &out_allocation_size,
329 &out_file_attributes,
330 &out_file_id_persistent,
331 &out_file_id_volatile,
333 if (!NT_STATUS_IS_OK(status)) {
334 error = smbd_smb2_request_error(smb2req, status);
335 if (!NT_STATUS_IS_OK(error)) {
336 smbd_server_connection_terminate(smb2req->xconn,
343 status = smb2_create_blob_push(smb2req, &out_context_buffer, out_context_blobs);
344 if (!NT_STATUS_IS_OK(status)) {
345 error = smbd_smb2_request_error(smb2req, status);
346 if (!NT_STATUS_IS_OK(error)) {
347 smbd_server_connection_terminate(smb2req->xconn,
354 if (out_context_buffer.length > 0) {
355 out_context_buffer_offset = SMB2_HDR_BODY + 0x58;
358 outbody = smbd_smb2_generate_outbody(smb2req, 0x58);
359 if (outbody.data == NULL) {
360 error = smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
361 if (!NT_STATUS_IS_OK(error)) {
362 smbd_server_connection_terminate(smb2req->xconn,
369 SSVAL(outbody.data, 0x00, 0x58 + 1); /* struct size */
370 SCVAL(outbody.data, 0x02,
371 out_oplock_level); /* oplock level */
372 SCVAL(outbody.data, 0x03, 0); /* reserved */
373 SIVAL(outbody.data, 0x04,
374 out_create_action); /* create action */
375 put_long_date_full_timespec(conn->ts_res,
376 (char *)outbody.data + 0x08,
377 &out_creation_ts); /* creation time */
378 put_long_date_full_timespec(conn->ts_res,
379 (char *)outbody.data + 0x10,
380 &out_last_access_ts); /* last access time */
381 put_long_date_full_timespec(conn->ts_res,
382 (char *)outbody.data + 0x18,
383 &out_last_write_ts); /* last write time */
384 put_long_date_full_timespec(conn->ts_res,
385 (char *)outbody.data + 0x20,
386 &out_change_ts); /* change time */
387 SBVAL(outbody.data, 0x28,
388 out_allocation_size); /* allocation size */
389 SBVAL(outbody.data, 0x30,
390 out_end_of_file); /* end of file */
391 SIVAL(outbody.data, 0x38,
392 out_file_attributes); /* file attributes */
393 SIVAL(outbody.data, 0x3C, 0); /* reserved */
394 SBVAL(outbody.data, 0x40,
395 out_file_id_persistent); /* file id (persistent) */
396 SBVAL(outbody.data, 0x48,
397 out_file_id_volatile); /* file id (volatile) */
398 SIVAL(outbody.data, 0x50,
399 out_context_buffer_offset); /* create contexts offset */
400 SIVAL(outbody.data, 0x54,
401 out_context_buffer.length); /* create contexts length */
403 outdyn = out_context_buffer;
405 error = smbd_smb2_request_done(smb2req, outbody, &outdyn);
406 if (!NT_STATUS_IS_OK(error)) {
407 smbd_server_connection_terminate(smb2req->xconn,
413 static bool smb2_lease_key_valid(const struct smb2_lease_key *key)
415 return ((key->data[0] != 0) || (key->data[1] != 0));
418 static NTSTATUS smbd_smb2_create_durable_lease_check(struct smb_request *smb1req,
419 const char *requested_filename, const struct files_struct *fsp,
420 const struct smb2_lease *lease_ptr)
422 char *filename = NULL;
423 struct smb_filename *smb_fname = NULL;
427 if (lease_ptr == NULL) {
428 if (fsp->oplock_type != LEASE_OPLOCK) {
431 DEBUG(10, ("Reopened file has lease, but no lease "
433 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
436 if (fsp->oplock_type != LEASE_OPLOCK) {
437 DEBUG(10, ("Lease requested, but reopened file has no "
439 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
442 if (!smb2_lease_key_equal(&lease_ptr->lease_key,
443 &fsp->lease->lease.lease_key)) {
444 DEBUG(10, ("Different lease key requested than found "
445 "in reopened file\n"));
446 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
449 filename = talloc_strdup(talloc_tos(), requested_filename);
450 if (filename == NULL) {
451 return NT_STATUS_NO_MEMORY;
454 /* This also converts '\' to '/' */
455 status = check_path_syntax(filename);
456 if (!NT_STATUS_IS_OK(status)) {
457 TALLOC_FREE(filename);
461 ucf_flags = filename_create_ucf_flags(smb1req, FILE_OPEN);
462 status = filename_convert(talloc_tos(), fsp->conn,
464 0, NULL, &smb_fname);
465 TALLOC_FREE(filename);
466 if (!NT_STATUS_IS_OK(status)) {
467 DEBUG(10, ("filename_convert returned %s\n",
472 if (!strequal(fsp->fsp_name->base_name, smb_fname->base_name)) {
473 DEBUG(10, ("Lease requested for file %s, reopened file "
474 "is named %s\n", smb_fname->base_name,
475 fsp->fsp_name->base_name));
476 TALLOC_FREE(smb_fname);
477 return NT_STATUS_INVALID_PARAMETER;
480 TALLOC_FREE(smb_fname);
485 struct smbd_smb2_create_state {
486 struct tevent_context *ev;
487 struct smbd_smb2_request *smb2req;
488 struct smb_request *smb1req;
489 bool open_was_deferred;
490 struct tevent_immediate *im;
491 struct timeval request_time;
493 struct deferred_open_record *open_rec;
494 files_struct *result;
495 bool replay_operation;
496 uint8_t in_oplock_level;
497 uint32_t in_create_disposition;
498 int requested_oplock_level;
501 struct ea_list *ea_list;
502 NTTIME max_access_time;
503 struct security_descriptor *sec_desc;
504 uint64_t allocation_size;
505 struct GUID _create_guid;
506 struct GUID *create_guid;
508 bool durable_requested;
509 uint32_t durable_timeout_msec;
510 bool do_durable_reconnect;
511 uint64_t persistent_id;
512 struct smb2_lease lease;
513 struct smb2_lease *lease_ptr;
515 bool need_replay_cache;
516 struct smbXsrv_open *op;
519 struct smb2_create_blob *dhnc;
520 struct smb2_create_blob *dh2c;
521 struct smb2_create_blob *dhnq;
522 struct smb2_create_blob *dh2q;
523 struct smb2_create_blob *rqls;
524 struct smb2_create_blob *exta;
525 struct smb2_create_blob *mxac;
526 struct smb2_create_blob *secd;
527 struct smb2_create_blob *alsi;
528 struct smb2_create_blob *twrp;
529 struct smb2_create_blob *qfid;
530 struct smb2_create_blob *svhdx;
532 uint8_t out_oplock_level;
533 uint32_t out_create_action;
534 struct timespec out_creation_ts;
535 struct timespec out_last_access_ts;
536 struct timespec out_last_write_ts;
537 struct timespec out_change_ts;
538 uint64_t out_allocation_size;
539 uint64_t out_end_of_file;
540 uint32_t out_file_attributes;
541 uint64_t out_file_id_persistent;
542 uint64_t out_file_id_volatile;
543 struct smb2_create_blobs *out_context_blobs;
546 static NTSTATUS smbd_smb2_create_fetch_create_ctx(
547 struct tevent_req *req,
548 struct smb2_create_blobs *in_context_blobs)
550 struct smbd_smb2_create_state *state = tevent_req_data(
551 req, struct smbd_smb2_create_state);
554 * For now, remove the posix create context from the wire. We
555 * are using it inside smbd and will properly use it once
556 * smb3.11 unix extensions will be done. So in the future we
557 * will remove it only if unix extensions are not negotiated.
559 smb2_create_blob_remove(in_context_blobs, SMB2_CREATE_TAG_POSIX);
561 state->dhnq = smb2_create_blob_find(in_context_blobs,
562 SMB2_CREATE_TAG_DHNQ);
563 state->dhnc = smb2_create_blob_find(in_context_blobs,
564 SMB2_CREATE_TAG_DHNC);
565 state->dh2q = smb2_create_blob_find(in_context_blobs,
566 SMB2_CREATE_TAG_DH2Q);
567 state->dh2c = smb2_create_blob_find(in_context_blobs,
568 SMB2_CREATE_TAG_DH2C);
569 if (state->smb2req->xconn->smb2.server.capabilities & SMB2_CAP_LEASING) {
570 state->rqls = smb2_create_blob_find(in_context_blobs,
571 SMB2_CREATE_TAG_RQLS);
574 if (((state->dhnc != NULL) && (state->dh2c != NULL)) ||
575 ((state->dhnc != NULL) && (state->dh2q != NULL)) ||
576 ((state->dh2c != NULL) && (state->dhnq != NULL)) ||
577 ((state->dh2q != NULL) && (state->dh2c != NULL)))
579 /* not both are allowed at the same time */
580 return NT_STATUS_INVALID_PARAMETER;
583 if (state->dhnc != NULL) {
584 uint32_t num_blobs_allowed;
586 if (state->dhnc->data.length != 16) {
587 return NT_STATUS_INVALID_PARAMETER;
591 * According to MS-SMB2: 3.3.5.9.7, "Handling the
592 * SMB2_CREATE_DURABLE_HANDLE_RECONNECT Create Context",
593 * we should ignore an additional dhnq blob, but fail
594 * the request (with status OBJECT_NAME_NOT_FOUND) if
595 * any other extra create blob has been provided.
597 * (Note that the cases of an additional dh2q or dh2c blob
598 * which require a different error code, have been treated
602 if (state->dhnq != NULL) {
603 num_blobs_allowed = 2;
605 num_blobs_allowed = 1;
608 if (state->rqls != NULL) {
609 num_blobs_allowed += 1;
612 if (in_context_blobs->num_blobs != num_blobs_allowed) {
613 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
617 if (state->dh2c!= NULL) {
618 uint32_t num_blobs_allowed;
620 if (state->dh2c->data.length != 36) {
621 return NT_STATUS_INVALID_PARAMETER;
625 * According to MS-SMB2: 3.3.5.9.12, "Handling the
626 * SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 Create Context",
627 * we should fail the request with status
628 * OBJECT_NAME_NOT_FOUND if any other create blob has been
631 * (Note that the cases of an additional dhnq, dhnc or dh2q
632 * blob which require a different error code, have been
636 num_blobs_allowed = 1;
638 if (state->rqls != NULL) {
639 num_blobs_allowed += 1;
642 if (in_context_blobs->num_blobs != num_blobs_allowed) {
643 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
647 state->exta = smb2_create_blob_find(in_context_blobs,
648 SMB2_CREATE_TAG_EXTA);
649 state->mxac = smb2_create_blob_find(in_context_blobs,
650 SMB2_CREATE_TAG_MXAC);
651 state->secd = smb2_create_blob_find(in_context_blobs,
652 SMB2_CREATE_TAG_SECD);
653 state->alsi = smb2_create_blob_find(in_context_blobs,
654 SMB2_CREATE_TAG_ALSI);
655 state->twrp = smb2_create_blob_find(in_context_blobs,
656 SMB2_CREATE_TAG_TWRP);
657 state->qfid = smb2_create_blob_find(in_context_blobs,
658 SMB2_CREATE_TAG_QFID);
659 if (state->smb2req->xconn->protocol >= PROTOCOL_SMB3_02) {
661 * This was introduced with SMB3_02
663 state->svhdx = smb2_create_blob_find(
664 in_context_blobs, SVHDX_OPEN_DEVICE_CONTEXT);
670 static void smbd_smb2_create_before_exec(struct tevent_req *req);
671 static void smbd_smb2_create_after_exec(struct tevent_req *req);
672 static void smbd_smb2_create_finish(struct tevent_req *req);
674 static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
675 struct tevent_context *ev,
676 struct smbd_smb2_request *smb2req,
677 uint8_t in_oplock_level,
678 uint32_t in_impersonation_level,
679 uint32_t in_desired_access,
680 uint32_t in_file_attributes,
681 uint32_t in_share_access,
682 uint32_t in_create_disposition,
683 uint32_t in_create_options,
685 struct smb2_create_blobs in_context_blobs)
687 struct tevent_req *req = NULL;
688 struct smbd_smb2_create_state *state = NULL;
690 struct smb_request *smb1req = NULL;
691 struct smb_filename *smb_fname = NULL;
694 req = tevent_req_create(mem_ctx, &state,
695 struct smbd_smb2_create_state);
699 *state = (struct smbd_smb2_create_state) {
702 .in_oplock_level = in_oplock_level,
703 .in_create_disposition = in_create_disposition,
706 smb1req = smbd_smb2_fake_smb_request(smb2req);
707 if (tevent_req_nomem(smb1req, req)) {
708 return tevent_req_post(req, state->ev);
710 state->smb1req = smb1req;
712 if (smb2req->subreq == NULL) {
713 DBG_DEBUG("name [%s]\n", in_name);
715 struct smbd_smb2_create_state *old_state = tevent_req_data(
716 smb2req->subreq, struct smbd_smb2_create_state);
718 DBG_DEBUG("reentrant for file %s\n", in_name);
720 state->id = old_state->id;
721 state->request_time = old_state->request_time;
722 state->open_rec = talloc_move(state, &old_state->open_rec);
723 state->open_was_deferred = old_state->open_was_deferred;
726 TALLOC_FREE(smb2req->subreq);
727 smb2req->subreq = req;
729 if (lp_fake_oplocks(SNUM(smb2req->tcon->compat))) {
730 state->requested_oplock_level = SMB2_OPLOCK_LEVEL_NONE;
732 state->requested_oplock_level = state->in_oplock_level;
735 /* these are ignored for SMB2 */
736 in_create_options &= ~(0x10);/* NTCREATEX_OPTIONS_SYNC_ALERT */
737 in_create_options &= ~(0x20);/* NTCREATEX_OPTIONS_ASYNC_ALERT */
739 in_file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS;
741 state->fname = talloc_strdup(state, in_name);
742 if (tevent_req_nomem(state->fname, req)) {
743 return tevent_req_post(req, state->ev);
746 state->out_context_blobs = talloc_zero(state, struct smb2_create_blobs);
747 if (tevent_req_nomem(state->out_context_blobs, req)) {
748 return tevent_req_post(req, state->ev);
751 status = smbd_smb2_create_fetch_create_ctx(req, &in_context_blobs);
752 if (tevent_req_nterror(req, status)) {
753 return tevent_req_post(req, state->ev);
756 if (IS_IPC(smb1req->conn)) {
757 const char *pipe_name = in_name;
759 if (state->dhnc != NULL || state->dh2c != NULL) {
760 /* durable handles are not supported on IPC$ */
761 tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
762 return tevent_req_post(req, state->ev);
765 if (!lp_nt_pipe_support()) {
766 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
767 return tevent_req_post(req, state->ev);
770 status = open_np_file(smb1req, pipe_name, &state->result);
771 if (!NT_STATUS_IS_OK(status)) {
772 tevent_req_nterror(req, status);
773 return tevent_req_post(req, state->ev);
775 state->info = FILE_WAS_OPENED;
777 smbd_smb2_create_finish(req);
780 } else if (CAN_PRINT(smb1req->conn)) {
781 if (state->dhnc != NULL || state->dh2c != NULL) {
782 /* durable handles are not supported on printers */
783 tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
784 return tevent_req_post(req, state->ev);
787 status = file_new(smb1req, smb1req->conn, &state->result);
788 if(!NT_STATUS_IS_OK(status)) {
789 tevent_req_nterror(req, status);
790 return tevent_req_post(req, state->ev);
793 status = print_spool_open(state->result, in_name,
795 if (!NT_STATUS_IS_OK(status)) {
796 file_free(smb1req, state->result);
797 tevent_req_nterror(req, status);
798 return tevent_req_post(req, state->ev);
800 state->info = FILE_WAS_CREATED;
802 smbd_smb2_create_finish(req);
806 /* Check for trailing slash specific directory handling. */
807 status = windows_name_trailing_check(state->fname, in_create_options);
808 if (!NT_STATUS_IS_OK(status)) {
809 tevent_req_nterror(req, status);
810 return tevent_req_post(req, state->ev);
813 smbd_smb2_create_before_exec(req);
814 if (!tevent_req_is_in_progress(req)) {
815 return tevent_req_post(req, state->ev);
818 DBG_DEBUG("open execution phase\n");
821 * For the backend file open procedure, there are
822 * three possible modes: replay operation (in which case
823 * there is nothing else to do), durable_reconnect or
826 if (state->replay_operation) {
827 state->result = state->op->compat;
828 state->result->op = state->op;
829 state->update_open = false;
830 state->info = state->op->create_action;
832 smbd_smb2_create_after_exec(req);
833 if (!tevent_req_is_in_progress(req)) {
837 smbd_smb2_create_finish(req);
840 } else if (state->do_durable_reconnect) {
841 DATA_BLOB new_cookie = data_blob_null;
842 NTTIME now = timeval_to_nttime(&smb2req->request_time);
844 status = smb2srv_open_recreate(smb2req->xconn,
845 smb1req->conn->session_info,
846 state->persistent_id,
850 if (!NT_STATUS_IS_OK(status)) {
851 DBG_NOTICE("smb2srv_open_recreate failed: %s\n",
853 tevent_req_nterror(req, status);
854 return tevent_req_post(req, state->ev);
857 DBG_DEBUG("%s to recreate durable handle\n",
858 state->op->global->durable ? "succeeded" : "failed");
860 if (!state->op->global->durable) {
861 talloc_free(state->op);
862 tevent_req_nterror(req,
863 NT_STATUS_OBJECT_NAME_NOT_FOUND);
864 return tevent_req_post(req, state->ev);
867 status = SMB_VFS_DURABLE_RECONNECT(smb1req->conn,
869 state->op, /* smbXsrv_open input */
870 state->op->global->backend_cookie,
871 state->op, /* TALLOC_CTX */
874 if (!NT_STATUS_IS_OK(status)) {
875 NTSTATUS return_status;
877 return_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
879 DBG_NOTICE("durable_reconnect failed: %s => %s\n",
881 nt_errstr(return_status));
883 tevent_req_nterror(req, return_status);
884 return tevent_req_post(req, state->ev);
887 DBG_DEBUG("oplock_type=%u, lease_ptr==%p\n",
888 (unsigned)state->result->oplock_type, state->lease_ptr);
890 status = smbd_smb2_create_durable_lease_check(
891 smb1req, state->fname, state->result, state->lease_ptr);
892 if (!NT_STATUS_IS_OK(status)) {
893 close_file(smb1req, state->result, SHUTDOWN_CLOSE);
894 tevent_req_nterror(req, status);
895 return tevent_req_post(req, state->ev);
898 data_blob_free(&state->op->global->backend_cookie);
899 state->op->global->backend_cookie = new_cookie;
901 state->op->status = NT_STATUS_OK;
902 state->op->global->disconnect_time = 0;
904 /* save the timout for later update */
905 state->durable_timeout_msec = state->op->global->durable_timeout_msec;
907 state->update_open = true;
909 state->info = FILE_WAS_OPENED;
911 smbd_smb2_create_after_exec(req);
912 if (!tevent_req_is_in_progress(req)) {
916 smbd_smb2_create_finish(req);
920 if (state->requested_oplock_level == SMB2_OPLOCK_LEVEL_LEASE) {
921 if (state->lease_ptr == NULL) {
922 state->requested_oplock_level = SMB2_OPLOCK_LEVEL_NONE;
925 state->lease_ptr = NULL;
929 * For a DFS path the function parse_dfs_path()
930 * will do the path processing.
933 if (!(smb1req->flags2 & FLAGS2_DFS_PATHNAMES)) {
934 /* convert '\\' into '/' */
935 status = check_path_syntax(state->fname);
936 if (!NT_STATUS_IS_OK(status)) {
937 tevent_req_nterror(req, status);
938 return tevent_req_post(req, state->ev);
942 ucf_flags = filename_create_ucf_flags(
943 smb1req, state->in_create_disposition);
944 status = filename_convert(req,
949 NULL, /* ppath_contains_wcards */
951 if (!NT_STATUS_IS_OK(status)) {
952 tevent_req_nterror(req, status);
953 return tevent_req_post(req, state->ev);
957 * MS-SMB2: 2.2.13 SMB2 CREATE Request
958 * ImpersonationLevel ... MUST contain one of the
959 * following values. The server MUST validate this
960 * field, but otherwise ignore it.
962 * NB. The source4/torture/smb2/durable_open.c test
963 * shows this check is only done on real opens, not
964 * on durable handle-reopens.
967 if (in_impersonation_level >
968 SMB2_IMPERSONATION_DELEGATE) {
969 tevent_req_nterror(req,
970 NT_STATUS_BAD_IMPERSONATION_LEVEL);
971 return tevent_req_post(req, state->ev);
975 * We know we're going to do a local open, so now
976 * we must be protocol strict. JRA.
978 * MS-SMB2: 3.3.5.9 - Receiving an SMB2 CREATE Request
979 * If the file name length is greater than zero and the
980 * first character is a path separator character, the
981 * server MUST fail the request with
982 * STATUS_INVALID_PARAMETER.
984 if (in_name[0] == '\\' || in_name[0] == '/') {
985 tevent_req_nterror(req,
986 NT_STATUS_INVALID_PARAMETER);
987 return tevent_req_post(req, state->ev);
990 status = SMB_VFS_CREATE_FILE(smb1req->conn,
992 &smb1req->conn->cwd_fsp,
996 state->in_create_disposition,
999 map_smb2_oplock_levels_to_samba(
1000 state->requested_oplock_level),
1002 state->allocation_size,
1003 0, /* private_flags */
1009 state->out_context_blobs);
1010 if (!NT_STATUS_IS_OK(status)) {
1011 if (open_was_deferred(smb1req->xconn, smb1req->mid)) {
1012 SMBPROFILE_IOBYTES_ASYNC_SET_IDLE(smb2req->profile);
1015 tevent_req_nterror(req, status);
1016 return tevent_req_post(req, state->ev);
1018 state->op = state->result->op;
1020 smbd_smb2_create_after_exec(req);
1021 if (!tevent_req_is_in_progress(req)) {
1025 smbd_smb2_create_finish(req);
1029 static void smbd_smb2_create_before_exec(struct tevent_req *req)
1031 struct smbd_smb2_create_state *state = tevent_req_data(
1032 req, struct smbd_smb2_create_state);
1033 struct smbd_smb2_request *smb2req = state->smb2req;
1036 if (state->exta != NULL) {
1037 if (!lp_ea_support(SNUM(smb2req->tcon->compat))) {
1038 tevent_req_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1042 state->ea_list = read_nttrans_ea_list(
1044 (const char *)state->exta->data.data,
1045 state->exta->data.length);
1046 if (state->ea_list == NULL) {
1047 DEBUG(10,("smbd_smb2_create_send: read_ea_name_list failed.\n"));
1048 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1053 * NB. When SMB2+ unix extensions are added,
1054 * we need to relax this check in invalid
1055 * names - we used to not do this if
1056 * lp_posix_pathnames() was false.
1058 if (ea_list_has_invalid_name(state->ea_list)) {
1059 tevent_req_nterror(req, STATUS_INVALID_EA_NAME);
1064 if (state->mxac != NULL) {
1065 if (state->mxac->data.length == 0) {
1066 state->max_access_time = 0;
1067 } else if (state->mxac->data.length == 8) {
1068 state->max_access_time = BVAL(state->mxac->data.data, 0);
1070 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1075 if (state->secd != NULL) {
1076 enum ndr_err_code ndr_err;
1078 state->sec_desc = talloc_zero(state, struct security_descriptor);
1079 if (tevent_req_nomem(state->sec_desc, req)) {
1083 ndr_err = ndr_pull_struct_blob(&state->secd->data,
1084 state->sec_desc, state->sec_desc,
1085 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
1086 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1087 DEBUG(2,("ndr_pull_security_descriptor failed: %s\n",
1088 ndr_errstr(ndr_err)));
1089 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1094 if (state->dhnq != NULL) {
1095 if (state->dhnq->data.length != 16) {
1096 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1100 if (state->dh2q != NULL) {
1101 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1106 * durable handle request is processed below.
1108 state->durable_requested = true;
1110 * Set the timeout to 16 mins.
1112 * TODO: test this against Windows 2012
1113 * as the default for durable v2 is 1 min.
1115 state->durable_timeout_msec = (16*60*1000);
1118 if (state->dh2q != NULL) {
1119 const uint8_t *p = state->dh2q->data.data;
1120 uint32_t durable_v2_timeout = 0;
1121 DATA_BLOB create_guid_blob;
1125 if (state->dh2q->data.length != 32) {
1126 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1130 if (state->dhnq != NULL) {
1131 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1135 durable_v2_timeout = IVAL(p, 0);
1136 create_guid_blob = data_blob_const(p + 16, 16);
1138 status = GUID_from_ndr_blob(&create_guid_blob,
1139 &state->_create_guid);
1140 if (tevent_req_nterror(req, status)) {
1143 state->create_guid = &state->_create_guid;
1146 * we need to store the create_guid later
1148 state->update_open = true;
1151 * And we need to create a cache for replaying the
1154 state->need_replay_cache = true;
1157 * durable handle v2 request processed below
1159 state->durable_requested = true;
1160 state->durable_timeout_msec = durable_v2_timeout;
1161 if (state->durable_timeout_msec == 0) {
1163 * Set the timeout to 1 min as default.
1165 * This matches Windows 2012.
1167 state->durable_timeout_msec = (60*1000);
1171 * Check for replay operation.
1172 * Only consider it when we have dh2q.
1173 * If we do not have a replay operation, verify that
1174 * the create_guid is not cached for replay.
1176 hdr = SMBD_SMB2_IN_HDR_PTR(smb2req);
1177 flags = IVAL(hdr, SMB2_HDR_FLAGS);
1178 state->replay_operation =
1179 flags & SMB2_HDR_FLAG_REPLAY_OPERATION;
1181 status = smb2srv_open_lookup_replay_cache(smb2req->xconn,
1185 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
1186 state->replay_operation = false;
1187 } else if (tevent_req_nterror(req, status)) {
1188 DBG_WARNING("smb2srv_open_lookup_replay_cache "
1189 "failed: %s\n", nt_errstr(status));
1191 } else if (!state->replay_operation) {
1193 * If a create without replay operation flag
1194 * is sent but with a create_guid that is
1195 * currently in the replay cache -- fail.
1197 status = NT_STATUS_DUPLICATE_OBJECTID;
1198 (void)tevent_req_nterror(req, status);
1203 if (state->dhnc != NULL) {
1204 state->persistent_id = BVAL(state->dhnc->data.data, 0);
1205 state->do_durable_reconnect = true;
1208 if (state->dh2c != NULL) {
1209 const uint8_t *p = state->dh2c->data.data;
1210 DATA_BLOB create_guid_blob;
1212 state->persistent_id = BVAL(p, 0);
1213 create_guid_blob = data_blob_const(p + 16, 16);
1215 status = GUID_from_ndr_blob(&create_guid_blob,
1216 &state->_create_guid);
1217 if (tevent_req_nterror(req, status)) {
1221 state->create_guid = &state->_create_guid;
1222 state->do_durable_reconnect = true;
1225 if (state->alsi != NULL) {
1226 if (state->alsi->data.length != 8) {
1227 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1230 state->allocation_size = BVAL(state->alsi->data.data, 0);
1233 if (state->twrp != NULL) {
1234 if (state->twrp->data.length != 8) {
1235 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1239 state->twrp_time = BVAL(state->twrp->data.data, 0);
1242 if (state->qfid != NULL) {
1243 if (state->qfid->data.length != 0) {
1244 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1249 if (state->rqls != NULL) {
1250 ssize_t lease_len = -1;
1252 lease_len = smb2_lease_pull(state->rqls->data.data,
1253 state->rqls->data.length,
1255 if (lease_len == -1) {
1257 req, NT_STATUS_INVALID_PARAMETER);
1260 state->lease_ptr = &state->lease;
1262 if (DEBUGLEVEL >= 10) {
1263 DEBUG(10, ("Got lease request size %d\n",
1265 NDR_PRINT_DEBUG(smb2_lease, state->lease_ptr);
1268 if (!smb2_lease_key_valid(&state->lease.lease_key)) {
1269 state->lease_ptr = NULL;
1270 state->requested_oplock_level = SMB2_OPLOCK_LEVEL_NONE;
1273 if ((smb2req->xconn->protocol < PROTOCOL_SMB3_00) &&
1274 (state->lease.lease_version != 1))
1276 DEBUG(10, ("v2 lease key only for SMB3\n"));
1277 state->lease_ptr = NULL;
1281 * Replay with a lease is only allowed if the
1282 * established open carries a lease with the
1285 if (state->replay_operation) {
1286 struct smb2_lease *op_ls =
1287 &state->op->compat->lease->lease;
1288 int op_oplock = state->op->compat->oplock_type;
1290 if (map_samba_oplock_levels_to_smb2(op_oplock)
1291 != SMB2_OPLOCK_LEVEL_LEASE)
1293 status = NT_STATUS_ACCESS_DENIED;
1294 (void)tevent_req_nterror(req, status);
1297 if (!smb2_lease_key_equal(&state->lease.lease_key,
1300 status = NT_STATUS_ACCESS_DENIED;
1301 (void)tevent_req_nterror(req, status);
1308 static void smbd_smb2_create_after_exec(struct tevent_req *req)
1310 struct smbd_smb2_create_state *state = tevent_req_data(
1311 req, struct smbd_smb2_create_state);
1312 struct smb_request *smb1req = state->smb1req;
1316 * here we have op == result->op
1319 DEBUG(10, ("smbd_smb2_create_send: "
1320 "response construction phase\n"));
1322 state->out_file_attributes = dos_mode(state->result->conn,
1323 state->result->fsp_name);
1325 if (state->mxac != NULL) {
1326 NTTIME last_write_time;
1328 last_write_time = full_timespec_to_nt_time(
1329 &state->result->fsp_name->st.st_ex_mtime);
1330 if (last_write_time != state->max_access_time) {
1332 uint32_t max_access_granted;
1333 DATA_BLOB blob = data_blob_const(p, sizeof(p));
1335 status = smbd_calculate_access_mask(smb1req->conn,
1336 smb1req->conn->cwd_fsp,
1337 state->result->fsp_name,
1339 SEC_FLAG_MAXIMUM_ALLOWED,
1340 &max_access_granted);
1342 SIVAL(p, 0, NT_STATUS_V(status));
1343 SIVAL(p, 4, max_access_granted);
1345 status = smb2_create_blob_add(
1346 state->out_context_blobs,
1347 state->out_context_blobs,
1348 SMB2_CREATE_TAG_MXAC,
1350 if (!NT_STATUS_IS_OK(status)) {
1351 tevent_req_nterror(req, status);
1352 tevent_req_post(req, state->ev);
1358 if (!state->replay_operation && state->durable_requested &&
1359 (fsp_lease_type(state->result) & SMB2_LEASE_HANDLE))
1361 status = SMB_VFS_DURABLE_COOKIE(
1364 &state->op->global->backend_cookie);
1365 if (!NT_STATUS_IS_OK(status)) {
1366 state->op->global->backend_cookie = data_blob_null;
1369 if (!state->replay_operation && state->op->global->backend_cookie.length > 0)
1371 state->update_open = true;
1373 state->op->global->durable = true;
1374 state->op->global->durable_timeout_msec = state->durable_timeout_msec;
1377 if (state->update_open) {
1378 state->op->global->create_guid = state->_create_guid;
1379 if (state->need_replay_cache) {
1380 state->op->flags |= SMBXSRV_OPEN_NEED_REPLAY_CACHE;
1383 status = smbXsrv_open_update(state->op);
1384 DEBUG(10, ("smb2_create_send: smbXsrv_open_update "
1386 nt_errstr(status)));
1387 if (!NT_STATUS_IS_OK(status)) {
1388 tevent_req_nterror(req, status);
1389 tevent_req_post(req, state->ev);
1394 if (state->dhnq != NULL && state->op->global->durable) {
1395 uint8_t p[8] = { 0, };
1396 DATA_BLOB blob = data_blob_const(p, sizeof(p));
1398 status = smb2_create_blob_add(state->out_context_blobs,
1399 state->out_context_blobs,
1400 SMB2_CREATE_TAG_DHNQ,
1402 if (!NT_STATUS_IS_OK(status)) {
1403 tevent_req_nterror(req, status);
1404 tevent_req_post(req, state->ev);
1409 if (state->dh2q != NULL && state->op->global->durable &&
1411 * For replay operations, we return the dh2q blob
1412 * in the case of oplocks not based on the state of
1413 * the open, but on whether it could have been granted
1414 * for the request data. In the case of leases instead,
1415 * the state of the open is used...
1417 (!state->replay_operation ||
1418 state->in_oplock_level == SMB2_OPLOCK_LEVEL_BATCH ||
1419 state->in_oplock_level == SMB2_OPLOCK_LEVEL_LEASE))
1421 uint8_t p[8] = { 0, };
1422 DATA_BLOB blob = data_blob_const(p, sizeof(p));
1423 uint32_t durable_v2_response_flags = 0;
1425 SIVAL(p, 0, state->op->global->durable_timeout_msec);
1426 SIVAL(p, 4, durable_v2_response_flags);
1428 status = smb2_create_blob_add(state->out_context_blobs,
1429 state->out_context_blobs,
1430 SMB2_CREATE_TAG_DH2Q,
1432 if (!NT_STATUS_IS_OK(status)) {
1433 tevent_req_nterror(req, status);
1434 tevent_req_post(req, state->ev);
1439 if (state->qfid != NULL) {
1441 uint64_t file_id = SMB_VFS_FS_FILE_ID(
1442 state->result->conn,
1443 &state->result->fsp_name->st);
1444 DATA_BLOB blob = data_blob_const(p, sizeof(p));
1448 /* From conversations with Microsoft engineers at
1449 the MS plugfest. The first 8 bytes are the "volume index"
1450 == inode, the second 8 bytes are the "volume id",
1451 == dev. This will be updated in the SMB2 doc. */
1452 SBVAL(p, 0, file_id);
1453 SIVAL(p, 8, state->result->fsp_name->st.st_ex_dev);/* FileIndexHigh */
1455 status = smb2_create_blob_add(state->out_context_blobs,
1456 state->out_context_blobs,
1457 SMB2_CREATE_TAG_QFID,
1459 if (!NT_STATUS_IS_OK(status)) {
1460 tevent_req_nterror(req, status);
1461 tevent_req_post(req, state->ev);
1466 if ((state->rqls != NULL) && (state->result->oplock_type == LEASE_OPLOCK)) {
1468 struct smb2_lease lease;
1471 lease = state->result->lease->lease;
1473 lease_len = sizeof(buf);
1474 if (lease.lease_version == 1) {
1478 if (!smb2_lease_push(&lease, buf, lease_len)) {
1480 req, NT_STATUS_INTERNAL_ERROR);
1481 tevent_req_post(req, state->ev);
1485 status = smb2_create_blob_add(
1486 state, state->out_context_blobs,
1487 SMB2_CREATE_TAG_RQLS,
1488 data_blob_const(buf, lease_len));
1489 if (!NT_STATUS_IS_OK(status)) {
1490 tevent_req_nterror(req, status);
1491 tevent_req_post(req, state->ev);
1499 static void smbd_smb2_create_finish(struct tevent_req *req)
1501 struct smbd_smb2_create_state *state = tevent_req_data(
1502 req, struct smbd_smb2_create_state);
1503 struct smbd_smb2_request *smb2req = state->smb2req;
1504 struct smb_request *smb1req = state->smb1req;
1505 files_struct *result = state->result;
1507 smb2req->compat_chain_fsp = smb1req->chain_fsp;
1509 if (state->replay_operation) {
1510 state->out_oplock_level = state->in_oplock_level;
1511 } else if (lp_fake_oplocks(SNUM(smb2req->tcon->compat))) {
1512 state->out_oplock_level = state->in_oplock_level;
1514 state->out_oplock_level = map_samba_oplock_levels_to_smb2(result->oplock_type);
1517 if ((state->in_create_disposition == FILE_SUPERSEDE)
1518 && (state->info == FILE_WAS_OVERWRITTEN)) {
1519 state->out_create_action = FILE_WAS_SUPERSEDED;
1521 state->out_create_action = state->info;
1523 result->op->create_action = state->out_create_action;
1525 state->out_creation_ts = get_create_timespec(smb1req->conn,
1526 result, result->fsp_name);
1527 state->out_last_access_ts = result->fsp_name->st.st_ex_atime;
1528 state->out_last_write_ts = result->fsp_name->st.st_ex_mtime;
1529 state->out_change_ts = get_change_timespec(smb1req->conn,
1530 result, result->fsp_name);
1532 if (lp_dos_filetime_resolution(SNUM(smb2req->tcon->compat))) {
1533 dos_filetime_timespec(&state->out_creation_ts);
1534 dos_filetime_timespec(&state->out_last_access_ts);
1535 dos_filetime_timespec(&state->out_last_write_ts);
1536 dos_filetime_timespec(&state->out_change_ts);
1539 state->out_allocation_size =
1540 SMB_VFS_GET_ALLOC_SIZE(smb1req->conn, result,
1541 &(result->fsp_name->st));
1542 state->out_end_of_file = result->fsp_name->st.st_ex_size;
1543 if (state->out_file_attributes == 0) {
1544 state->out_file_attributes = FILE_ATTRIBUTE_NORMAL;
1546 state->out_file_id_persistent = result->op->global->open_persistent_id;
1547 state->out_file_id_volatile = result->op->global->open_volatile_id;
1549 DBG_DEBUG("%s - %s\n", fsp_str_dbg(result), fsp_fnum_dbg(result));
1551 tevent_req_done(req);
1552 tevent_req_post(req, state->ev);
1555 static NTSTATUS smbd_smb2_create_recv(struct tevent_req *req,
1556 TALLOC_CTX *mem_ctx,
1557 uint8_t *out_oplock_level,
1558 uint32_t *out_create_action,
1559 struct timespec *out_creation_ts,
1560 struct timespec *out_last_access_ts,
1561 struct timespec *out_last_write_ts,
1562 struct timespec *out_change_ts,
1563 uint64_t *out_allocation_size,
1564 uint64_t *out_end_of_file,
1565 uint32_t *out_file_attributes,
1566 uint64_t *out_file_id_persistent,
1567 uint64_t *out_file_id_volatile,
1568 struct smb2_create_blobs *out_context_blobs)
1571 struct smbd_smb2_create_state *state = tevent_req_data(req,
1572 struct smbd_smb2_create_state);
1574 if (tevent_req_is_nterror(req, &status)) {
1575 tevent_req_received(req);
1579 *out_oplock_level = state->out_oplock_level;
1580 *out_create_action = state->out_create_action;
1581 *out_creation_ts = state->out_creation_ts;
1582 *out_last_access_ts = state->out_last_access_ts;
1583 *out_last_write_ts = state->out_last_write_ts;
1584 *out_change_ts = state->out_change_ts;
1585 *out_allocation_size = state->out_allocation_size;
1586 *out_end_of_file = state->out_end_of_file;
1587 *out_file_attributes = state->out_file_attributes;
1588 *out_file_id_persistent = state->out_file_id_persistent;
1589 *out_file_id_volatile = state->out_file_id_volatile;
1590 *out_context_blobs = *(state->out_context_blobs);
1592 talloc_steal(mem_ctx, state->out_context_blobs->blobs);
1594 tevent_req_received(req);
1595 return NT_STATUS_OK;
1598 /*********************************************************
1599 Code for dealing with deferred opens.
1600 *********************************************************/
1602 bool get_deferred_open_message_state_smb2(struct smbd_smb2_request *smb2req,
1603 struct timeval *p_request_time,
1604 struct deferred_open_record **open_rec)
1606 struct smbd_smb2_create_state *state = NULL;
1607 struct tevent_req *req = NULL;
1612 req = smb2req->subreq;
1616 state = tevent_req_data(req, struct smbd_smb2_create_state);
1620 if (!state->open_was_deferred) {
1623 if (p_request_time) {
1624 *p_request_time = state->request_time;
1626 if (open_rec != NULL) {
1627 *open_rec = state->open_rec;
1632 /*********************************************************
1633 Re-process this call early - requested by message or
1635 *********************************************************/
1637 static struct smbd_smb2_request *find_open_smb2req(
1638 struct smbXsrv_connection *xconn, uint64_t mid)
1640 struct smbd_smb2_request *smb2req;
1642 for (smb2req = xconn->smb2.requests; smb2req; smb2req = smb2req->next) {
1643 uint64_t message_id;
1644 if (smb2req->subreq == NULL) {
1645 /* This message has been processed. */
1648 if (!tevent_req_is_in_progress(smb2req->subreq)) {
1649 /* This message has been processed. */
1652 message_id = get_mid_from_smb2req(smb2req);
1653 if (message_id == mid) {
1660 bool open_was_deferred_smb2(struct smbXsrv_connection *xconn, uint64_t mid)
1662 struct smbd_smb2_create_state *state = NULL;
1663 struct smbd_smb2_request *smb2req;
1665 smb2req = find_open_smb2req(xconn, mid);
1668 DEBUG(10,("open_was_deferred_smb2: mid %llu smb2req == NULL\n",
1669 (unsigned long long)mid));
1672 if (!smb2req->subreq) {
1675 if (!tevent_req_is_in_progress(smb2req->subreq)) {
1678 state = tevent_req_data(smb2req->subreq,
1679 struct smbd_smb2_create_state);
1683 /* It's not in progress if there's no timeout event. */
1684 if (!state->open_was_deferred) {
1688 DEBUG(10,("open_was_deferred_smb2: mid = %llu\n",
1689 (unsigned long long)mid));
1694 static void remove_deferred_open_message_smb2_internal(struct smbd_smb2_request *smb2req,
1697 struct smbd_smb2_create_state *state = NULL;
1699 if (!smb2req->subreq) {
1702 if (!tevent_req_is_in_progress(smb2req->subreq)) {
1705 state = tevent_req_data(smb2req->subreq,
1706 struct smbd_smb2_create_state);
1711 DEBUG(10,("remove_deferred_open_message_smb2_internal: "
1713 (unsigned long long)mid ));
1715 state->open_was_deferred = false;
1716 /* Ensure we don't have any outstanding immediate event. */
1717 TALLOC_FREE(state->im);
1720 void remove_deferred_open_message_smb2(
1721 struct smbXsrv_connection *xconn, uint64_t mid)
1723 struct smbd_smb2_request *smb2req;
1725 smb2req = find_open_smb2req(xconn, mid);
1728 DEBUG(10,("remove_deferred_open_message_smb2: "
1729 "can't find mid %llu\n",
1730 (unsigned long long)mid ));
1733 remove_deferred_open_message_smb2_internal(smb2req, mid);
1736 static void smbd_smb2_create_request_dispatch_immediate(struct tevent_context *ctx,
1737 struct tevent_immediate *im,
1740 struct smbd_smb2_request *smb2req = talloc_get_type_abort(private_data,
1741 struct smbd_smb2_request);
1742 uint64_t mid = get_mid_from_smb2req(smb2req);
1745 DEBUG(10,("smbd_smb2_create_request_dispatch_immediate: "
1746 "re-dispatching mid %llu\n",
1747 (unsigned long long)mid ));
1749 status = smbd_smb2_request_dispatch(smb2req);
1750 if (!NT_STATUS_IS_OK(status)) {
1751 smbd_server_connection_terminate(smb2req->xconn,
1757 bool schedule_deferred_open_message_smb2(
1758 struct smbXsrv_connection *xconn, uint64_t mid)
1760 struct smbd_smb2_create_state *state = NULL;
1761 struct smbd_smb2_request *smb2req;
1763 smb2req = find_open_smb2req(xconn, mid);
1766 DEBUG(10,("schedule_deferred_open_message_smb2: "
1767 "can't find mid %llu\n",
1768 (unsigned long long)mid ));
1771 if (!smb2req->subreq) {
1774 if (!tevent_req_is_in_progress(smb2req->subreq)) {
1777 state = tevent_req_data(smb2req->subreq,
1778 struct smbd_smb2_create_state);
1783 /* Ensure we don't have any outstanding immediate event. */
1784 TALLOC_FREE(state->im);
1787 * This is subtle. We must null out the callback
1788 * before rescheduling, else the first call to
1789 * tevent_req_nterror() causes the _receive()
1790 * function to be called, this causing tevent_req_post()
1793 tevent_req_set_callback(smb2req->subreq, NULL, NULL);
1795 state->im = tevent_create_immediate(smb2req);
1797 smbd_server_connection_terminate(smb2req->xconn,
1798 nt_errstr(NT_STATUS_NO_MEMORY));
1802 DEBUG(10,("schedule_deferred_open_message_smb2: "
1803 "re-processing mid %llu\n",
1804 (unsigned long long)mid ));
1806 tevent_schedule_immediate(state->im,
1807 smb2req->sconn->ev_ctx,
1808 smbd_smb2_create_request_dispatch_immediate,
1814 static bool smbd_smb2_create_cancel(struct tevent_req *req)
1816 struct smbd_smb2_request *smb2req = NULL;
1817 struct smbd_smb2_create_state *state = tevent_req_data(req,
1818 struct smbd_smb2_create_state);
1825 if (!state->smb2req) {
1829 smb2req = state->smb2req;
1830 mid = get_mid_from_smb2req(smb2req);
1832 if (is_deferred_open_async(state->open_rec)) {
1833 /* Can't cancel an async create. */
1837 remove_deferred_open_message_smb2_internal(smb2req, mid);
1839 tevent_req_defer_callback(req, smb2req->sconn->ev_ctx);
1840 tevent_req_nterror(req, NT_STATUS_CANCELLED);
1844 bool push_deferred_open_message_smb2(struct smbd_smb2_request *smb2req,
1845 struct timeval request_time,
1846 struct timeval timeout,
1848 struct deferred_open_record *open_rec)
1850 struct tevent_req *req = NULL;
1851 struct smbd_smb2_create_state *state = NULL;
1852 struct timeval end_time;
1857 req = smb2req->subreq;
1861 state = tevent_req_data(req, struct smbd_smb2_create_state);
1866 state->request_time = request_time;
1867 state->open_rec = talloc_move(state, &open_rec);
1869 /* Re-schedule us to retry on timer expiry. */
1870 end_time = timeval_sum(&request_time, &timeout);
1872 DEBUG(10,("push_deferred_open_message_smb2: "
1874 timeval_string(talloc_tos(),
1878 state->open_was_deferred = true;
1880 /* allow this request to be canceled */
1881 tevent_req_set_cancel_fn(req, smbd_smb2_create_cancel);