s4: removed an unused variable
[ira/wip.git] / source4 / rpc_server / dcerpc_server.c
index fa7b8d26f5c72fe0c57ffb6d47e1f957da898b84..b529e605c59b398de4a2a1526bd164d65a1fbafc 100644 (file)
@@ -24,7 +24,7 @@
 #include "librpc/gen_ndr/ndr_dcerpc.h"
 #include "auth/auth.h"
 #include "auth/gensec/gensec.h"
-#include "lib/util/dlinklist.h"
+#include "../lib/util/dlinklist.h"
 #include "rpc_server/dcerpc_server.h"
 #include "rpc_server/dcerpc_server_proto.h"
 #include "librpc/rpc/dcerpc_proto.h"
@@ -36,7 +36,7 @@
 #include "libcli/security/security.h"
 #include "param/param.h"
 
-#define SAMBA_ACCOC_GROUP 0x12345678
+#define SAMBA_ASSOC_GROUP 0x12345678
 
 extern const struct dcesrv_interface dcesrv_mgmt_interface;
 
@@ -251,8 +251,8 @@ _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
        return NT_STATUS_OK;
 }
 
-static NTSTATUS dcesrv_inherited_session_key(struct dcesrv_connection *p,
-                                             DATA_BLOB *session_key)
+NTSTATUS dcesrv_inherited_session_key(struct dcesrv_connection *p,
+                                     DATA_BLOB *session_key)
 {
        if (p->auth_state.session_info->session_key.length) {
                *session_key = p->auth_state.session_info->session_key;
@@ -288,26 +288,6 @@ _PUBLIC_ NTSTATUS dcesrv_fetch_session_key(struct dcesrv_connection *p,
        return NT_STATUS_OK;
 }
 
-
-/*
-  destroy a link to an endpoint
-*/
-static int dcesrv_endpoint_destructor(struct dcesrv_connection *p)
-{
-       while (p->contexts) {
-               struct dcesrv_connection_context *c = p->contexts;
-
-               DLIST_REMOVE(p->contexts, c);
-
-               if (c->iface) {
-                       c->iface->unbind(c, c->iface);
-               }
-       }
-
-       return 0;
-}
-
-
 /*
   connect to a dcerpc endpoint
 */
@@ -315,7 +295,7 @@ _PUBLIC_ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
                                 TALLOC_CTX *mem_ctx,
                                 const struct dcesrv_endpoint *ep,
                                 struct auth_session_info *session_info,
-                                struct event_context *event_ctx,
+                                struct tevent_context *event_ctx,
                                 struct messaging_context *msg_ctx,
                                 struct server_id server_id,
                                 uint32_t state_flags,
@@ -339,6 +319,7 @@ _PUBLIC_ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
        p->endpoint = ep;
        p->contexts = NULL;
        p->call_list = NULL;
+       p->packet_log_dir = lp_lockdir(dce_ctx->lp_ctx);
        p->incoming_fragmented_call_list = NULL;
        p->pending_call_list = NULL;
        p->cli_max_recv_frag = 0;
@@ -354,8 +335,6 @@ _PUBLIC_ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
        p->state_flags = state_flags;
        ZERO_STRUCT(p->transport);
 
-       talloc_set_destructor(p, dcesrv_endpoint_destructor);
-
        *_p = p;
        return NT_STATUS_OK;
 }
@@ -367,7 +346,7 @@ _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 tevent_context *event_ctx,
                                        struct messaging_context *msg_ctx,
                                        struct server_id server_id,
                                        uint32_t state_flags,
@@ -488,6 +467,12 @@ static NTSTATUS dcesrv_fault(struct dcesrv_call_state *call, uint32_t fault_code
        DLIST_ADD_END(call->replies, rep, struct data_blob_list_item *);
        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) {
+                       call->conn->transport.report_output_data(call->conn);
+               }
+       }
+
        return NT_STATUS_OK;    
 }
 
@@ -527,9 +512,25 @@ static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
        DLIST_ADD_END(call->replies, rep, struct data_blob_list_item *);
        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) {
+                       call->conn->transport.report_output_data(call->conn);
+               }
+       }
+
        return NT_STATUS_OK;    
 }
 
