seltest: implicit FILE_READ_DATA non-reporting
[Samba.git] / source4 / torture / smb2 / util.c
blobd0fc69590df966146f5b802382c80be218ad4b25
1 /*
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/>.
22 #include "includes.h"
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"
39 write to a file on SMB2
41 NTSTATUS smb2_util_write(struct smb2_tree *tree,
42 struct smb2_handle handle,
43 const void *buf, off_t offset, size_t size)
45 struct smb2_write w;
47 ZERO_STRUCT(w);
48 w.in.file.handle = handle;
49 w.in.offset = offset;
50 w.in.data = data_blob_const(buf, size);
52 return smb2_write(tree, &w);
56 create a complex file/dir using the SMB2 protocol
58 static NTSTATUS smb2_create_complex(struct smb2_tree *tree, const char *fname,
59 struct smb2_handle *handle, bool dir)
61 TALLOC_CTX *tmp_ctx = talloc_new(tree);
62 char buf[7] = "abc";
63 struct smb2_create io;
64 union smb_setfileinfo setfile;
65 union smb_fileinfo fileinfo;
66 time_t t = (time(NULL) & ~1);
67 NTSTATUS status;
69 smb2_util_unlink(tree, fname);
70 ZERO_STRUCT(io);
71 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
72 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
73 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
74 io.in.share_access =
75 NTCREATEX_SHARE_ACCESS_DELETE|
76 NTCREATEX_SHARE_ACCESS_READ|
77 NTCREATEX_SHARE_ACCESS_WRITE;
78 io.in.create_options = 0;
79 io.in.fname = fname;
80 if (dir) {
81 io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
82 io.in.share_access &= ~NTCREATEX_SHARE_ACCESS_DELETE;
83 io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
84 io.in.create_disposition = NTCREATEX_DISP_CREATE;
87 /* it seems vista is now fussier about alignment? */
88 if (strchr(fname, ':') == NULL) {
89 /* setup some EAs */
90 io.in.eas.num_eas = 2;
91 io.in.eas.eas = talloc_array(tmp_ctx, struct ea_struct, 2);
92 io.in.eas.eas[0].flags = 0;
93 io.in.eas.eas[0].name.s = "EAONE";
94 io.in.eas.eas[0].value = data_blob_talloc(tmp_ctx, "VALUE1", 6);
95 io.in.eas.eas[1].flags = 0;
96 io.in.eas.eas[1].name.s = "SECONDEA";
97 io.in.eas.eas[1].value = data_blob_talloc(tmp_ctx, "ValueTwo", 8);
100 status = smb2_create(tree, tmp_ctx, &io);
101 talloc_free(tmp_ctx);
102 NT_STATUS_NOT_OK_RETURN(status);
104 *handle = io.out.file.handle;
106 if (!dir) {
107 status = smb2_util_write(tree, *handle, buf, 0, sizeof(buf));
108 NT_STATUS_NOT_OK_RETURN(status);
111 /* make sure all the timestamps aren't the same, and are also
112 in different DST zones*/
113 setfile.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
114 setfile.generic.in.file.handle = *handle;
116 unix_to_nt_time(&setfile.basic_info.in.create_time, t + 9*30*24*60*60);
117 unix_to_nt_time(&setfile.basic_info.in.access_time, t + 6*30*24*60*60);
118 unix_to_nt_time(&setfile.basic_info.in.write_time, t + 3*30*24*60*60);
119 unix_to_nt_time(&setfile.basic_info.in.change_time, t + 1*30*24*60*60);
120 setfile.basic_info.in.attrib = FILE_ATTRIBUTE_NORMAL;
122 status = smb2_setinfo_file(tree, &setfile);
123 if (!NT_STATUS_IS_OK(status)) {
124 printf("Failed to setup file times - %s\n", nt_errstr(status));
125 return status;
128 /* make sure all the timestamps aren't the same */
129 fileinfo.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
130 fileinfo.generic.in.file.handle = *handle;
132 status = smb2_getinfo_file(tree, tree, &fileinfo);
133 if (!NT_STATUS_IS_OK(status)) {
134 printf("Failed to query file times - %s\n", nt_errstr(status));
135 return status;
139 #define CHECK_TIME(field) do {\
140 if (setfile.basic_info.in.field != fileinfo.all_info2.out.field) { \
141 printf("(%s) " #field " not setup correctly: %s(%llu) => %s(%llu)\n", \
142 __location__, \
143 nt_time_string(tree, setfile.basic_info.in.field), \
144 (unsigned long long)setfile.basic_info.in.field, \
145 nt_time_string(tree, fileinfo.basic_info.out.field), \
146 (unsigned long long)fileinfo.basic_info.out.field); \
147 status = NT_STATUS_INVALID_PARAMETER; \
149 } while (0)
151 CHECK_TIME(create_time);
152 CHECK_TIME(access_time);
153 CHECK_TIME(write_time);
154 CHECK_TIME(change_time);
156 return status;
160 create a complex file using the SMB2 protocol
162 NTSTATUS smb2_create_complex_file(struct smb2_tree *tree, const char *fname,
163 struct smb2_handle *handle)
165 return smb2_create_complex(tree, fname, handle, false);
169 create a complex dir using the SMB2 protocol
171 NTSTATUS smb2_create_complex_dir(struct smb2_tree *tree, const char *fname,
172 struct smb2_handle *handle)
174 return smb2_create_complex(tree, fname, handle, true);
178 show lots of information about a file
180 void torture_smb2_all_info(struct smb2_tree *tree, struct smb2_handle handle)
182 NTSTATUS status;
183 TALLOC_CTX *tmp_ctx = talloc_new(tree);
184 union smb_fileinfo io;
186 io.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
187 io.generic.in.file.handle = handle;
189 status = smb2_getinfo_file(tree, tmp_ctx, &io);
190 if (!NT_STATUS_IS_OK(status)) {
191 DEBUG(0,("getinfo failed - %s\n", nt_errstr(status)));
192 talloc_free(tmp_ctx);
193 return;
196 d_printf("all_info for '%s'\n", io.all_info2.out.fname.s);
197 d_printf("\tcreate_time: %s\n", nt_time_string(tmp_ctx, io.all_info2.out.create_time));
198 d_printf("\taccess_time: %s\n", nt_time_string(tmp_ctx, io.all_info2.out.access_time));
199 d_printf("\twrite_time: %s\n", nt_time_string(tmp_ctx, io.all_info2.out.write_time));
200 d_printf("\tchange_time: %s\n", nt_time_string(tmp_ctx, io.all_info2.out.change_time));
201 d_printf("\tattrib: 0x%x\n", io.all_info2.out.attrib);
202 d_printf("\tunknown1: 0x%x\n", io.all_info2.out.unknown1);
203 d_printf("\talloc_size: %llu\n", (long long)io.all_info2.out.alloc_size);
204 d_printf("\tsize: %llu\n", (long long)io.all_info2.out.size);
205 d_printf("\tnlink: %u\n", io.all_info2.out.nlink);
206 d_printf("\tdelete_pending: %u\n", io.all_info2.out.delete_pending);
207 d_printf("\tdirectory: %u\n", io.all_info2.out.directory);
208 d_printf("\tfile_id: %llu\n", (long long)io.all_info2.out.file_id);
209 d_printf("\tea_size: %u\n", io.all_info2.out.ea_size);
210 d_printf("\taccess_mask: 0x%08x\n", io.all_info2.out.access_mask);
211 d_printf("\tposition: 0x%llx\n", (long long)io.all_info2.out.position);
212 d_printf("\tmode: 0x%llx\n", (long long)io.all_info2.out.mode);
214 /* short name, if any */
215 io.generic.level = RAW_FILEINFO_ALT_NAME_INFORMATION;
216 status = smb2_getinfo_file(tree, tmp_ctx, &io);
217 if (NT_STATUS_IS_OK(status)) {
218 d_printf("\tshort name: '%s'\n", io.alt_name_info.out.fname.s);
221 /* the EAs, if any */
222 io.generic.level = RAW_FILEINFO_SMB2_ALL_EAS;
223 status = smb2_getinfo_file(tree, tmp_ctx, &io);
224 if (NT_STATUS_IS_OK(status)) {
225 int i;
226 for (i=0;i<io.all_eas.out.num_eas;i++) {
227 d_printf("\tEA[%d] flags=%d len=%d '%s'\n", i,
228 io.all_eas.out.eas[i].flags,
229 (int)io.all_eas.out.eas[i].value.length,
230 io.all_eas.out.eas[i].name.s);
234 /* streams, if available */
235 io.generic.level = RAW_FILEINFO_STREAM_INFORMATION;
236 status = smb2_getinfo_file(tree, tmp_ctx, &io);
237 if (NT_STATUS_IS_OK(status)) {
238 int i;
239 for (i=0;i<io.stream_info.out.num_streams;i++) {
240 d_printf("\tstream %d:\n", i);
241 d_printf("\t\tsize %ld\n",
242 (long)io.stream_info.out.streams[i].size);
243 d_printf("\t\talloc size %ld\n",
244 (long)io.stream_info.out.streams[i].alloc_size);
245 d_printf("\t\tname %s\n", io.stream_info.out.streams[i].stream_name.s);
249 if (DEBUGLVL(1)) {
250 /* the security descriptor */
251 io.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
252 io.query_secdesc.in.secinfo_flags =
253 SECINFO_OWNER|SECINFO_GROUP|
254 SECINFO_DACL;
255 status = smb2_getinfo_file(tree, tmp_ctx, &io);
256 if (NT_STATUS_IS_OK(status)) {
257 NDR_PRINT_DEBUG(security_descriptor, io.query_secdesc.out.sd);
261 talloc_free(tmp_ctx);
265 get granted access of a file handle
267 NTSTATUS torture_smb2_get_allinfo_access(struct smb2_tree *tree,
268 struct smb2_handle handle,
269 uint32_t *granted_access)
271 NTSTATUS status;
272 TALLOC_CTX *tmp_ctx = talloc_new(tree);
273 union smb_fileinfo io;
275 io.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
276 io.generic.in.file.handle = handle;
278 status = smb2_getinfo_file(tree, tmp_ctx, &io);
279 if (!NT_STATUS_IS_OK(status)) {
280 DEBUG(0, ("getinfo failed - %s\n", nt_errstr(status)));
281 goto out;
284 *granted_access = io.all_info2.out.access_mask;
286 out:
287 talloc_free(tmp_ctx);
288 return status;
292 * open a smb2 tree connect
294 bool torture_smb2_tree_connect(struct torture_context *tctx,
295 struct smb2_session *session,
296 TALLOC_CTX *mem_ctx,
297 struct smb2_tree **_tree)
299 NTSTATUS status;
300 const char *host = torture_setting_string(tctx, "host", NULL);
301 const char *share = torture_setting_string(tctx, "share", NULL);
302 const char *unc;
303 struct smb2_tree *tree;
304 struct tevent_req *subreq;
305 uint32_t timeout_msec;
307 unc = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
308 torture_assert(tctx, unc != NULL, "talloc_asprintf");
310 tree = smb2_tree_init(session, mem_ctx, false);
311 torture_assert(tctx, tree != NULL, "smb2_tree_init");
313 timeout_msec = session->transport->options.request_timeout * 1000;
315 subreq = smb2cli_tcon_send(tree, tctx->ev,
316 session->transport->conn,
317 timeout_msec,
318 session->smbXcli,
319 tree->smbXcli,
320 0, /* flags */
321 unc);
322 torture_assert(tctx, subreq != NULL, "smb2cli_tcon_send");
324 torture_assert(tctx,
325 tevent_req_poll_ntstatus(subreq, tctx->ev, &status),
326 "tevent_req_poll_ntstatus");
328 status = smb2cli_tcon_recv(subreq);
329 TALLOC_FREE(subreq);
330 torture_assert_ntstatus_ok(tctx, status, "smb2cli_tcon_recv");
332 *_tree = tree;
334 return true;
338 * do a smb2 session setup (without a tree connect)
340 bool torture_smb2_session_setup(struct torture_context *tctx,
341 struct smb2_transport *transport,
342 uint64_t previous_session_id,
343 TALLOC_CTX *mem_ctx,
344 struct smb2_session **_session)
346 NTSTATUS status;
347 struct smb2_session *session;
348 struct cli_credentials *credentials = cmdline_credentials;
350 session = smb2_session_init(transport,
351 lpcfg_gensec_settings(tctx, tctx->lp_ctx),
352 mem_ctx);
354 if (session == NULL) {
355 return false;
358 status = smb2_session_setup_spnego(session, credentials,
359 previous_session_id);
360 if (!NT_STATUS_IS_OK(status)) {
361 printf("session setup failed: %s\n", nt_errstr(status));
362 talloc_free(session);
363 return false;
366 *_session = session;
368 return true;
372 open a smb2 connection
374 bool torture_smb2_connection_ext(struct torture_context *tctx,
375 uint64_t previous_session_id,
376 const struct smbcli_options *options,
377 struct smb2_tree **tree)
379 NTSTATUS status;
380 const char *host = torture_setting_string(tctx, "host", NULL);
381 const char *share = torture_setting_string(tctx, "share", NULL);
382 struct cli_credentials *credentials = cmdline_credentials;
384 status = smb2_connect_ext(tctx,
385 host,
386 lpcfg_smb_ports(tctx->lp_ctx),
387 share,
388 lpcfg_resolve_context(tctx->lp_ctx),
389 credentials,
390 previous_session_id,
391 tree,
392 tctx->ev,
393 options,
394 lpcfg_socket_options(tctx->lp_ctx),
395 lpcfg_gensec_settings(tctx, tctx->lp_ctx)
397 if (!NT_STATUS_IS_OK(status)) {
398 printf("Failed to connect to SMB2 share \\\\%s\\%s - %s\n",
399 host, share, nt_errstr(status));
400 return false;
402 return true;
405 bool torture_smb2_connection(struct torture_context *tctx, struct smb2_tree **tree)
407 bool ret;
408 struct smbcli_options options;
410 lpcfg_smbcli_options(tctx->lp_ctx, &options);
412 ret = torture_smb2_connection_ext(tctx, 0, &options, tree);
414 return ret;
418 * SMB2 connect with share from soption
420 bool torture_smb2_con_sopt(struct torture_context *tctx,
421 const char *soption,
422 struct smb2_tree **tree)
424 struct smbcli_options options;
425 NTSTATUS status;
426 const char *host = torture_setting_string(tctx, "host", NULL);
427 const char *share = torture_setting_string(tctx, soption, NULL);
428 struct cli_credentials *credentials = cmdline_credentials;
430 lpcfg_smbcli_options(tctx->lp_ctx, &options);
432 if (share == NULL) {
433 printf("No share for option %s\n", soption);
434 return false;
437 status = smb2_connect_ext(tctx,
438 host,
439 lpcfg_smb_ports(tctx->lp_ctx),
440 share,
441 lpcfg_resolve_context(tctx->lp_ctx),
442 credentials,
444 tree,
445 tctx->ev,
446 &options,
447 lpcfg_socket_options(tctx->lp_ctx),
448 lpcfg_gensec_settings(tctx, tctx->lp_ctx)
450 if (!NT_STATUS_IS_OK(status)) {
451 printf("Failed to connect to SMB2 share \\\\%s\\%s - %s\n",
452 host, share, nt_errstr(status));
453 return false;
455 return true;
459 create and return a handle to a test file
460 with a specific access mask
462 NTSTATUS torture_smb2_testfile_access(struct smb2_tree *tree, const char *fname,
463 struct smb2_handle *handle,
464 uint32_t desired_access)
466 struct smb2_create io;
467 NTSTATUS status;
469 ZERO_STRUCT(io);
470 io.in.oplock_level = 0;
471 io.in.desired_access = desired_access;
472 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
473 io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
474 io.in.share_access =
475 NTCREATEX_SHARE_ACCESS_DELETE|
476 NTCREATEX_SHARE_ACCESS_READ|
477 NTCREATEX_SHARE_ACCESS_WRITE;
478 io.in.create_options = 0;
479 io.in.fname = fname;
481 status = smb2_create(tree, tree, &io);
482 NT_STATUS_NOT_OK_RETURN(status);
484 *handle = io.out.file.handle;
486 return NT_STATUS_OK;
490 create and return a handle to a test file
492 NTSTATUS torture_smb2_testfile(struct smb2_tree *tree, const char *fname,
493 struct smb2_handle *handle)
495 return torture_smb2_testfile_access(tree, fname, handle,
496 SEC_RIGHTS_FILE_ALL);
500 create and return a handle to a test directory
501 with specific desired access
503 NTSTATUS torture_smb2_testdir_access(struct smb2_tree *tree, const char *fname,
504 struct smb2_handle *handle,
505 uint32_t desired_access)
507 struct smb2_create io;
508 NTSTATUS status;
510 ZERO_STRUCT(io);
511 io.in.oplock_level = 0;
512 io.in.desired_access = desired_access;
513 io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
514 io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
515 io.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE;
516 io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
517 io.in.fname = fname;
519 status = smb2_create(tree, tree, &io);
520 NT_STATUS_NOT_OK_RETURN(status);
522 *handle = io.out.file.handle;
524 return NT_STATUS_OK;
528 create and return a handle to a test directory
530 NTSTATUS torture_smb2_testdir(struct smb2_tree *tree, const char *fname,
531 struct smb2_handle *handle)
533 return torture_smb2_testdir_access(tree, fname, handle,
534 SEC_RIGHTS_DIR_ALL);
538 create a complex file using SMB2, to make it easier to
539 find fields in SMB2 getinfo levels
541 NTSTATUS torture_setup_complex_file(struct smb2_tree *tree, const char *fname)
543 struct smb2_handle handle;
544 NTSTATUS status = smb2_create_complex_file(tree, fname, &handle);
545 NT_STATUS_NOT_OK_RETURN(status);
546 return smb2_util_close(tree, handle);
551 create a complex dir using SMB2, to make it easier to
552 find fields in SMB2 getinfo levels
554 NTSTATUS torture_setup_complex_dir(struct smb2_tree *tree, const char *fname)
556 struct smb2_handle handle;
557 NTSTATUS status = smb2_create_complex_dir(tree, fname, &handle);
558 NT_STATUS_NOT_OK_RETURN(status);
559 return smb2_util_close(tree, handle);
564 return a handle to the root of the share
566 NTSTATUS smb2_util_roothandle(struct smb2_tree *tree, struct smb2_handle *handle)
568 struct smb2_create io;
569 NTSTATUS status;
571 ZERO_STRUCT(io);
572 io.in.oplock_level = 0;
573 io.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_DIR_READ_ATTRIBUTE | SEC_DIR_LIST;
574 io.in.file_attributes = 0;
575 io.in.create_disposition = NTCREATEX_DISP_OPEN;
576 io.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE;
577 io.in.create_options = NTCREATEX_OPTIONS_ASYNC_ALERT;
578 io.in.fname = "";
580 status = smb2_create(tree, tree, &io);
581 NT_STATUS_NOT_OK_RETURN(status);
583 *handle = io.out.file.handle;
585 return NT_STATUS_OK;
588 /* Comparable to torture_setup_dir, but for SMB2. */
589 bool smb2_util_setup_dir(struct torture_context *tctx, struct smb2_tree *tree,
590 const char *dname)
592 NTSTATUS status;
594 /* XXX: smb_raw_exit equivalent?
595 smb_raw_exit(cli->session); */
596 if (smb2_deltree(tree, dname) == -1) {
597 torture_result(tctx, TORTURE_ERROR, "Unable to deltree when setting up %s.\n", dname);
598 return false;
601 status = smb2_util_mkdir(tree, dname);
602 if (NT_STATUS_IS_ERR(status)) {
603 torture_result(tctx, TORTURE_ERROR, "Unable to mkdir when setting up %s - %s\n", dname,
604 nt_errstr(status));
605 return false;
608 return true;
611 #define CHECK_STATUS(status, correct) do { \
612 if (!NT_STATUS_EQUAL(status, correct)) { \
613 torture_result(tctx, TORTURE_FAIL, "(%s) Incorrect status %s - should be %s\n", \
614 __location__, nt_errstr(status), nt_errstr(correct)); \
615 ret = false; \
616 goto done; \
617 }} while (0)
620 * Helper function to verify a security descriptor, by querying
621 * and comparing against the passed in sd.
623 bool smb2_util_verify_sd(TALLOC_CTX *tctx, struct smb2_tree *tree,
624 struct smb2_handle handle, struct security_descriptor *sd)
626 NTSTATUS status;
627 bool ret = true;
628 union smb_fileinfo q = {};
630 q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
631 q.query_secdesc.in.file.handle = handle;
632 q.query_secdesc.in.secinfo_flags =
633 SECINFO_OWNER |
634 SECINFO_GROUP |
635 SECINFO_DACL;
636 status = smb2_getinfo_file(tree, tctx, &q);
637 CHECK_STATUS(status, NT_STATUS_OK);
639 if (!security_acl_equal(
640 q.query_secdesc.out.sd->dacl, sd->dacl)) {
641 torture_warning(tctx, "%s: security descriptors don't match!\n",
642 __location__);
643 torture_warning(tctx, "got:\n");
644 NDR_PRINT_DEBUG(security_descriptor,
645 q.query_secdesc.out.sd);
646 torture_warning(tctx, "expected:\n");
647 NDR_PRINT_DEBUG(security_descriptor, sd);
648 ret = false;
651 done:
652 return ret;
656 * Helper function to verify attributes, by querying
657 * and comparing against the passed in attrib.
659 bool smb2_util_verify_attrib(TALLOC_CTX *tctx, struct smb2_tree *tree,
660 struct smb2_handle handle, uint32_t attrib)
662 NTSTATUS status;
663 bool ret = true;
664 union smb_fileinfo q = {};
666 q.standard.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
667 q.standard.in.file.handle = handle;
668 status = smb2_getinfo_file(tree, tctx, &q);
669 CHECK_STATUS(status, NT_STATUS_OK);
671 q.all_info2.out.attrib &= ~(FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_NONINDEXED);
673 if (q.all_info2.out.attrib != attrib) {
674 torture_warning(tctx, "%s: attributes don't match! "
675 "got %x, expected %x\n", __location__,
676 (uint32_t)q.standard.out.attrib,
677 (uint32_t)attrib);
678 ret = false;
681 done:
682 return ret;
686 uint32_t smb2_util_lease_state(const char *ls)
688 uint32_t val = 0;
689 int i;
691 for (i = 0; i < strlen(ls); i++) {
692 switch (ls[i]) {
693 case 'R':
694 val |= SMB2_LEASE_READ;
695 break;
696 case 'H':
697 val |= SMB2_LEASE_HANDLE;
698 break;
699 case 'W':
700 val |= SMB2_LEASE_WRITE;
701 break;
705 return val;
709 uint32_t smb2_util_share_access(const char *sharemode)
711 uint32_t val = NTCREATEX_SHARE_ACCESS_NONE; /* 0 */
712 int i;
714 for (i = 0; i < strlen(sharemode); i++) {
715 switch(sharemode[i]) {
716 case 'R':
717 val |= NTCREATEX_SHARE_ACCESS_READ;
718 break;
719 case 'W':
720 val |= NTCREATEX_SHARE_ACCESS_WRITE;
721 break;
722 case 'D':
723 val |= NTCREATEX_SHARE_ACCESS_DELETE;
724 break;
728 return val;
731 uint8_t smb2_util_oplock_level(const char *op)
733 uint8_t val = SMB2_OPLOCK_LEVEL_NONE;
734 int i;
736 for (i = 0; i < strlen(op); i++) {
737 switch (op[i]) {
738 case 's':
739 return SMB2_OPLOCK_LEVEL_II;
740 case 'x':
741 return SMB2_OPLOCK_LEVEL_EXCLUSIVE;
742 case 'b':
743 return SMB2_OPLOCK_LEVEL_BATCH;
744 default:
745 continue;
749 return val;
753 * Helper functions to fill a smb2_create struct for several
754 * open scenarios.
756 void smb2_generic_create_share(struct smb2_create *io, struct smb2_lease *ls,
757 bool dir, const char *name, uint32_t disposition,
758 uint32_t share_access,
759 uint8_t oplock, uint64_t leasekey,
760 uint32_t leasestate)
762 ZERO_STRUCT(*io);
763 io->in.security_flags = 0x00;
764 io->in.oplock_level = oplock;
765 io->in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
766 io->in.create_flags = 0x00000000;
767 io->in.reserved = 0x00000000;
768 io->in.desired_access = SEC_RIGHTS_FILE_ALL;
769 io->in.file_attributes = FILE_ATTRIBUTE_NORMAL;
770 io->in.share_access = share_access;
771 io->in.create_disposition = disposition;
772 io->in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
773 NTCREATEX_OPTIONS_ASYNC_ALERT |
774 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
775 0x00200000;
776 io->in.fname = name;
778 if (dir) {
779 io->in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
780 io->in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
781 io->in.create_disposition = NTCREATEX_DISP_CREATE;
784 if (ls) {
785 ZERO_STRUCTPN(ls);
786 ls->lease_key.data[0] = leasekey;
787 ls->lease_key.data[1] = ~leasekey;
788 ls->lease_state = leasestate;
789 io->in.lease_request = ls;
793 void smb2_generic_create(struct smb2_create *io, struct smb2_lease *ls,
794 bool dir, const char *name, uint32_t disposition,
795 uint8_t oplock, uint64_t leasekey,
796 uint32_t leasestate)
798 smb2_generic_create_share(io, ls, dir, name, disposition,
799 smb2_util_share_access("RWD"),
800 oplock,
801 leasekey, leasestate);
804 void smb2_lease_create_share(struct smb2_create *io, struct smb2_lease *ls,
805 bool dir, const char *name, uint32_t share_access,
806 uint64_t leasekey, uint32_t leasestate)
808 smb2_generic_create_share(io, ls, dir, name, NTCREATEX_DISP_OPEN_IF,
809 share_access, SMB2_OPLOCK_LEVEL_LEASE,
810 leasekey, leasestate);
813 void smb2_lease_create(struct smb2_create *io, struct smb2_lease *ls,
814 bool dir, const char *name, uint64_t leasekey,
815 uint32_t leasestate)
817 smb2_lease_create_share(io, ls, dir, name,
818 smb2_util_share_access("RWD"),
819 leasekey, leasestate);
822 void smb2_lease_v2_create_share(struct smb2_create *io,
823 struct smb2_lease *ls,
824 bool dir,
825 const char *name,
826 uint32_t share_access,
827 uint64_t leasekey,
828 const uint64_t *parentleasekey,
829 uint32_t leasestate,
830 uint16_t lease_epoch)
832 smb2_generic_create_share(io, NULL, dir, name, NTCREATEX_DISP_OPEN_IF,
833 share_access, SMB2_OPLOCK_LEVEL_LEASE, 0, 0);
835 if (ls) {
836 ZERO_STRUCT(*ls);
837 ls->lease_key.data[0] = leasekey;
838 ls->lease_key.data[1] = ~leasekey;
839 ls->lease_state = leasestate;
840 if (parentleasekey != NULL) {
841 ls->lease_flags |= SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET;
842 ls->parent_lease_key.data[0] = *parentleasekey;
843 ls->parent_lease_key.data[1] = ~(*parentleasekey);
845 ls->lease_epoch = lease_epoch;
846 io->in.lease_request_v2 = ls;
850 void smb2_lease_v2_create(struct smb2_create *io,
851 struct smb2_lease *ls,
852 bool dir,
853 const char *name,
854 uint64_t leasekey,
855 const uint64_t *parentleasekey,
856 uint32_t leasestate,
857 uint16_t lease_epoch)
859 smb2_lease_v2_create_share(io, ls, dir, name,
860 smb2_util_share_access("RWD"),
861 leasekey, parentleasekey,
862 leasestate, lease_epoch);
866 void smb2_oplock_create_share(struct smb2_create *io, const char *name,
867 uint32_t share_access, uint8_t oplock)
869 smb2_generic_create_share(io, NULL, false, name, NTCREATEX_DISP_OPEN_IF,
870 share_access, oplock, 0, 0);
872 void smb2_oplock_create(struct smb2_create *io, const char *name, uint8_t oplock)
874 smb2_oplock_create_share(io, name, smb2_util_share_access("RWD"),
875 oplock);