2 Unix SMB/CIFS implementation.
4 helper functions for SMB2 test suite
6 Copyright (C) Andrew Tridgell 2005
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 "libcli/security/security_descriptor.h"
24 #include "libcli/smb2/smb2.h"
25 #include "libcli/smb2/smb2_calls.h"
26 #include "../libcli/smb/smbXcli_base.h"
27 #include "lib/cmdline/popt_common.h"
28 #include "system/time.h"
29 #include "librpc/gen_ndr/ndr_security.h"
30 #include "param/param.h"
31 #include "libcli/resolve/resolve.h"
32 #include "lib/util/tevent_ntstatus.h"
34 #include "torture/torture.h"
35 #include "torture/smb2/proto.h"
36 #include "source4/torture/util.h"
40 write to a file on SMB2
42 NTSTATUS
smb2_util_write(struct smb2_tree
*tree
,
43 struct smb2_handle handle
,
44 const void *buf
, off_t offset
, size_t size
)
49 w
.in
.file
.handle
= handle
;
51 w
.in
.data
= data_blob_const(buf
, size
);
53 return smb2_write(tree
, &w
);
57 create a complex file/dir using the SMB2 protocol
59 static NTSTATUS
smb2_create_complex(struct torture_context
*tctx
,
60 struct smb2_tree
*tree
,
62 struct smb2_handle
*handle
,
65 TALLOC_CTX
*tmp_ctx
= talloc_new(tree
);
67 struct smb2_create io
;
68 union smb_setfileinfo setfile
;
69 union smb_fileinfo fileinfo
;
70 time_t t
= (time(NULL
) & ~1);
73 smb2_util_unlink(tree
, fname
);
75 io
.in
.desired_access
= SEC_FLAG_MAXIMUM_ALLOWED
;
76 io
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
77 io
.in
.create_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
79 NTCREATEX_SHARE_ACCESS_DELETE
|
80 NTCREATEX_SHARE_ACCESS_READ
|
81 NTCREATEX_SHARE_ACCESS_WRITE
;
82 io
.in
.create_options
= 0;
85 io
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
86 io
.in
.share_access
&= ~NTCREATEX_SHARE_ACCESS_DELETE
;
87 io
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
88 io
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
91 /* it seems vista is now fussier about alignment? */
92 if (strchr(fname
, ':') == NULL
) {
94 io
.in
.eas
.num_eas
= 2;
95 io
.in
.eas
.eas
= talloc_array(tmp_ctx
, struct ea_struct
, 2);
96 io
.in
.eas
.eas
[0].flags
= 0;
97 io
.in
.eas
.eas
[0].name
.s
= "EAONE";
98 io
.in
.eas
.eas
[0].value
= data_blob_talloc(tmp_ctx
, "VALUE1", 6);
99 io
.in
.eas
.eas
[1].flags
= 0;
100 io
.in
.eas
.eas
[1].name
.s
= "SECONDEA";
101 io
.in
.eas
.eas
[1].value
= data_blob_talloc(tmp_ctx
, "ValueTwo", 8);
104 status
= smb2_create(tree
, tmp_ctx
, &io
);
105 talloc_free(tmp_ctx
);
106 NT_STATUS_NOT_OK_RETURN(status
);
108 *handle
= io
.out
.file
.handle
;
111 status
= smb2_util_write(tree
, *handle
, buf
, 0, sizeof(buf
));
112 NT_STATUS_NOT_OK_RETURN(status
);
115 /* make sure all the timestamps aren't the same, and are also
116 in different DST zones*/
117 setfile
.generic
.level
= RAW_SFILEINFO_BASIC_INFORMATION
;
118 setfile
.generic
.in
.file
.handle
= *handle
;
120 unix_to_nt_time(&setfile
.basic_info
.in
.create_time
, t
+ 9*30*24*60*60);
121 unix_to_nt_time(&setfile
.basic_info
.in
.access_time
, t
+ 6*30*24*60*60);
122 unix_to_nt_time(&setfile
.basic_info
.in
.write_time
, t
+ 3*30*24*60*60);
123 unix_to_nt_time(&setfile
.basic_info
.in
.change_time
, t
+ 1*30*24*60*60);
124 setfile
.basic_info
.in
.attrib
= FILE_ATTRIBUTE_NORMAL
;
126 status
= smb2_setinfo_file(tree
, &setfile
);
127 if (!NT_STATUS_IS_OK(status
)) {
128 torture_comment(tctx
, "Failed to setup file times - %s\n", nt_errstr(status
));
132 /* make sure all the timestamps aren't the same */
133 fileinfo
.generic
.level
= RAW_FILEINFO_SMB2_ALL_INFORMATION
;
134 fileinfo
.generic
.in
.file
.handle
= *handle
;
136 status
= smb2_getinfo_file(tree
, tree
, &fileinfo
);
137 if (!NT_STATUS_IS_OK(status
)) {
138 torture_comment(tctx
, "Failed to query file times - %s\n", nt_errstr(status
));
143 #define CHECK_TIME(field) do {\
144 if (setfile.basic_info.in.field != fileinfo.all_info2.out.field) { \
145 torture_comment(tctx, "(%s) " #field " not setup correctly: %s(%llu) => %s(%llu)\n", \
147 nt_time_string(tree, setfile.basic_info.in.field), \
148 (unsigned long long)setfile.basic_info.in.field, \
149 nt_time_string(tree, fileinfo.basic_info.out.field), \
150 (unsigned long long)fileinfo.basic_info.out.field); \
151 status = NT_STATUS_INVALID_PARAMETER; \
155 CHECK_TIME(create_time
);
156 CHECK_TIME(access_time
);
157 CHECK_TIME(write_time
);
158 CHECK_TIME(change_time
);
164 create a complex file using the SMB2 protocol
166 NTSTATUS
smb2_create_complex_file(struct torture_context
*tctx
,
167 struct smb2_tree
*tree
, const char *fname
,
168 struct smb2_handle
*handle
)
170 return smb2_create_complex(tctx
, tree
, fname
, handle
, false);
174 create a complex dir using the SMB2 protocol
176 NTSTATUS
smb2_create_complex_dir(struct torture_context
*tctx
,
177 struct smb2_tree
*tree
, const char *fname
,
178 struct smb2_handle
*handle
)
180 return smb2_create_complex(tctx
, tree
, fname
, handle
, true);
184 show lots of information about a file
186 void torture_smb2_all_info(struct torture_context
*tctx
,
187 struct smb2_tree
*tree
, struct smb2_handle handle
)
190 TALLOC_CTX
*tmp_ctx
= talloc_new(tree
);
191 union smb_fileinfo io
;
193 io
.generic
.level
= RAW_FILEINFO_SMB2_ALL_INFORMATION
;
194 io
.generic
.in
.file
.handle
= handle
;
196 status
= smb2_getinfo_file(tree
, tmp_ctx
, &io
);
197 if (!NT_STATUS_IS_OK(status
)) {
198 DEBUG(0,("getinfo failed - %s\n", nt_errstr(status
)));
199 talloc_free(tmp_ctx
);
203 torture_comment(tctx
, "all_info for '%s'\n", io
.all_info2
.out
.fname
.s
);
204 torture_comment(tctx
, "\tcreate_time: %s\n", nt_time_string(tmp_ctx
, io
.all_info2
.out
.create_time
));
205 torture_comment(tctx
, "\taccess_time: %s\n", nt_time_string(tmp_ctx
, io
.all_info2
.out
.access_time
));
206 torture_comment(tctx
, "\twrite_time: %s\n", nt_time_string(tmp_ctx
, io
.all_info2
.out
.write_time
));
207 torture_comment(tctx
, "\tchange_time: %s\n", nt_time_string(tmp_ctx
, io
.all_info2
.out
.change_time
));
208 torture_comment(tctx
, "\tattrib: 0x%x\n", io
.all_info2
.out
.attrib
);
209 torture_comment(tctx
, "\tunknown1: 0x%x\n", io
.all_info2
.out
.unknown1
);
210 torture_comment(tctx
, "\talloc_size: %llu\n", (long long)io
.all_info2
.out
.alloc_size
);
211 torture_comment(tctx
, "\tsize: %llu\n", (long long)io
.all_info2
.out
.size
);
212 torture_comment(tctx
, "\tnlink: %u\n", io
.all_info2
.out
.nlink
);
213 torture_comment(tctx
, "\tdelete_pending: %u\n", io
.all_info2
.out
.delete_pending
);
214 torture_comment(tctx
, "\tdirectory: %u\n", io
.all_info2
.out
.directory
);
215 torture_comment(tctx
, "\tfile_id: %llu\n", (long long)io
.all_info2
.out
.file_id
);
216 torture_comment(tctx
, "\tea_size: %u\n", io
.all_info2
.out
.ea_size
);
217 torture_comment(tctx
, "\taccess_mask: 0x%08x\n", io
.all_info2
.out
.access_mask
);
218 torture_comment(tctx
, "\tposition: 0x%llx\n", (long long)io
.all_info2
.out
.position
);
219 torture_comment(tctx
, "\tmode: 0x%llx\n", (long long)io
.all_info2
.out
.mode
);
221 /* short name, if any */
222 io
.generic
.level
= RAW_FILEINFO_ALT_NAME_INFORMATION
;
223 status
= smb2_getinfo_file(tree
, tmp_ctx
, &io
);
224 if (NT_STATUS_IS_OK(status
)) {
225 torture_comment(tctx
, "\tshort name: '%s'\n", io
.alt_name_info
.out
.fname
.s
);
228 /* the EAs, if any */
229 io
.generic
.level
= RAW_FILEINFO_SMB2_ALL_EAS
;
230 status
= smb2_getinfo_file(tree
, tmp_ctx
, &io
);
231 if (NT_STATUS_IS_OK(status
)) {
233 for (i
=0;i
<io
.all_eas
.out
.num_eas
;i
++) {
234 torture_comment(tctx
, "\tEA[%d] flags=%d len=%d '%s'\n", i
,
235 io
.all_eas
.out
.eas
[i
].flags
,
236 (int)io
.all_eas
.out
.eas
[i
].value
.length
,
237 io
.all_eas
.out
.eas
[i
].name
.s
);
241 /* streams, if available */
242 io
.generic
.level
= RAW_FILEINFO_STREAM_INFORMATION
;
243 status
= smb2_getinfo_file(tree
, tmp_ctx
, &io
);
244 if (NT_STATUS_IS_OK(status
)) {
246 for (i
=0;i
<io
.stream_info
.out
.num_streams
;i
++) {
247 torture_comment(tctx
, "\tstream %d:\n", i
);
248 torture_comment(tctx
, "\t\tsize %ld\n",
249 (long)io
.stream_info
.out
.streams
[i
].size
);
250 torture_comment(tctx
, "\t\talloc size %ld\n",
251 (long)io
.stream_info
.out
.streams
[i
].alloc_size
);
252 torture_comment(tctx
, "\t\tname %s\n", io
.stream_info
.out
.streams
[i
].stream_name
.s
);
257 /* the security descriptor */
258 io
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
259 io
.query_secdesc
.in
.secinfo_flags
=
260 SECINFO_OWNER
|SECINFO_GROUP
|
262 status
= smb2_getinfo_file(tree
, tmp_ctx
, &io
);
263 if (NT_STATUS_IS_OK(status
)) {
264 NDR_PRINT_DEBUG(security_descriptor
, io
.query_secdesc
.out
.sd
);
268 talloc_free(tmp_ctx
);
272 get granted access of a file handle
274 NTSTATUS
torture_smb2_get_allinfo_access(struct smb2_tree
*tree
,
275 struct smb2_handle handle
,
276 uint32_t *granted_access
)
279 TALLOC_CTX
*tmp_ctx
= talloc_new(tree
);
280 union smb_fileinfo io
;
282 io
.generic
.level
= RAW_FILEINFO_SMB2_ALL_INFORMATION
;
283 io
.generic
.in
.file
.handle
= handle
;
285 status
= smb2_getinfo_file(tree
, tmp_ctx
, &io
);
286 if (!NT_STATUS_IS_OK(status
)) {
287 DEBUG(0, ("getinfo failed - %s\n", nt_errstr(status
)));
291 *granted_access
= io
.all_info2
.out
.access_mask
;
294 talloc_free(tmp_ctx
);
299 * open a smb2 tree connect
301 bool torture_smb2_tree_connect(struct torture_context
*tctx
,
302 struct smb2_session
*session
,
304 struct smb2_tree
**_tree
)
307 const char *host
= torture_setting_string(tctx
, "host", NULL
);
308 const char *share
= torture_setting_string(tctx
, "share", NULL
);
310 struct smb2_tree
*tree
;
311 struct tevent_req
*subreq
;
312 uint32_t timeout_msec
;
314 unc
= talloc_asprintf(tctx
, "\\\\%s\\%s", host
, share
);
315 torture_assert(tctx
, unc
!= NULL
, "talloc_asprintf");
317 tree
= smb2_tree_init(session
, mem_ctx
, false);
318 torture_assert(tctx
, tree
!= NULL
, "smb2_tree_init");
320 timeout_msec
= session
->transport
->options
.request_timeout
* 1000;
322 subreq
= smb2cli_tcon_send(tree
, tctx
->ev
,
323 session
->transport
->conn
,
329 torture_assert(tctx
, subreq
!= NULL
, "smb2cli_tcon_send");
332 tevent_req_poll_ntstatus(subreq
, tctx
->ev
, &status
),
333 "tevent_req_poll_ntstatus");
335 status
= smb2cli_tcon_recv(subreq
);
337 torture_assert_ntstatus_ok(tctx
, status
, "smb2cli_tcon_recv");
345 * do a smb2 session setup (without a tree connect)
347 bool torture_smb2_session_setup(struct torture_context
*tctx
,
348 struct smb2_transport
*transport
,
349 uint64_t previous_session_id
,
351 struct smb2_session
**_session
)
354 struct smb2_session
*session
;
356 session
= smb2_session_init(transport
,
357 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
),
360 if (session
== NULL
) {
364 status
= smb2_session_setup_spnego(session
,
365 popt_get_cmdline_credentials(),
366 previous_session_id
);
367 if (!NT_STATUS_IS_OK(status
)) {
368 torture_comment(tctx
, "session setup failed: %s\n", nt_errstr(status
));
369 talloc_free(session
);
379 open a smb2 connection
381 bool torture_smb2_connection_ext(struct torture_context
*tctx
,
382 uint64_t previous_session_id
,
383 const struct smbcli_options
*options
,
384 struct smb2_tree
**tree
)
387 const char *host
= torture_setting_string(tctx
, "host", NULL
);
388 const char *share
= torture_setting_string(tctx
, "share", NULL
);
389 const char *p
= torture_setting_string(tctx
, "unclist", NULL
);
390 TALLOC_CTX
*mem_ctx
= NULL
;
397 mem_ctx
= talloc_new(tctx
);
398 if (mem_ctx
== NULL
) {
402 ok
= torture_get_conn_index(tctx
->conn_index
++, mem_ctx
, tctx
,
405 TALLOC_FREE(mem_ctx
);
413 status
= smb2_connect_ext(tctx
,
415 lpcfg_smb_ports(tctx
->lp_ctx
),
417 lpcfg_resolve_context(tctx
->lp_ctx
),
418 popt_get_cmdline_credentials(),
423 lpcfg_socket_options(tctx
->lp_ctx
),
424 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
)
426 if (!NT_STATUS_IS_OK(status
)) {
427 torture_comment(tctx
, "Failed to connect to SMB2 share \\\\%s\\%s - %s\n",
428 host
, share
, nt_errstr(status
));
429 TALLOC_FREE(mem_ctx
);
433 TALLOC_FREE(mem_ctx
);
437 bool torture_smb2_connection(struct torture_context
*tctx
, struct smb2_tree
**tree
)
440 struct smbcli_options options
;
442 lpcfg_smbcli_options(tctx
->lp_ctx
, &options
);
444 ret
= torture_smb2_connection_ext(tctx
, 0, &options
, tree
);
450 * SMB2 connect with share from soption
452 bool torture_smb2_con_sopt(struct torture_context
*tctx
,
454 struct smb2_tree
**tree
)
456 struct smbcli_options options
;
458 const char *host
= torture_setting_string(tctx
, "host", NULL
);
459 const char *share
= torture_setting_string(tctx
, soption
, NULL
);
461 lpcfg_smbcli_options(tctx
->lp_ctx
, &options
);
464 torture_comment(tctx
, "No share for option %s\n", soption
);
468 status
= smb2_connect_ext(tctx
,
470 lpcfg_smb_ports(tctx
->lp_ctx
),
472 lpcfg_resolve_context(tctx
->lp_ctx
),
473 popt_get_cmdline_credentials(),
478 lpcfg_socket_options(tctx
->lp_ctx
),
479 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
)
481 if (!NT_STATUS_IS_OK(status
)) {
482 torture_comment(tctx
, "Failed to connect to SMB2 share \\\\%s\\%s - %s\n",
483 host
, share
, nt_errstr(status
));
490 create and return a handle to a test file
491 with a specific access mask
493 NTSTATUS
torture_smb2_testfile_access(struct smb2_tree
*tree
, const char *fname
,
494 struct smb2_handle
*handle
,
495 uint32_t desired_access
)
497 struct smb2_create io
;
501 io
.in
.oplock_level
= 0;
502 io
.in
.desired_access
= desired_access
;
503 io
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
504 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
506 NTCREATEX_SHARE_ACCESS_DELETE
|
507 NTCREATEX_SHARE_ACCESS_READ
|
508 NTCREATEX_SHARE_ACCESS_WRITE
;
509 io
.in
.create_options
= 0;
512 status
= smb2_create(tree
, tree
, &io
);
513 NT_STATUS_NOT_OK_RETURN(status
);
515 *handle
= io
.out
.file
.handle
;
521 create and return a handle to a test file
523 NTSTATUS
torture_smb2_testfile(struct smb2_tree
*tree
, const char *fname
,
524 struct smb2_handle
*handle
)
526 return torture_smb2_testfile_access(tree
, fname
, handle
,
527 SEC_RIGHTS_FILE_ALL
);
531 create and return a handle to a test directory
532 with specific desired access
534 NTSTATUS
torture_smb2_testdir_access(struct smb2_tree
*tree
, const char *fname
,
535 struct smb2_handle
*handle
,
536 uint32_t desired_access
)
538 struct smb2_create io
;
542 io
.in
.oplock_level
= 0;
543 io
.in
.desired_access
= desired_access
;
544 io
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
545 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
546 io
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|NTCREATEX_SHARE_ACCESS_WRITE
|NTCREATEX_SHARE_ACCESS_DELETE
;
547 io
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
550 status
= smb2_create(tree
, tree
, &io
);
551 NT_STATUS_NOT_OK_RETURN(status
);
553 *handle
= io
.out
.file
.handle
;
559 create and return a handle to a test directory
561 NTSTATUS
torture_smb2_testdir(struct smb2_tree
*tree
, const char *fname
,
562 struct smb2_handle
*handle
)
564 return torture_smb2_testdir_access(tree
, fname
, handle
,
569 create a complex file using SMB2, to make it easier to
570 find fields in SMB2 getinfo levels
572 NTSTATUS
torture_setup_complex_file(struct torture_context
*tctx
,
573 struct smb2_tree
*tree
, const char *fname
)
575 struct smb2_handle handle
;
576 NTSTATUS status
= smb2_create_complex_file(tctx
, tree
, fname
, &handle
);
577 NT_STATUS_NOT_OK_RETURN(status
);
578 return smb2_util_close(tree
, handle
);
583 create a complex dir using SMB2, to make it easier to
584 find fields in SMB2 getinfo levels
586 NTSTATUS
torture_setup_complex_dir(struct torture_context
*tctx
,
587 struct smb2_tree
*tree
, const char *fname
)
589 struct smb2_handle handle
;
590 NTSTATUS status
= smb2_create_complex_dir(tctx
, tree
, fname
, &handle
);
591 NT_STATUS_NOT_OK_RETURN(status
);
592 return smb2_util_close(tree
, handle
);
597 return a handle to the root of the share
599 NTSTATUS
smb2_util_roothandle(struct smb2_tree
*tree
, struct smb2_handle
*handle
)
601 struct smb2_create io
;
605 io
.in
.oplock_level
= 0;
606 io
.in
.desired_access
= SEC_STD_SYNCHRONIZE
| SEC_DIR_READ_ATTRIBUTE
| SEC_DIR_LIST
;
607 io
.in
.file_attributes
= 0;
608 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
609 io
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|NTCREATEX_SHARE_ACCESS_DELETE
;
610 io
.in
.create_options
= NTCREATEX_OPTIONS_ASYNC_ALERT
;
613 status
= smb2_create(tree
, tree
, &io
);
614 NT_STATUS_NOT_OK_RETURN(status
);
616 *handle
= io
.out
.file
.handle
;
621 /* Comparable to torture_setup_dir, but for SMB2. */
622 bool smb2_util_setup_dir(struct torture_context
*tctx
, struct smb2_tree
*tree
,
627 /* XXX: smb_raw_exit equivalent?
628 smb_raw_exit(cli->session); */
629 if (smb2_deltree(tree
, dname
) == -1) {
630 torture_result(tctx
, TORTURE_ERROR
, "Unable to deltree when setting up %s.\n", dname
);
634 status
= smb2_util_mkdir(tree
, dname
);
635 if (NT_STATUS_IS_ERR(status
)) {
636 torture_result(tctx
, TORTURE_ERROR
, "Unable to mkdir when setting up %s - %s\n", dname
,
644 #define CHECK_STATUS(status, correct) do { \
645 if (!NT_STATUS_EQUAL(status, correct)) { \
646 torture_result(tctx, TORTURE_FAIL, "(%s) Incorrect status %s - should be %s\n", \
647 __location__, nt_errstr(status), nt_errstr(correct)); \
653 * Helper function to verify a security descriptor, by querying
654 * and comparing against the passed in sd.
656 bool smb2_util_verify_sd(TALLOC_CTX
*tctx
, struct smb2_tree
*tree
,
657 struct smb2_handle handle
, struct security_descriptor
*sd
)
661 union smb_fileinfo q
= {};
663 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
664 q
.query_secdesc
.in
.file
.handle
= handle
;
665 q
.query_secdesc
.in
.secinfo_flags
=
669 status
= smb2_getinfo_file(tree
, tctx
, &q
);
670 CHECK_STATUS(status
, NT_STATUS_OK
);
672 if (!security_acl_equal(
673 q
.query_secdesc
.out
.sd
->dacl
, sd
->dacl
)) {
674 torture_warning(tctx
, "%s: security descriptors don't match!\n",
676 torture_warning(tctx
, "got:\n");
677 NDR_PRINT_DEBUG(security_descriptor
,
678 q
.query_secdesc
.out
.sd
);
679 torture_warning(tctx
, "expected:\n");
680 NDR_PRINT_DEBUG(security_descriptor
, sd
);
689 * Helper function to verify attributes, by querying
690 * and comparing against the passed in attrib.
692 bool smb2_util_verify_attrib(TALLOC_CTX
*tctx
, struct smb2_tree
*tree
,
693 struct smb2_handle handle
, uint32_t attrib
)
697 union smb_fileinfo q
= {};
699 q
.standard
.level
= RAW_FILEINFO_SMB2_ALL_INFORMATION
;
700 q
.standard
.in
.file
.handle
= handle
;
701 status
= smb2_getinfo_file(tree
, tctx
, &q
);
702 CHECK_STATUS(status
, NT_STATUS_OK
);
704 q
.all_info2
.out
.attrib
&= ~(FILE_ATTRIBUTE_ARCHIVE
| FILE_ATTRIBUTE_NONINDEXED
);
706 if (q
.all_info2
.out
.attrib
!= attrib
) {
707 torture_warning(tctx
, "%s: attributes don't match! "
708 "got %x, expected %x\n", __location__
,
709 (uint32_t)q
.standard
.out
.attrib
,
719 uint32_t smb2_util_lease_state(const char *ls
)
724 for (i
= 0; i
< strlen(ls
); i
++) {
727 val
|= SMB2_LEASE_READ
;
730 val
|= SMB2_LEASE_HANDLE
;
733 val
|= SMB2_LEASE_WRITE
;
742 uint32_t smb2_util_share_access(const char *sharemode
)
744 uint32_t val
= NTCREATEX_SHARE_ACCESS_NONE
; /* 0 */
747 for (i
= 0; i
< strlen(sharemode
); i
++) {
748 switch(sharemode
[i
]) {
750 val
|= NTCREATEX_SHARE_ACCESS_READ
;
753 val
|= NTCREATEX_SHARE_ACCESS_WRITE
;
756 val
|= NTCREATEX_SHARE_ACCESS_DELETE
;
764 uint8_t smb2_util_oplock_level(const char *op
)
766 uint8_t val
= SMB2_OPLOCK_LEVEL_NONE
;
769 for (i
= 0; i
< strlen(op
); i
++) {
772 return SMB2_OPLOCK_LEVEL_II
;
774 return SMB2_OPLOCK_LEVEL_EXCLUSIVE
;
776 return SMB2_OPLOCK_LEVEL_BATCH
;
786 * Helper functions to fill a smb2_create struct for several
789 void smb2_generic_create_share(struct smb2_create
*io
, struct smb2_lease
*ls
,
790 bool dir
, const char *name
, uint32_t disposition
,
791 uint32_t share_access
,
792 uint8_t oplock
, uint64_t leasekey
,
796 io
->in
.security_flags
= 0x00;
797 io
->in
.oplock_level
= oplock
;
798 io
->in
.impersonation_level
= NTCREATEX_IMPERSONATION_IMPERSONATION
;
799 io
->in
.create_flags
= 0x00000000;
800 io
->in
.reserved
= 0x00000000;
801 io
->in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
802 io
->in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
803 io
->in
.share_access
= share_access
;
804 io
->in
.create_disposition
= disposition
;
805 io
->in
.create_options
= NTCREATEX_OPTIONS_SEQUENTIAL_ONLY
|
806 NTCREATEX_OPTIONS_ASYNC_ALERT
|
807 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
|
812 io
->in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
813 io
->in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
814 io
->in
.create_disposition
= NTCREATEX_DISP_CREATE
;
819 ls
->lease_key
.data
[0] = leasekey
;
820 ls
->lease_key
.data
[1] = ~leasekey
;
821 ls
->lease_state
= leasestate
;
822 io
->in
.lease_request
= ls
;
826 void smb2_generic_create(struct smb2_create
*io
, struct smb2_lease
*ls
,
827 bool dir
, const char *name
, uint32_t disposition
,
828 uint8_t oplock
, uint64_t leasekey
,
831 smb2_generic_create_share(io
, ls
, dir
, name
, disposition
,
832 smb2_util_share_access("RWD"),
834 leasekey
, leasestate
);
837 void smb2_lease_create_share(struct smb2_create
*io
, struct smb2_lease
*ls
,
838 bool dir
, const char *name
, uint32_t share_access
,
839 uint64_t leasekey
, uint32_t leasestate
)
841 smb2_generic_create_share(io
, ls
, dir
, name
, NTCREATEX_DISP_OPEN_IF
,
842 share_access
, SMB2_OPLOCK_LEVEL_LEASE
,
843 leasekey
, leasestate
);
846 void smb2_lease_create(struct smb2_create
*io
, struct smb2_lease
*ls
,
847 bool dir
, const char *name
, uint64_t leasekey
,
850 smb2_lease_create_share(io
, ls
, dir
, name
,
851 smb2_util_share_access("RWD"),
852 leasekey
, leasestate
);
855 void smb2_lease_v2_create_share(struct smb2_create
*io
,
856 struct smb2_lease
*ls
,
859 uint32_t share_access
,
861 const uint64_t *parentleasekey
,
863 uint16_t lease_epoch
)
865 smb2_generic_create_share(io
, NULL
, dir
, name
, NTCREATEX_DISP_OPEN_IF
,
866 share_access
, SMB2_OPLOCK_LEVEL_LEASE
, 0, 0);
870 ls
->lease_key
.data
[0] = leasekey
;
871 ls
->lease_key
.data
[1] = ~leasekey
;
872 ls
->lease_state
= leasestate
;
873 if (parentleasekey
!= NULL
) {
874 ls
->lease_flags
|= SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET
;
875 ls
->parent_lease_key
.data
[0] = *parentleasekey
;
876 ls
->parent_lease_key
.data
[1] = ~(*parentleasekey
);
878 ls
->lease_epoch
= lease_epoch
;
879 io
->in
.lease_request_v2
= ls
;
883 void smb2_lease_v2_create(struct smb2_create
*io
,
884 struct smb2_lease
*ls
,
888 const uint64_t *parentleasekey
,
890 uint16_t lease_epoch
)
892 smb2_lease_v2_create_share(io
, ls
, dir
, name
,
893 smb2_util_share_access("RWD"),
894 leasekey
, parentleasekey
,
895 leasestate
, lease_epoch
);
899 void smb2_oplock_create_share(struct smb2_create
*io
, const char *name
,
900 uint32_t share_access
, uint8_t oplock
)
902 smb2_generic_create_share(io
, NULL
, false, name
, NTCREATEX_DISP_OPEN_IF
,
903 share_access
, oplock
, 0, 0);
905 void smb2_oplock_create(struct smb2_create
*io
, const char *name
, uint8_t oplock
)
907 smb2_oplock_create_share(io
, name
, smb2_util_share_access("RWD"),