summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/build/pidl/parser.pm6
-rw-r--r--source4/librpc/rpc/dcerpc.c18
-rw-r--r--source4/librpc/rpc/dcerpc.h12
-rw-r--r--source4/librpc/rpc/dcerpc_smb.c244
-rw-r--r--source4/torture/torture.c18
5 files changed, 178 insertions, 120 deletions
diff --git a/source4/build/pidl/parser.pm b/source4/build/pidl/parser.pm
index e536ab083d..a7dad3707c 100644
--- a/source4/build/pidl/parser.pm
+++ b/source4/build/pidl/parser.pm
@@ -1176,10 +1176,10 @@ sub ParseFunctionElementPull($$)
if (util::need_wire_pointer($e)) {
pidl "\tNDR_CHECK(ndr_pull_uint32(ndr, &_ptr_$e->{NAME}));\n";
pidl "\tif (_ptr_$e->{NAME}) {\n";
- } elsif ($inout eq "in" && util::has_property($e, "ref")) {
- pidl "\t{\n";
- } else {
+ } elsif ($inout eq "out" && util::has_property($e, "ref")) {
pidl "\tif (r->$inout.$e->{NAME}) {\n";
+ } else {
+ pidl "\t{\n";
}
ParseArrayPull($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
pidl "\t}\n";
diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c
index 276b3c9ef4..495e36ec1f 100644
--- a/source4/librpc/rpc/dcerpc.c
+++ b/source4/librpc/rpc/dcerpc.c
@@ -40,10 +40,7 @@ struct dcerpc_pipe *dcerpc_pipe_init(struct cli_tree *tree)
p->reference_count = 0;
p->mem_ctx = mem_ctx;
- p->tree = tree;
- p->tree->reference_count++;
p->call_id = 1;
- p->fnum = 0;
return p;
}
@@ -54,7 +51,7 @@ void dcerpc_pipe_close(struct dcerpc_pipe *p)
if (!p) return;
p->reference_count--;
if (p->reference_count <= 0) {
- cli_tree_close(p->tree);
+ p->transport.shutdown_pipe(p);
talloc_destroy(p->mem_ctx);
}
}
@@ -167,7 +164,7 @@ NTSTATUS dcerpc_bind(struct dcerpc_pipe *p,
return status;
}
- status = dcerpc_raw_packet(p, mem_ctx, &blob, &blob_out);
+ status = p->transport.full_request(p, mem_ctx, &blob, &blob_out);
if (!NT_STATUS_IS_OK(status)) {
talloc_destroy(mem_ctx);
return status;
@@ -269,7 +266,7 @@ NTSTATUS dcerpc_request(struct dcerpc_pipe *p,
return status;
}
- status = dcerpc_raw_packet_initial(p, mem_ctx, &blob_in);
+ status = p->transport.initial_request(p, mem_ctx, &blob_in);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@@ -294,7 +291,7 @@ NTSTATUS dcerpc_request(struct dcerpc_pipe *p,
}
/* send the pdu and get the initial response pdu */
- status = dcerpc_raw_packet(p, mem_ctx, &blob_in, &blob_out);
+ status = p->transport.full_request(p, mem_ctx, &blob_in, &blob_out);
status = dcerpc_pull(&blob_out, mem_ctx, &pkt);
if (!NT_STATUS_IS_OK(status)) {
@@ -320,7 +317,7 @@ NTSTATUS dcerpc_request(struct dcerpc_pipe *p,
while (!(pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
uint32 length;
- status = dcerpc_raw_packet_secondary(p, mem_ctx, &blob_out);
+ status = p->transport.secondary_request(p, mem_ctx, &blob_out);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@@ -596,5 +593,8 @@ failed:
*/
const char *dcerpc_server_name(struct dcerpc_pipe *p)
{
- return p->tree->session->transport->called.name;
+ if (!p->transport.peer_name) {
+ return "";
+ }
+ return p->transport.peer_name(p);
}
diff --git a/source4/librpc/rpc/dcerpc.h b/source4/librpc/rpc/dcerpc.h
index 6ba0f8429a..e0e7c8bd5a 100644
--- a/source4/librpc/rpc/dcerpc.h
+++ b/source4/librpc/rpc/dcerpc.h
@@ -31,13 +31,21 @@
struct dcerpc_pipe {
TALLOC_CTX *mem_ctx;
- uint16 fnum;
int reference_count;
uint32 call_id;
uint32 srv_max_xmit_frag;
uint32 srv_max_recv_frag;
- struct cli_tree *tree;
unsigned flags;
+
+ struct dcerpc_transport {
+ void *private;
+ NTSTATUS (*full_request)(struct dcerpc_pipe *,
+ TALLOC_CTX *, DATA_BLOB *, DATA_BLOB *);
+ NTSTATUS (*secondary_request)(struct dcerpc_pipe *, TALLOC_CTX *, DATA_BLOB *);
+ NTSTATUS (*initial_request)(struct dcerpc_pipe *, TALLOC_CTX *, DATA_BLOB *);
+ NTSTATUS (*shutdown_pipe)(struct dcerpc_pipe *);
+ const char *(*peer_name)(struct dcerpc_pipe *);
+ } transport;
};
/* dcerpc pipe flags */
diff --git a/source4/librpc/rpc/dcerpc_smb.c b/source4/librpc/rpc/dcerpc_smb.c
index a5570a4ea9..ba9c0c62a2 100644
--- a/source4/librpc/rpc/dcerpc_smb.c
+++ b/source4/librpc/rpc/dcerpc_smb.c
@@ -22,76 +22,15 @@
#include "includes.h"
+/* transport private information used by SMB pipe transport */
+struct smb_private {
+ uint16 fnum;
+ struct cli_tree *tree;
+};
-/*
- open a rpc connection to a named pipe
-*/
-NTSTATUS dcerpc_pipe_open_smb(struct dcerpc_pipe *p,
- const char *pipe_name,
- const char *pipe_uuid,
- uint32 pipe_version)
-{
- NTSTATUS status;
- char *name = NULL;
- union smb_open io;
- TALLOC_CTX *mem_ctx;
-
- asprintf(&name, "\\%s", pipe_name);
- if (!name) {
- return NT_STATUS_NO_MEMORY;
- }
-
- io.ntcreatex.level = RAW_OPEN_NTCREATEX;
- io.ntcreatex.in.flags = 0;
- io.ntcreatex.in.root_fid = 0;
- io.ntcreatex.in.access_mask =
- STD_RIGHT_READ_CONTROL_ACCESS |
- SA_RIGHT_FILE_WRITE_ATTRIBUTES |
- SA_RIGHT_FILE_WRITE_EA |
- GENERIC_RIGHTS_FILE_READ |
- GENERIC_RIGHTS_FILE_WRITE;
- io.ntcreatex.in.file_attr = 0;
- io.ntcreatex.in.alloc_size = 0;
- io.ntcreatex.in.share_access =
- NTCREATEX_SHARE_ACCESS_READ |
- NTCREATEX_SHARE_ACCESS_WRITE;
- io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
- io.ntcreatex.in.create_options = 0;
- io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_IMPERSONATION;
- io.ntcreatex.in.security_flags = 0;
- io.ntcreatex.in.fname = name;
-
- mem_ctx = talloc_init("torture_rpc_connection");
- if (!mem_ctx) {
- return NT_STATUS_NO_MEMORY;
- }
- status = smb_raw_open(p->tree, mem_ctx, &io);
- free(name);
- talloc_destroy(mem_ctx);
-
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- p->fnum = io.ntcreatex.out.fnum;
-
- /* bind to the pipe, using the pipe_name as the key */
- status = dcerpc_bind_byuuid(p, pipe_uuid, pipe_version);
-
- if (!NT_STATUS_IS_OK(status)) {
- union smb_close c;
- c.close.level = RAW_CLOSE_CLOSE;
- c.close.in.fnum = p->fnum;
- c.close.in.write_time = 0;
- smb_raw_close(p->tree, &c);
- }
-
- return status;
-}
-
-
-struct cli_request *dcerpc_raw_send(struct dcerpc_pipe *p, DATA_BLOB *blob)
+static struct cli_request *dcerpc_raw_send(struct dcerpc_pipe *p, DATA_BLOB *blob)
{
+ struct smb_private *smb = p->transport.private;
struct smb_trans2 trans;
uint16 setup[2];
struct cli_request *req;
@@ -104,7 +43,7 @@ struct cli_request *dcerpc_raw_send(struct dcerpc_pipe *p, DATA_BLOB *blob)
trans.in.params = data_blob(NULL, 0);
setup[0] = TRANSACT_DCERPCCMD;
- setup[1] = p->fnum;
+ setup[1] = smb->fnum;
trans.in.max_param = 0;
trans.in.max_data = 0x8000;
@@ -115,7 +54,7 @@ struct cli_request *dcerpc_raw_send(struct dcerpc_pipe *p, DATA_BLOB *blob)
trans.in.setup = setup;
trans.in.trans_name = "\\PIPE\\";
- req = smb_raw_trans_send(p->tree, &trans);
+ req = smb_raw_trans_send(smb->tree, &trans);
talloc_destroy(mem_ctx);
@@ -123,11 +62,12 @@ struct cli_request *dcerpc_raw_send(struct dcerpc_pipe *p, DATA_BLOB *blob)
}
-NTSTATUS dcerpc_raw_recv(struct dcerpc_pipe *p,
- struct cli_request *req,
- TALLOC_CTX *mem_ctx,
- DATA_BLOB *blob)
+static NTSTATUS dcerpc_raw_recv(struct dcerpc_pipe *p,
+ struct cli_request *req,
+ TALLOC_CTX *mem_ctx,
+ DATA_BLOB *blob)
{
+ struct smb_private *smb = p->transport.private;
struct smb_trans2 trans;
NTSTATUS status;
uint16 frag_length;
@@ -172,13 +112,13 @@ NTSTATUS dcerpc_raw_recv(struct dcerpc_pipe *p,
}
io.generic.level = RAW_READ_READX;
- io.readx.in.fnum = p->fnum;
+ io.readx.in.fnum = smb->fnum;
io.readx.in.mincnt = n;
io.readx.in.maxcnt = n;
io.readx.in.offset = 0;
io.readx.in.remaining = 0;
io.readx.out.data = payload.data + payload.length;
- status = smb_raw_read(p->tree, &io);
+ status = smb_raw_read(smb->tree, &io);
if (!NT_STATUS_IS_OK(status) &&
!NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW)) {
break;
@@ -207,10 +147,10 @@ done:
return status;
}
-NTSTATUS dcerpc_raw_packet(struct dcerpc_pipe *p,
- TALLOC_CTX *mem_ctx,
- DATA_BLOB *request_blob,
- DATA_BLOB *reply_blob)
+static NTSTATUS smb_full_request(struct dcerpc_pipe *p,
+ TALLOC_CTX *mem_ctx,
+ DATA_BLOB *request_blob,
+ DATA_BLOB *reply_blob)
{
struct cli_request *req;
req = dcerpc_raw_send(p, request_blob);
@@ -221,10 +161,11 @@ NTSTATUS dcerpc_raw_packet(struct dcerpc_pipe *p,
/*
retrieve a secondary pdu from a pipe
*/
-NTSTATUS dcerpc_raw_packet_secondary(struct dcerpc_pipe *p,
- TALLOC_CTX *mem_ctx,
- DATA_BLOB *blob)
+NTSTATUS smb_secondary_request(struct dcerpc_pipe *p,
+ TALLOC_CTX *mem_ctx,
+ DATA_BLOB *blob)
{
+ struct smb_private *smb = p->transport.private;
union smb_read io;
uint32 n = 0x2000;
uint32 frag_length;
@@ -236,14 +177,14 @@ NTSTATUS dcerpc_raw_packet_secondary(struct dcerpc_pipe *p,
}
io.generic.level = RAW_READ_READX;
- io.readx.in.fnum = p->fnum;
+ io.readx.in.fnum = smb->fnum;
io.readx.in.mincnt = n;
io.readx.in.maxcnt = n;
io.readx.in.offset = 0;
io.readx.in.remaining = 0;
io.readx.out.data = blob->data;
- status = smb_raw_read(p->tree, &io);
+ status = smb_raw_read(smb->tree, &io);
if (!NT_STATUS_IS_OK(status) &&
!NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW)) {
return status;
@@ -276,7 +217,7 @@ NTSTATUS dcerpc_raw_packet_secondary(struct dcerpc_pipe *p,
io.readx.in.mincnt = n;
io.readx.in.maxcnt = n;
io.readx.out.data = blob->data + blob->length;
- status = smb_raw_read(p->tree, &io);
+ status = smb_raw_read(smb->tree, &io);
if (!NT_STATUS_IS_OK(status) &&
!NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW)) {
@@ -294,22 +235,23 @@ NTSTATUS dcerpc_raw_packet_secondary(struct dcerpc_pipe *p,
/*
send an initial pdu in a multi-pdu sequence
*/
-NTSTATUS dcerpc_raw_packet_initial(struct dcerpc_pipe *p,
- TALLOC_CTX *mem_ctx,
- DATA_BLOB *blob)
+static NTSTATUS smb_initial_request(struct dcerpc_pipe *p,
+ TALLOC_CTX *mem_ctx,
+ DATA_BLOB *blob)
{
+ struct smb_private *smb = p->transport.private;
union smb_write io;
NTSTATUS status;
io.generic.level = RAW_WRITE_WRITEX;
- io.writex.in.fnum = p->fnum;
+ io.writex.in.fnum = smb->fnum;
io.writex.in.offset = 0;
io.writex.in.wmode = PIPE_START_MESSAGE;
io.writex.in.remaining = blob->length;
io.writex.in.count = blob->length;
io.writex.in.data = blob->data;
- status = smb_raw_write(p->tree, &io);
+ status = smb_raw_write(smb->tree, &io);
if (NT_STATUS_IS_OK(status)) {
return status;
}
@@ -321,3 +263,123 @@ NTSTATUS dcerpc_raw_packet_initial(struct dcerpc_pipe *p,
return status;
}
+
+
+/*
+ shutdown SMB pipe connection
+*/
+static NTSTATUS smb_shutdown_pipe(struct dcerpc_pipe *p)
+{
+ struct smb_private *smb = p->transport.private;
+ union smb_close c;
+
+ /* maybe we're still starting up */
+ if (!smb) return NT_STATUS_OK;
+
+ c.close.level = RAW_CLOSE_CLOSE;
+ c.close.in.fnum = smb->fnum;
+ c.close.in.write_time = 0;
+ smb_raw_close(smb->tree, &c);
+ cli_tree_close(smb->tree);
+
+ return NT_STATUS_OK;
+}
+
+/*
+ return SMB server name
+*/
+static const char *smb_peer_name(struct dcerpc_pipe *p)
+{
+ struct smb_private *smb = p->transport.private;
+ return smb->tree->session->transport->called.name;
+}
+
+
+/*
+ open a rpc connection to a named pipe
+*/
+NTSTATUS dcerpc_pipe_open_smb(struct dcerpc_pipe **p,
+ struct cli_tree *tree,
+ const char *pipe_name,
+ const char *pipe_uuid,
+ uint32 pipe_version)
+{
+ struct smb_private *smb;
+ NTSTATUS status;
+ char *name = NULL;
+ union smb_open io;
+ TALLOC_CTX *mem_ctx;
+
+ asprintf(&name, "\\%s", pipe_name);
+ if (!name) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ io.ntcreatex.level = RAW_OPEN_NTCREATEX;
+ io.ntcreatex.in.flags = 0;
+ io.ntcreatex.in.root_fid = 0;
+ io.ntcreatex.in.access_mask =
+ STD_RIGHT_READ_CONTROL_ACCESS |
+ SA_RIGHT_FILE_WRITE_ATTRIBUTES |
+ SA_RIGHT_FILE_WRITE_EA |
+ GENERIC_RIGHTS_FILE_READ |
+ GENERIC_RIGHTS_FILE_WRITE;
+ io.ntcreatex.in.file_attr = 0;
+ io.ntcreatex.in.alloc_size = 0;
+ io.ntcreatex.in.share_access =
+ NTCREATEX_SHARE_ACCESS_READ |
+ NTCREATEX_SHARE_ACCESS_WRITE;
+ io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
+ io.ntcreatex.in.create_options = 0;
+ io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_IMPERSONATION;
+ io.ntcreatex.in.security_flags = 0;
+ io.ntcreatex.in.fname = name;
+
+ mem_ctx = talloc_init("torture_rpc_connection");
+ if (!mem_ctx) {
+ free(name);
+ return NT_STATUS_NO_MEMORY;
+ }
+ status = smb_raw_open(tree, mem_ctx, &io);
+ free(name);
+ talloc_destroy(mem_ctx);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ if (!(*p = dcerpc_pipe_init(tree))) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /*
+ fill in the transport methods
+ */
+ (*p)->transport.private = NULL;
+ (*p)->transport.full_request = smb_full_request;
+ (*p)->transport.secondary_request = smb_secondary_request;
+ (*p)->transport.initial_request = smb_initial_request;
+ (*p)->transport.shutdown_pipe = smb_shutdown_pipe;
+ (*p)->transport.peer_name = smb_peer_name;
+
+ smb = talloc((*p)->mem_ctx, sizeof(*smb));
+ if (!smb) {
+ dcerpc_pipe_close(*p);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ smb->fnum = io.ntcreatex.out.fnum;
+ smb->tree = tree;
+
+ (*p)->transport.private = smb;
+ tree->reference_count++;
+
+ /* bind to the pipe, using the uuid as the key */
+ status = dcerpc_bind_byuuid(*p, pipe_uuid, pipe_version);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ dcerpc_pipe_close(*p);
+ }
+
+ return status;
+}
diff --git a/source4/torture/torture.c b/source4/torture/torture.c
index e13933a231..c07b516baa 100644
--- a/source4/torture/torture.c
+++ b/source4/torture/torture.c
@@ -143,14 +143,11 @@ NTSTATUS torture_rpc_connection(struct dcerpc_pipe **p,
return NT_STATUS_UNSUCCESSFUL;
}
- if (!(*p = dcerpc_pipe_init(cli->tree))) {
- return NT_STATUS_NO_MEMORY;
- }
-
- status = dcerpc_pipe_open_smb(*p, pipe_name, pipe_uuid, pipe_version);
+ status = dcerpc_pipe_open_smb(p, cli->tree, pipe_name, pipe_uuid, pipe_version);
if (!NT_STATUS_IS_OK(status)) {
printf("Open of pipe '%s' failed with error (%s)\n",
pipe_name, nt_errstr(status));
+ torture_close_connection(cli);
return status;
}
@@ -163,17 +160,8 @@ NTSTATUS torture_rpc_connection(struct dcerpc_pipe **p,
/* close a rpc connection to a named pipe */
NTSTATUS torture_rpc_close(struct dcerpc_pipe *p)
{
- union smb_close io;
- NTSTATUS status;
-
- io.close.level = RAW_CLOSE_CLOSE;
- io.close.in.fnum = p->fnum;
- io.close.in.write_time = 0;
- status = smb_raw_close(p->tree, &io);
-
dcerpc_pipe_close(p);
-
- return status;
+ return NT_STATUS_OK;
}