mme_app_authentication.c 13 KB
Newer Older
Cedric Roux's avatar
 
Cedric Roux committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
/*******************************************************************************

  Eurecom OpenAirInterface
  Copyright(c) 1999 - 2013 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.fr/openairinterface
  Address      : EURECOM, Campus SophiaTech, 450 Route des Chappes
                 06410 Biot FRANCE

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

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

#include "intertask_interface.h"
37
#include "mme_app_itti_messaging.h"
Cedric Roux's avatar
 
Cedric Roux committed
38 39 40 41 42 43 44 45

#include "mme_config.h"

#include "mme_app_ue_context.h"
#include "mme_app_defs.h"

#include "assertions.h"

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

52
static
Cedric Roux's avatar
 
Cedric Roux committed
53 54
int mme_app_request_authentication_info(const mme_app_imsi_t imsi,
                                        const uint8_t nb_of_vectors,
55 56
                                        const plmn_t *plmn,
                                        const uint8_t *auts)
Cedric Roux's avatar
 
Cedric Roux committed
57 58 59 60 61 62
{
    s6a_auth_info_req_t *auth_info_req;
    MessageDef          *message_p;

    DevAssert(plmn != NULL);

63
    message_p = itti_alloc_new_message(TASK_MME_APP, S6A_AUTH_INFO_REQ);
Cedric Roux's avatar
 
Cedric Roux committed
64

65
    auth_info_req = &message_p->ittiMsg.s6a_auth_info_req;
Cedric Roux's avatar
 
Cedric Roux committed
66 67 68
    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;
69 70 71 72 73 74 75
    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));
    }
Cedric Roux's avatar
 
Cedric Roux committed
76

77
    return itti_send_msg_to_task(TASK_S6A, INSTANCE_DEFAULT, message_p);
Cedric Roux's avatar
 
Cedric Roux committed
78 79 80 81 82 83 84 85 86 87 88 89 90
}

int mme_app_handle_nas_auth_resp(nas_auth_resp_t *nas_auth_resp_p)
{
    struct ue_context_s *ue_context;
    uint64_t imsi;

    DevAssert(nas_auth_resp_p != NULL);

    MME_APP_STRING_TO_IMSI((char *)nas_auth_resp_p->imsi, &imsi);

    MME_APP_DEBUG("Handling imsi %"IMSI_FORMAT"\n", imsi);

91 92
    if ((ue_context = mme_ue_context_exists_imsi(&mme_app_desc.mme_ue_contexts,
                      imsi)) == NULL) {
Cedric Roux's avatar
 
Cedric Roux committed
93 94 95 96 97 98 99 100 101 102 103 104 105 106
        MME_APP_ERROR("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;
        s6a_update_location_req_t *s6a_ulr;

107
        message_p = itti_alloc_new_message(TASK_MME_APP, S6A_UPDATE_LOCATION_REQ);
Cedric Roux's avatar
 
Cedric Roux committed
108 109 110 111 112

        if (message_p == NULL) {
            return -1;
        }

113
        s6a_ulr = &message_p->ittiMsg.s6a_update_location_req;
Cedric Roux's avatar
 
Cedric Roux committed
114 115 116 117 118 119 120

        memcpy(s6a_ulr->imsi, nas_auth_resp_p->imsi, 16);
        s6a_ulr->initial_attach = INITIAL_ATTACH;
        s6a_ulr->rat_type = RAT_EUTRAN;
        /* Check if we already have UE data */
        s6a_ulr->skip_subsriber_data = 0;

121
        return itti_send_msg_to_task(TASK_S6A, INSTANCE_DEFAULT, message_p);
Cedric Roux's avatar
 
Cedric Roux committed
122 123 124 125
    }
    return -1;
}

126 127
int mme_app_handle_authentication_info_answer(s6a_auth_info_ans_t
        *s6a_auth_info_ans_p)
Cedric Roux's avatar
 
Cedric Roux committed
128 129 130 131 132 133 134 135 136 137
{
    struct ue_context_s *ue_context;
    uint64_t imsi;

    DevAssert(s6a_auth_info_ans_p != NULL);

    MME_APP_STRING_TO_IMSI((char *)s6a_auth_info_ans_p->imsi, &imsi);

    MME_APP_DEBUG("Handling imsi %"IMSI_FORMAT"\n", imsi);

138 139
    if ((ue_context = mme_ue_context_exists_imsi(&mme_app_desc.mme_ue_contexts,
                      imsi)) == NULL) {
Cedric Roux's avatar
 
Cedric Roux committed
140 141 142 143 144
        MME_APP_ERROR("That's embarrassing as we don't know this IMSI\n");
        return -1;
    }

    if ((s6a_auth_info_ans_p->result.present == S6A_RESULT_BASE) &&
145
            (s6a_auth_info_ans_p->result.choice.base == DIAMETER_SUCCESS)) {
Cedric Roux's avatar
 
Cedric Roux committed
146 147 148 149 150 151 152 153
        /* 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_p->auth_info.nb_of_vectors == 1,
                 s6a_auth_info_ans_p->auth_info.nb_of_vectors, 1, 0);

154 155 156 157 158 159 160 161 162 163 164
        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 + 1) * sizeof(eutran_vector_t));
            DevAssert(ue_context->vector_list != NULL);
        }
        memcpy(&ue_context->vector_list[ue_context->nb_of_vectors],
               &s6a_auth_info_ans_p->auth_info.eutran_vector, sizeof(eutran_vector_t));
Cedric Roux's avatar
 
Cedric Roux committed
165

166
        ue_context->vector_in_use = &ue_context->vector_list[ue_context->nb_of_vectors];
Cedric Roux's avatar
 
Cedric Roux committed
167

168
        ue_context->nb_of_vectors += s6a_auth_info_ans_p->auth_info.nb_of_vectors;
Cedric Roux's avatar
 
Cedric Roux committed
169

170 171
        mme_app_itti_auth_rsp(ue_context->ue_id, 1,
                              &s6a_auth_info_ans_p->auth_info.eutran_vector);
Cedric Roux's avatar
 
Cedric Roux committed
172
    } else {
173 174 175 176 177 178 179 180
        /* Inform NAS layer with the right failure */
        if (s6a_auth_info_ans_p->result.present == S6A_RESULT_BASE) {
            mme_app_itti_auth_fail(ue_context->ue_id, s6a_error_2_nas_cause(
                s6a_auth_info_ans_p->result.choice.base, 0));
        } else {
            mme_app_itti_auth_fail(ue_context->ue_id, s6a_error_2_nas_cause(
                s6a_auth_info_ans_p->result.choice.experimental, 1));
        }
Cedric Roux's avatar
 
Cedric Roux committed
181 182
    }

183
    return 0;
Cedric Roux's avatar
 
Cedric Roux committed
184 185
}

