selftest: Move simple-dc-steps.sh to correct folder
[kai/samba-autobuild/.git] / source4 / rpc_server / dcerpc_server.c
index 7cb8e11eeea86342df5685cbcef09583f9a1785a..3decc34451b396e41539614a3bd469f47ca713d4 100644 (file)
@@ -65,18 +65,34 @@ static struct dcesrv_assoc_group *dcesrv_assoc_group_find(struct dcesrv_context
 /*
   take a reference to an existing association group
  */
-static struct dcesrv_assoc_group *dcesrv_assoc_group_reference(TALLOC_CTX *mem_ctx,
-                                                              struct dcesrv_context *dce_ctx,
+static struct dcesrv_assoc_group *dcesrv_assoc_group_reference(struct dcesrv_connection *conn,
                                                               uint32_t id)
 {
+       const struct dcesrv_endpoint *endpoint = conn->endpoint;
+       enum dcerpc_transport_t transport =
+               dcerpc_binding_get_transport(endpoint->ep_description);
        struct dcesrv_assoc_group *assoc_group;
 
-       assoc_group = dcesrv_assoc_group_find(dce_ctx, id);
+       assoc_group = dcesrv_assoc_group_find(conn->dce_ctx, id);
        if (assoc_group == NULL) {
-               DEBUG(2,(__location__ ": Failed to find assoc_group 0x%08x\n", id));
+               DBG_NOTICE("Failed to find assoc_group 0x%08x\n", id);
+               return NULL;
+       }
+       if (assoc_group->transport != transport) {
+               const char *at =
+                       derpc_transport_string_by_transport(
+                               assoc_group->transport);
+               const char *ct =
+                       derpc_transport_string_by_transport(
+                               transport);
+
+               DBG_NOTICE("assoc_group 0x%08x (transport %s) "
+                          "is not available on transport %s",
+                          id, at, ct);
                return NULL;
        }
-       return talloc_reference(mem_ctx, assoc_group);
+
+       return talloc_reference(conn, assoc_group);
 }
 
 static int dcesrv_assoc_group_destructor(struct dcesrv_assoc_group *assoc_group)
@@ -93,13 +109,16 @@ static int dcesrv_assoc_group_destructor(struct dcesrv_assoc_group *assoc_group)
 /*
   allocate a new association group
  */
-static struct dcesrv_assoc_group *dcesrv_assoc_group_new(TALLOC_CTX *mem_ctx,
-                                                        struct dcesrv_context *dce_ctx)
+static struct dcesrv_assoc_group *dcesrv_assoc_group_new(struct dcesrv_connection *conn)
 {
+       struct dcesrv_context *dce_ctx = conn->dce_ctx;
+       const struct dcesrv_endpoint *endpoint = conn->endpoint;
+       enum dcerpc_transport_t transport =
+               dcerpc_binding_get_transport(endpoint->ep_description);
        struct dcesrv_assoc_group *assoc_group;
        int id;
 
-       assoc_group = talloc_zero(mem_ctx, struct dcesrv_assoc_group);
+       assoc_group = talloc_zero(conn, struct dcesrv_assoc_group);
        if (assoc_group == NULL) {
                return NULL;
        }
@@ -111,6 +130,7 @@ static struct dcesrv_assoc_group *dcesrv_assoc_group_new(TALLOC_CTX *mem_ctx,
                return NULL;
        }
 
+       assoc_group->transport = transport;
        assoc_group->id = id;
        assoc_group->dce_ctx = dce_ctx;
 
@@ -264,12 +284,14 @@ static struct dcesrv_call_state *dcesrv_find_fragmented_call(struct dcesrv_conne
 */
 _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
                                   const char *ep_name,
+                                  const char *ncacn_np_secondary_endpoint,
                                   const struct dcesrv_interface *iface,
                                   const struct security_descriptor *sd)
 {
        struct dcesrv_endpoint *ep;
        struct dcesrv_if_list *ifl;
        struct dcerpc_binding *binding;
+       struct dcerpc_binding *binding2 = NULL;
        bool add_ep = false;
        NTSTATUS status;
        enum dcerpc_transport_t transport;
@@ -334,6 +356,22 @@ _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
                }
        }
 
+       if (transport == NCACN_NP && ncacn_np_secondary_endpoint != NULL) {
+               enum dcerpc_transport_t transport2;
+
+               status = dcerpc_parse_binding(dce_ctx,
+                                             ncacn_np_secondary_endpoint,
+                                             &binding2);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(0, ("Trouble parsing 2nd binding string '%s'\n",
+                                 ncacn_np_secondary_endpoint));
+                       return status;
+               }
+
+               transport2 = dcerpc_binding_get_transport(binding2);
+               SMB_ASSERT(transport2 == transport);
+       }
+
        /* see if the interface is already registered on the endpoint */
        if (find_interface_by_binding(dce_ctx, binding, iface)!=NULL) {
                DEBUG(0,("dcesrv_interface_register: interface '%s' already registered on endpoint '%s'\n",
@@ -375,6 +413,7 @@ _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
                }
                ZERO_STRUCTP(ep);
                ep->ep_description = talloc_move(ep, &binding);
+               ep->ep_2nd_description = talloc_move(ep, &binding2);
                add_ep = true;
 
                /* add mgmt interface */
@@ -500,7 +539,7 @@ _PUBLIC_ NTSTATUS dcesrv_auth_session_key(struct dcesrv_call_state *call,
                                          DATA_BLOB *session_key)
 {
        struct dcesrv_auth *auth = call->auth_state;
-
+       SMB_ASSERT(auth->auth_finished);
        return dcesrv_session_info_session_key(auth, session_key);
 }
 
@@ -517,6 +556,8 @@ _PUBLIC_ NTSTATUS dcesrv_transport_session_key(struct dcesrv_call_state *call,
        struct dcesrv_auth *auth = call->auth_state;
        NTSTATUS status;
 
+       SMB_ASSERT(auth->auth_finished);
+
        if (auth->session_key_fn == NULL) {
                return NT_STATUS_NO_USER_SESSION_KEY;
        }
@@ -597,6 +638,17 @@ static NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
        p->max_xmit_frag = 5840;
        p->max_total_request_size = DCERPC_NCACN_REQUEST_DEFAULT_MAX_SIZE;
 
+       p->support_hdr_signing = lpcfg_parm_bool(dce_ctx->lp_ctx,
+                                                NULL,
+                                                "dcesrv",
+                                                "header signing",
+                                                true);
+       p->max_auth_states = lpcfg_parm_ulong(dce_ctx->lp_ctx,
+                                             NULL,
+                                             "dcesrv",
+                                             "max auth states",
+                                             2049);
+
        auth = dcesrv_auth_create(p);
        if (auth == NULL) {
                talloc_free(p);
@@ -660,17 +712,21 @@ static void dcesrv_call_set_list(struct dcesrv_call_state *call,
 static void dcesrv_call_disconnect_after(struct dcesrv_call_state *call,
                                         const char *reason)
 {
+       struct dcesrv_auth *a = NULL;
+
        if (call->conn->terminate != NULL) {
                return;
        }
 
        call->conn->allow_bind = false;
        call->conn->allow_alter = false;
-       call->conn->allow_auth3 = false;
-       call->conn->allow_request = false;
 
        call->conn->default_auth_state->auth_invalid = true;
 
+       for (a = call->conn->auth_states; a != NULL; a = a->next) {
+               a->auth_invalid = true;
+       }
+
        call->terminate_reason = talloc_strdup(call, reason);
        if (call->terminate_reason == NULL) {
                call->terminate_reason = __location__;
@@ -783,44 +839,31 @@ static void dcesrv_prepare_context_auth(struct dcesrv_call_state *dce_call)
                                        context->allow_connect);
 }
 
-NTSTATUS dcesrv_interface_bind_require_integrity(struct dcesrv_call_state *dce_call,
+NTSTATUS dcesrv_interface_bind_require_integrity(struct dcesrv_connection_context *context,
                                                 const struct dcesrv_interface *iface)
 {
-       if (dce_call->context == NULL) {
-               return NT_STATUS_INTERNAL_ERROR;
-       }
-
        /*
         * For connection oriented DCERPC DCERPC_AUTH_LEVEL_PACKET (4)
         * has the same behavior as DCERPC_AUTH_LEVEL_INTEGRITY (5).
         */
-       dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_PACKET;
+       context->min_auth_level = DCERPC_AUTH_LEVEL_PACKET;
        return NT_STATUS_OK;
 }
 
-NTSTATUS dcesrv_interface_bind_require_privacy(struct dcesrv_call_state *dce_call,
+NTSTATUS dcesrv_interface_bind_require_privacy(struct dcesrv_connection_context *context,
                                               const struct dcesrv_interface *iface)
 {
-       if (dce_call->context == NULL) {
-               return NT_STATUS_INTERNAL_ERROR;
-       }
-
-       dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
+       context->min_auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
        return NT_STATUS_OK;
 }
 
-_PUBLIC_ NTSTATUS dcesrv_interface_bind_reject_connect(struct dcesrv_call_state *dce_call,
+_PUBLIC_ NTSTATUS dcesrv_interface_bind_reject_connect(struct dcesrv_connection_context *context,
                                                       const struct dcesrv_interface *iface)
 {
-       struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
-       const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
+       struct loadparm_context *lp_ctx = context->conn->dce_ctx->lp_ctx;
+       const struct dcesrv_endpoint *endpoint = context->conn->endpoint;
        enum dcerpc_transport_t transport =
                dcerpc_binding_get_transport(endpoint->ep_description);
-       struct dcesrv_connection_context *context = dce_call->context;
-
-       if (context == NULL) {
-               return NT_STATUS_INTERNAL_ERROR;
-       }
 
        if (transport == NCALRPC) {
                context->allow_connect = true;
@@ -839,18 +882,13 @@ _PUBLIC_ NTSTATUS dcesrv_interface_bind_reject_connect(struct dcesrv_call_state
        return NT_STATUS_OK;
 }
 
-_PUBLIC_ NTSTATUS dcesrv_interface_bind_allow_connect(struct dcesrv_call_state *dce_call,
+_PUBLIC_ NTSTATUS dcesrv_interface_bind_allow_connect(struct dcesrv_connection_context *context,
                                                      const struct dcesrv_interface *iface)
 {
-       struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
-       const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
+       struct loadparm_context *lp_ctx = context->conn->dce_ctx->lp_ctx;
+       const struct dcesrv_endpoint *endpoint = context->conn->endpoint;
        enum dcerpc_transport_t transport =
                dcerpc_binding_get_transport(endpoint->ep_description);
-       struct dcesrv_connection_context *context = dce_call->context;
-
-       if (context == NULL) {
-               return NT_STATUS_INTERNAL_ERROR;
-       }
 
        if (transport == NCALRPC) {
                context->allow_connect = true;
@@ -970,7 +1008,7 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
        uint32_t extra_flags = 0;
        uint16_t max_req = 0;
        uint16_t max_rep = 0;
-       const char *ep_prefix = "";
+       struct dcerpc_binding *ep_2nd_description = NULL;
        const char *endpoint = NULL;
        struct dcesrv_auth *auth = call->auth_state;
        struct dcerpc_ack_ctx *ack_ctx_list = NULL;
@@ -1016,11 +1054,9 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
         */
        if (call->pkt.u.bind.assoc_group_id != 0) {
                call->conn->assoc_group = dcesrv_assoc_group_reference(call->conn,
-                                                                      call->conn->dce_ctx,
                                                                       call->pkt.u.bind.assoc_group_id);
        } else {
-               call->conn->assoc_group = dcesrv_assoc_group_new(call->conn,
-                                                                call->conn->dce_ctx);
+               call->conn->assoc_group = dcesrv_assoc_group_new(call->conn);
        }
 
        /*
@@ -1046,8 +1082,7 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
        if (call->conn->assoc_group == NULL &&
            !call->conn->endpoint->use_single_process) {
                call->conn->assoc_group
-                       = dcesrv_assoc_group_new(call->conn,
-                                                call->conn->dce_ctx);
+                       = dcesrv_assoc_group_new(call->conn);
        }
        if (call->conn->assoc_group == NULL) {
                return dcesrv_bind_nak(call, 0);
@@ -1102,14 +1137,17 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
                a->result = DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK;
                a->reason.negotiate = 0;
                if (features & DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING) {
-                       /* not supported yet */
+                       if (call->conn->max_auth_states != 0) {
+                               a->reason.negotiate |=
+                               DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING;
+                       }
                }
                if (features & DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN) {
                        a->reason.negotiate |=
                                DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN;
                }
 
-               call->conn->bind_time_features = a->reason.negotiate;
+               call->conn->assoc_group->bind_time_features = a->reason.negotiate;
        }
 
        /*
@@ -1183,29 +1221,19 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
        pkt->u.bind_ack.max_recv_frag = call->conn->max_recv_frag;
        pkt->u.bind_ack.assoc_group_id = call->conn->assoc_group->id;
 
+       ep_2nd_description = call->conn->endpoint->ep_2nd_description;
+       if (ep_2nd_description == NULL) {
+               ep_2nd_description = call->conn->endpoint->ep_description;
+       }
+
        endpoint = dcerpc_binding_get_string_option(
-                               call->conn->endpoint->ep_description,
+                               ep_2nd_description,
                                "endpoint");
        if (endpoint == NULL) {
                endpoint = "";
        }
 
-       if (strncasecmp(endpoint, "\\pipe\\", 6) == 0) {
-               /*
-                * TODO: check if this is really needed
-                *
-                * Or if we should fix this in our idl files.
-                */
-               ep_prefix = "\\PIPE\\";
-               endpoint += 6;
-       }
-
-       pkt->u.bind_ack.secondary_address = talloc_asprintf(call, "%s%s",
-                                                          ep_prefix,
-                                                          endpoint);
-       if (pkt->u.bind_ack.secondary_address == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
+       pkt->u.bind_ack.secondary_address = endpoint;
        pkt->u.bind_ack.num_results = call->pkt.u.bind.num_contexts;
        pkt->u.bind_ack.ctx_list = ack_ctx_list;
        pkt->u.bind_ack.auth_info = data_blob_null;
@@ -1298,7 +1326,7 @@ static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
        struct tevent_req *subreq = NULL;
        NTSTATUS status;
 
-       if (!call->conn->allow_auth3) {
+       if (!auth->auth_started) {
                return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
        }
 
@@ -1519,7 +1547,6 @@ static NTSTATUS dcesrv_check_or_create_context(struct dcesrv_call_state *call,
        context->context_id = ctx->context_id;
        context->iface = iface;
        context->transfer_syntax = *selected_transfer;
-       context->private_data = NULL;
        DLIST_ADD(call->conn->contexts, context);
        call->context = context;
        talloc_set_destructor(context, dcesrv_connection_context_destructor);
@@ -1531,7 +1558,7 @@ static NTSTATUS dcesrv_check_or_create_context(struct dcesrv_call_state *call,
         */
        call->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
 
-       status = iface->bind(call, iface, if_version);
+       status = iface->bind(context, iface);
        call->context = NULL;
        if (!NT_STATUS_IS_OK(status)) {
                /* we don't want to trigger the iface->unbind() hook */
@@ -1806,8 +1833,7 @@ static void dcesrv_save_call(struct dcesrv_call_state *call, const char *why)
 static NTSTATUS dcesrv_check_verification_trailer(struct dcesrv_call_state *call)
 {
        TALLOC_CTX *frame = talloc_stackframe();
-       const struct dcesrv_auth *auth = call->auth_state;
-       const uint32_t bitmask1 = auth->client_hdr_signing ?
+       const uint32_t bitmask1 = call->conn->client_hdr_signing ?
                DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING : 0;
        const struct dcerpc_sec_vt_pcontext pcontext = {
                .abstract_syntax = call->context->iface->syntax_id,
@@ -1852,7 +1878,7 @@ static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
        struct ndr_pull *pull;
        NTSTATUS status;
 
-       if (!call->conn->allow_request) {
+       if (!auth->auth_finished) {
                return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
        }
 
@@ -2006,6 +2032,10 @@ static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
        NTSTATUS status;
        struct dcesrv_call_state *call;
        struct dcesrv_call_state *existing = NULL;
+       size_t num_auth_ctx = 0;
+       enum dcerpc_AuthType auth_type = 0;
+       enum dcerpc_AuthLevel auth_level = 0;
+       uint32_t auth_context_id = 0;
 
        call = talloc_zero(dce_conn, struct dcesrv_call_state);
        if (!call) {
@@ -2024,7 +2054,73 @@ static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
        talloc_steal(call, blob.data);
        call->pkt = *pkt;
 
-       call->auth_state = dce_conn->default_auth_state;
+       if (dce_conn->max_auth_states == 0) {
+               call->auth_state = dce_conn->default_auth_state;
+       } else if (call->pkt.auth_length == 0) {
+               if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
+                   dce_conn->default_auth_level_connect != NULL)
+               {
+                       call->auth_state = dce_conn->default_auth_level_connect;
+               } else {
+                       call->auth_state = dce_conn->default_auth_state;
+               }
+       }
+
+       if (call->auth_state == NULL) {
+               struct dcesrv_auth *a = NULL;
+
+               auth_type = dcerpc_get_auth_type(&blob);
+               auth_level = dcerpc_get_auth_level(&blob);
+               auth_context_id = dcerpc_get_auth_context_id(&blob);
+
+               if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
+                       dce_conn->default_auth_level_connect = NULL;
+                       if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
+                               dce_conn->got_explicit_auth_level_connect = true;
+                       }
+               }
+
+               for (a = dce_conn->auth_states; a != NULL; a = a->next) {
+                       num_auth_ctx++;
+
+                       if (a->auth_type != auth_type) {
+                               continue;
+                       }
+                       if (a->auth_finished && a->auth_level != auth_level) {
+                               continue;
+                       }
+                       if (a->auth_context_id != auth_context_id) {
+                               continue;
+                       }
+
+                       DLIST_PROMOTE(dce_conn->auth_states, a);
+                       call->auth_state = a;
+                       break;
+               }
+       }
+
+       if (call->auth_state == NULL) {
+               struct dcesrv_auth *a = NULL;
+
+               if (num_auth_ctx >= dce_conn->max_auth_states) {
+                       return dcesrv_fault_disconnect(call,
+                                       DCERPC_NCA_S_PROTO_ERROR);
+               }
+
+               a = dcesrv_auth_create(dce_conn);
+               if (a == NULL) {
+                       talloc_free(call);
+                       return NT_STATUS_NO_MEMORY;
+               }
+               DLIST_ADD(dce_conn->auth_states, a);
+               if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
+                       /*
+                        * This can never be valid.
+                        */
+                       a->auth_invalid = true;
+               }
+               call->auth_state = a;
+       }
 
        talloc_set_destructor(call, dcesrv_call_dequeue);
 
@@ -2039,7 +2135,10 @@ static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
        /* we have to check the signing here, before combining the
           pdus */
        if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
-               if (!call->conn->allow_request) {
+               dcesrv_default_auth_state_prepare_request(call);
+
+               if (call->auth_state->auth_started &&
+                   !call->auth_state->auth_finished) {
                        return dcesrv_fault_disconnect(call,
                                        DCERPC_NCA_S_PROTO_ERROR);
                }
@@ -2467,6 +2566,7 @@ const struct dcesrv_critical_sizes *dcerpc_module_version(void)
 static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
 {
        struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
+       struct dcesrv_auth *a = NULL;
        struct stream_connection *srv_conn;
        srv_conn = talloc_get_type(dce_conn->transport.private_data,
                                   struct stream_connection);
@@ -2476,12 +2576,14 @@ static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, cons
        dce_conn->wait_private = NULL;
 
        dce_conn->allow_bind = false;
-       dce_conn->allow_auth3 = false;
        dce_conn->allow_alter = false;
-       dce_conn->allow_request = false;
 
        dce_conn->default_auth_state->auth_invalid = true;
 
+       for (a = dce_conn->auth_states; a != NULL; a = a->next) {
+               a->auth_invalid = true;
+       }
+
        if (dce_conn->pending_call_list == NULL) {
                char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
 
@@ -3120,7 +3222,7 @@ static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx,
                for (iface = e->interface_list; iface; iface = iface->next) {
                        DEBUGADD(0, ("%s ", iface->iface.name));
                }
-               DEBUGADD(0, ("failed - %s",
+               DEBUGADD(0, ("failed - %s\n",
                             nt_errstr(status)));
                return status;
        }
@@ -3235,6 +3337,7 @@ NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
 _PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
 {
        struct dcesrv_auth *auth = dce_call->auth_state;
+       SMB_ASSERT(auth->auth_finished);
        return auth->session_info->credentials;
 }
 
@@ -3245,6 +3348,7 @@ _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
 {
        struct dcesrv_auth *auth = dce_call->auth_state;
        enum security_user_level level;
+       SMB_ASSERT(auth->auth_finished);
        level = security_session_user_level(auth->session_info, NULL);
        return level >= SECURITY_USER;
 }
@@ -3255,6 +3359,7 @@ _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
 _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
 {
        struct dcesrv_auth *auth = dce_call->auth_state;
+       SMB_ASSERT(auth->auth_finished);
        return auth->session_info->info->account_name;
 }
 
@@ -3264,6 +3369,7 @@ _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call
 _PUBLIC_ struct auth_session_info *dcesrv_call_session_info(struct dcesrv_call_state *dce_call)
 {
        struct dcesrv_auth *auth = dce_call->auth_state;
+       SMB_ASSERT(auth->auth_finished);
        return auth->session_info;
 }
 
@@ -3276,6 +3382,8 @@ _PUBLIC_ void dcesrv_call_auth_info(struct dcesrv_call_state *dce_call,
 {
        struct dcesrv_auth *auth = dce_call->auth_state;
 
+       SMB_ASSERT(auth->auth_finished);
+
        if (auth_type != NULL) {
                *auth_type = auth->auth_type;
        }