mme_app_authentication.c 12.5 KB
Newer Older
Cedric Roux's avatar
 
Cedric Roux committed
1
/*******************************************************************************
Lionel Gauthier's avatar
GPLv3  
Lionel Gauthier committed
2 3
    OpenAirInterface
    Copyright(c) 1999 - 2014 Eurecom
Cedric Roux's avatar
 
Cedric Roux committed
4

Lionel Gauthier's avatar
GPLv3  
Lionel Gauthier committed
5 6 7 8
    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
Cedric Roux's avatar
 
Cedric Roux committed
9 10


Lionel Gauthier's avatar
GPLv3  
Lionel Gauthier committed
11 12 13 14
    OpenAirInterface is distributed in the hope that 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.
Cedric Roux's avatar
 
Cedric Roux committed
15

Lionel Gauthier's avatar
GPLv3  
Lionel Gauthier committed
16 17 18 19
    You should have received a copy of the GNU General Public License
    along with OpenAirInterface.The full GNU General Public License is
   included in this distribution in the file called "COPYING". If not,
   see <http://www.gnu.org/licenses/>.
Cedric Roux's avatar
 
Cedric Roux committed
20 21

  Contact Information
Lionel Gauthier's avatar
GPLv3  
Lionel Gauthier committed
22 23 24 25 26 27 28 29
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
  OpenAirInterface Dev  : openair4g-devel@eurecom.fr

  Address      : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.

 *******************************************************************************/

Cedric Roux's avatar
 
Cedric Roux committed
30 31 32 33

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
34
#include <unistd.h>
Cedric Roux's avatar
 
Cedric Roux committed
35

Lionel Gauthier's avatar
Lionel Gauthier committed
36
#include "msc.h"
Cedric Roux's avatar
 
Cedric Roux committed
37
#include "intertask_interface.h"
38
#include "mme_app_itti_messaging.h"
Cedric Roux's avatar
 
Cedric Roux committed
39 40 41 42 43

#include "mme_config.h"

#include "mme_app_ue_context.h"
#include "mme_app_defs.h"
Lionel Gauthier's avatar
Lionel Gauthier committed
44
#include "mcc_mnc_itu.h"
Cedric Roux's avatar
 
Cedric Roux committed
45 46 47

#include "assertions.h"

48
static
49
int mme_app_request_authentication_info(const char   *imsi,
Cedric Roux's avatar
 
Cedric Roux committed
50
                                        const uint8_t nb_of_vectors,
51 52
                                        const plmn_t *plmn,
                                        const uint8_t *auts);
Cedric Roux's avatar
 
Cedric Roux committed
53

54
static
55
int mme_app_request_authentication_info(const char   *imsi,
Cedric Roux's avatar
 
Cedric Roux committed
56
                                        const uint8_t nb_of_vectors,
57 58
                                        const plmn_t *plmn,
                                        const uint8_t *auts)
Cedric Roux's avatar
 
Cedric Roux committed
59
{
60 61
  s6a_auth_info_req_t *auth_info_req = NULL;
  MessageDef          *message_p     = NULL;
62
  int                  imsi_length   = strlen(imsi);
63 64 65 66 67 68 69 70

  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;
  memset(auth_info_req, 0, sizeof(*auth_info_req));

71 72 73
  strncpy(auth_info_req->imsi, imsi, imsi_length);
  auth_info_req->imsi_length = imsi_length;
  //MME_APP_IMSI_TO_STRING(imsi, auth_info_req->imsi);
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100

  memcpy(&auth_info_req->visited_plmn, plmn, sizeof(plmn_t));
  MME_APP_DEBUG("%s visited_plmn MCC %X%X%X MNC %X%X%X\n",
                __FUNCTION__,
                auth_info_req->visited_plmn.MCCdigit1,
                auth_info_req->visited_plmn.MCCdigit2,
                auth_info_req->visited_plmn.MCCdigit3,
                auth_info_req->visited_plmn.MNCdigit1,
                auth_info_req->visited_plmn.MNCdigit2,
                auth_info_req->visited_plmn.MNCdigit3);
  uint8_t *ptr = (uint8_t *)&auth_info_req->visited_plmn;
  MME_APP_DEBUG("%s visited_plmn %02X%02X%02X\n",
                __FUNCTION__,
                ptr[0],
                ptr[1],
                ptr[2]);

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

Lionel Gauthier's avatar
Lionel Gauthier committed
101 102 103 104 105 106 107
  MSC_LOG_TX_MESSAGE(
  		MSC_MMEAPP_MME,
  		MSC_S6A_MME,
  		NULL,0,
  		"0 S6A_AUTH_INFO_REQ IMSI %s visited_plmn %02X%02X%02X re_sync %u",
  		imsi,ptr[0],ptr[1],ptr[2],auth_info_req->re_synchronization);

108
  return itti_send_msg_to_task(TASK_S6A, INSTANCE_DEFAULT, message_p);
Cedric Roux's avatar
 
Cedric Roux committed
109 110
}