+static int dcesrv_connection_context_destructor(struct dcesrv_connection_context *c)
+{
+       DLIST_REMOVE(c->conn->contexts, c);
+
+       if (c->iface) {
+               c->iface->unbind(c, c->iface);
+       }
+
+       return 0;
+}
 
 /*
   handle a bind request
@@ -557,7 +558,8 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
         * assoc_group_id back to the clients
         */
        if (call->pkt.u.bind.assoc_group_id != 0 &&
-           call->pkt.u.bind.assoc_group_id != SAMBA_ACCOC_GROUP) {
+           lp_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
+           call->pkt.u.bind.assoc_group_id != SAMBA_ASSOC_GROUP) {
                return dcesrv_bind_nak(call, 0);        
        }
 
@@ -608,10 +610,29 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
                context->conn = call->conn;
                context->iface = iface;
                context->context_id = context_id;
-               context->private = NULL;
+               /*
+                * we need to send a non zero assoc_group_id here to make longhorn happy,
+                * it also matches samba3
+                */
+               context->assoc_group_id = SAMBA_ASSOC_GROUP;
+               context->private_data = NULL;
                context->handles = NULL;
                DLIST_ADD(call->conn->contexts, context);
                call->context = context;
+               talloc_set_destructor(context, dcesrv_connection_context_destructor);
+
+               status = iface->bind(call, iface);
+               if (!NT_STATUS_IS_OK(status)) {
+                       char *uuid_str = GUID_string(call, &uuid);
+                       DEBUG(2,("Request for dcerpc interface %s/%d rejected: %s\n",
+                                uuid_str, if_version, nt_errstr(status)));
+                       talloc_free(uuid_str);
+                       /* we don't want to trigger the iface->unbind() hook */
+                       context->iface = NULL;
+                       talloc_free(call->context);
+                       call->context = NULL;
+                       return dcesrv_bind_nak(call, 0);
+               }
        }
 
        if (call->conn->cli_max_recv_frag == 0) {
@@ -626,6 +647,8 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
 
        /* handle any authentication that is being requested */
        if (!dcesrv_auth_bind(call)) {
+               talloc_free(call->context);
+               call->context = NULL;
                return dcesrv_bind_nak(call, DCERPC_BIND_REASON_INVALID_AUTH_TYPE);
        }
 
@@ -637,8 +660,20 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
        pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
        pkt.u.bind_ack.max_xmit_frag = 0x2000;
        pkt.u.bind_ack.max_recv_frag = 0x2000;
-       /* 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 = SAMBA_ACCOC_GROUP;
+
+       /*
+         make it possible for iface->bind() to specify the assoc_group_id
+         This helps the openchange mapiproxy plugin to work correctly.
+         
+         metze
+       */
+       if (call->context) {
+               pkt.u.bind_ack.assoc_group_id = call->context->assoc_group_id;
+       } else {
+               /* we better pick something - this chosen so as to send a non zero assoc_group_id (matching windows), it also matches samba3 */
+               pkt.u.bind_ack.assoc_group_id = SAMBA_ASSOC_GROUP;
+       }
+
        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);
@@ -648,6 +683,8 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
        pkt.u.bind_ack.num_results = 1;
        pkt.u.bind_ack.ctx_list = talloc(call, struct dcerpc_ack_ctx);
        if (!pkt.u.bind_ack.ctx_list) {
+               talloc_free(call->context);
+               call->context = NULL;
                return NT_STATUS_NO_MEMORY;
        }
        pkt.u.bind_ack.ctx_list[0].result = result;
@@ -657,27 +694,22 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
 
        status = dcesrv_auth_bind_ack(call, &pkt);
        if (!NT_STATUS_IS_OK(status)) {
+               talloc_free(call->context);
+               call->context = NULL;
                return dcesrv_bind_nak(call, 0);
        }
 
