Files
openairinterface5g/openair-cn/MME_APP/mme_app_authentication.c
T

400 lines
15 KiB
C

/*******************************************************************************
Eurecom OpenAirInterface Core Network
Copyright(c) 1999 - 2014 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fsr/openairinterface
Address : EURECOM,
Campus SophiaTech,
450 Route des Chappes,
CS 50193
06904 Biot Sophia Antipolis cedex,
FRANCE
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "intertask_interface.h"
#include "mme_app_itti_messaging.h"
#include "mme_config.h"
#include "mme_app_ue_context.h"
#include "mme_app_defs.h"
#include "assertions.h"
static
int mme_app_request_authentication_info(const mme_app_imsi_t imsi,
const uint8_t nb_of_vectors,
const plmn_t *plmn,
const uint8_t *auts);
static
int mme_app_request_authentication_info(const mme_app_imsi_t imsi,
const uint8_t nb_of_vectors,
const plmn_t *plmn,
const uint8_t *auts)
{
s6a_auth_info_req_t *auth_info_req = NULL;
MessageDef *message_p = NULL;
DevAssert(plmn != NULL);
message_p = itti_alloc_new_message(TASK_MME_APP, S6A_AUTH_INFO_REQ);
auth_info_req = &message_p->ittiMsg.s6a_auth_info_req;
MME_APP_IMSI_TO_STRING(imsi, auth_info_req->imsi);
memcpy(&auth_info_req->visited_plmn, plmn, sizeof(plmn_t));
auth_info_req->nb_of_vectors = nb_of_vectors;
if (auts != NULL) {
auth_info_req->re_synchronization = 1;
memcpy(auth_info_req->auts, auts, sizeof(auth_info_req->auts));
} else {
auth_info_req->re_synchronization = 0;
memset(auth_info_req->auts, 0, sizeof(auth_info_req->auts));
}
return itti_send_msg_to_task(TASK_S6A, INSTANCE_DEFAULT, message_p);
}
int mme_app_handle_nas_auth_resp(const nas_auth_resp_t * const nas_auth_resp_pP)
{
struct ue_context_s *ue_context = NULL;
uint64_t imsi = 0;
DevAssert(nas_auth_resp_pP != NULL);
MME_APP_STRING_TO_IMSI((char *)nas_auth_resp_pP->imsi, &imsi);
MME_APP_DEBUG("Handling imsi %"IMSI_FORMAT"\n", imsi);
if ((ue_context = mme_ue_context_exists_imsi(&mme_app_desc.mme_ue_contexts,
imsi)) == NULL) {
MME_APP_ERROR("That's embarrassing as we don't know this IMSI\n");
AssertFatal(0, "That's embarrassing as we don't know this IMSI\n");
return -1;
}
/* Consider the UE authenticated */
ue_context->imsi_auth = IMSI_AUTHENTICATED;
/* TODO: Get keys... */
/* Now generate S6A ULR */
{
MessageDef *message_p = NULL;
s6a_update_location_req_t *s6a_ulr = NULL;
message_p = itti_alloc_new_message(TASK_MME_APP, S6A_UPDATE_LOCATION_REQ);
if (message_p == NULL) {
return -1;
}
s6a_ulr = &message_p->ittiMsg.s6a_update_location_req;
memcpy(s6a_ulr->imsi, nas_auth_resp_pP->imsi, 16);
s6a_ulr->initial_attach = INITIAL_ATTACH;
s6a_ulr->rat_type = RAT_EUTRAN;
/* Check if we already have UE data */
s6a_ulr->skip_subscriber_data = 0;
return itti_send_msg_to_task(TASK_S6A, INSTANCE_DEFAULT, message_p);
}
return -1;
}
int
mme_app_handle_authentication_info_answer(
const s6a_auth_info_ans_t * const s6a_auth_info_ans_pP)
{
struct ue_context_s *ue_context;
uint64_t imsi;
DevAssert(s6a_auth_info_ans_pP != NULL);
MME_APP_STRING_TO_IMSI((char *)s6a_auth_info_ans_pP->imsi, &imsi);
MME_APP_DEBUG("Handling imsi %"IMSI_FORMAT"\n", imsi);
if ((ue_context = mme_ue_context_exists_imsi(&mme_app_desc.mme_ue_contexts,
imsi)) == NULL) {
MME_APP_ERROR("That's embarrassing as we don't know this IMSI\n");
return -1;
}
if ((s6a_auth_info_ans_pP->result.present == S6A_RESULT_BASE) &&
(s6a_auth_info_ans_pP->result.choice.base == DIAMETER_SUCCESS)) {
/* S6A procedure has succeeded.
* We have to request UE authentication.
*/
/* Check that list is not empty and contain only one element */
DevCheck(s6a_auth_info_ans_pP->auth_info.nb_of_vectors == 1,
s6a_auth_info_ans_pP->auth_info.nb_of_vectors, 1, 0);
if (ue_context->vector_list == NULL) {
ue_context->vector_list = malloc(sizeof(eutran_vector_t));
DevAssert(ue_context->vector_list != NULL);
} else {
/* Some vector already exist */
ue_context->vector_list = realloc(
ue_context->vector_list,
(ue_context->nb_of_vectors + s6a_auth_info_ans_pP->auth_info.nb_of_vectors) * sizeof(eutran_vector_t));
DevAssert(ue_context->vector_list != NULL);
}
memcpy(&ue_context->vector_list[ue_context->nb_of_vectors],
&s6a_auth_info_ans_pP->auth_info.eutran_vector, sizeof(eutran_vector_t));
ue_context->vector_in_use = &ue_context->vector_list[ue_context->nb_of_vectors];
ue_context->nb_of_vectors += s6a_auth_info_ans_pP->auth_info.nb_of_vectors;
MME_APP_DEBUG("INFORMING NAS ABOUT AUTH RESP SUCCESS got %u vector(s)\n",
s6a_auth_info_ans_pP->auth_info.nb_of_vectors);
mme_app_itti_auth_rsp(ue_context->ue_id,
1,
&s6a_auth_info_ans_pP->auth_info.eutran_vector);
} else {
MME_APP_ERROR("INFORMING NAS ABOUT AUTH RESP ERROR CODE\n");
/* Inform NAS layer with the right failure */
if (s6a_auth_info_ans_pP->result.present == S6A_RESULT_BASE) {
mme_app_itti_auth_fail(ue_context->ue_id, s6a_error_2_nas_cause(
s6a_auth_info_ans_pP->result.choice.base, 0));
} else {
mme_app_itti_auth_fail(ue_context->ue_id, s6a_error_2_nas_cause(
s6a_auth_info_ans_pP->result.choice.experimental, 1));
}
}
return 0;
}
#if defined(DISABLE_USE_NAS)
int mme_app_handle_attach_req(nas_attach_req_t *attach_req_p)
{
/* An attach request has been received from NAS layer.
* If the UE authentication vectors for the UE are known within MME then the
* authentication procedure should be triggered only if the request is an
* initial attach, otherwise an update location should be sent to the HSS
* and default bearer should be established for the provided APN.
* In case of initial attach procedure, the default APN retrieved from the
* HSS will be used to establish the default bearer within EPC.
* The default APN is the one that matches the context-identifier
*/
struct ue_context_s *ue_context;
uint64_t imsi = 0;
DevAssert(attach_req_p != NULL);
MME_APP_STRING_TO_IMSI((char *)attach_req_p->imsi, &imsi);
MME_APP_DEBUG("Handling imsi %"IMSI_FORMAT"\n", imsi);
ue_context = mme_ue_context_exists_imsi(&mme_app_desc.mme_ue_contexts, imsi);
if (ue_context == NULL) {
/* The MME doesn't know this IMSI.
* Insert the UE to the list of known equipements and
* Retrieve the authentication vector from HSS.
*/
MME_APP_DEBUG("UE context doesn't exist -> create one\n");
if ((ue_context = mme_create_new_ue_context()) == NULL) {
/* Error during ue context malloc */
/* TODO */
DevMessage("mme_create_new_ue_context");
return -1;
}
ue_context->imsi = imsi;
ue_context->eNB_ue_s1ap_id = attach_req_p->transparent.eNB_ue_s1ap_id;
ue_context->mme_ue_s1ap_id = attach_req_p->transparent.mme_ue_s1ap_id;
ue_context->ue_id = attach_req_p->transparent.mme_ue_s1ap_id;
// STAILQ_INIT(&ue_context->vector_list);
DevAssert(mme_insert_ue_context(&mme_app_desc.mme_ue_contexts, ue_context) == 0);
goto request_auth;
} else {
/* MME knows this IMSI, check if UE is authenticated and authentication
* vectors are known.
*/
MME_APP_DEBUG("UE context already exists, use it\n");
/* Update mme ue s1ap id */
ue_context->mme_ue_s1ap_id = attach_req_p->transparent.mme_ue_s1ap_id;
if ((ue_context->imsi_auth == IMSI_AUTHENTICATED) &&
(attach_req_p->initial != INITIAL_REQUEST)) {
/* We have to send an update location request to the HSS */
MME_APP_DEBUG("UE is authenticated\n");
} else {
MME_APP_DEBUG("UE is not authenticated\n");
/* UE is not authenticated or an initial request */
// if (STAILQ_EMPTY(&ue_context->vector_list))
if (ue_context->nb_of_vectors == 0)
request_auth: {
/* We have no vector for this UE, send an authentication request
* to the HSS.
*/
plmn_t plmn = {
.MCCdigit2 = 0,
.MCCdigit1 = 8,
.MCCdigit3 = 2,
.MNCdigit1 = 0,
.MNCdigit2 = 4,
.MNCdigit3 = 3,
};
memcpy(&ue_context->e_utran_cgi, &attach_req_p->transparent.e_utran_cgi,
sizeof(cgi_t));
/* Acquire the current time */
time(&ue_context->cell_age);
/* Some random values for GUTI */
ue_context->guti.m_tmsi = 0x24568956;
ue_context->guti.gummei.MMEcode = 0x01;
ue_context->guti.gummei.MMEgid = 0x5691;
memcpy(&ue_context->guti.gummei.plmn, &plmn, sizeof(plmn_t));
MME_APP_DEBUG("and we have no auth. vector for it, request"
" authentication information\n");
// mme_app_dump_ue_contexts();
mme_app_request_authentication_info(imsi, 1, &plmn, NULL);
} else {
nas_auth_req_t *nas_auth_req_p;
MessageDef *message_p;
/* We have a vector... USE it */
MME_APP_DEBUG("but we have an auth. vector for it, request"
" authentication from NAS\n");
message_p = itti_alloc_new_message(TASK_MME_APP, NAS_AUTHENTICATION_PARAM_FAIL);
nas_auth_req_p = &message_p->ittiMsg.nas_auth_req;
MME_APP_IMSI_TO_STRING(imsi, nas_auth_req_p->imsi);
nas_auth_req_p->failure = NAS_FAILURE_OK;
return itti_send_msg_to_task(TASK_NAS_MME, INSTANCE_DEFAULT, message_p);
}
}
}
return 0;
}
#else
void
mme_app_handle_nas_auth_param_req(
const nas_auth_param_req_t * const nas_auth_param_req_pP)
{
static const plmn_t visited_plmn_eur = {
.MCCdigit3 = 2,
.MCCdigit2 = 0,
.MCCdigit1 = 8,
.MNCdigit1 = 0,
.MNCdigit2 = 1,
.MNCdigit3 = 0,
};
static const plmn_t visited_plmn_dongle = {
.MCCdigit3 = 2,
.MCCdigit2 = 0,
.MCCdigit1 = 8,
.MNCdigit3 = 2,
.MNCdigit2 = 9,
.MNCdigit1 = 0xF,
};
plmn_t *visited_plmn = NULL;
struct ue_context_s *ue_context = NULL;
uint64_t imsi = 0;
plmn_t visited_plmn_from_req = {
.MCCdigit3 = 0,
.MCCdigit2 = 0,
.MCCdigit1 = 0,
.MNCdigit1 = 0,
.MNCdigit2 = 0,
.MNCdigit3 = 0,
};
DevAssert(nas_auth_param_req_pP != NULL);
//visited_plmn = &visited_plmn_eur;
//visited_plmn = &visited_plmn_dongle;
visited_plmn = &visited_plmn_from_req;
#warning "assume MNC on 2 digits only"
visited_plmn_from_req.MCCdigit3 = nas_auth_param_req_pP->imsi[0];
visited_plmn_from_req.MCCdigit2 = nas_auth_param_req_pP->imsi[1];
visited_plmn_from_req.MCCdigit1 = nas_auth_param_req_pP->imsi[2];
visited_plmn_from_req.MNCdigit1 = 0;
visited_plmn_from_req.MNCdigit2 = nas_auth_param_req_pP->imsi[3];
visited_plmn_from_req.MNCdigit3 = nas_auth_param_req_pP->imsi[4];
MME_APP_STRING_TO_IMSI(nas_auth_param_req_pP->imsi, &imsi);
MME_APP_DEBUG("%s Handling imsi %"IMSI_FORMAT"\n", __FUNCTION__, imsi);
MME_APP_DEBUG("%s Handling imsi from req %s\n", __FUNCTION__, nas_auth_param_req_pP->imsi);
/* Fetch the context associated with this IMSI */
ue_context = mme_ue_context_exists_imsi(&mme_app_desc.mme_ue_contexts, imsi);
if (ue_context == NULL) {
/* Currently no context available -> trigger an authentication request
* to the HSS.
*/
MME_APP_DEBUG("UE context search by IMSI failed, try by ue id\n");
ue_context = mme_ue_context_exists_nas_ue_id(&mme_app_desc.mme_ue_contexts, nas_auth_param_req_pP->ue_id);
if (ue_context == NULL) {
// should have been created by initial ue message
MME_APP_ERROR("UE context doesn't exist -> create one\n");
if ((ue_context = mme_create_new_ue_context()) == NULL) {
/* Error during ue context malloc */
/* TODO */
DevMessage("mme_create_new_ue_context");
return;
}
ue_context->ue_id = nas_auth_param_req_pP->ue_id;
ue_context->mme_ue_s1ap_id = nas_auth_param_req_pP->ue_id;
DevAssert(mme_insert_ue_context(&mme_app_desc.mme_ue_contexts, ue_context) == 0);
}
ue_context->imsi = imsi;
/* We have no vector for this UE, send an authentication request
* to the HSS.
*/
/* Acquire the current time */
time(&ue_context->cell_age);
memcpy(&ue_context->guti.gummei.plmn, visited_plmn, sizeof(plmn_t));
MME_APP_DEBUG("and we have no auth. vector for it, request"
" authentication information\n");
mme_app_request_authentication_info(imsi, 1, visited_plmn, NULL);
} else {
memcpy(&ue_context->guti.gummei.plmn, visited_plmn, sizeof(plmn_t));
mme_app_request_authentication_info(imsi, 1, visited_plmn, nas_auth_param_req_pP->auts);
}
}
#endif