diff options
-rw-r--r-- | source4/librpc/rpc/dcerpc.h | 9 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc_smb.c | 15 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc_tcp.c | 1 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc_util.c | 39 | ||||
-rw-r--r-- | source4/torture/rpc/spoolss.c | 41 |
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; } |