-       if (iface) {
-               status = iface->bind(call, iface);
-               if (!NT_STATUS_IS_OK(status)) {
-                       char *uuid_str = GUID_string(call, &uuid);
-                       DEBUG(2,("Request for dcerpc interface %s/%d rejected: %s\n", 
-                                uuid_str, if_version, nt_errstr(status)));
-                       talloc_free(uuid_str);
-                       return dcesrv_bind_nak(call, 0);
-               }
-       }
-
        rep = talloc(call, struct data_blob_list_item);
        if (!rep) {
+               talloc_free(call->context);
+               call->context = NULL;
                return NT_STATUS_NO_MEMORY;
        }
 
        status = ncacn_push_auth(&rep->blob, call, lp_iconv_convenience(call->conn->dce_ctx->lp_ctx), &pkt, call->conn->auth_state.auth_info);
        if (!NT_STATUS_IS_OK(status)) {
+               talloc_free(call->context);
+               call->context = NULL;
                return status;
        }
 
@@ -686,6 +718,12 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
        DLIST_ADD_END(call->replies, rep, struct data_blob_list_item *);
        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) {
+                       call->conn->transport.report_output_data(call->conn);
+               }
+       }
+
        return NT_STATUS_OK;
 }
 
@@ -746,16 +784,20 @@ static NTSTATUS dcesrv_alter_new_context(struct dcesrv_call_state *call, uint32_
        context->conn = call->conn;
        context->iface = iface;
        context->context_id = context_id;
-       context->private = NULL;
+       context->assoc_group_id = SAMBA_ASSOC_GROUP;
+       context->private_data = NULL;
        context->handles = NULL;
        DLIST_ADD(call->conn->contexts, context);
        call->context = context;
+       talloc_set_destructor(context, dcesrv_connection_context_destructor);
 
-       if (iface) {
-               status = iface->bind(call, iface);
-               if (!NT_STATUS_IS_OK(status)) {
-                       return status;
-               }
+       status = iface->bind(call, iface);
+       if (!NT_STATUS_IS_OK(status)) {
+               /* we don't want to trigger the iface->unbind() hook */
+               context->iface = NULL;
+               talloc_free(context);
+               call->context = NULL;
+               return status;
        }
 
        return NT_STATUS_OK;
@@ -783,15 +825,26 @@ static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
        context_id = call->pkt.u.alter.ctx_list[0].context_id;
 
        /* see if they are asking for a new interface */
-       if (result == 0 &&
-           dcesrv_find_context(call->conn, context_id) == NULL) {
-               status = dcesrv_alter_new_context(call, context_id);
-               if (!NT_STATUS_IS_OK(status)) {
-                       result = DCERPC_BIND_PROVIDER_REJECT;
-                       reason = DCERPC_BIND_REASON_ASYNTAX;            
+       if (result == 0) {
+               call->context = dcesrv_find_context(call->conn, context_id);
+               if (!call->context) {
+                       status = dcesrv_alter_new_context(call, context_id);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               result = DCERPC_BIND_PROVIDER_REJECT;
+                               reason = DCERPC_BIND_REASON_ASYNTAX;
+                       }
                }
        }
 
+       if (result == 0 &&
+           call->pkt.u.alter.assoc_group_id != 0 &&
+           lp_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
+           call->pkt.u.alter.assoc_group_id != call->context->assoc_group_id) {
+               /* TODO: work out what to return here */
+               result = DCERPC_BIND_PROVIDER_REJECT;
+               reason = DCERPC_BIND_REASON_ASYNTAX;
+       }
+
        /* setup a alter_resp */
        dcesrv_init_hdr(&pkt, lp_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
        pkt.auth_length = 0;
@@ -800,7 +853,11 @@ static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
        pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
        pkt.u.alter_resp.max_xmit_frag = 0x2000;
        pkt.u.alter_resp.max_recv_frag = 0x2000;
-       pkt.u.alter_resp.assoc_group_id = call->pkt.u.alter.assoc_group_id;
+       if (result == 0) {
+               pkt.u.alter_resp.assoc_group_id = call->context->assoc_group_id;
+       } else {
+               pkt.u.alter_resp.assoc_group_id = 0;
+       }
        pkt.u.alter_resp.num_results = 1;
        pkt.u.alter_resp.ctx_list = talloc_array(call, struct dcerpc_ack_ctx, 1);
        if (!pkt.u.alter_resp.ctx_list) {
@@ -838,6 +895,12 @@ static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
        DLIST_ADD_END(call->replies, rep, struct data_blob_list_item *);
        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) {
+                       call->conn->transport.report_output_data(call->conn);
+               }
+       }
+
        return NT_STATUS_OK;
 }
 
@@ -870,10 +933,6 @@ static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
        call->context   = context;
        call->ndr_pull  = pull;
 
-       if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
-               pull->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
-       }
-
        if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
                pull->flags |= LIBNDR_FLAG_BIGENDIAN;
        }
