Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(amf): Re-Attempt Authentication during subscriberdb lock #11454

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions lte/gateway/c/core/oai/include/amf_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
#define MAX_APN_CORRECTION_MAP_LIST 10
#define AMF_S_NSSAI_ST_DEFAULT_VALUE 1
#define AMF_S_NSSAI_SD_INVALID_VALUE 0xffffff
#define AUTHENTICATION_COUNTER_MAX_RETRY "AUTHENTICATION_MAX_RETRY"
#define AUTHENTICATION_RETRY_TIMER_EXPIRY_MSECS "AUTHENTICATION_TIMER_EXPIRY"

#define AMF_CONFIG_STRING_AMF_CONFIG "AMF"
#define AMF_CONFIG_STRING_DEFAULT_DNS_IPV4_ADDRESS "DEFAULT_DNS_IPV4_ADDRESS"
Expand Down Expand Up @@ -179,6 +181,8 @@ typedef struct amf_config_s {
} ipv4;
bstring amf_name;
bstring default_dnn;
uint32_t auth_retry_interval;
uint32_t auth_retry_max_count;
} amf_config_t;

int amf_app_init(amf_config_t*);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ struct amf_procedures_t;
#define PDU_ADDR_IPV4_LEN 0x4
#define GNB_IPV4_ADDR_LEN 4
#define GNB_TEID_LEN 4

#define DIAMETER_TOO_BUSY 3004
#define NON_AMF_3GPP_ACCESS 2
#define AMF_3GPP_ACCESS_AND_NON_AMF_3GPP_ACCESS 3

Expand Down Expand Up @@ -351,6 +351,8 @@ typedef struct amf_context_s {
apn_config_profile_t apn_config_profile;

amf_nas_message_decode_status_t decode_status;
nas5g_timer_t auth_retry_timer;
uint32_t auth_retry_count = 0;
} amf_context_t;

