simple echo rawpipe torture test npower_wsp_rawpipe
authorNoel Power <noel.power@suse.com>
Tue, 9 Jan 2024 15:27:48 +0000 (15:27 +0000)
committerNoel Power <noel.power@suse.com>
Tue, 9 Jan 2024 16:08:57 +0000 (16:08 +0000)
Signed-off-by: Noel Power <noel.power@suse.com>
source4/selftest/tests.py
source4/torture/rpc/rawpipe.c [new file with mode: 0644]
source4/torture/rpc/rpc.c
source4/torture/wscript_build

index 2ab930a6c9a6eb362a91f8c381e3eb59d453ebf3..ddbaa2f359a7e673c41c76258658224990af861f 100755 (executable)
@@ -284,6 +284,8 @@ for bindoptions in [""] + validate_list + ["bigendian"]:
             env = "ad_dc_ntvfs"
         elif t == "rpc.join":
             env = "ad_dc_default_smb1"
+        elif t in ["rpc.rawpipe"]:
+            env = "fileserver"
         plansmbtorture4testsuite(t, env, ["$SERVER[%s]" % bindoptions, '-U$USERNAME%$PASSWORD', '--workgroup=$DOMAIN'], "samba4.%s with %s" % (t, bindoptions))
 
 t = "rpc.countcalls"
