Skip to content

Commit

Permalink
fix(amf): handle and proper response the error code from subscriberdb…
Browse files Browse the repository at this point in the history
… during authentication

Signed-off-by: RahulKalsangra <rahul.kalsangra@wavelabs.ai>
  • Loading branch information
RahulKalsangra committed Mar 2, 2022
1 parent 6310b47 commit 0ee2500
Show file tree
Hide file tree
Showing 9 changed files with 220 additions and 36 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
64 changes: 43 additions & 21 deletions lte/gateway/c/core/oai/tasks/amf/amf_authentication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,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 @@ -121,48 +119,76 @@ 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_FUNC_RETURN(LOG_NAS_AMF, rc);
}

OAILOG_FUNC_RETURN(LOG_NAS_AMF, RETURNok);
}

int amf_authentication_request_sent(amf_ue_ngap_id_t ue_id) {
ue_m5gmm_context_s* ue_mm_context = NULL;
amf_context_t* amf_context = NULL;
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 the UE due to NULL"
"ue_context\n");
OAILOG_FUNC_RETURN(LOG_NAS_AMF, rc);
}
amf_context = &ue_mm_context->amf_context;
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, rc);
}
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);
}

if (is_initial_req) {
nas5g_auth_info_proc_t* auth_info_proc =
get_nas5g_cn_procedure_auth_info(amf_context);
auth_info_proc->request_sent = true;
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 @@ -734,28 +760,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);

int 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
90 changes: 79 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,54 @@ 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 = NULL;
int amf_cause = -1;
nas5g_auth_info_proc_t* auth_info_proc = NULL;
int rc = RETURNerror;
ue_m5gmm_context_s* ue_mm_context = NULL;
if (!amf_pop_timer_arg(timer_id, &ue_id)) {
OAILOG_WARNING(
LOG_AMF_APP,
"auth_retry_timer: Invalid Timer Id expiration, Timer Id: %d \n",
timer_id);
OAILOG_FUNC_RETURN(LOG_NAS_AMF, RETURNok);
}
ue_mm_context = amf_ue_context_exists_amf_ue_ngap_id(ue_id);
amf_ctxt_p = &ue_mm_context->amf_context;
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);
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\n");
amf_cause = AMF_UE_ILLEGAL;

rc = amf_proc_registration_reject(ue_id, amf_cause);
if (auth_info_proc) {
nas5g_delete_cn_procedure(amf_ctxt_p, &auth_info_proc->cn_proc);
}

amf_free_ue_context(ue_mm_context);
}

return rc;
}

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 +491,16 @@ 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);
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 +521,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);
return 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
36 changes: 34 additions & 2 deletions lte/gateway/c/core/oai/test/amf/test_amf_procedures.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1632,7 +1632,6 @@ TEST_F(AMFAppProcedureTest, ServiceRequestSignalling) {
imsi64 = send_initial_ue_message_no_tmsi(amf_app_desc_p, 36, 1, 1, 0, plmn,
initial_ue_message_hexbuf,
sizeof(initial_ue_message_hexbuf));

/* Check if UE Context is created with correct imsi */
EXPECT_TRUE(get_ue_id_from_imsi(amf_app_desc_p, imsi64, &ue_id));

Expand Down Expand Up @@ -1693,4 +1692,37 @@ TEST_F(AMFAppProcedureTest, ServiceRequestSignalling) {
EXPECT_TRUE(expected_Ids == AMFClientServicer::getInstance().msgtype_stack);
}

} // namespace magma5g
TEST_F(AMFAppProcedureTest, TestAuthFailureFromSubscribeDbLock) {
amf_ue_ngap_id_t ue_id = 0;
amf_context_t* amf_ctxt_p = NULL;
nas5g_auth_info_proc_t* auth_info_proc = NULL;
ue_m5gmm_context_s* ue_context_p = nullptr;
std::vector<MessagesIds> expected_Ids{
AMF_APP_NGAP_AMF_UE_ID_NOTIFICATION, // new registration notification
// indication to ngap
NGAP_NAS_DL_DATA_REQ, // Registration Reject
NGAP_UE_CONTEXT_RELEASE_COMMAND // UEContextReleaseCommand
};
/* Send the initial UE message */
imsi64_t imsi64 = 0;
imsi64 = send_initial_ue_message_no_tmsi(amf_app_desc_p, 36, 1, 1, 0, plmn,
initial_ue_message_hexbuf,
sizeof(initial_ue_message_hexbuf));
/* Check if UE Context is created with correct imsi */
EXPECT_TRUE(get_ue_id_from_imsi(amf_app_desc_p, imsi64, &ue_id));

/* Send the authentication response message from subscriberdb */
itti_amf_subs_auth_info_ans_t aia_itti_msg = {};
strncpy(aia_itti_msg.imsi, imsi.c_str(), imsi.size());
aia_itti_msg.imsi_length = imsi.size();
aia_itti_msg.result = DIAMETER_TOO_BUSY;
int rc = RETURNerror;
rc = amf_nas_proc_authentication_info_answer(&aia_itti_msg);
EXPECT_TRUE(rc == RETURNok);
ue_context_p = amf_ue_context_exists_amf_ue_ngap_id(ue_id);
amf_ctxt_p = &ue_context_p->amf_context;
auth_info_proc = get_nas5g_cn_procedure_auth_info(amf_ctxt_p);
nas5g_delete_cn_procedure(amf_ctxt_p, &auth_info_proc->cn_proc);
amf_free_ue_context(ue_context_p);
}
} // namespace magma5g
2 changes: 2 additions & 0 deletions lte/gateway/configs/templates/mme.conf.template
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,8 @@ AMF :
DEFAULT_DNS_SEC_IPV4_ADDRESS = "{{ ipv4_sec_dns }}";
AMF_NAME = "{{ amf_name }}";
DEFAULT_DNN = "{{ default_dnn }}";
AUTHENTICATION_MAX_RETRY = "{{ auth_retry_max_count }}";
AUTHENTICATION_TIMER_EXPIRY = "{{ auth_retry_interval }}";
PLMN_SUPPORT_LIST = (
{ MCC="{{ mcc }}" ; MNC="{{ mnc }}"; AMF_DEFAULT_SLICE_SERVICE_TYPE="{{ amf_default_slice_service_type }}" ; AMF_DEFAULT_SLICE_DIFFERENTIATOR="{{ amf_default_slice_differentiator }}"; }
);
Expand Down

0 comments on commit 0ee2500

Please sign in to comment.