summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/librpc/rpc/dcerpc.h9
-rw-r--r--source4/librpc/rpc/dcerpc_smb.c15
-rw-r--r--source4/librpc/rpc/dcerpc_tcp.c1
-rw-r--r--source4/librpc/rpc/dcerpc_util.c39
-rw-r--r--source4/torture/rpc/spoolss.c41
5 files changed, 102 insertions, 3 deletions
diff --git a/source4/librpc/rpc/dcerpc.h b/source4/librpc/rpc/dcerpc.h
index 5d25882041..fdd17fcbb3 100644
--- a/source4/librpc/rpc/dcerpc.h
+++ b/source4/librpc/rpc/dcerpc.h
@@ -29,6 +29,9 @@
marshalling/unmarshalling routines in decrpc.c
*/
+enum dcerpc_transport_t {NCACN_NP, NCACN_IP_TCP};
+
+
struct dcerpc_pipe {
TALLOC_CTX *mem_ctx;
int reference_count;
@@ -38,8 +41,10 @@ struct dcerpc_pipe {
unsigned flags;
struct ntlmssp_state *ntlmssp_state;
struct dcerpc_auth *auth_info;
-
+ const char *binding_string;
+
struct dcerpc_transport {
+ enum dcerpc_transport_t transport;
void *private;
NTSTATUS (*full_request)(struct dcerpc_pipe *,
TALLOC_CTX *, DATA_BLOB *, DATA_BLOB *);
@@ -94,8 +99,6 @@ struct dcerpc_interface_table {
};
-enum dcerpc_transport_t {NCACN_NP, NCACN_IP_TCP};
-
/* this describes a binding to a particular transport/pipe */
struct dcerpc_binding {
enum dcerpc_transport_t transport;
diff --git a/source4/librpc/rpc/dcerpc_smb.c b/source4/librpc/rpc/dcerpc_smb.c
index fc71a47cf4..da43a8a92b 100644
--- a/source4/librpc/rpc/dcerpc_smb.c
+++ b/source4/librpc/rpc/dcerpc_smb.c
@@ -354,6 +354,7 @@ NTSTATUS dcerpc_pipe_open_smb(struct dcerpc_pipe **p,
/*
fill in the transport methods
*/
+ (*p)->transport.transport = NCACN_NP;
(*p)->transport.private = NULL;
(*p)->transport.full_request = smb_full_request;
(*p)->transport.secondary_request = smb_secondary_request;
@@ -375,3 +376,17 @@ NTSTATUS dcerpc_pipe_open_smb(struct dcerpc_pipe **p,
return NT_STATUS_OK;
}
+
+/*
+ return the SMB tree used for a dcerpc over SMB pipe
+*/
+struct cli_tree *dcerpc_smb_tree(struct dcerpc_pipe *p)
+{
+ struct smb_private *smb = p->transport.private;
+
+ if (p->transport.transport != NCACN_NP) {
+ return NULL;
+ }
+
+ return smb->tree;
+}
diff --git a/source4/librpc/rpc/dcerpc_tcp.c b/source4/librpc/rpc/dcerpc_tcp.c
index b577260033..afdf243071 100644
--- a/source4/librpc/rpc/dcerpc_tcp.c
+++ b/source4/librpc/rpc/dcerpc_tcp.c
@@ -183,6 +183,7 @@ NTSTATUS dcerpc_pipe_open_tcp(struct dcerpc_pipe **p,
/*
fill in the transport methods
*/
+ (*p)->transport.transport = NCACN_IP_TCP;
(*p)->transport.private = NULL;
(*p)->transport.full_request = tcp_full_request;
(*p)->transport.secondary_request = tcp_secondary_request;
diff --git a/source4/librpc/rpc/dcerpc_util.c b/source4/librpc/rpc/dcerpc_util.c
index 8efcefc8a7..1ef776125f 100644
--- a/source4/librpc/rpc/dcerpc_util.c
+++ b/source4/librpc/rpc/dcerpc_util.c
@@ -578,6 +578,11 @@ NTSTATUS dcerpc_pipe_connect_b(struct dcerpc_pipe **p,
break;
}
+ /* remember the binding string for possible secondary connections */
+ if (NT_STATUS_IS_OK(status)) {
+ (*p)->binding_string = dcerpc_binding_string((*p)->mem_ctx, binding);
+ }
+
return status;
}
@@ -613,3 +618,37 @@ NTSTATUS dcerpc_pipe_connect(struct dcerpc_pipe **p,
talloc_destroy(mem_ctx);
return status;
}
+
+
+/*
+ create a secondary dcerpc connection on SMB
+ the secondary connection will be on the same SMB connection, but
+ use a new fnum
+*/
+NTSTATUS dcerpc_secondary_smb(struct dcerpc_pipe *p, struct dcerpc_pipe **p2,
+ const char *pipe_name,
+ const char *pipe_uuid,
+ uint32 pipe_version)
+{
+ NTSTATUS status;
+ struct cli_tree *tree;
+
+ tree = dcerpc_smb_tree(p);
+ if (!tree) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ status = dcerpc_pipe_open_smb(p2, tree, pipe_name);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ (*p2)->flags = p->flags;
+
+ status = dcerpc_bind_auth_none(*p2, pipe_uuid, pipe_version);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ return NT_STATUS_OK;
+}
diff --git a/source4/torture/rpc/spoolss.c b/source4/torture/rpc/spoolss.c
index 14cfbd0d29..5b118bec7b 100644
--- a/source4/torture/rpc/spoolss.c
+++ b/source4/torture/rpc/spoolss.c
@@ -573,6 +573,39 @@ static BOOL test_SetPrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
return True;
}
+static BOOL test_SecondaryClosePrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+ struct policy_handle *handle)
+{
+ NTSTATUS status;
+ struct dcerpc_pipe *p2;
+
+ /* only makes sense on SMB */
+ if (p->transport.transport != NCACN_NP) {
+ return True;
+ }
+
+ printf("testing close on secondary pipe\n");
+
+ status = dcerpc_secondary_smb(p, &p2,
+ DCERPC_SPOOLSS_NAME,
+ DCERPC_SPOOLSS_UUID,
+ DCERPC_SPOOLSS_VERSION);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("Failed to create secondary connection\n");
+ return False;
+ }
+
+ if (test_ClosePrinter(p2, mem_ctx, handle)) {
+ printf("ERROR: Allowed close on secondary connection!\n");
+ dcerpc_pipe_close(p2);
+ return False;
+ }
+
+ dcerpc_pipe_close(p2);
+
+ return True;
+}
+
static BOOL test_OpenPrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
const char *name)
{
@@ -605,6 +638,10 @@ static BOOL test_OpenPrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
ret = False;
}
+ if (!test_SecondaryClosePrinter(p, mem_ctx, &handle)) {
+ ret = False;
+ }
+
if (!test_ClosePrinter(p, mem_ctx, &handle)) {
ret = False;
}
@@ -693,6 +730,10 @@ static BOOL test_OpenPrinterEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
ret = False;
}
+ if (!test_SecondaryClosePrinter(p, mem_ctx, &handle)) {
+ ret = False;
+ }
+
if (!test_ClosePrinter(p, mem_ctx, &handle)) {
ret = False;
}