diff options
-rw-r--r-- | source4/build/pidl/parser.pm | 6 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc.c | 18 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc.h | 12 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc_smb.c | 244 | ||||
-rw-r--r-- | source4/torture/torture.c | 18 |
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; } |