111
int mme_app_handle_nas_auth_resp(const nas_auth_resp_t * const nas_auth_resp_pP)
Cedric Roux's avatar
 
Cedric Roux committed
112
{
113 114
  struct ue_context_s *ue_context = NULL;
  uint64_t             imsi       = 0;
Cedric Roux's avatar
 
Cedric Roux committed
115

116
  DevAssert(nas_auth_resp_pP != NULL);
Cedric Roux's avatar
 
Cedric Roux committed
117

118
  MME_APP_STRING_TO_IMSI((char *)nas_auth_resp_pP->imsi, &imsi);
Cedric Roux's avatar
 
Cedric Roux committed
119

120
  MME_APP_DEBUG("Handling imsi %"IMSI_FORMAT"\n", imsi);
Cedric Roux's avatar
 
Cedric Roux committed
121

Lionel Gauthier's avatar
Lionel Gauthier committed
122

123 124 125
  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");
Lionel Gauthier's avatar
Lionel Gauthier committed
126 127
    MSC_LOG_EVENT(
    		MSC_MMEAPP_MME,
Lionel Gauthier's avatar
Lionel Gauthier committed
128
    		"0 NAS_AUTH_RESP Unknown imsi %"IMSI_FORMAT,imsi);
129 130 131
    AssertFatal(0, "That's embarrassing as we don't know this IMSI\n");
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
132

133 134
  /* Consider the UE authenticated */
  ue_context->imsi_auth = IMSI_AUTHENTICATED;
Cedric Roux's avatar
 
Cedric Roux committed
135

136
  /* TODO: Get keys... */
Cedric Roux's avatar
 
Cedric Roux committed
137

138 139 140 141
  /* Now generate S6A ULR */
  {
    MessageDef                *message_p = NULL;
    s6a_update_location_req_t *s6a_ulr   = NULL;
Cedric Roux's avatar
 
Cedric Roux committed
142

143
    message_p = itti_alloc_new_message(TASK_MME_APP, S6A_UPDATE_LOCATION_REQ);
Cedric Roux's avatar
 
Cedric Roux committed
144

145 146 147
    if (message_p == NULL) {
      return -1;
    }
Cedric Roux's avatar
 
Cedric Roux committed
148

149
    s6a_ulr = &message_p->ittiMsg.s6a_update_location_req;
Cedric Roux's avatar
 
Cedric Roux committed
150

151 152 153 154 155
    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;
Cedric Roux's avatar
 
Cedric Roux committed
156

Lionel Gauthier's avatar
Lionel Gauthier committed
157 158 159 160 161 162 163
    MSC_LOG_TX_MESSAGE(
    		MSC_MMEAPP_MME,
    		MSC_S6A_MME,
    		NULL,0,
    		" S6A_UPDATE_LOCATION_REQ IMSI %s RAT_EUTRAN",
    		imsi);

164 165 166
    return itti_send_msg_to_task(TASK_S6A, INSTANCE_DEFAULT, message_p);
  }
  return -1;
Cedric Roux's avatar
 
Cedric Roux committed
167 168
}

169 170
int
mme_app_handle_authentication_info_answer(
171
  const s6a_auth_info_ans_t * const s6a_auth_info_ans_pP)
Cedric Roux's avatar
 