@@ -951,13 +1010,16 @@ _PUBLIC_ NTSTATUS dcesrv_reply(struct dcesrv_call_state *call)
           request header size */
        chunk_size = call->conn->cli_max_recv_frag;
        chunk_size -= DCERPC_REQUEST_LENGTH;
-       if (call->conn->auth_state.gensec_security) {
-               chunk_size -= DCERPC_AUTH_TRAILER_LENGTH;
+       if (call->conn->auth_state.auth_info &&
+           call->conn->auth_state.gensec_security) {
                sig_size = gensec_sig_size(call->conn->auth_state.gensec_security,
                                           call->conn->cli_max_recv_frag);
-               chunk_size -= sig_size;
-               chunk_size -= (chunk_size % 16);
+               if (sig_size) {
+                       chunk_size -= DCERPC_AUTH_TRAILER_LENGTH;
+                       chunk_size -= sig_size;
+               }
        }
+       chunk_size -= (chunk_size % 16);
 
        do {
                uint32_t length;
@@ -1073,17 +1135,17 @@ static int dcesrv_call_dequeue(struct dcesrv_call_state *call)
 /*
   process some input to a dcerpc endpoint server.
 */
-NTSTATUS dcesrv_input_process(struct dcesrv_connection *dce_conn)
+NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
+                                    struct ncacn_packet *pkt,
+                                    DATA_BLOB blob)
 {
-       struct ndr_pull *ndr;
-       enum ndr_err_code ndr_err;
        NTSTATUS status;
        struct dcesrv_call_state *call;
-       DATA_BLOB blob;
 
        call = talloc_zero(dce_conn, struct dcesrv_call_state);
        if (!call) {
-               talloc_free(dce_conn->partial_input.data);
+               data_blob_free(&blob);
+               talloc_free(pkt);
                return NT_STATUS_NO_MEMORY;
        }
        call->conn              = dce_conn;
@@ -1093,39 +1155,19 @@ NTSTATUS dcesrv_input_process(struct dcesrv_connection *dce_conn)
        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, lp_iconv_convenience(call->conn->dce_ctx->lp_ctx));
-       if (!ndr) {
-               talloc_free(dce_conn->partial_input.data);
-               talloc_free(call);
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       if (!(CVAL(blob.data, DCERPC_DREP_OFFSET) & DCERPC_DREP_LE)) {
-               ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
-       }
+       talloc_steal(call, pkt);
+       talloc_steal(call, blob.data);
+       call->pkt = *pkt;
 
-       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 ndr_map_error2ntstatus(ndr_err);
-       }
+       talloc_set_destructor(call, dcesrv_call_dequeue);
 
        /* we have to check the signing here, before combining the
           pdus */
        if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
            !dcesrv_auth_request(call, &blob)) {
-               dce_partial_advance(dce_conn, blob.length);
                return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);          
        }
 
-       dce_partial_advance(dce_conn, blob.length);
-
        /* see if this is a continued packet */
        if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
            !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
