summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/include/ntvfs.h5
-rw-r--r--source4/libcli/raw/rawtrans.c8
-rw-r--r--source4/librpc/rpc/dcerpc_smb.c2
-rw-r--r--source4/ntvfs/cifs/vfs_cifs.c8
-rw-r--r--source4/ntvfs/ipc/vfs_ipc.c146
-rw-r--r--source4/ntvfs/simple/vfs_simple.c7
-rw-r--r--source4/rpc_server/dcerpc_server.c18
-rw-r--r--source4/smbd/reply.c18
-rw-r--r--source4/smbd/trans2.c53
9 files changed, 232 insertions, 33 deletions
diff --git a/source4/include/ntvfs.h b/source4/include/ntvfs.h
index 6628402a97..88122166ee 100644
--- a/source4/include/ntvfs.h
+++ b/source4/include/ntvfs.h
@@ -75,8 +75,11 @@ struct ntvfs_ops {
/* printing specific operations */
NTSTATUS (*lpq)(struct request_context *req, union smb_lpq *lpq);
- /* trans interfaces - only used by CIFS backend to prover complete passthru for testing */
+ /* trans2 interface - only used by CIFS backend to prover complete passthru for testing */
NTSTATUS (*trans2)(struct request_context *req, struct smb_trans2 *trans2);
+
+ /* trans interface - used by IPC backend for pipes and RAP calls */
+ NTSTATUS (*trans)(struct request_context *req, struct smb_trans2 *trans);
};
diff --git a/source4/libcli/raw/rawtrans.c b/source4/libcli/raw/rawtrans.c
index f31b1eaf7e..f7a3b4aa43 100644
--- a/source4/libcli/raw/rawtrans.c
+++ b/source4/libcli/raw/rawtrans.c
@@ -233,6 +233,11 @@ struct cli_request *smb_raw_trans_send_backend(struct cli_tree *tree,
/* make sure we don't leak data via the padding */
memset(req->out.data, 0, padding);
+ if (command == SMBtrans && parms->in.trans_name) {
+ namelen = cli_req_append_string(req, parms->in.trans_name,
+ STR_TERMINATE);
+ }
+
/* primary request */
SSVAL(req->out.vwv,VWV(0),parms->in.params.length);
SSVAL(req->out.vwv,VWV(1),parms->in.data.length);
@@ -243,9 +248,6 @@ struct cli_request *smb_raw_trans_send_backend(struct cli_tree *tree,
SIVAL(req->out.vwv,VWV(6),parms->in.timeout);
SSVAL(req->out.vwv,VWV(8),0); /* reserved */
SSVAL(req->out.vwv,VWV(9),parms->in.params.length);
- if (command == SMBtrans && parms->in.trans_name)
- namelen = cli_req_append_string(req, parms->in.trans_name,
- STR_TERMINATE);
SSVAL(req->out.vwv,VWV(10),PTR_DIFF(outparam,req->out.hdr)+namelen);
SSVAL(req->out.vwv,VWV(11),parms->in.data.length);
SSVAL(req->out.vwv,VWV(12),PTR_DIFF(outdata,req->out.hdr)+namelen);
diff --git a/source4/librpc/rpc/dcerpc_smb.c b/source4/librpc/rpc/dcerpc_smb.c
index 8a7a5ca68d..9acae00249 100644
--- a/source4/librpc/rpc/dcerpc_smb.c
+++ b/source4/librpc/rpc/dcerpc_smb.c
@@ -309,7 +309,7 @@ NTSTATUS dcerpc_pipe_open_smb(struct dcerpc_pipe **p,
union smb_open io;
TALLOC_CTX *mem_ctx;
- asprintf(&name, "\\pipe\\%s", pipe_name);
+ asprintf(&name, "\\%s", pipe_name);
if (!name) {
return NT_STATUS_NO_MEMORY;
}
diff --git a/source4/ntvfs/cifs/vfs_cifs.c b/source4/ntvfs/cifs/vfs_cifs.c
index c61749e2ad..ba2d6e7d24 100644
--- a/source4/ntvfs/cifs/vfs_cifs.c
+++ b/source4/ntvfs/cifs/vfs_cifs.c
@@ -669,6 +669,13 @@ static NTSTATUS cvfs_trans2(struct request_context *req, struct smb_trans2 *tran
ASYNC_RECV_TAIL(trans2, async_trans2);
}
+
+/* SMBtrans - not used on file shares */
+static NTSTATUS cvfs_trans(struct request_context *req, struct smb_trans2 *trans2)
+{
+ return NT_STATUS_ACCESS_DENIED;
+}
+
/*
initialise the CIFS->CIFS backend, registering ourselves with the ntvfs subsystem
*/
@@ -709,6 +716,7 @@ NTSTATUS ntvfs_cifs_init(void)
ops.search_first = cvfs_search_first;
ops.search_next = cvfs_search_next;
ops.search_close = cvfs_search_close;
+ ops.trans = cvfs_trans;
/* only define this one for trans2 testing */
ops.trans2 = cvfs_trans2;
diff --git a/source4/ntvfs/ipc/vfs_ipc.c b/source4/ntvfs/ipc/vfs_ipc.c
index 7ad02bb8cb..5ab608c46b 100644
--- a/source4/ntvfs/ipc/vfs_ipc.c
+++ b/source4/ntvfs/ipc/vfs_ipc.c
@@ -220,11 +220,9 @@ static NTSTATUS ipc_open(struct request_context *req, union smb_open *oi)
return NT_STATUS_TOO_MANY_OPENED_FILES;
}
- if (strncasecmp(p->pipe_name, "\\pipe\\", 6) != 0) {
- talloc_destroy(mem_ctx);
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ while (p->pipe_name[0] == '\\') {
+ p->pipe_name++;
}
- p->pipe_name += 6;
/*
we're all set, now ask the dcerpc server subsystem to open the
@@ -293,7 +291,51 @@ static NTSTATUS ipc_copy(struct request_context *req, struct smb_copy *cp)
*/
static NTSTATUS ipc_read(struct request_context *req, union smb_read *rd)
{
- return NT_STATUS_ACCESS_DENIED;
+ struct ipc_private *private = req->conn->ntvfs_private;
+ DATA_BLOB data;
+ uint16 fnum;
+ struct pipe_state *p;
+ NTSTATUS status;
+
+ switch (rd->generic.level) {
+ case RAW_READ_READ:
+ fnum = rd->read.in.fnum;
+ data.length = rd->read.in.count;
+ data.data = rd->read.out.data;
+ break;
+ case RAW_READ_READX:
+ fnum = rd->readx.in.fnum;
+ data.length = rd->readx.in.maxcnt;
+ data.data = rd->readx.out.data;
+ break;
+ default:
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+
+ p = pipe_state_find(private, fnum);
+ if (!p) {
+ return NT_STATUS_INVALID_HANDLE;
+ }
+
+ status = dcesrv_output(p->pipe_state, &data);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ switch (rd->generic.level) {
+ case RAW_READ_READ:
+ rd->read.out.nread = data.length;
+ break;
+ case RAW_READ_READX:
+ rd->readx.out.remaining = 0;
+ rd->readx.out.compaction_mode = 0;
+ rd->readx.out.nread = data.length;
+ break;
+ default:
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+
+ return NT_STATUS_OK;
}
/*
@@ -301,7 +343,52 @@ static NTSTATUS ipc_read(struct request_context *req, union smb_read *rd)
*/
static NTSTATUS ipc_write(struct request_context *req, union smb_write *wr)
{
- return NT_STATUS_ACCESS_DENIED;
+ struct ipc_private *private = req->conn->ntvfs_private;
+ DATA_BLOB data;
+ uint16 fnum;
+ struct pipe_state *p;
+ NTSTATUS status;
+
+ switch (wr->generic.level) {
+ case RAW_WRITE_WRITE:
+ fnum = wr->write.in.fnum;
+ data.data = wr->write.in.data;
+ data.length = wr->write.in.count;
+ break;
+
+ case RAW_WRITE_WRITEX:
+ fnum = wr->writex.in.fnum;
+ data.data = wr->writex.in.data;
+ data.length = wr->writex.in.count;
+ break;
+
+ default:
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+
+ p = pipe_state_find(private, fnum);
+ if (!p) {
+ return NT_STATUS_INVALID_HANDLE;
+ }
+
+ status = dcesrv_input(p->pipe_state, &data);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ switch (wr->generic.level) {
+ case RAW_WRITE_WRITE:
+ wr->write.out.nwritten = data.length;
+ break;
+ case RAW_WRITE_WRITEX:
+ wr->writex.out.nwritten = data.length;
+ wr->writex.out.remaining = 0;
+ break;
+ default:
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+
+ return NT_STATUS_OK;
}
/*
@@ -421,6 +508,52 @@ NTSTATUS ipc_search_close(struct request_context *req, union smb_search_close *i
}
+/* SMBtrans - used to provide access to SMB pipes */
+static NTSTATUS ipc_trans(struct request_context *req, struct smb_trans2 *trans)
+{
+ struct pipe_state *p;
+ struct ipc_private *private = req->conn->ntvfs_private;
+ NTSTATUS status;
+
+ if (trans->in.setup_count != 2 ||
+ trans->in.setup[0] != TRANSACT_DCERPCCMD) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* the fnum is in setup[1] */
+ p = pipe_state_find(private, trans->in.setup[1]);
+ if (!p) {
+ return NT_STATUS_INVALID_HANDLE;
+ }
+
+ /* 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->pipe_state, &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->pipe_state, &trans->out.data);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ trans->out.setup_count = 0;
+ trans->out.setup = NULL;
+ trans->out.params = data_blob(NULL, 0);
+
+ return NT_STATUS_OK;
+}
+
+
+
/*
initialialise the IPC backend, registering ourselves with the ntvfs subsystem
*/
@@ -460,6 +593,7 @@ NTSTATUS ntvfs_ipc_init(void)
ops.search_first = ipc_search_first;
ops.search_next = ipc_search_next;
ops.search_close = ipc_search_close;
+ ops.trans = ipc_trans;
/* register ourselves with the NTVFS subsystem. */
ret = register_backend("ntvfs", &ops);
diff --git a/source4/ntvfs/simple/vfs_simple.c b/source4/ntvfs/simple/vfs_simple.c
index 261ce4a19a..7972a3565a 100644
--- a/source4/ntvfs/simple/vfs_simple.c
+++ b/source4/ntvfs/simple/vfs_simple.c
@@ -803,6 +803,12 @@ static NTSTATUS svfs_search_close(struct request_context *req, union smb_search_
return NT_STATUS_OK;
}
+/* SMBtrans - not used on file shares */
+static NTSTATUS svfs_trans(struct request_context *req, struct smb_trans2 *trans2)
+{
+ return NT_STATUS_ACCESS_DENIED;
+}
+
/*
initialialise the POSIX disk backend, registering ourselves with the ntvfs subsystem
@@ -844,6 +850,7 @@ NTSTATUS ntvfs_simple_init(void)
ops.search_first = svfs_search_first;
ops.search_next = svfs_search_next;
ops.search_close = svfs_search_close;
+ ops.trans = svfs_trans;
/* register ourselves with the NTVFS subsystem. We register under the name 'default'
as we wish to be the default backend */
diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c
index c01dc4d9db..e1d6da2292 100644
--- a/source4/rpc_server/dcerpc_server.c
+++ b/source4/rpc_server/dcerpc_server.c
@@ -108,6 +108,24 @@ void dcesrv_endpoint_disconnect(struct dcesrv_state *p)
}
+/*
+ provide some input to a dcerpc endpoint server. This passes data
+ from a dcerpc client into the server
+*/
+NTSTATUS dcesrv_input(struct dcesrv_state *p, const DATA_BLOB *data)
+{
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+/*
+ retrieve some output from a dcerpc server. The amount of data that
+ is wanted is in data->length
+*/
+NTSTATUS dcesrv_output(struct dcesrv_state *p, DATA_BLOB *data)
+{
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
/*
a useful function for implementing the query endpoint op
diff --git a/source4/smbd/reply.c b/source4/smbd/reply.c
index 759ec1ef05..ce203cbf93 100644
--- a/source4/smbd/reply.c
+++ b/source4/smbd/reply.c
@@ -2169,24 +2169,6 @@ void reply_ulogoffX(struct request_context *req)
/****************************************************************************
- Reply to an SMBtrans request
-****************************************************************************/
-void reply_trans(struct request_context *req)
-{
- req_reply_error(req, NT_STATUS_FOOBAR);
-}
-
-
-/****************************************************************************
- Reply to an SMBtranss2 request
-****************************************************************************/
-void reply_transs2(struct request_context *req)
-{
- req_reply_error(req, NT_STATUS_FOOBAR);
-}
-
-
-/****************************************************************************
Reply to an SMBfindclose request
****************************************************************************/
void reply_findclose(struct request_context *req)
diff --git a/source4/smbd/trans2.c b/source4/smbd/trans2.c
index 0975f77eed..3115a330e5 100644
--- a/source4/smbd/trans2.c
+++ b/source4/smbd/trans2.c
@@ -1214,10 +1214,20 @@ static NTSTATUS trans2_backend(struct request_context *req, struct smb_trans2 *t
}
+/*
+ backend for trans requests
+*/
+static NTSTATUS trans_backend(struct request_context *req, struct smb_trans2 *trans)
+{
+
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+
/****************************************************************************
- Reply to an SMBtrans2 request
+ Reply to an SMBtrans or SMBtrans2 request
****************************************************************************/
-void reply_trans2(struct request_context *req)
+void reply_trans_generic(struct request_context *req, uint8 command)
{
struct smb_trans2 trans;
int i;
@@ -1262,6 +1272,10 @@ void reply_trans2(struct request_context *req)
trans.in.setup[i] = SVAL(req->in.vwv, VWV(14+i));
}
+ if (command == SMBtrans) {
+ req_pull_string(req, &trans.in.trans_name, req->in.data, -1, STR_TERMINATE);
+ }
+
if (!req_pull_blob(req, req->in.hdr + param_ofs, param_count, &trans.in.params) ||
!req_pull_blob(req, req->in.hdr + data_ofs, data_count, &trans.in.data)) {
req_reply_error(req, NT_STATUS_FOOBAR);
@@ -1271,12 +1285,16 @@ void reply_trans2(struct request_context *req)
/* is it a partial request? if so, then send a 'send more' message */
if (param_total > param_count ||
data_total > data_count) {
- DEBUG(0,("REWRITE: not handling partial trans2 requests!\n"));
+ DEBUG(0,("REWRITE: not handling partial trans requests!\n"));
return;
}
/* its a full request, give it to the backend */
- status = trans2_backend(req, &trans);
+ if (command == SMBtrans) {
+ status = trans_backend(req, &trans);
+ } else {
+ status = trans2_backend(req, &trans);
+ }
if (!NT_STATUS_IS_OK(status)) {
req_reply_error(req, status);
@@ -1353,3 +1371,30 @@ void reply_trans2(struct request_context *req)
req_send_reply(req);
} while (params_left != 0 || data_left != 0);
}
+
+
+/****************************************************************************
+ Reply to an SMBtrans2
+****************************************************************************/
+void reply_trans2(struct request_context *req)
+{
+ reply_trans_generic(req, SMBtrans2);
+}
+
+/****************************************************************************
+ Reply to an SMBtrans
+****************************************************************************/
+void reply_trans(struct request_context *req)
+{
+ reply_trans_generic(req, SMBtrans);
+}
+
+/****************************************************************************
+ Reply to an SMBtranss2 request
+****************************************************************************/
+void reply_transs2(struct request_context *req)
+{
+ req_reply_error(req, NT_STATUS_FOOBAR);
+}
+
+