Cedric Roux committed
172
{
173 174
  struct ue_context_s *ue_context = NULL;
  uint64_t             imsi       = 0;
Cedric Roux's avatar
 
Cedric Roux committed
175

176
  DevAssert(s6a_auth_info_ans_pP != NULL);
Cedric Roux's avatar
 
Cedric Roux committed
177

178
  MME_APP_STRING_TO_IMSI((char *)s6a_auth_info_ans_pP->imsi, &imsi);
Cedric Roux's avatar
 
Cedric Roux committed
179

180
  MME_APP_DEBUG("Handling imsi %"IMSI_FORMAT"\n", imsi);
Cedric Roux's avatar
 
Cedric Roux committed
181

Lionel Gauthier's avatar
Lionel Gauthier committed
182

183 184 185
  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");
Lionel Gauthier's avatar
Lionel Gauthier committed
186 187
    MSC_LOG_EVENT(
    		MSC_MMEAPP_MME,
Lionel Gauthier's avatar
Lionel Gauthier committed
188
    		"0 S6A_AUTH_INFO_ANS Unknown imsi %"IMSI_FORMAT,imsi);
189 190
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
191

192 193 194 195 196
  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.
     */
Cedric Roux's avatar
 
Cedric Roux committed
197

198 199 200
    /* 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);
Cedric Roux's avatar
 
Cedric Roux committed
201

202 203 204 205 206 207 208 209
    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));
Lionel Gauthier's avatar
 
Lionel Gauthier committed
210

211 212
      DevAssert(ue_context->vector_list != NULL);
    }
Cedric Roux's avatar
 
Cedric Roux committed
213

214 215
    memcpy(&ue_context->vector_list[ue_context->nb_of_vectors],
           &s6a_auth_info_ans_pP->auth_info.eutran_vector, sizeof(eutran_vector_t));
Cedric Roux's avatar
 
Cedric Roux committed
216

217
    ue_context->vector_in_use = &ue_context->vector_list[ue_context->nb_of_vectors];
218

219
    ue_context->nb_of_vectors += s6a_auth_info_ans_pP->auth_info.nb_of_vectors;
Cedric Roux's avatar
 
Cedric Roux committed
220

221 222 223 224 225 226 227 228
    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");
Lionel Gauthier's avatar
Lionel Gauthier committed
229 230
    MSC_LOG_EVENT(
    		MSC_MMEAPP_MME,
Lionel Gauthier's avatar
Lionel Gauthier committed
231
    		"0 S6A_AUTH_INFO_ANS S6A Failure imsi %"IMSI_FORMAT,imsi);
Lionel Gauthier's avatar
Lionel Gauthier committed
232 233


234 235 236 237 238

    /* 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));
Cedric Roux's avatar
 
Cedric Roux committed
239
    } else {
240 241
      mme_app_itti_auth_fail(ue_context->ue_id, s6a_error_2_nas_cause(
                               s6a_auth_info_ans_pP->result.choice.experimental, 1));
Cedric Roux's avatar
 
Cedric Roux committed
242
    }
243
  }
Cedric Roux's avatar
 
Cedric Roux committed
244

245
  return 0;
Cedric Roux's avatar
 
Cedric Roux committed
246 247
}

248

249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
void
mme_app_handle_nas_auth_param_req(
  const nas_auth_param_req_t * const nas_auth_param_req_pP)
{
  plmn_t              *visited_plmn  = NULL;
  struct ue_context_s *ue_context    = NULL;
  uint64_t             imsi          = 0;
  int                  mnc_length    = 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_from_req;

  visited_plmn_from_req.MCCdigit1 = nas_auth_param_req_pP->imsi[0];
  visited_plmn_from_req.MCCdigit2 = nas_auth_param_req_pP->imsi[1];
  visited_plmn_from_req.MCCdigit3 = nas_auth_param_req_pP->imsi[2];

273 274 275 276 277 278 279 280
  mnc_length = find_mnc_length(
                 nas_auth_param_req_pP->imsi[0],
                 nas_auth_param_req_pP->imsi[1],
                 nas_auth_param_req_pP->imsi[2],
                 nas_auth_param_req_pP->imsi[3],
                 nas_auth_param_req_pP->imsi[4],
                 nas_auth_param_req_pP->imsi[5]
               );
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329

  if (mnc_length == 2) {
    visited_plmn_from_req.MNCdigit1 = nas_auth_param_req_pP->imsi[3];
    visited_plmn_from_req.MNCdigit2 = nas_auth_param_req_pP->imsi[4];
    visited_plmn_from_req.MNCdigit3 = 15;
  } else if (mnc_length == 3) {
    visited_plmn_from_req.MNCdigit1 = nas_auth_param_req_pP->imsi[3];
    visited_plmn_from_req.MNCdigit2 = nas_auth_param_req_pP->imsi[4];
    visited_plmn_from_req.MNCdigit3 = nas_auth_param_req_pP->imsi[5];
  } else {
    AssertFatal(0, "MNC Not found (mcc_mnc_list)");
  }

  if (mnc_length == 3) {
    MME_APP_DEBUG("%s visited_plmn_from_req  %1d%1d%1d.%1d%1d%1d\n",
                  __FUNCTION__,
                  visited_plmn_from_req.MCCdigit1,
                  visited_plmn_from_req.MCCdigit2,
                  visited_plmn_from_req.MCCdigit3,
                  visited_plmn_from_req.MNCdigit1,
                  visited_plmn_from_req.MNCdigit2,
                  visited_plmn_from_req.MNCdigit3);
  } else {
    MME_APP_DEBUG("%s visited_plmn_from_req  %1d%1d%1d.%1d%1d\n",
                  __FUNCTION__,
                  visited_plmn_from_req.MCCdigit1,
                  visited_plmn_from_req.MCCdigit2,
                  visited_plmn_from_req.MCCdigit3,
                  visited_plmn_from_req.MNCdigit1,
                  visited_plmn_from_req.MNCdigit2);
  }

  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 (mnc length %d)\n",
                __FUNCTION__,
                nas_auth_param_req_pP->imsi,
                mnc_length);

  /* 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);
330

331 332 333 334 335 336 337 338 339 340 341 342 343 344
    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);
345
    }
346 347 348 349 350 351 352 353 354 355 356 357 358

    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");
359
    mme_app_request_authentication_info(nas_auth_param_req_pP->imsi, 1, visited_plmn, NULL);
360 361 362
  } else {
    memcpy(&ue_context->guti.gummei.plmn, visited_plmn, sizeof(plmn_t));

363
    mme_app_request_authentication_info(nas_auth_param_req_pP->imsi, 1, visited_plmn, nas_auth_param_req_pP->auts);
364
  }
365
}