Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into v4-0-gmake3
[kai/samba.git] / source / rpc_server / dcerpc_server.c
index 08b68b2318f2effddff64dcfe403c94db05fbb88..b043424faabe64afc40ca0be29934780262484f7 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,
@@ -17,8 +17,7 @@
    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 "system/filesys.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) {
@@ -50,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;
 }
 
 /*
@@ -86,7 +88,7 @@ static struct dcesrv_connection_context *dcesrv_find_context(struct dcesrv_conne
 /*
   see if a uuid and if_version match to an interface
 */
-static BOOL interface_match(const struct dcesrv_interface *if1,
+static bool interface_match(const struct dcesrv_interface *if1,
                                                        const struct dcesrv_interface *if2)
 {
        return (if1->syntax_id.if_version == if2->syntax_id.if_version && 
@@ -111,7 +113,7 @@ static const struct dcesrv_interface *find_interface(const struct dcesrv_endpoin
 /*
   see if a uuid and if_version match to an interface
 */
-static BOOL interface_match_by_uuid(const struct dcesrv_interface *iface,
+static bool interface_match_by_uuid(const struct dcesrv_interface *iface,
                                    const struct GUID *uuid, uint32_t if_version)
 {
        return (iface->syntax_id.if_version == if_version && 
@@ -158,7 +160,7 @@ _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
        struct dcesrv_endpoint *ep;
        struct dcesrv_if_list *ifl;
        struct dcerpc_binding *binding;
-       BOOL add_ep = False;
+       bool add_ep = false;
        NTSTATUS status;
        
        status = dcerpc_parse_binding(dce_ctx, ep_name, &binding);
@@ -177,7 +179,18 @@ _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
                }
                ZERO_STRUCTP(ep);
                ep->ep_description = talloc_reference(ep, binding);
-               add_ep = True;
+               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 */
@@ -292,7 +305,7 @@ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
                                 struct auth_session_info *session_info,
                                 struct event_context *event_ctx,
                                 struct messaging_context *msg_ctx,
-                                uint32_t server_id,
+                                struct server_id server_id,
                                 uint32_t state_flags,
                                 struct dcesrv_connection **_p)
 {
@@ -325,7 +338,7 @@ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
        p->event_ctx = event_ctx;
        p->msg_ctx = msg_ctx;
        p->server_id = server_id;
-       p->processing = False;
+       p->processing = false;
        p->state_flags = state_flags;
        ZERO_STRUCT(p->transport);
 
@@ -344,7 +357,7 @@ _PUBLIC_ NTSTATUS dcesrv_endpoint_search_connect(struct dcesrv_context *dce_ctx,
                                        struct auth_session_info *session_info,
                                        struct event_context *event_ctx,
                                        struct messaging_context *msg_ctx,
-                                       uint32_t server_id,
+                                       struct server_id server_id,
                                        uint32_t state_flags,
                                        struct dcesrv_connection **dce_conn_p)
 {
@@ -373,11 +386,11 @@ _PUBLIC_ NTSTATUS dcesrv_endpoint_search_connect(struct dcesrv_context *dce_ctx,
 }
 
 
-static void dcesrv_init_hdr(struct ncacn_packet *pkt)
+static void dcesrv_init_hdr(struct ncacn_packet *pkt, bool bigendian)
 {
        pkt->rpc_vers = 5;
        pkt->rpc_vers_minor = 0;
-       if (lp_rpc_big_endian()) {
+       if (bigendian) {
                pkt->drep[0] = 0;
        } else {
                pkt->drep[0] = DCERPC_DREP_LE;
@@ -387,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
 */
@@ -397,7 +447,7 @@ static NTSTATUS dcesrv_fault(struct dcesrv_call_state *call, uint32_t fault_code
        NTSTATUS status;
 
        /* setup a bind_ack */
-       dcesrv_init_hdr(&pkt);
+       dcesrv_init_hdr(&pkt, lp_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
        pkt.auth_length = 0;
        pkt.call_id = call->pkt.call_id;
        pkt.ptype = DCERPC_PKT_FAULT;
@@ -420,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;    
 }
@@ -436,7 +486,7 @@ static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
        NTSTATUS status;
 
        /* setup a bind_nak */
-       dcesrv_init_hdr(&pkt);
+       dcesrv_init_hdr(&pkt, lp_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
        pkt.auth_length = 0;
        pkt.call_id = call->pkt.call_id;
        pkt.ptype = DCERPC_PKT_BIND_NAK;
@@ -459,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;    
 }
@@ -479,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);
@@ -542,14 +596,15 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
        }
 
        /* setup a bind_ack */
-       dcesrv_init_hdr(&pkt);
+       dcesrv_init_hdr(&pkt, lp_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
        pkt.auth_length = 0;
        pkt.call_id = call->pkt.call_id;
        pkt.ptype = DCERPC_PKT_BIND_ACK;
        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);
@@ -566,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);
        }
 
@@ -595,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;
 }
@@ -696,7 +752,7 @@ static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
        }
 
        /* setup a alter_resp */
-       dcesrv_init_hdr(&pkt);
+       dcesrv_init_hdr(&pkt, lp_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
        pkt.auth_length = 0;
        pkt.call_id = call->pkt.call_id;
        pkt.ptype = DCERPC_PKT_ALTER_RESP;
@@ -715,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);
@@ -733,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;
 }
@@ -758,7 +821,8 @@ static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
                return dcesrv_fault(call, DCERPC_FAULT_UNK_IF);
        }
 
-       pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
+       pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call,
+                                 lp_iconv_convenience(call->conn->dce_ctx->lp_ctx));
        NT_STATUS_HAVE_NO_MEMORY(pull);
 
        pull->flags |= LIBNDR_FLAG_REF_ALLOC;
@@ -766,7 +830,7 @@ static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
        call->context   = context;
        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;
        }
 
@@ -797,7 +861,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;
@@ -821,7 +885,7 @@ _PUBLIC_ NTSTATUS dcesrv_reply(struct dcesrv_call_state *call)
        }
 
        /* form the reply NDR */
