1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-11 05:18:09 +03:00

the next step in the dcerpc server code. Added the link between the

IPC IO routines and the dcerpc endpoint servers.
This commit is contained in:
Andrew Tridgell 0001-01-01 00:00:00 +00:00
parent c598590a11
commit 4929c53bc8
9 changed files with 232 additions and 33 deletions

View File

@ -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);
};

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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 */

View File

@ -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

View File

@ -2168,24 +2168,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
****************************************************************************/

View File

@ -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);
}