*/
#include "includes.h"
+#include "libcli/security/security_descriptor.h"
#include "libcli/smb2/smb2.h"
#include "libcli/smb2/smb2_calls.h"
-#include "libcli/smb_composite/smb_composite.h"
#include "lib/cmdline/popt_common.h"
-#include "lib/events/events.h"
#include "system/time.h"
#include "librpc/gen_ndr/ndr_security.h"
#include "param/param.h"
#include "torture/smb2/proto.h"
-/*
- close a handle with SMB2
-*/
-NTSTATUS smb2_util_close(struct smb2_tree *tree, struct smb2_handle h)
-{
- struct smb2_close c;
-
- ZERO_STRUCT(c);
- c.in.file.handle = h;
-
- return smb2_close(tree, &c);
-}
-
-/*
- unlink a file with SMB2
-*/
-NTSTATUS smb2_util_unlink(struct smb2_tree *tree, const char *fname)
-{
- union smb_unlink io;
-
- ZERO_STRUCT(io);
- io.unlink.in.pattern = fname;
-
- return smb2_composite_unlink(tree, &io);
-}
-
/*
write to a file on SMB2
*/
const char *host = torture_setting_string(tctx, "host", NULL);
const char *share = torture_setting_string(tctx, "share", NULL);
struct cli_credentials *credentials = cmdline_credentials;
-
- status = smb2_connect(tctx, host, share,
- lp_resolve_context(tctx->lp_ctx),
- credentials, tree,
- tctx->ev);
+ struct smbcli_options options;
+
+ lpcfg_smbcli_options(tctx->lp_ctx, &options);
+
+ status = smb2_connect(tctx,
+ host,
+ lpcfg_smb_ports(tctx->lp_ctx),
+ share,
+ lpcfg_resolve_context(tctx->lp_ctx),
+ credentials,
+ tree,
+ tctx->ev,
+ &options,
+ lpcfg_socket_options(tctx->lp_ctx),
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx)
+ );
if (!NT_STATUS_IS_OK(status)) {
printf("Failed to connect to SMB2 share \\\\%s\\%s - %s\n",
host, share, nt_errstr(status));
struct smb2_handle *handle)
{
struct smb2_create io;
- struct smb2_read r;
NTSTATUS status;
ZERO_STRUCT(io);
*handle = io.out.file.handle;
- ZERO_STRUCT(r);
- r.in.file.handle = *handle;
- r.in.length = 5;
- r.in.offset = 0;
-
- smb2_read(tree, tree, &r);
-
return NT_STATUS_OK;
}
/*
- create a complex file using the old SMB protocol, to make it easier to
+ create a complex file using SMB2, to make it easier to
find fields in SMB2 getinfo levels
*/
NTSTATUS torture_setup_complex_file(struct smb2_tree *tree, const char *fname)
/*
- create a complex dir using the old SMB protocol, to make it easier to
+ create a complex dir using SMB2, to make it easier to
find fields in SMB2 getinfo levels
*/
NTSTATUS torture_setup_complex_dir(struct smb2_tree *tree, const char *fname)
return NT_STATUS_OK;
}
+
+/* Comparable to torture_setup_dir, but for SMB2. */
+bool smb2_util_setup_dir(struct torture_context *tctx, struct smb2_tree *tree,
+ const char *dname)
+{
+ NTSTATUS status;
+
+ /* XXX: smb_raw_exit equivalent?
+ smb_raw_exit(cli->session); */
+ if (smb2_deltree(tree, dname) == -1) {
+ torture_result(tctx, TORTURE_ERROR, "Unable to deltree when setting up %s.\n", dname);
+ return false;
+ }
+
+ status = smb2_util_mkdir(tree, dname);
+ if (NT_STATUS_IS_ERR(status)) {
+ torture_result(tctx, TORTURE_ERROR, "Unable to mkdir when setting up %s - %s\n", dname,
+ nt_errstr(status));
+ return false;
+ }
+
+ return true;
+}
+
+#define CHECK_STATUS(status, correct) do { \
+ if (!NT_STATUS_EQUAL(status, correct)) { \
+ torture_result(tctx, TORTURE_FAIL, "(%s) Incorrect status %s - should be %s\n", \
+ __location__, nt_errstr(status), nt_errstr(correct)); \
+ ret = false; \
+ goto done; \
+ }} while (0)
+
+/*
+ * Helper function to verify a security descriptor, by querying
+ * and comparing against the passed in sd.
+ */
+bool smb2_util_verify_sd(TALLOC_CTX *tctx, struct smb2_tree *tree,
+ struct smb2_handle handle, struct security_descriptor *sd)
+{
+ NTSTATUS status;
+ bool ret = true;
+ union smb_fileinfo q = {};
+
+ q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
+ q.query_secdesc.in.file.handle = handle;
+ q.query_secdesc.in.secinfo_flags =
+ SECINFO_OWNER |
+ SECINFO_GROUP |
+ SECINFO_DACL;
+ status = smb2_getinfo_file(tree, tctx, &q);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ if (!security_acl_equal(
+ q.query_secdesc.out.sd->dacl, sd->dacl)) {
+ torture_warning(tctx, "%s: security descriptors don't match!\n",
+ __location__);
+ torture_warning(tctx, "got:\n");
+ NDR_PRINT_DEBUG(security_descriptor,
+ q.query_secdesc.out.sd);
+ torture_warning(tctx, "expected:\n");
+ NDR_PRINT_DEBUG(security_descriptor, sd);
+ ret = false;
+ }
+
+ done:
+ return ret;
+}
+
+/*
+ * Helper function to verify attributes, by querying
+ * and comparing against the passed in attrib.
+ */
+bool smb2_util_verify_attrib(TALLOC_CTX *tctx, struct smb2_tree *tree,
+ struct smb2_handle handle, uint32_t attrib)
+{
+ NTSTATUS status;
+ bool ret = true;
+ union smb_fileinfo q = {};
+
+ q.standard.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
+ q.standard.in.file.handle = handle;
+ status = smb2_getinfo_file(tree, tctx, &q);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ q.all_info2.out.attrib &= ~FILE_ATTRIBUTE_ARCHIVE;
+
+ if (q.all_info2.out.attrib != attrib) {
+ torture_warning(tctx, "%s: attributes don't match! "
+ "got %x, expected %x\n", __location__,
+ (uint32_t)q.standard.out.attrib,
+ (uint32_t)attrib);
+ ret = false;
+ }
+
+ done:
+ return ret;
+}
+
+
+uint32_t smb2_util_lease_state(const char *ls)
+{
+ uint32_t val = 0;
+ int i;
+
+ for (i = 0; i < strlen(ls); i++) {
+ switch (ls[i]) {
+ case 'R':
+ val |= SMB2_LEASE_READ;
+ break;
+ case 'H':
+ val |= SMB2_LEASE_HANDLE;
+ break;
+ case 'W':
+ val |= SMB2_LEASE_WRITE;
+ break;
+ }
+ }
+
+ return val;
+}
+
+
+uint32_t smb2_util_share_access(const char *sharemode)
+{
+ uint32_t val = NTCREATEX_SHARE_ACCESS_NONE; /* 0 */
+ int i;
+
+ for (i = 0; i < strlen(sharemode); i++) {
+ switch(sharemode[i]) {
+ case 'R':
+ val |= NTCREATEX_SHARE_ACCESS_READ;
+ break;
+ case 'W':
+ val |= NTCREATEX_SHARE_ACCESS_WRITE;
+ break;
+ case 'D':
+ val |= NTCREATEX_SHARE_ACCESS_DELETE;
+ break;
+ }
+ }
+
+ return val;
+}
+
+uint8_t smb2_util_oplock_level(const char *op)
+{
+ uint8_t val = SMB2_OPLOCK_LEVEL_NONE;
+ int i;
+
+ for (i = 0; i < strlen(op); i++) {
+ switch (op[i]) {
+ case 's':
+ return SMB2_OPLOCK_LEVEL_II;
+ case 'x':
+ return SMB2_OPLOCK_LEVEL_EXCLUSIVE;
+ case 'b':
+ return SMB2_OPLOCK_LEVEL_BATCH;
+ default:
+ continue;
+ }
+ }
+
+ return val;
+}
+
+/**
+ * Helper functions to fill a smb2_create struct for several
+ * open scenarios.
+ */
+void smb2_generic_create_share(struct smb2_create *io, struct smb2_lease *ls,
+ bool dir, const char *name, uint32_t disposition,
+ uint32_t share_access,
+ uint8_t oplock, uint64_t leasekey,
+ uint32_t leasestate)
+{
+ ZERO_STRUCT(*io);
+ io->in.security_flags = 0x00;
+ io->in.oplock_level = oplock;
+ io->in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+ io->in.create_flags = 0x00000000;
+ io->in.reserved = 0x00000000;
+ io->in.desired_access = SEC_RIGHTS_FILE_ALL;
+ io->in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ io->in.share_access = share_access;
+ io->in.create_disposition = disposition;
+ io->in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
+ NTCREATEX_OPTIONS_ASYNC_ALERT |
+ NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
+ 0x00200000;
+ io->in.fname = name;
+
+ if (dir) {
+ io->in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+ io->in.share_access &= ~NTCREATEX_SHARE_ACCESS_DELETE;
+ io->in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
+ io->in.create_disposition = NTCREATEX_DISP_CREATE;
+ }
+
+ if (ls) {
+ ZERO_STRUCT(*ls);
+ ls->lease_key.data[0] = leasekey;
+ ls->lease_key.data[1] = ~leasekey;
+ ls->lease_state = leasestate;
+ io->in.lease_request = ls;
+ }
+}
+
+void smb2_generic_create(struct smb2_create *io, struct smb2_lease *ls,
+ bool dir, const char *name, uint32_t disposition,
+ uint8_t oplock, uint64_t leasekey,
+ uint32_t leasestate)
+{
+ smb2_generic_create_share(io, ls, dir, name, disposition,
+ smb2_util_share_access("RWD"),
+ oplock,
+ leasekey, leasestate);
+}
+
+void smb2_lease_create_share(struct smb2_create *io, struct smb2_lease *ls,
+ bool dir, const char *name, uint32_t share_access,
+ uint64_t leasekey, uint32_t leasestate)
+{
+ smb2_generic_create_share(io, ls, dir, name, NTCREATEX_DISP_OPEN_IF,
+ share_access, SMB2_OPLOCK_LEVEL_LEASE,
+ leasekey, leasestate);
+}
+
+void smb2_lease_create(struct smb2_create *io, struct smb2_lease *ls,
+ bool dir, const char *name, uint64_t leasekey,
+ uint32_t leasestate)
+{
+ smb2_lease_create_share(io, ls, dir, name,
+ smb2_util_share_access("RWD"),
+ leasekey, leasestate);
+}
+
+void smb2_oplock_create_share(struct smb2_create *io, const char *name,
+ uint32_t share_access, uint8_t oplock)
+{
+ smb2_generic_create_share(io, NULL, false, name, NTCREATEX_DISP_OPEN_IF,
+ share_access, oplock, 0, 0);
+}
+void smb2_oplock_create(struct smb2_create *io, const char *name, uint8_t oplock)
+{
+ smb2_oplock_create_share(io, name, smb2_util_share_access("RWD"),
+ oplock);
+}
+