tests/krb5: Clarify checksum type assertion message
[Samba.git] / source3 / smbd / smb2_create.c
blob75c86fe5e5fd7775e2e5f75193c725ef7d7b6cc8
1 /*
2 Unix SMB/CIFS implementation.
3 Core SMB2 server
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/>.
22 #include "includes.h"
23 #include "printing.h"
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"
30 #include "messages.h"
32 #undef DBGC_CLASS
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:
39 return NO_OPLOCK;
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:
45 return BATCH_OPLOCK;
46 case SMB2_OPLOCK_LEVEL_LEASE:
47 return LEASE_OPLOCK;
48 default:
49 DEBUG(2,("map_smb2_oplock_levels_to_samba: "
50 "unknown level %u\n",
51 (unsigned int)in_oplock_level));
52 return NO_OPLOCK;
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;
66 } else {
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);
86 char trail_c;
88 if (name_len <= 1) {
89 return NT_STATUS_OK;
92 trail_c = name[name_len-1];
95 * Trailing '/' is always invalid.
97 if (trail_c == '/') {
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;
106 return NT_STATUS_OK;
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,
119 const char *in_name,
120 struct smb2_create_blobs in_context_blobs);
121 static NTSTATUS smbd_smb2_create_recv(struct tevent_req *req,
122 TALLOC_CTX *mem_ctx,
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;
161 uint32_t dyn_offset;
162 NTSTATUS status;
163 bool ok;
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
189 * overlap
192 dyn_offset = SMB2_HDR_BODY + SMBD_SMB2_IN_BODY_LEN(smb2req);
194 if (in_name_offset == 0 && in_name_length == 0) {
195 /* This is ok */
196 name_offset = 0;
197 } else if (in_name_offset < dyn_offset) {
198 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
199 } else {
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) {
219 /* This is ok */
220 context_offset = 0;
221 } else if (in_context_offset < dyn_offset) {
222 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
223 } else {
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 +
238 context_offset;
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,
246 in_name_buffer.data,
247 in_name_buffer.length,
248 &in_name_string,
249 &in_name_string_size);
250 if (!ok) {
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,
270 smb2req,
271 in_oplock_level,
272 in_impersonation_level,
273 in_desired_access,
274 in_file_attributes,
275 in_share_access,
276 in_create_disposition,
277 in_create_options,
278 in_name_string,
279 in_context_blobs);
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);
299 DATA_BLOB outbody;
300 DATA_BLOB outdyn;
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;
316 NTSTATUS status;
317 NTSTATUS error; /* transport error */
319 status = smbd_smb2_create_recv(tsubreq,
320 smb2req,
321 &out_oplock_level,
322 &out_create_action,
323 &out_creation_ts,
324 &out_last_access_ts,
325 &out_last_write_ts,
326 &out_change_ts,
327 &out_allocation_size,
328 &out_end_of_file,
329 &out_file_attributes,
330 &out_file_id_persistent,
331 &out_file_id_volatile,
332 &out_context_blobs);
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,
337 nt_errstr(error));
338 return;
340 return;
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,
348 nt_errstr(error));
349 return;
351 return;
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,
363 nt_errstr(error));
364 return;
366 return;
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,
408 nt_errstr(error));
409 return;
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;
424 uint32_t ucf_flags;
425 NTSTATUS status;
427 if (lease_ptr == NULL) {
428 if (fsp->oplock_type != LEASE_OPLOCK) {
429 return NT_STATUS_OK;
431 DEBUG(10, ("Reopened file has lease, but no lease "
432 "requested\n"));
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 "
438 "lease\n"));
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);
458 return status;
461 ucf_flags = filename_create_ucf_flags(smb1req, FILE_OPEN);
462 status = filename_convert(talloc_tos(), fsp->conn,
463 filename, ucf_flags,
464 0, NULL, &smb_fname);
465 TALLOC_FREE(filename);
466 if (!NT_STATUS_IS_OK(status)) {
467 DEBUG(10, ("filename_convert returned %s\n",
468 nt_errstr(status)));
469 return status;
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);
482 return NT_STATUS_OK;
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;
492 struct file_id id;
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;
499 int info;
500 char *fname;
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;
507 bool update_open;
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;
514 ssize_t lease_len;
515 bool need_replay_cache;
516 struct smbXsrv_open *op;
517 NTTIME twrp_time;
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
599 * above.)
602 if (state->dhnq != NULL) {
603 num_blobs_allowed = 2;
604 } else {
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
629 * provided.
631 * (Note that the cases of an additional dhnq, dhnc or dh2q
632 * blob which require a different error code, have been
633 * treated above.)
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);
667 return NT_STATUS_OK;
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,
684 const char *in_name,
685 struct smb2_create_blobs in_context_blobs)
687 struct tevent_req *req = NULL;
688 struct smbd_smb2_create_state *state = NULL;
689 NTSTATUS status;
690 struct smb_request *smb1req = NULL;
691 struct smb_filename *smb_fname = NULL;
692 uint32_t ucf_flags;
694 req = tevent_req_create(mem_ctx, &state,
695 struct smbd_smb2_create_state);
696 if (req == NULL) {
697 return NULL;
699 *state = (struct smbd_smb2_create_state) {
700 .ev = ev,
701 .smb2req = smb2req,
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);
714 } else {
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;
731 } else {
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);
778 return 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,
794 smb1req->vuid);
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);
803 return 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
824 * new open.
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)) {
834 return req;
837 smbd_smb2_create_finish(req);
838 return 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,
847 state->create_guid,
848 now,
849 &state->op);
850 if (!NT_STATUS_IS_OK(status)) {
851 DBG_NOTICE("smb2srv_open_recreate failed: %s\n",
852 nt_errstr(status));
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,
868 smb1req,
869 state->op, /* smbXsrv_open input */
870 state->op->global->backend_cookie,
871 state->op, /* TALLOC_CTX */
872 &state->result,
873 &new_cookie);
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",
880 nt_errstr(status),
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)) {
913 return req;
916 smbd_smb2_create_finish(req);
917 return 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;
924 } else {
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,
945 smb1req->conn,
946 state->fname,
947 ucf_flags,
948 state->twrp_time,
949 NULL, /* ppath_contains_wcards */
950 &smb_fname);
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,
991 smb1req,
992 &smb1req->conn->cwd_fsp,
993 smb_fname,
994 in_desired_access,
995 in_share_access,
996 state->in_create_disposition,
997 in_create_options,
998 in_file_attributes,
999 map_smb2_oplock_levels_to_samba(
1000 state->requested_oplock_level),
1001 state->lease_ptr,
1002 state->allocation_size,
1003 0, /* private_flags */
1004 state->sec_desc,
1005 state->ea_list,
1006 &state->result,
1007 &state->info,
1008 &in_context_blobs,
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);
1013 return req;
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)) {
1022 return req;
1025 smbd_smb2_create_finish(req);
1026 return 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;
1034 NTSTATUS status;
1036 if (state->exta != NULL) {
1037 if (!lp_ea_support(SNUM(smb2req->tcon->compat))) {
1038 tevent_req_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1039 return;
1042 state->ea_list = read_nttrans_ea_list(
1043 state,
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);
1049 return;
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);
1060 return;
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);
1069 } else {
1070 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1071 return;
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)) {
1080 return;
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);
1090 return;
1094 if (state->dhnq != NULL) {
1095 if (state->dhnq->data.length != 16) {
1096 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1097 return;
1100 if (state->dh2q != NULL) {
1101 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1102 return;
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;
1122 const uint8_t *hdr;
1123 uint32_t flags;
1125 if (state->dh2q->data.length != 32) {
1126 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1127 return;
1130 if (state->dhnq != NULL) {
1131 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1132 return;
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)) {
1141 return;
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
1152 * create.
1154 state->need_replay_cache = true;
1157 * durable handle v2 request processed below
1159 state->durable_requested = true;
1160 state->durable_timeout_msec = MIN(durable_v2_timeout, 300*1000);
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,
1182 state->create_guid,
1183 0 /* now */,
1184 &state->op);
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));
1190 return;
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);
1199 return;
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)) {
1218 return;
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);
1228 return;
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);
1236 return;
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);
1245 return;
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,
1254 &state->lease);
1255 if (lease_len == -1) {
1256 tevent_req_nterror(
1257 req, NT_STATUS_INVALID_PARAMETER);
1258 return;
1260 state->lease_ptr = &state->lease;
1262 if (DEBUGLEVEL >= 10) {
1263 DEBUG(10, ("Got lease request size %d\n",
1264 (int)lease_len));
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
1283 * same lease key.
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);
1295 return;
1297 if (!smb2_lease_key_equal(&state->lease.lease_key,
1298 &op_ls->lease_key))
1300 status = NT_STATUS_ACCESS_DENIED;
1301 (void)tevent_req_nterror(req, status);
1302 return;
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;
1313 NTSTATUS status;
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) {
1331 uint8_t p[8];
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,
1338 false,
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,
1349 blob);
1350 if (!NT_STATUS_IS_OK(status)) {
1351 tevent_req_nterror(req, status);
1352 tevent_req_post(req, state->ev);
1353 return;
1358 if (!state->replay_operation && state->durable_requested &&
1359 (fsp_lease_type(state->result) & SMB2_LEASE_HANDLE))
1361 status = SMB_VFS_DURABLE_COOKIE(
1362 state->result,
1363 state->op,
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 "
1385 "returned %s\n",
1386 nt_errstr(status)));
1387 if (!NT_STATUS_IS_OK(status)) {
1388 tevent_req_nterror(req, status);
1389 tevent_req_post(req, state->ev);
1390 return;
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,
1401 blob);
1402 if (!NT_STATUS_IS_OK(status)) {
1403 tevent_req_nterror(req, status);
1404 tevent_req_post(req, state->ev);
1405 return;
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,
1431 blob);
1432 if (!NT_STATUS_IS_OK(status)) {
1433 tevent_req_nterror(req, status);
1434 tevent_req_post(req, state->ev);
1435 return;
1439 if (state->qfid != NULL) {
1440 uint8_t p[32];
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));
1446 ZERO_STRUCT(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,
1458 blob);
1459 if (!NT_STATUS_IS_OK(status)) {
1460 tevent_req_nterror(req, status);
1461 tevent_req_post(req, state->ev);
1462 return;
1466 if ((state->rqls != NULL) && (state->result->oplock_type == LEASE_OPLOCK)) {
1467 uint8_t buf[52];
1468 struct smb2_lease lease;
1469 size_t lease_len;
1471 lease = state->result->lease->lease;
1473 lease_len = sizeof(buf);
1474 if (lease.lease_version == 1) {
1475 lease_len = 32;
1478 if (!smb2_lease_push(&lease, buf, lease_len)) {
1479 tevent_req_nterror(
1480 req, NT_STATUS_INTERNAL_ERROR);
1481 tevent_req_post(req, state->ev);
1482 return;
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);
1492 return;
1496 return;
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;
1513 } else {
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;
1520 } else {
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)
1570 NTSTATUS status;
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);
1576 return status;
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;
1609 if (!smb2req) {
1610 return false;
1612 req = smb2req->subreq;
1613 if (!req) {
1614 return false;
1616 state = tevent_req_data(req, struct smbd_smb2_create_state);
1617 if (!state) {
1618 return false;
1620 if (!state->open_was_deferred) {
1621 return false;
1623 if (p_request_time) {
1624 *p_request_time = state->request_time;
1626 if (open_rec != NULL) {
1627 *open_rec = state->open_rec;
1629 return true;
1632 /*********************************************************
1633 Re-process this call early - requested by message or
1634 close.
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. */
1646 continue;
1648 if (!tevent_req_is_in_progress(smb2req->subreq)) {
1649 /* This message has been processed. */
1650 continue;
1652 message_id = get_mid_from_smb2req(smb2req);
1653 if (message_id == mid) {
1654 return smb2req;
1657 return NULL;
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);
1667 if (!smb2req) {
1668 DEBUG(10,("open_was_deferred_smb2: mid %llu smb2req == NULL\n",
1669 (unsigned long long)mid));
1670 return false;
1672 if (!smb2req->subreq) {
1673 return false;
1675 if (!tevent_req_is_in_progress(smb2req->subreq)) {
1676 return false;
1678 state = tevent_req_data(smb2req->subreq,
1679 struct smbd_smb2_create_state);
1680 if (!state) {
1681 return false;
1683 /* It's not in progress if there's no timeout event. */
1684 if (!state->open_was_deferred) {
1685 return false;
1688 DEBUG(10,("open_was_deferred_smb2: mid = %llu\n",
1689 (unsigned long long)mid));
1691 return true;
1694 static void remove_deferred_open_message_smb2_internal(struct smbd_smb2_request *smb2req,
1695 uint64_t mid)
1697 struct smbd_smb2_create_state *state = NULL;
1699 if (!smb2req->subreq) {
1700 return;
1702 if (!tevent_req_is_in_progress(smb2req->subreq)) {
1703 return;
1705 state = tevent_req_data(smb2req->subreq,
1706 struct smbd_smb2_create_state);
1707 if (!state) {
1708 return;
1711 DEBUG(10,("remove_deferred_open_message_smb2_internal: "
1712 "mid %llu\n",
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);
1718 TALLOC_FREE(state->open_rec);
1721 void remove_deferred_open_message_smb2(
1722 struct smbXsrv_connection *xconn, uint64_t mid)
1724 struct smbd_smb2_request *smb2req;
1726 smb2req = find_open_smb2req(xconn, mid);
1728 if (!smb2req) {
1729 DEBUG(10,("remove_deferred_open_message_smb2: "
1730 "can't find mid %llu\n",
1731 (unsigned long long)mid ));
1732 return;
1734 remove_deferred_open_message_smb2_internal(smb2req, mid);
1737 static void smbd_smb2_create_request_dispatch_immediate(struct tevent_context *ctx,
1738 struct tevent_immediate *im,
1739 void *private_data)
1741 struct smbd_smb2_request *smb2req = talloc_get_type_abort(private_data,
1742 struct smbd_smb2_request);
1743 uint64_t mid = get_mid_from_smb2req(smb2req);
1744 NTSTATUS status;
1746 DEBUG(10,("smbd_smb2_create_request_dispatch_immediate: "
1747 "re-dispatching mid %llu\n",
1748 (unsigned long long)mid ));
1750 status = smbd_smb2_request_dispatch(smb2req);
1751 if (!NT_STATUS_IS_OK(status)) {
1752 smbd_server_connection_terminate(smb2req->xconn,
1753 nt_errstr(status));
1754 return;
1758 bool schedule_deferred_open_message_smb2(
1759 struct smbXsrv_connection *xconn, uint64_t mid)
1761 struct smbd_smb2_create_state *state = NULL;
1762 struct smbd_smb2_request *smb2req;
1764 smb2req = find_open_smb2req(xconn, mid);
1766 if (!smb2req) {
1767 DEBUG(10,("schedule_deferred_open_message_smb2: "
1768 "can't find mid %llu\n",
1769 (unsigned long long)mid ));
1770 return false;
1772 if (!smb2req->subreq) {
1773 return false;
1775 if (!tevent_req_is_in_progress(smb2req->subreq)) {
1776 return false;
1778 state = tevent_req_data(smb2req->subreq,
1779 struct smbd_smb2_create_state);
1780 if (!state) {
1781 return false;
1784 /* Ensure we don't have any outstanding immediate event. */
1785 TALLOC_FREE(state->im);
1788 * This is subtle. We must null out the callback
1789 * before rescheduling, else the first call to
1790 * tevent_req_nterror() causes the _receive()
1791 * function to be called, this causing tevent_req_post()
1792 * to crash.
1794 tevent_req_set_callback(smb2req->subreq, NULL, NULL);
1796 state->im = tevent_create_immediate(smb2req);
1797 if (!state->im) {
1798 smbd_server_connection_terminate(smb2req->xconn,
1799 nt_errstr(NT_STATUS_NO_MEMORY));
1800 return false;
1803 DEBUG(10,("schedule_deferred_open_message_smb2: "
1804 "re-processing mid %llu\n",
1805 (unsigned long long)mid ));
1807 tevent_schedule_immediate(state->im,
1808 smb2req->sconn->ev_ctx,
1809 smbd_smb2_create_request_dispatch_immediate,
1810 smb2req);
1812 return true;
1815 static bool smbd_smb2_create_cancel(struct tevent_req *req)
1817 struct smbd_smb2_request *smb2req = NULL;
1818 struct smbd_smb2_create_state *state = tevent_req_data(req,
1819 struct smbd_smb2_create_state);
1820 uint64_t mid;
1822 if (!state) {
1823 return false;
1826 if (!state->smb2req) {
1827 return false;
1830 smb2req = state->smb2req;
1831 mid = get_mid_from_smb2req(smb2req);
1833 if (is_deferred_open_async(state->open_rec)) {
1834 /* Can't cancel an async create. */
1835 return false;
1838 remove_deferred_open_message_smb2_internal(smb2req, mid);
1840 tevent_req_defer_callback(req, smb2req->sconn->ev_ctx);
1841 tevent_req_nterror(req, NT_STATUS_CANCELLED);
1842 return true;
1845 bool push_deferred_open_message_smb2(struct smbd_smb2_request *smb2req,
1846 struct timeval request_time,
1847 struct timeval timeout,
1848 struct file_id id,
1849 struct deferred_open_record *open_rec)
1851 struct tevent_req *req = NULL;
1852 struct smbd_smb2_create_state *state = NULL;
1853 struct timeval end_time;
1855 if (!smb2req) {
1856 return false;
1858 req = smb2req->subreq;
1859 if (!req) {
1860 return false;
1862 state = tevent_req_data(req, struct smbd_smb2_create_state);
1863 if (!state) {
1864 return false;
1866 state->id = id;
1867 state->request_time = request_time;
1868 state->open_rec = talloc_move(state, &open_rec);
1870 /* Re-schedule us to retry on timer expiry. */
1871 end_time = timeval_sum(&request_time, &timeout);
1873 DEBUG(10,("push_deferred_open_message_smb2: "
1874 "timeout at %s\n",
1875 timeval_string(talloc_tos(),
1876 &end_time,
1877 true) ));
1879 state->open_was_deferred = true;
1881 /* allow this request to be canceled */
1882 tevent_req_set_cancel_fn(req, smbd_smb2_create_cancel);
1884 return true;