2 Unix SMB/CIFS implementation.
5 Copyright (C) Stefan Metzmacher 2009
6 Copyright (C) Jeremy Allison 2010
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "smbd/globals.h"
24 #include "../libcli/smb/smb_common.h"
26 int map_smb2_oplock_levels_to_samba(uint8_t in_oplock_level
)
28 switch(in_oplock_level
) {
29 case SMB2_OPLOCK_LEVEL_NONE
:
31 case SMB2_OPLOCK_LEVEL_II
:
32 return LEVEL_II_OPLOCK
;
33 case SMB2_OPLOCK_LEVEL_EXCLUSIVE
:
34 return EXCLUSIVE_OPLOCK
;
35 case SMB2_OPLOCK_LEVEL_BATCH
:
37 case SMB2_OPLOCK_LEVEL_LEASE
:
38 DEBUG(2,("map_smb2_oplock_levels_to_samba: "
39 "LEASE_OPLOCK_REQUESTED\n"));
42 DEBUG(2,("map_smb2_oplock_levels_to_samba: "
44 (unsigned int)in_oplock_level
));
49 uint8_t map_samba_oplock_levels_to_smb2(int oplock_type
)
51 if (BATCH_OPLOCK_TYPE(oplock_type
)) {
52 return SMB2_OPLOCK_LEVEL_BATCH
;
53 } else if (EXCLUSIVE_OPLOCK_TYPE(oplock_type
)) {
54 return SMB2_OPLOCK_LEVEL_EXCLUSIVE
;
55 } else if (LEVEL_II_OPLOCK_TYPE(oplock_type
)) {
56 return SMB2_OPLOCK_LEVEL_II
;
58 return SMB2_OPLOCK_LEVEL_NONE
;
62 static struct tevent_req
*smbd_smb2_create_send(TALLOC_CTX
*mem_ctx
,
63 struct tevent_context
*ev
,
64 struct smbd_smb2_request
*smb2req
,
65 uint8_t in_oplock_level
,
66 uint32_t in_impersonation_level
,
67 uint32_t in_desired_access
,
68 uint32_t in_file_attributes
,
69 uint32_t in_share_access
,
70 uint32_t in_create_disposition
,
71 uint32_t in_create_options
,
73 struct smb2_create_blobs in_context_blobs
);
74 static NTSTATUS
smbd_smb2_create_recv(struct tevent_req
*req
,
76 uint8_t *out_oplock_level
,
77 uint32_t *out_create_action
,
78 NTTIME
*out_creation_time
,
79 NTTIME
*out_last_access_time
,
80 NTTIME
*out_last_write_time
,
81 NTTIME
*out_change_time
,
82 uint64_t *out_allocation_size
,
83 uint64_t *out_end_of_file
,
84 uint32_t *out_file_attributes
,
85 uint64_t *out_file_id_volatile
,
86 struct smb2_create_blobs
*out_context_blobs
);
88 static void smbd_smb2_request_create_done(struct tevent_req
*tsubreq
);
89 NTSTATUS
smbd_smb2_request_process_create(struct smbd_smb2_request
*smb2req
)
91 const uint8_t *inbody
;
92 int i
= smb2req
->current_idx
;
93 size_t expected_body_size
= 0x39;
95 uint8_t in_oplock_level
;
96 uint32_t in_impersonation_level
;
97 uint32_t in_desired_access
;
98 uint32_t in_file_attributes
;
99 uint32_t in_share_access
;
100 uint32_t in_create_disposition
;
101 uint32_t in_create_options
;
102 uint16_t in_name_offset
;
103 uint16_t in_name_length
;
104 DATA_BLOB in_name_buffer
;
105 char *in_name_string
;
106 size_t in_name_string_size
;
107 uint32_t name_offset
= 0;
108 uint32_t name_available_length
= 0;
109 uint32_t in_context_offset
;
110 uint32_t in_context_length
;
111 DATA_BLOB in_context_buffer
;
112 struct smb2_create_blobs in_context_blobs
;
113 uint32_t context_offset
= 0;
114 uint32_t context_available_length
= 0;
118 struct tevent_req
*tsubreq
;
120 if (smb2req
->in
.vector
[i
+1].iov_len
!= (expected_body_size
& 0xFFFFFFFE)) {
121 return smbd_smb2_request_error(smb2req
, NT_STATUS_INVALID_PARAMETER
);
124 inbody
= (const uint8_t *)smb2req
->in
.vector
[i
+1].iov_base
;
126 body_size
= SVAL(inbody
, 0x00);
127 if (body_size
!= expected_body_size
) {
128 return smbd_smb2_request_error(smb2req
, NT_STATUS_INVALID_PARAMETER
);
131 in_oplock_level
= CVAL(inbody
, 0x03);
132 in_impersonation_level
= IVAL(inbody
, 0x04);
133 in_desired_access
= IVAL(inbody
, 0x18);
134 in_file_attributes
= IVAL(inbody
, 0x1C);
135 in_share_access
= IVAL(inbody
, 0x20);
136 in_create_disposition
= IVAL(inbody
, 0x24);
137 in_create_options
= IVAL(inbody
, 0x28);
138 in_name_offset
= SVAL(inbody
, 0x2C);
139 in_name_length
= SVAL(inbody
, 0x2E);
140 in_context_offset
= IVAL(inbody
, 0x30);
141 in_context_length
= IVAL(inbody
, 0x34);
144 * First check if the dynamic name and context buffers
145 * are correctly specified.
147 * Note: That we don't check if the name and context buffers
151 dyn_offset
= SMB2_HDR_BODY
+ (body_size
& 0xFFFFFFFE);
153 if (in_name_offset
== 0 && in_name_length
== 0) {
156 } else if (in_name_offset
< dyn_offset
) {
157 return smbd_smb2_request_error(smb2req
, NT_STATUS_INVALID_PARAMETER
);
159 name_offset
= in_name_offset
- dyn_offset
;
162 if (name_offset
> smb2req
->in
.vector
[i
+2].iov_len
) {
163 return smbd_smb2_request_error(smb2req
, NT_STATUS_INVALID_PARAMETER
);
166 name_available_length
= smb2req
->in
.vector
[i
+2].iov_len
- name_offset
;
168 if (in_name_length
> name_available_length
) {
169 return smbd_smb2_request_error(smb2req
, NT_STATUS_INVALID_PARAMETER
);
172 in_name_buffer
.data
= (uint8_t *)smb2req
->in
.vector
[i
+2].iov_base
+
174 in_name_buffer
.length
= in_name_length
;
176 if (in_context_offset
== 0 && in_context_length
== 0) {
179 } else if (in_context_offset
< dyn_offset
) {
180 return smbd_smb2_request_error(smb2req
, NT_STATUS_INVALID_PARAMETER
);
182 context_offset
= in_context_offset
- dyn_offset
;
185 if (context_offset
> smb2req
->in
.vector
[i
+2].iov_len
) {
186 return smbd_smb2_request_error(smb2req
, NT_STATUS_INVALID_PARAMETER
);
189 context_available_length
= smb2req
->in
.vector
[i
+2].iov_len
- context_offset
;
191 if (in_context_length
> context_available_length
) {
192 return smbd_smb2_request_error(smb2req
, NT_STATUS_INVALID_PARAMETER
);
195 in_context_buffer
.data
= (uint8_t *)smb2req
->in
.vector
[i
+2].iov_base
+
197 in_context_buffer
.length
= in_context_length
;
200 * Now interpret the name and context buffers
203 ok
= convert_string_talloc(smb2req
, CH_UTF16
, CH_UNIX
,
205 in_name_buffer
.length
,
207 &in_name_string_size
, false);
209 return smbd_smb2_request_error(smb2req
, NT_STATUS_ILLEGAL_CHARACTER
);
212 ZERO_STRUCT(in_context_blobs
);
213 status
= smb2_create_blob_parse(smb2req
, in_context_buffer
, &in_context_blobs
);
214 if (!NT_STATUS_IS_OK(status
)) {
215 return smbd_smb2_request_error(smb2req
, status
);
218 tsubreq
= smbd_smb2_create_send(smb2req
,
219 smb2req
->sconn
->smb2
.event_ctx
,
222 in_impersonation_level
,
226 in_create_disposition
,
230 if (tsubreq
== NULL
) {
231 smb2req
->subreq
= NULL
;
232 return smbd_smb2_request_error(smb2req
, NT_STATUS_NO_MEMORY
);
234 tevent_req_set_callback(tsubreq
, smbd_smb2_request_create_done
, smb2req
);
236 return smbd_smb2_request_pending_queue(smb2req
, tsubreq
);
239 static uint64_t get_mid_from_smb2req(struct smbd_smb2_request
*smb2req
)
241 uint8_t *reqhdr
= (uint8_t *)smb2req
->out
.vector
[smb2req
->current_idx
].iov_base
;
242 return BVAL(reqhdr
, SMB2_HDR_MESSAGE_ID
);
245 static void smbd_smb2_request_create_done(struct tevent_req
*tsubreq
)
247 struct smbd_smb2_request
*smb2req
= tevent_req_callback_data(tsubreq
,
248 struct smbd_smb2_request
);
249 int i
= smb2req
->current_idx
;
253 uint8_t out_oplock_level
= 0;
254 uint32_t out_create_action
= 0;
255 NTTIME out_creation_time
= 0;
256 NTTIME out_last_access_time
= 0;
257 NTTIME out_last_write_time
= 0;
258 NTTIME out_change_time
= 0;
259 uint64_t out_allocation_size
= 0;
260 uint64_t out_end_of_file
= 0;
261 uint32_t out_file_attributes
= 0;
262 uint64_t out_file_id_volatile
= 0;
263 struct smb2_create_blobs out_context_blobs
;
264 DATA_BLOB out_context_buffer
;
265 uint16_t out_context_buffer_offset
= 0;
267 NTSTATUS error
; /* transport error */
269 if (smb2req
->cancelled
) {
270 uint64_t mid
= get_mid_from_smb2req(smb2req
);
271 DEBUG(10,("smbd_smb2_request_create_done: cancelled mid %llu\n",
272 (unsigned long long)mid
));
273 error
= smbd_smb2_request_error(smb2req
, NT_STATUS_CANCELLED
);
274 if (!NT_STATUS_IS_OK(error
)) {
275 smbd_server_connection_terminate(smb2req
->sconn
,
282 status
= smbd_smb2_create_recv(tsubreq
,
287 &out_last_access_time
,
288 &out_last_write_time
,
290 &out_allocation_size
,
292 &out_file_attributes
,
293 &out_file_id_volatile
,
295 if (!NT_STATUS_IS_OK(status
)) {
296 error
= smbd_smb2_request_error(smb2req
, status
);
297 if (!NT_STATUS_IS_OK(error
)) {
298 smbd_server_connection_terminate(smb2req
->sconn
,
305 status
= smb2_create_blob_push(smb2req
, &out_context_buffer
, out_context_blobs
);
306 if (!NT_STATUS_IS_OK(status
)) {
307 error
= smbd_smb2_request_error(smb2req
, status
);
308 if (!NT_STATUS_IS_OK(error
)) {
309 smbd_server_connection_terminate(smb2req
->sconn
,
316 if (out_context_buffer
.length
> 0) {
317 out_context_buffer_offset
= SMB2_HDR_BODY
+ 0x58;
320 outhdr
= (uint8_t *)smb2req
->out
.vector
[i
].iov_base
;
322 outbody
= data_blob_talloc(smb2req
->out
.vector
, NULL
, 0x58);
323 if (outbody
.data
== NULL
) {
324 error
= smbd_smb2_request_error(smb2req
, NT_STATUS_NO_MEMORY
);
325 if (!NT_STATUS_IS_OK(error
)) {
326 smbd_server_connection_terminate(smb2req
->sconn
,
333 SSVAL(outbody
.data
, 0x00, 0x58 + 1); /* struct size */
334 SCVAL(outbody
.data
, 0x02,
335 out_oplock_level
); /* oplock level */
336 SCVAL(outbody
.data
, 0x03, 0); /* reserved */
337 SIVAL(outbody
.data
, 0x04,
338 out_create_action
); /* create action */
339 SBVAL(outbody
.data
, 0x08,
340 out_creation_time
); /* creation time */
341 SBVAL(outbody
.data
, 0x10,
342 out_last_access_time
); /* last access time */
343 SBVAL(outbody
.data
, 0x18,
344 out_last_write_time
); /* last write time */
345 SBVAL(outbody
.data
, 0x20,
346 out_change_time
); /* change time */
347 SBVAL(outbody
.data
, 0x28,
348 out_allocation_size
); /* allocation size */
349 SBVAL(outbody
.data
, 0x30,
350 out_end_of_file
); /* end of file */
351 SIVAL(outbody
.data
, 0x38,
352 out_file_attributes
); /* file attributes */
353 SIVAL(outbody
.data
, 0x3C, 0); /* reserved */
354 SBVAL(outbody
.data
, 0x40, 0); /* file id (persistent) */
355 SBVAL(outbody
.data
, 0x48,
356 out_file_id_volatile
); /* file id (volatile) */
357 SIVAL(outbody
.data
, 0x50,
358 out_context_buffer_offset
); /* create contexts offset */
359 SIVAL(outbody
.data
, 0x54,
360 out_context_buffer
.length
); /* create contexts length */
362 outdyn
= out_context_buffer
;
364 error
= smbd_smb2_request_done(smb2req
, outbody
, &outdyn
);
365 if (!NT_STATUS_IS_OK(error
)) {
366 smbd_server_connection_terminate(smb2req
->sconn
,
372 struct smbd_smb2_create_state
{
373 struct smbd_smb2_request
*smb2req
;
374 struct smb_request
*smb1req
;
375 struct timed_event
*te
;
376 struct timeval request_time
;
378 DATA_BLOB private_data
;
379 uint8_t out_oplock_level
;
380 uint32_t out_create_action
;
381 NTTIME out_creation_time
;
382 NTTIME out_last_access_time
;
383 NTTIME out_last_write_time
;
384 NTTIME out_change_time
;
385 uint64_t out_allocation_size
;
386 uint64_t out_end_of_file
;
387 uint32_t out_file_attributes
;
388 uint64_t out_file_id_volatile
;
389 struct smb2_create_blobs out_context_blobs
;
392 static struct tevent_req
*smbd_smb2_create_send(TALLOC_CTX
*mem_ctx
,
393 struct tevent_context
*ev
,
394 struct smbd_smb2_request
*smb2req
,
395 uint8_t in_oplock_level
,
396 uint32_t in_impersonation_level
,
397 uint32_t in_desired_access
,
398 uint32_t in_file_attributes
,
399 uint32_t in_share_access
,
400 uint32_t in_create_disposition
,
401 uint32_t in_create_options
,
403 struct smb2_create_blobs in_context_blobs
)
405 struct tevent_req
*req
= NULL
;
406 struct smbd_smb2_create_state
*state
= NULL
;
408 struct smb_request
*smb1req
= NULL
;
409 files_struct
*result
= NULL
;
411 struct timespec write_time_ts
;
412 struct smb2_create_blobs out_context_blobs
;
414 ZERO_STRUCT(out_context_blobs
);
416 if (!smb2req
->async
) {
417 /* New create call. */
418 req
= tevent_req_create(mem_ctx
, &state
,
419 struct smbd_smb2_create_state
);
423 state
->smb2req
= smb2req
;
424 smb2req
->subreq
= req
; /* So we can find this when going async. */
426 smb1req
= smbd_smb2_fake_smb_request(smb2req
);
427 if (tevent_req_nomem(smb1req
, req
)) {
428 return tevent_req_post(req
, ev
);
430 state
->smb1req
= smb1req
;
431 DEBUG(10,("smbd_smb2_create: name[%s]\n",
434 /* Re-entrant create call. */
435 req
= smb2req
->subreq
;
436 state
= tevent_req_data(req
,
437 struct smbd_smb2_create_state
);
438 smb1req
= state
->smb1req
;
439 DEBUG(10,("smbd_smb2_create_send: reentrant for file %s\n",
443 if (IS_IPC(smb1req
->conn
)) {
444 const char *pipe_name
= in_name
;
446 if (!lp_nt_pipe_support()) {
447 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
448 return tevent_req_post(req
, ev
);
451 /* Strip \\ off the name. */
452 if (pipe_name
[0] == '\\') {
456 status
= open_np_file(smb1req
, pipe_name
, &result
);
457 if (!NT_STATUS_IS_OK(status
)) {
458 tevent_req_nterror(req
, status
);
459 return tevent_req_post(req
, ev
);
461 info
= FILE_WAS_OPENED
;
462 } else if (CAN_PRINT(smb1req
->conn
)) {
463 status
= file_new(smb1req
, smb1req
->conn
, &result
);
464 if(!NT_STATUS_IS_OK(status
)) {
465 tevent_req_nterror(req
, status
);
466 return tevent_req_post(req
, ev
);
469 status
= print_fsp_open(smb1req
,
474 if (!NT_STATUS_IS_OK(status
)) {
475 file_free(smb1req
, result
);
476 tevent_req_nterror(req
, status
);
477 return tevent_req_post(req
, ev
);
479 info
= FILE_WAS_CREATED
;
482 struct smb_filename
*smb_fname
= NULL
;
483 struct smb2_create_blob
*exta
= NULL
;
484 struct ea_list
*ea_list
= NULL
;
485 struct smb2_create_blob
*mxac
= NULL
;
486 NTTIME max_access_time
= 0;
487 struct smb2_create_blob
*secd
= NULL
;
488 struct security_descriptor
*sec_desc
= NULL
;
489 struct smb2_create_blob
*dhnq
= NULL
;
490 struct smb2_create_blob
*dhnc
= NULL
;
491 struct smb2_create_blob
*alsi
= NULL
;
492 uint64_t allocation_size
= 0;
493 struct smb2_create_blob
*twrp
= NULL
;
494 struct smb2_create_blob
*qfid
= NULL
;
496 exta
= smb2_create_blob_find(&in_context_blobs
,
497 SMB2_CREATE_TAG_EXTA
);
498 mxac
= smb2_create_blob_find(&in_context_blobs
,
499 SMB2_CREATE_TAG_MXAC
);
500 secd
= smb2_create_blob_find(&in_context_blobs
,
501 SMB2_CREATE_TAG_SECD
);
502 dhnq
= smb2_create_blob_find(&in_context_blobs
,
503 SMB2_CREATE_TAG_DHNQ
);
504 dhnc
= smb2_create_blob_find(&in_context_blobs
,
505 SMB2_CREATE_TAG_DHNC
);
506 alsi
= smb2_create_blob_find(&in_context_blobs
,
507 SMB2_CREATE_TAG_ALSI
);
508 twrp
= smb2_create_blob_find(&in_context_blobs
,
509 SMB2_CREATE_TAG_TWRP
);
510 qfid
= smb2_create_blob_find(&in_context_blobs
,
511 SMB2_CREATE_TAG_QFID
);
513 fname
= talloc_strdup(state
, in_name
);
514 if (tevent_req_nomem(fname
, req
)) {
515 return tevent_req_post(req
, ev
);
520 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
521 return tevent_req_post(req
, ev
);
524 ea_list
= read_nttrans_ea_list(mem_ctx
,
525 (const char *)exta
->data
.data
, exta
->data
.length
);
527 DEBUG(10,("smbd_smb2_create_send: read_ea_name_list failed.\n"));
528 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
529 return tevent_req_post(req
, ev
);
535 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
536 return tevent_req_post(req
, ev
);
539 if (mxac
->data
.length
== 0) {
541 } else if (mxac
->data
.length
== 8) {
542 max_access_time
= BVAL(mxac
->data
.data
, 0);
544 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
545 return tevent_req_post(req
, ev
);
550 enum ndr_err_code ndr_err
;
553 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
554 return tevent_req_post(req
, ev
);
557 sec_desc
= talloc_zero(state
, struct security_descriptor
);
558 if (tevent_req_nomem(sec_desc
, req
)) {
559 return tevent_req_post(req
, ev
);
562 ndr_err
= ndr_pull_struct_blob(&secd
->data
,
563 sec_desc
, NULL
, sec_desc
,
564 (ndr_pull_flags_fn_t
)ndr_pull_security_descriptor
);
565 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
566 DEBUG(2,("ndr_pull_security_descriptor failed: %s\n",
567 ndr_errstr(ndr_err
)));
568 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
569 return tevent_req_post(req
, ev
);
575 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
576 return tevent_req_post(req
, ev
);
579 if (dhnq
->data
.length
!= 16) {
580 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
581 return tevent_req_post(req
, ev
);
584 * we don't support durable handles yet
585 * and have to ignore this
590 if (dhnc
->data
.length
!= 16) {
591 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
592 return tevent_req_post(req
, ev
);
594 /* we don't support durable handles yet */
595 tevent_req_nterror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
596 return tevent_req_post(req
, ev
);
601 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
602 return tevent_req_post(req
, ev
);
605 if (alsi
->data
.length
!= 8) {
606 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
607 return tevent_req_post(req
, ev
);
609 allocation_size
= BVAL(alsi
->data
.data
, 0);
618 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
619 return tevent_req_post(req
, ev
);
622 if (twrp
->data
.length
!= 8) {
623 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
624 return tevent_req_post(req
, ev
);
627 nttime
= BVAL(twrp
->data
.data
, 0);
628 t
= nt_time_to_unix(nttime
);
632 fname
= talloc_asprintf(state
,
633 "@GMT-%04u.%02u.%02u-%02u.%02u.%02u\\%s",
641 if (tevent_req_nomem(fname
, req
)) {
642 return tevent_req_post(req
, ev
);
647 if (qfid
->data
.length
!= 0) {
648 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
649 return tevent_req_post(req
, ev
);
653 /* these are ignored for SMB2 */
654 in_create_options
&= ~(0x10);/* NTCREATEX_OPTIONS_SYNC_ALERT */
655 in_create_options
&= ~(0x20);/* NTCREATEX_OPTIONS_ASYNC_ALERT */
657 /* convert '\\' into '/' */
658 status
= check_path_syntax(fname
);
659 if (!NT_STATUS_IS_OK(status
)) {
660 tevent_req_nterror(req
, status
);
661 return tevent_req_post(req
, ev
);
664 status
= filename_convert(req
,
666 smb1req
->flags2
& FLAGS2_DFS_PATHNAMES
,
671 if (!NT_STATUS_IS_OK(status
)) {
672 tevent_req_nterror(req
, status
);
673 return tevent_req_post(req
, ev
);
676 in_file_attributes
&= ~FILE_FLAG_POSIX_SEMANTICS
;
678 status
= SMB_VFS_CREATE_FILE(smb1req
->conn
,
680 0, /* root_dir_fid */
684 in_create_disposition
,
687 map_smb2_oplock_levels_to_samba(in_oplock_level
),
689 0, /* private_flags */
694 if (!NT_STATUS_IS_OK(status
)) {
695 if (open_was_deferred(smb1req
->mid
)) {
698 tevent_req_nterror(req
, status
);
699 return tevent_req_post(req
, ev
);
703 NTTIME last_write_time
;
705 unix_timespec_to_nt_time(&last_write_time
,
706 result
->fsp_name
->st
.st_ex_mtime
);
707 if (last_write_time
!= max_access_time
) {
709 uint32_t max_access_granted
;
710 DATA_BLOB blob
= data_blob_const(p
, sizeof(p
));
712 status
= smbd_check_open_rights(smb1req
->conn
,
714 SEC_FLAG_MAXIMUM_ALLOWED
,
715 &max_access_granted
);
717 SIVAL(p
, 0, NT_STATUS_V(status
));
718 SIVAL(p
, 4, max_access_granted
);
720 status
= smb2_create_blob_add(state
,
722 SMB2_CREATE_TAG_MXAC
,
724 if (!NT_STATUS_IS_OK(status
)) {
725 tevent_req_nterror(req
, status
);
726 return tevent_req_post(req
, ev
);
733 DATA_BLOB blob
= data_blob_const(p
, sizeof(p
));
737 /* TODO: maybe use result->file_id */
738 SIVAL(p
, 0, result
->fsp_name
->st
.st_ex_ino
);/* FileIndexLow */
739 SIVAL(p
, 4, result
->fsp_name
->st
.st_ex_dev
);/* FileIndexHigh */
741 status
= smb2_create_blob_add(state
, &out_context_blobs
,
742 SMB2_CREATE_TAG_QFID
,
744 if (!NT_STATUS_IS_OK(status
)) {
745 tevent_req_nterror(req
, status
);
746 return tevent_req_post(req
, ev
);
751 smb2req
->compat_chain_fsp
= smb1req
->chain_fsp
;
753 state
->out_oplock_level
= map_samba_oplock_levels_to_smb2(result
->oplock_type
);
755 if ((in_create_disposition
== FILE_SUPERSEDE
)
756 && (info
== FILE_WAS_OVERWRITTEN
)) {
757 state
->out_create_action
= FILE_WAS_SUPERSEDED
;
759 state
->out_create_action
= info
;
761 state
->out_file_attributes
= dos_mode(result
->conn
,
763 /* Deal with other possible opens having a modified
765 ZERO_STRUCT(write_time_ts
);
766 get_file_infos(result
->file_id
, NULL
, &write_time_ts
);
767 if (!null_timespec(write_time_ts
)) {
768 update_stat_ex_mtime(&result
->fsp_name
->st
, write_time_ts
);
771 unix_timespec_to_nt_time(&state
->out_creation_time
,
772 get_create_timespec(smb1req
->conn
, result
,
774 unix_timespec_to_nt_time(&state
->out_last_access_time
,
775 result
->fsp_name
->st
.st_ex_atime
);
776 unix_timespec_to_nt_time(&state
->out_last_write_time
,
777 result
->fsp_name
->st
.st_ex_mtime
);
778 unix_timespec_to_nt_time(&state
->out_change_time
,
779 get_change_timespec(smb1req
->conn
, result
,
781 state
->out_allocation_size
=
782 result
->fsp_name
->st
.st_ex_blksize
*
783 result
->fsp_name
->st
.st_ex_blocks
;
784 state
->out_end_of_file
= result
->fsp_name
->st
.st_ex_size
;
785 if (state
->out_file_attributes
== 0) {
786 state
->out_file_attributes
= FILE_ATTRIBUTE_NORMAL
;
788 state
->out_file_id_volatile
= result
->fnum
;
789 state
->out_context_blobs
= out_context_blobs
;
791 tevent_req_done(req
);
792 return tevent_req_post(req
, ev
);
795 static NTSTATUS
smbd_smb2_create_recv(struct tevent_req
*req
,
797 uint8_t *out_oplock_level
,
798 uint32_t *out_create_action
,
799 NTTIME
*out_creation_time
,
800 NTTIME
*out_last_access_time
,
801 NTTIME
*out_last_write_time
,
802 NTTIME
*out_change_time
,
803 uint64_t *out_allocation_size
,
804 uint64_t *out_end_of_file
,
805 uint32_t *out_file_attributes
,
806 uint64_t *out_file_id_volatile
,
807 struct smb2_create_blobs
*out_context_blobs
)
810 struct smbd_smb2_create_state
*state
= tevent_req_data(req
,
811 struct smbd_smb2_create_state
);
813 if (tevent_req_is_nterror(req
, &status
)) {
814 tevent_req_received(req
);
818 *out_oplock_level
= state
->out_oplock_level
;
819 *out_create_action
= state
->out_create_action
;
820 *out_creation_time
= state
->out_creation_time
;
821 *out_last_access_time
= state
->out_last_access_time
;
822 *out_last_write_time
= state
->out_last_write_time
;
823 *out_change_time
= state
->out_change_time
;
824 *out_allocation_size
= state
->out_allocation_size
;
825 *out_end_of_file
= state
->out_end_of_file
;
826 *out_file_attributes
= state
->out_file_attributes
;
827 *out_file_id_volatile
= state
->out_file_id_volatile
;
828 *out_context_blobs
= state
->out_context_blobs
;
830 talloc_steal(mem_ctx
, state
->out_context_blobs
.blobs
);
832 tevent_req_received(req
);
836 /*********************************************************
837 Code for dealing with deferred opens.
838 *********************************************************/
840 bool get_deferred_open_message_state_smb2(struct smbd_smb2_request
*smb2req
,
841 struct timeval
*p_request_time
,
844 struct smbd_smb2_create_state
*state
= NULL
;
845 struct tevent_req
*req
= NULL
;
850 if (!smb2req
->async
) {
853 req
= smb2req
->subreq
;
857 state
= tevent_req_data(req
, struct smbd_smb2_create_state
);
861 if (p_request_time
) {
862 *p_request_time
= state
->request_time
;
865 *pp_state
= (void *)state
->private_data
.data
;
870 /*********************************************************
871 Re-process this call early - requested by message or
873 *********************************************************/
875 static struct smbd_smb2_request
*find_open_smb2req(uint64_t mid
)
877 struct smbd_server_connection
*sconn
= smbd_server_conn
;
878 struct smbd_smb2_request
*smb2req
;
880 for (smb2req
= sconn
->smb2
.requests
; smb2req
; smb2req
= smb2req
->next
) {
882 if (smb2req
->subreq
== NULL
) {
883 /* This message has been processed. */
886 if (!tevent_req_is_in_progress(smb2req
->subreq
)) {
887 /* This message has been processed. */
890 message_id
= get_mid_from_smb2req(smb2req
);
891 if (message_id
== mid
) {
898 bool open_was_deferred_smb2(uint64_t mid
)
900 struct smbd_smb2_create_state
*state
= NULL
;
901 struct smbd_smb2_request
*smb2req
= find_open_smb2req(mid
);
904 DEBUG(10,("open_was_deferred_smb2: mid %llu smb2req == NULL\n",
905 (unsigned long long)mid
));
908 if (!smb2req
->subreq
) {
911 if (!tevent_req_is_in_progress(smb2req
->subreq
)) {
914 state
= tevent_req_data(smb2req
->subreq
,
915 struct smbd_smb2_create_state
);
919 /* It's not in progress if there's no timeout event. */
924 DEBUG(10,("open_was_deferred_smb2: mid = %llu\n",
925 (unsigned long long)mid
));
930 static void remove_deferred_open_message_smb2_internal(struct smbd_smb2_request
*smb2req
,
933 struct smbd_smb2_create_state
*state
= NULL
;
935 if (!smb2req
->subreq
) {
938 if (!tevent_req_is_in_progress(smb2req
->subreq
)) {
941 state
= tevent_req_data(smb2req
->subreq
,
942 struct smbd_smb2_create_state
);
947 DEBUG(10,("remove_deferred_open_message_smb2_internal: "
949 (unsigned long long)mid
));
951 /* Ensure we don't have any outstanding timer event. */
952 TALLOC_FREE(state
->te
);
955 void remove_deferred_open_message_smb2(uint64_t mid
)
957 struct smbd_smb2_request
*smb2req
= find_open_smb2req(mid
);
960 DEBUG(10,("remove_deferred_open_message_smb2: "
961 "can't find mid %llu\n",
962 (unsigned long long)mid
));
965 remove_deferred_open_message_smb2_internal(smb2req
, mid
);
968 void schedule_deferred_open_message_smb2(uint64_t mid
)
970 struct tevent_immediate
*im
= NULL
;
971 struct smbd_smb2_create_state
*state
= NULL
;
972 struct smbd_smb2_request
*smb2req
= find_open_smb2req(mid
);
975 DEBUG(10,("schedule_deferred_open_message_smb2: "
976 "can't find mid %llu\n",
977 (unsigned long long)mid
));
980 if (!smb2req
->subreq
) {
983 if (!tevent_req_is_in_progress(smb2req
->subreq
)) {
986 state
= tevent_req_data(smb2req
->subreq
,
987 struct smbd_smb2_create_state
);
991 /* Ensure we don't have any outstanding timer event. */
992 TALLOC_FREE(state
->te
);
995 * This is subtle. We must null out the callback
996 * before resheduling, else the first call to
997 * tevent_req_nterror() causes the _receive()
998 * function to be called, this causing tevent_req_post()
1001 tevent_req_set_callback(smb2req
->subreq
, NULL
, NULL
);
1003 im
= tevent_create_immediate(smb2req
);
1005 smbd_server_connection_terminate(smb2req
->sconn
,
1006 nt_errstr(NT_STATUS_NO_MEMORY
));
1009 DEBUG(10,("schedule_deferred_open_message_smb2: "
1010 "re-processing mid %llu\n",
1011 (unsigned long long)mid
));
1013 tevent_schedule_immediate(im
,
1014 smb2req
->sconn
->smb2
.event_ctx
,
1015 smbd_smb2_request_dispatch_immediate
,
1019 /*********************************************************
1020 Re-process this call.
1021 *********************************************************/
1023 static void smb2_deferred_open_timer(struct event_context
*ev
,
1024 struct timed_event
*te
,
1025 struct timeval _tval
,
1029 struct smbd_smb2_create_state
*state
= NULL
;
1030 struct smbd_smb2_request
*smb2req
= talloc_get_type(private_data
,
1031 struct smbd_smb2_request
);
1033 DEBUG(10,("smb2_deferred_open_timer: [idx=%d], %s\n",
1034 smb2req
->current_idx
,
1035 tevent_req_default_print(smb2req
->subreq
, talloc_tos()) ));
1037 state
= tevent_req_data(smb2req
->subreq
,
1038 struct smbd_smb2_create_state
);
1043 * Null this out, don't talloc_free. It will
1044 * be talloc_free'd by the tevent library when
1050 * This is subtle. We must null out the callback
1051 * before resheduling, else the first call to
1052 * tevent_req_nterror() causes the _receive()
1053 * function to be called, this causing tevent_req_post()
1056 tevent_req_set_callback(smb2req
->subreq
, NULL
, NULL
);
1058 status
= smbd_smb2_request_dispatch(smb2req
);
1060 if (!NT_STATUS_IS_OK(status
)) {
1061 smbd_server_connection_terminate(smb2req
->sconn
,
1066 static bool smbd_smb2_create_cancel(struct tevent_req
*req
)
1068 struct smbd_smb2_request
*smb2req
= NULL
;
1069 struct smbd_smb2_create_state
*state
= tevent_req_data(req
,
1070 struct smbd_smb2_create_state
);
1077 if (!state
->smb2req
) {
1081 smb2req
= state
->smb2req
;
1082 mid
= get_mid_from_smb2req(smb2req
);
1084 remove_deferred_open_entry(state
->id
, mid
);
1085 remove_deferred_open_message_smb2_internal(smb2req
, mid
);
1086 smb2req
->cancelled
= true;
1088 tevent_req_done(req
);
1092 bool push_deferred_open_message_smb2(struct smbd_smb2_request
*smb2req
,
1093 struct timeval request_time
,
1094 struct timeval timeout
,
1099 struct tevent_req
*req
= NULL
;
1100 struct smbd_smb2_create_state
*state
= NULL
;
1101 struct timeval end_time
;
1106 req
= smb2req
->subreq
;
1110 state
= tevent_req_data(req
, struct smbd_smb2_create_state
);
1115 state
->request_time
= request_time
;
1116 state
->private_data
= data_blob_talloc(state
, private_data
,
1118 if (!state
->private_data
.data
) {
1122 /* Boo - turns out this isn't what W2K8R2
1123 does. It actually sends the STATUS_PENDING
1124 message followed by the STATUS_SHARING_VIOLATION
1125 message. Surely this means that all open
1126 calls (even on directories) will potentially
1127 fail in a chain.... ? And I've seen directory
1128 opens as the start of a chain. JRA.
1131 * More subtlety. To match W2K8R2 don't
1132 * send a "gone async" message if it's simply
1133 * a STATUS_SHARING_VIOLATION (short) wait, not
1134 * an oplock break wait. We do this by prematurely
1135 * setting smb2req->async flag.
1137 if (timeout
.tv_sec
< 2) {
1138 DEBUG(10,("push_deferred_open_message_smb2: "
1139 "short timer wait (usec = %u). "
1140 "Don't send async message.\n",
1141 (unsigned int)timeout
.tv_usec
));
1142 smb2req
->async
= true;
1146 /* Re-schedule us to retry on timer expiry. */
1147 end_time
= timeval_sum(&request_time
, &timeout
);
1149 DEBUG(10,("push_deferred_open_message_smb2: "
1151 timeval_string(talloc_tos(),
1155 state
->te
= event_add_timed(smb2req
->sconn
->smb2
.event_ctx
,
1158 smb2_deferred_open_timer
,
1164 /* allow this request to be canceled */
1165 tevent_req_set_cancel_fn(req
, smbd_smb2_create_cancel
);