From 18fba0d3dbbcf1d48d98b3a33252c57317090e22 Mon Sep 17 00:00:00 2001 From: Bostjan Meglic <103102696+bmeglic@users.noreply.github.com> Date: Sat, 28 Oct 2023 14:48:33 +0200 Subject: [PATCH] Delete authentication data on UE deregistration (#2706) * [AUSF] Fix removing UE context on authentication removal request AUSF crashed when trying to access ausf_ue->sm fields after they were already deleted. * [AMF] Delete UE authentication result after UE deregisters from 5G core Based on TS 29.509 - 5.2.2.2.5 Authentication Result Removal with 5G AKA method: In the case that the Purge of subscriber data in AMF after the UE deregisters from the network or the NAS SMC fails following the successful authentication in the registration procedure, the NF Service Consumer (AMF) requests the AUSF to inform the UDM to remove the authentication result. --- src/amf/gmm-sm.c | 148 ++++++++++++++++++++++++++++++++++------ src/ausf/ausf-sm.c | 3 + src/ausf/ausf-sm.h | 1 + src/ausf/nudm-handler.c | 2 +- src/ausf/ue-sm.c | 27 +++++++- 5 files changed, 157 insertions(+), 24 deletions(-) diff --git a/src/amf/gmm-sm.c b/src/amf/gmm-sm.c index 2dfd41128..0ed9ca095 100644 --- a/src/amf/gmm-sm.c +++ b/src/amf/gmm-sm.c @@ -275,6 +275,46 @@ void gmm_state_de_registered(ogs_fsm_t *s, amf_event_t *e) if (amf_ue->confirmation_url_for_5g_aka) ogs_free(amf_ue->confirmation_url_for_5g_aka); amf_ue->confirmation_url_for_5g_aka = NULL; + + if (state == AMF_RELEASE_SM_CONTEXT_NO_STATE || + state == AMF_UE_INITIATED_DE_REGISTERED) { + + if (PCF_AM_POLICY_ASSOCIATED(amf_ue)) { + r = amf_ue_sbi_discover_and_send( + OGS_SBI_SERVICE_TYPE_NPCF_AM_POLICY_CONTROL, + NULL, + amf_npcf_am_policy_control_build_delete, + amf_ue, state, NULL); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + } else { + r = nas_5gs_send_de_registration_accept(amf_ue); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + } + + } else if (state == + AMF_NETWORK_INITIATED_IMPLICIT_DE_REGISTERED || + state == + AMF_NETWORK_INITIATED_EXPLICIT_DE_REGISTERED) { + + int xact_count = amf_sess_xact_count(amf_ue); + amf_sbi_send_release_all_sessions(amf_ue, state); + + if (!AMF_SESSION_RELEASE_PENDING(amf_ue) && + amf_sess_xact_count(amf_ue) == xact_count) { + + if (PCF_AM_POLICY_ASSOCIATED(amf_ue)) { + r = amf_ue_sbi_discover_and_send( + OGS_SBI_SERVICE_TYPE_NPCF_AM_POLICY_CONTROL, + NULL, + amf_npcf_am_policy_control_build_delete, + amf_ue, state, NULL); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + } + } + } break; DEFAULT ogs_error("[%s] Invalid HTTP method [%s]", @@ -404,7 +444,16 @@ void gmm_state_de_registered(ogs_fsm_t *s, amf_event_t *e) */ if (state == AMF_RELEASE_SM_CONTEXT_NO_STATE || state == AMF_UE_INITIATED_DE_REGISTERED) { - if (PCF_AM_POLICY_ASSOCIATED(amf_ue)) { + + if (amf_ue->confirmation_url_for_5g_aka) { + r = amf_ue_sbi_discover_and_send( + OGS_SBI_SERVICE_TYPE_NAUSF_AUTH, + NULL, + amf_nausf_auth_build_authenticate_delete, + amf_ue, state, NULL); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + } else if (PCF_AM_POLICY_ASSOCIATED(amf_ue)) { r = amf_ue_sbi_discover_and_send( OGS_SBI_SERVICE_TYPE_NPCF_AM_POLICY_CONTROL, NULL, @@ -756,6 +805,46 @@ void gmm_state_registered(ogs_fsm_t *s, amf_event_t *e) if (amf_ue->confirmation_url_for_5g_aka) ogs_free(amf_ue->confirmation_url_for_5g_aka); amf_ue->confirmation_url_for_5g_aka = NULL; + + if (state == AMF_RELEASE_SM_CONTEXT_NO_STATE || + state == AMF_UE_INITIATED_DE_REGISTERED) { + + if (PCF_AM_POLICY_ASSOCIATED(amf_ue)) { + r = amf_ue_sbi_discover_and_send( + OGS_SBI_SERVICE_TYPE_NPCF_AM_POLICY_CONTROL, + NULL, + amf_npcf_am_policy_control_build_delete, + amf_ue, state, NULL); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + } else { + r = nas_5gs_send_de_registration_accept(amf_ue); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + } + + } else if (state == + AMF_NETWORK_INITIATED_IMPLICIT_DE_REGISTERED || + state == + AMF_NETWORK_INITIATED_EXPLICIT_DE_REGISTERED) { + + int xact_count = amf_sess_xact_count(amf_ue); + amf_sbi_send_release_all_sessions(amf_ue, state); + + if (!AMF_SESSION_RELEASE_PENDING(amf_ue) && + amf_sess_xact_count(amf_ue) == xact_count) { + + if (PCF_AM_POLICY_ASSOCIATED(amf_ue)) { + r = amf_ue_sbi_discover_and_send( + OGS_SBI_SERVICE_TYPE_NPCF_AM_POLICY_CONTROL, + NULL, + amf_npcf_am_policy_control_build_delete, + amf_ue, state, NULL); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + } + } + } break; DEFAULT ogs_error("[%s] Invalid HTTP method [%s]", @@ -874,42 +963,57 @@ void gmm_state_registered(ogs_fsm_t *s, amf_event_t *e) * 1. Implicit Timer Expiration * 2. UDM_SDM_Unsubscribe * 3. UDM_UECM_Deregisration - * 4. PDU session release request - * 5. PDUSessionResourceReleaseCommand + + * 4. Authentication Result Removal + * 5. PDU session release request + * 6. PDUSessionResourceReleaseCommand + * PDU session release command - * 6. PDUSessionResourceReleaseResponse - * 7. AM_Policy_Association_Termination + * 7. PDUSessionResourceReleaseResponse + * 8. AM_Policy_Association_Termination * * - AMF_NETWORK_INITIATED_EXPLICIT_DE_REGISTERED * 1. UDM_UECM_DeregistrationNotification * 2. Deregistration request * 3. UDM_SDM_Unsubscribe * 4. UDM_UECM_Deregisration - * 5. PDU session release request - * 6. PDUSessionResourceReleaseCommand + + * 5. Authentication Result Removal + * 6. PDU session release request + * 7. PDUSessionResourceReleaseCommand + * PDU session release command - * 7. PDUSessionResourceReleaseResponse - * 8. AM_Policy_Association_Termination - * 9. Deregistration accept - * 10. Signalling Connecion Release + * 8. PDUSessionResourceReleaseResponse + * 9. AM_Policy_Association_Termination + * 10. Deregistration accept + * 11. Signalling Connecion Release */ if (state == AMF_NETWORK_INITIATED_IMPLICIT_DE_REGISTERED || state == AMF_NETWORK_INITIATED_EXPLICIT_DE_REGISTERED) { - amf_sbi_send_release_all_sessions(amf_ue, state); + if (amf_ue->confirmation_url_for_5g_aka) { + r = amf_ue_sbi_discover_and_send( + OGS_SBI_SERVICE_TYPE_NAUSF_AUTH, + NULL, + amf_nausf_auth_build_authenticate_delete, + amf_ue, state, NULL); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); - if (!AMF_SESSION_RELEASE_PENDING(amf_ue) && - amf_sess_xact_count(amf_ue) == xact_count) { - if (PCF_AM_POLICY_ASSOCIATED(amf_ue)) { - r = amf_ue_sbi_discover_and_send( - OGS_SBI_SERVICE_TYPE_NPCF_AM_POLICY_CONTROL, - NULL, - amf_npcf_am_policy_control_build_delete, - amf_ue, state, NULL); - ogs_expect(r == OGS_OK); - ogs_assert(r != OGS_ERROR); + } else { + + amf_sbi_send_release_all_sessions(amf_ue, state); + + if (!AMF_SESSION_RELEASE_PENDING(amf_ue) && + amf_sess_xact_count(amf_ue) == xact_count) { + + if (PCF_AM_POLICY_ASSOCIATED(amf_ue)) { + r = amf_ue_sbi_discover_and_send( + OGS_SBI_SERVICE_TYPE_NPCF_AM_POLICY_CONTROL, + NULL, + amf_npcf_am_policy_control_build_delete, + amf_ue, state, NULL); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + } } } } else { diff --git a/src/ausf/ausf-sm.c b/src/ausf/ausf-sm.c index 9aab54a84..d2b7228dd 100644 --- a/src/ausf/ausf-sm.c +++ b/src/ausf/ausf-sm.c @@ -322,6 +322,9 @@ void ausf_state_operational(ogs_fsm_t *s, ausf_event_t *e) if (OGS_FSM_CHECK(&ausf_ue->sm, ausf_ue_state_exception)) { ogs_error("[%s] State machine exception", ausf_ue->suci); ausf_ue_remove(ausf_ue); + } else if (OGS_FSM_CHECK(&ausf_ue->sm, ausf_ue_state_deleted)) { + ogs_debug("[%s] AUSF-UE removed", ausf_ue->supi); + ausf_ue_remove(ausf_ue); } break; diff --git a/src/ausf/ausf-sm.h b/src/ausf/ausf-sm.h index aa1fd1bab..faa3344e3 100644 --- a/src/ausf/ausf-sm.h +++ b/src/ausf/ausf-sm.h @@ -33,6 +33,7 @@ void ausf_state_operational(ogs_fsm_t *s, ausf_event_t *e); void ausf_ue_state_initial(ogs_fsm_t *s, ausf_event_t *e); void ausf_ue_state_final(ogs_fsm_t *s, ausf_event_t *e); void ausf_ue_state_operational(ogs_fsm_t *s, ausf_event_t *e); +void ausf_ue_state_deleted(ogs_fsm_t *s, ausf_event_t *e); void ausf_ue_state_exception(ogs_fsm_t *s, ausf_event_t *e); #define ausf_sm_debug(__pe) \ diff --git a/src/ausf/nudm-handler.c b/src/ausf/nudm-handler.c index 360c75d63..f1f4470db 100644 --- a/src/ausf/nudm-handler.c +++ b/src/ausf/nudm-handler.c @@ -243,7 +243,7 @@ bool ausf_nudm_ueau_handle_auth_removal_ind(ausf_ue_t *ausf_ue, ogs_assert(ausf_ue); ogs_assert(stream); - ausf_ue_remove(ausf_ue); + OGS_FSM_TRAN(&ausf_ue->sm, &ausf_ue_state_deleted); memset(&sendmsg, 0, sizeof(sendmsg)); response = ogs_sbi_build_response(&sendmsg, OGS_SBI_HTTP_STATUS_NO_CONTENT); diff --git a/src/ausf/ue-sm.c b/src/ausf/ue-sm.c index 3c2b0c169..4a5c47af4 100644 --- a/src/ausf/ue-sm.c +++ b/src/ausf/ue-sm.c @@ -150,7 +150,8 @@ void ausf_ue_state_operational(ogs_fsm_t *s, ausf_event_t *e) SWITCH(message->h.service.name) CASE(OGS_SBI_SERVICE_NAME_NUDM_UEAU) if (message->res_status != OGS_SBI_HTTP_STATUS_OK && - message->res_status != OGS_SBI_HTTP_STATUS_CREATED) { + message->res_status != OGS_SBI_HTTP_STATUS_CREATED && + message->res_status != OGS_SBI_HTTP_STATUS_NO_CONTENT) { if (message->res_status == OGS_SBI_HTTP_STATUS_NOT_FOUND) { ogs_warn("[%s] Cannot find SUPI [%d]", ausf_ue->suci, message->res_status); @@ -213,6 +214,30 @@ void ausf_ue_state_operational(ogs_fsm_t *s, ausf_event_t *e) } } +void ausf_ue_state_deleted(ogs_fsm_t *s, ausf_event_t *e) +{ + ausf_ue_t *ausf_ue = NULL; + ogs_assert(s); + ogs_assert(e); + + ausf_sm_debug(e); + + ausf_ue = e->ausf_ue; + ogs_assert(ausf_ue); + + switch (e->h.id) { + case OGS_FSM_ENTRY_SIG: + break; + + case OGS_FSM_EXIT_SIG: + break; + + default: + ogs_error("[%s] Unknown event %s", ausf_ue->supi, ausf_event_get_name(e)); + break; + } +} + void ausf_ue_state_exception(ogs_fsm_t *s, ausf_event_t *e) { ausf_ue_t *ausf_ue = NULL;