r25398: Parse loadparm context to all lp_*() functions.
[ab/samba.git/.git] / source4 / rpc_server / dcerpc_server.c
index f161075fa62655c373f2322b80e945b9c8432d03..02f38a15fd304600ca2d5647ff3ceb8f62491aa1 100644 (file)
@@ -8,7 +8,7 @@
    
    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
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    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.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
 #include "librpc/gen_ndr/ndr_dcerpc.h"
 #include "auth/auth.h"
-#include "dlinklist.h"
+#include "auth/gensec/gensec.h"
+#include "lib/util/dlinklist.h"
 #include "rpc_server/dcerpc_server.h"
 #include "lib/events/events.h"
 #include "smbd/service_task.h"
 #include "smbd/service_stream.h"
 #include "smbd/service.h"
 #include "system/filesys.h"
-#include "libcli/security/proto.h"
+#include "libcli/security/security.h"
 #include "build.h"
+#include "param/param.h"
+
+extern const struct dcesrv_interface dcesrv_mgmt_interface;
 
 /*
   see if two endpoints match
 */
-static BOOL endpoints_match(const struct dcerpc_binding *ep1,
+static bool endpoints_match(const struct dcerpc_binding *ep1,
                            const struct dcerpc_binding *ep2)
 {
        if (ep1->transport != ep2->transport) {
-               return False;
+               return false;
        }
 
        if (!ep1->endpoint || !ep2->endpoint) {
@@ -49,9 +52,9 @@ static BOOL endpoints_match(const struct dcerpc_binding *ep1,
        }
 
        if (strcasecmp(ep1->endpoint, ep2->endpoint) != 0) 
-               return False;
+               return false;
 
-       return True;
+       return true;
 }
 
 /*
@@ -133,12 +136,12 @@ static const struct dcesrv_interface *find_interface_by_uuid(const struct dcesrv
 }
 
 /*
-  find a call that is pending in our call list
+  find the earlier parts of a fragmented call awaiting reassembily
 */
-static struct dcesrv_call_state *dcesrv_find_call(struct dcesrv_connection *dce_conn, uint16_t call_id)
+static struct dcesrv_call_state *dcesrv_find_fragmented_call(struct dcesrv_connection *dce_conn, uint16_t call_id)
 {
        struct dcesrv_call_state *c;
-       for (c=dce_conn->call_list;c;c=c->next) {
+       for (c=dce_conn->incoming_fragmented_call_list;c;c=c->next) {
                if (c->pkt.call_id == call_id) {
                        return c;
                }
@@ -149,7 +152,7 @@ static struct dcesrv_call_state *dcesrv_find_call(struct dcesrv_connection *dce_
 /*
   register an interface on an endpoint
 */
-NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
+_PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
                                   const char *ep_name,
                                   const struct dcesrv_interface *iface,
                                   const struct security_descriptor *sd)
@@ -177,6 +180,17 @@ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
                ZERO_STRUCTP(ep);
                ep->ep_description = talloc_reference(ep, binding);
                add_ep = True;
+
+               /* add mgmt interface */
+               ifl = talloc(dce_ctx, struct dcesrv_if_list);
+               if (!ifl) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               memcpy(&(ifl->iface), &dcesrv_mgmt_interface, 
+                          sizeof(struct dcesrv_interface));
+
+               DLIST_ADD(ep->interface_list, ifl);
        }
 
        /* see if the interface is already registered on te endpoint */
@@ -256,7 +270,7 @@ NTSTATUS dcesrv_generic_session_key(struct dcesrv_connection *p,
 /*
   fetch the user session key - may be default (above) or the SMB session key
 */
-NTSTATUS dcesrv_fetch_session_key(struct dcesrv_connection *p,
+_PUBLIC_ NTSTATUS dcesrv_fetch_session_key(struct dcesrv_connection *p,
                                  DATA_BLOB *session_key)
 {
        return p->auth_state.session_key(p, session_key);
@@ -266,10 +280,8 @@ NTSTATUS dcesrv_fetch_session_key(struct dcesrv_connection *p,
 /*
   destroy a link to an endpoint
 */
-static int dcesrv_endpoint_destructor(void *ptr)
+static int dcesrv_endpoint_destructor(struct dcesrv_connection *p)
 {
-       struct dcesrv_connection *p = ptr;
-
        while (p->contexts) {
                struct dcesrv_connection_context *c = p->contexts;
 
@@ -292,6 +304,8 @@ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
                                 const struct dcesrv_endpoint *ep,
                                 struct auth_session_info *session_info,
                                 struct event_context *event_ctx,
+                                struct messaging_context *msg_ctx,
+                                struct server_id server_id,
                                 uint32_t state_flags,
                                 struct dcesrv_connection **_p)
 {
@@ -313,6 +327,7 @@ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
        p->endpoint = ep;
        p->contexts = NULL;
        p->call_list = NULL;
+       p->incoming_fragmented_call_list = NULL;
        p->pending_call_list = NULL;
        p->cli_max_recv_frag = 0;
        p->partial_input = data_blob(NULL, 0);
@@ -321,6 +336,8 @@ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
        p->auth_state.session_info = session_info;
        p->auth_state.session_key = dcesrv_generic_session_key;
        p->event_ctx = event_ctx;
+       p->msg_ctx = msg_ctx;
+       p->server_id = server_id;
        p->processing = False;
        p->state_flags = state_flags;
        ZERO_STRUCT(p->transport);
@@ -334,11 +351,13 @@ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
 /*
   search and connect to a dcerpc endpoint
 */
-NTSTATUS dcesrv_endpoint_search_connect(struct dcesrv_context *dce_ctx,
+_PUBLIC_ NTSTATUS dcesrv_endpoint_search_connect(struct dcesrv_context *dce_ctx,
                                        TALLOC_CTX *mem_ctx,
                                        const struct dcerpc_binding *ep_description,
                                        struct auth_session_info *session_info,
                                        struct event_context *event_ctx,
+                                       struct messaging_context *msg_ctx,
+                                       struct server_id server_id,
                                        uint32_t state_flags,
                                        struct dcesrv_connection **dce_conn_p)
 {
@@ -351,7 +370,9 @@ NTSTATUS dcesrv_endpoint_search_connect(struct dcesrv_context *dce_ctx,
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
        }
 
-       status = dcesrv_endpoint_connect(dce_ctx, mem_ctx, ep, session_info, event_ctx, state_flags, dce_conn_p);
+       status = dcesrv_endpoint_connect(dce_ctx, mem_ctx, ep, session_info,
+                                        event_ctx, msg_ctx, server_id,
+                                        state_flags, dce_conn_p);
        NT_STATUS_NOT_OK_RETURN(status);
 
        (*dce_conn_p)->auth_state.session_key = dcesrv_inherited_session_key;
@@ -369,7 +390,7 @@ static void dcesrv_init_hdr(struct ncacn_packet *pkt)
 {
        pkt->rpc_vers = 5;
        pkt->rpc_vers_minor = 0;
-       if (lp_rpc_big_endian()) {
+       if (lp_rpc_big_endian(global_loadparm)) {
                pkt->drep[0] = 0;
        } else {
                pkt->drep[0] = DCERPC_DREP_LE;
@@ -379,6 +400,43 @@ static void dcesrv_init_hdr(struct ncacn_packet *pkt)
        pkt->drep[3] = 0;
 }
 
+/*
+  move a call from an existing linked list to the specified list. This
+  prevents bugs where we forget to remove the call from a previous
+  list when moving it.
+ */
+static void dcesrv_call_set_list(struct dcesrv_call_state *call, 
+                                enum dcesrv_call_list list)
+{
+       switch (call->list) {
+       case DCESRV_LIST_NONE:
+               break;
+       case DCESRV_LIST_CALL_LIST:
+               DLIST_REMOVE(call->conn->call_list, call);
+               break;
+       case DCESRV_LIST_FRAGMENTED_CALL_LIST:
+               DLIST_REMOVE(call->conn->incoming_fragmented_call_list, call);
+               break;
+       case DCESRV_LIST_PENDING_CALL_LIST:
+               DLIST_REMOVE(call->conn->pending_call_list, call);
+               break;
+       }
+       call->list = list;
+       switch (list) {
+       case DCESRV_LIST_NONE:
+               break;
+       case DCESRV_LIST_CALL_LIST:
+               DLIST_ADD_END(call->conn->call_list, call, struct dcesrv_call_state *);
+               break;
+       case DCESRV_LIST_FRAGMENTED_CALL_LIST:
+               DLIST_ADD_END(call->conn->incoming_fragmented_call_list, call, struct dcesrv_call_state *);
+               break;
+       case DCESRV_LIST_PENDING_CALL_LIST:
+               DLIST_ADD_END(call->conn->pending_call_list, call, struct dcesrv_call_state *);
+               break;
+       }
+}
+
 /*
   return a dcerpc fault
 */
@@ -412,7 +470,7 @@ static NTSTATUS dcesrv_fault(struct dcesrv_call_state *call, uint32_t fault_code
        dcerpc_set_frag_length(&rep->blob, rep->blob.length);
 
        DLIST_ADD_END(call->replies, rep, struct data_blob_list_item *);
-       DLIST_ADD_END(call->conn->call_list, call, struct dcesrv_call_state *);
+       dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
 
        return NT_STATUS_OK;    
 }
@@ -451,7 +509,7 @@ static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
        dcerpc_set_frag_length(&rep->blob, rep->blob.length);
 
        DLIST_ADD_END(call->replies, rep, struct data_blob_list_item *);
-       DLIST_ADD_END(call->conn->call_list, call, struct dcesrv_call_state *);
+       dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
 
        return NT_STATUS_OK;    
 }
@@ -471,6 +529,10 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
        uint32_t context_id;
        const struct dcesrv_interface *iface;
 
+       if (call->pkt.u.bind.assoc_group_id != 0) {
+               return dcesrv_bind_nak(call, 0);        
+       }
+
        if (call->pkt.u.bind.num_contexts < 1 ||
            call->pkt.u.bind.ctx_list[0].num_transfer_syntaxes < 1) {
                return dcesrv_bind_nak(call, 0);
@@ -541,7 +603,8 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
        pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
        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;
+       /* we need to send a non zero assoc_group_id here to make longhorn happy, it also matches samba3 */
+       pkt.u.bind_ack.assoc_group_id = 0x12345678;
        if (iface) {
                /* FIXME: Use pipe name as specified by endpoint instead of interface name */
                pkt.u.bind_ack.secondary_address = talloc_asprintf(call, "\\PIPE\\%s", iface->name);
@@ -558,7 +621,8 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
        pkt.u.bind_ack.ctx_list[0].syntax = ndr_transfer_syntax;
        pkt.u.bind_ack.auth_info = data_blob(NULL, 0);
 
-       if (!dcesrv_auth_bind_ack(call, &pkt)) {
+       status = dcesrv_auth_bind_ack(call, &pkt);
+       if (!NT_STATUS_IS_OK(status)) {
                return dcesrv_bind_nak(call, 0);
        }
 
@@ -587,7 +651,7 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
        dcerpc_set_frag_length(&rep->blob, rep->blob.length);
 
        DLIST_ADD_END(call->replies, rep, struct data_blob_list_item *);
-       DLIST_ADD_END(call->conn->call_list, call, struct dcesrv_call_state *);
+       dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
 
        return NT_STATUS_OK;
 }
@@ -707,8 +771,15 @@ static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
        pkt.u.alter_resp.auth_info = data_blob(NULL, 0);
        pkt.u.alter_resp.secondary_address = "";
 
-       if (!dcesrv_auth_alter_ack(call, &pkt)) {
-               return dcesrv_bind_nak(call, 0);
+       status = dcesrv_auth_alter_ack(call, &pkt);
+       if (!NT_STATUS_IS_OK(status)) {
+               if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)
+                   || NT_STATUS_EQUAL(status, NT_STATUS_LOGON_FAILURE)
+                   || NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)
+                   || NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
+                       return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
+               }
+               return dcesrv_fault(call, 0);
        }
 
        rep = talloc(call, struct data_blob_list_item);
@@ -725,7 +796,7 @@ static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
        dcerpc_set_frag_length(&rep->blob, rep->blob.length);
 
        DLIST_ADD_END(call->replies, rep, struct data_blob_list_item *);
-       DLIST_ADD_END(call->conn->call_list, call, struct dcesrv_call_state *);
+       dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
 
        return NT_STATUS_OK;
 }
@@ -739,10 +810,6 @@ static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
        NTSTATUS status;
        struct dcesrv_connection_context *context;
 
-       call->fault_code        = 0;
-       call->state_flags       = call->conn->state_flags;
-       call->time              = timeval_current();
-
        /* if authenticated, and the mech we use can't do async replies, don't use them... */
        if (call->conn->auth_state.gensec_security && 
            !gensec_have_feature(call->conn->auth_state.gensec_security, GENSEC_FEATURE_ASYNC_REPLIES)) {
@@ -760,10 +827,9 @@ static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
        pull->flags |= LIBNDR_FLAG_REF_ALLOC;
 
        call->context   = context;
-       call->event_ctx = context->conn->event_ctx;
        call->ndr_pull  = pull;
 
-       if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_ORPC) {
+       if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
                pull->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
        }
 
@@ -794,7 +860,7 @@ static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
        }
 
        /* add the call to the pending list */
-       DLIST_ADD_END(call->conn->pending_call_list, call, struct dcesrv_call_state *);
+       dcesrv_call_set_list(call, DCESRV_LIST_PENDING_CALL_LIST);
 
        if (call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
                return NT_STATUS_OK;
@@ -803,7 +869,7 @@ static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
        return dcesrv_reply(call);
 }
 
-NTSTATUS dcesrv_reply(struct dcesrv_call_state *call)
+_PUBLIC_ NTSTATUS dcesrv_reply(struct dcesrv_call_state *call)
 {
        struct ndr_push *push;
        NTSTATUS status;
@@ -826,7 +892,7 @@ NTSTATUS dcesrv_reply(struct dcesrv_call_state *call)
           pointers */
        push->ptr_count = call->ndr_pull->ptr_count;
 
-       if (lp_rpc_big_endian()) {
+       if (lp_rpc_big_endian(global_loadparm)) {
                push->flags |= LIBNDR_FLAG_BIGENDIAN;
        }
 
@@ -885,8 +951,7 @@ NTSTATUS dcesrv_reply(struct dcesrv_call_state *call)
        } while (stub.length != 0);
 
        /* move the call from the pending to the finished calls list */
-       DLIST_REMOVE(call->conn->pending_call_list, call);
-       DLIST_ADD_END(call->conn->call_list, call, struct dcesrv_call_state *);
+       dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
 
        if (call->conn->call_list && call->conn->call_list->replies) {
                if (call->conn->transport.report_output_data) {
@@ -897,7 +962,7 @@ NTSTATUS dcesrv_reply(struct dcesrv_call_state *call)
        return NT_STATUS_OK;
 }
 
-struct socket_address *dcesrv_connection_get_my_addr(struct dcesrv_connection *conn, TALLOC_CTX *mem_ctx)
+_PUBLIC_ struct socket_address *dcesrv_connection_get_my_addr(struct dcesrv_connection *conn, TALLOC_CTX *mem_ctx)
 {
        if (!conn->transport.get_my_addr) {
                return NULL;
@@ -906,7 +971,7 @@ struct socket_address *dcesrv_connection_get_my_addr(struct dcesrv_connection *c
        return conn->transport.get_my_addr(conn, mem_ctx);
 }
 
-struct socket_address *dcesrv_connection_get_peer_addr(struct dcesrv_connection *conn, TALLOC_CTX *mem_ctx)
+_PUBLIC_ struct socket_address *dcesrv_connection_get_peer_addr(struct dcesrv_connection *conn, TALLOC_CTX *mem_ctx)
 {
        if (!conn->transport.get_peer_addr) {
                return NULL;
@@ -947,6 +1012,15 @@ static void dce_partial_advance(struct dcesrv_connection *dce_conn, uint32_t off
        data_blob_free(&blob);
 }
 
+/*
+  remove the call from the right list when freed
+ */
+static int dcesrv_call_dequeue(struct dcesrv_call_state *call)
+{
+       dcesrv_call_set_list(call, DCESRV_LIST_NONE);
+       return 0;
+}
+
 /*
   process some input to a dcerpc endpoint server.
 */
@@ -957,15 +1031,19 @@ NTSTATUS dcesrv_input_process(struct dcesrv_connection *dce_conn)
        struct dcesrv_call_state *call;
        DATA_BLOB blob;
 
-       call = talloc(dce_conn, struct dcesrv_call_state);
+       call = talloc_zero(dce_conn, struct dcesrv_call_state);
        if (!call) {
                talloc_free(dce_conn->partial_input.data);
                return NT_STATUS_NO_MEMORY;
        }
-       call->conn      = dce_conn;
-       call->replies   = NULL;
-       call->context   = NULL;
-       call->event_ctx = dce_conn->event_ctx;
+       call->conn              = dce_conn;
+       call->event_ctx         = dce_conn->event_ctx;
+       call->msg_ctx           = dce_conn->msg_ctx;
+       call->state_flags       = call->conn->state_flags;
+       call->time              = timeval_current();
+       call->list              = DCESRV_LIST_NONE;
+
+       talloc_set_destructor(call, dcesrv_call_dequeue);
 
        blob = dce_conn->partial_input;
        blob.length = dcerpc_get_frag_length(&blob);
@@ -1011,7 +1089,7 @@ NTSTATUS dcesrv_input_process(struct dcesrv_connection *dce_conn)
 
                /* this is a continuation of an existing call - find the call then
                   tack it on the end */
-               call = dcesrv_find_call(dce_conn, call2->pkt.call_id);
+               call = dcesrv_find_fragmented_call(dce_conn, call2->pkt.call_id);
                if (!call) {
                        return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
                }
@@ -1047,12 +1125,15 @@ NTSTATUS dcesrv_input_process(struct dcesrv_connection *dce_conn)
        }
 
        /* 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 */
+          just put it on the incoming_fragmented_call_list and wait for the rest */
        if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
            !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
-               DLIST_ADD_END(dce_conn->call_list, call, struct dcesrv_call_state *);
+               dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
                return NT_STATUS_OK;
-       }
+       } 
+       
+       /* This removes any fragments we may have had stashed away */
+       dcesrv_call_set_list(call, DCESRV_LIST_NONE);
 
        switch (call->pkt.ptype) {
        case DCERPC_PKT_BIND:
@@ -1087,7 +1168,7 @@ NTSTATUS dcesrv_input_process(struct dcesrv_connection *dce_conn)
   provide some input to a dcerpc endpoint server. This passes data
   from a dcerpc client into the server
 */
-NTSTATUS dcesrv_input(struct dcesrv_connection *dce_conn, const DATA_BLOB *data)
+_PUBLIC_ NTSTATUS dcesrv_input(struct dcesrv_connection *dce_conn, const DATA_BLOB *data)
 {
        NTSTATUS status;
 
@@ -1159,14 +1240,14 @@ _PUBLIC_ NTSTATUS dcesrv_output(struct dcesrv_connection *dce_conn,
 
        if (call->replies == NULL) {
                /* we're done with the whole call */
-               DLIST_REMOVE(dce_conn->call_list, call);
+               dcesrv_call_set_list(call, DCESRV_LIST_NONE);
                talloc_free(call);
        }
 
        return status;
 }
 
-static NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx, const char **endpoint_servers, struct dcesrv_context **_dce_ctx)
+_PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx, const char **endpoint_servers, struct dcesrv_context **_dce_ctx)
 {
        NTSTATUS status;
        struct dcesrv_context *dce_ctx;
@@ -1202,21 +1283,6 @@ static NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx, const char **endpoint_s
        return NT_STATUS_OK;
 }
 
-/*
-  initialise the dcerpc server context for ncacn_np based services
-*/
-NTSTATUS dcesrv_init_ipc_context(TALLOC_CTX *mem_ctx, struct dcesrv_context **_dce_ctx)
-{
-       NTSTATUS status;
-       struct dcesrv_context *dce_ctx;
-
-       status = dcesrv_init_context(mem_ctx, lp_dcerpc_endpoint_servers(), &dce_ctx);
-       NT_STATUS_NOT_OK_RETURN(status);
-
-       *_dce_ctx = dce_ctx;
-       return NT_STATUS_OK;
-}
-
 /* the list of currently registered DCERPC endpoint servers.
  */
 static struct ep_server {
@@ -1232,7 +1298,7 @@ static int num_ep_servers;
 
   The 'type' is used to specify whether this is for a disk, printer or IPC$ share
 */
-NTSTATUS dcerpc_register_ep_server(const void *_ep_server)
+_PUBLIC_ NTSTATUS dcerpc_register_ep_server(const void *_ep_server)
 {
        const struct dcesrv_endpoint_server *ep_server = _ep_server;
        
@@ -1299,78 +1365,18 @@ const struct dcesrv_critical_sizes *dcerpc_module_version(void)
 }
 
 /*
-  open the dcerpc server sockets
+  initialise the dcerpc server context for ncacn_np based services
 */
-static void dcesrv_task_init(struct task_server *task)
+_PUBLIC_ NTSTATUS dcesrv_init_ipc_context(TALLOC_CTX *mem_ctx, struct dcesrv_context **_dce_ctx)
 {
        NTSTATUS status;
        struct dcesrv_context *dce_ctx;
-       struct dcesrv_endpoint *e;
-
-       task_server_set_title(task, "task[dcesrv]");
-
-       status = dcesrv_init_context(task->event_ctx,
-                                    lp_dcerpc_endpoint_servers(),
-                                    &dce_ctx);
-       if (!NT_STATUS_IS_OK(status)) goto failed;
-
-       /* Make sure the directory for NCALRPC exists */
-       if (!directory_exist(lp_ncalrpc_dir())) {
-               mkdir(lp_ncalrpc_dir(), 0755);
-       }
 
-       for (e=dce_ctx->endpoint_list;e;e=e->next) {
-               switch (e->ep_description->transport) {
-               case NCACN_UNIX_STREAM:
-                       status = dcesrv_add_ep_unix(dce_ctx, e, task->event_ctx, task->model_ops);
-                       if (!NT_STATUS_IS_OK(status)) goto failed;
-                       break;
-               
-               case NCALRPC:
-                       status = dcesrv_add_ep_ncalrpc(dce_ctx, e, task->event_ctx, task->model_ops);
-                       if (!NT_STATUS_IS_OK(status)) goto failed;
-                       break;
-
-               case NCACN_IP_TCP:
-                       status = dcesrv_add_ep_tcp(dce_ctx, e, task->event_ctx, task->model_ops);
-                       if (!NT_STATUS_IS_OK(status)) goto failed;
-                       break;
-                       
-               case NCACN_NP:
-/*                     FIXME: status = dcesrv_add_ep_np(dce_ctx, e, task->event_ctx, task->model_ops);
-                       if (!NT_STATUS_IS_OK(status)) goto failed;
-*/                     break;
-
-               default:
-                       status = NT_STATUS_NOT_SUPPORTED;
-                       if (!NT_STATUS_IS_OK(status)) goto failed;
-               }
-       }
-
-       return;
-failed:
-       task_server_terminate(task, "Failed to startup dcerpc server task");    
-}
+       status = dcesrv_init_context(mem_ctx, lp_dcerpc_endpoint_servers(global_loadparm), &dce_ctx);
+       NT_STATUS_NOT_OK_RETURN(status);
 
-/*
-  called on startup of the smb server service It's job is to start
-  listening on all configured sockets
-*/
-static NTSTATUS dcesrv_init(struct event_context *event_context, 
-                           const struct model_ops *model_ops)
-{      
-       return task_server_startup(event_context, model_ops, dcesrv_task_init);
+       *_dce_ctx = dce_ctx;
+       return NT_STATUS_OK;
 }
 
-NTSTATUS server_service_rpc_init(void)
-{
-       init_module_fn static_init[] = STATIC_dcerpc_server_MODULES;
-       init_module_fn *shared_init = load_samba_modules(NULL, "dcerpc_server");
-
-       run_init_functions(static_init);
-       run_init_functions(shared_init);
 
-       talloc_free(shared_init);
-       
-       return register_server_service("rpc", dcesrv_init);
-}