s4:torture:smb2: add smb2_oplock_create_share() that takes sharemode as parameter
[bbaumbach/samba-autobuild/.git] / source4 / torture / smb2 / util.c
index 4995bbe978bb11473d3994300523f1dab961e918..094161e6eb9ab0e8281d46c71ec7dc93da8f7fbd 100644 (file)
 */
 
 #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
 */
@@ -296,11 +269,22 @@ bool torture_smb2_connection(struct torture_context *tctx, struct smb2_tree **tr
        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));
@@ -317,7 +301,6 @@ NTSTATUS torture_smb2_testfile(struct smb2_tree *tree, const char *fname,
                               struct smb2_handle *handle)
 {
        struct smb2_create io;
-       struct smb2_read r;
        NTSTATUS status;
 
        ZERO_STRUCT(io);
@@ -337,13 +320,6 @@ NTSTATUS torture_smb2_testfile(struct smb2_tree *tree, const char *fname,
 
        *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;
 }
 
@@ -375,7 +351,7 @@ NTSTATUS torture_smb2_testdir(struct smb2_tree *tree, const char *fname,
 
 
 /*
-  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)
@@ -388,7 +364,7 @@ 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)
@@ -424,3 +400,251 @@ NTSTATUS smb2_util_roothandle(struct smb2_tree *tree, struct smb2_handle *handle
 
        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);
+}
+