Skip to content

Commit

Permalink
fix(amf): Re-Attempt Authentication during subscriberdb lock (magma#1…
Browse files Browse the repository at this point in the history
…1454)

* fix(amf): handle and proper response the error code from subscriberdb during authentication

Signed-off-by: RahulKalsangra <rahul.kalsangra@wavelabs.ai>

* Addressed review comment (R1)

Signed-off-by: RahulKalsangra <rahul.kalsangra@wavelabs.ai>

* Addressed review comment (R2)

Signed-off-by: RahulKalsangra <rahul.kalsangra@wavelabs.ai>
  • Loading branch information
RahulKalsangra authored and vikramgreddy committed Mar 23, 2022
1 parent 6a9ff1c commit 16afb53
Show file tree
Hide file tree
Showing 9 changed files with 254 additions and 37 deletions.
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);
}

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);
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) {
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);
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(
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 =
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

0 comments on commit 16afb53

Please sign in to comment.