2 Unix SMB/CIFS implementation.
5 Copyright (C) Stefan Metzmacher 2009
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "smbd/globals.h"
23 #include "../libcli/smb/smb_common.h"
25 static struct tevent_req
*smbd_smb2_create_send(TALLOC_CTX
*mem_ctx
,
26 struct tevent_context
*ev
,
27 struct smbd_smb2_request
*smb2req
,
28 uint8_t in_oplock_level
,
29 uint32_t in_impersonation_level
,
30 uint32_t in_desired_access
,
31 uint32_t in_file_attributes
,
32 uint32_t in_share_access
,
33 uint32_t in_create_disposition
,
34 uint32_t in_create_options
,
36 struct smb2_create_blobs in_context_blobs
);
37 static NTSTATUS
smbd_smb2_create_recv(struct tevent_req
*req
,
39 uint8_t *out_oplock_level
,
40 uint32_t *out_create_action
,
41 NTTIME
*out_creation_time
,
42 NTTIME
*out_last_access_time
,
43 NTTIME
*out_last_write_time
,
44 NTTIME
*out_change_time
,
45 uint64_t *out_allocation_size
,
46 uint64_t *out_end_of_file
,
47 uint32_t *out_file_attributes
,
48 uint64_t *out_file_id_volatile
,
49 struct smb2_create_blobs
*out_context_blobs
);
51 static void smbd_smb2_request_create_done(struct tevent_req
*subreq
);
52 NTSTATUS
smbd_smb2_request_process_create(struct smbd_smb2_request
*req
)
54 const uint8_t *inbody
;
55 int i
= req
->current_idx
;
56 size_t expected_body_size
= 0x39;
58 uint8_t in_oplock_level
;
59 uint32_t in_impersonation_level
;
60 uint32_t in_desired_access
;
61 uint32_t in_file_attributes
;
62 uint32_t in_share_access
;
63 uint32_t in_create_disposition
;
64 uint32_t in_create_options
;
65 uint16_t in_name_offset
;
66 uint16_t in_name_length
;
67 DATA_BLOB in_name_buffer
;
69 size_t in_name_string_size
;
70 uint32_t name_offset
= 0;
71 uint32_t name_available_length
= 0;
72 uint32_t in_context_offset
;
73 uint32_t in_context_length
;
74 DATA_BLOB in_context_buffer
;
75 struct smb2_create_blobs in_context_blobs
;
76 uint32_t context_offset
= 0;
77 uint32_t context_available_length
= 0;
81 struct tevent_req
*subreq
;
83 if (req
->in
.vector
[i
+1].iov_len
!= (expected_body_size
& 0xFFFFFFFE)) {
84 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
87 inbody
= (const uint8_t *)req
->in
.vector
[i
+1].iov_base
;
89 body_size
= SVAL(inbody
, 0x00);
90 if (body_size
!= expected_body_size
) {
91 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
94 in_oplock_level
= CVAL(inbody
, 0x03);
95 in_impersonation_level
= IVAL(inbody
, 0x04);
96 in_desired_access
= IVAL(inbody
, 0x18);
97 in_file_attributes
= IVAL(inbody
, 0x1C);
98 in_share_access
= IVAL(inbody
, 0x20);
99 in_create_disposition
= IVAL(inbody
, 0x24);
100 in_create_options
= IVAL(inbody
, 0x28);
101 in_name_offset
= SVAL(inbody
, 0x2C);
102 in_name_length
= SVAL(inbody
, 0x2E);
103 in_context_offset
= IVAL(inbody
, 0x30);
104 in_context_length
= IVAL(inbody
, 0x34);
107 * First check if the dynamic name and context buffers
108 * are correctly specified.
110 * Note: That we don't check if the name and context buffers
114 dyn_offset
= SMB2_HDR_BODY
+ (body_size
& 0xFFFFFFFE);
116 if (in_name_offset
== 0 && in_name_length
== 0) {
119 } else if (in_name_offset
< dyn_offset
) {
120 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
122 name_offset
= in_name_offset
- dyn_offset
;
125 if (name_offset
> req
->in
.vector
[i
+2].iov_len
) {
126 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
129 name_available_length
= req
->in
.vector
[i
+2].iov_len
- name_offset
;
131 if (in_name_length
> name_available_length
) {
132 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
135 in_name_buffer
.data
= (uint8_t *)req
->in
.vector
[i
+2].iov_base
+
137 in_name_buffer
.length
= in_name_length
;
139 if (in_context_offset
== 0 && in_context_length
== 0) {
142 } else if (in_context_offset
< dyn_offset
) {
143 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
145 context_offset
= in_context_offset
- dyn_offset
;
148 if (context_offset
> req
->in
.vector
[i
+2].iov_len
) {
149 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
152 context_available_length
= req
->in
.vector
[i
+2].iov_len
- context_offset
;
154 if (in_context_length
> context_available_length
) {
155 return smbd_smb2_request_error(req
, NT_STATUS_INVALID_PARAMETER
);
158 in_context_buffer
.data
= (uint8_t *)req
->in
.vector
[i
+2].iov_base
+
160 in_context_buffer
.length
= in_context_length
;
163 * Now interpret the name and context buffers
166 ok
= convert_string_talloc(req
, CH_UTF16
, CH_UNIX
,
168 in_name_buffer
.length
,
170 &in_name_string_size
, false);
172 return smbd_smb2_request_error(req
, NT_STATUS_ILLEGAL_CHARACTER
);
175 ZERO_STRUCT(in_context_blobs
);
176 status
= smb2_create_blob_parse(req
, in_context_buffer
, &in_context_blobs
);
177 if (!NT_STATUS_IS_OK(status
)) {
178 return smbd_smb2_request_error(req
, status
);
181 subreq
= smbd_smb2_create_send(req
,
182 req
->sconn
->smb2
.event_ctx
,
185 in_impersonation_level
,
189 in_create_disposition
,
193 if (subreq
== NULL
) {
194 return smbd_smb2_request_error(req
, NT_STATUS_NO_MEMORY
);
196 tevent_req_set_callback(subreq
, smbd_smb2_request_create_done
, req
);
198 return smbd_smb2_request_pending_queue(req
, subreq
);
201 static void smbd_smb2_request_create_done(struct tevent_req
*subreq
)
203 struct smbd_smb2_request
*req
= tevent_req_callback_data(subreq
,
204 struct smbd_smb2_request
);
205 int i
= req
->current_idx
;
209 uint8_t out_oplock_level
= 0;
210 uint32_t out_create_action
= 0;
211 NTTIME out_creation_time
= 0;
212 NTTIME out_last_access_time
= 0;
213 NTTIME out_last_write_time
= 0;
214 NTTIME out_change_time
= 0;
215 uint64_t out_allocation_size
= 0;
216 uint64_t out_end_of_file
= 0;
217 uint32_t out_file_attributes
= 0;
218 uint64_t out_file_id_volatile
= 0;
219 struct smb2_create_blobs out_context_blobs
;
220 DATA_BLOB out_context_buffer
;
221 uint16_t out_context_buffer_offset
= 0;
223 NTSTATUS error
; /* transport error */
225 status
= smbd_smb2_create_recv(subreq
,
230 &out_last_access_time
,
231 &out_last_write_time
,
233 &out_allocation_size
,
235 &out_file_attributes
,
236 &out_file_id_volatile
,
239 if (!NT_STATUS_IS_OK(status
)) {
240 error
= smbd_smb2_request_error(req
, status
);
241 if (!NT_STATUS_IS_OK(error
)) {
242 smbd_server_connection_terminate(req
->sconn
,
249 status
= smb2_create_blob_push(req
, &out_context_buffer
, out_context_blobs
);
250 if (!NT_STATUS_IS_OK(status
)) {
251 error
= smbd_smb2_request_error(req
, status
);
252 if (!NT_STATUS_IS_OK(error
)) {
253 smbd_server_connection_terminate(req
->sconn
,
260 if (out_context_buffer
.length
> 0) {
261 out_context_buffer_offset
= SMB2_HDR_BODY
+ 0x58;
264 outhdr
= (uint8_t *)req
->out
.vector
[i
].iov_base
;
266 outbody
= data_blob_talloc(req
->out
.vector
, NULL
, 0x58);
267 if (outbody
.data
== NULL
) {
268 error
= smbd_smb2_request_error(req
, NT_STATUS_NO_MEMORY
);
269 if (!NT_STATUS_IS_OK(error
)) {
270 smbd_server_connection_terminate(req
->sconn
,
277 SSVAL(outbody
.data
, 0x00, 0x58 + 1); /* struct size */
278 SCVAL(outbody
.data
, 0x02,
279 out_oplock_level
); /* oplock level */
280 SCVAL(outbody
.data
, 0x03, 0); /* reserved */
281 SIVAL(outbody
.data
, 0x04,
282 out_create_action
); /* create action */
283 SBVAL(outbody
.data
, 0x08,
284 out_creation_time
); /* creation time */
285 SBVAL(outbody
.data
, 0x10,
286 out_last_access_time
); /* last access time */
287 SBVAL(outbody
.data
, 0x18,
288 out_last_write_time
); /* last write time */
289 SBVAL(outbody
.data
, 0x20,
290 out_change_time
); /* change time */
291 SBVAL(outbody
.data
, 0x28,
292 out_allocation_size
); /* allocation size */
293 SBVAL(outbody
.data
, 0x30,
294 out_end_of_file
); /* end of file */
295 SIVAL(outbody
.data
, 0x38,
296 out_file_attributes
); /* file attributes */
297 SIVAL(outbody
.data
, 0x3C, 0); /* reserved */
298 SBVAL(outbody
.data
, 0x40, 0); /* file id (persistent) */
299 SBVAL(outbody
.data
, 0x48,
300 out_file_id_volatile
); /* file id (volatile) */
301 SIVAL(outbody
.data
, 0x50,
302 out_context_buffer_offset
); /* create contexts offset */
303 SIVAL(outbody
.data
, 0x54,
304 out_context_buffer
.length
); /* create contexts length */
306 outdyn
= out_context_buffer
;
308 error
= smbd_smb2_request_done(req
, outbody
, &outdyn
);
309 if (!NT_STATUS_IS_OK(error
)) {
310 smbd_server_connection_terminate(req
->sconn
,
316 struct smbd_smb2_create_state
{
317 struct smbd_smb2_request
*smb2req
;
318 uint8_t out_oplock_level
;
319 uint32_t out_create_action
;
320 NTTIME out_creation_time
;
321 NTTIME out_last_access_time
;
322 NTTIME out_last_write_time
;
323 NTTIME out_change_time
;
324 uint64_t out_allocation_size
;
325 uint64_t out_end_of_file
;
326 uint32_t out_file_attributes
;
327 uint64_t out_file_id_volatile
;
328 struct smb2_create_blobs out_context_blobs
;
331 static struct tevent_req
*smbd_smb2_create_send(TALLOC_CTX
*mem_ctx
,
332 struct tevent_context
*ev
,
333 struct smbd_smb2_request
*smb2req
,
334 uint8_t in_oplock_level
,
335 uint32_t in_impersonation_level
,
336 uint32_t in_desired_access
,
337 uint32_t in_file_attributes
,
338 uint32_t in_share_access
,
339 uint32_t in_create_disposition
,
340 uint32_t in_create_options
,
342 struct smb2_create_blobs in_context_blobs
)
344 struct tevent_req
*req
;
345 struct smbd_smb2_create_state
*state
;
347 struct smb_request
*smbreq
;
348 files_struct
*result
;
350 SMB_STRUCT_STAT sbuf
;
351 struct smb2_create_blobs out_context_blobs
;
353 ZERO_STRUCT(out_context_blobs
);
355 req
= tevent_req_create(mem_ctx
, &state
,
356 struct smbd_smb2_create_state
);
360 state
->smb2req
= smb2req
;
362 DEBUG(10,("smbd_smb2_create: name[%s]\n",
365 smbreq
= smbd_smb2_fake_smb_request(smb2req
);
366 if (tevent_req_nomem(smbreq
, req
)) {
367 return tevent_req_post(req
, ev
);
370 if (IS_IPC(smbreq
->conn
)) {
371 const char *pipe_name
= in_name
;
373 if (!lp_nt_pipe_support()) {
374 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
375 return tevent_req_post(req
, ev
);
378 /* Strip \\ off the name. */
379 if (pipe_name
[0] == '\\') {
383 status
= open_np_file(smbreq
, pipe_name
, &result
);
384 if (!NT_STATUS_IS_OK(status
)) {
385 tevent_req_nterror(req
, status
);
386 return tevent_req_post(req
, ev
);
388 info
= FILE_WAS_OPENED
;
390 } else if (CAN_PRINT(smbreq
->conn
)) {
391 status
= file_new(smbreq
, smbreq
->conn
, &result
);
392 if(!NT_STATUS_IS_OK(status
)) {
393 tevent_req_nterror(req
, status
);
394 return tevent_req_post(req
, ev
);
397 status
= print_fsp_open(smbreq
,
403 if (!NT_STATUS_IS_OK(status
)) {
404 file_free(smbreq
, result
);
405 tevent_req_nterror(req
, status
);
406 return tevent_req_post(req
, ev
);
408 info
= FILE_WAS_CREATED
;
411 struct smb_filename
*smb_fname
= NULL
;
412 struct smb2_create_blob
*exta
= NULL
;
413 struct ea_list
*ea_list
= NULL
;
414 struct smb2_create_blob
*mxac
= NULL
;
415 NTTIME max_access_time
= 0;
416 struct smb2_create_blob
*secd
= NULL
;
417 struct security_descriptor
*sec_desc
= NULL
;
418 struct smb2_create_blob
*dhnq
= NULL
;
419 struct smb2_create_blob
*dhnc
= NULL
;
420 struct smb2_create_blob
*alsi
= NULL
;
421 uint64_t allocation_size
= 0;
422 struct smb2_create_blob
*twrp
= NULL
;
423 struct smb2_create_blob
*qfid
= NULL
;
425 exta
= smb2_create_blob_find(&in_context_blobs
,
426 SMB2_CREATE_TAG_EXTA
);
427 mxac
= smb2_create_blob_find(&in_context_blobs
,
428 SMB2_CREATE_TAG_MXAC
);
429 secd
= smb2_create_blob_find(&in_context_blobs
,
430 SMB2_CREATE_TAG_SECD
);
431 dhnq
= smb2_create_blob_find(&in_context_blobs
,
432 SMB2_CREATE_TAG_DHNQ
);
433 dhnc
= smb2_create_blob_find(&in_context_blobs
,
434 SMB2_CREATE_TAG_DHNC
);
435 alsi
= smb2_create_blob_find(&in_context_blobs
,
436 SMB2_CREATE_TAG_ALSI
);
437 twrp
= smb2_create_blob_find(&in_context_blobs
,
438 SMB2_CREATE_TAG_TWRP
);
439 qfid
= smb2_create_blob_find(&in_context_blobs
,
440 SMB2_CREATE_TAG_QFID
);
442 fname
= talloc_strdup(state
, in_name
);
443 if (tevent_req_nomem(fname
, req
)) {
444 return tevent_req_post(req
, ev
);
449 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
450 return tevent_req_post(req
, ev
);
453 ea_list
= read_nttrans_ea_list(mem_ctx
,
454 (const char *)exta
->data
.data
, exta
->data
.length
);
456 DEBUG(10,("smbd_smb2_create_send: read_ea_name_list failed.\n"));
457 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
458 return tevent_req_post(req
, ev
);
464 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
465 return tevent_req_post(req
, ev
);
468 if (mxac
->data
.length
== 0) {
470 } else if (mxac
->data
.length
== 8) {
471 max_access_time
= BVAL(mxac
->data
.data
, 0);
473 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
474 return tevent_req_post(req
, ev
);
479 enum ndr_err_code ndr_err
;
482 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
483 return tevent_req_post(req
, ev
);
486 sec_desc
= talloc_zero(state
, struct security_descriptor
);
487 if (tevent_req_nomem(sec_desc
, req
)) {
488 return tevent_req_post(req
, ev
);
491 ndr_err
= ndr_pull_struct_blob(&secd
->data
,
492 sec_desc
, NULL
, sec_desc
,
493 (ndr_pull_flags_fn_t
)ndr_pull_security_descriptor
);
494 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
495 DEBUG(2,("ndr_pull_security_descriptor failed: %s\n",
496 ndr_errstr(ndr_err
)));
497 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
498 return tevent_req_post(req
, ev
);
504 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
505 return tevent_req_post(req
, ev
);
508 if (dhnq
->data
.length
!= 16) {
509 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
510 return tevent_req_post(req
, ev
);
513 * we don't support durable handles yet
514 * and have to ignore this
519 if (dhnc
->data
.length
!= 16) {
520 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
521 return tevent_req_post(req
, ev
);
523 /* we don't support durable handles yet */
524 tevent_req_nterror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
525 return tevent_req_post(req
, ev
);
530 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
531 return tevent_req_post(req
, ev
);
534 if (alsi
->data
.length
!= 8) {
535 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
536 return tevent_req_post(req
, ev
);
538 allocation_size
= BVAL(alsi
->data
.data
, 0);
547 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
548 return tevent_req_post(req
, ev
);
551 if (twrp
->data
.length
!= 8) {
552 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
553 return tevent_req_post(req
, ev
);
556 nttime
= BVAL(twrp
->data
.data
, 0);
557 t
= nt_time_to_unix(nttime
);
561 fname
= talloc_asprintf(state
,
562 "@GMT-%04u.%02u.%02u-%02u.%02u.%02u\\%s",
570 if (tevent_req_nomem(fname
, req
)) {
571 return tevent_req_post(req
, ev
);
576 if (qfid
->data
.length
!= 0) {
577 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
578 return tevent_req_post(req
, ev
);
582 /* these are ignored for SMB2 */
583 in_create_options
&= ~(0x10);/* NTCREATEX_OPTIONS_SYNC_ALERT */
584 in_create_options
&= ~(0x20);/* NTCREATEX_OPTIONS_ASYNC_ALERT */
586 /* convert '\\' into '/' */
587 status
= check_path_syntax(fname
);
588 if (!NT_STATUS_IS_OK(status
)) {
589 tevent_req_nterror(req
, status
);
590 return tevent_req_post(req
, ev
);
593 status
= filename_convert(req
,
595 smbreq
->flags2
& FLAGS2_DFS_PATHNAMES
,
600 if (!NT_STATUS_IS_OK(status
)) {
601 tevent_req_nterror(req
, status
);
602 return tevent_req_post(req
, ev
);
605 status
= SMB_VFS_CREATE_FILE(smbreq
->conn
,
607 0, /* root_dir_fid */
611 in_create_disposition
,
614 0, /* oplock_request */
620 if (!NT_STATUS_IS_OK(status
)) {
621 tevent_req_nterror(req
, status
);
622 return tevent_req_post(req
, ev
);
626 NTTIME last_write_time
;
628 unix_timespec_to_nt_time(&last_write_time
,
629 result
->fsp_name
->st
.st_ex_mtime
);
630 if (last_write_time
!= max_access_time
) {
632 uint32_t max_access_granted
;
633 DATA_BLOB blob
= data_blob_const(p
, sizeof(p
));
635 status
= smbd_check_open_rights(smbreq
->conn
,
637 SEC_FLAG_MAXIMUM_ALLOWED
,
638 &max_access_granted
);
640 SIVAL(p
, 0, NT_STATUS_V(status
));
641 SIVAL(p
, 4, max_access_granted
);
643 status
= smb2_create_blob_add(state
,
645 SMB2_CREATE_TAG_MXAC
,
647 if (!NT_STATUS_IS_OK(status
)) {
648 tevent_req_nterror(req
, status
);
649 return tevent_req_post(req
, ev
);
656 DATA_BLOB blob
= data_blob_const(p
, sizeof(p
));
660 /* TODO: maybe use result->file_id */
661 SIVAL(p
, 0, result
->fsp_name
->st
.st_ex_ino
);/* FileIndexLow */
662 SIVAL(p
, 4, result
->fsp_name
->st
.st_ex_dev
);/* FileIndexHigh */
664 status
= smb2_create_blob_add(state
, &out_context_blobs
,
665 SMB2_CREATE_TAG_QFID
,
667 if (!NT_STATUS_IS_OK(status
)) {
668 tevent_req_nterror(req
, status
);
669 return tevent_req_post(req
, ev
);
673 sbuf
= result
->fsp_name
->st
;
676 smb2req
->compat_chain_fsp
= smbreq
->chain_fsp
;
678 state
->out_oplock_level
= 0;
679 if ((in_create_disposition
== FILE_SUPERSEDE
)
680 && (info
== FILE_WAS_OVERWRITTEN
)) {
681 state
->out_create_action
= FILE_WAS_SUPERSEDED
;
683 state
->out_create_action
= info
;
685 unix_timespec_to_nt_time(&state
->out_creation_time
, sbuf
.st_ex_btime
);
686 unix_timespec_to_nt_time(&state
->out_last_access_time
, sbuf
.st_ex_atime
);
687 unix_timespec_to_nt_time(&state
->out_last_write_time
,sbuf
.st_ex_mtime
);
688 unix_timespec_to_nt_time(&state
->out_change_time
, sbuf
.st_ex_ctime
);
689 state
->out_allocation_size
= sbuf
.st_ex_blksize
* sbuf
.st_ex_blocks
;
690 state
->out_end_of_file
= sbuf
.st_ex_size
;
691 state
->out_file_attributes
= dos_mode(result
->conn
,
693 if (state
->out_file_attributes
== 0) {
694 state
->out_file_attributes
= FILE_ATTRIBUTE_NORMAL
;
696 state
->out_file_id_volatile
= result
->fnum
;
697 state
->out_context_blobs
= out_context_blobs
;
699 tevent_req_done(req
);
700 return tevent_req_post(req
, ev
);
703 static NTSTATUS
smbd_smb2_create_recv(struct tevent_req
*req
,
705 uint8_t *out_oplock_level
,
706 uint32_t *out_create_action
,
707 NTTIME
*out_creation_time
,
708 NTTIME
*out_last_access_time
,
709 NTTIME
*out_last_write_time
,
710 NTTIME
*out_change_time
,
711 uint64_t *out_allocation_size
,
712 uint64_t *out_end_of_file
,
713 uint32_t *out_file_attributes
,
714 uint64_t *out_file_id_volatile
,
715 struct smb2_create_blobs
*out_context_blobs
)
718 struct smbd_smb2_create_state
*state
= tevent_req_data(req
,
719 struct smbd_smb2_create_state
);
721 if (tevent_req_is_nterror(req
, &status
)) {
722 tevent_req_received(req
);
726 *out_oplock_level
= state
->out_oplock_level
;
727 *out_create_action
= state
->out_create_action
;
728 *out_creation_time
= state
->out_creation_time
;
729 *out_last_access_time
= state
->out_last_access_time
;
730 *out_last_write_time
= state
->out_last_write_time
;
731 *out_change_time
= state
->out_change_time
;
732 *out_allocation_size
= state
->out_allocation_size
;
733 *out_end_of_file
= state
->out_end_of_file
;
734 *out_file_attributes
= state
->out_file_attributes
;
735 *out_file_id_volatile
= state
->out_file_id_volatile
;
736 *out_context_blobs
= state
->out_context_blobs
;
738 talloc_steal(mem_ctx
, state
->out_context_blobs
.blobs
);
740 tevent_req_received(req
);