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

r13208: Clearly separate named pipes from the IPC$ NTVFS type.

This allows the easy addition of additional named pipes and removes the
circular dependencies between the CIFS, RPC and RAP servers.

Simple tests for a custom named pipe included.
(This used to be commit 898d15acbd)
This commit is contained in:
Jelmer Vernooij 2006-01-28 12:58:38 +00:00 committed by Gerald (Jerry) Carter
parent 654a21178f
commit ad6303f82f
16 changed files with 554 additions and 164 deletions

View File

@ -28,7 +28,10 @@ sub _prepare_build_h($)
foreach my $key (values %{$depend}) {
my $DEFINE = ();
next if ($key->{TYPE} ne "LIBRARY" and $key->{TYPE} ne "SUBSYSTEM");
next if ($key->{TYPE} ne "LIBRARY" and
$key->{TYPE} ne "SUBSYSTEM" and
$key->{TYPE} ne "BINARY" and
$key->{TYPE} ne "MODULE");
next unless defined($key->{INIT_FUNCTIONS});
$DEFINE->{COMMENT} = "$key->{TYPE} $key->{NAME} INIT";

View File

@ -319,10 +319,10 @@
/* used to indicate end of chain */
#define SMB_CHAIN_NONE 0xFF
/* These are the trans subcommands */
#define TRANSACT_SETNAMEDPIPEHANDLESTATE 0x01
#define TRANSACT_DCERPCCMD 0x26
#define TRANSACT_WAITNAMEDPIPEHANDLESTATE 0x53
/* These are the named pipe commands */
#define NAMED_PIPE_SETHANDLESTATE 0x01
#define NAMED_PIPE_TRANSACT 0x26
#define NAMED_PIPE_WAITHANDLESTATE 0x53
/* These are the NT transact sub commands. */
#define NT_TRANSACT_CREATE 1

View File

@ -164,3 +164,5 @@ struct smbcli_state;
struct substitute_context;
struct model_ops;
struct named_pipe_ops;

View File

@ -240,7 +240,7 @@ static NTSTATUS smb_send_trans_request(struct dcerpc_connection *c, DATA_BLOB *b
trans->in.data = *blob;
trans->in.params = data_blob(NULL, 0);
setup[0] = TRANSACT_DCERPCCMD;
setup[0] = NAMED_PIPE_TRANSACT;
setup[1] = smb->fnum;
trans->in.max_param = 0;

View File

@ -47,7 +47,10 @@ OBJ_FILES = \
# End MODULE ntvfs_ipc
################################################
[MODULE::np_echo]
INIT_FUNCTION = np_echo_init
OBJ_FILES = ipc/np_echo.o
SUBSYSTEM = ntvfs_ipc
################################################
# Start MODULE ntvfs_nbench

30
source4/ntvfs/ipc/ipc.h Normal file
View File

@ -0,0 +1,30 @@
/*
Unix SMB/CIFS implementation.
NTVFS IPC$ Named Pipes
Copyright (C) Jelmer Vernooij 2005
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
struct named_pipe_ops {
NTSTATUS (*open)(void *context_data,
const char *path,
struct auth_session_info *session,
struct stream_connection *stream,
TALLOC_CTX *ctx, void **private_data);
NTSTATUS (*trans)(void *private_data, DATA_BLOB *in, DATA_BLOB *out);
NTSTATUS (*write)(void *private_data, DATA_BLOB *out);
NTSTATUS (*read)(void *private_data, DATA_BLOB *in);
};

View File

@ -0,0 +1,77 @@
/*
Unix SMB/CIFS implementation.
DCE/RPC over named pipes support (glue between dcerpc and smb servers)
Copyright (C) Jelmer Vernooij 2005
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
#include "lib/socket/socket.h"
#include "lib/events/events.h"
#include "rpc_server/dcerpc_server.h"
#include "ntvfs/ipc/ipc.h"
static NTSTATUS echo_pipe_open (void *context_data, const char *path, struct auth_session_info *session_info, struct stream_connection *srv_conn, TALLOC_CTX *mem_ctx, void **private_data)
{
*private_data = talloc_zero(mem_ctx, DATA_BLOB);
return NT_STATUS_OK;
}
static NTSTATUS echo_pipe_trans(void *private_data, DATA_BLOB *in, DATA_BLOB *out)
{
memcpy(out->data, in->data, MIN(out->length,in->length));
return NT_STATUS_OK;
}
static NTSTATUS echo_pipe_write(void *private_data, DATA_BLOB *out)
{
DATA_BLOB *cache = private_data;
return data_blob_append(cache, cache, out->data, out->length);
}
static NTSTATUS echo_pipe_read(void *private_data, DATA_BLOB *in)
{
uint8_t *newdata;
DATA_BLOB *cache = private_data;
uint32_t numread = MIN(in->length, cache->length);
memcpy(in->data, cache->data, numread);
cache->length -= numread;
newdata = talloc_memdup(cache, cache+numread, cache->length);
if (newdata == NULL)
return NT_STATUS_NO_MEMORY;
talloc_free(cache->data);
cache->data = newdata;
return NT_STATUS_OK;
}
const struct named_pipe_ops echo_pipe_ops = {
.open = echo_pipe_open,
.write = echo_pipe_write,
.read = echo_pipe_read,
.trans = echo_pipe_trans
};
NTSTATUS np_echo_init(void)
{
return named_pipe_listen("\\PIPE\\NPECHO", &echo_pipe_ops, NULL);
}

View File

@ -4,6 +4,7 @@
Copyright (C) Andrew Tridgell 2003
Copyright (C) Stefan (metze) Metzmacher 2004-2005
Copyright (C) Jelmer Vernooij 2005
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -28,8 +29,10 @@
#include "includes.h"
#include "dlinklist.h"
#include "smb_server/smb_server.h"
#include "ntvfs/ipc/ipc.h"
#include "ntvfs/ntvfs.h"
#include "rpc_server/dcerpc_server.h"
#include "smb_build.h"
#define IPC_BASE_FNUM 0x400
@ -46,8 +49,9 @@ struct ipc_private {
struct pipe_state *next, *prev;
struct ipc_private *private;
const char *pipe_name;
const struct named_pipe_ops *ops;
void *private_data;
uint16_t fnum;
struct dcesrv_connection *dce_conn;
uint16_t ipc_state;
/* we need to remember the session it was opened on,
as it is illegal to operate on someone elses fnum */
@ -76,7 +80,6 @@ static struct pipe_state *pipe_state_find(struct ipc_private *private, uint16_t
static NTSTATUS ipc_connect(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req, const char *sharename)
{
NTSTATUS status;
struct smbsrv_tcon *tcon = req->tcon;
struct ipc_private *private;
@ -97,10 +100,6 @@ static NTSTATUS ipc_connect(struct ntvfs_module_context *ntvfs,
private->idtree_fnum = idr_init(private);
NT_STATUS_HAVE_NO_MEMORY(private->idtree_fnum);
/* setup the DCERPC server subsystem */
status = dcesrv_init_ipc_context(private, &private->dcesrv);
NT_STATUS_NOT_OK_RETURN(status);
return NT_STATUS_OK;
}
@ -171,6 +170,55 @@ static int ipc_fd_destructor(void *ptr)
return 0;
}
static struct named_pipe {
struct named_pipe *prev, *next;
const char *name;
const struct named_pipe_ops *ops;
void *context_data;
} *named_pipes = NULL;
static NTSTATUS find_pipe_ops(const char *fname, const struct named_pipe_ops **ops, void **context_data)
{
struct named_pipe *np;
for (np = named_pipes; np; np = np->next) {
if (strcasecmp_m(np->name, fname) == 0) {
if (ops) *ops = np->ops;
if (context_data) *context_data = np->context_data;
return NT_STATUS_OK;
}
}
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
NTSTATUS named_pipe_listen(const char *name, const struct named_pipe_ops *ops, void *context_data)
{
NTSTATUS status;
struct named_pipe *np;
DEBUG(3, ("Registering named pipe `%s'\n", name));
status = find_pipe_ops(name, NULL, NULL);
if (NT_STATUS_IS_OK(status)) {
return NT_STATUS_OBJECT_NAME_COLLISION;
}
if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
return status;
}
np = talloc(talloc_autofree_context(), struct named_pipe);
np->name = talloc_strdup(np, name);
np->ops = ops;
np->context_data = context_data;
np->prev = np->next = NULL;
DLIST_ADD(named_pipes, np);
return NT_STATUS_OK;
}
/*
open a file backend - used for MSRPC pipes
@ -181,10 +229,9 @@ static NTSTATUS ipc_open_generic(struct ntvfs_module_context *ntvfs,
{
struct pipe_state *p;
NTSTATUS status;
struct dcerpc_binding *ep_description;
struct ipc_private *private = ntvfs->private_data;
void *context_data;
int fnum;
struct stream_connection *srv_conn = req->smb_conn->connection;
if (!req->session || !req->session->session_info) {
return NT_STATUS_ACCESS_DENIED;
@ -193,14 +240,24 @@ static NTSTATUS ipc_open_generic(struct ntvfs_module_context *ntvfs,
p = talloc(req, struct pipe_state);
NT_STATUS_HAVE_NO_MEMORY(p);
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);
status = find_pipe_ops(p->pipe_name, &p->ops, &context_data);
/* FIXME: Perhaps fall back to opening /var/lib/samba/ipc/<pipename> ? */
if (NT_STATUS_IS_ERR(status)) {
DEBUG(0, ("Unable to find pipe ops for `%s'\n", p->pipe_name));
return status;
}
status = p->ops->open(context_data, p->pipe_name, req->session->session_info, req->smb_conn->connection, p, &p->private_data);
if (NT_STATUS_IS_ERR(status)) {
return status;
}
fnum = idr_get_new_above(private->idtree_fnum, p, IPC_BASE_FNUM, UINT16_MAX);
if (fnum == -1) {
return NT_STATUS_TOO_MANY_OPENED_FILES;
@ -209,29 +266,6 @@ static NTSTATUS ipc_open_generic(struct ntvfs_module_context *ntvfs,
p->fnum = fnum;
p->ipc_state = 0x5ff;
/*
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(private->dcesrv,
p,
ep_description,
req->session->session_info,
srv_conn,
&p->dce_conn);
if (!NT_STATUS_IS_OK(status)) {
idr_remove(private->idtree_fnum, p->fnum);
return status;
}
DLIST_ADD(private->pipe_list, p);
p->smbpid = req->smbpid;
@ -351,18 +385,6 @@ static NTSTATUS ipc_copy(struct ntvfs_module_context *ntvfs,
return NT_STATUS_ACCESS_DENIED;
}
static NTSTATUS ipc_readx_dcesrv_output(void *private_data, DATA_BLOB *out, size_t *nwritten)
{
DATA_BLOB *blob = private_data;
if (out->length < blob->length) {
blob->length = out->length;
}
memcpy(blob->data, out->data, blob->length);
*nwritten = blob->length;
return NT_STATUS_OK;
}
/*
read from a file
*/
@ -393,7 +415,7 @@ static NTSTATUS ipc_read(struct ntvfs_module_context *ntvfs,
}
if (data.length != 0) {
status = dcesrv_output(p->dce_conn, &data, ipc_readx_dcesrv_output);
status = p->ops->read(p->private_data, &data);
if (NT_STATUS_IS_ERR(status)) {
return status;
}
@ -431,7 +453,7 @@ static NTSTATUS ipc_write(struct ntvfs_module_context *ntvfs,
return NT_STATUS_INVALID_HANDLE;
}
status = dcesrv_input(p->dce_conn, &data);
status = p->ops->write(p->private_data, &data);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@ -617,71 +639,8 @@ static NTSTATUS ipc_search_close(struct ntvfs_module_context *ntvfs,
return NT_STATUS_ACCESS_DENIED;
}
static NTSTATUS ipc_trans_dcesrv_output(void *private_data, DATA_BLOB *out, size_t *nwritten)
{
NTSTATUS status = NT_STATUS_OK;
DATA_BLOB *blob = private_data;
if (out->length > blob->length) {
status = STATUS_BUFFER_OVERFLOW;
}
if (out->length < blob->length) {
blob->length = out->length;
}
memcpy(blob->data, out->data, blob->length);
*nwritten = blob->length;
return status;
}
/* SMBtrans - handle a DCERPC command */
static NTSTATUS ipc_dcerpc_cmd(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req, struct smb_trans2 *trans)
{
struct pipe_state *p;
struct ipc_private *private = ntvfs->private_data;
NTSTATUS status;
/* the fnum is in setup[1] */
p = pipe_state_find(private, trans->in.setup[1]);
if (!p) {
return NT_STATUS_INVALID_HANDLE;
}
trans->out.data = data_blob_talloc(req, NULL, trans->in.max_data);
if (!trans->out.data.data) {
return NT_STATUS_NO_MEMORY;
}
/* 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;
}
trans->out.setup_count = 0;
trans->out.setup = NULL;
trans->out.params = data_blob(NULL, 0);
return status;
}
/* SMBtrans - set named pipe state */
static NTSTATUS ipc_set_nm_pipe_state(struct ntvfs_module_context *ntvfs,
static NTSTATUS ipc_np_set_nm_state(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req, struct smb_trans2 *trans)
{
struct ipc_private *private = ntvfs->private_data;
@ -706,6 +665,40 @@ static NTSTATUS ipc_set_nm_pipe_state(struct ntvfs_module_context *ntvfs,
return NT_STATUS_OK;
}
/* SMBtrans - named pipe transaction */
static NTSTATUS ipc_np_trans(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req, struct smb_trans2 *trans)
{
struct ipc_private *private = ntvfs->private_data;
NTSTATUS status;
struct pipe_state *p;
/* the fnum is in setup[1] */
p = pipe_state_find(private, trans->in.setup[1]);
if (!p) {
return NT_STATUS_INVALID_HANDLE;
}
if (trans->in.setup_count != 2) {
return NT_STATUS_INVALID_PARAMETER;
}
trans->out.data = data_blob_talloc(req, NULL, trans->in.max_data);
if (!trans->out.data.data) {
return NT_STATUS_NO_MEMORY;
}
status = p->ops->trans(p->private_data, &trans->in.data, &trans->out.data);
if (NT_STATUS_IS_ERR(status)) {
return status;
}
trans->out.setup_count = 0;
trans->out.setup = NULL;
trans->out.params = data_blob(NULL, 0);
return NT_STATUS_OK;
}
/* SMBtrans - used to provide access to SMB pipes */
static NTSTATUS ipc_trans(struct ntvfs_module_context *ntvfs,
@ -713,30 +706,28 @@ static NTSTATUS ipc_trans(struct ntvfs_module_context *ntvfs,
{
NTSTATUS status;
if (strequal(trans->in.trans_name, "\\PIPE\\LANMAN"))
return ipc_rap_call(req, trans);
if (trans->in.setup_count != 2) {
return NT_STATUS_INVALID_PARAMETER;
}
switch (trans->in.setup[0]) {
case TRANSACT_SETNAMEDPIPEHANDLESTATE:
status = ipc_set_nm_pipe_state(ntvfs, req, trans);
break;
case TRANSACT_DCERPCCMD:
status = ipc_dcerpc_cmd(ntvfs, req, trans);
break;
default:
status = NT_STATUS_INVALID_PARAMETER;
break;
if (strequal(trans->in.trans_name, "\\PIPE\\")) { /* Named pipe */
switch (trans->in.setup[0]) {
case NAMED_PIPE_SETHANDLESTATE:
status = ipc_np_set_nm_state(ntvfs, req, trans);
break;
case NAMED_PIPE_TRANSACT:
status = ipc_np_trans(ntvfs, req, trans);
break;
default:
status = NT_STATUS_INVALID_PARAMETER;
break;
}
} else if (strequal(trans->in.trans_name, "\\PIPE\\LANMAN")) { /* RAP */
status = ipc_rap_call(req, trans);
} else {
DEBUG(1, ("Unknown transaction name `%s'\n", trans->in.trans_name));
status = NT_STATUS_NOT_SUPPORTED;
}
return status;
}
/*
initialialise the IPC backend, registering ourselves with the ntvfs subsystem
*/
@ -744,7 +735,9 @@ NTSTATUS ntvfs_ipc_init(void)
{
NTSTATUS ret;
struct ntvfs_ops ops;
init_module_fn static_init[] = STATIC_ntvfs_ipc_MODULES;
init_module_fn *shared_init;
ZERO_STRUCT(ops);
/* fill in the name and type */
@ -791,5 +784,13 @@ NTSTATUS ntvfs_ipc_init(void)
return ret;
}
/* load available named pipe backends */
shared_init = load_samba_modules(NULL, "np");
run_init_functions(static_init);
run_init_functions(shared_init);
talloc_free(shared_init);
return ret;
}

View File

@ -204,6 +204,7 @@ REQUIRED_SUBSYSTEMS = \
PRIVATE_PROTO_HEADER = dcerpc_server_proto.h
OBJ_FILES = \
dcerpc_server.o \
dcerpc_np.o \
dcerpc_sock.o \
dcesrv_auth.o \
handles.o

View File

@ -0,0 +1,167 @@
/*
Unix SMB/CIFS implementation.
DCE/RPC over named pipes support (glue between dcerpc and smb servers)
Copyright (C) Jelmer Vernooij 2005
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
#include "lib/socket/socket.h"
#include "lib/events/events.h"
#include "rpc_server/dcerpc_server.h"
#include "ntvfs/ipc/ipc.h"
static NTSTATUS dcesrv_pipe_open (void *context_data, const char *path, struct auth_session_info *session_info, struct stream_connection *srv_conn, TALLOC_CTX *mem_ctx, void **private_data)
{
NTSTATUS status;
struct dcerpc_binding *ep_description;
struct dcesrv_connection *dce_conn;
ep_description = talloc(mem_ctx, struct dcerpc_binding);
NT_STATUS_HAVE_NO_MEMORY(ep_description);
/*
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, path);
/* The session info is refcount-increased in the
* dcesrv_endpoint_search_connect() function
*/
status = dcesrv_endpoint_search_connect(context_data,
mem_ctx,
ep_description,
session_info,
srv_conn,
&dce_conn);
talloc_free(ep_description);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
*private_data = dce_conn;
return NT_STATUS_OK;
}
static NTSTATUS ipc_trans_dcesrv_output(void *private_data, DATA_BLOB *out, size_t *nwritten)
{
NTSTATUS status = NT_STATUS_OK;
DATA_BLOB *blob = private_data;
if (out->length > blob->length) {
status = STATUS_BUFFER_OVERFLOW;
}
if (out->length < blob->length) {
blob->length = out->length;
}
memcpy(blob->data, out->data, blob->length);
*nwritten = blob->length;
return status;
}
static NTSTATUS dcesrv_pipe_trans(void *private_data, DATA_BLOB *in, DATA_BLOB *out)
{
struct dcesrv_connection *dce_conn = private_data;
NTSTATUS status;
/* 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(dce_conn, in);
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(dce_conn, out, ipc_trans_dcesrv_output);
if (NT_STATUS_IS_ERR(status)) {
return status;
}
return status;
}
static NTSTATUS dcesrv_pipe_write(void *private_data, DATA_BLOB *out)
{
struct dcesrv_connection *dce_conn = private_data;
NTSTATUS status;
status = dcesrv_input(dce_conn, out);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
return status;
}
static NTSTATUS ipc_readx_dcesrv_output(void *private_data, DATA_BLOB *out, size_t *nwritten)
{
DATA_BLOB *blob = private_data;
if (out->length < blob->length) {
blob->length = out->length;
}
memcpy(blob->data, out->data, blob->length);
*nwritten = blob->length;
return NT_STATUS_OK;
}
static NTSTATUS dcesrv_pipe_read(void *private_data, DATA_BLOB *in)
{
struct dcesrv_connection *dce_conn = private_data;
NTSTATUS status;
status = dcesrv_output(dce_conn, in, ipc_readx_dcesrv_output);
if (NT_STATUS_IS_ERR(status)) {
return status;
}
return status;
}
const struct named_pipe_ops dce_pipe_ops = {
.open = dcesrv_pipe_open,
.write = dcesrv_pipe_write,
.read = dcesrv_pipe_read,
.trans = dcesrv_pipe_trans
};
/* Add named pipe endpoint */
NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e, struct event_context *event_ctx, const struct model_ops *model_ops)
{
NTSTATUS status;
status = named_pipe_listen(e->ep_description->endpoint, &dce_pipe_ops, dce_ctx);
if (NT_STATUS_IS_ERR(status)) {
return status;
}
return NT_STATUS_OK;
}

View File

@ -1171,21 +1171,6 @@ static NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx, const char **endpoint_s
return NT_STATUS_OK;
}
/*
initialise the dcerpc server context for ncacn_np based services
*/
NTSTATUS dcesrv_init_ipc_context(TALLOC_CTX *mem_ctx, struct dcesrv_context **_dce_ctx)
{
NTSTATUS status;
struct dcesrv_context *dce_ctx;
status = dcesrv_init_context(mem_ctx, lp_dcerpc_endpoint_servers(), 0, &dce_ctx);
NT_STATUS_NOT_OK_RETURN(status);
*_dce_ctx = dce_ctx;
return NT_STATUS_OK;
}
/* the list of currently registered DCERPC endpoint servers.
*/
static struct ep_server {
@ -1305,8 +1290,8 @@ static NTSTATUS dcesrv_init(struct event_context *event_context, const struct mo
break;
case NCACN_NP:
/* FIXME: status = dcesrv_add_ep_np(dce_ctx, e, event_context, model_ops);
NT_STATUS_NOT_OK_RETURN(status); */
status = dcesrv_add_ep_np(dce_ctx, e, event_context, model_ops);
NT_STATUS_NOT_OK_RETURN(status);
break;
default:

View File

@ -23,7 +23,7 @@ tests="$tests BASE-DIR2 BASE-TCON BASE-OPEN"
tests="$tests BASE-CHKPATH RAW-QFSINFO RAW-QFILEINFO RAW-SFILEINFO"
tests="$tests RAW-LOCK RAW-MKDIR RAW-SEEK RAW-OPEN RAW-WRITE"
tests="$tests RAW-UNLINK RAW-READ RAW-CLOSE RAW-IOCTL RAW-RENAME"
tests="$tests RAW-EAS RAW-STREAMS RAW-ACLS"
tests="$tests RAW-EAS RAW-STREAMS RAW-ACLS RAW-PIPE-ECHO"
failed=0
for t in $tests; do

View File

@ -121,13 +121,14 @@ REQUIRED_SUBSYSTEMS = \
#################################
#################################
# Start SUBSYSTEM TORTURE_RAP
[SUBSYSTEM::TORTURE_RAP]
# Start SUBSYSTEM TORTURE_IPC
[SUBSYSTEM::TORTURE_IPC]
OBJ_FILES = \
rap/rap.o
ipc/rap.o \
ipc/np_echo.o
REQUIRED_SUBSYSTEMS = \
LIBSMB
# End SUBSYSTEM TORTURE_RAP
# End SUBSYSTEM TORTURE_IPC
#################################
#################################
@ -210,7 +211,7 @@ REQUIRED_SUBSYSTEMS = \
TORTURE_RAW \
TORTURE_SMB2 \
TORTURE_RPC \
TORTURE_RAP \
TORTURE_IPC \
TORTURE_AUTH \
TORTURE_LOCAL \
TORTURE_NBENCH \

View File

@ -0,0 +1,119 @@
/*
Unix SMB/CIFS implementation.
Named Pipe Echo test
Copyright (C) Jelmer Vernooij 2005
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
#include "librpc/gen_ndr/security.h"
#include "smb.h"
#include "torture/torture.h"
#include "libcli/raw/libcliraw.h"
#include "libcli/libcli.h"
#define ECHODATA "Good Times, Bad Times"
int torture_np_echo(void)
{
NTSTATUS status;
TALLOC_CTX *mem_ctx = NULL;
struct smbcli_state *cli;
const char *pipe_name = "\\NPECHO";
union smb_open open;
union smb_read read;
union smb_write write;
union smb_close close;
int fnum;
BOOL ret;
ret = torture_open_connection_share(mem_ctx, &cli,
lp_parm_string(-1, "torture", "host"),
"IPC$",
NULL);
if (!ret)
return False;
open.ntcreatex.level = RAW_OPEN_NTCREATEX;
open.ntcreatex.in.flags = 0;
open.ntcreatex.in.root_fid = 0;
open.ntcreatex.in.access_mask =
SEC_STD_READ_CONTROL |
SEC_FILE_WRITE_ATTRIBUTE |
SEC_FILE_WRITE_EA |
SEC_FILE_READ_DATA |
SEC_FILE_WRITE_DATA;
open.ntcreatex.in.file_attr = 0;
open.ntcreatex.in.alloc_size = 0;
open.ntcreatex.in.share_access =
NTCREATEX_SHARE_ACCESS_READ |
NTCREATEX_SHARE_ACCESS_WRITE;
open.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
open.ntcreatex.in.create_options = 0;
open.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_IMPERSONATION;
open.ntcreatex.in.security_flags = 0;
open.ntcreatex.in.fname = pipe_name;
status = smb_raw_open(cli->tree, cli->tree, &open);
if (NT_STATUS_IS_ERR(status))
return False;
fnum = open.ntcreatex.out.fnum;
write.write.level = RAW_WRITE_WRITE;
write.write.in.fnum = fnum;
write.write.in.count = strlen(ECHODATA);
write.write.in.offset = 0;
write.write.in.remaining = 0;
write.write.in.data = (const uint8_t *)ECHODATA;
status = smb_raw_write(cli->tree, &write);
if (NT_STATUS_IS_ERR(status))
return False;
if (write.write.out.nwritten != strlen(ECHODATA))
return False;
read.read.level = RAW_READ_READ;
read.read.in.fnum = fnum;
read.read.in.count = strlen(ECHODATA);
read.read.in.offset = 0;
read.read.in.remaining = 0;
read.read.out.data = talloc_array(mem_ctx, uint8_t, strlen(ECHODATA));
status = smb_raw_read(cli->tree, &read);
if (NT_STATUS_IS_ERR(status))
return False;
if (read.read.out.nread != strlen(ECHODATA))
return False;
if (memcmp(read.read.out.data, ECHODATA, strlen(ECHODATA)) != 0) {
printf ("np_echo: Returned data did not match!\n");
return False;
}
close.close.level = RAW_CLOSE_CLOSE;
close.close.in.fnum = fnum;
close.close.in.write_time = 0;
status = smb_raw_close(cli->tree, &close);
if (NT_STATUS_IS_ERR(status))
return False;
return True;
}

View File

@ -20,10 +20,10 @@
*/
#include "includes.h"
#include "torture/torture.h"
#include "rap.h"
#include "libcli/raw/libcliraw.h"
#include "libcli/libcli.h"
#include "torture/torture.h"
struct rap_call {
uint16_t callno;

View File

@ -2246,6 +2246,7 @@ static struct {
{"RAW-ACLS", torture_raw_acls, 0},
{"RAW-RAP", torture_raw_rap, 0},
{"RAW-COMPOSITE", torture_raw_composite, 0},
{"RAW-PIPE-ECHO", torture_np_echo, 0 },
/* SMB2 tests */
{"SMB2-CONNECT", torture_smb2_connect, 0},