@@ -1220,8 +1262,6 @@ NTSTATUS dcesrv_input_process(struct dcesrv_connection *dce_conn)
 */
 _PUBLIC_ NTSTATUS dcesrv_input(struct dcesrv_connection *dce_conn, const DATA_BLOB *data)
 {
-       NTSTATUS status;
-
        dce_conn->partial_input.data = talloc_realloc(dce_conn,
                                                      dce_conn->partial_input.data,
                                                      uint8_t,
@@ -1234,7 +1274,52 @@ _PUBLIC_ NTSTATUS dcesrv_input(struct dcesrv_connection *dce_conn, const DATA_BL
        dce_conn->partial_input.length += data->length;
 
        while (dce_full_packet(&dce_conn->partial_input)) {
-               status = dcesrv_input_process(dce_conn);
+               NTSTATUS status;
+               struct ndr_pull *ndr;
+               enum ndr_err_code ndr_err;
+               DATA_BLOB blob;
+               struct ncacn_packet *pkt;
+
+               blob = dce_conn->partial_input;
+               blob.length = dcerpc_get_frag_length(&blob);
+               blob = data_blob_talloc(dce_conn, blob.data, blob.length);
+               if (!blob.data) {
+                       data_blob_free(&dce_conn->partial_input);
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               dce_partial_advance(dce_conn, blob.length);
+
+               pkt = talloc(dce_conn, struct ncacn_packet);
+               if (!pkt) {
+                       data_blob_free(&blob);
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               ndr = ndr_pull_init_blob(&blob, pkt, lp_iconv_convenience(dce_conn->dce_ctx->lp_ctx));
+               if (!ndr) {
+                       data_blob_free(&blob);
+                       talloc_free(pkt);
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               if (!(CVAL(blob.data, DCERPC_DREP_OFFSET) & DCERPC_DREP_LE)) {
+                       ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
+               }
+
+               if (CVAL(blob.data, DCERPC_PFC_OFFSET) & DCERPC_PFC_FLAG_OBJECT_UUID) {
+                       ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
+               }
+
+               ndr_err = ndr_pull_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt);
+               TALLOC_FREE(ndr);
+               if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+                       data_blob_free(&blob);
+                       talloc_free(pkt);
+                       return ndr_map_error2ntstatus(ndr_err);
+               }
+
+               status = dcesrv_process_ncacn_packet(dce_conn, pkt, blob);
                if (!NT_STATUS_IS_OK(status)) {
                        return status;
                }
@@ -1394,6 +1479,38 @@ const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
        return NULL;
 }
 
+void dcerpc_server_init(struct loadparm_context *lp_ctx)
+{
+       static bool initialized;
+       extern NTSTATUS dcerpc_server_wkssvc_init(void);
+       extern NTSTATUS dcerpc_server_drsuapi_init(void);
+       extern NTSTATUS dcerpc_server_winreg_init(void);
+       extern NTSTATUS dcerpc_server_spoolss_init(void);
+       extern NTSTATUS dcerpc_server_epmapper_init(void);
+       extern NTSTATUS dcerpc_server_srvsvc_init(void);
+       extern NTSTATUS dcerpc_server_netlogon_init(void);
+       extern NTSTATUS dcerpc_server_rpcecho_init(void);
+       extern NTSTATUS dcerpc_server_unixinfo_init(void);
+       extern NTSTATUS dcerpc_server_samr_init(void);
+       extern NTSTATUS dcerpc_server_remote_init(void);
+       extern NTSTATUS dcerpc_server_lsa_init(void);
+       extern NTSTATUS dcerpc_server_browser_init(void);
+       init_module_fn static_init[] = { STATIC_dcerpc_server_MODULES };
+       init_module_fn *shared_init;
+
+       if (initialized) {
+               return;
+       }
+       initialized = true;
+
+       shared_init = load_samba_modules(NULL, lp_ctx, "dcerpc_server");
+
+       run_init_functions(static_init);
+       run_init_functions(shared_init);
+
+       talloc_free(shared_init);
+}
+
 /*
   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
@@ -1426,6 +1543,8 @@ _PUBLIC_ NTSTATUS dcesrv_init_ipc_context(TALLOC_CTX *mem_ctx, struct loadparm_c
        NTSTATUS status;
        struct dcesrv_context *dce_ctx;
 
+       dcerpc_server_init(lp_ctx);
+
        status = dcesrv_init_context(mem_ctx, lp_ctx, lp_dcerpc_endpoint_servers(lp_ctx), &dce_ctx);
        NT_STATUS_NOT_OK_RETURN(status);