186
#if defined(DISABLE_USE_NAS)
Cedric Roux's avatar
 
Cedric Roux committed
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
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;

225
//         STAILQ_INIT(&ue_context->vector_list);
Cedric Roux's avatar
 
Cedric Roux committed
226 227 228 229 230 231 232 233 234 235 236 237
        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) &&
238
                (attach_req_p->initial != INITIAL_REQUEST)) {
Cedric Roux's avatar
 
Cedric Roux committed
239 240 241 242 243
            /* 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 */
244 245
//              if (STAILQ_EMPTY(&ue_context->vector_list))
            if (ue_context->nb_of_vectors == 0)
246
request_auth: {
Cedric Roux's avatar
 
Cedric Roux committed
247 248 249 250 251 252 253 254 255 256 257 258 259
                /* 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,
260
                       sizeof(cgi_t));
Cedric Roux's avatar
 
Cedric Roux committed
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279

                /* 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);
            } 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"
280 281
                              " authentication from NAS\n");
                message_p = itti_alloc_new_message(TASK_MME_APP, NAS_AUTHENTICATION_PARAM_FAIL);
Cedric Roux's avatar
 
Cedric Roux committed
282

283
                nas_auth_req_p = &message_p->ittiMsg.nas_auth_req;
Cedric Roux's avatar
 
Cedric Roux committed
284 285 286 287

                MME_APP_IMSI_TO_STRING(imsi, nas_auth_req_p->imsi);
                nas_auth_req_p->failure = NAS_FAILURE_OK;

288
                return itti_send_msg_to_task(TASK_NAS, INSTANCE_DEFAULT, message_p);
Cedric Roux's avatar
 
Cedric Roux committed
289 290 291 292 293
            }
        }
    }
    return 0;
}
294 295 296 297 298 299
#else
void mme_app_handle_nas_auth_param_req(nas_auth_param_req_t
                                       *nas_auth_param_req_p)
{
    struct ue_context_s *ue_context;
    uint64_t imsi = 0;
300 301 302 303 304 305 306 307
    plmn_t visited_plmn_dongle = {
        .MCCdigit3 = 2,
        .MCCdigit2 = 0,
        .MCCdigit1 = 8,
        .MNCdigit3 = 2,
        .MNCdigit2 = 9,
        .MNCdigit1 = 0xF,
    };
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337

    DevAssert(nas_auth_param_req_p != NULL);

    MME_APP_STRING_TO_IMSI(nas_auth_param_req_p->imsi, &imsi);

    MME_APP_DEBUG("Handling imsi %"IMSI_FORMAT"\n", 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 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->imsi  = imsi;
        ue_context->ue_id = nas_auth_param_req_p->ue_id;

        DevAssert(mme_insert_ue_context(&mme_app_desc.mme_ue_contexts, ue_context) == 0);

        /* We have no vector for this UE, send an authentication request
         * to the HSS.
         */
338 339
        plmn_t visited_plmn_eur = {
            .MCCdigit3 = 2,
340 341 342 343 344 345 346 347 348 349
            .MCCdigit2 = 0,
            .MCCdigit1 = 8,
            .MNCdigit1 = 0,
            .MNCdigit2 = 4,
            .MNCdigit3 = 3,
        };

        /* Acquire the current time */
        time(&ue_context->cell_age);

350
        memcpy(&ue_context->guti.gummei.plmn, &visited_plmn_dongle, sizeof(plmn_t));
351 352
        MME_APP_DEBUG("and we have no auth. vector for it, request"
                      " authentication information\n");
353
        mme_app_request_authentication_info(imsi, 1, &visited_plmn_dongle, NULL);
354
    } else {
355 356 357
        memcpy(&ue_context->guti.gummei.plmn, &visited_plmn_dongle, sizeof(plmn_t));

        mme_app_request_authentication_info(imsi, 1, &visited_plmn_dongle, nas_auth_param_req_p->auts);
358 359
    }
}
360
#endif