s4-torture: Add helper functions to create channels.
authorSachin Prabhu <sprabhu@redhat.com>
Thu, 28 Feb 2019 12:09:08 +0000 (12:09 +0000)
committerJeremy Allison <jra@samba.org>
Fri, 19 Apr 2019 17:27:13 +0000 (17:27 +0000)
Helper functions used by both oplock and lease break tests.

Signed-off-by: Guenther Deschner <gd@samba.org>
Signed-off-by: Sachin Prabhu <sprabhu@redhat.com>
Reviewed-by: Jeremy Allison <jra@samba.org>
source4/torture/smb2/multichannel.c

index 9aba784a98010365f68f0da19fa7ffc94699ceba..5207fa453da5128b05bd5b05ab8fc237d4cbd726 100644 (file)
 #include "libcli/smb2/smb2.h"
 #include "libcli/smb2/smb2_calls.h"
 #include "torture/torture.h"
-#include "torture/util.h"
 #include "torture/smb2/proto.h"
 #include "libcli/security/security.h"
 #include "librpc/gen_ndr/ndr_security.h"
 #include "librpc/gen_ndr/ndr_ioctl.h"
 #include "../libcli/smb/smbXcli_base.h"
+#include "libcli/resolve/resolve.h"
+#include "lib/param/param.h"
 
 #define BASEDIR "multichanneltestdir"
 
@@ -156,6 +157,151 @@ static bool test_multichannel_interface_info(struct torture_context *tctx,
        return test_ioctl_network_interface_info(tctx, tree, &info);
 }
 
+static struct smb2_tree *test_multichannel_create_channel(
+                               struct torture_context *tctx,
+                               const char *host,
+                               const char *share,
+                               struct cli_credentials *credentials,
+                               struct smbcli_options *transport_options,
+                               struct smb2_tree *parent_tree
+                               )
+{
+       NTSTATUS status;
+       struct smb2_transport *transport;
+       struct smb2_session *session;
+       bool ret = true;
+       struct smb2_tree *tree;
+
+       status = smb2_connect(tctx,
+                       host,
+                       lpcfg_smb_ports(tctx->lp_ctx),
+                       share,
+                       lpcfg_resolve_context(tctx->lp_ctx),
+                       credentials,
+                       &tree,
+                       tctx->ev,
+                       transport_options,
+                       lpcfg_socket_options(tctx->lp_ctx),
+                       lpcfg_gensec_settings(tctx, tctx->lp_ctx)
+                       );
+       torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+                       "smb2_connect failed");
+       transport = tree->session->transport;
+       transport->oplock.handler = torture_oplock_ack_handler;
+       transport->oplock.private_data = tree;
+       transport->lease.handler = torture_lease_handler;
+       transport->lease.private_data = tree;
+       torture_comment(tctx, "established transport [%p]\n", transport);
+
+       /*
+        * If parent tree is set, bind the session to the parent transport
+        */
+       if (parent_tree) {
+               session = smb2_session_channel(transport,
+                               lpcfg_gensec_settings(tctx, tctx->lp_ctx),
+                               parent_tree, parent_tree->session);
+               torture_assert_goto(tctx, session != NULL, ret, done,
+                               "smb2_session_channel failed");
+
+               tree->smbXcli = parent_tree->smbXcli;
+               tree->session = session;
+               status = smb2_session_setup_spnego(session,
+                                               credentials,
+                                               0 /* previous_session_id */);
+               CHECK_STATUS(status, NT_STATUS_OK);
+               torture_comment(tctx, "bound new session to parent\n");
+       }
+       /*
+        * We absolutely need to make sure to send something over this
+        * connection to register the oplock break handler with the smb client
+        * connection. If we do not send something (at least a keepalive), we
+        * will *NEVER* receive anything over this transport.
+        */
+       smb2_keepalive(transport);
+
+done:
+       if (ret) {
+               return tree;
+       } else {
+               return NULL;
+       }
+}
+
+bool test_multichannel_create_channels(
+                               struct torture_context *tctx,
+                               const char *host,
+                               const char *share,
+                               struct cli_credentials *credentials,
+                               struct smbcli_options *transport_options,
+                               struct smb2_tree **tree2A,
+                               struct smb2_tree **tree2B,
+                               struct smb2_tree **tree2C
+                               )
+{
+       struct smb2_tree *tree;
+       struct smb2_transport *transport2A;
+       struct smb2_transport *transport2B;
+       struct smb2_transport *transport2C;
+       uint16_t local_port = 0;
+
+       transport_options->client_guid = GUID_random();
+
+       /* Session 2A */
+       torture_comment(tctx, "Setting up connection 2A\n");
+       tree = test_multichannel_create_channel(tctx, host, share,
+                               credentials, transport_options, NULL);
+       if (!tree) {
+               goto done;
+       }
+       *tree2A = tree;
+       transport2A = tree->session->transport;
+       local_port = torture_get_local_port_from_transport(transport2A);
+       torture_comment(tctx, "transport2A uses tcp port: %d\n", local_port);
+
+       /* Session 2B */
+       if (tree2B) {
+               torture_comment(tctx, "Setting up connection 2B\n");
+               tree = test_multichannel_create_channel(tctx, host, share,
+                               credentials, transport_options, *tree2A);
+               if (!tree) {
+                       goto done;
+               }
+               *tree2B = tree;
+               transport2B = tree->session->transport;
+               local_port = torture_get_local_port_from_transport(transport2B);
+               torture_comment(tctx, "transport2B uses tcp port: %d\n",
+                                                               local_port);
+       }
+
+       /* Session 2C */
+       if (tree2C) {
+               torture_comment(tctx, "Setting up connection 2C\n");
+               tree = test_multichannel_create_channel(tctx, host, share,
+                               credentials, transport_options, *tree2A);
+               if (!tree) {
+                       goto done;
+               }
+               *tree2C = tree;
+               transport2C = tree->session->transport;
+               local_port = torture_get_local_port_from_transport(transport2C);
+               torture_comment(tctx, "transport2C uses tcp port: %d\n",
+                                                               local_port);
+       }
+
+       return true;
+done:
+       return false;
+}
+
+static void test_multichannel_free_channels(struct smb2_tree *tree2A,
+                                            struct smb2_tree *tree2B,
+                                            struct smb2_tree *tree2C)
+{
+       TALLOC_FREE(tree2A);
+       TALLOC_FREE(tree2B);
+       TALLOC_FREE(tree2C);
+}
+
 struct torture_suite *torture_smb2_multichannel_init(TALLOC_CTX *ctx)
 {
        struct torture_suite *suite = torture_suite_create(ctx, "multichannel");