This patch adds a better dcerpc server infastructure.
authorStefan Metzmacher <metze@samba.org>
Thu, 8 Jan 2004 22:55:27 +0000 (22:55 +0000)
committerStefan Metzmacher <metze@samba.org>
Thu, 8 Jan 2004 22:55:27 +0000 (22:55 +0000)
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 :-)

24 files changed:
source/Makefile.in
source/build/pidl/header.pm
source/build/pidl/server.pm
source/build/pidl/tables.pl
source/build/pidl/template.pm
source/configure.in
source/lib/module.c
source/librpc/ndr/ndr_sec.c
source/ntvfs/ipc/vfs_ipc.c
source/ntvfs/ntvfs_base.c
source/param/loadparm.c
source/rpc_server/config.m4 [new file with mode: 0644]
source/rpc_server/dcerpc_server.c
source/rpc_server/dcerpc_server.h
source/rpc_server/dcerpc_tcp.c
source/rpc_server/dcesrv_auth.c
source/rpc_server/echo/rpc_echo.c
source/rpc_server/epmapper/rpc_epmapper.c
source/rpc_server/handles.c
source/rpc_server/remote/dcesrv_remote.c [new file with mode: 0644]
source/smbd/process.c
source/smbd/process_thread.c
source/smbd/reply.c
source/smbd/request.c

index 784ed22f101fb91a2168e8be1cea9729c6f0d7ad..00adf52e07974b7d90863fe0402c40ddcd6c2fde 100644 (file)
@@ -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 \
index 418ae97aed8cae8858cf570dcc8936b39f42eeee..c1b6eb44a14d36fe3f5b89bfe25c9d773254f915 100644 (file)
@@ -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}) {
index f5256d18a678786569c9b13aacd7991713e38514..0938515f485d0cf81500a89aa349d514ce80d55f 100644 (file)
@@ -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;
 }
 
index fa53af1c0994175b98a6a3e2077d94cddbdf3430..bf1db20e28a0948220c8efbae5cd6012d193baad 100755 (executable)
@@ -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";
 
index f9f9897ce2146b659980c2d3e7ec0ef5d76b32d4..6e0decbf405bb6a13c1bd3da80a8412cc9d458c1 100644 (file)
@@ -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;
-
index 82773bc179854d45b965e0a2ad8059d559015bd8..e615a31ceefb75fc0a1aeba5ba8b0786c5138d8f 100644 (file)
@@ -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])
 
index ffd6a38c77098dd071835203a88e3a89aa01aae1..15f92db59e06d2be6945e6925ae19ff3b4ff9523 100644 (file)
@@ -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)
index a3be697c49ec9ae71b8a09ac511562c223fa8000..49c88d15637cbd4cd5483b6f115fabde23702b4e 100644 (file)
@@ -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
@@ -114,15 +145,6 @@ size_t ndr_size_security_acl(struct security_acl *acl)
        return ret;
 }
 
-/*
-  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
 */
@@ -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;
 }
index 96f28895c9bde84c685876040a983e31f827e560..cd300b6589ebd40dd97dad026e76d653db535f24 100644 (file)
@@ -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;
        }
index ad1b3ae671b479d32a86590123cd032c098aa3e1..e4009fd1f0144ca6ffc33450aa402bb7ce73aa80 100644 (file)
@@ -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;
 }
 
index aff4a4f12a19ea1632eb00ee61df45bc1b8fda95..9052fe440975e01373fcc7c6cbc633b61b1ea8d1 100644 (file)
@@ -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/source/rpc_server/config.m4 b/source/rpc_server/config.m4
new file mode 100644 (file)
index 0000000..cdc4f65
--- /dev/null
@@ -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)
index d3e2f1917f8f6c04eb4213120acb3a6a1d7adb57..46341e6db1affebeb3baed4a2d2c014d1837f8a7 100644 (file)
@@ -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
 #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;
 }
index 8481372d55066f8b66c9d4438337c52f576b9a31..411bf400bf311935477f8191cf8147dec1e288b6 100644 (file)
@@ -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
    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;
+};
index c9aeb400d012b7f4355011dbbe2b2567d1984903..34e6db63e35691f2444d9aecff3208c586493661 100644 (file)
@@ -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
 #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);
                }
        }
 
index 776d394e99a8f71deda14345adea3149743414c6..a117f0844567e273585cffdf143d2ca06b1a1389 100644 (file)
@@ -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
 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;
 }
index 9d2c72e1b6dead875d63b808a095b1e4fad1a96c..ec5d667b46a98683583f4212060f44f6261d4bb0 100644 (file)
 #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) {
index 5e571ee1ef7ca9f81e216d6de296b38f53c99072..f3285729a69a6488233c7e9371310c49ab63af7c 100644 (file)
 /* 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;
index 26d7552afb0e1414848dcad16a4d4c973d303ef6..043318c075c81d760b758afd2f3ff9d04f97033d 100644 (file)
@@ -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/source/rpc_server/remote/dcesrv_remote.c b/source/rpc_server/remote/dcesrv_remote.c
new file mode 100644 (file)
index 0000000..381c791
--- /dev/null
@@ -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;
+}
index b5138ac9710367494705ef95e2b991ff2cbad3e0..411ffef717c060b482df07ee4ee06d33b8a4f95a 100644 (file)
@@ -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();
        
index 523c38f521b37da4231decbb6c5dd76ff50c8adc..9acd49916b9bd4b27e0eae74095acfa46ed2bfe5 100644 (file)
@@ -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);
index ce203cbf9303a07a1362a716a76001b99d674989..7d6450b395ea78bb6bec789c4b3c6a6de2821d42 100644 (file)
@@ -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));
 
index 65bf71051f4a88b885b3e8471bd7dd418f8646e7..065e63a8d2c3bb1fe3d4e9bb144cd92bc05e2894 100644 (file)
@@ -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 */