// Amf-Map Declarations:
Expand Down
79 changes: 57 additions & 22 deletions lte/gateway/c/core/oai/tasks/amf/amf_authentication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,6 @@ static int start_authentication_information_procedure(
OAILOG_FUNC_IN(LOG_NAS_AMF);

int rc = RETURNerror;
char imsi_str[IMSI_BCD_DIGITS_MAX + 1];
uint8_t snni[40] = {0};

amf_ue_ngap_id_t ue_id =
PARENT_STRUCT(amf_context, ue_m5gmm_context_s, amf_context)
Expand All @@ -122,48 +120,89 @@ static int start_authentication_information_procedure(
auth_info_proc->ue_id = ue_id;
auth_info_proc->resync = auth_info_proc->request_sent;

bool is_initial_req = !(auth_info_proc->request_sent);
auth_info_proc->request_sent = true;
rc = amf_authentication_request_sent(ue_id);
if (rc != RETURNok) {
OAILOG_WARNING(LOG_NAS_AMF,
"AMF-PROC - Failed authentication request for ue_id "
"= " AMF_UE_NGAP_ID_FMT "\n",
ue_id);
OAILOG_FUNC_RETURN(LOG_NAS_AMF, rc);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to add a log here along with IMSI/ue_id. Helps in debugging

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment addressed.

}

OAILOG_FUNC_RETURN(LOG_NAS_AMF, RETURNok);
}

status_code_e amf_authentication_request_sent(amf_ue_ngap_id_t ue_id) {
ue_m5gmm_context_s* ue_mm_context = nullptr;
amf_context_t* amf_context = nullptr;
char imsi_str[IMSI_BCD_DIGITS_MAX + 1];
int rc = RETURNerror;
ue_mm_context = amf_ue_context_exists_amf_ue_ngap_id(ue_id);
uint8_t snni[40] = {0};
if (!ue_mm_context) {
OAILOG_WARNING(LOG_NAS_AMF,
"AMF-PROC - Failed authentication request for UE ID "
"= " AMF_UE_NGAP_ID_FMT
"due to NULL"
"ue_context\n",
ue_id);
OAILOG_FUNC_RETURN(LOG_NAS_AMF, RETURNerror);
}
amf_context = &ue_mm_context->amf_context;
if (!amf_context) {
OAILOG_WARNING(LOG_NAS_AMF,
"AMF-PROC - Failed authentication request for UE ID "
"= " AMF_UE_NGAP_ID_FMT
"due to NULL"
"amf_context\n",
ue_id);
OAILOG_FUNC_RETURN(LOG_NAS_AMF, RETURNerror);
}
nas5g_amf_auth_proc_t* auth_proc =
get_nas5g_common_procedure_authentication(amf_context);

if (!auth_proc) {
OAILOG_WARNING(LOG_NAS_AMF, "authentication procedure not present\n");
OAILOG_FUNC_RETURN(LOG_NAS_AMF, RETURNerror);
}
IMSI64_TO_STRING(amf_context->imsi64, imsi_str, IMSI_LENGTH);

rc = calculate_amf_serving_network_name(amf_context, snni);
if (rc != RETURNok) {
OAILOG_FUNC_RETURN(LOG_NAS_AMF, rc);
OAILOG_FUNC_RETURN(LOG_NAS_AMF, RETURNerror);
}

if (is_initial_req) {
if (!(auth_proc->auts.data)) {
OAILOG_INFO(LOG_AMF_APP,
"Sending msg(grpc) to :[subscriberdb] for ue: [%s] auth-info\n",
imsi_str);
AMFClientServicer::getInstance().get_subs_auth_info(
imsi_str, IMSI_LENGTH, reinterpret_cast<const char*>(snni), ue_id);
} else if (auts->data) {
} else if (auth_proc->auts.data) {
OAILOG_INFO(
LOG_AMF_APP,
"Sending msg(grpc) to :[subscriberdb] for ue: [%s] auth-info-resync\n",
imsi_str);
AMFClientServicer::getInstance().get_subs_auth_info_resync(
imsi_str, IMSI_LENGTH, reinterpret_cast<const char*>(snni), auts->data,
RAND_LENGTH_OCTETS + AUTS_LENGTH, ue_id);
imsi_str, IMSI_LENGTH, reinterpret_cast<const char*>(snni),
auth_proc->auts.data, RAND_LENGTH_OCTETS + AUTS_LENGTH, ue_id);
}

OAILOG_FUNC_RETURN(LOG_NAS_AMF, RETURNok);
}

static int start_authentication_information_procedure_synch(
amf_context_t* amf_context, nas5g_amf_auth_proc_t* const auth_proc,
const_bstring auts) {
amf_context_t* amf_context, nas5g_amf_auth_proc_t* const auth_proc) {
OAILOG_FUNC_IN(LOG_NAS_AMF);

// Ask upper layer to fetch new security context
nas5g_auth_info_proc_t* auth_info_proc =
get_nas5g_cn_procedure_auth_info(amf_context);

if (!auth_info_proc) {
auth_info_proc = nas5g_new_cn_auth_info_procedure(amf_context);
auth_info_proc->request_sent = true;
start_authentication_information_procedure(amf_context, auth_proc, auts);
start_authentication_information_procedure(amf_context, auth_proc,
&auth_proc->auts);
OAILOG_FUNC_RETURN(LOG_NAS_EMM, RETURNok);
}

Expand Down Expand Up @@ -761,28 +800,24 @@ int amf_proc_authentication_failure(amf_ue_ngap_id_t ue_id,
if (MAX_SYNC_FAILURES <= auth_proc->retry_sync_failure) {
rc = amf_auth_auth_rej(ue_id);
} else {
struct tagbstring resync_param;
resync_param.data = (unsigned char*)calloc(1, RESYNC_PARAM_LENGTH);
if (resync_param.data == NULL) {
auth_proc->auts.data = (unsigned char*)calloc(1, RESYNC_PARAM_LENGTH);
if (auth_proc->auts.data == NULL) {
OAILOG_ERROR(LOG_NAS_AMF,
"Sending authentication reject with cause "
"AMF_CAUSE_SYNCH_FAILURE\n");
rc = amf_auth_auth_rej(ue_id);
OAILOG_FUNC_RETURN(LOG_NAS_EMM, rc);
}

memcpy(resync_param.data,
memcpy(auth_proc->auts.data,
(amf_ctx->_vector[amf_ctx->_security.vector_index].rand),
RAND_LENGTH_OCTETS);

memcpy((resync_param.data + RAND_LENGTH_OCTETS),
memcpy((auth_proc->auts.data + RAND_LENGTH_OCTETS),
msg->auth_failure_ie.authentication_failure_info->data,
AUTS_LENGTH);

start_authentication_information_procedure_synch(amf_ctx, auth_proc,
&resync_param);
free_wrapper(reinterpret_cast<void**>(&resync_param.data));

start_authentication_information_procedure_synch(amf_ctx, auth_proc);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is auth_proc->auts.data freed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

free_wrapper(reinterpret_cast<void**>(&auth_proc->auts.data));

amf_ctx_clear_auth_vectors(amf_ctx);
}

Expand Down
3 changes: 2 additions & 1 deletion lte/gateway/c/core/oai/tasks/amf/amf_authentication.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ typedef struct nas5g_amf_auth_proc_s {
int amf_cause;
int retry_sync_failure;
#define MAX_SYNC_FAILURES 2
struct tagbstring auts;
} nas5g_amf_auth_proc_t;

typedef struct nas5g_auth_info_proc_s {
Expand Down Expand Up @@ -77,7 +78,7 @@ int amf_send_authentication_request(amf_context_t* amf_context,

// To be called when authentication is successful from subscriberdb
int amf_authentication_proc_success(amf_context_t* amf_context);

status_code_e amf_authentication_request_sent(amf_ue_ngap_id_t ue_id);
int amf_nas_proc_authentication_info_answer(itti_amf_subs_auth_info_ans_t* aia);
nas5g_amf_auth_proc_t* get_nas5g_common_procedure_authentication(
const amf_context_t* const ctxt);
Expand Down
11 changes: 11 additions & 0 deletions lte/gateway/c/core/oai/tasks/amf/amf_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,17 @@ int amf_config_parse_file(amf_config_t* config_pP,
(const char**)&astring)) {
config_pP->default_dnn = bfromcstr(astring);
}
// DEFAULT AUTH MAX RETRY COUNT
if (config_setting_lookup_string(
setting_amf, AUTHENTICATION_COUNTER_MAX_RETRY, &astring)) {
config_pP->auth_retry_max_count = (uint32_t)atoi(astring);
}

// DEFAULT AUTH RETRY TIMER EXPIRES MSECS
if (config_setting_lookup_string(
setting_amf, AUTHENTICATION_RETRY_TIMER_EXPIRY_MSECS, &astring)) {
config_pP->auth_retry_interval = (uint32_t)atoi(astring);
}

// AMF_PLMN_SUPPORT SETTING
setting = config_setting_get_member(setting_amf,
Expand Down
116 changes: 105 additions & 11 deletions lte/gateway/c/core/oai/tasks/amf/nas_proc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ extern task_zmq_ctx_s amf_app_task_zmq_ctx;
AmfMsg amf_msg_obj;
extern std::unordered_map<imsi64_t, guti_and_amf_id_t> amf_supi_guti_map;
static int identification_t3570_handler(zloop_t* loop, int timer_id, void* arg);
static int subs_auth_retry(zloop_t* loop, int timer_id, void* output);
int nas_proc_establish_ind(const amf_ue_ngap_id_t ue_id,
const bool is_mm_ctx_new,
const tai_t originating_tai, const ecgi_t ecgi,
Expand Down Expand Up @@ -413,10 +414,78 @@ int amf_nas_proc_auth_param_res(amf_ue_ngap_id_t amf_ue_ngap_id,
OAILOG_FUNC_RETURN(LOG_NAS_AMF, rc);
}

static int subs_auth_retry(zloop_t* loop, int timer_id, void* arg) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use status_code_e for return type

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hence it is tightly coupled with the existing timer code. will make it generic in the upcoming pr.

amf_ue_ngap_id_t ue_id = 0;
amf_context_t* amf_ctxt_p = nullptr;
int amf_cause = -1;
nas5g_auth_info_proc_t* auth_info_proc = nullptr;
int rc = RETURNerror;
ue_m5gmm_context_s* ue_mm_context = nullptr;
if (!amf_pop_timer_arg(timer_id, &ue_id)) {
OAILOG_WARNING(LOG_AMF_APP,
"auth_retry_timer: Invalid Timer Id expiration, Timer Id: "
"%d and UE id: " AMF_UE_NGAP_ID_FMT "\n",
timer_id, ue_id);
OAILOG_FUNC_RETURN(LOG_NAS_AMF, RETURNok);
}
ue_mm_context = amf_ue_context_exists_amf_ue_ngap_id(ue_id);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add NULL check for ue_mm_context and amf_ctxt_p

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment addressed.

if (!ue_mm_context) {
OAILOG_WARNING(
LOG_NAS_AMF,
"AMF-PROC - Failed authentication request for UE id " AMF_UE_NGAP_ID_FMT
"due to NULL"
"ue_context\n",
ue_id);
OAILOG_FUNC_RETURN(LOG_NAS_AMF, RETURNerror);
}
amf_ctxt_p = &ue_mm_context->amf_context;
if (!amf_ctxt_p) {
OAILOG_WARNING(LOG_NAS_AMF,
"AMF-PROC - Failed authentication request for UE "
"id= " AMF_UE_NGAP_ID_FMT
"due to NULL"
"amf_ctxt_p\n",
ue_id);
OAILOG_FUNC_RETURN(LOG_NAS_AMF, RETURNerror);
}
if (amf_ctxt_p->auth_retry_count < amf_config.auth_retry_max_count) {
amf_ctxt_p->auth_retry_count++;
OAILOG_INFO(LOG_AMF_APP,
"auth_retry_timer: Incrementing auth_retry_count to %u\n",
amf_ctxt_p->auth_retry_count);
rc = amf_authentication_request_sent(ue_id);
if (rc != RETURNok) {
OAILOG_FUNC_RETURN(LOG_NAS_AMF, RETURNerror);
}
amf_ctxt_p->auth_retry_timer.id =
amf_app_start_timer(amf_config.auth_retry_interval, TIMER_REPEAT_ONCE,
subs_auth_retry, ue_id);
} else {
auth_info_proc = get_nas5g_cn_procedure_auth_info(amf_ctxt_p);
OAILOG_ERROR(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

General comment: Add ue_id/IMSI in logs where ever possible

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment addressed.

LOG_NAS_AMF,
"auth_retry_timer is expired . Authentication reject with cause "
"AMF_UE_ILLEGAL for ue_id " AMF_UE_NGAP_ID_FMT "\n",
ue_id);
amf_cause = AMF_UE_ILLEGAL;

rc = amf_proc_registration_reject(ue_id, amf_cause);
if (rc != RETURNok) {
OAILOG_FUNC_RETURN(LOG_NAS_AMF, RETURNerror);
}
if (auth_info_proc) {
nas5g_delete_cn_procedure(amf_ctxt_p, &auth_info_proc->cn_proc);
}

amf_free_ue_context(ue_mm_context);
}
OAILOG_FUNC_RETURN(LOG_NAS_AMF, RETURNok);
}

int amf_nas_proc_authentication_info_answer(
itti_amf_subs_auth_info_ans_t* aia) {
imsi64_t imsi64 = INVALID_IMSI64;
int rc = RETURNerror;
int rc = RETURNok;
amf_context_t* amf_ctxt_p = NULL;
ue_m5gmm_context_s* ue_5gmm_context_p = NULL;
int amf_cause = -1;
Expand Down Expand Up @@ -446,8 +515,18 @@ int amf_nas_proc_authentication_info_answer(
"Received Authentication Information Answer from Subscriberdb for"
" UE ID = " AMF_UE_NGAP_ID_FMT,
amf_ue_ngap_id);

if (aia->auth_info.nb_of_vectors) {
nas5g_amf_auth_proc_t* auth_proc =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing NULL check for auth_proc

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment addressed.

get_nas5g_common_procedure_authentication(amf_ctxt_p);
if (auth_proc) {
free_wrapper(reinterpret_cast<void**>(&auth_proc->auts.data));
}
if ((NAS5G_TIMER_INACTIVE_ID != amf_ctxt_p->auth_retry_timer.id) &&
(0 != amf_ctxt_p->auth_retry_timer.id)) {
OAILOG_DEBUG(LOG_NAS_AMF, "Stopping: Timer auth_retry_timer.\n");
amf_app_stop_timer(amf_ctxt_p->auth_retry_timer.id);
amf_ctxt_p->auth_retry_timer.id = NAS5G_TIMER_INACTIVE_ID;
}
/*
* Check that list is not empty and contain at most MAX_EPS_AUTH_VECTORS
* elements
Expand All @@ -468,17 +547,32 @@ int amf_nas_proc_authentication_info_answer(
} else {
/* Get Auth Info Pro */
auth_info_proc = get_nas5g_cn_procedure_auth_info(amf_ctxt_p);
OAILOG_ERROR(LOG_NAS_AMF,
"result=%d, nb_of_vectors received is zero from subscriberdb",
aia->result);
amf_cause = AMF_UE_ILLEGAL;
rc = amf_proc_registration_reject(amf_ue_ngap_id, amf_cause);
if (auth_info_proc) {
nas5g_delete_cn_procedure(amf_ctxt_p, &auth_info_proc->cn_proc);
amf_ctxt_p->auth_retry_count = 0;
if (aia->result != DIAMETER_TOO_BUSY) {
if ((NAS5G_TIMER_INACTIVE_ID != amf_ctxt_p->auth_retry_timer.id) &&
(0 != amf_ctxt_p->auth_retry_timer.id)) {
OAILOG_DEBUG(LOG_NAS_AMF, "Stopping: Timer auth_retry_timer.\n");
amf_app_stop_timer(amf_ctxt_p->auth_retry_timer.id);
amf_ctxt_p->auth_retry_timer.id = NAS5G_TIMER_INACTIVE_ID;
}
OAILOG_ERROR(
LOG_NAS_AMF,
"result=%d, nb_of_vectors received is zero from subscriberdb",
aia->result);
amf_cause = AMF_UE_ILLEGAL;
rc = amf_proc_registration_reject(amf_ue_ngap_id, amf_cause);
if (auth_info_proc) {
nas5g_delete_cn_procedure(amf_ctxt_p, &auth_info_proc->cn_proc);
}
amf_free_ue_context(ue_5gmm_context_p);
OAILOG_FUNC_RETURN(LOG_NAS_AMF, rc);
} else {
amf_ctxt_p->auth_retry_timer.id =
amf_app_start_timer(amf_config.auth_retry_interval, TIMER_REPEAT_ONCE,
subs_auth_retry, aia->ue_id);
rc = RETURNok;
}
amf_free_ue_context(ue_5gmm_context_p);
}

OAILOG_FUNC_RETURN(LOG_NAS_AMF, rc);
}

Expand Down