diff --git a/source4/torture/rpc/rawpipe.c b/source4/torture/rpc/rawpipe.c
new file mode 100644 (file)
index 0000000..b0a1acd
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+   Unix SMB/CIFS implementation.
+   test suite for lsa rpc operations
+
+   Copyright (C) Andrew Tridgell 2003
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "lib/cmdline/cmdline.h"
+#include "torture/torture.h"
+#include "torture/rpc/torture_rpc.h"
+#include "libcli/tstream_binding_handle/tstream_binding_handle.h"
+#include "lib/tsocket/tsocket.h"
+#include "param/param.h"
+#include "libcli/smb2/smb2.h"
+#include "libcli/smb2/smb2_calls.h"
+#include "libcli/resolve/resolve.h"
+#include "libcli/libcli.h"
+#include "libcli/smb/smbXcli_base.h"
+#include "librpc/gen_ndr/ndr_rawpipe.h"
+
+static NTSTATUS raw_resp_pdu_complete(struct tstream_context *stream,
+void *private_data,
+DATA_BLOB blob,
+size_t *packet_size)
+{
+       ssize_t to_read;
+
+       to_read = tstream_pending_bytes(stream);
+       if (to_read == -1) {
+               return NT_STATUS_IO_DEVICE_ERROR;
+       }
+
+       if (to_read > 0) {
+               *packet_size = blob.length + to_read;
+               return STATUS_MORE_ENTRIES;
+       }
+
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS torture_rawpipe_connection(struct torture_context *tctx,
+                               struct dcerpc_pipe **p,
+                               const char* pipename)
+{
+       struct cli_credentials *credentials = samba_cmdline_get_creds();
+       struct tevent_context *ev_ctx = tctx->ev;
+       NTSTATUS status;
+       struct dcerpc_binding *binding;
+       struct loadparm_context *lp_ctx = tctx->lp_ctx;
+       bool smb2_or_greater;
+       struct smbcli_options options;
+       struct smbcli_session_options session_options;
+       struct dcerpc_pipe *pipe = NULL;
+       struct smb2_tree *tree = NULL;
+       struct smbcli_state *cli = NULL;
+       const char *target_hostname = NULL;
+       enum protocol_types protocol;
+       lpcfg_smbcli_options(lp_ctx, &options);
+       lpcfg_smbcli_session_options(lp_ctx, &session_options);
+       status = torture_rpc_binding(tctx, &binding);
+       if (NT_STATUS_IS_ERR(status)) {
+               return status;
+       }
+
+       target_hostname =
+               dcerpc_binding_get_string_option(binding, "target_hostname");
+
+       if (target_hostname == NULL) {
+               target_hostname =
+                       dcerpc_binding_get_string_option(binding, "host");
+       }
+
+       smb2_or_greater =
+               (lpcfg_client_ipc_max_protocol(lp_ctx) >= PROTOCOL_SMB2_02);
+       if (smb2_or_greater) {
+               status = smb2_connect(tctx,
+                             target_hostname,
+                             lpcfg_smb_ports(lp_ctx),
+                             "IPC$",
+                             lpcfg_resolve_context(lp_ctx),
+                             credentials,
+                             &tree,
+                             ev_ctx,
+                             &options,
+                             lpcfg_socket_options(lp_ctx),
+                             lpcfg_gensec_settings(tctx,
+                                                   lp_ctx)
+                             );
+
+               if (NT_STATUS_IS_OK(status)) {
+                       protocol =
+                               smbXcli_conn_protocol(
+                                       tree->session->transport->conn);
+               } else {
+                       return status;
+               }
+
+       } else {
+               status = smbcli_full_connection(tctx,
+                                       &cli,
+                                       target_hostname,
+                                       lpcfg_smb_ports(lp_ctx),
+                                       "IPC$", NULL,
+                                       lpcfg_socket_options(lp_ctx),
+                                       credentials,
+                                       lpcfg_resolve_context(lp_ctx),
+                                       ev_ctx, &options, &session_options,
+                                       lpcfg_gensec_settings(tctx,
+                                                             lp_ctx));
+               if (NT_STATUS_IS_OK(status)) {
+                       protocol =
+                               smbXcli_conn_protocol(
+                                       cli->transport->conn);
+               } else {
+                       return status;
+               }
+       }
+
+       pipe = dcerpc_pipe_init(tctx, ev_ctx);
+       if (!pipe) {
+               DBG_ERR("failed to int the pipe)\n");
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       if (protocol >= PROTOCOL_SMB2_02) {
+               status = dcerpc_pipe_open_smb2(pipe, tree, pipename);
+       } else {
+               status = dcerpc_pipe_open_smb(pipe, cli->tree, pipename);
+       }
+       if (NT_STATUS_IS_OK(status)) {
+               *p = pipe;
+       }
+       return status;
+}
+
+bool torture_rpc_rawpipe_echo_impl(struct torture_context *tctx,
+                               const char* pipename)
+{
+       NTSTATUS status;
+       struct dcerpc_pipe *p;
+       bool ret = true;
+       struct dcerpc_binding_handle *b;
+       int count;
+       const char* echoes[] = {
+               "one",
+               "two",
+               "three",
+               "four"};
+       status = torture_rawpipe_connection(tctx, &p, pipename);
+
+       torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
+
+       /* use custom rawpipe specific handle */
+       b =  tstream_binding_handle_create(p,
+                       NULL,
+                       &p->conn->transport.stream,
+                       3,
+                       raw_resp_pdu_complete,
+                       tctx, 42280);
+       dcerpc_binding_handle_set_timeout(b,
+               DCERPC_REQUEST_TIMEOUT * 1000);
+       for (count=0; count < ARRAY_SIZE(echoes); count++) {
+               DATA_BLOB in = {0};
+               DATA_BLOB out = {0};
+               struct raw_request_response *request = NULL;
+               struct raw_request_response *response = NULL;
+               uint32_t outflags;
+               struct ndr_pull *ndr = NULL;
+               struct ndr_push *ndr_push = NULL;
+               enum ndr_err_code err;
+               int ndr_flags = NDR_SCALARS | NDR_BUFFERS;
+
+               request = talloc_zero(tctx, struct raw_request_response);
+               torture_assert(tctx, request != NULL, "talloc_zero failed");
+
+               response = talloc_zero(tctx, struct raw_request_response);
+               torture_assert(tctx, response != NULL, "talloc_zero failed");
+
+               request->payload = talloc_strdup(talloc_tos(), echoes[count]);
+               torture_assert(tctx,
+                       request->payload != NULL,
+                       "failed to allocate payload");
+
+               ndr_push = ndr_push_init_ctx(tctx);
+               torture_assert(tctx,
+                       ndr_push != NULL,
+                       "Failed to init push ctx");
+
+               err = ndr_push_raw_request_response(ndr_push,
+                       ndr_flags,
+                       request);
+
+               torture_assert(tctx, err == 0, "push payload failed");
+               in = ndr_push_blob(ndr_push);
+
+               status = dcerpc_binding_handle_raw_call(b,
+                               NULL,
+                               0,
+                               0,
+                               in.data,
+                               in.length,
+                               tctx,
+                               &out.data,
+                               &out.length,
+                               &outflags);
+               torture_assert_ntstatus_ok(tctx,
+                                       status,
+                                       "Failed to send to rawpipe");
+               ndr = ndr_pull_init_blob(&out, tctx);
+               torture_assert(tctx, ndr != NULL, "failed to init push blob");
+               err = ndr_pull_raw_request_response(ndr, ndr_flags, response);
+
+               torture_assert(tctx, err == 0, "pull response payload failed");
+               printf("Received %s from rawd\n", response->payload);
+       }
+       return ret;
+}
+
+bool torture_rpc_rawpipe(struct torture_context *tctx)
+{
+       return torture_rpc_rawpipe_echo_impl(tctx,
+                               "rawpipe");
+}
index ea214e043c41f19b109949098740e2cedb9a9fdb..baa967e76d5e13e02f643311b0d16b6664688980 100644 (file)
@@ -572,6 +572,7 @@ NTSTATUS torture_rpc_init(TALLOC_CTX *ctx)
        ndr_table_init();
 
        torture_suite_add_simple_test(suite, "lsa", torture_rpc_lsa);
+       torture_suite_add_simple_test(suite, "rawpipe", torture_rpc_rawpipe);
        torture_suite_add_simple_test(suite, "lsalookup", torture_rpc_lsa_lookup);
        torture_suite_add_simple_test(suite, "lsa-getuser", torture_rpc_lsa_get_user);
        torture_suite_add_suite(suite, torture_rpc_lsa_lookup_sids(suite));
index 1ddce713dfb90ca97455c35b07d000886da8697e..9b56ce91aaae46fd517b7e68cca4358bb9893a42 100644 (file)
@@ -98,6 +98,7 @@ bld.SAMBA_MODULE('torture_rpc',
                         rpc/drsuapi_w2k8.c
                         rpc/drsuapi_cracknames.c
                         rpc/dsgetinfo.c
+                        rpc/rawpipe.c
                         rpc/spoolss.c
                         rpc/spoolss_win.c
                         rpc/spoolss_access.c
@@ -188,6 +189,7 @@ bld.SAMBA_MODULE('torture_rpc',
                       printer_driver
                       RPC_NDR_MDSSVC
                       mdssvc
+                      tstream_binding_handle
                       ''' % samba_net + ntvfs_specific['deps'],
                  internal_module=True,
                  enabled=bld.PYTHON_BUILD_IS_ENABLED())