diff options
Diffstat (limited to 'source4/librpc/rpc/dcerpc_smb.c')
-rw-r--r-- | source4/librpc/rpc/dcerpc_smb.c | 244 |
1 files changed, 153 insertions, 91 deletions
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; +} |