s3: smbd: Strip any leading '\\' characters if the SMB2 DFS flag is set.
[Samba.git] / source3 / smbd / smb2_create.c
blob0f18d5594a46f6541ce3d36fe007a7e93ede15c4
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 "smbd/smbXsrv_open.h"
27 #include "../libcli/smb/smb_common.h"
28 #include "../librpc/gen_ndr/ndr_security.h"
29 #include "../librpc/gen_ndr/ndr_smb2_lease_struct.h"
30 #include "../lib/util/tevent_ntstatus.h"
31 #include "messages.h"
32 #include "lib/util_ea.h"
33 #include "source3/passdb/lookup_sid.h"
35 #undef DBGC_CLASS
36 #define DBGC_CLASS DBGC_SMB2
38 int map_smb2_oplock_levels_to_samba(uint8_t in_oplock_level)
40 switch(in_oplock_level) {
41 case SMB2_OPLOCK_LEVEL_NONE:
42 return NO_OPLOCK;
43 case SMB2_OPLOCK_LEVEL_II:
44 return LEVEL_II_OPLOCK;
45 case SMB2_OPLOCK_LEVEL_EXCLUSIVE:
46 return EXCLUSIVE_OPLOCK;
47 case SMB2_OPLOCK_LEVEL_BATCH:
48 return BATCH_OPLOCK;
49 case SMB2_OPLOCK_LEVEL_LEASE:
50 return LEASE_OPLOCK;
51 default:
52 DEBUG(2,("map_smb2_oplock_levels_to_samba: "
53 "unknown level %u\n",
54 (unsigned int)in_oplock_level));
55 return NO_OPLOCK;
59 static uint8_t map_samba_oplock_levels_to_smb2(int oplock_type)
61 if (BATCH_OPLOCK_TYPE(oplock_type)) {
62 return SMB2_OPLOCK_LEVEL_BATCH;
63 } else if (EXCLUSIVE_OPLOCK_TYPE(oplock_type)) {
64 return SMB2_OPLOCK_LEVEL_EXCLUSIVE;
65 } else if (oplock_type == LEVEL_II_OPLOCK) {
66 return SMB2_OPLOCK_LEVEL_II;
67 } else if (oplock_type == LEASE_OPLOCK) {
68 return SMB2_OPLOCK_LEVEL_LEASE;
69 } else {
70 return SMB2_OPLOCK_LEVEL_NONE;
75 MS-FSA 2.1.5.1 Server Requests an Open of a File
76 Trailing '/' or '\\' checker.
77 Must be done before the filename parser removes any
78 trailing characters. If we decide to add this to SMB1
79 NTCreate processing we can make this public.
81 Note this is Windows pathname processing only. When
82 POSIX pathnames are added to SMB2 this will not apply.
85 static NTSTATUS windows_name_trailing_check(const char *name,
86 uint32_t create_options)
88 size_t name_len = strlen(name);
89 char trail_c;
91 if (name_len <= 1) {
92 return NT_STATUS_OK;
95 trail_c = name[name_len-1];
98 * Trailing '/' is always invalid.
100 if (trail_c == '/') {
101 return NT_STATUS_OBJECT_NAME_INVALID;
104 if (create_options & FILE_NON_DIRECTORY_FILE) {
105 if (trail_c == '\\') {
106 return NT_STATUS_OBJECT_NAME_INVALID;
109 return NT_STATUS_OK;
112 static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
113 struct tevent_context *ev,
114 struct smbd_smb2_request *smb2req,
115 uint8_t in_oplock_level,
116 uint32_t in_impersonation_level,
117 uint32_t in_desired_access,
118 uint32_t in_file_attributes,
119 uint32_t in_share_access,
120 uint32_t in_create_disposition,
121 uint32_t in_create_options,
122 const char *in_name,
123 struct smb2_create_blobs in_context_blobs);
124 static NTSTATUS smbd_smb2_create_recv(struct tevent_req *req,
125 TALLOC_CTX *mem_ctx,
126 uint8_t *out_oplock_level,
127 uint32_t *out_create_action,
128 struct timespec *out_creation_ts,
129 struct timespec *out_last_access_ts,
130 struct timespec *out_last_write_ts,
131 struct timespec *out_change_ts,
132 uint64_t *out_allocation_size,
133 uint64_t *out_end_of_file,
134 uint32_t *out_file_attributes,
135 uint64_t *out_file_id_persistent,
136 uint64_t *out_file_id_volatile,
137 struct smb2_create_blobs *out_context_blobs);
139 static void smbd_smb2_request_create_done(struct tevent_req *tsubreq);
140 NTSTATUS smbd_smb2_request_process_create(struct smbd_smb2_request *smb2req)
142 const uint8_t *inbody;
143 const struct iovec *indyniov;
144 uint8_t in_oplock_level;
145 uint32_t in_impersonation_level;
146 uint32_t in_desired_access;
147 uint32_t in_file_attributes;
148 uint32_t in_share_access;
149 uint32_t in_create_disposition;
150 uint32_t in_create_options;
151 uint16_t in_name_offset;
152 uint16_t in_name_length;
153 DATA_BLOB in_name_buffer;
154 char *in_name_string;
155 size_t in_name_string_size;
156 uint32_t name_offset = 0;
157 uint32_t name_available_length = 0;
158 uint32_t in_context_offset;
159 uint32_t in_context_length;
160 DATA_BLOB in_context_buffer;
161 struct smb2_create_blobs in_context_blobs;
162 uint32_t context_offset = 0;
163 uint32_t context_available_length = 0;
164 uint32_t dyn_offset;
165 NTSTATUS status;
166 bool ok;
167 struct tevent_req *tsubreq;
169 status = smbd_smb2_request_verify_sizes(smb2req, 0x39);
170 if (!NT_STATUS_IS_OK(status)) {
171 return smbd_smb2_request_error(smb2req, status);
173 inbody = SMBD_SMB2_IN_BODY_PTR(smb2req);
175 in_oplock_level = CVAL(inbody, 0x03);
176 in_impersonation_level = IVAL(inbody, 0x04);
177 in_desired_access = IVAL(inbody, 0x18);
178 in_file_attributes = IVAL(inbody, 0x1C);
179 in_share_access = IVAL(inbody, 0x20);
180 in_create_disposition = IVAL(inbody, 0x24);
181 in_create_options = IVAL(inbody, 0x28);
182 in_name_offset = SVAL(inbody, 0x2C);
183 in_name_length = SVAL(inbody, 0x2E);
184 in_context_offset = IVAL(inbody, 0x30);
185 in_context_length = IVAL(inbody, 0x34);
188 * First check if the dynamic name and context buffers
189 * are correctly specified.
191 * Note: That we don't check if the name and context buffers
192 * overlap
195 dyn_offset = SMB2_HDR_BODY + SMBD_SMB2_IN_BODY_LEN(smb2req);
197 if (in_name_offset == 0 && in_name_length == 0) {
198 /* This is ok */
199 name_offset = 0;
200 } else if (in_name_offset < dyn_offset) {
201 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
202 } else {
203 name_offset = in_name_offset - dyn_offset;
206 indyniov = SMBD_SMB2_IN_DYN_IOV(smb2req);
208 if (name_offset > indyniov->iov_len) {
209 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
212 name_available_length = indyniov->iov_len - name_offset;
214 if (in_name_length > name_available_length) {
215 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
218 in_name_buffer.data = (uint8_t *)indyniov->iov_base + name_offset;
219 in_name_buffer.length = in_name_length;
221 if (in_context_offset == 0 && in_context_length == 0) {
222 /* This is ok */
223 context_offset = 0;
224 } else if (in_context_offset < dyn_offset) {
225 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
226 } else {
227 context_offset = in_context_offset - dyn_offset;
230 if (context_offset > indyniov->iov_len) {
231 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
234 context_available_length = indyniov->iov_len - context_offset;
236 if (in_context_length > context_available_length) {
237 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
240 in_context_buffer.data = (uint8_t *)indyniov->iov_base +
241 context_offset;
242 in_context_buffer.length = in_context_length;
245 * Now interpret the name and context buffers
248 ok = convert_string_talloc(smb2req, CH_UTF16, CH_UNIX,
249 in_name_buffer.data,
250 in_name_buffer.length,
251 &in_name_string,
252 &in_name_string_size);
253 if (!ok) {
254 return smbd_smb2_request_error(smb2req, NT_STATUS_ILLEGAL_CHARACTER);
257 if (in_name_buffer.length == 0) {
258 in_name_string_size = 0;
261 if (strlen(in_name_string) != in_name_string_size) {
262 return smbd_smb2_request_error(smb2req, NT_STATUS_OBJECT_NAME_INVALID);
265 ZERO_STRUCT(in_context_blobs);
266 status = smb2_create_blob_parse(smb2req, in_context_buffer, &in_context_blobs);
267 if (!NT_STATUS_IS_OK(status)) {
268 return smbd_smb2_request_error(smb2req, status);
271 tsubreq = smbd_smb2_create_send(smb2req,
272 smb2req->sconn->ev_ctx,
273 smb2req,
274 in_oplock_level,
275 in_impersonation_level,
276 in_desired_access,
277 in_file_attributes,
278 in_share_access,
279 in_create_disposition,
280 in_create_options,
281 in_name_string,
282 in_context_blobs);
283 if (tsubreq == NULL) {
284 smb2req->subreq = NULL;
285 return smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
287 tevent_req_set_callback(tsubreq, smbd_smb2_request_create_done, smb2req);
289 return smbd_smb2_request_pending_queue(smb2req, tsubreq, 500);
292 static uint64_t get_mid_from_smb2req(struct smbd_smb2_request *smb2req)
294 uint8_t *reqhdr = SMBD_SMB2_OUT_HDR_PTR(smb2req);
295 return BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
298 static void smbd_smb2_request_create_done(struct tevent_req *tsubreq)
300 struct smbd_smb2_request *smb2req = tevent_req_callback_data(tsubreq,
301 struct smbd_smb2_request);
302 DATA_BLOB outbody;
303 DATA_BLOB outdyn;
304 uint8_t out_oplock_level = 0;
305 uint32_t out_create_action = 0;
306 connection_struct *conn = smb2req->tcon->compat;
307 struct timespec out_creation_ts = { 0, };
308 struct timespec out_last_access_ts = { 0, };
309 struct timespec out_last_write_ts = { 0, };
310 struct timespec out_change_ts = { 0, };
311 uint64_t out_allocation_size = 0;
312 uint64_t out_end_of_file = 0;
313 uint32_t out_file_attributes = 0;
314 uint64_t out_file_id_persistent = 0;
315 uint64_t out_file_id_volatile = 0;
316 struct smb2_create_blobs out_context_blobs;
317 DATA_BLOB out_context_buffer;
318 uint16_t out_context_buffer_offset = 0;
319 NTSTATUS status;
320 NTSTATUS error; /* transport error */
322 status = smbd_smb2_create_recv(tsubreq,
323 smb2req,
324 &out_oplock_level,
325 &out_create_action,
326 &out_creation_ts,
327 &out_last_access_ts,
328 &out_last_write_ts,
329 &out_change_ts,
330 &out_allocation_size,
331 &out_end_of_file,
332 &out_file_attributes,
333 &out_file_id_persistent,
334 &out_file_id_volatile,
335 &out_context_blobs);
336 if (!NT_STATUS_IS_OK(status)) {
337 if (smbd_smb2_is_compound(smb2req)) {
338 smb2req->compound_create_err = status;
340 error = smbd_smb2_request_error(smb2req, status);
341 if (!NT_STATUS_IS_OK(error)) {
342 smbd_server_connection_terminate(smb2req->xconn,
343 nt_errstr(error));
344 return;
346 return;
349 status = smb2_create_blob_push(smb2req, &out_context_buffer, out_context_blobs);
350 if (!NT_STATUS_IS_OK(status)) {
351 error = smbd_smb2_request_error(smb2req, status);
352 if (!NT_STATUS_IS_OK(error)) {
353 smbd_server_connection_terminate(smb2req->xconn,
354 nt_errstr(error));
355 return;
357 return;
360 if (out_context_buffer.length > 0) {
361 out_context_buffer_offset = SMB2_HDR_BODY + 0x58;
364 outbody = smbd_smb2_generate_outbody(smb2req, 0x58);
365 if (outbody.data == NULL) {
366 error = smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
367 if (!NT_STATUS_IS_OK(error)) {
368 smbd_server_connection_terminate(smb2req->xconn,
369 nt_errstr(error));
370 return;
372 return;
375 SSVAL(outbody.data, 0x00, 0x58 + 1); /* struct size */
376 SCVAL(outbody.data, 0x02,
377 out_oplock_level); /* oplock level */
378 SCVAL(outbody.data, 0x03, 0); /* reserved */
379 SIVAL(outbody.data, 0x04,
380 out_create_action); /* create action */
381 put_long_date_full_timespec(conn->ts_res,
382 (char *)outbody.data + 0x08,
383 &out_creation_ts); /* creation time */
384 put_long_date_full_timespec(conn->ts_res,
385 (char *)outbody.data + 0x10,
386 &out_last_access_ts); /* last access time */
387 put_long_date_full_timespec(conn->ts_res,
388 (char *)outbody.data + 0x18,
389 &out_last_write_ts); /* last write time */
390 put_long_date_full_timespec(conn->ts_res,
391 (char *)outbody.data + 0x20,
392 &out_change_ts); /* change time */
393 SBVAL(outbody.data, 0x28,
394 out_allocation_size); /* allocation size */
395 SBVAL(outbody.data, 0x30,
396 out_end_of_file); /* end of file */
397 SIVAL(outbody.data, 0x38,
398 out_file_attributes); /* file attributes */
399 SIVAL(outbody.data, 0x3C, 0); /* reserved */
400 SBVAL(outbody.data, 0x40,
401 out_file_id_persistent); /* file id (persistent) */
402 SBVAL(outbody.data, 0x48,
403 out_file_id_volatile); /* file id (volatile) */
404 SIVAL(outbody.data, 0x50,
405 out_context_buffer_offset); /* create contexts offset */
406 SIVAL(outbody.data, 0x54,
407 out_context_buffer.length); /* create contexts length */
409 outdyn = out_context_buffer;
411 error = smbd_smb2_request_done(smb2req, outbody, &outdyn);
412 if (!NT_STATUS_IS_OK(error)) {
413 smbd_server_connection_terminate(smb2req->xconn,
414 nt_errstr(error));
415 return;
419 static bool smb2_lease_key_valid(const struct smb2_lease_key *key)
421 return ((key->data[0] != 0) || (key->data[1] != 0));
424 static NTSTATUS smbd_smb2_create_durable_lease_check(struct smb_request *smb1req,
425 const char *requested_filename, const struct files_struct *fsp,
426 const struct smb2_lease *lease_ptr)
428 struct files_struct *dirfsp = NULL;
429 char *filename = NULL;
430 struct smb_filename *smb_fname = NULL;
431 uint32_t ucf_flags;
432 NTTIME twrp = fsp->fsp_name->twrp;
433 NTSTATUS status;
434 bool is_dfs = (smb1req->flags2 & FLAGS2_DFS_PATHNAMES);
436 if (lease_ptr == NULL) {
437 if (fsp->oplock_type != LEASE_OPLOCK) {
438 return NT_STATUS_OK;
440 DEBUG(10, ("Reopened file has lease, but no lease "
441 "requested\n"));
442 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
445 if (fsp->oplock_type != LEASE_OPLOCK) {
446 DEBUG(10, ("Lease requested, but reopened file has no "
447 "lease\n"));
448 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
451 if (!smb2_lease_key_equal(&lease_ptr->lease_key,
452 &fsp->lease->lease.lease_key)) {
453 DEBUG(10, ("Different lease key requested than found "
454 "in reopened file\n"));
455 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
458 filename = talloc_strdup(talloc_tos(), requested_filename);
459 if (filename == NULL) {
460 return NT_STATUS_NO_MEMORY;
463 /* This also converts '\' to '/' */
464 status = check_path_syntax_smb2(filename, is_dfs);
465 if (!NT_STATUS_IS_OK(status)) {
466 TALLOC_FREE(filename);
467 return status;
470 ucf_flags = filename_create_ucf_flags(smb1req, FILE_OPEN);
471 status = filename_convert_dirfsp(talloc_tos(),
472 fsp->conn,
473 filename,
474 ucf_flags,
475 twrp,
476 &dirfsp,
477 &smb_fname);
478 TALLOC_FREE(filename);
479 if (!NT_STATUS_IS_OK(status)) {
480 DEBUG(10, ("filename_convert returned %s\n",
481 nt_errstr(status)));
482 return status;
485 if (!strequal(fsp->fsp_name->base_name, smb_fname->base_name)) {
486 DEBUG(10, ("Lease requested for file %s, reopened file "
487 "is named %s\n", smb_fname->base_name,
488 fsp->fsp_name->base_name));
489 TALLOC_FREE(smb_fname);
490 return NT_STATUS_INVALID_PARAMETER;
493 TALLOC_FREE(smb_fname);
495 return NT_STATUS_OK;
498 struct smbd_smb2_create_state {
499 struct tevent_context *ev;
500 struct smbd_smb2_request *smb2req;
501 struct GUID req_guid;
502 struct smb_request *smb1req;
503 bool open_was_deferred;
504 struct tevent_immediate *im;
505 struct timeval request_time;
506 struct file_id id;
507 struct deferred_open_record *open_rec;
508 files_struct *result;
509 bool replay_operation;
510 uint8_t in_oplock_level;
511 uint32_t in_create_disposition;
512 int requested_oplock_level;
513 int info;
514 char *fname;
515 struct ea_list *ea_list;
516 NTTIME max_access_time;
517 struct security_descriptor *sec_desc;
518 uint64_t allocation_size;
519 struct GUID _create_guid;
520 struct GUID *create_guid;
521 struct GUID _purge_create_guid;
522 struct GUID *purge_create_guid;
523 bool update_open;
524 bool durable_requested;
525 uint32_t durable_timeout_msec;
526 bool do_durable_reconnect;
527 uint64_t persistent_id;
528 struct smb2_lease lease;
529 struct smb2_lease *lease_ptr;
530 ssize_t lease_len;
531 bool need_replay_cache;
532 struct smbXsrv_open *op;
533 NTTIME twrp_time;
535 struct smb2_create_blob *dhnc;
536 struct smb2_create_blob *dh2c;
537 struct smb2_create_blob *dhnq;
538 struct smb2_create_blob *dh2q;
539 struct smb2_create_blob *rqls;
540 struct smb2_create_blob *exta;
541 struct smb2_create_blob *mxac;
542 struct smb2_create_blob *secd;
543 struct smb2_create_blob *alsi;
544 struct smb2_create_blob *twrp;
545 struct smb2_create_blob *qfid;
546 struct smb2_create_blob *posx;
547 struct smb2_create_blob *svhdx;
549 uint8_t out_oplock_level;
550 uint32_t out_create_action;
551 struct timespec out_creation_ts;
552 struct timespec out_last_access_ts;
553 struct timespec out_last_write_ts;
554 struct timespec out_change_ts;
555 uint64_t out_allocation_size;
556 uint64_t out_end_of_file;
557 uint32_t out_file_attributes;
558 uint64_t out_file_id_persistent;
559 uint64_t out_file_id_volatile;
560 struct smb2_create_blobs *out_context_blobs;
563 static void smbd_smb2_create_purge_replay_cache(struct tevent_req *req,
564 const char *caller_func);
566 static void smbd_smb2_create_cleanup(struct tevent_req *req,
567 enum tevent_req_state req_state)
569 smbd_smb2_create_purge_replay_cache(req, __func__);
572 static NTSTATUS smbd_smb2_create_fetch_create_ctx(
573 struct tevent_req *req,
574 struct smb2_create_blobs *in_context_blobs)
576 struct smbd_smb2_create_state *state = tevent_req_data(
577 req, struct smbd_smb2_create_state);
578 struct smbd_smb2_request *smb2req = state->smb2req;
579 struct smbXsrv_connection *xconn = smb2req->xconn;
581 state->dhnq = smb2_create_blob_find(in_context_blobs,
582 SMB2_CREATE_TAG_DHNQ);
583 state->dhnc = smb2_create_blob_find(in_context_blobs,
584 SMB2_CREATE_TAG_DHNC);
585 state->dh2q = smb2_create_blob_find(in_context_blobs,
586 SMB2_CREATE_TAG_DH2Q);
587 state->dh2c = smb2_create_blob_find(in_context_blobs,
588 SMB2_CREATE_TAG_DH2C);
589 if (xconn->smb2.server.capabilities & SMB2_CAP_LEASING) {
590 state->rqls = smb2_create_blob_find(in_context_blobs,
591 SMB2_CREATE_TAG_RQLS);
594 if (((state->dhnc != NULL) && (state->dh2c != NULL)) ||
595 ((state->dhnc != NULL) && (state->dh2q != NULL)) ||
596 ((state->dh2c != NULL) && (state->dhnq != NULL)) ||
597 ((state->dh2q != NULL) && (state->dh2c != NULL)))
599 /* not both are allowed at the same time */
600 return NT_STATUS_INVALID_PARAMETER;
603 if (state->dhnc != NULL) {
604 uint32_t num_blobs_allowed;
606 if (state->dhnc->data.length != 16) {
607 return NT_STATUS_INVALID_PARAMETER;
611 * According to MS-SMB2: 3.3.5.9.7, "Handling the
612 * SMB2_CREATE_DURABLE_HANDLE_RECONNECT Create Context",
613 * we should ignore an additional dhnq blob, but fail
614 * the request (with status OBJECT_NAME_NOT_FOUND) if
615 * any other extra create blob has been provided.
617 * (Note that the cases of an additional dh2q or dh2c blob
618 * which require a different error code, have been treated
619 * above.)
622 if (state->dhnq != NULL) {
623 num_blobs_allowed = 2;
624 } else {
625 num_blobs_allowed = 1;
628 if (state->rqls != NULL) {
629 num_blobs_allowed += 1;
632 if (in_context_blobs->num_blobs != num_blobs_allowed) {
633 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
637 if (state->dh2c!= NULL) {
638 uint32_t num_blobs_allowed;
640 if (state->dh2c->data.length != 36) {
641 return NT_STATUS_INVALID_PARAMETER;
645 * According to MS-SMB2: 3.3.5.9.12, "Handling the
646 * SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 Create Context",
647 * we should fail the request with status
648 * OBJECT_NAME_NOT_FOUND if any other create blob has been
649 * provided.
651 * (Note that the cases of an additional dhnq, dhnc or dh2q
652 * blob which require a different error code, have been
653 * treated above.)
656 num_blobs_allowed = 1;
658 if (state->rqls != NULL) {
659 num_blobs_allowed += 1;
662 if (in_context_blobs->num_blobs != num_blobs_allowed) {
663 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
667 state->exta = smb2_create_blob_find(in_context_blobs,
668 SMB2_CREATE_TAG_EXTA);
669 state->mxac = smb2_create_blob_find(in_context_blobs,
670 SMB2_CREATE_TAG_MXAC);
671 state->secd = smb2_create_blob_find(in_context_blobs,
672 SMB2_CREATE_TAG_SECD);
673 state->alsi = smb2_create_blob_find(in_context_blobs,
674 SMB2_CREATE_TAG_ALSI);
675 state->twrp = smb2_create_blob_find(in_context_blobs,
676 SMB2_CREATE_TAG_TWRP);
677 state->qfid = smb2_create_blob_find(in_context_blobs,
678 SMB2_CREATE_TAG_QFID);
679 if (xconn->protocol >= PROTOCOL_SMB3_02) {
681 * This was introduced with SMB3_02
683 state->svhdx = smb2_create_blob_find(
684 in_context_blobs, SVHDX_OPEN_DEVICE_CONTEXT);
686 if (xconn->smb2.server.posix_extensions_negotiated) {
688 * Negprot only allowed this for proto>=3.11
690 SMB_ASSERT(xconn->protocol >= PROTOCOL_SMB3_11);
692 state->posx = smb2_create_blob_find(
693 in_context_blobs, SMB2_CREATE_TAG_POSIX);
696 return NT_STATUS_OK;
699 static void smbd_smb2_create_before_exec(struct tevent_req *req);
700 static void smbd_smb2_create_after_exec(struct tevent_req *req);
701 static void smbd_smb2_create_finish(struct tevent_req *req);
703 static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
704 struct tevent_context *ev,
705 struct smbd_smb2_request *smb2req,
706 uint8_t in_oplock_level,
707 uint32_t in_impersonation_level,
708 uint32_t in_desired_access,
709 uint32_t in_file_attributes,
710 uint32_t in_share_access,
711 uint32_t in_create_disposition,
712 uint32_t in_create_options,
713 const char *in_name,
714 struct smb2_create_blobs in_context_blobs)
716 struct tevent_req *req = NULL;
717 struct smbd_smb2_create_state *state = NULL;
718 NTSTATUS status;
719 struct smb_request *smb1req = NULL;
720 struct files_struct *dirfsp = NULL;
721 struct smb_filename *smb_fname = NULL;
722 uint32_t ucf_flags;
723 bool is_dfs = false;
725 req = tevent_req_create(mem_ctx, &state,
726 struct smbd_smb2_create_state);
727 if (req == NULL) {
728 return NULL;
730 *state = (struct smbd_smb2_create_state) {
731 .ev = ev,
732 .smb2req = smb2req,
733 .in_oplock_level = in_oplock_level,
734 .in_create_disposition = in_create_disposition,
737 smb1req = smbd_smb2_fake_smb_request(smb2req);
738 if (tevent_req_nomem(smb1req, req)) {
739 return tevent_req_post(req, state->ev);
741 state->smb1req = smb1req;
743 state->req_guid = smbd_request_guid(smb1req, 0);
745 tevent_req_set_cleanup_fn(req, smbd_smb2_create_cleanup);
747 if (smb2req->subreq == NULL) {
748 DBG_DEBUG("name [%s]\n", in_name);
749 } else {
750 struct smbd_smb2_create_state *old_state = tevent_req_data(
751 smb2req->subreq, struct smbd_smb2_create_state);
753 DBG_DEBUG("reentrant for file %s\n", in_name);
755 state->id = old_state->id;
756 state->request_time = old_state->request_time;
757 state->open_rec = talloc_move(state, &old_state->open_rec);
758 state->open_was_deferred = old_state->open_was_deferred;
759 state->_purge_create_guid = old_state->_purge_create_guid;
760 state->purge_create_guid = old_state->purge_create_guid;
761 old_state->purge_create_guid = NULL;
764 TALLOC_FREE(smb2req->subreq);
765 smb2req->subreq = req;
767 if (lp_fake_oplocks(SNUM(smb2req->tcon->compat))) {
768 state->requested_oplock_level = SMB2_OPLOCK_LEVEL_NONE;
769 } else {
770 state->requested_oplock_level = state->in_oplock_level;
773 /* these are ignored for SMB2 */
774 in_create_options &= ~(0x10);/* NTCREATEX_OPTIONS_SYNC_ALERT */
775 in_create_options &= ~(0x20);/* NTCREATEX_OPTIONS_ASYNC_ALERT */
777 in_file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS;
779 is_dfs = (smb1req->flags2 & FLAGS2_DFS_PATHNAMES);
780 if (is_dfs) {
782 * With a DFS flag set, remove any leading '\\'
783 * characters from in_name before further processing.
785 while (in_name[0] == '\\') {
786 in_name++;
790 state->fname = talloc_strdup(state, in_name);
791 if (tevent_req_nomem(state->fname, req)) {
792 return tevent_req_post(req, state->ev);
795 state->out_context_blobs = talloc_zero(state, struct smb2_create_blobs);
796 if (tevent_req_nomem(state->out_context_blobs, req)) {
797 return tevent_req_post(req, state->ev);
800 status = smbd_smb2_create_fetch_create_ctx(req, &in_context_blobs);
801 if (tevent_req_nterror(req, status)) {
802 return tevent_req_post(req, state->ev);
805 if (IS_IPC(smb1req->conn)) {
806 const char *pipe_name = in_name;
808 if (state->dhnc != NULL || state->dh2c != NULL) {
809 /* durable handles are not supported on IPC$ */
810 tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
811 return tevent_req_post(req, state->ev);
814 if (!lp_nt_pipe_support()) {
815 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
816 return tevent_req_post(req, state->ev);
819 status = open_np_file(smb1req, pipe_name, &state->result);
820 if (tevent_req_nterror(req, status)) {
821 return tevent_req_post(req, state->ev);
823 state->info = FILE_WAS_OPENED;
825 smbd_smb2_create_finish(req);
826 return req;
829 if (CAN_PRINT(smb1req->conn)) {
830 if (state->dhnc != NULL || state->dh2c != NULL) {
831 /* durable handles are not supported on printers */
832 tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
833 return tevent_req_post(req, state->ev);
836 status = file_new(smb1req, smb1req->conn, &state->result);
837 if (tevent_req_nterror(req, status)) {
838 return tevent_req_post(req, state->ev);
841 status = print_spool_open(state->result, in_name,
842 smb1req->vuid);
843 if (tevent_req_nterror(req, status)) {
844 file_free(smb1req, state->result);
845 return tevent_req_post(req, state->ev);
847 state->info = FILE_WAS_CREATED;
849 smbd_smb2_create_finish(req);
850 return req;
853 /* Check for trailing slash specific directory handling. */
854 status = windows_name_trailing_check(state->fname, in_create_options);
855 if (tevent_req_nterror(req, status)) {
856 return tevent_req_post(req, state->ev);
859 smbd_smb2_create_before_exec(req);
860 if (!tevent_req_is_in_progress(req)) {
861 return tevent_req_post(req, state->ev);
864 DBG_DEBUG("open execution phase\n");
867 * For the backend file open procedure, there are
868 * three possible modes: replay operation (in which case
869 * there is nothing else to do), durable_reconnect or
870 * new open.
872 if (state->replay_operation) {
873 state->result = state->op->compat;
874 state->result->op = state->op;
875 state->update_open = false;
876 state->info = state->op->create_action;
878 smbd_smb2_create_after_exec(req);
879 if (!tevent_req_is_in_progress(req)) {
880 return req;
883 smbd_smb2_create_finish(req);
884 return req;
887 if (state->do_durable_reconnect) {
888 DATA_BLOB new_cookie = data_blob_null;
889 NTTIME now = timeval_to_nttime(&smb2req->request_time);
891 status = smb2srv_open_recreate(smb2req->xconn,
892 smb1req->conn->session_info,
893 state->persistent_id,
894 state->create_guid,
895 now,
896 &state->op);
897 if (tevent_req_nterror(req, status)) {
898 DBG_NOTICE("smb2srv_open_recreate failed: %s\n",
899 nt_errstr(status));
900 return tevent_req_post(req, state->ev);
903 DBG_DEBUG("%s to recreate durable handle\n",
904 state->op->global->durable ? "succeeded" : "failed");
906 if (!state->op->global->durable) {
907 talloc_free(state->op);
908 tevent_req_nterror(req,
909 NT_STATUS_OBJECT_NAME_NOT_FOUND);
910 return tevent_req_post(req, state->ev);
913 status = SMB_VFS_DURABLE_RECONNECT(smb1req->conn,
914 smb1req,
915 state->op, /* smbXsrv_open input */
916 state->op->global->backend_cookie,
917 state->op, /* TALLOC_CTX */
918 &state->result,
919 &new_cookie);
920 if (!NT_STATUS_IS_OK(status)) {
921 NTSTATUS return_status;
923 return_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
925 DBG_NOTICE("durable_reconnect failed: %s => %s\n",
926 nt_errstr(status),
927 nt_errstr(return_status));
929 tevent_req_nterror(req, return_status);
930 return tevent_req_post(req, state->ev);
933 DBG_DEBUG("oplock_type=%u, lease_ptr==%p\n",
934 (unsigned)state->result->oplock_type, state->lease_ptr);
936 status = smbd_smb2_create_durable_lease_check(
937 smb1req, state->fname, state->result, state->lease_ptr);
938 if (tevent_req_nterror(req, status)) {
939 close_file_free(
940 smb1req, &state->result, SHUTDOWN_CLOSE);
941 return tevent_req_post(req, state->ev);
944 data_blob_free(&state->op->global->backend_cookie);
945 state->op->global->backend_cookie = new_cookie;
947 state->op->status = NT_STATUS_OK;
948 state->op->global->disconnect_time = 0;
950 /* save the timout for later update */
951 state->durable_timeout_msec = state->op->global->durable_timeout_msec;
953 state->update_open = true;
955 state->info = FILE_WAS_OPENED;
957 smbd_smb2_create_after_exec(req);
958 if (!tevent_req_is_in_progress(req)) {
959 return req;
962 smbd_smb2_create_finish(req);
963 return req;
966 if (state->requested_oplock_level == SMB2_OPLOCK_LEVEL_LEASE) {
967 if (state->lease_ptr == NULL) {
968 state->requested_oplock_level = SMB2_OPLOCK_LEVEL_NONE;
970 } else {
971 state->lease_ptr = NULL;
974 /* convert '\\' into '/' */
975 status = check_path_syntax_smb2(state->fname, is_dfs);
976 if (tevent_req_nterror(req, status)) {
977 return tevent_req_post(req, state->ev);
980 ucf_flags = filename_create_ucf_flags(
981 smb1req, state->in_create_disposition);
983 status = filename_convert_dirfsp(
984 req,
985 smb1req->conn,
986 state->fname,
987 ucf_flags,
988 state->twrp_time,
989 &dirfsp,
990 &smb_fname);
991 if (tevent_req_nterror(req, status)) {
992 return tevent_req_post(req, state->ev);
996 * MS-SMB2: 2.2.13 SMB2 CREATE Request
997 * ImpersonationLevel ... MUST contain one of the
998 * following values. The server MUST validate this
999 * field, but otherwise ignore it.
1001 * NB. The source4/torture/smb2/durable_open.c test
1002 * shows this check is only done on real opens, not
1003 * on durable handle-reopens.
1006 if (in_impersonation_level >
1007 SMB2_IMPERSONATION_DELEGATE) {
1008 tevent_req_nterror(req,
1009 NT_STATUS_BAD_IMPERSONATION_LEVEL);
1010 return tevent_req_post(req, state->ev);
1014 * We know we're going to do a local open, so now
1015 * we must be protocol strict. JRA.
1017 * MS-SMB2: 3.3.5.9 - Receiving an SMB2 CREATE Request
1018 * If the file name length is greater than zero and the
1019 * first character is a path separator character, the
1020 * server MUST fail the request with
1021 * STATUS_INVALID_PARAMETER.
1023 if (in_name[0] == '\\' || in_name[0] == '/') {
1024 tevent_req_nterror(req,
1025 NT_STATUS_INVALID_PARAMETER);
1026 return tevent_req_post(req, state->ev);
1029 status = SMB_VFS_CREATE_FILE(smb1req->conn,
1030 smb1req,
1031 dirfsp,
1032 smb_fname,
1033 in_desired_access,
1034 in_share_access,
1035 state->in_create_disposition,
1036 in_create_options,
1037 in_file_attributes,
1038 map_smb2_oplock_levels_to_samba(
1039 state->requested_oplock_level),
1040 state->lease_ptr,
1041 state->allocation_size,
1042 0, /* private_flags */
1043 state->sec_desc,
1044 state->ea_list,
1045 &state->result,
1046 &state->info,
1047 &in_context_blobs,
1048 state->out_context_blobs);
1049 if (!NT_STATUS_IS_OK(status)) {
1050 if (open_was_deferred(smb1req->xconn, smb1req->mid)) {
1051 SMBPROFILE_IOBYTES_ASYNC_SET_IDLE(smb2req->profile);
1052 return req;
1054 tevent_req_nterror(req, status);
1055 return tevent_req_post(req, state->ev);
1057 state->op = state->result->op;
1059 smbd_smb2_create_after_exec(req);
1060 if (!tevent_req_is_in_progress(req)) {
1061 return req;
1064 smbd_smb2_create_finish(req);
1065 return req;
1068 static void smbd_smb2_create_purge_replay_cache(struct tevent_req *req,
1069 const char *caller_func)
1071 struct smbd_smb2_create_state *state = tevent_req_data(
1072 req, struct smbd_smb2_create_state);
1073 NTSTATUS status;
1075 if (state->purge_create_guid == NULL) {
1076 return;
1079 status = smbXsrv_open_purge_replay_cache(state->smb2req->xconn->client,
1080 state->purge_create_guid);
1081 if (!NT_STATUS_IS_OK(status)) {
1082 struct GUID_txt_buf buf;
1084 D_ERR("%s: smbXsrv_open_purge_replay_cache(%s) %s\n",
1085 caller_func,
1086 GUID_buf_string(state->purge_create_guid, &buf),
1087 nt_errstr(status));
1090 state->purge_create_guid = NULL;
1093 static void smbd_smb2_create_before_exec(struct tevent_req *req)
1095 struct smbd_smb2_create_state *state = tevent_req_data(
1096 req, struct smbd_smb2_create_state);
1097 struct smbd_smb2_request *smb2req = state->smb2req;
1098 NTSTATUS status;
1100 if (state->exta != NULL) {
1101 if (!lp_ea_support(SNUM(smb2req->tcon->compat))) {
1102 tevent_req_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1103 return;
1106 state->ea_list = read_nttrans_ea_list(
1107 state,
1108 (const char *)state->exta->data.data,
1109 state->exta->data.length);
1110 if (state->ea_list == NULL) {
1111 DEBUG(10,("smbd_smb2_create_send: read_ea_name_list failed.\n"));
1112 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1113 return;
1117 * NB. When SMB2+ unix extensions are added,
1118 * we need to relax this check in invalid
1119 * names - we used to not do this if
1120 * lp_posix_pathnames() was false.
1122 if (ea_list_has_invalid_name(state->ea_list)) {
1123 tevent_req_nterror(req, STATUS_INVALID_EA_NAME);
1124 return;
1128 if (state->mxac != NULL) {
1129 if (state->mxac->data.length == 0) {
1130 state->max_access_time = 0;
1131 } else if (state->mxac->data.length == 8) {
1132 state->max_access_time = BVAL(state->mxac->data.data, 0);
1133 } else {
1134 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1135 return;
1139 if (state->secd != NULL) {
1140 enum ndr_err_code ndr_err;
1142 state->sec_desc = talloc_zero(state, struct security_descriptor);
1143 if (tevent_req_nomem(state->sec_desc, req)) {
1144 return;
1147 ndr_err = ndr_pull_struct_blob(&state->secd->data,
1148 state->sec_desc, state->sec_desc,
1149 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
1150 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1151 DEBUG(2,("ndr_pull_security_descriptor failed: %s\n",
1152 ndr_errstr(ndr_err)));
1153 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1154 return;
1158 if (state->dhnq != NULL) {
1159 if (state->dhnq->data.length != 16) {
1160 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1161 return;
1164 if (state->dh2q != NULL) {
1165 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1166 return;
1170 * durable handle request is processed below.
1172 state->durable_requested = true;
1174 * Set the timeout to 16 mins.
1176 * TODO: test this against Windows 2012
1177 * as the default for durable v2 is 1 min.
1179 state->durable_timeout_msec = (16*60*1000);
1182 if (state->dh2q != NULL) {
1183 const uint8_t *p = state->dh2q->data.data;
1184 NTTIME now = timeval_to_nttime(&smb2req->request_time);
1185 uint32_t durable_v2_timeout = 0;
1186 DATA_BLOB create_guid_blob;
1187 const uint8_t *hdr;
1188 uint32_t flags;
1190 if (state->dh2q->data.length != 32) {
1191 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1192 return;
1195 if (state->dhnq != NULL) {
1196 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1197 return;
1200 durable_v2_timeout = IVAL(p, 0);
1201 create_guid_blob = data_blob_const(p + 16, 16);
1203 status = GUID_from_ndr_blob(&create_guid_blob,
1204 &state->_create_guid);
1205 if (tevent_req_nterror(req, status)) {
1206 return;
1208 state->create_guid = &state->_create_guid;
1211 * we need to store the create_guid later
1213 state->update_open = true;
1216 * And we need to create a cache for replaying the
1217 * create.
1219 state->need_replay_cache = true;
1222 * durable handle v2 request processed below
1224 state->durable_requested = true;
1225 state->durable_timeout_msec = MIN(durable_v2_timeout, 300*1000);
1226 if (state->durable_timeout_msec == 0) {
1228 * Set the timeout to 1 min as default.
1230 * This matches Windows 2012.
1232 state->durable_timeout_msec = (60*1000);
1236 * Check for replay operation.
1237 * Only consider it when we have dh2q.
1238 * If we do not have a replay operation, verify that
1239 * the create_guid is not cached for replay.
1241 hdr = SMBD_SMB2_IN_HDR_PTR(smb2req);
1242 flags = IVAL(hdr, SMB2_HDR_FLAGS);
1243 state->replay_operation =
1244 flags & SMB2_HDR_FLAG_REPLAY_OPERATION;
1246 status = smb2srv_open_lookup_replay_cache(smb2req->xconn,
1247 state->req_guid,
1248 *state->create_guid,
1249 state->fname,
1250 now,
1251 &state->op);
1252 if (NT_STATUS_EQUAL(status, NT_STATUS_FWP_RESERVED)) {
1254 * We've reserved the replay_cache record
1255 * for ourself, indicating we're still
1256 * in progress.
1258 * It means the smbd_smb2_create_cleanup()
1259 * may need to call smbXsrv_open_purge_replay_cache()
1260 * in order to cleanup.
1262 SMB_ASSERT(state->op == NULL);
1263 state->_purge_create_guid = state->_create_guid;
1264 state->purge_create_guid = &state->_purge_create_guid;
1265 status = NT_STATUS_OK;
1266 state->replay_operation = false;
1267 } else if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_NOT_AVAILABLE)) {
1268 tevent_req_nterror(req, status);
1269 return;
1270 } else if (tevent_req_nterror(req, status)) {
1271 DBG_WARNING("smb2srv_open_lookup_replay_cache "
1272 "failed: %s\n", nt_errstr(status));
1273 return;
1274 } else if (!state->replay_operation) {
1276 * If a create without replay operation flag
1277 * is sent but with a create_guid that is
1278 * currently in the replay cache -- fail.
1280 status = NT_STATUS_DUPLICATE_OBJECTID;
1281 (void)tevent_req_nterror(req, status);
1282 return;
1286 if (state->dhnc != NULL) {
1287 state->persistent_id = BVAL(state->dhnc->data.data, 0);
1288 state->do_durable_reconnect = true;
1291 if (state->dh2c != NULL) {
1292 const uint8_t *p = state->dh2c->data.data;
1293 DATA_BLOB create_guid_blob;
1295 state->persistent_id = BVAL(p, 0);
1296 create_guid_blob = data_blob_const(p + 16, 16);
1298 status = GUID_from_ndr_blob(&create_guid_blob,
1299 &state->_create_guid);
1300 if (tevent_req_nterror(req, status)) {
1301 return;
1304 state->create_guid = &state->_create_guid;
1305 state->do_durable_reconnect = true;
1308 if (state->alsi != NULL) {
1309 if (state->alsi->data.length != 8) {
1310 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1311 return;
1313 state->allocation_size = BVAL(state->alsi->data.data, 0);
1316 if (state->twrp != NULL) {
1317 if (state->twrp->data.length != 8) {
1318 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1319 return;
1322 state->twrp_time = BVAL(state->twrp->data.data, 0);
1325 if (state->qfid != NULL) {
1326 if (state->qfid->data.length != 0) {
1327 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1328 return;
1332 if (state->rqls != NULL) {
1333 ssize_t lease_len = -1;
1335 lease_len = smb2_lease_pull(state->rqls->data.data,
1336 state->rqls->data.length,
1337 &state->lease);
1338 if (lease_len == -1) {
1339 tevent_req_nterror(
1340 req, NT_STATUS_INVALID_PARAMETER);
1341 return;
1343 state->lease_ptr = &state->lease;
1345 if (DEBUGLEVEL >= 10) {
1346 DEBUG(10, ("Got lease request size %d\n",
1347 (int)lease_len));
1348 NDR_PRINT_DEBUG(smb2_lease, state->lease_ptr);
1351 if (!smb2_lease_key_valid(&state->lease.lease_key)) {
1352 state->lease_ptr = NULL;
1353 state->requested_oplock_level = SMB2_OPLOCK_LEVEL_NONE;
1356 if ((smb2req->xconn->protocol < PROTOCOL_SMB3_00) &&
1357 (state->lease.lease_version != 1))
1359 DEBUG(10, ("v2 lease key only for SMB3\n"));
1360 state->lease_ptr = NULL;
1364 * Replay with a lease is only allowed if the
1365 * established open carries a lease with the
1366 * same lease key.
1368 if (state->replay_operation) {
1369 struct smb2_lease *op_ls =
1370 &state->op->compat->lease->lease;
1371 int op_oplock = state->op->compat->oplock_type;
1373 if (map_samba_oplock_levels_to_smb2(op_oplock)
1374 != SMB2_OPLOCK_LEVEL_LEASE)
1376 status = NT_STATUS_ACCESS_DENIED;
1377 (void)tevent_req_nterror(req, status);
1378 return;
1380 if (!smb2_lease_key_equal(&state->lease.lease_key,
1381 &op_ls->lease_key))
1383 status = NT_STATUS_ACCESS_DENIED;
1384 (void)tevent_req_nterror(req, status);
1385 return;
1390 if (state->posx != NULL) {
1391 if (state->posx->data.length != 4) {
1392 DBG_DEBUG("Got %zu bytes POSX cctx, expected 4\n",
1393 state->posx->data.length);
1394 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1395 return;
1400 static void smbd_smb2_create_after_exec(struct tevent_req *req)
1402 struct smbd_smb2_create_state *state = tevent_req_data(
1403 req, struct smbd_smb2_create_state);
1404 connection_struct *conn = state->result->conn;
1405 NTSTATUS status;
1408 * here we have op == result->op
1411 DEBUG(10, ("smbd_smb2_create_send: "
1412 "response construction phase\n"));
1414 state->out_file_attributes = fdos_mode(state->result);
1416 if (state->mxac != NULL) {
1417 NTTIME last_write_time;
1419 last_write_time = full_timespec_to_nt_time(
1420 &state->result->fsp_name->st.st_ex_mtime);
1421 if (last_write_time != state->max_access_time) {
1422 uint8_t p[8];
1423 uint32_t max_access_granted;
1424 DATA_BLOB blob = data_blob_const(p, sizeof(p));
1426 status = smbd_calculate_access_mask_fsp(
1427 conn->cwd_fsp,
1428 state->result,
1429 false,
1430 SEC_FLAG_MAXIMUM_ALLOWED,
1431 &max_access_granted);
1433 SIVAL(p, 0, NT_STATUS_V(status));
1434 SIVAL(p, 4, max_access_granted);
1436 status = smb2_create_blob_add(
1437 state->out_context_blobs,
1438 state->out_context_blobs,
1439 SMB2_CREATE_TAG_MXAC,
1440 blob);
1441 if (!NT_STATUS_IS_OK(status)) {
1442 goto fail;
1447 if (!state->replay_operation && state->durable_requested &&
1448 (fsp_lease_type(state->result) & SMB2_LEASE_HANDLE))
1450 status = SMB_VFS_DURABLE_COOKIE(
1451 state->result,
1452 state->op,
1453 &state->op->global->backend_cookie);
1454 if (!NT_STATUS_IS_OK(status)) {
1455 state->op->global->backend_cookie = data_blob_null;
1458 if (!state->replay_operation && state->op->global->backend_cookie.length > 0)
1460 state->update_open = true;
1462 state->op->global->durable = true;
1463 state->op->global->durable_timeout_msec = state->durable_timeout_msec;
1466 if (state->update_open) {
1467 state->op->global->create_guid = state->_create_guid;
1468 if (state->need_replay_cache) {
1469 state->op->flags |= SMBXSRV_OPEN_NEED_REPLAY_CACHE;
1472 status = smbXsrv_open_update(state->op);
1473 DEBUG(10, ("smb2_create_send: smbXsrv_open_update "
1474 "returned %s\n",
1475 nt_errstr(status)));
1476 if (!NT_STATUS_IS_OK(status)) {
1477 goto fail;
1481 * We should not purge the replay cache anymore
1482 * as it's attached to the smbXsrv_open record now.
1484 state->purge_create_guid = NULL;
1487 if (state->dhnq != NULL && state->op->global->durable) {
1488 uint8_t p[8] = { 0, };
1489 DATA_BLOB blob = data_blob_const(p, sizeof(p));
1491 status = smb2_create_blob_add(state->out_context_blobs,
1492 state->out_context_blobs,
1493 SMB2_CREATE_TAG_DHNQ,
1494 blob);
1495 if (!NT_STATUS_IS_OK(status)) {
1496 goto fail;
1500 if (state->dh2q != NULL && state->op->global->durable &&
1502 * For replay operations, we return the dh2q blob
1503 * in the case of oplocks not based on the state of
1504 * the open, but on whether it could have been granted
1505 * for the request data. In the case of leases instead,
1506 * the state of the open is used...
1508 (!state->replay_operation ||
1509 state->in_oplock_level == SMB2_OPLOCK_LEVEL_BATCH ||
1510 state->in_oplock_level == SMB2_OPLOCK_LEVEL_LEASE))
1512 uint8_t p[8] = { 0, };
1513 DATA_BLOB blob = data_blob_const(p, sizeof(p));
1514 uint32_t durable_v2_response_flags = 0;
1516 SIVAL(p, 0, state->op->global->durable_timeout_msec);
1517 SIVAL(p, 4, durable_v2_response_flags);
1519 status = smb2_create_blob_add(state->out_context_blobs,
1520 state->out_context_blobs,
1521 SMB2_CREATE_TAG_DH2Q,
1522 blob);
1523 if (!NT_STATUS_IS_OK(status)) {
1524 goto fail;
1528 if (state->qfid != NULL) {
1529 uint8_t p[32];
1530 SMB_STRUCT_STAT *base_sp = state->result->base_fsp ?
1531 &state->result->base_fsp->fsp_name->st :
1532 &state->result->fsp_name->st;
1533 uint64_t file_id = SMB_VFS_FS_FILE_ID(conn, base_sp);
1534 DATA_BLOB blob = data_blob_const(p, sizeof(p));
1536 ZERO_STRUCT(p);
1538 /* From conversations with Microsoft engineers at
1539 the MS plugfest. The first 8 bytes are the "volume index"
1540 == inode, the second 8 bytes are the "volume id",
1541 == dev. This will be updated in the SMB2 doc. */
1542 SBVAL(p, 0, file_id);
1543 SIVAL(p, 8, base_sp->st_ex_dev);/* FileIndexHigh */
1545 status = smb2_create_blob_add(state->out_context_blobs,
1546 state->out_context_blobs,
1547 SMB2_CREATE_TAG_QFID,
1548 blob);
1549 if (!NT_STATUS_IS_OK(status)) {
1550 goto fail;
1554 if ((state->rqls != NULL) && (state->result->oplock_type == LEASE_OPLOCK)) {
1555 uint8_t buf[52];
1556 struct smb2_lease lease;
1557 size_t lease_len;
1559 lease = state->result->lease->lease;
1561 lease_len = sizeof(buf);
1562 if (lease.lease_version == 1) {
1563 lease_len = 32;
1566 if (!smb2_lease_push(&lease, buf, lease_len)) {
1567 status = NT_STATUS_INTERNAL_ERROR;
1568 goto fail;
1571 status = smb2_create_blob_add(
1572 state, state->out_context_blobs,
1573 SMB2_CREATE_TAG_RQLS,
1574 data_blob_const(buf, lease_len));
1575 if (!NT_STATUS_IS_OK(status)) {
1576 goto fail;
1580 if (state->posx != NULL) {
1581 struct dom_sid owner = { .sid_rev_num = 0, };
1582 struct dom_sid group = { .sid_rev_num = 0, };
1583 struct stat_ex *psbuf = &state->result->fsp_name->st;
1584 ssize_t cc_len;
1586 uid_to_sid(&owner, psbuf->st_ex_uid);
1587 gid_to_sid(&group, psbuf->st_ex_gid);
1589 cc_len = smb2_posix_cc_info(
1590 conn, 0, psbuf, &owner, &group, NULL, 0);
1592 if (cc_len == -1) {
1593 status = NT_STATUS_INSUFFICIENT_RESOURCES;
1594 goto fail;
1599 * cc_len is 68 + 2 SIDs, allocate on the stack
1601 uint8_t buf[cc_len];
1602 DATA_BLOB blob = { .data = buf, .length = cc_len, };
1604 smb2_posix_cc_info(
1605 conn,
1607 psbuf,
1608 &owner,
1609 &group,
1610 buf,
1611 sizeof(buf));
1613 status = smb2_create_blob_add(
1614 state->out_context_blobs,
1615 state->out_context_blobs,
1616 SMB2_CREATE_TAG_POSIX,
1617 blob);
1618 if (!NT_STATUS_IS_OK(status)) {
1619 goto fail;
1624 return;
1626 fail:
1627 close_file_free(state->smb1req, &state->result, ERROR_CLOSE);
1628 tevent_req_nterror(req, status);
1629 tevent_req_post(req, state->ev);
1632 static void smbd_smb2_create_finish(struct tevent_req *req)
1634 struct smbd_smb2_create_state *state = tevent_req_data(
1635 req, struct smbd_smb2_create_state);
1636 struct smbd_smb2_request *smb2req = state->smb2req;
1637 struct smb_request *smb1req = state->smb1req;
1638 files_struct *result = state->result;
1640 smb2req->compat_chain_fsp = smb1req->chain_fsp;
1642 if (state->replay_operation) {
1643 state->out_oplock_level = state->in_oplock_level;
1644 } else if (lp_fake_oplocks(SNUM(smb2req->tcon->compat))) {
1645 state->out_oplock_level = state->in_oplock_level;
1646 } else {
1647 state->out_oplock_level = map_samba_oplock_levels_to_smb2(result->oplock_type);
1650 if ((state->in_create_disposition == FILE_SUPERSEDE)
1651 && (state->info == FILE_WAS_OVERWRITTEN)) {
1652 state->out_create_action = FILE_WAS_SUPERSEDED;
1653 } else {
1654 state->out_create_action = state->info;
1656 result->op->create_action = state->out_create_action;
1658 state->out_creation_ts = get_create_timespec(smb1req->conn,
1659 result, result->fsp_name);
1660 state->out_last_access_ts = result->fsp_name->st.st_ex_atime;
1661 state->out_last_write_ts = result->fsp_name->st.st_ex_mtime;
1662 state->out_change_ts = get_change_timespec(smb1req->conn,
1663 result, result->fsp_name);
1665 if (lp_dos_filetime_resolution(SNUM(smb2req->tcon->compat))) {
1666 dos_filetime_timespec(&state->out_creation_ts);
1667 dos_filetime_timespec(&state->out_last_access_ts);
1668 dos_filetime_timespec(&state->out_last_write_ts);
1669 dos_filetime_timespec(&state->out_change_ts);
1672 state->out_allocation_size =
1673 SMB_VFS_GET_ALLOC_SIZE(smb1req->conn, result,
1674 &(result->fsp_name->st));
1675 state->out_end_of_file = result->fsp_name->st.st_ex_size;
1676 if (state->out_file_attributes == 0) {
1677 state->out_file_attributes = FILE_ATTRIBUTE_NORMAL;
1679 state->out_file_id_persistent = result->op->global->open_persistent_id;
1680 state->out_file_id_volatile = result->op->global->open_volatile_id;
1682 DBG_DEBUG("%s - %s\n", fsp_str_dbg(result), fsp_fnum_dbg(result));
1684 tevent_req_done(req);
1685 tevent_req_post(req, state->ev);
1688 static NTSTATUS smbd_smb2_create_recv(struct tevent_req *req,
1689 TALLOC_CTX *mem_ctx,
1690 uint8_t *out_oplock_level,
1691 uint32_t *out_create_action,
1692 struct timespec *out_creation_ts,
1693 struct timespec *out_last_access_ts,
1694 struct timespec *out_last_write_ts,
1695 struct timespec *out_change_ts,
1696 uint64_t *out_allocation_size,
1697 uint64_t *out_end_of_file,
1698 uint32_t *out_file_attributes,
1699 uint64_t *out_file_id_persistent,
1700 uint64_t *out_file_id_volatile,
1701 struct smb2_create_blobs *out_context_blobs)
1703 NTSTATUS status;
1704 struct smbd_smb2_create_state *state = tevent_req_data(req,
1705 struct smbd_smb2_create_state);
1707 if (tevent_req_is_nterror(req, &status)) {
1708 tevent_req_received(req);
1709 return status;
1712 *out_oplock_level = state->out_oplock_level;
1713 *out_create_action = state->out_create_action;
1714 *out_creation_ts = state->out_creation_ts;
1715 *out_last_access_ts = state->out_last_access_ts;
1716 *out_last_write_ts = state->out_last_write_ts;
1717 *out_change_ts = state->out_change_ts;
1718 *out_allocation_size = state->out_allocation_size;
1719 *out_end_of_file = state->out_end_of_file;
1720 *out_file_attributes = state->out_file_attributes;
1721 *out_file_id_persistent = state->out_file_id_persistent;
1722 *out_file_id_volatile = state->out_file_id_volatile;
1723 *out_context_blobs = *(state->out_context_blobs);
1725 talloc_steal(mem_ctx, state->out_context_blobs->blobs);
1727 tevent_req_received(req);
1728 return NT_STATUS_OK;
1731 /*********************************************************
1732 Code for dealing with deferred opens.
1733 *********************************************************/
1735 bool get_deferred_open_message_state_smb2(struct smbd_smb2_request *smb2req,
1736 struct timeval *p_request_time,
1737 struct deferred_open_record **open_rec)
1739 struct smbd_smb2_create_state *state = NULL;
1740 struct tevent_req *req = NULL;
1742 if (!smb2req) {
1743 return false;
1745 req = smb2req->subreq;
1746 if (!req) {
1747 return false;
1749 state = tevent_req_data(req, struct smbd_smb2_create_state);
1750 if (!state) {
1751 return false;
1753 if (!state->open_was_deferred) {
1754 return false;
1756 if (p_request_time) {
1757 *p_request_time = state->request_time;
1759 if (open_rec != NULL) {
1760 *open_rec = state->open_rec;
1762 return true;
1765 /*********************************************************
1766 Re-process this call early - requested by message or
1767 close.
1768 *********************************************************/
1770 static struct smbd_smb2_request *find_open_smb2req(
1771 struct smbXsrv_connection *xconn, uint64_t mid)
1773 struct smbd_smb2_request *smb2req;
1775 for (smb2req = xconn->smb2.requests; smb2req; smb2req = smb2req->next) {
1776 uint64_t message_id;
1777 if (smb2req->subreq == NULL) {
1778 /* This message has been processed. */
1779 continue;
1781 if (!tevent_req_is_in_progress(smb2req->subreq)) {
1782 /* This message has been processed. */
1783 continue;
1785 message_id = get_mid_from_smb2req(smb2req);
1786 if (message_id == mid) {
1787 return smb2req;
1790 return NULL;
1793 bool open_was_deferred_smb2(struct smbXsrv_connection *xconn, uint64_t mid)
1795 struct smbd_smb2_create_state *state = NULL;
1796 struct smbd_smb2_request *smb2req;
1798 smb2req = find_open_smb2req(xconn, mid);
1800 if (!smb2req) {
1801 DEBUG(10,("open_was_deferred_smb2: mid %llu smb2req == NULL\n",
1802 (unsigned long long)mid));
1803 return false;
1805 if (!smb2req->subreq) {
1806 return false;
1808 if (!tevent_req_is_in_progress(smb2req->subreq)) {
1809 return false;
1811 state = tevent_req_data(smb2req->subreq,
1812 struct smbd_smb2_create_state);
1813 if (!state) {
1814 return false;
1816 /* It's not in progress if there's no timeout event. */
1817 if (!state->open_was_deferred) {
1818 return false;
1821 DEBUG(10,("open_was_deferred_smb2: mid = %llu\n",
1822 (unsigned long long)mid));
1824 return true;
1827 static void remove_deferred_open_message_smb2_internal(struct smbd_smb2_request *smb2req,
1828 uint64_t mid)
1830 struct smbd_smb2_create_state *state = NULL;
1832 if (!smb2req->subreq) {
1833 return;
1835 if (!tevent_req_is_in_progress(smb2req->subreq)) {
1836 return;
1838 state = tevent_req_data(smb2req->subreq,
1839 struct smbd_smb2_create_state);
1840 if (!state) {
1841 return;
1844 DEBUG(10,("remove_deferred_open_message_smb2_internal: "
1845 "mid %llu\n",
1846 (unsigned long long)mid ));
1848 state->open_was_deferred = false;
1849 /* Ensure we don't have any outstanding immediate event. */
1850 TALLOC_FREE(state->im);
1851 TALLOC_FREE(state->open_rec);
1854 void remove_deferred_open_message_smb2(
1855 struct smbXsrv_connection *xconn, uint64_t mid)
1857 struct smbd_smb2_request *smb2req;
1859 smb2req = find_open_smb2req(xconn, mid);
1861 if (!smb2req) {
1862 DEBUG(10,("remove_deferred_open_message_smb2: "
1863 "can't find mid %llu\n",
1864 (unsigned long long)mid ));
1865 return;
1867 remove_deferred_open_message_smb2_internal(smb2req, mid);
1870 static void smbd_smb2_create_request_dispatch_immediate(struct tevent_context *ctx,
1871 struct tevent_immediate *im,
1872 void *private_data)
1874 struct smbd_smb2_request *smb2req = talloc_get_type_abort(private_data,
1875 struct smbd_smb2_request);
1876 uint64_t mid = get_mid_from_smb2req(smb2req);
1877 NTSTATUS status;
1879 DEBUG(10,("smbd_smb2_create_request_dispatch_immediate: "
1880 "re-dispatching mid %llu\n",
1881 (unsigned long long)mid ));
1883 status = smbd_smb2_request_dispatch(smb2req);
1884 if (!NT_STATUS_IS_OK(status)) {
1885 smbd_server_connection_terminate(smb2req->xconn,
1886 nt_errstr(status));
1887 return;
1891 bool schedule_deferred_open_message_smb2(
1892 struct smbXsrv_connection *xconn, uint64_t mid)
1894 struct smbd_smb2_create_state *state = NULL;
1895 struct smbd_smb2_request *smb2req;
1897 smb2req = find_open_smb2req(xconn, mid);
1899 if (!smb2req) {
1900 DEBUG(10,("schedule_deferred_open_message_smb2: "
1901 "can't find mid %llu\n",
1902 (unsigned long long)mid ));
1903 return false;
1905 if (!smb2req->subreq) {
1906 return false;
1908 if (!tevent_req_is_in_progress(smb2req->subreq)) {
1909 return false;
1911 state = tevent_req_data(smb2req->subreq,
1912 struct smbd_smb2_create_state);
1913 if (!state) {
1914 return false;
1917 /* Ensure we don't have any outstanding immediate event. */
1918 TALLOC_FREE(state->im);
1921 * This is subtle. We must null out the callback
1922 * before rescheduling, else the first call to
1923 * tevent_req_nterror() causes the _receive()
1924 * function to be called, this causing tevent_req_post()
1925 * to crash.
1927 tevent_req_set_callback(smb2req->subreq, NULL, NULL);
1929 state->im = tevent_create_immediate(smb2req);
1930 if (!state->im) {
1931 smbd_server_connection_terminate(smb2req->xconn,
1932 nt_errstr(NT_STATUS_NO_MEMORY));
1933 return false;
1936 DEBUG(10,("schedule_deferred_open_message_smb2: "
1937 "re-processing mid %llu\n",
1938 (unsigned long long)mid ));
1940 tevent_schedule_immediate(state->im,
1941 smb2req->sconn->ev_ctx,
1942 smbd_smb2_create_request_dispatch_immediate,
1943 smb2req);
1945 return true;
1948 static bool smbd_smb2_create_cancel(struct tevent_req *req)
1950 struct smbd_smb2_request *smb2req = NULL;
1951 struct smbd_smb2_create_state *state = tevent_req_data(req,
1952 struct smbd_smb2_create_state);
1953 uint64_t mid;
1955 if (!state) {
1956 return false;
1959 if (!state->smb2req) {
1960 return false;
1963 smb2req = state->smb2req;
1964 mid = get_mid_from_smb2req(smb2req);
1966 if (is_deferred_open_async(state->open_rec)) {
1967 /* Can't cancel an async create. */
1968 return false;
1971 remove_deferred_open_message_smb2_internal(smb2req, mid);
1973 tevent_req_defer_callback(req, smb2req->sconn->ev_ctx);
1974 tevent_req_nterror(req, NT_STATUS_CANCELLED);
1975 return true;
1978 bool push_deferred_open_message_smb2(struct smbd_smb2_request *smb2req,
1979 struct timeval request_time,
1980 struct timeval timeout,
1981 struct file_id id,
1982 struct deferred_open_record *open_rec)
1984 struct tevent_req *req = NULL;
1985 struct smbd_smb2_create_state *state = NULL;
1986 struct timeval end_time;
1988 if (!smb2req) {
1989 return false;
1991 req = smb2req->subreq;
1992 if (!req) {
1993 return false;
1995 state = tevent_req_data(req, struct smbd_smb2_create_state);
1996 if (!state) {
1997 return false;
1999 state->id = id;
2000 state->request_time = request_time;
2001 state->open_rec = talloc_move(state, &open_rec);
2003 /* Re-schedule us to retry on timer expiry. */
2004 end_time = timeval_sum(&request_time, &timeout);
2006 DEBUG(10,("push_deferred_open_message_smb2: "
2007 "timeout at %s\n",
2008 timeval_string(talloc_tos(),
2009 &end_time,
2010 true) ));
2012 state->open_was_deferred = true;
2014 /* allow this request to be canceled */
2015 tevent_req_set_cancel_fn(req, smbd_smb2_create_cancel);
2017 return true;