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;
71 static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
72 struct tevent_context *ev,
73 struct smbd_smb2_request *smb2req,
74 uint8_t in_oplock_level,
75 uint32_t in_impersonation_level,
76 uint32_t in_desired_access,
77 uint32_t in_file_attributes,
78 uint32_t in_share_access,
79 uint32_t in_create_disposition,
80 uint32_t in_create_options,
82 struct smb2_create_blobs in_context_blobs);
83 static NTSTATUS smbd_smb2_create_recv(struct tevent_req *req,
85 uint8_t *out_oplock_level,
86 uint32_t *out_create_action,
87 struct timespec *out_creation_ts,
88 struct timespec *out_last_access_ts,
89 struct timespec *out_last_write_ts,
90 struct timespec *out_change_ts,
91 uint64_t *out_allocation_size,
92 uint64_t *out_end_of_file,
93 uint32_t *out_file_attributes,
94 uint64_t *out_file_id_persistent,
95 uint64_t *out_file_id_volatile,
96 struct smb2_create_blobs *out_context_blobs);
98 static void smbd_smb2_request_create_done(struct tevent_req *tsubreq);
99 NTSTATUS smbd_smb2_request_process_create(struct smbd_smb2_request *smb2req)
101 const uint8_t *inbody;
102 const struct iovec *indyniov;
103 uint8_t in_oplock_level;
104 uint32_t in_impersonation_level;
105 uint32_t in_desired_access;
106 uint32_t in_file_attributes;
107 uint32_t in_share_access;
108 uint32_t in_create_disposition;
109 uint32_t in_create_options;
110 uint16_t in_name_offset;
111 uint16_t in_name_length;
112 DATA_BLOB in_name_buffer;
113 char *in_name_string;
114 size_t in_name_string_size;
115 uint32_t name_offset = 0;
116 uint32_t name_available_length = 0;
117 uint32_t in_context_offset;
118 uint32_t in_context_length;
119 DATA_BLOB in_context_buffer;
120 struct smb2_create_blobs in_context_blobs;
121 uint32_t context_offset = 0;
122 uint32_t context_available_length = 0;
126 struct tevent_req *tsubreq;
128 status = smbd_smb2_request_verify_sizes(smb2req, 0x39);
129 if (!NT_STATUS_IS_OK(status)) {
130 return smbd_smb2_request_error(smb2req, status);
132 inbody = SMBD_SMB2_IN_BODY_PTR(smb2req);
134 in_oplock_level = CVAL(inbody, 0x03);
135 in_impersonation_level = IVAL(inbody, 0x04);
136 in_desired_access = IVAL(inbody, 0x18);
137 in_file_attributes = IVAL(inbody, 0x1C);
138 in_share_access = IVAL(inbody, 0x20);
139 in_create_disposition = IVAL(inbody, 0x24);
140 in_create_options = IVAL(inbody, 0x28);
141 in_name_offset = SVAL(inbody, 0x2C);
142 in_name_length = SVAL(inbody, 0x2E);
143 in_context_offset = IVAL(inbody, 0x30);
144 in_context_length = IVAL(inbody, 0x34);
147 * First check if the dynamic name and context buffers
148 * are correctly specified.
150 * Note: That we don't check if the name and context buffers
154 dyn_offset = SMB2_HDR_BODY + SMBD_SMB2_IN_BODY_LEN(smb2req);
156 if (in_name_offset == 0 && in_name_length == 0) {
159 } else if (in_name_offset < dyn_offset) {
160 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
162 name_offset = in_name_offset - dyn_offset;
165 indyniov = SMBD_SMB2_IN_DYN_IOV(smb2req);
167 if (name_offset > indyniov->iov_len) {
168 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
171 name_available_length = indyniov->iov_len - name_offset;
173 if (in_name_length > name_available_length) {
174 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
177 in_name_buffer.data = (uint8_t *)indyniov->iov_base + name_offset;
178 in_name_buffer.length = in_name_length;
180 if (in_context_offset == 0 && in_context_length == 0) {
183 } else if (in_context_offset < dyn_offset) {
184 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
186 context_offset = in_context_offset - dyn_offset;
189 if (context_offset > indyniov->iov_len) {
190 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
193 context_available_length = indyniov->iov_len - context_offset;
195 if (in_context_length > context_available_length) {
196 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
199 in_context_buffer.data = (uint8_t *)indyniov->iov_base +
201 in_context_buffer.length = in_context_length;
204 * Now interpret the name and context buffers
207 ok = convert_string_talloc(smb2req, CH_UTF16, CH_UNIX,
209 in_name_buffer.length,
211 &in_name_string_size);
213 return smbd_smb2_request_error(smb2req, NT_STATUS_ILLEGAL_CHARACTER);
216 if (in_name_buffer.length == 0) {
217 in_name_string_size = 0;
220 if (strlen(in_name_string) != in_name_string_size) {
221 return smbd_smb2_request_error(smb2req, NT_STATUS_OBJECT_NAME_INVALID);
224 ZERO_STRUCT(in_context_blobs);
225 status = smb2_create_blob_parse(smb2req, in_context_buffer, &in_context_blobs);
226 if (!NT_STATUS_IS_OK(status)) {
227 return smbd_smb2_request_error(smb2req, status);
230 tsubreq = smbd_smb2_create_send(smb2req,
234 in_impersonation_level,
238 in_create_disposition,
242 if (tsubreq == NULL) {
243 smb2req->subreq = NULL;
244 return smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
246 tevent_req_set_callback(tsubreq, smbd_smb2_request_create_done, smb2req);
248 return smbd_smb2_request_pending_queue(smb2req, tsubreq, 500);
251 static uint64_t get_mid_from_smb2req(struct smbd_smb2_request *smb2req)
253 uint8_t *reqhdr = SMBD_SMB2_OUT_HDR_PTR(smb2req);
254 return BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
257 static void smbd_smb2_request_create_done(struct tevent_req *tsubreq)
259 struct smbd_smb2_request *smb2req = tevent_req_callback_data(tsubreq,
260 struct smbd_smb2_request);
263 uint8_t out_oplock_level = 0;
264 uint32_t out_create_action = 0;
265 connection_struct *conn = smb2req->tcon->compat;
266 struct timespec out_creation_ts = { 0, };
267 struct timespec out_last_access_ts = { 0, };
268 struct timespec out_last_write_ts = { 0, };
269 struct timespec out_change_ts = { 0, };
270 uint64_t out_allocation_size = 0;
271 uint64_t out_end_of_file = 0;
272 uint32_t out_file_attributes = 0;
273 uint64_t out_file_id_persistent = 0;
274 uint64_t out_file_id_volatile = 0;
275 struct smb2_create_blobs out_context_blobs;
276 DATA_BLOB out_context_buffer;
277 uint16_t out_context_buffer_offset = 0;
279 NTSTATUS error; /* transport error */
281 status = smbd_smb2_create_recv(tsubreq,
289 &out_allocation_size,
291 &out_file_attributes,
292 &out_file_id_persistent,
293 &out_file_id_volatile,
295 if (!NT_STATUS_IS_OK(status)) {
296 error = smbd_smb2_request_error(smb2req, status);
297 if (!NT_STATUS_IS_OK(error)) {
298 smbd_server_connection_terminate(smb2req->xconn,
305 status = smb2_create_blob_push(smb2req, &out_context_buffer, out_context_blobs);
306 if (!NT_STATUS_IS_OK(status)) {
307 error = smbd_smb2_request_error(smb2req, status);
308 if (!NT_STATUS_IS_OK(error)) {
309 smbd_server_connection_terminate(smb2req->xconn,
316 if (out_context_buffer.length > 0) {
317 out_context_buffer_offset = SMB2_HDR_BODY + 0x58;
320 outbody = smbd_smb2_generate_outbody(smb2req, 0x58);
321 if (outbody.data == NULL) {
322 error = smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
323 if (!NT_STATUS_IS_OK(error)) {
324 smbd_server_connection_terminate(smb2req->xconn,
331 SSVAL(outbody.data, 0x00, 0x58 + 1); /* struct size */
332 SCVAL(outbody.data, 0x02,
333 out_oplock_level); /* oplock level */
334 SCVAL(outbody.data, 0x03, 0); /* reserved */
335 SIVAL(outbody.data, 0x04,
336 out_create_action); /* create action */
337 put_long_date_timespec(conn->ts_res,
338 (char *)outbody.data + 0x08,
339 out_creation_ts); /* creation time */
340 put_long_date_timespec(conn->ts_res,
341 (char *)outbody.data + 0x10,
342 out_last_access_ts); /* last access time */
343 put_long_date_timespec(conn->ts_res,
344 (char *)outbody.data + 0x18,
345 out_last_write_ts); /* last write time */
346 put_long_date_timespec(conn->ts_res,
347 (char *)outbody.data + 0x20,
348 out_change_ts); /* change time */
349 SBVAL(outbody.data, 0x28,
350 out_allocation_size); /* allocation size */
351 SBVAL(outbody.data, 0x30,
352 out_end_of_file); /* end of file */
353 SIVAL(outbody.data, 0x38,
354 out_file_attributes); /* file attributes */
355 SIVAL(outbody.data, 0x3C, 0); /* reserved */
356 SBVAL(outbody.data, 0x40,
357 out_file_id_persistent); /* file id (persistent) */
358 SBVAL(outbody.data, 0x48,
359 out_file_id_volatile); /* file id (volatile) */
360 SIVAL(outbody.data, 0x50,
361 out_context_buffer_offset); /* create contexts offset */
362 SIVAL(outbody.data, 0x54,
363 out_context_buffer.length); /* create contexts length */
365 outdyn = out_context_buffer;
367 error = smbd_smb2_request_done(smb2req, outbody, &outdyn);
368 if (!NT_STATUS_IS_OK(error)) {
369 smbd_server_connection_terminate(smb2req->xconn,
375 static bool smb2_lease_key_valid(const struct smb2_lease_key *key)
377 return ((key->data[0] != 0) || (key->data[1] != 0));
380 static NTSTATUS smbd_smb2_create_durable_lease_check(struct smb_request *smb1req,
381 const char *requested_filename, const struct files_struct *fsp,
382 const struct smb2_lease *lease_ptr)
384 char *filename = NULL;
385 struct smb_filename *smb_fname = NULL;
389 if (lease_ptr == NULL) {
390 if (fsp->oplock_type != LEASE_OPLOCK) {
393 DEBUG(10, ("Reopened file has lease, but no lease "
395 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
398 if (fsp->oplock_type != LEASE_OPLOCK) {
399 DEBUG(10, ("Lease requested, but reopened file has no "
401 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
404 if (!smb2_lease_key_equal(&lease_ptr->lease_key,
405 &fsp->lease->lease.lease_key)) {
406 DEBUG(10, ("Different lease key requested than found "
407 "in reopened file\n"));
408 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
411 filename = talloc_strdup(talloc_tos(), requested_filename);
412 if (filename == NULL) {
413 return NT_STATUS_NO_MEMORY;
416 /* This also converts '\' to '/' */
417 status = check_path_syntax(filename);
418 if (!NT_STATUS_IS_OK(status)) {
419 TALLOC_FREE(filename);
423 ucf_flags = filename_create_ucf_flags(smb1req, FILE_OPEN);
424 status = filename_convert(talloc_tos(), fsp->conn,
427 TALLOC_FREE(filename);
428 if (!NT_STATUS_IS_OK(status)) {
429 DEBUG(10, ("filename_convert returned %s\n",
434 if (!strequal(fsp->fsp_name->base_name, smb_fname->base_name)) {
435 DEBUG(10, ("Lease requested for file %s, reopened file "
436 "is named %s\n", smb_fname->base_name,
437 fsp->fsp_name->base_name));
438 TALLOC_FREE(smb_fname);
439 return NT_STATUS_INVALID_PARAMETER;
442 TALLOC_FREE(smb_fname);
447 struct smbd_smb2_create_state {
448 struct tevent_context *ev;
449 struct smbd_smb2_request *smb2req;
450 struct smb_request *smb1req;
451 bool open_was_deferred;
452 struct tevent_immediate *im;
453 struct timeval request_time;
455 struct deferred_open_record *open_rec;
456 files_struct *result;
457 bool replay_operation;
458 uint8_t in_oplock_level;
459 uint32_t in_create_disposition;
460 int requested_oplock_level;
463 struct ea_list *ea_list;
464 NTTIME max_access_time;
465 struct security_descriptor *sec_desc;
466 uint64_t allocation_size;
467 struct GUID _create_guid;
468 struct GUID *create_guid;
470 bool durable_requested;
471 uint32_t durable_timeout_msec;
472 bool do_durable_reconnect;
473 uint64_t persistent_id;
474 struct smb2_lease lease;
475 struct smb2_lease *lease_ptr;
477 bool need_replay_cache;
478 struct smbXsrv_open *op;
480 struct smb2_create_blob *dhnc;
481 struct smb2_create_blob *dh2c;
482 struct smb2_create_blob *dhnq;
483 struct smb2_create_blob *dh2q;
484 struct smb2_create_blob *rqls;
485 struct smb2_create_blob *exta;
486 struct smb2_create_blob *mxac;
487 struct smb2_create_blob *secd;
488 struct smb2_create_blob *alsi;
489 struct smb2_create_blob *twrp;
490 struct smb2_create_blob *qfid;
491 struct smb2_create_blob *svhdx;
493 uint8_t out_oplock_level;
494 uint32_t out_create_action;
495 struct timespec out_creation_ts;
496 struct timespec out_last_access_ts;
497 struct timespec out_last_write_ts;
498 struct timespec out_change_ts;
499 uint64_t out_allocation_size;
500 uint64_t out_end_of_file;
501 uint32_t out_file_attributes;
502 uint64_t out_file_id_persistent;
503 uint64_t out_file_id_volatile;
504 struct smb2_create_blobs *out_context_blobs;
507 static NTSTATUS smbd_smb2_create_fetch_create_ctx(
508 struct tevent_req *req,
509 struct smb2_create_blobs *in_context_blobs)
511 struct smbd_smb2_create_state *state = tevent_req_data(
512 req, struct smbd_smb2_create_state);
514 state->dhnq = smb2_create_blob_find(in_context_blobs,
515 SMB2_CREATE_TAG_DHNQ);
516 state->dhnc = smb2_create_blob_find(in_context_blobs,
517 SMB2_CREATE_TAG_DHNC);
518 state->dh2q = smb2_create_blob_find(in_context_blobs,
519 SMB2_CREATE_TAG_DH2Q);
520 state->dh2c = smb2_create_blob_find(in_context_blobs,
521 SMB2_CREATE_TAG_DH2C);
522 if (state->smb2req->xconn->smb2.server.capabilities & SMB2_CAP_LEASING) {
523 state->rqls = smb2_create_blob_find(in_context_blobs,
524 SMB2_CREATE_TAG_RQLS);
527 if (((state->dhnc != NULL) && (state->dh2c != NULL)) ||
528 ((state->dhnc != NULL) && (state->dh2q != NULL)) ||
529 ((state->dh2c != NULL) && (state->dhnq != NULL)) ||
530 ((state->dh2q != NULL) && (state->dh2c != NULL)))
532 /* not both are allowed at the same time */
533 return NT_STATUS_INVALID_PARAMETER;
536 if (state->dhnc != NULL) {
537 uint32_t num_blobs_allowed;
539 if (state->dhnc->data.length != 16) {
540 return NT_STATUS_INVALID_PARAMETER;
544 * According to MS-SMB2: 3.3.5.9.7, "Handling the
545 * SMB2_CREATE_DURABLE_HANDLE_RECONNECT Create Context",
546 * we should ignore an additional dhnq blob, but fail
547 * the request (with status OBJECT_NAME_NOT_FOUND) if
548 * any other extra create blob has been provided.
550 * (Note that the cases of an additional dh2q or dh2c blob
551 * which require a different error code, have been treated
555 if (state->dhnq != NULL) {
556 num_blobs_allowed = 2;
558 num_blobs_allowed = 1;
561 if (state->rqls != NULL) {
562 num_blobs_allowed += 1;
565 if (in_context_blobs->num_blobs != num_blobs_allowed) {
566 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
570 if (state->dh2c!= NULL) {
571 uint32_t num_blobs_allowed;
573 if (state->dh2c->data.length != 36) {
574 return NT_STATUS_INVALID_PARAMETER;
578 * According to MS-SMB2: 3.3.5.9.12, "Handling the
579 * SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 Create Context",
580 * we should fail the request with status
581 * OBJECT_NAME_NOT_FOUND if any other create blob has been
584 * (Note that the cases of an additional dhnq, dhnc or dh2q
585 * blob which require a different error code, have been
589 num_blobs_allowed = 1;
591 if (state->rqls != NULL) {
592 num_blobs_allowed += 1;
595 if (in_context_blobs->num_blobs != num_blobs_allowed) {
596 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
600 state->exta = smb2_create_blob_find(in_context_blobs,
601 SMB2_CREATE_TAG_EXTA);
602 state->mxac = smb2_create_blob_find(in_context_blobs,
603 SMB2_CREATE_TAG_MXAC);
604 state->secd = smb2_create_blob_find(in_context_blobs,
605 SMB2_CREATE_TAG_SECD);
606 state->alsi = smb2_create_blob_find(in_context_blobs,
607 SMB2_CREATE_TAG_ALSI);
608 state->twrp = smb2_create_blob_find(in_context_blobs,
609 SMB2_CREATE_TAG_TWRP);
610 state->qfid = smb2_create_blob_find(in_context_blobs,
611 SMB2_CREATE_TAG_QFID);
612 if (state->smb2req->xconn->protocol >= PROTOCOL_SMB3_02) {
614 * This was introduced with SMB3_02
616 state->svhdx = smb2_create_blob_find(
617 in_context_blobs, SVHDX_OPEN_DEVICE_CONTEXT);
623 static void smbd_smb2_create_before_exec(struct tevent_req *req);
624 static void smbd_smb2_create_after_exec(struct tevent_req *req);
625 static void smbd_smb2_create_finish(struct tevent_req *req);
627 static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
628 struct tevent_context *ev,
629 struct smbd_smb2_request *smb2req,
630 uint8_t in_oplock_level,
631 uint32_t in_impersonation_level,
632 uint32_t in_desired_access,
633 uint32_t in_file_attributes,
634 uint32_t in_share_access,
635 uint32_t in_create_disposition,
636 uint32_t in_create_options,
638 struct smb2_create_blobs in_context_blobs)
640 struct tevent_req *req = NULL;
641 struct smbd_smb2_create_state *state = NULL;
643 struct smb_request *smb1req = NULL;
644 struct smb_filename *smb_fname = NULL;
647 req = tevent_req_create(mem_ctx, &state,
648 struct smbd_smb2_create_state);
652 *state = (struct smbd_smb2_create_state) {
655 .in_oplock_level = in_oplock_level,
656 .in_create_disposition = in_create_disposition,
659 smb1req = smbd_smb2_fake_smb_request(smb2req);
660 if (tevent_req_nomem(smb1req, req)) {
661 return tevent_req_post(req, state->ev);
663 state->smb1req = smb1req;
665 if (smb2req->subreq == NULL) {
666 DBG_DEBUG("name [%s]\n", in_name);
668 struct smbd_smb2_create_state *old_state = tevent_req_data(
669 smb2req->subreq, struct smbd_smb2_create_state);
671 DBG_DEBUG("reentrant for file %s\n", in_name);
673 state->id = old_state->id;
674 state->request_time = old_state->request_time;
675 state->open_rec = talloc_move(state, &old_state->open_rec);
676 state->open_was_deferred = old_state->open_was_deferred;
679 TALLOC_FREE(smb2req->subreq);
680 smb2req->subreq = req;
682 if (lp_fake_oplocks(SNUM(smb2req->tcon->compat))) {
683 state->requested_oplock_level = SMB2_OPLOCK_LEVEL_NONE;
685 state->requested_oplock_level = state->in_oplock_level;
688 /* these are ignored for SMB2 */
689 in_create_options &= ~(0x10);/* NTCREATEX_OPTIONS_SYNC_ALERT */
690 in_create_options &= ~(0x20);/* NTCREATEX_OPTIONS_ASYNC_ALERT */
692 in_file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS;
694 state->fname = talloc_strdup(state, in_name);
695 if (tevent_req_nomem(state->fname, req)) {
696 return tevent_req_post(req, state->ev);
699 state->out_context_blobs = talloc_zero(state, struct smb2_create_blobs);
700 if (tevent_req_nomem(state->out_context_blobs, req)) {
701 return tevent_req_post(req, state->ev);
704 status = smbd_smb2_create_fetch_create_ctx(req, &in_context_blobs);
705 if (tevent_req_nterror(req, status)) {
706 return tevent_req_post(req, state->ev);
709 if (IS_IPC(smb1req->conn)) {
710 const char *pipe_name = in_name;
712 if (state->dhnc != NULL || state->dh2c != NULL) {
713 /* durable handles are not supported on IPC$ */
714 tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
715 return tevent_req_post(req, state->ev);
718 if (!lp_nt_pipe_support()) {
719 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
720 return tevent_req_post(req, state->ev);
723 status = open_np_file(smb1req, pipe_name, &state->result);
724 if (!NT_STATUS_IS_OK(status)) {
725 tevent_req_nterror(req, status);
726 return tevent_req_post(req, state->ev);
728 state->info = FILE_WAS_OPENED;
730 smbd_smb2_create_finish(req);
733 } else if (CAN_PRINT(smb1req->conn)) {
734 if (state->dhnc != NULL || state->dh2c != NULL) {
735 /* durable handles are not supported on printers */
736 tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
737 return tevent_req_post(req, state->ev);
740 status = file_new(smb1req, smb1req->conn, &state->result);
741 if(!NT_STATUS_IS_OK(status)) {
742 tevent_req_nterror(req, status);
743 return tevent_req_post(req, state->ev);
746 status = print_spool_open(state->result, in_name,
748 if (!NT_STATUS_IS_OK(status)) {
749 file_free(smb1req, state->result);
750 tevent_req_nterror(req, status);
751 return tevent_req_post(req, state->ev);
753 state->info = FILE_WAS_CREATED;
755 smbd_smb2_create_finish(req);
759 smbd_smb2_create_before_exec(req);
760 if (!tevent_req_is_in_progress(req)) {
761 return tevent_req_post(req, state->ev);
764 DBG_DEBUG("open execution phase\n");
767 * For the backend file open procedure, there are
768 * three possible modes: replay operation (in which case
769 * there is nothing else to do), durable_reconnect or
772 if (state->replay_operation) {
773 state->result = state->op->compat;
774 state->result->op = state->op;
775 state->update_open = false;
776 state->info = state->op->create_action;
778 smbd_smb2_create_after_exec(req);
779 if (!tevent_req_is_in_progress(req)) {
783 smbd_smb2_create_finish(req);
786 } else if (state->do_durable_reconnect) {
787 DATA_BLOB new_cookie = data_blob_null;
788 NTTIME now = timeval_to_nttime(&smb2req->request_time);
790 status = smb2srv_open_recreate(smb2req->xconn,
791 smb1req->conn->session_info,
792 state->persistent_id,
796 if (!NT_STATUS_IS_OK(status)) {
797 DBG_NOTICE("smb2srv_open_recreate failed: %s\n",
799 tevent_req_nterror(req, status);
800 return tevent_req_post(req, state->ev);
803 DBG_DEBUG("%s to recreate durable handle\n",
804 state->op->global->durable ? "succeeded" : "failed");
806 if (!state->op->global->durable) {
807 talloc_free(state->op);
808 tevent_req_nterror(req,
809 NT_STATUS_OBJECT_NAME_NOT_FOUND);
810 return tevent_req_post(req, state->ev);
813 status = SMB_VFS_DURABLE_RECONNECT(smb1req->conn,
815 state->op, /* smbXsrv_open input */
816 state->op->global->backend_cookie,
817 state->op, /* TALLOC_CTX */
820 if (!NT_STATUS_IS_OK(status)) {
821 NTSTATUS return_status;
823 return_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
825 DBG_NOTICE("durable_reconnect failed: %s => %s\n",
827 nt_errstr(return_status));
829 tevent_req_nterror(req, return_status);
830 return tevent_req_post(req, state->ev);
833 DBG_DEBUG("oplock_type=%u, lease_ptr==%p\n",
834 (unsigned)state->result->oplock_type, state->lease_ptr);
836 status = smbd_smb2_create_durable_lease_check(
837 smb1req, state->fname, state->result, state->lease_ptr);
838 if (!NT_STATUS_IS_OK(status)) {
839 close_file(smb1req, state->result, SHUTDOWN_CLOSE);
840 tevent_req_nterror(req, status);
841 return tevent_req_post(req, state->ev);
844 data_blob_free(&state->op->global->backend_cookie);
845 state->op->global->backend_cookie = new_cookie;
847 state->op->status = NT_STATUS_OK;
848 state->op->global->disconnect_time = 0;
850 /* save the timout for later update */
851 state->durable_timeout_msec = state->op->global->durable_timeout_msec;
853 state->update_open = true;
855 state->info = FILE_WAS_OPENED;
857 smbd_smb2_create_after_exec(req);
858 if (!tevent_req_is_in_progress(req)) {
862 smbd_smb2_create_finish(req);
866 if (state->requested_oplock_level == SMB2_OPLOCK_LEVEL_LEASE) {
867 if (state->lease_ptr == NULL) {
868 state->requested_oplock_level = SMB2_OPLOCK_LEVEL_NONE;
871 state->lease_ptr = NULL;
875 * For a DFS path the function parse_dfs_path()
876 * will do the path processing.
879 if (!(smb1req->flags2 & FLAGS2_DFS_PATHNAMES)) {
880 /* convert '\\' into '/' */
881 status = check_path_syntax(state->fname);
882 if (!NT_STATUS_IS_OK(status)) {
883 tevent_req_nterror(req, status);
884 return tevent_req_post(req, state->ev);
888 ucf_flags = filename_create_ucf_flags(
889 smb1req, state->in_create_disposition);
890 status = filename_convert(req,
894 NULL, /* ppath_contains_wcards */
896 if (!NT_STATUS_IS_OK(status)) {
897 tevent_req_nterror(req, status);
898 return tevent_req_post(req, state->ev);
902 * MS-SMB2: 2.2.13 SMB2 CREATE Request
903 * ImpersonationLevel ... MUST contain one of the
904 * following values. The server MUST validate this
905 * field, but otherwise ignore it.
907 * NB. The source4/torture/smb2/durable_open.c test
908 * shows this check is only done on real opens, not
909 * on durable handle-reopens.
912 if (in_impersonation_level >
913 SMB2_IMPERSONATION_DELEGATE) {
914 tevent_req_nterror(req,
915 NT_STATUS_BAD_IMPERSONATION_LEVEL);
916 return tevent_req_post(req, state->ev);
920 * We know we're going to do a local open, so now
921 * we must be protocol strict. JRA.
923 * MS-SMB2: 3.3.5.9 - Receiving an SMB2 CREATE Request
924 * If the file name length is greater than zero and the
925 * first character is a path separator character, the
926 * server MUST fail the request with
927 * STATUS_INVALID_PARAMETER.
929 if (in_name[0] == '\\' || in_name[0] == '/') {
930 tevent_req_nterror(req,
931 NT_STATUS_INVALID_PARAMETER);
932 return tevent_req_post(req, state->ev);
935 status = SMB_VFS_CREATE_FILE(smb1req->conn,
937 0, /* root_dir_fid */
941 state->in_create_disposition,
944 map_smb2_oplock_levels_to_samba(
945 state->requested_oplock_level),
947 state->allocation_size,
948 0, /* private_flags */
954 state->out_context_blobs);
955 if (!NT_STATUS_IS_OK(status)) {
956 if (open_was_deferred(smb1req->xconn, smb1req->mid)) {
957 SMBPROFILE_IOBYTES_ASYNC_SET_IDLE(smb2req->profile);
960 tevent_req_nterror(req, status);
961 return tevent_req_post(req, state->ev);
963 state->op = state->result->op;
965 smbd_smb2_create_after_exec(req);
966 if (!tevent_req_is_in_progress(req)) {
970 smbd_smb2_create_finish(req);
974 static void smbd_smb2_create_before_exec(struct tevent_req *req)
976 struct smbd_smb2_create_state *state = tevent_req_data(
977 req, struct smbd_smb2_create_state);
978 struct smb_request *smb1req = state->smb1req;
979 struct smbd_smb2_request *smb2req = state->smb2req;
982 if (state->exta != NULL) {
983 if (!lp_ea_support(SNUM(smb2req->tcon->compat))) {
984 tevent_req_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
988 state->ea_list = read_nttrans_ea_list(
990 (const char *)state->exta->data.data,
991 state->exta->data.length);
992 if (state->ea_list == NULL) {
993 DEBUG(10,("smbd_smb2_create_send: read_ea_name_list failed.\n"));
994 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
999 * NB. When SMB2+ unix extensions are added,
1000 * we need to relax this check in invalid
1001 * names - we used to not do this if
1002 * lp_posix_pathnames() was false.
1004 if (ea_list_has_invalid_name(state->ea_list)) {
1005 tevent_req_nterror(req, STATUS_INVALID_EA_NAME);
1010 if (state->mxac != NULL) {
1011 if (state->mxac->data.length == 0) {
1012 state->max_access_time = 0;
1013 } else if (state->mxac->data.length == 8) {
1014 state->max_access_time = BVAL(state->mxac->data.data, 0);
1016 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1021 if (state->secd != NULL) {
1022 enum ndr_err_code ndr_err;
1024 state->sec_desc = talloc_zero(state, struct security_descriptor);
1025 if (tevent_req_nomem(state->sec_desc, req)) {
1029 ndr_err = ndr_pull_struct_blob(&state->secd->data,
1030 state->sec_desc, state->sec_desc,
1031 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
1032 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1033 DEBUG(2,("ndr_pull_security_descriptor failed: %s\n",
1034 ndr_errstr(ndr_err)));
1035 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1040 if (state->dhnq != NULL) {
1041 if (state->dhnq->data.length != 16) {
1042 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1046 if (state->dh2q != NULL) {
1047 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1052 * durable handle request is processed below.
1054 state->durable_requested = true;
1056 * Set the timeout to 16 mins.
1058 * TODO: test this against Windows 2012
1059 * as the default for durable v2 is 1 min.
1061 state->durable_timeout_msec = (16*60*1000);
1064 if (state->dh2q != NULL) {
1065 const uint8_t *p = state->dh2q->data.data;
1066 uint32_t durable_v2_timeout = 0;
1067 DATA_BLOB create_guid_blob;
1071 if (state->dh2q->data.length != 32) {
1072 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1076 if (state->dhnq != NULL) {
1077 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1081 durable_v2_timeout = IVAL(p, 0);
1082 create_guid_blob = data_blob_const(p + 16, 16);
1084 status = GUID_from_ndr_blob(&create_guid_blob,
1085 &state->_create_guid);
1086 if (tevent_req_nterror(req, status)) {
1089 state->create_guid = &state->_create_guid;
1092 * we need to store the create_guid later
1094 state->update_open = true;
1097 * And we need to create a cache for replaying the
1100 state->need_replay_cache = true;
1103 * durable handle v2 request processed below
1105 state->durable_requested = true;
1106 state->durable_timeout_msec = durable_v2_timeout;
1107 if (state->durable_timeout_msec == 0) {
1109 * Set the timeout to 1 min as default.
1111 * This matches Windows 2012.
1113 state->durable_timeout_msec = (60*1000);
1117 * Check for replay operation.
1118 * Only consider it when we have dh2q.
1119 * If we do not have a replay operation, verify that
1120 * the create_guid is not cached for replay.
1122 hdr = SMBD_SMB2_IN_HDR_PTR(smb2req);
1123 flags = IVAL(hdr, SMB2_HDR_FLAGS);
1124 state->replay_operation =
1125 flags & SMB2_HDR_FLAG_REPLAY_OPERATION;
1127 status = smb2srv_open_lookup_replay_cache(smb2req->xconn,
1131 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
1132 state->replay_operation = false;
1133 } else if (tevent_req_nterror(req, status)) {
1134 DBG_WARNING("smb2srv_open_lookup_replay_cache "
1135 "failed: %s\n", nt_errstr(status));
1137 } else if (!state->replay_operation) {
1139 * If a create without replay operation flag
1140 * is sent but with a create_guid that is
1141 * currently in the replay cache -- fail.
1143 status = NT_STATUS_DUPLICATE_OBJECTID;
1144 (void)tevent_req_nterror(req, status);
1149 if (state->dhnc != NULL) {
1150 state->persistent_id = BVAL(state->dhnc->data.data, 0);
1151 state->do_durable_reconnect = true;
1154 if (state->dh2c != NULL) {
1155 const uint8_t *p = state->dh2c->data.data;
1156 DATA_BLOB create_guid_blob;
1158 state->persistent_id = BVAL(p, 0);
1159 create_guid_blob = data_blob_const(p + 16, 16);
1161 status = GUID_from_ndr_blob(&create_guid_blob,
1162 &state->_create_guid);
1163 if (tevent_req_nterror(req, status)) {
1167 state->create_guid = &state->_create_guid;
1168 state->do_durable_reconnect = true;
1171 if (state->alsi != NULL) {
1172 if (state->alsi->data.length != 8) {
1173 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1176 state->allocation_size = BVAL(state->alsi->data.data, 0);
1179 if (state->twrp != NULL) {
1183 char *tmpname = state->fname;
1185 if (state->twrp->data.length != 8) {
1186 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1190 nttime = BVAL(state->twrp->data.data, 0);
1191 t = nt_time_to_unix(nttime);
1194 state->fname = talloc_asprintf(
1196 "%s\\@GMT-%04u.%02u.%02u-%02u.%02u.%02u",
1204 if (tevent_req_nomem(state->fname, req)) {
1207 TALLOC_FREE(tmpname);
1209 * Tell filename_create_ucf_flags() this
1212 smb1req->flags2 |= FLAGS2_REPARSE_PATH;
1215 if (state->qfid != NULL) {
1216 if (state->qfid->data.length != 0) {
1217 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1222 if (state->rqls != NULL) {
1223 ssize_t lease_len = -1;
1225 lease_len = smb2_lease_pull(state->rqls->data.data,
1226 state->rqls->data.length,
1228 if (lease_len == -1) {
1230 req, NT_STATUS_INVALID_PARAMETER);
1233 state->lease_ptr = &state->lease;
1235 if (DEBUGLEVEL >= 10) {
1236 DEBUG(10, ("Got lease request size %d\n",
1238 NDR_PRINT_DEBUG(smb2_lease, state->lease_ptr);
1241 if (!smb2_lease_key_valid(&state->lease.lease_key)) {
1242 state->lease_ptr = NULL;
1243 state->requested_oplock_level = SMB2_OPLOCK_LEVEL_NONE;
1246 if ((smb2req->xconn->protocol < PROTOCOL_SMB3_00) &&
1247 (state->lease.lease_version != 1))
1249 DEBUG(10, ("v2 lease key only for SMB3\n"));
1250 state->lease_ptr = NULL;
1254 * Replay with a lease is only allowed if the
1255 * established open carries a lease with the
1258 if (state->replay_operation) {
1259 struct smb2_lease *op_ls =
1260 &state->op->compat->lease->lease;
1261 int op_oplock = state->op->compat->oplock_type;
1263 if (map_samba_oplock_levels_to_smb2(op_oplock)
1264 != SMB2_OPLOCK_LEVEL_LEASE)
1266 status = NT_STATUS_ACCESS_DENIED;
1267 (void)tevent_req_nterror(req, status);
1270 if (!smb2_lease_key_equal(&state->lease.lease_key,
1273 status = NT_STATUS_ACCESS_DENIED;
1274 (void)tevent_req_nterror(req, status);
1283 static void smbd_smb2_create_after_exec(struct tevent_req *req)
1285 struct smbd_smb2_create_state *state = tevent_req_data(
1286 req, struct smbd_smb2_create_state);
1287 struct smb_request *smb1req = state->smb1req;
1291 * here we have op == result->op
1294 DEBUG(10, ("smbd_smb2_create_send: "
1295 "response construction phase\n"));
1297 if (state->mxac != NULL) {
1298 NTTIME last_write_time;
1300 last_write_time = unix_timespec_to_nt_time(
1301 state->result->fsp_name->st.st_ex_mtime);
1302 if (last_write_time != state->max_access_time) {
1304 uint32_t max_access_granted;
1305 DATA_BLOB blob = data_blob_const(p, sizeof(p));
1307 status = smbd_calculate_access_mask(smb1req->conn,
1308 state->result->fsp_name,
1310 SEC_FLAG_MAXIMUM_ALLOWED,
1311 &max_access_granted);
1313 SIVAL(p, 0, NT_STATUS_V(status));
1314 SIVAL(p, 4, max_access_granted);
1316 status = smb2_create_blob_add(
1317 state->out_context_blobs,
1318 state->out_context_blobs,
1319 SMB2_CREATE_TAG_MXAC,
1321 if (!NT_STATUS_IS_OK(status)) {
1322 tevent_req_nterror(req, status);
1323 tevent_req_post(req, state->ev);
1329 if (!state->replay_operation && state->durable_requested &&
1330 (fsp_lease_type(state->result) & SMB2_LEASE_HANDLE))
1332 status = SMB_VFS_DURABLE_COOKIE(
1335 &state->op->global->backend_cookie);
1336 if (!NT_STATUS_IS_OK(status)) {
1337 state->op->global->backend_cookie = data_blob_null;
1340 if (!state->replay_operation && state->op->global->backend_cookie.length > 0)
1342 state->update_open = true;
1344 state->op->global->durable = true;
1345 state->op->global->durable_timeout_msec = state->durable_timeout_msec;
1348 if (state->update_open) {
1349 state->op->global->create_guid = state->_create_guid;
1350 if (state->need_replay_cache) {
1351 state->op->flags |= SMBXSRV_OPEN_NEED_REPLAY_CACHE;
1354 status = smbXsrv_open_update(state->op);
1355 DEBUG(10, ("smb2_create_send: smbXsrv_open_update "
1357 nt_errstr(status)));
1358 if (!NT_STATUS_IS_OK(status)) {
1359 tevent_req_nterror(req, status);
1360 tevent_req_post(req, state->ev);
1365 if (state->dhnq != NULL && state->op->global->durable) {
1366 uint8_t p[8] = { 0, };
1367 DATA_BLOB blob = data_blob_const(p, sizeof(p));
1369 status = smb2_create_blob_add(state->out_context_blobs,
1370 state->out_context_blobs,
1371 SMB2_CREATE_TAG_DHNQ,
1373 if (!NT_STATUS_IS_OK(status)) {
1374 tevent_req_nterror(req, status);
1375 tevent_req_post(req, state->ev);
1380 if (state->dh2q != NULL && state->op->global->durable &&
1382 * For replay operations, we return the dh2q blob
1383 * in the case of oplocks not based on the state of
1384 * the open, but on whether it could have been granted
1385 * for the request data. In the case of leases instead,
1386 * the state of the open is used...
1388 (!state->replay_operation ||
1389 state->in_oplock_level == SMB2_OPLOCK_LEVEL_BATCH ||
1390 state->in_oplock_level == SMB2_OPLOCK_LEVEL_LEASE))
1392 uint8_t p[8] = { 0, };
1393 DATA_BLOB blob = data_blob_const(p, sizeof(p));
1394 uint32_t durable_v2_response_flags = 0;
1396 SIVAL(p, 0, state->op->global->durable_timeout_msec);
1397 SIVAL(p, 4, durable_v2_response_flags);
1399 status = smb2_create_blob_add(state->out_context_blobs,
1400 state->out_context_blobs,
1401 SMB2_CREATE_TAG_DH2Q,
1403 if (!NT_STATUS_IS_OK(status)) {
1404 tevent_req_nterror(req, status);
1405 tevent_req_post(req, state->ev);
1410 if (state->qfid != NULL) {
1412 uint64_t file_index = get_FileIndex(state->result->conn,
1413 &state->result->fsp_name->st);
1414 DATA_BLOB blob = data_blob_const(p, sizeof(p));
1418 /* From conversations with Microsoft engineers at
1419 the MS plugfest. The first 8 bytes are the "volume index"
1420 == inode, the second 8 bytes are the "volume id",
1421 == dev. This will be updated in the SMB2 doc. */
1422 SBVAL(p, 0, file_index);
1423 SIVAL(p, 8, state->result->fsp_name->st.st_ex_dev);/* FileIndexHigh */
1425 status = smb2_create_blob_add(state->out_context_blobs,
1426 state->out_context_blobs,
1427 SMB2_CREATE_TAG_QFID,
1429 if (!NT_STATUS_IS_OK(status)) {
1430 tevent_req_nterror(req, status);
1431 tevent_req_post(req, state->ev);
1436 if ((state->rqls != NULL) && (state->result->oplock_type == LEASE_OPLOCK)) {
1438 struct smb2_lease lease;
1441 lease = state->result->lease->lease;
1443 lease_len = sizeof(buf);
1444 if (lease.lease_version == 1) {
1448 if (!smb2_lease_push(&lease, buf, lease_len)) {
1450 req, NT_STATUS_INTERNAL_ERROR);
1451 tevent_req_post(req, state->ev);
1455 status = smb2_create_blob_add(
1456 state, state->out_context_blobs,
1457 SMB2_CREATE_TAG_RQLS,
1458 data_blob_const(buf, lease_len));
1459 if (!NT_STATUS_IS_OK(status)) {
1460 tevent_req_nterror(req, status);
1461 tevent_req_post(req, state->ev);
1469 static void smbd_smb2_create_finish(struct tevent_req *req)
1471 struct smbd_smb2_create_state *state = tevent_req_data(
1472 req, struct smbd_smb2_create_state);
1473 struct smbd_smb2_request *smb2req = state->smb2req;
1474 struct smb_request *smb1req = state->smb1req;
1475 files_struct *result = state->result;
1477 smb2req->compat_chain_fsp = smb1req->chain_fsp;
1479 if (state->replay_operation) {
1480 state->out_oplock_level = state->in_oplock_level;
1481 } else if (lp_fake_oplocks(SNUM(smb2req->tcon->compat))) {
1482 state->out_oplock_level = state->in_oplock_level;
1484 state->out_oplock_level = map_samba_oplock_levels_to_smb2(result->oplock_type);
1487 if ((state->in_create_disposition == FILE_SUPERSEDE)
1488 && (state->info == FILE_WAS_OVERWRITTEN)) {
1489 state->out_create_action = FILE_WAS_SUPERSEDED;
1491 state->out_create_action = state->info;
1493 result->op->create_action = state->out_create_action;
1494 state->out_file_attributes = dos_mode(result->conn,
1497 state->out_creation_ts = get_create_timespec(smb1req->conn,
1498 result, result->fsp_name);
1499 state->out_last_access_ts = result->fsp_name->st.st_ex_atime;
1500 state->out_last_write_ts = result->fsp_name->st.st_ex_mtime;
1501 state->out_change_ts = get_change_timespec(smb1req->conn,
1502 result, result->fsp_name);
1504 if (lp_dos_filetime_resolution(SNUM(smb2req->tcon->compat))) {
1505 dos_filetime_timespec(&state->out_creation_ts);
1506 dos_filetime_timespec(&state->out_last_access_ts);
1507 dos_filetime_timespec(&state->out_last_write_ts);
1508 dos_filetime_timespec(&state->out_change_ts);
1511 state->out_allocation_size =
1512 SMB_VFS_GET_ALLOC_SIZE(smb1req->conn, result,
1513 &(result->fsp_name->st));
1514 state->out_end_of_file = result->fsp_name->st.st_ex_size;
1515 if (state->out_file_attributes == 0) {
1516 state->out_file_attributes = FILE_ATTRIBUTE_NORMAL;
1518 state->out_file_id_persistent = result->op->global->open_persistent_id;
1519 state->out_file_id_volatile = result->op->global->open_volatile_id;
1521 DBG_DEBUG("%s - %s\n", fsp_str_dbg(result), fsp_fnum_dbg(result));
1523 tevent_req_done(req);
1524 tevent_req_post(req, state->ev);
1528 static NTSTATUS smbd_smb2_create_recv(struct tevent_req *req,
1529 TALLOC_CTX *mem_ctx,
1530 uint8_t *out_oplock_level,
1531 uint32_t *out_create_action,
1532 struct timespec *out_creation_ts,
1533 struct timespec *out_last_access_ts,
1534 struct timespec *out_last_write_ts,
1535 struct timespec *out_change_ts,
1536 uint64_t *out_allocation_size,
1537 uint64_t *out_end_of_file,
1538 uint32_t *out_file_attributes,
1539 uint64_t *out_file_id_persistent,
1540 uint64_t *out_file_id_volatile,
1541 struct smb2_create_blobs *out_context_blobs)
1544 struct smbd_smb2_create_state *state = tevent_req_data(req,
1545 struct smbd_smb2_create_state);
1547 if (tevent_req_is_nterror(req, &status)) {
1548 tevent_req_received(req);
1552 *out_oplock_level = state->out_oplock_level;
1553 *out_create_action = state->out_create_action;
1554 *out_creation_ts = state->out_creation_ts;
1555 *out_last_access_ts = state->out_last_access_ts;
1556 *out_last_write_ts = state->out_last_write_ts;
1557 *out_change_ts = state->out_change_ts;
1558 *out_allocation_size = state->out_allocation_size;
1559 *out_end_of_file = state->out_end_of_file;
1560 *out_file_attributes = state->out_file_attributes;
1561 *out_file_id_persistent = state->out_file_id_persistent;
1562 *out_file_id_volatile = state->out_file_id_volatile;
1563 *out_context_blobs = *(state->out_context_blobs);
1565 talloc_steal(mem_ctx, state->out_context_blobs->blobs);
1567 tevent_req_received(req);
1568 return NT_STATUS_OK;
1571 /*********************************************************
1572 Code for dealing with deferred opens.
1573 *********************************************************/
1575 bool get_deferred_open_message_state_smb2(struct smbd_smb2_request *smb2req,
1576 struct timeval *p_request_time,
1577 struct deferred_open_record **open_rec)
1579 struct smbd_smb2_create_state *state = NULL;
1580 struct tevent_req *req = NULL;
1585 req = smb2req->subreq;
1589 state = tevent_req_data(req, struct smbd_smb2_create_state);
1593 if (!state->open_was_deferred) {
1596 if (p_request_time) {
1597 *p_request_time = state->request_time;
1599 if (open_rec != NULL) {
1600 *open_rec = state->open_rec;
1605 /*********************************************************
1606 Re-process this call early - requested by message or
1608 *********************************************************/
1610 static struct smbd_smb2_request *find_open_smb2req(
1611 struct smbXsrv_connection *xconn, uint64_t mid)
1613 struct smbd_smb2_request *smb2req;
1615 for (smb2req = xconn->smb2.requests; smb2req; smb2req = smb2req->next) {
1616 uint64_t message_id;
1617 if (smb2req->subreq == NULL) {
1618 /* This message has been processed. */
1621 if (!tevent_req_is_in_progress(smb2req->subreq)) {
1622 /* This message has been processed. */
1625 message_id = get_mid_from_smb2req(smb2req);
1626 if (message_id == mid) {
1633 bool open_was_deferred_smb2(struct smbXsrv_connection *xconn, uint64_t mid)
1635 struct smbd_smb2_create_state *state = NULL;
1636 struct smbd_smb2_request *smb2req;
1638 smb2req = find_open_smb2req(xconn, mid);
1641 DEBUG(10,("open_was_deferred_smb2: mid %llu smb2req == NULL\n",
1642 (unsigned long long)mid));
1645 if (!smb2req->subreq) {
1648 if (!tevent_req_is_in_progress(smb2req->subreq)) {
1651 state = tevent_req_data(smb2req->subreq,
1652 struct smbd_smb2_create_state);
1656 /* It's not in progress if there's no timeout event. */
1657 if (!state->open_was_deferred) {
1661 DEBUG(10,("open_was_deferred_smb2: mid = %llu\n",
1662 (unsigned long long)mid));
1667 static void remove_deferred_open_message_smb2_internal(struct smbd_smb2_request *smb2req,
1670 struct smbd_smb2_create_state *state = NULL;
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);
1684 DEBUG(10,("remove_deferred_open_message_smb2_internal: "
1686 (unsigned long long)mid ));
1688 state->open_was_deferred = false;
1689 /* Ensure we don't have any outstanding immediate event. */
1690 TALLOC_FREE(state->im);
1693 void remove_deferred_open_message_smb2(
1694 struct smbXsrv_connection *xconn, uint64_t mid)
1696 struct smbd_smb2_request *smb2req;
1698 smb2req = find_open_smb2req(xconn, mid);
1701 DEBUG(10,("remove_deferred_open_message_smb2: "
1702 "can't find mid %llu\n",
1703 (unsigned long long)mid ));
1706 remove_deferred_open_message_smb2_internal(smb2req, mid);
1709 static void smbd_smb2_create_request_dispatch_immediate(struct tevent_context *ctx,
1710 struct tevent_immediate *im,
1713 struct smbd_smb2_request *smb2req = talloc_get_type_abort(private_data,
1714 struct smbd_smb2_request);
1715 uint64_t mid = get_mid_from_smb2req(smb2req);
1718 DEBUG(10,("smbd_smb2_create_request_dispatch_immediate: "
1719 "re-dispatching mid %llu\n",
1720 (unsigned long long)mid ));
1722 status = smbd_smb2_request_dispatch(smb2req);
1723 if (!NT_STATUS_IS_OK(status)) {
1724 smbd_server_connection_terminate(smb2req->xconn,
1730 bool schedule_deferred_open_message_smb2(
1731 struct smbXsrv_connection *xconn, uint64_t mid)
1733 struct smbd_smb2_create_state *state = NULL;
1734 struct smbd_smb2_request *smb2req;
1736 smb2req = find_open_smb2req(xconn, mid);
1739 DEBUG(10,("schedule_deferred_open_message_smb2: "
1740 "can't find mid %llu\n",
1741 (unsigned long long)mid ));
1744 if (!smb2req->subreq) {
1747 if (!tevent_req_is_in_progress(smb2req->subreq)) {
1750 state = tevent_req_data(smb2req->subreq,
1751 struct smbd_smb2_create_state);
1756 /* Ensure we don't have any outstanding immediate event. */
1757 TALLOC_FREE(state->im);
1760 * This is subtle. We must null out the callback
1761 * before rescheduling, else the first call to
1762 * tevent_req_nterror() causes the _receive()
1763 * function to be called, this causing tevent_req_post()
1766 tevent_req_set_callback(smb2req->subreq, NULL, NULL);
1768 state->im = tevent_create_immediate(smb2req);
1770 smbd_server_connection_terminate(smb2req->xconn,
1771 nt_errstr(NT_STATUS_NO_MEMORY));
1775 DEBUG(10,("schedule_deferred_open_message_smb2: "
1776 "re-processing mid %llu\n",
1777 (unsigned long long)mid ));
1779 tevent_schedule_immediate(state->im,
1781 smbd_smb2_create_request_dispatch_immediate,
1787 static bool smbd_smb2_create_cancel(struct tevent_req *req)
1789 struct smbd_smb2_request *smb2req = NULL;
1790 struct smbd_smb2_create_state *state = tevent_req_data(req,
1791 struct smbd_smb2_create_state);
1798 if (!state->smb2req) {
1802 smb2req = state->smb2req;
1803 mid = get_mid_from_smb2req(smb2req);
1805 if (is_deferred_open_async(state->open_rec)) {
1806 /* Can't cancel an async create. */
1810 remove_deferred_open_message_smb2_internal(smb2req, mid);
1812 tevent_req_defer_callback(req, smb2req->ev_ctx);
1813 tevent_req_nterror(req, NT_STATUS_CANCELLED);
1817 bool push_deferred_open_message_smb2(struct smbd_smb2_request *smb2req,
1818 struct timeval request_time,
1819 struct timeval timeout,
1821 struct deferred_open_record *open_rec)
1823 struct tevent_req *req = NULL;
1824 struct smbd_smb2_create_state *state = NULL;
1825 struct timeval end_time;
1830 req = smb2req->subreq;
1834 state = tevent_req_data(req, struct smbd_smb2_create_state);
1839 state->request_time = request_time;
1840 state->open_rec = talloc_move(state, &open_rec);
1842 /* Re-schedule us to retry on timer expiry. */
1843 end_time = timeval_sum(&request_time, &timeout);
1845 DEBUG(10,("push_deferred_open_message_smb2: "
1847 timeval_string(talloc_tos(),
1851 state->open_was_deferred = true;
1853 /* allow this request to be canceled */
1854 tevent_req_set_cancel_fn(req, smbd_smb2_create_cancel);