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.
This commit is contained in:
Bostjan Meglic 2023-10-28 14:48:33 +02:00 committed by GitHub
parent b2be7393a0
commit 18fba0d3db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 157 additions and 24 deletions

View File

@ -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 {

View File

@ -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;

View File

@ -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) \

View File

@ -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);

View File

@ -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;