summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2004-01-08 22:55:27 +0000
committerStefan Metzmacher <metze@samba.org>2004-01-08 22:55:27 +0000
commit7e6cf43756b7643e2f0ee7ada5076f36f3a24bb7 (patch)
treead6aebaaf7e3da39992548925135537d66ffabaa
parent8364fd2853ff4bb608157656878e05ca7984a2b9 (diff)
downloadsamba-7e6cf43756b7643e2f0ee7ada5076f36f3a24bb7.tar.gz
samba-7e6cf43756b7643e2f0ee7ada5076f36f3a24bb7.tar.bz2
samba-7e6cf43756b7643e2f0ee7ada5076f36f3a24bb7.zip
This patch adds a better dcerpc server infastructure.
1.) We now register endpoint servers add startup via register_backend() and later use the smb.conf 'dcerpc endpoint servers' parameter to setup the dcesrv_context 2.) each endpoint server can register at context creation time as much interfaces as it wants (multiple interfaces on one endpoint are supported!) (NOTE: there's a difference between 'endpoint server' and 'endpoint'! for details look at rpc_server/dcesrv_server.h) 3.) one endpoint can have a security descriptor registered to it self this will be checked in the future when a client wants to connect to an smb pipe endpoint. 4.) we now have a 'remote' endpoint server, which works like the ntvfs_cifs module it takes this options in the [globals] section: dcerpc remote:interfaces = srvsvc, winreg, w32time, epmapper dcerpc remote:binding = ... dcerpc remote:user = ... dcerpc remote:password = ... 5.) we currently have tree endpoint servers: epmapper, rpcecho and remote the default for the 'dcerpc endpiont servers = epmapper, rpcecho' for testing you can also do dcerpc endpoint servers = rpcecho, remote, epmapper dcerpc remote:interfaces = srvsvc, samr, netlogon 6,) please notice the the epmapper now only returns NO_ENTRIES (but I think we'll find a solution for this too:-) 7.) also there're some other stuff left, but step by step :-) This patch also includes updates for the register_subsystem() , ntvfs_init(), and some other funtions to check for duplicate subsystem registration metze (hmmm, my first large commit...I hope it works as supposed :-) (This used to be commit 917e45dafd5be4c2cd90ff425b8d6f8403122349)
-rw-r--r--source4/Makefile.in12
-rw-r--r--source4/build/pidl/header.pm2
-rw-r--r--source4/build/pidl/server.pm114
-rwxr-xr-xsource4/build/pidl/tables.pl2
-rw-r--r--source4/build/pidl/template.pm6
-rw-r--r--source4/configure.in3
-rw-r--r--source4/lib/module.c14
-rw-r--r--source4/librpc/ndr/ndr_sec.c68
-rw-r--r--source4/ntvfs/ipc/vfs_ipc.c22
-rw-r--r--source4/ntvfs/ntvfs_base.c11
-rw-r--r--source4/param/loadparm.c5
-rw-r--r--source4/rpc_server/config.m47
-rw-r--r--source4/rpc_server/dcerpc_server.c529
-rw-r--r--source4/rpc_server/dcerpc_server.h129
-rw-r--r--source4/rpc_server/dcerpc_tcp.c59
-rw-r--r--source4/rpc_server/dcesrv_auth.c98
-rw-r--r--source4/rpc_server/echo/rpc_echo.c12
-rw-r--r--source4/rpc_server/epmapper/rpc_epmapper.c59
-rw-r--r--source4/rpc_server/handles.c14
-rw-r--r--source4/rpc_server/remote/dcesrv_remote.c198
-rw-r--r--source4/smbd/process.c6
-rw-r--r--source4/smbd/process_thread.c2
-rw-r--r--source4/smbd/reply.c2
-rw-r--r--source4/smbd/request.c4
24 files changed, 970 insertions, 408 deletions
diff --git a/source4/Makefile.in b/source4/Makefile.in
index 784ed22f10..00adf52e07 100644
--- a/source4/Makefile.in
+++ b/source4/Makefile.in
@@ -284,12 +284,12 @@ NTVFS_POSIX_OBJ = ntvfs/posix/vfs_posix.o
SMBD_NTVFS_OBJ = ntvfs/ntvfs_base.o ntvfs/ntvfs_util.o \
ntvfs/ntvfs_generic.o @NTVFS_STATIC@
-SMBD_RPC_OBJ = rpc_server/dcerpc_server.o \
- rpc_server/dcesrv_auth.o \
- rpc_server/dcerpc_tcp.o \
- rpc_server/handles.o \
- rpc_server/echo/rpc_echo.o \
- rpc_server/epmapper/rpc_epmapper.o
+DCERPC_RPCECHO_OBJ = rpc_server/echo/rpc_echo.o
+DCERPC_EPMAPPER_OBJ = rpc_server/epmapper/rpc_epmapper.o
+DCERPC_REMOTE_OBJ = rpc_server/remote/dcesrv_remote.o
+
+SMBD_RPC_OBJ = rpc_server/dcerpc_server.o rpc_server/dcesrv_auth.o \
+ rpc_server/dcerpc_tcp.o rpc_server/handles.o @DCERPC_STATIC@
SMBD_OBJ_SRV = smbd/connection.o \
smbd/session.o \
diff --git a/source4/build/pidl/header.pm b/source4/build/pidl/header.pm
index 418ae97aed..c1b6eb44a1 100644
--- a/source4/build/pidl/header.pm
+++ b/source4/build/pidl/header.pm
@@ -278,7 +278,7 @@ sub HeaderInterface($)
$res .= "#define DCERPC_$name\_VERSION $if_version\n";
$res .= "#define DCERPC_$name\_NAME \"$interface->{NAME}\"\n\n";
$res .= "extern const struct dcerpc_interface_table dcerpc_table_$interface->{NAME};\n";
- $res .= "void rpc_$interface->{NAME}_init(void *);\n\n";
+ $res .= "NTSTATUS dcerpc_$interface->{NAME}_init(void);\n\n";
}
foreach my $d (@{$data}) {
diff --git a/source4/build/pidl/server.pm b/source4/build/pidl/server.pm
index f5256d18a6..0938515f48 100644
--- a/source4/build/pidl/server.pm
+++ b/source4/build/pidl/server.pm
@@ -1,6 +1,7 @@
###################################################
# server boilerplate generator
# Copyright tridge@samba.org 2003
+# Copyright metze@samba.org 2004
# released under the GNU GPL
package IdlServer;
@@ -16,7 +17,7 @@ sub pidl($)
#####################################################################
# produce boilerplate code for a interface
-sub Boilerplate($)
+sub Boilerplate_Iface($)
{
my($interface) = shift;
my($data) = $interface->{DATA};
@@ -41,49 +42,105 @@ sub Boilerplate($)
pidl "\tNULL};\n\n";
pidl "
-static BOOL $name\_op_query_endpoint(const struct dcesrv_endpoint *ep)
+static NTSTATUS $name\_op_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface)
{
- return dcesrv_table_query(&dcerpc_table_$name, ep);
+ return NT_STATUS_OK;
}
-static BOOL $name\_op_set_interface(struct dcesrv_state *dce,
- const char *uuid, uint32 if_version)
+static void $name\_op_unbind(struct dcesrv_connection *dce_conn, const struct dcesrv_interface *iface)
{
- return dcesrv_set_interface(dce, uuid, if_version,
- &dcerpc_table_$name, $name\_dispatch_table);
+ return;
}
-static NTSTATUS $name\_op_connect(struct dcesrv_state *dce)
+static NTSTATUS $name\_op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
{
+ uint16 opnum = dce_call->pkt.u.request.opnum;
+
+ return $name\_dispatch_table[opnum](dce_call, mem_ctx, r);
+}
+
+static const struct dcesrv_interface $name\_interface = {
+ &dcerpc_table_$name,
+ $name\_op_bind,
+ $name\_op_unbind,
+ $name\_op_dispatch
+};
+
+";
+}
+
+#####################################################################
+# produce boilerplate code for an endpoint server
+sub Boilerplate_Ep_Server($)
+{
+ my($interface) = shift;
+ my($data) = $interface->{DATA};
+ my $count = 0;
+ my $name = $interface->{NAME};
+ my $uname = uc $name;
+
+ foreach my $d (@{$data}) {
+ if ($d->{TYPE} eq "FUNCTION") { $count++; }
+ }
+
+ if ($count == 0) {
+ return;
+ }
+
+ pidl "
+static NTSTATUS $name\_op_init_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server)
+{
+ int i;
+
+ for (i=0;i<$name\_interface.ndr->endpoints->count;i++) {
+ NTSTATUS ret;
+ const char *name = $name\_interface.ndr->endpoints->names[i];
+
+ ret = dcesrv_interface_register(dce_ctx, name, &$name\_interface, NULL);
+ if (!NT_STATUS_IS_OK(ret)) {
+ DEBUG(1,(\"$name\_op_init_server: failed to register endpoint \'%s\'\\n\",name));
+ return ret;
+ }
+ }
+
return NT_STATUS_OK;
}
-static void $name\_op_disconnect(struct dcesrv_state *dce)
+static BOOL $name\_op_interface_by_uuid(struct dcesrv_interface *iface, const char *uuid, uint32 if_version)
{
- /* nothing to do */
+ return False;
}
-static int $name\_op_lookup_endpoints(TALLOC_CTX *mem_ctx, struct dcesrv_ep_iface **e)
+static BOOL $name\_op_interface_by_name(struct dcesrv_interface *iface, const char *name)
{
- return dcesrv_lookup_endpoints(&dcerpc_table_$name, mem_ctx, e);
+ return False;
}
+
+NTSTATUS dcerpc_$name\_init(void)
+{
+ NTSTATUS ret;
+ struct dcesrv_endpoint_server ep_server;
-static const struct dcesrv_endpoint_ops $name\_ops = {
- $name\_op_query_endpoint,
- $name\_op_set_interface,
- $name\_op_connect,
- $name\_op_disconnect,
- $name\_op_lookup_endpoints
-};
+ /* fill in our name */
+ ep_server.name = \"$name\";
-void rpc_$name\_init(void *v)
-{
- struct dcesrv_context *dce = v;
- if (!dcesrv_endpoint_register(dce, &$name\_ops,
- &dcerpc_table_$name)) {
- DEBUG(1,(\"Failed to register rpcecho endpoint\\n\"));
+ /* fill in all the operations */
+ ep_server.init_server = $name\_op_init_server;
+
+ ep_server.interface_by_uuid = $name\_op_interface_by_uuid;
+ ep_server.interface_by_name = $name\_op_interface_by_name;
+
+ /* register ourselves with the NTVFS subsystem. */
+ ret = register_backend(\"dcerpc\", &ep_server);
+
+ if (!NT_STATUS_IS_OK(ret)) {
+ DEBUG(0,(\"Failed to register \'$name\' endpoint server!\\n\"));
+ return ret;
}
+
+ return ret;
}
+
";
}
@@ -95,9 +152,12 @@ sub Parse($)
my($idl) = shift;
$res = "/* dcerpc server boilerplate generated by pidl */\n\n";
foreach my $x (@{$idl}) {
- ($x->{TYPE} eq "INTERFACE") &&
- Boilerplate($x);
+ if ($x->{TYPE} eq "INTERFACE") {
+ Boilerplate_Iface($x);
+ Boilerplate_Ep_Server($x);
+ }
}
+
return $res;
}
diff --git a/source4/build/pidl/tables.pl b/source4/build/pidl/tables.pl
index fa53af1c09..bf1db20e28 100755
--- a/source4/build/pidl/tables.pl
+++ b/source4/build/pidl/tables.pl
@@ -60,7 +60,7 @@ sub process_file($)
close(FILE);
}
-
+print "Creating $opt_output.[ch]\n";
open(TABLEH, ">$opt_output.h") || die "failed to open $opt_output.h\n";
open(TABLEC, ">$opt_output.c") || die "failed to open $opt_output.c\n";
diff --git a/source4/build/pidl/template.pm b/source4/build/pidl/template.pm
index f9f9897ce2..6e0decbf40 100644
--- a/source4/build/pidl/template.pm
+++ b/source4/build/pidl/template.pm
@@ -18,8 +18,7 @@ sub Template($)
my $name = $interface->{NAME};
$res .=
-"
-/*
+"/*
Unix SMB/CIFS implementation.
endpoint server for the $name pipe
@@ -53,7 +52,7 @@ sub Template($)
/*
$fname
*/
-static NTSTATUS $fname(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx,
+static NTSTATUS $fname(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct $fname *r)
{
return NT_STATUS_NOT_IMPLEMENTED;
@@ -85,4 +84,3 @@ sub Parse($)
}
1;
-
diff --git a/source4/configure.in b/source4/configure.in
index 82773bc179..e615a31cee 100644
--- a/source4/configure.in
+++ b/source4/configure.in
@@ -233,7 +233,7 @@ DYNEXP=
dnl Add modules that have to be built by default here
dnl These have to be built static:
-default_static_modules="ntvfs_ipc ntvfs_simple ntvfs_print ntvfs_cifs"
+default_static_modules="ntvfs_ipc ntvfs_simple ntvfs_print ntvfs_cifs dcerpc_rpcecho dcerpc_epmapper dcerpc_remote"
dnl These are preferably build shared, and static if dlopen() is not available
default_shared_modules=""
@@ -2830,6 +2830,7 @@ SMB_MODULE(charset_weird, modules/weird.o, "bin/weird.$SHLIBEXT", CHARSET)
SMB_SUBSYSTEM(CHARSET,lib/iconv.o)
sinclude(ntvfs/config.m4)
+sinclude(rpc_server/config.m4)
AC_DEFINE_UNQUOTED(STRING_STATIC_MODULES, "$string_static_modules", [String list of builtin modules])
diff --git a/source4/lib/module.c b/source4/lib/module.c
index ffd6a38c77..15f92db59e 100644
--- a/source4/lib/module.c
+++ b/source4/lib/module.c
@@ -125,9 +125,19 @@ struct subsystem {
static struct subsystem *subsystems = NULL;
-void register_subsystem(const char *name, register_backend_function callback)
+NTSTATUS register_subsystem(const char *name, register_backend_function callback)
{
struct subsystem *s;
+ struct subsystem *t = subsystems;
+
+ while(t) {
+ if(!strcmp(name, t->name)) {
+ /* its already registered! */
+ DEBUG(0,("SUBSYSTEM '%s' for type already registered\n", name));
+ return NT_STATUS_OBJECT_NAME_COLLISION;
+ }
+ t = t->next;
+ }
s = smb_xmalloc(sizeof(struct subsystem));
@@ -136,6 +146,8 @@ void register_subsystem(const char *name, register_backend_function callback)
s->prev = s->next = NULL;
DLIST_ADD(subsystems, s);
+
+ return NT_STATUS_OK;
}
NTSTATUS register_backend(const char *subsystem, void *args)
diff --git a/source4/librpc/ndr/ndr_sec.c b/source4/librpc/ndr/ndr_sec.c
index a3be697c49..49c88d1563 100644
--- a/source4/librpc/ndr/ndr_sec.c
+++ b/source4/librpc/ndr/ndr_sec.c
@@ -88,6 +88,37 @@ void ndr_print_dom_sid2(struct ndr_print *ndr, const char *name, struct dom_sid2
ndr_print_dom_sid(ndr, name, sid);
}
+/*
+ return the wire size of a dom_sid
+*/
+size_t ndr_size_dom_sid(struct dom_sid *sid)
+{
+ if (!sid) return 0;
+ return 8 + 4*sid->num_auths;
+}
+
+/*
+ add a rid to a domain dom_sid to make a full dom_sid
+*/
+struct dom_sid *dom_sid_add_rid(TALLOC_CTX *mem_ctx,
+ const struct dom_sid *domain_sid,
+ uint32 rid)
+{
+ struct dom_sid *sid;
+
+ sid = talloc_p(mem_ctx, struct dom_sid);
+ if (!sid) return NULL;
+
+ *sid = *domain_sid;
+ sid->sub_auths = talloc_array_p(mem_ctx, uint32, sid->num_auths+1);
+ if (!sid->sub_auths) {
+ return NULL;
+ }
+ memcpy(sid->sub_auths, domain_sid->sub_auths, sid->num_auths*sizeof(uint32));
+ sid->sub_auths[sid->num_auths] = rid;
+ sid->num_auths++;
+ return sid;
+}
/*
return the wire size of a security_ace
@@ -115,15 +146,6 @@ size_t ndr_size_security_acl(struct security_acl *acl)
}
/*
- return the wire size of a dom_sid
-*/
-size_t ndr_size_dom_sid(struct dom_sid *sid)
-{
- if (!sid) return 0;
- return 8 + 4*sid->num_auths;
-}
-
-/*
return the wire size of a security descriptor
*/
size_t ndr_size_security_descriptor(struct security_descriptor *sd)
@@ -139,25 +161,17 @@ size_t ndr_size_security_descriptor(struct security_descriptor *sd)
return ret;
}
-/*
- add a rid to a domain dom_sid to make a full dom_sid
-*/
-struct dom_sid *dom_sid_add_rid(TALLOC_CTX *mem_ctx,
- const struct dom_sid *domain_sid,
- uint32 rid)
+/*
+ talloc and copy a security descriptor
+ */
+struct security_descriptor *copy_security_descriptor(TALLOC_CTX *mem_ctx,
+ const struct security_descriptor *osd)
{
- struct dom_sid *sid;
+ struct security_descriptor *nsd;
- sid = talloc_p(mem_ctx, struct dom_sid);
- if (!sid) return NULL;
+ /* FIXME */
+ DEBUG(1, ("copy_security_descriptor: sorry unimplemented yet\n"));
+ nsd = NULL;
- *sid = *domain_sid;
- sid->sub_auths = talloc_array_p(mem_ctx, uint32, sid->num_auths+1);
- if (!sid->sub_auths) {
- return NULL;
- }
- memcpy(sid->sub_auths, domain_sid->sub_auths, sid->num_auths*sizeof(uint32));
- sid->sub_auths[sid->num_auths] = rid;
- sid->num_auths++;
- return sid;
+ return nsd;
}
diff --git a/source4/ntvfs/ipc/vfs_ipc.c b/source4/ntvfs/ipc/vfs_ipc.c
index 96f28895c9..cd300b6589 100644
--- a/source4/ntvfs/ipc/vfs_ipc.c
+++ b/source4/ntvfs/ipc/vfs_ipc.c
@@ -1,7 +1,9 @@
/*
Unix SMB/CIFS implementation.
default IPC$ NTVFS backend
+
Copyright (C) Andrew Tridgell 2003
+ Copyright (C) Stefan (metze) Metzmacher 2004
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
@@ -39,7 +41,7 @@ struct ipc_private {
TALLOC_CTX *mem_ctx;
const char *pipe_name;
uint16 fnum;
- struct dcesrv_state *pipe_state;
+ struct dcesrv_connection *dce_conn;
uint16 ipc_state;
} *pipe_list;
@@ -77,7 +79,7 @@ again:
static void pipe_shutdown(struct ipc_private *private, struct pipe_state *p)
{
TALLOC_CTX *mem_ctx = private->pipe_list->mem_ctx;
- dcesrv_endpoint_disconnect(private->pipe_list->pipe_state);
+ dcesrv_endpoint_disconnect(private->pipe_list->dce_conn);
DLIST_REMOVE(private->pipe_list, private->pipe_list);
talloc_destroy(mem_ctx);
}
@@ -192,7 +194,7 @@ static NTSTATUS ipc_open_generic(struct request_context *req, const char *fname,
struct pipe_state *p;
TALLOC_CTX *mem_ctx;
NTSTATUS status;
- struct dcesrv_endpoint endpoint;
+ struct dcesrv_ep_description ep_description;
struct ipc_private *private = req->conn->ntvfs_private;
mem_ctx = talloc_init("ipc_open '%s'", fname);
@@ -235,10 +237,10 @@ static NTSTATUS ipc_open_generic(struct request_context *req, const char *fname,
finalised for Samba4
*/
- endpoint.type = ENDPOINT_SMB;
- endpoint.info.smb_pipe = p->pipe_name;
+ ep_description.type = ENDPOINT_SMB;
+ ep_description.info.smb_pipe = p->pipe_name;
- status = dcesrv_endpoint_connect(&req->smb->dcesrv, &endpoint, &p->pipe_state);
+ status = dcesrv_endpoint_search_connect(&req->smb->dcesrv, &ep_description, &p->dce_conn);
if (!NT_STATUS_IS_OK(status)) {
talloc_destroy(mem_ctx);
return status;
@@ -386,7 +388,7 @@ static NTSTATUS ipc_read(struct request_context *req, union smb_read *rd)
return NT_STATUS_INVALID_HANDLE;
}
- status = dcesrv_output(p->pipe_state, &data);
+ status = dcesrv_output(p->dce_conn, &data);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@@ -440,7 +442,7 @@ static NTSTATUS ipc_write(struct request_context *req, union smb_write *wr)
return NT_STATUS_INVALID_HANDLE;
}
- status = dcesrv_input(p->pipe_state, &data);
+ status = dcesrv_input(p->dce_conn, &data);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@@ -599,7 +601,7 @@ static NTSTATUS ipc_dcerpc_cmd(struct request_context *req, struct smb_trans2 *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);
+ status = dcesrv_input(p->dce_conn, &trans->in.data);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@@ -609,7 +611,7 @@ static NTSTATUS ipc_dcerpc_cmd(struct request_context *req, struct smb_trans2 *t
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);
+ status = dcesrv_output(p->dce_conn, &trans->out.data);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
diff --git a/source4/ntvfs/ntvfs_base.c b/source4/ntvfs/ntvfs_base.c
index ad1b3ae671..e4009fd1f0 100644
--- a/source4/ntvfs/ntvfs_base.c
+++ b/source4/ntvfs/ntvfs_base.c
@@ -1,7 +1,9 @@
/*
Unix SMB/CIFS implementation.
NTVFS base code
+
Copyright (C) Andrew Tridgell 2003
+ Copyright (C) Stefan (metze) Metzmacher 2004
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
@@ -107,12 +109,17 @@ const struct ntvfs_critical_sizes *ntvfs_interface_version(void)
*/
BOOL ntvfs_init(void)
{
- register_subsystem("ntvfs", ntvfs_register);
+ NTSTATUS status;
+
+ status = register_subsystem("ntvfs", ntvfs_register);
+ if (!NT_STATUS_IS_OK(status)) {
+ return False;
+ }
/* FIXME: Perhaps panic if a basic backend, such as IPC, fails to initialise? */
static_init_ntvfs;
- DEBUG(3,("NTVFS version %d initialised\n", NTVFS_INTERFACE_VERSION));
+ DEBUG(3,("NTVFS subsystem version %d initialised\n", NTVFS_INTERFACE_VERSION));
return True;
}
diff --git a/source4/param/loadparm.c b/source4/param/loadparm.c
index aff4a4f12a..9052fe4409 100644
--- a/source4/param/loadparm.c
+++ b/source4/param/loadparm.c
@@ -151,6 +151,7 @@ typedef struct
char *szAbortShutdownScript;
char *szWINSHook;
char *szWINSPartners;
+ char **dcerpc_ep_servers;
#ifdef WITH_UTMP
char *szUtmpDir;
char *szWtmpDir;
@@ -738,6 +739,7 @@ static struct parm_struct parm_table[] = {
{"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
{"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
{"ntvfs handler", P_STRING, P_LOCAL, &sDefault.ntvfs_handler, NULL, NULL, FLAG_ADVANCED},
+ {"dcerpc endpoint servers", P_LIST, P_GLOBAL, &Globals.dcerpc_ep_servers, NULL, NULL, FLAG_ADVANCED},
{"Security Options", P_SEP, P_SEPARATOR},
@@ -1270,6 +1272,8 @@ static void init_globals(void)
string_set(&sDefault.fstype, FSTYPE_STRING);
string_set(&sDefault.ntvfs_handler, "default");
+ Globals.dcerpc_ep_servers = str_list_make("epmapper rpcecho", NULL);
+
string_set(&Globals.szSMBPasswdFile, dyn_SMB_PASSWD_FILE);
string_set(&Globals.szPrivateDir, dyn_PRIVATE_DIR);
@@ -1571,6 +1575,7 @@ FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
FN_GLOBAL_STRING(lp_mangling_method, &Globals.szManglingMethod)
FN_GLOBAL_INTEGER(lp_mangle_prefix, &Globals.mangle_prefix)
+FN_GLOBAL_LIST(lp_dcerpc_endpoint_servers, &Globals.dcerpc_ep_servers)
#ifdef WITH_UTMP
FN_GLOBAL_STRING(lp_utmpdir, &Globals.szUtmpDir)
FN_GLOBAL_STRING(lp_wtmpdir, &Globals.szWtmpDir)
diff --git a/source4/rpc_server/config.m4 b/source4/rpc_server/config.m4
new file mode 100644
index 0000000000..cdc4f65186
--- /dev/null
+++ b/source4/rpc_server/config.m4
@@ -0,0 +1,7 @@
+default_static_modules="$default_static_modules dcerpc_rpcecho dcerpc_epmapper dcerpc_remote"
+
+SMB_MODULE(dcerpc_rpcecho, \$(DCERPC_RPCECHO_OBJ), "bin/dcerpc_rpcecho.$SHLIBEXT$", DCERPC)
+SMB_MODULE(dcerpc_epmapper, \$(DCERPC_EPMAPPER_OBJ), "bin/dcerpc_epmapper.$SHLIBEXT$", DCERPC)
+SMB_MODULE(dcerpc_remote, \$(DCERPC_REMOTE_OBJ), "bin/dcerpc_remote.$SHLIBEXT$", DCERPC)
+
+SMB_SUBSYSTEM(DCERPC,rpc_server/dcerpc_server.o)
diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c
index d3e2f1917f..46341e6db1 100644
--- a/source4/rpc_server/dcerpc_server.c
+++ b/source4/rpc_server/dcerpc_server.c
@@ -4,6 +4,7 @@
server side dcerpc core code
Copyright (C) Andrew Tridgell 2003
+ Copyright (C) Stefan (metze) Metzmacher 2004
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
@@ -23,15 +24,105 @@
#include "includes.h"
/*
- find the set of endpoint operations for an endpoint server
+ see if two endpoints match
*/
-static const struct dcesrv_endpoint_ops *find_endpoint(struct dcesrv_context *dce,
- const struct dcesrv_endpoint *endpoint)
+static BOOL endpoints_match(const struct dcesrv_ep_description *ep1,
+ const struct dcesrv_ep_description *ep2)
{
- struct dce_endpoint *ep;
- for (ep=dce->endpoint_list; ep; ep=ep->next) {
- if (ep->endpoint_ops->query_endpoint(endpoint)) {
- return ep->endpoint_ops;
+ if (ep1->type != ep2->type) {
+ return False;
+ }
+
+ switch (ep1->type) {
+ case ENDPOINT_SMB:
+ if (strcmp(ep1->info.smb_pipe,ep2->info.smb_pipe)==0) {
+ return True;
+ }
+ break;
+ case ENDPOINT_TCP:
+ if (ep1->info.tcp_port == ep2->info.tcp_port) {
+ return True;
+ }
+ break;
+ }
+
+ return False;
+}
+
+/*
+ find an endpoint in the dcesrv_context
+*/
+static struct dcesrv_endpoint *find_endpoint(struct dcesrv_context *dce_ctx,
+ const struct dcesrv_ep_description *ep_description)
+{
+ struct dcesrv_endpoint *ep;
+ for (ep=dce_ctx->endpoint_list; ep; ep=ep->next) {
+ if (endpoints_match(&ep->ep_description, ep_description)) {
+ return ep;
+ }
+ }
+ return NULL;
+}
+
+/*
+ see if a uuid and if_version match to an interface
+*/
+static BOOL interface_match(const struct dcesrv_interface *if1,
+ const struct dcesrv_interface *if2)
+{
+ if (if1->ndr->if_version != if2->ndr->if_version) {
+ return False;
+ }
+
+ if (strcmp(if1->ndr->uuid, if2->ndr->uuid)==0) {
+ return True;
+ }
+
+ return False;
+}
+
+/*
+ find the interface operations on an endpoint
+*/
+static const struct dcesrv_interface *find_interface(const struct dcesrv_endpoint *endpoint,
+ const struct dcesrv_interface *iface)
+{
+ struct dcesrv_if_list *ifl;
+ for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
+ if (interface_match(&(ifl->iface), iface)) {
+ return &(ifl->iface);
+ }
+ }
+ return NULL;
+}
+
+/*
+ see if a uuid and if_version match to an interface
+*/
+static BOOL interface_match_by_uuid(const struct dcesrv_interface *iface,
+ const char *uuid, uint32 if_version)
+{
+ if (iface->ndr->if_version != if_version) {
+ return False;
+ }
+
+ if (strcmp(iface->ndr->uuid, uuid)==0) {
+ return True;
+ }
+
+ return False;
+}
+
+/*
+ find the interface operations on an endpoint by uuid
+*/
+static const struct dcesrv_interface *find_interface_by_uuid(const struct dcesrv_endpoint *endpoint,
+ const char *uuid, uint32 if_version)
+{
+ struct dcesrv_if_list *ifl;
+ for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
+ if (interface_match_by_uuid(&(ifl->iface), uuid, if_version)) {
+ return &(ifl->iface);
}
}
return NULL;
@@ -40,10 +131,10 @@ static const struct dcesrv_endpoint_ops *find_endpoint(struct dcesrv_context *dc
/*
find a call that is pending in our call list
*/
-static struct dcesrv_call_state *dcesrv_find_call(struct dcesrv_state *dce, uint16 call_id)
+static struct dcesrv_call_state *dcesrv_find_call(struct dcesrv_connection *dce_conn, uint16 call_id)
{
struct dcesrv_call_state *c;
- for (c=dce->call_list;c;c=c->next) {
+ for (c=dce_conn->call_list;c;c=c->next) {
if (c->pkt.call_id == call_id) {
return c;
}
@@ -52,121 +143,175 @@ static struct dcesrv_call_state *dcesrv_find_call(struct dcesrv_state *dce, uint
}
/*
- register an endpoint server
+ register an interface on an endpoint
*/
-BOOL dcesrv_endpoint_register(struct dcesrv_context *dce,
- const struct dcesrv_endpoint_ops *ops,
- const struct dcerpc_interface_table *table)
+NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
+ const char *ep_name,
+ const struct dcesrv_interface *iface,
+ const struct security_descriptor *sd)
{
- BOOL done_smb=False;
- BOOL done_tcp=False;
- int i;
+ struct dcesrv_ep_description ep_description;
+ struct dcesrv_endpoint *ep;
+ struct dcesrv_if_list *ifl;
+ BOOL tcp;
+ BOOL add_ep = False;
- for (i=0;i<table->endpoints->count;i++) {
- struct dce_endpoint *ep;
- BOOL tcp;
+ tcp = (strncasecmp(ep_name, "TCP-", 4) == 0);
- tcp = (strncasecmp(table->endpoints->names[i], "TCP-", 4) == 0);
+ if (tcp) {
+ ep_description.type = ENDPOINT_TCP;
+ ep_description.info.tcp_port = atoi(ep_name+4);
+ } else {
+ ep_description.type = ENDPOINT_SMB;
+ ep_description.info.smb_pipe = ep_name;
+ }
+ /* check if this endpoint exists
+ */
+ if ((ep=find_endpoint(dce_ctx, &ep_description))==NULL) {
+ ep = talloc(dce_ctx->mem_ctx, sizeof(*ep));
+ if (!ep) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ ZERO_STRUCTP(ep);
if (tcp) {
- if (done_tcp) continue;
- done_tcp = True;
+ ep->ep_description.type = ENDPOINT_TCP;
+ ep->ep_description.info.tcp_port = atoi(ep_name+4);
} else {
- if (done_smb) continue;
- done_smb = True;
+ ep->ep_description.type = ENDPOINT_SMB;
+ ep->ep_description.info.smb_pipe = smb_xstrdup(ep_name);
}
+ add_ep = True;
+ }
- ep = malloc(sizeof(*ep));
- if (!ep) {
- return False;
+ /* see if the interface is already registered on te endpoint */
+ if (find_interface(ep, iface)!=NULL) {
+ DEBUG(0,("dcesrv_interface_register: interface '%s' already registered on endpoint '%s'\n",
+ iface->ndr->name, ep_name));
+ return NT_STATUS_OBJECT_NAME_COLLISION;
+ }
+
+ /* talloc a new interface list element */
+ ifl = talloc(dce_ctx->mem_ctx, sizeof(*ifl));
+ if (!ifl) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* copy the given interface struct to the one on the endpoints interface list */
+ memcpy(&(ifl->iface),iface, sizeof(struct dcesrv_interface));
+
+ /* if we have a security descriptor given,
+ * we should see if we can set it up on the endpoint
+ */
+ if (sd != NULL) {
+ /* if there's currently no security descriptor given on the endpoint
+ * we try to set it
+ */
+ if (ep->sd == NULL) {
+ ep->sd = copy_security_descriptor(dce_ctx->mem_ctx, sd);
}
- if (tcp) {
- ep->endpoint.type = ENDPOINT_TCP;
- ep->endpoint.info.tcp_port = atoi(table->endpoints->names[i]+4);
- } else {
- ep->endpoint.type = ENDPOINT_SMB;
- ep->endpoint.info.smb_pipe = table->endpoints->names[i];
+ /* if now there's no security descriptor given on the endpoint
+ * something goes wrong, either we failed to copy the security descriptor
+ * or there was already one on the endpoint
+ */
+ if (ep->sd != NULL) {
+ DEBUG(0,("dcesrv_interface_register: interface '%s' failed to setup a security descriptor\n"
+ " on endpoint '%s'\n",
+ iface->ndr->name, ep_name));
+ if (add_ep) free(ep);
+ free(ifl);
+ return NT_STATUS_OBJECT_NAME_COLLISION;
}
+ }
- ep->endpoint_ops = ops;
- DLIST_ADD(dce->endpoint_list, ep);
+ /* finally add the interface on the endpoint */
+ DLIST_ADD(ep->interface_list, ifl);
+
+ /* if it's a new endpoint add it to the dcesrv_context */
+ if (add_ep) {
+ DLIST_ADD(dce_ctx->endpoint_list, ep);
}
- return True;
+ DEBUG(3,("dcesrv_interface_register: interface '%s' registered on endpoint '%s'\n",
+ iface->ndr->name, ep_name));
+
+ return NT_STATUS_OK;
}
/*
connect to a dcerpc endpoint
*/
-NTSTATUS dcesrv_endpoint_connect_ops(struct dcesrv_context *dce,
- const struct dcesrv_endpoint *endpoint,
- const struct dcesrv_endpoint_ops *ops,
- struct dcesrv_state **p)
+NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
+ const struct dcesrv_endpoint *ep,
+ struct dcesrv_connection **p)
{
TALLOC_CTX *mem_ctx;
- NTSTATUS status;
mem_ctx = talloc_init("dcesrv_endpoint_connect");
if (!mem_ctx) {
return NT_STATUS_NO_MEMORY;
}
- *p = talloc_p(mem_ctx, struct dcesrv_state);
+ *p = talloc_p(mem_ctx, struct dcesrv_connection);
if (! *p) {
talloc_destroy(mem_ctx);
return NT_STATUS_NO_MEMORY;
}
- (*p)->dce = dce;
+ (*p)->dce_ctx = dce_ctx;
(*p)->mem_ctx = mem_ctx;
- (*p)->endpoint = *endpoint;
- (*p)->ops = ops;
+ (*p)->endpoint = ep;
+ (*p)->iface = NULL;
(*p)->private = NULL;
(*p)->call_list = NULL;
(*p)->cli_max_recv_frag = 0;
- (*p)->ndr = NULL;
- (*p)->dispatch = NULL;
(*p)->handles = NULL;
(*p)->partial_input = data_blob(NULL, 0);
(*p)->auth_state.ntlmssp_state = NULL;
(*p)->auth_state.auth_info = NULL;
- /* make sure the endpoint server likes the connection */
- status = ops->connect(*p);
- if (!NT_STATUS_IS_OK(status)) {
- talloc_destroy(mem_ctx);
- return status;
- }
-
return NT_STATUS_OK;
}
/*
- connect to a dcerpc endpoint
+ search and connect to a dcerpc endpoint
*/
-NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce,
- const struct dcesrv_endpoint *endpoint,
- struct dcesrv_state **p)
+NTSTATUS dcesrv_endpoint_search_connect(struct dcesrv_context *dce_ctx,
+ const struct dcesrv_ep_description *ep_description,
+ struct dcesrv_connection **dce_conn_p)
{
- const struct dcesrv_endpoint_ops *ops;
+ NTSTATUS status;
+ const struct dcesrv_endpoint *ep;
/* make sure this endpoint exists */
- ops = find_endpoint(dce, endpoint);
- if (!ops) {
+ ep = find_endpoint(dce_ctx, ep_description);
+ if (!ep) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
- return dcesrv_endpoint_connect_ops(dce, endpoint, ops, p);
+ status = dcesrv_endpoint_connect(dce_ctx, ep, dce_conn_p);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /* TODO: check security descriptor of the endpoint here
+ * if it's a smb named pipe
+ * if it's failed free dce_conn_p
+ */
+
+ return NT_STATUS_OK;
}
/*
disconnect a link to an endpoint
*/
-void dcesrv_endpoint_disconnect(struct dcesrv_state *p)
+void dcesrv_endpoint_disconnect(struct dcesrv_connection *p)
{
- p->ops->disconnect(p);
+ if (p->iface) {
+ p->iface->unbind(p, p->iface);
+ }
/* destroy any handles */
while (p->handles) {
@@ -315,15 +460,16 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
return dcesrv_bind_nak(call, 0);
}
- if (!call->dce->ops->set_interface(call->dce, uuid, if_version)) {
+ call->conn->iface = find_interface_by_uuid(call->conn->endpoint, uuid, if_version);
+ if (!call->conn->iface) {
DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid, if_version));
/* we don't know about that interface */
result = DCERPC_BIND_PROVIDER_REJECT;
- reason = DCERPC_BIND_REASON_ASYNTAX;
+ reason = DCERPC_BIND_REASON_ASYNTAX;
}
- if (call->dce->cli_max_recv_frag == 0) {
- call->dce->cli_max_recv_frag = call->pkt.u.bind.max_recv_frag;
+ if (call->conn->cli_max_recv_frag == 0) {
+ call->conn->cli_max_recv_frag = call->pkt.u.bind.max_recv_frag;
}
/* handle any authentication that is being requested */
@@ -340,9 +486,9 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
pkt.u.bind_ack.max_xmit_frag = 0x2000;
pkt.u.bind_ack.max_recv_frag = 0x2000;
pkt.u.bind_ack.assoc_group_id = call->pkt.u.bind.assoc_group_id;
- if (call->dce->ndr) {
+ if (call->conn->iface && call->conn->iface->ndr) {
pkt.u.bind_ack.secondary_address = talloc_asprintf(call->mem_ctx, "\\PIPE\\%s",
- call->dce->ndr->name);
+ call->conn->iface->ndr->name);
} else {
pkt.u.bind_ack.secondary_address = "";
}
@@ -361,13 +507,21 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
return dcesrv_bind_nak(call, 0);
}
+ if (call->conn->iface) {
+ status = call->conn->iface->bind(call, call->conn->iface);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(2,("Request for dcerpc interface %s/%d rejected\n", uuid, if_version));
+ return status;
+ }
+ }
+
rep = talloc_p(call->mem_ctx, struct dcesrv_call_reply);
if (!rep) {
return NT_STATUS_NO_MEMORY;
}
status = dcerpc_push_auth(&rep->data, call->mem_ctx, &pkt,
- call->dce->auth_state.auth_info);
+ call->conn->auth_state.auth_info);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@@ -375,7 +529,7 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
dcerpc_set_frag_length(&rep->data, rep->data.length);
DLIST_ADD_END(call->replies, rep, struct dcesrv_call_reply *);
- DLIST_ADD_END(call->dce->call_list, call, struct dcesrv_call_state *);
+ DLIST_ADD_END(call->conn->call_list, call, struct dcesrv_call_state *);
return NT_STATUS_OK;
}
@@ -413,7 +567,7 @@ static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
opnum = call->pkt.u.request.opnum;
- if (opnum >= call->dce->ndr->num_calls) {
+ if (opnum >= call->conn->iface->ndr->num_calls) {
return dcesrv_fault(call, DCERPC_FAULT_OP_RNG_ERROR);
}
@@ -422,7 +576,7 @@ static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
return NT_STATUS_NO_MEMORY;
}
- r = talloc(call->mem_ctx, call->dce->ndr->calls[opnum].struct_size);
+ r = talloc(call->mem_ctx, call->conn->iface->ndr->calls[opnum].struct_size);
if (!r) {
return NT_STATUS_NO_MEMORY;
}
@@ -432,13 +586,13 @@ static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
}
/* unravel the NDR for the packet */
- status = call->dce->ndr->calls[opnum].ndr_pull(pull, NDR_IN, r);
+ status = call->conn->iface->ndr->calls[opnum].ndr_pull(pull, NDR_IN, r);
if (!NT_STATUS_IS_OK(status)) {
return dcesrv_fault(call, DCERPC_FAULT_NDR);
}
/* call the dispatch function */
- status = call->dce->dispatch[opnum](call->dce, call->mem_ctx, r);
+ status = call->conn->iface->dispatch(call, call->mem_ctx, r);
if (!NT_STATUS_IS_OK(status)) {
return dcesrv_fault_nt(call, status);
}
@@ -453,7 +607,7 @@ static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
push->flags |= LIBNDR_FLAG_BIGENDIAN;
}
- status = call->dce->ndr->calls[opnum].ndr_push(push, NDR_OUT, r);
+ status = call->conn->iface->ndr->calls[opnum].ndr_push(push, NDR_OUT, r);
if (!NT_STATUS_IS_OK(status)) {
return dcesrv_fault(call, DCERPC_FAULT_NDR);
}
@@ -471,9 +625,9 @@ static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
}
length = stub.length;
- if (length + DCERPC_RESPONSE_LENGTH > call->dce->cli_max_recv_frag) {
+ if (length + DCERPC_RESPONSE_LENGTH > call->conn->cli_max_recv_frag) {
/* the 32 is to cope with signing data */
- length = call->dce->cli_max_recv_frag -
+ length = call->conn->cli_max_recv_frag -
(DCERPC_MAX_SIGN_SIZE+DCERPC_RESPONSE_LENGTH);
}
@@ -507,7 +661,7 @@ static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
stub.length -= length;
} while (stub.length != 0);
- DLIST_ADD_END(call->dce->call_list, call, struct dcesrv_call_state *);
+ DLIST_ADD_END(call->conn->call_list, call, struct dcesrv_call_state *);
return NT_STATUS_OK;
}
@@ -530,18 +684,18 @@ static BOOL dce_full_packet(const DATA_BLOB *data)
/*
we might have consumed only part of our input - advance past that part
*/
-static void dce_partial_advance(struct dcesrv_state *dce, uint32 offset)
+static void dce_partial_advance(struct dcesrv_connection *dce_conn, uint32 offset)
{
DATA_BLOB blob;
- if (dce->partial_input.length == offset) {
- free(dce->partial_input.data);
- dce->partial_input = data_blob(NULL, 0);
+ if (dce_conn->partial_input.length == offset) {
+ free(dce_conn->partial_input.data);
+ dce_conn->partial_input = data_blob(NULL, 0);
return;
}
- blob = dce->partial_input;
- dce->partial_input = data_blob(blob.data + offset,
+ blob = dce_conn->partial_input;
+ dce_conn->partial_input = data_blob(blob.data + offset,
blob.length - offset);
free(blob.data);
}
@@ -549,7 +703,7 @@ static void dce_partial_advance(struct dcesrv_state *dce, uint32 offset)
/*
process some input to a dcerpc endpoint server.
*/
-NTSTATUS dcesrv_input_process(struct dcesrv_state *dce)
+NTSTATUS dcesrv_input_process(struct dcesrv_connection *dce_conn)
{
struct ndr_pull *ndr;
TALLOC_CTX *mem_ctx;
@@ -563,20 +717,20 @@ NTSTATUS dcesrv_input_process(struct dcesrv_state *dce)
}
call = talloc_p(mem_ctx, struct dcesrv_call_state);
if (!call) {
- talloc_free(dce->mem_ctx, dce->partial_input.data);
+ talloc_free(dce_conn->mem_ctx, dce_conn->partial_input.data);
talloc_destroy(mem_ctx);
return NT_STATUS_NO_MEMORY;
}
call->mem_ctx = mem_ctx;
- call->dce = dce;
+ call->conn = dce_conn;
call->replies = NULL;
- blob = dce->partial_input;
+ blob = dce_conn->partial_input;
blob.length = dcerpc_get_frag_length(&blob);
ndr = ndr_pull_init_blob(&blob, mem_ctx);
if (!ndr) {
- talloc_free(dce->mem_ctx, dce->partial_input.data);
+ talloc_free(dce_conn->mem_ctx, dce_conn->partial_input.data);
talloc_destroy(mem_ctx);
return NT_STATUS_NO_MEMORY;
}
@@ -587,12 +741,12 @@ NTSTATUS dcesrv_input_process(struct dcesrv_state *dce)
status = ndr_pull_dcerpc_packet(ndr, NDR_SCALARS|NDR_BUFFERS, &call->pkt);
if (!NT_STATUS_IS_OK(status)) {
- talloc_free(dce->mem_ctx, dce->partial_input.data);
+ talloc_free(dce_conn->mem_ctx, dce_conn->partial_input.data);
talloc_destroy(mem_ctx);
return status;
}
- dce_partial_advance(dce, blob.length);
+ dce_partial_advance(dce_conn, blob.length);
/* we have to check the signing here, before combining the
pdus */
@@ -613,7 +767,7 @@ NTSTATUS dcesrv_input_process(struct dcesrv_state *dce)
/* this is a continuation of an existing call - find the call then
tack it on the end */
- call = dcesrv_find_call(dce, call2->pkt.call_id);
+ call = dcesrv_find_call(dce_conn, call2->pkt.call_id);
if (!call) {
return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
}
@@ -648,7 +802,7 @@ NTSTATUS dcesrv_input_process(struct dcesrv_state *dce)
/* this may not be the last pdu in the chain - if its isn't then
just put it on the call_list and wait for the rest */
if (!(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
- DLIST_ADD_END(dce->call_list, call, struct dcesrv_call_state *);
+ DLIST_ADD_END(dce_conn->call_list, call, struct dcesrv_call_state *);
return NT_STATUS_OK;
}
@@ -682,21 +836,21 @@ NTSTATUS dcesrv_input_process(struct dcesrv_state *dce)
provide some input to a dcerpc endpoint server. This passes data
from a dcerpc client into the server
*/
-NTSTATUS dcesrv_input(struct dcesrv_state *dce, const DATA_BLOB *data)
+NTSTATUS dcesrv_input(struct dcesrv_connection *dce_conn, const DATA_BLOB *data)
{
NTSTATUS status;
- dce->partial_input.data = Realloc(dce->partial_input.data,
- dce->partial_input.length + data->length);
- if (!dce->partial_input.data) {
+ dce_conn->partial_input.data = Realloc(dce_conn->partial_input.data,
+ dce_conn->partial_input.length + data->length);
+ if (!dce_conn->partial_input.data) {
return NT_STATUS_NO_MEMORY;
}
- memcpy(dce->partial_input.data + dce->partial_input.length,
+ memcpy(dce_conn->partial_input.data + dce_conn->partial_input.length,
data->data, data->length);
- dce->partial_input.length += data->length;
+ dce_conn->partial_input.length += data->length;
- while (dce_full_packet(&dce->partial_input)) {
- status = dcesrv_input_process(dce);
+ while (dce_full_packet(&dce_conn->partial_input)) {
+ status = dcesrv_input_process(dce_conn);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@@ -710,12 +864,12 @@ NTSTATUS dcesrv_input(struct dcesrv_state *dce, const DATA_BLOB *data)
is wanted is in data->length and data->data is already allocated
to hold that much data.
*/
-NTSTATUS dcesrv_output(struct dcesrv_state *dce, DATA_BLOB *data)
+NTSTATUS dcesrv_output(struct dcesrv_connection *dce_conn, DATA_BLOB *data)
{
struct dcesrv_call_state *call;
struct dcesrv_call_reply *rep;
- call = dce->call_list;
+ call = dce_conn->call_list;
if (!call || !call->replies) {
return NT_STATUS_FOOBAR;
}
@@ -736,88 +890,151 @@ NTSTATUS dcesrv_output(struct dcesrv_state *dce, DATA_BLOB *data)
if (call->replies == NULL) {
/* we're done with the whole call */
- DLIST_REMOVE(dce->call_list, call);
+ DLIST_REMOVE(dce_conn->call_list, call);
talloc_destroy(call->mem_ctx);
}
return NT_STATUS_OK;
}
-
/*
- a useful function for implementing the query endpoint op
- */
-BOOL dcesrv_table_query(const struct dcerpc_interface_table *table,
- const struct dcesrv_endpoint *ep)
+ initialise the dcerpc server context
+*/
+NTSTATUS dcesrv_init_context(struct dcesrv_context *dce_ctx)
{
int i;
- const struct dcerpc_endpoint_list *endpoints = table->endpoints;
+ const char **endpoint_servers = lp_dcerpc_endpoint_servers();
- if (ep->type != ENDPOINT_SMB) {
- return False;
+ dce_ctx->mem_ctx = talloc_init("struct dcesrv_context");
+ if (!dce_ctx->mem_ctx) {
+ DEBUG(3,("dcesrv_init_context: talloc_init failed\n"));
+ return NT_STATUS_NO_MEMORY;
}
- for (i=0;i<endpoints->count;i++) {
- if (strcasecmp(ep->info.smb_pipe, endpoints->names[i]) == 0) {
- return True;
+ dce_ctx->endpoint_list = NULL;
+
+ if (!endpoint_servers) {
+ DEBUG(3,("dcesrv_init_context: no endpoint servers configured\n"));
+ return NT_STATUS_OK;
+ }
+
+ for (i=0;endpoint_servers[i];i++) {
+ NTSTATUS ret;
+ const struct dcesrv_endpoint_server *ep_server;
+
+ ep_server = dcesrv_ep_server_byname(endpoint_servers[i]);
+ if (!ep_server) {
+ DEBUG(0,("dcesrv_init_context: failed to find endpoint server = '%s'\n", endpoint_servers[i]));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ ret = ep_server->init_server(dce_ctx, ep_server);
+ if (!NT_STATUS_IS_OK(ret)) {
+ DEBUG(0,("dcesrv_init_context: failed to init endpoint server = '%s'\n", endpoint_servers[i]));
+ return ret;
}
}
- return False;
+
+ return NT_STATUS_OK;
}
+/* the list of currently registered DCERPC endpoint servers.
+ */
+static struct {
+ struct dcesrv_endpoint_server *ep_server;
+} *ep_servers = NULL;
+static int num_ep_servers;
/*
- a useful function for implementing the lookup_endpoints op
- */
-int dcesrv_lookup_endpoints(const struct dcerpc_interface_table *table,
- TALLOC_CTX *mem_ctx,
- struct dcesrv_ep_iface **e)
+ register a DCERPC endpoint server.
+
+ The 'name' can be later used by other backends to find the operations
+ structure for this backend.
+
+ The 'type' is used to specify whether this is for a disk, printer or IPC$ share
+*/
+static NTSTATUS decrpc_register_ep_server(void *_ep_server)
{
- int i;
- *e = talloc_array_p(mem_ctx, struct dcesrv_ep_iface, table->endpoints->count);
- if (! *e) {
- return -1;
- }
-
- for (i=0;i<table->endpoints->count;i++) {
- (*e)[i].name = table->name;
- (*e)[i].uuid = table->uuid;
- (*e)[i].if_version = table->if_version;
- if (strncmp(table->endpoints->names[i], "TCP-", 4) == 0) {
- (*e)[i].endpoint.type = ENDPOINT_TCP;
- (*e)[i].endpoint.info.tcp_port = atoi(table->endpoints->names[i]+4);
- } else {
- (*e)[i].endpoint.type = ENDPOINT_SMB;
- (*e)[i].endpoint.info.smb_pipe = table->endpoints->names[i];
- }
+ const struct dcesrv_endpoint_server *ep_server = _ep_server;
+
+ if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
+ /* its already registered! */
+ DEBUG(1,("DCERPC endpoint server '%s' already registered\n",
+ ep_server->name));
+ return NT_STATUS_OBJECT_NAME_COLLISION;
}
- return i;
-}
+ ep_servers = Realloc(ep_servers, sizeof(ep_servers[0]) * (num_ep_servers+1));
+ if (!ep_servers) {
+ smb_panic("out of memory in decrpc_register");
+ }
+
+ ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
+ ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
+
+ num_ep_servers++;
+
+ DEBUG(1,("DCERPC module '%s' registered\n",
+ ep_server->name));
+ return NT_STATUS_OK;
+}
-BOOL dcesrv_set_interface(struct dcesrv_state *dce,
- const char *uuid, uint32 if_version,
- const struct dcerpc_interface_table *table,
- const dcesrv_dispatch_fn_t *dispatch_table)
+/*
+ return the operations structure for a named backend of the specified type
+*/
+const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
{
- if (strcasecmp(table->uuid, uuid) != 0 || if_version != table->if_version) {
- DEBUG(2,("Attempt to use unknown interface %s/%d\n", uuid, if_version));
- return False;
+ int i;
+
+ for (i=0;i<num_ep_servers;i++) {
+ if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
+ return ep_servers[i].ep_server;
+ }
}
- dce->ndr = table;
- dce->dispatch = dispatch_table;
- return True;
+ return NULL;
}
+/*
+ return the DCERPC module version, and the size of some critical types
+ This can be used by endpoint server modules to either detect compilation errors, or provide
+ multiple implementations for different smbd compilation options in one module
+*/
+const struct dcesrv_critical_sizes *dcerpc_module_version(void)
+{
+ static const struct dcesrv_critical_sizes critical_sizes = {
+ DCERPC_MODULE_VERSION,
+ sizeof(struct dcesrv_context),
+ sizeof(struct dcesrv_endpoint),
+ sizeof(struct dcesrv_endpoint_server),
+ sizeof(struct dcesrv_ep_description),
+ sizeof(struct dcesrv_interface),
+ sizeof(struct dcesrv_if_list),
+ sizeof(struct dcesrv_connection),
+ sizeof(struct dcesrv_call_state),
+ sizeof(struct dcesrv_auth),
+ sizeof(struct dcesrv_handle)
+ };
+
+ return &critical_sizes;
+}
/*
- initialise the dcerpc server subsystem
+ initialise the DCERPC subsystem
*/
-BOOL dcesrv_init(struct dcesrv_context *dce)
+BOOL dcesrv_init(void)
{
- rpc_rpcecho_init(dce);
- rpc_epmapper_init(dce);
+ NTSTATUS status;
+
+ status = register_subsystem("dcerpc", decrpc_register_ep_server);
+ if (!NT_STATUS_IS_OK(status)) {
+ return False;
+ }
+
+ /* FIXME: Perhaps panic if a basic endpoint server, such as EPMAPER, fails to initialise? */
+ static_init_dcerpc;
+
+ DEBUG(1,("DCERPC subsystem version %d initialised\n", DCERPC_MODULE_VERSION));
return True;
}
diff --git a/source4/rpc_server/dcerpc_server.h b/source4/rpc_server/dcerpc_server.h
index 8481372d55..411bf400bf 100644
--- a/source4/rpc_server/dcerpc_server.h
+++ b/source4/rpc_server/dcerpc_server.h
@@ -4,6 +4,7 @@
server side dcerpc defines
Copyright (C) Andrew Tridgell 2003
+ Copyright (C) Stefan (metze) Metzmacher 2004
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
@@ -20,12 +21,18 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+/* modules can use the following to determine if the interface has changed
+ * please increment the version number after each interface change
+ * with a comment and maybe update struct dcesrv_critical_sizes.
+ */
+/* version 1 - initial version - metze */
+#define DCERPC_MODULE_VERSION 1
enum endpoint_type {ENDPOINT_SMB, ENDPOINT_TCP};
/* a description of a single dcerpc endpoint. Not as flexible as a full epm tower,
but much easier to work with */
-struct dcesrv_endpoint {
+struct dcesrv_ep_description {
enum endpoint_type type;
union {
const char *smb_pipe;
@@ -33,23 +40,31 @@ struct dcesrv_endpoint {
} info;
};
-/* a endpoint combined with an interface description */
-struct dcesrv_ep_iface {
- const char *name;
- struct dcesrv_endpoint endpoint;
- const char *uuid;
- uint32 if_version;
-};
-
-struct dcesrv_state;
+struct dcesrv_connection;
+struct dcesrv_call_state;
/* the dispatch functions for an interface take this form */
-typedef NTSTATUS (*dcesrv_dispatch_fn_t)(struct dcesrv_state *, TALLOC_CTX *, void *);
+typedef NTSTATUS (*dcesrv_dispatch_fn_t)(struct dcesrv_call_state *, TALLOC_CTX *, void *);
+
+struct dcesrv_interface {
+ /* the ndr function table for the chosen interface */
+ const struct dcerpc_interface_table *ndr;
+
+ /* this function is called when the client binds to this interface */
+ NTSTATUS (*bind)(struct dcesrv_call_state *, const struct dcesrv_interface *);
+
+ /* this function is called when the client disconnects the endpoint */
+ void (*unbind)(struct dcesrv_connection *, const struct dcesrv_interface *);
+
+ /* the dispatch function for the chosen interface.
+ */
+ dcesrv_dispatch_fn_t dispatch;
+};
/* the state of an ongoing dcerpc call */
struct dcesrv_call_state {
struct dcesrv_call_state *next, *prev;
- struct dcesrv_state *dce;
+ struct dcesrv_connection *conn;
TALLOC_CTX *mem_ctx;
struct dcerpc_packet pkt;
@@ -78,24 +93,17 @@ struct dcesrv_auth {
/* the state associated with a dcerpc server connection */
-struct dcesrv_state {
+struct dcesrv_connection {
/* the top level context for this server */
- struct dcesrv_context *dce;
+ struct dcesrv_context *dce_ctx;
TALLOC_CTX *mem_ctx;
/* the endpoint that was opened */
- struct dcesrv_endpoint endpoint;
-
- /* endpoint operations provided by the endpoint server */
- const struct dcesrv_endpoint_ops *ops;
+ const struct dcesrv_endpoint *endpoint;
/* the ndr function table for the chosen interface */
- const struct dcerpc_interface_table *ndr;
-
- /* the dispatch table for the chosen interface. Must contain
- enough entries for all entries in the ndr table */
- const dcesrv_dispatch_fn_t *dispatch;
+ const struct dcesrv_interface *iface;
/* the state of the current calls */
struct dcesrv_call_state *call_list;
@@ -103,7 +111,7 @@ struct dcesrv_state {
/* the maximum size the client wants to receive */
uint32 cli_max_recv_frag;
- /* private data for the endpoint server */
+ /* private data for the interface implementation */
void *private;
/* current rpc handles - this is really the wrong scope for
@@ -117,34 +125,61 @@ struct dcesrv_state {
};
-struct dcesrv_endpoint_ops {
- /* this function is used to ask an endpoint server if it
- handles a particular endpoint */
- BOOL (*query_endpoint)(const struct dcesrv_endpoint *);
-
- /* this function sets up the dispatch table for this
- connection */
- BOOL (*set_interface)(struct dcesrv_state *, const char *, uint32);
-
- /* connect() is called when a connection is made to an endpoint */
- NTSTATUS (*connect)(struct dcesrv_state *);
-
- /* disconnect() is called when the endpoint is disconnected */
- void (*disconnect)(struct dcesrv_state *);
+struct dcesrv_endpoint_server {
+ /* this is the name of the endpoint server */
+ const char *name;
- /* this function is used to ask an endpoint server for a list
- of endpoints/interfaces it wants to handle */
- int (*lookup_endpoints)(TALLOC_CTX *mem_ctx, struct dcesrv_ep_iface **);
+ /* this function should register endpoints and some other setup stuff,
+ * it is called when the dcesrv_context gets initialized.
+ */
+ NTSTATUS (*init_server)(struct dcesrv_context *, const struct dcesrv_endpoint_server *);
+
+ /* this function can be used by other endpoint servers to
+ * ask for a dcesrv_interface implementation
+ * - iface must be referenz to an allready existent struct !
+ */
+ BOOL (*interface_by_uuid)(struct dcesrv_interface *iface, const char *, uint32);
+
+ /* this function can be used by other endpoint servers to
+ * ask for a dcesrv_interface implementation
+ * - iface must be referenz to an allready existent struct !
+ */
+ BOOL (*interface_by_name)(struct dcesrv_interface *iface, const char *);
};
/* server-wide context information for the dcerpc server */
struct dcesrv_context {
-
- /* the list of endpoints servers that have registered */
- struct dce_endpoint {
- struct dce_endpoint *next, *prev;
- struct dcesrv_endpoint endpoint;
- const struct dcesrv_endpoint_ops *endpoint_ops;
+ TALLOC_CTX *mem_ctx;
+
+ /* the list of endpoints that have registered
+ * by the configured endpoint servers
+ */
+ struct dcesrv_endpoint {
+ struct dcesrv_endpoint *next, *prev;
+ /* the type and location of the endpoint */
+ struct dcesrv_ep_description ep_description;
+ /* the security descriptor for smb named pipes */
+ struct security_descriptor *sd;
+ /* the list of interfaces available on this endpoint */
+ struct dcesrv_if_list {
+ struct dcesrv_if_list *next, *prev;
+ struct dcesrv_interface iface;
+ } *interface_list;
} *endpoint_list;
};
+
+/* this structure is used by modules to determine the size of some critical types */
+struct dcesrv_critical_sizes {
+ int interface_version;
+ int sizeof_dcesrv_context;
+ int sizeof_dcesrv_endpoint;
+ int sizeof_dcesrv_endpoint_server;
+ int sizeof_dcesrv_ep_description;
+ int sizeof_dcesrv_interface;
+ int sizeof_dcesrv_if_list;
+ int sizeof_dcesrv_connection;
+ int sizeof_dcesrv_call_state;
+ int sizeof_dcesrv_auth;
+ int sizeof_dcesrv_handle;
+};
diff --git a/source4/rpc_server/dcerpc_tcp.c b/source4/rpc_server/dcerpc_tcp.c
index c9aeb400d0..34e6db63e3 100644
--- a/source4/rpc_server/dcerpc_tcp.c
+++ b/source4/rpc_server/dcerpc_tcp.c
@@ -4,7 +4,8 @@
server side dcerpc over tcp code
Copyright (C) Andrew Tridgell 2003
-
+ Copyright (C) Stefan (metze) Metzmacher 2004
+
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
@@ -23,10 +24,10 @@
#include "includes.h"
struct rpc_server_context {
- struct dcesrv_endpoint *endpoint;
- const struct dcesrv_endpoint_ops *endpoint_ops;
+ struct dcesrv_ep_description *ep_description;
+ const struct dcesrv_endpoint *endpoint;
const struct model_ops *model_ops;
- struct dcesrv_state *dce;
+ struct dcesrv_connection *dce_conn;
struct dcesrv_context dcesrv_context;
int socket_fd;
struct event_context *events;
@@ -39,7 +40,7 @@ void rpc_server_terminate(void *rr)
{
struct rpc_server_context *r = rr;
- dcesrv_endpoint_disconnect(r->dce);
+ dcesrv_endpoint_disconnect(r->dce_conn);
close(r->socket_fd);
event_remove_fd_all(r->events, r->socket_fd);
free(r);
@@ -69,13 +70,13 @@ static void dcerpc_write_handler(struct event_context *ev, struct fd_event *fde,
return;
}
- status = dcesrv_output(r->dce, &blob);
+ status = dcesrv_output(r->dce_conn, &blob);
if (NT_STATUS_IS_OK(status)) {
write_data(fde->fd, blob.data, blob.length);
}
- if (!r->dce->call_list || !r->dce->call_list->replies) {
+ if (!r->dce_conn->call_list || !r->dce_conn->call_list->replies) {
fde->flags &= ~EVENT_FD_WRITE;
}
@@ -111,11 +112,11 @@ static void dcerpc_read_handler(struct event_context *ev, struct fd_event *fde,
blob.length = ret;
- dcesrv_input(r->dce, &blob);
+ dcesrv_input(r->dce_conn, &blob);
data_blob_free(&blob);
- if (r->dce->call_list && r->dce->call_list->replies) {
+ if (r->dce_conn->call_list && r->dce_conn->call_list->replies) {
fde->flags |= EVENT_FD_WRITE;
}
}
@@ -146,6 +147,7 @@ void init_rpc_session(struct event_context *ev, void *private, int fd)
{
struct fd_event fde;
struct rpc_server_context *r = private;
+ NTSTATUS status;
r = memdup(r, sizeof(struct rpc_server_context));
@@ -155,9 +157,16 @@ void init_rpc_session(struct event_context *ev, void *private, int fd)
set_socket_options(fd,"SO_KEEPALIVE");
set_socket_options(fd, lp_socket_options());
- dcesrv_endpoint_connect_ops(&r->dcesrv_context, r->endpoint, r->endpoint_ops, &r->dce);
+ status = dcesrv_endpoint_connect(&r->dcesrv_context, r->endpoint, &r->dce_conn);
+ if (!NT_STATUS_IS_OK(status)) {
+ close(fd);
+ free(r);
+ DEBUG(0,("init_rpc_session: connection to endpoint failed: %s\n",
+ nt_errstr(status)));
+ return;
+ }
- r->dce->dce = &r->dcesrv_context;
+ r->dce_conn->dce_ctx = &r->dcesrv_context;
set_blocking(fd, False);
@@ -179,7 +188,7 @@ static void setup_listen_rpc(struct event_context *events,
struct model_ops *model_ops,
struct in_addr *ifip, uint32 *port,
struct rpc_server_context *r,
- const struct dcesrv_endpoint_ops *endpoint_ops)
+ const struct dcesrv_endpoint *endpoint)
{
struct fd_event fde;
int i;
@@ -209,14 +218,14 @@ static void setup_listen_rpc(struct event_context *events,
smb_panic("out of memory");
}
- r->endpoint_ops = endpoint_ops;
-
- r->endpoint = malloc(sizeof(struct dcesrv_endpoint));
- if (!r->endpoint) {
+ r->ep_description = malloc(sizeof(struct dcesrv_ep_description));
+ if (!r->ep_description) {
smb_panic("out of memory");
}
- r->endpoint->type = ENDPOINT_TCP;
- r->endpoint->info.tcp_port = *port;
+ r->ep_description->type = ENDPOINT_TCP;
+ r->ep_description->info.tcp_port = *port;
+
+ r->endpoint = endpoint;
/* ready to listen */
set_socket_options(fde.fd, "SO_KEEPALIVE");
@@ -244,7 +253,7 @@ static void add_socket_rpc(struct event_context *events,
struct model_ops *model_ops,
struct in_addr *ifip)
{
- struct dce_endpoint *e;
+ struct dcesrv_endpoint *e;
struct rpc_server_context *r;
r = malloc(sizeof(struct rpc_server_context));
@@ -253,18 +262,18 @@ static void add_socket_rpc(struct event_context *events,
}
r->dcesrv_context.endpoint_list = NULL;
- dcesrv_init(&r->dcesrv_context);
- r->endpoint = NULL;
+ dcesrv_init_context(&r->dcesrv_context);
+ r->ep_description = NULL;
r->model_ops = model_ops;
- r->dce = NULL;
+ r->dce_conn = NULL;
r->socket_fd = -1;
r->events = NULL;
for (e=r->dcesrv_context.endpoint_list;e;e=e->next) {
- if (e->endpoint.type == ENDPOINT_TCP) {
+ if (e->ep_description.type == ENDPOINT_TCP) {
setup_listen_rpc(events, model_ops, ifip,
- &e->endpoint.info.tcp_port,
- r, e->endpoint_ops);
+ &e->ep_description.info.tcp_port,
+ r, e);
}
}
diff --git a/source4/rpc_server/dcesrv_auth.c b/source4/rpc_server/dcesrv_auth.c
index 776d394e99..a117f08445 100644
--- a/source4/rpc_server/dcesrv_auth.c
+++ b/source4/rpc_server/dcesrv_auth.c
@@ -4,7 +4,7 @@
server side dcerpc authentication code
Copyright (C) Andrew Tridgell 2003
-
+
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
@@ -31,40 +31,40 @@
BOOL dcesrv_auth_bind(struct dcesrv_call_state *call)
{
struct dcerpc_packet *pkt = &call->pkt;
- struct dcesrv_state *dce = call->dce;
+ struct dcesrv_connection *dce_conn = call->conn;
NTSTATUS status;
if (pkt->u.bind.auth_info.length == 0) {
- dce->auth_state.auth_info = NULL;
+ dce_conn->auth_state.auth_info = NULL;
return True;
}
- dce->auth_state.auth_info = talloc_p(dce->mem_ctx, struct dcerpc_auth);
- if (!dce->auth_state.auth_info) {
+ dce_conn->auth_state.auth_info = talloc_p(dce_conn->mem_ctx, struct dcerpc_auth);
+ if (!dce_conn->auth_state.auth_info) {
return False;
}
status = ndr_pull_struct_blob(&pkt->u.bind.auth_info,
call->mem_ctx,
- dce->auth_state.auth_info,
+ dce_conn->auth_state.auth_info,
(ndr_pull_flags_fn_t)ndr_pull_dcerpc_auth);
if (!NT_STATUS_IS_OK(status)) {
return False;
}
- if (dce->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_NTLMSSP) {
+ if (dce_conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_NTLMSSP) {
/* only do NTLMSSP for now */
- DEBUG(2,("auth_type %d not supported\n", dce->auth_state.auth_info->auth_type));
+ DEBUG(2,("auth_type %d not supported\n", dce_conn->auth_state.auth_info->auth_type));
return False;
}
- if (dce->auth_state.auth_info->auth_level != DCERPC_AUTH_LEVEL_INTEGRITY &&
- dce->auth_state.auth_info->auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
- DEBUG(2,("auth_level %d not supported\n", dce->auth_state.auth_info->auth_level));
+ if (dce_conn->auth_state.auth_info->auth_level != DCERPC_AUTH_LEVEL_INTEGRITY &&
+ dce_conn->auth_state.auth_info->auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
+ DEBUG(2,("auth_level %d not supported\n", dce_conn->auth_state.auth_info->auth_level));
return False;
}
- status = auth_ntlmssp_start(&dce->auth_state.ntlmssp_state);
+ status = auth_ntlmssp_start(&dce_conn->auth_state.ntlmssp_state);
if (!NT_STATUS_IS_OK(status)) {
return False;
}
@@ -77,23 +77,23 @@ BOOL dcesrv_auth_bind(struct dcesrv_call_state *call)
*/
BOOL dcesrv_auth_bind_ack(struct dcesrv_call_state *call, struct dcerpc_packet *pkt)
{
- struct dcesrv_state *dce = call->dce;
+ struct dcesrv_connection *dce_conn = call->conn;
NTSTATUS status;
- if (!call->dce->auth_state.ntlmssp_state) {
+ if (!call->conn->auth_state.ntlmssp_state) {
return True;
}
- status = auth_ntlmssp_update(dce->auth_state.ntlmssp_state,
- dce->auth_state.auth_info->credentials,
- &dce->auth_state.auth_info->credentials);
+ status = auth_ntlmssp_update(dce_conn->auth_state.ntlmssp_state,
+ dce_conn->auth_state.auth_info->credentials,
+ &dce_conn->auth_state.auth_info->credentials);
if (!NT_STATUS_IS_OK(status) &&
!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
return False;
}
- dce->auth_state.auth_info->auth_pad_length = 0;
- dce->auth_state.auth_info->auth_reserved = 0;
+ dce_conn->auth_state.auth_info->auth_pad_length = 0;
+ dce_conn->auth_state.auth_info->auth_reserved = 0;
return True;
}
@@ -105,43 +105,43 @@ BOOL dcesrv_auth_bind_ack(struct dcesrv_call_state *call, struct dcerpc_packet *
BOOL dcesrv_auth_auth3(struct dcesrv_call_state *call)
{
struct dcerpc_packet *pkt = &call->pkt;
- struct dcesrv_state *dce = call->dce;
+ struct dcesrv_connection *dce_conn = call->conn;
NTSTATUS status;
- if (!dce->auth_state.auth_info ||
- !dce->auth_state.ntlmssp_state ||
+ if (!dce_conn->auth_state.auth_info ||
+ !dce_conn->auth_state.ntlmssp_state ||
pkt->u.auth.auth_info.length == 0) {
return False;
}
status = ndr_pull_struct_blob(&pkt->u.auth.auth_info,
call->mem_ctx,
- dce->auth_state.auth_info,
+ dce_conn->auth_state.auth_info,
(ndr_pull_flags_fn_t)ndr_pull_dcerpc_auth);
if (!NT_STATUS_IS_OK(status)) {
return False;
}
- if (dce->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_NTLMSSP) {
+ if (dce_conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_NTLMSSP) {
return False;
}
- if (dce->auth_state.auth_info->auth_level != DCERPC_AUTH_LEVEL_INTEGRITY &&
- dce->auth_state.auth_info->auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
+ if (dce_conn->auth_state.auth_info->auth_level != DCERPC_AUTH_LEVEL_INTEGRITY &&
+ dce_conn->auth_state.auth_info->auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
return False;
}
- status = auth_ntlmssp_update(dce->auth_state.ntlmssp_state,
- dce->auth_state.auth_info->credentials,
- &dce->auth_state.auth_info->credentials);
+ status = auth_ntlmssp_update(dce_conn->auth_state.ntlmssp_state,
+ dce_conn->auth_state.auth_info->credentials,
+ &dce_conn->auth_state.auth_info->credentials);
if (!NT_STATUS_IS_OK(status)) {
return False;
}
- switch (dce->auth_state.auth_info->auth_level) {
+ switch (dce_conn->auth_state.auth_info->auth_level) {
case DCERPC_AUTH_LEVEL_PRIVACY:
case DCERPC_AUTH_LEVEL_INTEGRITY:
/* setup for signing */
- status = ntlmssp_sign_init(dce->auth_state.ntlmssp_state->ntlmssp_state);
+ status = ntlmssp_sign_init(dce_conn->auth_state.ntlmssp_state->ntlmssp_state);
break;
}
@@ -155,14 +155,14 @@ BOOL dcesrv_auth_auth3(struct dcesrv_call_state *call)
BOOL dcesrv_auth_request(struct dcesrv_call_state *call)
{
struct dcerpc_packet *pkt = &call->pkt;
- struct dcesrv_state *dce = call->dce;
+ struct dcesrv_connection *dce_conn = call->conn;
DATA_BLOB auth_blob;
struct dcerpc_auth auth;
struct ndr_pull *ndr;
NTSTATUS status;
- if (!dce->auth_state.auth_info ||
- !dce->auth_state.ntlmssp_state) {
+ if (!dce_conn->auth_state.auth_info ||
+ !dce_conn->auth_state.ntlmssp_state) {
return True;
}
@@ -194,16 +194,16 @@ BOOL dcesrv_auth_request(struct dcesrv_call_state *call)
}
/* check signature or unseal the packet */
- switch (dce->auth_state.auth_info->auth_level) {
+ switch (dce_conn->auth_state.auth_info->auth_level) {
case DCERPC_AUTH_LEVEL_PRIVACY:
- status = ntlmssp_unseal_packet(dce->auth_state.ntlmssp_state->ntlmssp_state,
+ status = ntlmssp_unseal_packet(dce_conn->auth_state.ntlmssp_state->ntlmssp_state,
pkt->u.request.stub_and_verifier.data,
pkt->u.request.stub_and_verifier.length,
&auth.credentials);
break;
case DCERPC_AUTH_LEVEL_INTEGRITY:
- status = ntlmssp_check_packet(dce->auth_state.ntlmssp_state->ntlmssp_state,
+ status = ntlmssp_check_packet(dce_conn->auth_state.ntlmssp_state->ntlmssp_state,
pkt->u.request.stub_and_verifier.data,
pkt->u.request.stub_and_verifier.length,
&auth.credentials);
@@ -230,12 +230,12 @@ BOOL dcesrv_auth_request(struct dcesrv_call_state *call)
BOOL dcesrv_auth_response(struct dcesrv_call_state *call,
DATA_BLOB *blob, struct dcerpc_packet *pkt)
{
- struct dcesrv_state *dce = call->dce;
+ struct dcesrv_connection *dce_conn = call->conn;
NTSTATUS status;
struct ndr_push *ndr;
/* non-signed packets are simple */
- if (!dce->auth_state.auth_info || !dce->auth_state.ntlmssp_state) {
+ if (!dce_conn->auth_state.auth_info || !dce_conn->auth_state.ntlmssp_state) {
status = dcerpc_push_auth(blob, call->mem_ctx, pkt, NULL);
return NT_STATUS_IS_OK(status);
}
@@ -255,23 +255,23 @@ BOOL dcesrv_auth_response(struct dcesrv_call_state *call,
}
/* pad to 8 byte multiple */
- dce->auth_state.auth_info->auth_pad_length = NDR_ALIGN(ndr, 8);
- ndr_push_zero(ndr, dce->auth_state.auth_info->auth_pad_length);
+ dce_conn->auth_state.auth_info->auth_pad_length = NDR_ALIGN(ndr, 8);
+ ndr_push_zero(ndr, dce_conn->auth_state.auth_info->auth_pad_length);
/* sign or seal the packet */
- switch (dce->auth_state.auth_info->auth_level) {
+ switch (dce_conn->auth_state.auth_info->auth_level) {
case DCERPC_AUTH_LEVEL_PRIVACY:
- status = ntlmssp_seal_packet(dce->auth_state.ntlmssp_state->ntlmssp_state,
+ status = ntlmssp_seal_packet(dce_conn->auth_state.ntlmssp_state->ntlmssp_state,
ndr->data + DCERPC_REQUEST_LENGTH,
ndr->offset - DCERPC_REQUEST_LENGTH,
- &dce->auth_state.auth_info->credentials);
+ &dce_conn->auth_state.auth_info->credentials);
break;
case DCERPC_AUTH_LEVEL_INTEGRITY:
- status = ntlmssp_sign_packet(dce->auth_state.ntlmssp_state->ntlmssp_state,
+ status = ntlmssp_sign_packet(dce_conn->auth_state.ntlmssp_state->ntlmssp_state,
ndr->data + DCERPC_REQUEST_LENGTH,
ndr->offset - DCERPC_REQUEST_LENGTH,
- &dce->auth_state.auth_info->credentials);
+ &dce_conn->auth_state.auth_info->credentials);
break;
default:
status = NT_STATUS_INVALID_LEVEL;
@@ -283,7 +283,7 @@ BOOL dcesrv_auth_response(struct dcesrv_call_state *call,
}
/* add the auth verifier */
- status = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, dce->auth_state.auth_info);
+ status = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, dce_conn->auth_state.auth_info);
if (!NT_STATUS_IS_OK(status)) {
return False;
}
@@ -295,9 +295,9 @@ BOOL dcesrv_auth_response(struct dcesrv_call_state *call,
in these earlier as we don't know the signature length (it
could be variable length) */
dcerpc_set_frag_length(blob, blob->length);
- dcerpc_set_auth_length(blob, dce->auth_state.auth_info->credentials.length);
+ dcerpc_set_auth_length(blob, dce_conn->auth_state.auth_info->credentials.length);
- data_blob_free(&dce->auth_state.auth_info->credentials);
+ data_blob_free(&dce_conn->auth_state.auth_info->credentials);
return True;
}
diff --git a/source4/rpc_server/echo/rpc_echo.c b/source4/rpc_server/echo/rpc_echo.c
index 9d2c72e1b6..ec5d667b46 100644
--- a/source4/rpc_server/echo/rpc_echo.c
+++ b/source4/rpc_server/echo/rpc_echo.c
@@ -23,13 +23,13 @@
#include "includes.h"
-static NTSTATUS echo_AddOne(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx, struct echo_AddOne *r)
+static NTSTATUS echo_AddOne(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct echo_AddOne *r)
{
*r->out.v = *r->in.v + 1;
return NT_STATUS_OK;
}
-static NTSTATUS echo_EchoData(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx, struct echo_EchoData *r)
+static NTSTATUS echo_EchoData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct echo_EchoData *r)
{
if (!r->in.len) {
return NT_STATUS_OK;
@@ -44,12 +44,12 @@ static NTSTATUS echo_EchoData(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx, str
return NT_STATUS_OK;
}
-static NTSTATUS echo_SinkData(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx, struct echo_SinkData *r)
+static NTSTATUS echo_SinkData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct echo_SinkData *r)
{
return NT_STATUS_OK;
}
-static NTSTATUS echo_SourceData(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx, struct echo_SourceData *r)
+static NTSTATUS echo_SourceData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct echo_SourceData *r)
{
int i;
for (i=0;i<r->in.len;i++) {
@@ -59,14 +59,14 @@ static NTSTATUS echo_SourceData(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx, s
return NT_STATUS_OK;
}
-static NTSTATUS echo_TestCall(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx, struct echo_TestCall *r)
+static NTSTATUS echo_TestCall(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct echo_TestCall *r)
{
r->out.s2 = "this is a test string";
return NT_STATUS_OK;
}
-static NTSTATUS echo_TestCall2(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx, struct echo_TestCall2 *r)
+static NTSTATUS echo_TestCall2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct echo_TestCall2 *r)
{
r->out.info = talloc(mem_ctx, sizeof(*r->out.info));
if (!r->out.info) {
diff --git a/source4/rpc_server/epmapper/rpc_epmapper.c b/source4/rpc_server/epmapper/rpc_epmapper.c
index 5e571ee1ef..f3285729a6 100644
--- a/source4/rpc_server/epmapper/rpc_epmapper.c
+++ b/source4/rpc_server/epmapper/rpc_epmapper.c
@@ -26,6 +26,13 @@
/* handle types for this module */
enum handle_types {HTYPE_LOOKUP};
+/* a endpoint combined with an interface description */
+struct dcesrv_ep_iface {
+ const char *name;
+ struct dcesrv_ep_description ep_description;
+ const char *uuid;
+ uint32 if_version;
+};
/*
simple routine to compare a GUID string to a GUID structure
@@ -67,13 +74,13 @@ static BOOL fill_protocol_tower(TALLOC_CTX *mem_ctx, struct epm_towers *twr,
twr->floors[2].lhs.info.lhs_data = data_blob(NULL, 0);
twr->floors[2].rhs.rhs_data = data_blob_talloc_zero(mem_ctx, 2);
- switch (e->endpoint.type) {
+ switch (e->ep_description.type) {
case ENDPOINT_SMB:
/* on a SMB pipe ... */
twr->floors[3].lhs.protocol = EPM_PROTOCOL_SMB;
twr->floors[3].lhs.info.lhs_data = data_blob(NULL, 0);
twr->floors[3].rhs.rhs_data.data = talloc_asprintf(mem_ctx, "\\PIPE\\%s",
- e->endpoint.info.smb_pipe);
+ e->ep_description.info.smb_pipe);
twr->floors[3].rhs.rhs_data.length = strlen(twr->floors[3].rhs.rhs_data.data)+1;
/* on an NetBIOS link ... */
@@ -89,7 +96,7 @@ static BOOL fill_protocol_tower(TALLOC_CTX *mem_ctx, struct epm_towers *twr,
twr->floors[3].lhs.protocol = EPM_PROTOCOL_TCP;
twr->floors[3].lhs.info.lhs_data = data_blob(NULL, 0);
twr->floors[3].rhs.rhs_data = data_blob_talloc(mem_ctx, NULL, 2);
- RSSVAL(twr->floors[3].rhs.rhs_data.data, 0, e->endpoint.info.tcp_port);
+ RSSVAL(twr->floors[3].rhs.rhs_data.data, 0, e->ep_description.info.tcp_port);
/* on an IP link ... */
twr->floors[4].lhs.protocol = EPM_PROTOCOL_IP;
@@ -106,44 +113,26 @@ static BOOL fill_protocol_tower(TALLOC_CTX *mem_ctx, struct epm_towers *twr,
build a list of all interfaces handled by all endpoint servers
*/
static uint32 build_ep_list(TALLOC_CTX *mem_ctx,
- struct dce_endpoint *endpoint_list,
+ struct dcesrv_endpoint *endpoint_list,
struct dcesrv_ep_iface **eps)
{
- struct dce_endpoint *d;
uint32 total = 0;
(*eps) = NULL;
- for (d=endpoint_list; d; d=d->next) {
- struct dcesrv_ep_iface *e;
- int count = d->endpoint_ops->lookup_endpoints(mem_ctx, &e);
- if (count > 0) {
- int i;
- for (i=0;i<count;i++) {
- e[i].endpoint = d->endpoint;
- }
- (*eps) = talloc_realloc_p(mem_ctx, *eps,
- struct dcesrv_ep_iface,
- total + count);
- if (!*eps) {
- return 0;
- }
- memcpy((*eps) + total, e, sizeof(*e) * count);
- total += count;
- }
- }
+ /* TODO */
return total;
}
-static NTSTATUS epm_Insert(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx,
+static NTSTATUS epm_Insert(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct epm_Insert *r)
{
return NT_STATUS_NOT_IMPLEMENTED;
}
-static NTSTATUS epm_Delete(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx,
+static NTSTATUS epm_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct epm_Delete *r)
{
return NT_STATUS_NOT_IMPLEMENTED;
@@ -154,7 +143,7 @@ static NTSTATUS epm_Delete(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx,
implement epm_Lookup. This call is used to enumerate the interfaces
available on a rpc server
*/
-static NTSTATUS epm_Lookup(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx,
+static NTSTATUS epm_Lookup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct epm_Lookup *r)
{
struct dcesrv_handle *h;
@@ -165,7 +154,7 @@ static NTSTATUS epm_Lookup(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx,
uint32 num_ents;
int i;
- h = dcesrv_handle_fetch(dce, r->in.entry_handle, HTYPE_LOOKUP);
+ h = dcesrv_handle_fetch(dce_call->conn, r->in.entry_handle, HTYPE_LOOKUP);
if (!h) {
return NT_STATUS_INVALID_HANDLE;
}
@@ -181,7 +170,7 @@ static NTSTATUS epm_Lookup(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx,
}
h->data = eps;
- eps->count = build_ep_list(h->mem_ctx, dce->dce->endpoint_list, &eps->e);
+ eps->count = build_ep_list(h->mem_ctx, dce_call->conn->dce_ctx->endpoint_list, &eps->e);
}
/* return the next N elements */
@@ -198,7 +187,7 @@ static NTSTATUS epm_Lookup(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx,
r->out.entries = NULL;
r->out.status = EPMAPPER_STATUS_NO_MORE_ENTRIES;
ZERO_STRUCTP(r->out.entry_handle);
- dcesrv_handle_destroy(dce, h);
+ dcesrv_handle_destroy(dce_call->conn, h);
return NT_STATUS_OK;
}
@@ -231,7 +220,7 @@ static NTSTATUS epm_Lookup(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx,
implement epm_Map. This is used to find the specific endpoint to talk to given
a generic protocol tower
*/
-static NTSTATUS epm_Map(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx,
+static NTSTATUS epm_Map(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct epm_Map *r)
{
uint32 count;
@@ -239,7 +228,7 @@ static NTSTATUS epm_Map(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx,
struct dcesrv_ep_iface *eps;
struct epm_floor *floors;
- count = build_ep_list(mem_ctx, dce->dce->endpoint_list, &eps);
+ count = build_ep_list(mem_ctx, dce_call->conn->dce_ctx->endpoint_list, &eps);
ZERO_STRUCTP(r->out.entry_handle);
r->out.num_towers = 1;
@@ -273,7 +262,7 @@ static NTSTATUS epm_Map(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx,
floors[0].lhs.info.uuid.version != eps[i].if_version) {
continue;
}
- switch (eps[i].endpoint.type) {
+ switch (eps[i].ep_description.type) {
case ENDPOINT_SMB:
if (floors[3].lhs.protocol != EPM_PROTOCOL_SMB ||
floors[4].lhs.protocol != EPM_PROTOCOL_NETBIOS) {
@@ -300,19 +289,19 @@ failed:
return NT_STATUS_OK;
}
-static NTSTATUS epm_LookupHandleFree(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx,
+static NTSTATUS epm_LookupHandleFree(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct epm_LookupHandleFree *r)
{
return NT_STATUS_NOT_IMPLEMENTED;
}
-static NTSTATUS epm_InqObject(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx,
+static NTSTATUS epm_InqObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct epm_InqObject *r)
{
return NT_STATUS_NOT_IMPLEMENTED;
}
-static NTSTATUS epm_MgmtDelete(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx,
+static NTSTATUS epm_MgmtDelete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct epm_MgmtDelete *r)
{
return NT_STATUS_NOT_IMPLEMENTED;
diff --git a/source4/rpc_server/handles.c b/source4/rpc_server/handles.c
index 26d7552afb..043318c075 100644
--- a/source4/rpc_server/handles.c
+++ b/source4/rpc_server/handles.c
@@ -25,7 +25,7 @@
/*
allocate a new rpc handle
*/
-struct dcesrv_handle *dcesrv_handle_new(struct dcesrv_state *dce,
+struct dcesrv_handle *dcesrv_handle_new(struct dcesrv_connection *dce_conn,
uint8 handle_type)
{
TALLOC_CTX *mem_ctx;
@@ -46,7 +46,7 @@ struct dcesrv_handle *dcesrv_handle_new(struct dcesrv_state *dce,
h->wire_handle.handle_type = handle_type;
uuid_generate_random(&h->wire_handle.uuid);
- DLIST_ADD(dce->handles, h);
+ DLIST_ADD(dce_conn->handles, h);
return h;
}
@@ -54,10 +54,10 @@ struct dcesrv_handle *dcesrv_handle_new(struct dcesrv_state *dce,
/*
destroy a rpc handle
*/
-void dcesrv_handle_destroy(struct dcesrv_state *dce,
+void dcesrv_handle_destroy(struct dcesrv_connection *dce_conn,
struct dcesrv_handle *h)
{
- DLIST_REMOVE(dce->handles, h);
+ DLIST_REMOVE(dce_conn->handles, h);
talloc_destroy(h->mem_ctx);
}
@@ -66,17 +66,17 @@ void dcesrv_handle_destroy(struct dcesrv_state *dce,
find an internal handle given a wire handle. If the wire handle is NULL then
allocate a new handle
*/
-struct dcesrv_handle *dcesrv_handle_fetch(struct dcesrv_state *dce,
+struct dcesrv_handle *dcesrv_handle_fetch(struct dcesrv_connection *dce_conn,
struct policy_handle *p,
uint8 handle_type)
{
struct dcesrv_handle *h;
if (policy_handle_empty(p)) {
- return dcesrv_handle_new(dce, handle_type);
+ return dcesrv_handle_new(dce_conn, handle_type);
}
- for (h=dce->handles; h; h=h->next) {
+ for (h=dce_conn->handles; h; h=h->next) {
if (h->wire_handle.handle_type == p->handle_type &&
uuid_equal(&p->uuid, &h->wire_handle.uuid)) {
if (p->handle_type != handle_type) {
diff --git a/source4/rpc_server/remote/dcesrv_remote.c b/source4/rpc_server/remote/dcesrv_remote.c
new file mode 100644
index 0000000000..381c79135c
--- /dev/null
+++ b/source4/rpc_server/remote/dcesrv_remote.c
@@ -0,0 +1,198 @@
+/*
+ Unix SMB/CIFS implementation.
+ remote dcerpc operations
+
+ Copyright (C) Stefan (metze) Metzmacher 2004
+
+ 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"
+
+struct dcesrv_remote_private {
+ struct dcerpc_pipe *c_pipe;
+ void *private;
+};
+
+static NTSTATUS remote_op_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface)
+{
+ NTSTATUS status;
+ struct dcesrv_remote_private *private;
+ const char *binding = lp_parm_string(-1, "dcerpc_remote", "binding");
+ const char *print_debug = lp_parm_string(-1, "dcerpc_remote", "print_debug");
+
+ if (!binding) {
+ printf("You must specify a ncacn binding string\n");
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ private = talloc_p(dce_call->conn->mem_ctx, struct dcesrv_remote_private);
+ if (!private) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ status = dcerpc_pipe_connect(&(private->c_pipe), binding, iface->ndr->uuid, iface->ndr->if_version,
+ lp_workgroup(),
+ lp_parm_string(-1, "dcerpc_remote", "username"),
+ lp_parm_string(-1, "dcerpc_remote", "password"));
+
+ if (print_debug && strcasecmp("yes",print_debug) == 0) {
+ private->c_pipe->flags |= DCERPC_DEBUG_PRINT_BOTH;
+ }
+
+ dce_call->conn->private = private;
+
+ return NT_STATUS_OK;
+}
+
+static void remote_op_unbind(struct dcesrv_connection *dce_conn, const struct dcesrv_interface *iface)
+{
+ struct dcesrv_remote_private *private = dce_conn->private;
+
+ dcerpc_pipe_close(private->c_pipe);
+
+ return;
+}
+
+static NTSTATUS remote_op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
+{
+ struct dcesrv_remote_private *private = dce_call->conn->private;
+ NTSTATUS status;
+ uint16 opnum = dce_call->pkt.u.request.opnum;
+ ndr_push_flags_fn_t ndr_push_fn = dce_call->conn->iface->ndr->calls[opnum].ndr_push;
+ ndr_pull_flags_fn_t ndr_pull_fn = dce_call->conn->iface->ndr->calls[opnum].ndr_pull;
+ size_t struct_size = dce_call->conn->iface->ndr->calls[opnum].struct_size;
+
+ status = dcerpc_ndr_request(private->c_pipe, opnum, mem_ctx,
+ (ndr_push_flags_fn_t) ndr_push_fn,
+ (ndr_pull_flags_fn_t) ndr_pull_fn,
+ r, struct_size);
+
+ return status;
+}
+
+static NTSTATUS remote_register_one_iface(struct dcesrv_context *dce_ctx, const struct dcesrv_interface *iface)
+{
+ int i;
+
+ for (i=0;i<iface->ndr->endpoints->count;i++) {
+ NTSTATUS ret;
+ const char *name = iface->ndr->endpoints->names[i];
+
+ ret = dcesrv_interface_register(dce_ctx, name, iface, NULL);
+ if (!NT_STATUS_IS_OK(ret)) {
+ DEBUG(1,("remote_op_init_server: failed to register endpoint '%s'\n",name));
+ return ret;
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS remote_op_init_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server)
+{
+ int i;
+ char **ifaces = str_list_make(lp_parm_string(-1,"dcerpc_remote","interfaces"),NULL);
+
+ if (!ifaces) {
+ DEBUG(3,("remote_op_init_server: no interfaces configured\n"));
+ return NT_STATUS_OK;
+ }
+
+ for (i=0;ifaces[i];i++) {
+ NTSTATUS ret;
+ struct dcesrv_interface iface;
+
+ if (!ep_server->interface_by_name(&iface, ifaces[i])) {
+ DEBUG(0,("remote_op_init_server: failed to find interface = '%s'\n", ifaces[i]));
+ str_list_free(&ifaces);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ ret = remote_register_one_iface(dce_ctx, &iface);
+ if (!NT_STATUS_IS_OK(ret)) {
+ DEBUG(0,("remote_op_init_server: failed to register interface = '%s'\n", ifaces[i]));
+ str_list_free(&ifaces);
+ return ret;
+ }
+ }
+
+ str_list_free(&ifaces);
+ return NT_STATUS_OK;
+}
+
+static BOOL remote_fill_interface(struct dcesrv_interface *iface, const struct dcerpc_interface_table *if_tabl)
+{
+ iface->ndr = if_tabl;
+
+ iface->bind = remote_op_bind;
+ iface->unbind = remote_op_unbind;
+ iface->dispatch = remote_op_dispatch;
+
+ return True;
+}
+
+static BOOL remote_op_interface_by_uuid(struct dcesrv_interface *iface, const char *uuid, uint32 if_version)
+{
+ int i;
+
+ for (i=0;dcerpc_pipes[i];i++) {
+ if (dcerpc_pipes[i]->if_version == if_version &&
+ strcmp(dcerpc_pipes[i]->uuid, uuid)==0) {
+ return remote_fill_interface(iface, dcerpc_pipes[i]);
+ }
+ }
+
+ return False;
+}
+
+static BOOL remote_op_interface_by_name(struct dcesrv_interface *iface, const char *name)
+{
+ int i;
+
+ for (i=0;dcerpc_pipes[i];i++) {
+ if (strcmp(dcerpc_pipes[i]->name, name)==0) {
+ return remote_fill_interface(iface, dcerpc_pipes[i]);
+ }
+ }
+
+ return False;
+}
+
+NTSTATUS dcerpc_remote_init(void)
+{
+ NTSTATUS ret;
+ struct dcesrv_endpoint_server ep_server;
+
+ ZERO_STRUCT(ep_server);
+
+ /* fill in our name */
+ ep_server.name = "remote";
+
+ /* fill in all the operations */
+ ep_server.init_server = remote_op_init_server;
+
+ ep_server.interface_by_uuid = remote_op_interface_by_uuid;
+ ep_server.interface_by_name = remote_op_interface_by_name;
+
+ /* register ourselves with the NTVFS subsystem. */
+ ret = register_backend("dcerpc", &ep_server);
+ if (!NT_STATUS_IS_OK(ret)) {
+ DEBUG(0,("Failed to register 'remote' endpoint server!\n"));
+ return ret;
+ }
+
+ return ret;
+}
diff --git a/source4/smbd/process.c b/source4/smbd/process.c
index b5138ac971..411ffef717 100644
--- a/source4/smbd/process.c
+++ b/source4/smbd/process.c
@@ -765,7 +765,7 @@ void init_smbsession(struct event_context *ev, struct model_ops *model_ops, int
event_add_fd(ev, &fde);
/* setup the DCERPC server subsystem */
- dcesrv_init(&smb->dcesrv);
+ dcesrv_init_context(&smb->dcesrv);
}
@@ -825,6 +825,10 @@ void smbd_process_init(void)
if (!ntvfs_init())
exit(1);
+ /* Setup the DCERPC subsystem */
+ if (!dcesrv_init())
+ exit(1);
+
/* re-initialise the timezone */
TimeInit();
diff --git a/source4/smbd/process_thread.c b/source4/smbd/process_thread.c
index 523c38f521..9acd49916b 100644
--- a/source4/smbd/process_thread.c
+++ b/source4/smbd/process_thread.c
@@ -110,7 +110,7 @@ static void accept_rpc_connection(struct event_context *ev, struct fd_event *fde
ev = event_context_init();
MUTEX_LOCK_BY_ID(MUTEX_SMBD);
- init_rpcsession(ev, fde->private, accepted_fd);
+ init_rpc_session(ev, fde->private, accepted_fd);
MUTEX_UNLOCK_BY_ID(MUTEX_SMBD);
pthread_attr_init(&thread_attr);
diff --git a/source4/smbd/reply.c b/source4/smbd/reply.c
index ce203cbf93..7d6450b395 100644
--- a/source4/smbd/reply.c
+++ b/source4/smbd/reply.c
@@ -249,7 +249,7 @@ void reply_ioctl(struct request_context *req)
{
union smb_ioctl *io;
- /* parse requst */
+ /* parse request */
REQ_CHECK_WCT(req, 3);
REQ_TALLOC(io, sizeof(*io));
diff --git a/source4/smbd/request.c b/source4/smbd/request.c
index 65bf71051f..065e63a8d2 100644
--- a/source4/smbd/request.c
+++ b/source4/smbd/request.c
@@ -62,6 +62,10 @@ struct request_context *init_smb_request(struct server_context *smb)
smb->socket.pkt_count++;
req = talloc(mem_ctx, sizeof(*req));
+ if (!req) {
+ return NULL;
+ }
+
ZERO_STRUCTP(req);
/* setup the request context */