#include "rpc_server/dcerpc_server.h"
#include "libcli/raw/ioctl.h"
#include "param/param.h"
-#include "../lib/tsocket/tsocket.h"
/* this is the private structure used to keep the state of an open
ipc$ connection. It needs to keep information about all open
struct ipc_private *ipriv;
const char *pipe_name;
struct ntvfs_handle *handle;
+ struct dcesrv_connection *dce_conn;
uint16_t ipc_state;
- uint16_t fmode;
- struct tsocket_context *npipe;
} *pipe_list;
};
return ntvfs_get_peer_addr(ipriv->ntvfs, mem_ctx);
}
-static void ipc_open_done(struct tevent_req *subreq);
-
/*
- open a file - used for MSRPC pipes
+ open a file backend - used for MSRPC pipes
*/
-static NTSTATUS ipc_open(struct ntvfs_module_context *ntvfs,
- struct ntvfs_request *req, union smb_open *oi)
+static NTSTATUS ipc_open_generic(struct ntvfs_module_context *ntvfs,
+ struct ntvfs_request *req, const char *fname,
+ struct pipe_state **ps)
{
- NTSTATUS status;
struct pipe_state *p;
+ NTSTATUS status;
+ struct dcerpc_binding *ep_description;
struct ipc_private *ipriv = ntvfs->private_data;
struct ntvfs_handle *h;
- struct tsocket_address *laddr;
- struct tsocket_address *raddr;
-
- switch (oi->generic.level) {
- case RAW_OPEN_NTCREATEX:
- fname = oi->ntcreatex.in.fname);
- break;
- case RAW_OPEN_OPENX:
- fname = oi->openx.in.fname;
- break;
- case RAW_OPEN_SMB2:
- fname = oi->smb2.in.fname;
- break;
- default:
- status = NT_STATUS_NOT_SUPPORTED;
- break;
- }
status = ntvfs_handle_new(ntvfs, req, &h);
NT_STATUS_NOT_OK_RETURN(status);
p = talloc(h, struct pipe_state);
NT_STATUS_HAVE_NO_MEMORY(p);
- while (fname[0] == '\\') fname++;
-
- ret = tsocket_address_npa_client_local(req, &laddr);
- if (ret != 0) {
-
- }
-
- //Vreturn ipc_rap_call(req, ntvfs->ctx->event_ctx, ntvfs->ctx->lp_ctx, trans);
- ret = tsocket_address_npa_client_remote(req,
- directory,
- fname,
- &laddr);
- if (ret != 0) {
+ ep_description = talloc(req, struct dcerpc_binding);
+ NT_STATUS_HAVE_NO_MEMORY(ep_description);
- }
+ while (fname[0] == '\\') fname++;
p->pipe_name = talloc_asprintf(p, "\\pipe\\%s", fname);
NT_STATUS_HAVE_NO_MEMORY(p->pipe_name);
p->handle = h;
p->ipc_state = 0x5ff;
- p->file_type = FILE_TYPE_MESSAGE_MODE_PIPE;
+
+ /*
+ we're all set, now ask the dcerpc server subsystem to open the
+ endpoint. At this stage the pipe isn't bound, so we don't
+ know what interface the user actually wants, just that they want
+ one of the interfaces attached to this pipe endpoint.
+ */
+ ep_description->transport = NCACN_NP;
+ ep_description->endpoint = talloc_reference(ep_description, p->pipe_name);
+
+ /* The session info is refcount-increased in the
+ * dcesrv_endpoint_search_connect() function
+ */
+ status = dcesrv_endpoint_search_connect(ipriv->dcesrv,
+ p,
+ ep_description,
+ h->session_info,
+ ntvfs->ctx->event_ctx,
+ ntvfs->ctx->msg_ctx,
+ ntvfs->ctx->server_id,
+ 0,
+ &p->dce_conn);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ p->dce_conn->transport.private_data = ipriv;
+ p->dce_conn->transport.report_output_data = NULL;
+ p->dce_conn->transport.get_my_addr = ipc_get_my_addr;
+ p->dce_conn->transport.get_peer_addr = ipc_get_peer_addr;
+
+ DLIST_ADD(ipriv->pipe_list, p);
+
p->ipriv = ipriv;
- ret = tsocket_address_create_socket(laddr, TSOCKET_TYPE_STREAM,
- p, &p->np_sock);
- if (ret != 0) {
+ talloc_set_destructor(p, ipc_fd_destructor);
- }
+ status = ntvfs_handle_set_backend_data(h, ipriv->ntvfs, p);
+ NT_STATUS_NOT_OK_RETURN(status);
- subreq = tsocket_connect_send(p->np_sock, p, raddr);
- if (!subreq) {
+ *ps = p;
+ return NT_STATUS_OK;
+}
+
+/*
+ open a file with ntcreatex - used for MSRPC pipes
+*/
+static NTSTATUS ipc_open_ntcreatex(struct ntvfs_module_context *ntvfs,
+ struct ntvfs_request *req, union smb_open *oi)
+{
+ struct pipe_state *p;
+ NTSTATUS status;
+ status = ipc_open_generic(ntvfs, req, oi->ntcreatex.in.fname, &p);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
- tevent_req_set_callback(subreq, ipc_open_done, p);
- /*TODO: reply async */
+ ZERO_STRUCT(oi->ntcreatex.out);
+ oi->ntcreatex.out.file.ntvfs= p->handle;
+ oi->ntcreatex.out.ipc_state = p->ipc_state;
+ oi->ntcreatex.out.file_type = FILE_TYPE_MESSAGE_MODE_PIPE;
+
+ return status;
}
-static void ipc_open_done(struct tevent_req *subreq)
+/*
+ open a file with openx - used for MSRPC pipes
+*/
+static NTSTATUS ipc_open_openx(struct ntvfs_module_context *ntvfs,
+ struct ntvfs_request *req, union smb_open *oi)
{
+ struct pipe_state *p;
+ NTSTATUS status;
+ const char *fname = oi->openx.in.fname;
+
+ status = ipc_open_generic(ntvfs, req, fname, &p);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ ZERO_STRUCT(oi->openx.out);
+ oi->openx.out.file.ntvfs= p->handle;
+ oi->openx.out.ftype = 2;
+ oi->openx.out.devstate = p->ipc_state;
+
+ return status;
+}
- int ret;
- int sys_errno;
+/*
+ open a file with SMB2 Create - used for MSRPC pipes
+*/
+static NTSTATUS ipc_open_smb2(struct ntvfs_module_context *ntvfs,
+ struct ntvfs_request *req, union smb_open *oi)
+{
+ struct pipe_state *p;
+ NTSTATUS status;
- ret = tsocket_connect_recv(subreq, &sys_errno);
- if (ret != 0) {
+ status = ipc_open_generic(ntvfs, req, oi->smb2.in.fname, &p);
+ NT_STATUS_NOT_OK_RETURN(status);
- }
+ ZERO_STRUCT(oi->smb2.out);
+ oi->smb2.out.file.ntvfs = p->handle;
+ oi->smb2.out.oplock_level = oi->smb2.in.oplock_level;
+ oi->smb2.out.create_action = NTCREATEX_ACTION_EXISTED;
+ oi->smb2.out.create_time = 0;
+ oi->smb2.out.access_time = 0;
+ oi->smb2.out.write_time = 0;
+ oi->smb2.out.change_time = 0;
+ oi->smb2.out.alloc_size = 4096;
+ oi->smb2.out.size = 0;
+ oi->smb2.out.file_attr = FILE_ATTRIBUTE_NORMAL;
+ oi->smb2.out.reserved2 = 0;
- DLIST_ADD(ipriv->pipe_list, p);
- talloc_set_destructor(p, ipc_fd_destructor);
- status = ntvfs_handle_set_backend_data(h, ipriv->ntvfs, p);
- if (!NT_STATUS_IS_OK(status)) {
+ return status;
+}
- }
+/*
+ open a file - used for MSRPC pipes
+*/
+static NTSTATUS ipc_open(struct ntvfs_module_context *ntvfs,
+ struct ntvfs_request *req, union smb_open *oi)
+{
+ NTSTATUS status;
switch (oi->generic.level) {
case RAW_OPEN_NTCREATEX:
- ZERO_STRUCT(oi->ntcreatex.out);
- oi->ntcreatex.out.file.ntvfs= p->handle;
- oi->ntcreatex.out.ipc_state = p->ipc_state;
- oi->ntcreatex.out.file_type = p->file_type;
-FILE_TYPE_MESSAGE_MODE_PIPE;
+ status = ipc_open_ntcreatex(ntvfs, req, oi);
break;
case RAW_OPEN_OPENX:
- ZERO_STRUCT(oi->openx.out);
- oi->openx.out.file.ntvfs= p->handle;
- oi->openx.out.ftype = p->file_type;
- oi->openx.out.devstate = p->ipc_state;
+ status = ipc_open_openx(ntvfs, req, oi);
break;
case RAW_OPEN_SMB2:
- ZERO_STRUCT(oi->smb2.out);
- oi->smb2.out.file.ntvfs = p->handle;
- oi->smb2.out.oplock_level = oi->smb2.in.oplock_level;
- oi->smb2.out.create_action = NTCREATEX_ACTION_EXISTED;
- oi->smb2.out.create_time = 0;
- oi->smb2.out.access_time = 0;
- oi->smb2.out.write_time = 0;
- oi->smb2.out.change_time = 0;
- oi->smb2.out.alloc_size = 4096;
- oi->smb2.out.size = 0;
- oi->smb2.out.file_attr = FILE_ATTRIBUTE_NORMAL;
- oi->smb2.out.reserved2 = 0;
+ status = ipc_open_smb2(ntvfs, req, oi);
break;
default:
+ status = NT_STATUS_NOT_SUPPORTED;
break;
}
- /*TODO: reply async */
+ return status;
}
/*
data.length = UINT16_MAX;
}
- subreq = tsocket_readv_queue_send(p->read_queue,
- req);
- if (!subreq) {
-
+ if (data.length != 0) {
+ status = dcesrv_output(p->dce_conn, &data, ipc_readx_dcesrv_output);
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
}
- tevent_req_set_callback(subreq, ipc_read_done, req);
-
- /* reply async */
-}
-
-static void ipc_read_done(struct tevent_req *subreq)
-{
- int ret;
- int sys_errno;
-
- ret = tsocket_readv_queue_recv(subreq, &sys_errno);
rd->readx.out.remaining = 0;
rd->readx.out.compaction_mode = 0;
return NT_STATUS_INVALID_HANDLE;
}
- subreq = tsocket_writev_queue_send(p->write_queue, req);
- if (!subreq) {
-
- }
- tevent_req_set_callback(subreq, ipc_write_done, req);
-
- /* reply async */
-}
-
-static void ipc_write_done(struct tevent_req *subreq)
-{
- int ret;
- int sys_errno;
-
- ret = tsocket_writev_queue_recv(subreq, &sys_errno);
- if (ret != 0) {
-
+ status = dcesrv_input(p->dce_conn, &data);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
wr->writex.out.nwritten = data.length;
wr->writex.out.remaining = 0;
- /* reply async */
+ return NT_STATUS_OK;
}
/*
return NT_STATUS_INVALID_HANDLE;
}
- if (p->num_trans || p->num_reads) {
- return NT_STATUS_PIPE_BUSY;
- }
-
trans->out.data = data_blob_talloc(req, NULL, trans->in.max_data);
if (!trans->out.data.data) {
return NT_STATUS_NO_MEMORY;
}
- p->num_trans++;
-
- subreq = tsocket_writev_queue_send(p->write_queue, req);
- if (!subreq) {
+ /* pass the data to the dcerpc server. Note that we don't
+ expect this to fail, and things like NDR faults are not
+ reported at this stage. Those sorts of errors happen in the
+ dcesrv_output stage */
+ status = dcesrv_input(p->dce_conn, &trans->in.data);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ /*
+ now ask the dcerpc system for some output. This doesn't yet handle
+ async calls. Again, we only expect NT_STATUS_OK. If the call fails then
+ the error is encoded at the dcerpc level
+ */
+ status = dcesrv_output(p->dce_conn, &trans->out.data, ipc_trans_dcesrv_output);
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
}
- tevent_req_set_callback(subreq, ipc
+
trans->out.setup_count = 0;
trans->out.setup = NULL;
trans->out.params = data_blob(NULL, 0);