-       push = ndr_push_init_ctx(call);
+       push = ndr_push_init_ctx(call, lp_iconv_convenience(call->conn->dce_ctx->lp_ctx));
        NT_STATUS_HAVE_NO_MEMORY(push);
 
        /* carry over the pointer count to the reply in case we are
@@ -829,7 +893,7 @@ _PUBLIC_ 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(call->conn->dce_ctx->lp_ctx)) {
                push->flags |= LIBNDR_FLAG_BIGENDIAN;
        }
 
@@ -858,7 +922,7 @@ _PUBLIC_ NTSTATUS dcesrv_reply(struct dcesrv_call_state *call)
                }
 
                /* form the dcerpc response packet */
-               dcesrv_init_hdr(&pkt);
+               dcesrv_init_hdr(&pkt, lp_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
                pkt.auth_length = 0;
                pkt.call_id = call->pkt.call_id;
                pkt.ptype = DCERPC_PKT_RESPONSE;
@@ -888,8 +952,7 @@ _PUBLIC_ 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) {
@@ -921,15 +984,15 @@ _PUBLIC_ struct socket_address *dcesrv_connection_get_peer_addr(struct dcesrv_co
 /*
   work out if we have a full packet yet
 */
-static BOOL dce_full_packet(const DATA_BLOB *data)
+static bool dce_full_packet(const DATA_BLOB *data)
 {
        if (data->length < DCERPC_FRAG_LEN_OFFSET+2) {
-               return False;
+               return false;
        }
        if (dcerpc_get_frag_length(data) > data->length) {
-               return False;
+               return false;
        }
-       return True;
+       return true;
 }
 
 /*
@@ -950,12 +1013,22 @@ 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.
 */
 NTSTATUS dcesrv_input_process(struct dcesrv_connection *dce_conn)
 {
        struct ndr_pull *ndr;
+       enum ndr_err_code ndr_err;
        NTSTATUS status;
        struct dcesrv_call_state *call;
        DATA_BLOB blob;
@@ -970,11 +1043,14 @@ NTSTATUS dcesrv_input_process(struct dcesrv_connection *dce_conn)
        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);
 
-       ndr = ndr_pull_init_blob(&blob, call);
+       ndr = ndr_pull_init_blob(&blob, call, lp_iconv_convenience(call->conn->dce_ctx->lp_ctx));
        if (!ndr) {
                talloc_free(dce_conn->partial_input.data);
                talloc_free(call);
@@ -985,11 +1061,11 @@ NTSTATUS dcesrv_input_process(struct dcesrv_connection *dce_conn)
                ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
        }
 
-       status = ndr_pull_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, &call->pkt);
-       if (!NT_STATUS_IS_OK(status)) {
+       ndr_err = ndr_pull_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, &call->pkt);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                talloc_free(dce_conn->partial_input.data);
                talloc_free(call);
-               return status;
+               return ndr_map_error2ntstatus(ndr_err);
        }
 
        /* we have to check the signing here, before combining the
@@ -1054,13 +1130,12 @@ NTSTATUS dcesrv_input_process(struct dcesrv_connection *dce_conn)
           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->incoming_fragmented_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 */
-       DLIST_REMOVE(dce_conn->incoming_fragmented_call_list, call);
+       dcesrv_call_set_list(call, DCESRV_LIST_NONE);
 
        switch (call->pkt.ptype) {
        case DCERPC_PKT_BIND:
@@ -1167,14 +1242,16 @@ _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, 
+                                     struct loadparm_context *lp_ctx,
+                                     const char **endpoint_servers, struct dcesrv_context **_dce_ctx)
 {
        NTSTATUS status;
        struct dcesrv_context *dce_ctx;
@@ -1188,6 +1265,7 @@ static NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx, const char **endpoint_s
        dce_ctx = talloc(mem_ctx, struct dcesrv_context);
        NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
        dce_ctx->endpoint_list  = NULL;
+       dce_ctx->lp_ctx = lp_ctx;
 
        for (i=0;endpoint_servers[i];i++) {
                const struct dcesrv_endpoint_server *ep_server;
@@ -1210,21 +1288,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
-*/
-_PUBLIC_ 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 {
@@ -1307,78 +1370,19 @@ 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 loadparm_context *lp_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_ctx, lp_dcerpc_endpoint_servers(lp_ctx), &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);
-}