/* * Copyright (C) 2019 by Sukchan Lee * * This file is part of Open5GS. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "nudm-handler.h" static const char *links_member_name(OpenAPI_auth_type_e auth_type) { if (auth_type == OpenAPI_auth_type_5G_AKA || auth_type == OpenAPI_auth_type_EAP_AKA_PRIME) { return OGS_SBI_RESOURCE_NAME_5G_AKA; } else if (auth_type == OpenAPI_auth_type_EAP_TLS) { return OGS_SBI_RESOURCE_NAME_EAP_SESSION; } ogs_assert_if_reached(); return NULL; } bool ausf_nudm_ueau_handle_get(ausf_ue_t *ausf_ue, ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg) { ogs_sbi_server_t *server = NULL; ogs_sbi_message_t sendmsg; ogs_sbi_header_t header; ogs_sbi_response_t *response = NULL; char hxres_star_string[OGS_KEYSTRLEN(OGS_MAX_RES_LEN)]; OpenAPI_authentication_info_result_t *AuthenticationInfoResult = NULL; OpenAPI_authentication_vector_t *AuthenticationVector = NULL; OpenAPI_ue_authentication_ctx_t UeAuthenticationCtx; OpenAPI_ue_authentication_ctx_5g_auth_data_t AV5G_AKA; OpenAPI_map_t *LinksValueScheme = NULL; OpenAPI_links_value_schema_t LinksValueSchemeValue; ogs_assert(ausf_ue); ogs_assert(stream); server = ogs_sbi_server_from_stream(stream); ogs_assert(server); ogs_assert(recvmsg); AuthenticationInfoResult = recvmsg->AuthenticationInfoResult; if (!AuthenticationInfoResult) { ogs_error("[%s] No AuthenticationInfoResult", ausf_ue->suci); ogs_assert(true == ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, recvmsg, "No AuthenticationInfoResult", ausf_ue->suci, NULL)); return false; } /* See TS29.509 6.1.7.3 Application Errors */ if (AuthenticationInfoResult->auth_type != OpenAPI_auth_type_5G_AKA) { ogs_error("[%s] Not supported Auth Method [%d]", ausf_ue->suci, AuthenticationInfoResult->auth_type); ogs_assert(true == ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_NOT_IMPLEMENTED, recvmsg, "Not supported Auth Method", ausf_ue->suci, NULL)); return false; } AuthenticationVector = AuthenticationInfoResult->authentication_vector; if (!AuthenticationVector) { ogs_error("[%s] No AuthenticationVector", ausf_ue->suci); ogs_assert(true == ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, recvmsg, "No AuthenticationVector", ausf_ue->suci, NULL)); return false; } if (AuthenticationVector->av_type != OpenAPI_av_type_5G_HE_AKA) { ogs_error("[%s] Not supported Auth Method [%d]", ausf_ue->suci, AuthenticationVector->av_type); /* * TS29.509 * 5.2.2.2.2 5G AKA * * On failure or redirection, one of the HTTP status code * listed in table 6.1.7.3-1 shall be returned with the message * body containing a ProblemDetails structure with the "cause" * attribute set to one of the application error listed in * Table 6.1.7.3-1. * Application Error: AUTHENTICATION_REJECTED * HTTP status code: 403 Forbidden * Description: The user cannot be authenticated with this * authentication method e.g. only SIM data available */ ogs_assert(true == ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_FORBIDDEN, recvmsg, "Not supported Auth Method", ausf_ue->suci, "AUTHENTICATION_REJECTED")); return false; } if (!AuthenticationVector->rand) { ogs_error("[%s] No AuthenticationVector.rand", ausf_ue->suci); ogs_assert(true == ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, recvmsg, "No AuthenticationVector.rand", ausf_ue->suci, NULL)); return false; } if (!AuthenticationVector->xres_star) { ogs_error("[%s] No AuthenticationVector.xresStar", ausf_ue->suci); ogs_assert(true == ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, recvmsg, "No AuthenticationVector.xresStar", ausf_ue->suci, NULL)); return false; } if (!AuthenticationVector->autn) { ogs_error("[%s] No AuthenticationVector.autn", ausf_ue->suci); ogs_assert(true == ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, recvmsg, "No AuthenticationVector.autn", ausf_ue->suci, NULL)); return false; } if (!AuthenticationVector->kausf) { ogs_error("[%s] No AuthenticationVector.kausf", ausf_ue->suci); ogs_assert(true == ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, recvmsg, "No AuthenticationVector.kausf", ausf_ue->suci, NULL)); return false; } if (!AuthenticationInfoResult->supi) { ogs_error("[%s] No AuthenticationVector.supi", ausf_ue->suci); ogs_assert(true == ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, recvmsg, "No AuthenticationVector.supi", ausf_ue->suci, NULL)); return false; } /* SUPI */ if (ausf_ue->supi) { ogs_hash_set(ausf_self()->supi_hash, ausf_ue->supi, strlen(ausf_ue->supi), NULL); ogs_free(ausf_ue->supi); } ausf_ue->supi = ogs_strdup(AuthenticationInfoResult->supi); ogs_assert(ausf_ue->supi); ogs_hash_set(ausf_self()->supi_hash, ausf_ue->supi, strlen(ausf_ue->supi), ausf_ue); ausf_ue->auth_type = AuthenticationInfoResult->auth_type; ogs_ascii_to_hex( AuthenticationVector->rand, strlen(AuthenticationVector->rand), ausf_ue->rand, sizeof(ausf_ue->rand)); ogs_ascii_to_hex( AuthenticationVector->xres_star, strlen(AuthenticationVector->xres_star), ausf_ue->xres_star, sizeof(ausf_ue->xres_star)); ogs_ascii_to_hex( AuthenticationVector->kausf, strlen(AuthenticationVector->kausf), ausf_ue->kausf, sizeof(ausf_ue->kausf)); memset(&UeAuthenticationCtx, 0, sizeof(UeAuthenticationCtx)); UeAuthenticationCtx.auth_type = ausf_ue->auth_type; memset(&AV5G_AKA, 0, sizeof(AV5G_AKA)); AV5G_AKA.rand = AuthenticationVector->rand; AV5G_AKA.autn = AuthenticationVector->autn; ogs_kdf_hxres_star(ausf_ue->rand, ausf_ue->xres_star, ausf_ue->hxres_star); ogs_hex_to_ascii(ausf_ue->hxres_star, sizeof(ausf_ue->hxres_star), hxres_star_string, sizeof(hxres_star_string)); AV5G_AKA.hxres_star = hxres_star_string; UeAuthenticationCtx._5g_auth_data = &AV5G_AKA; memset(&LinksValueSchemeValue, 0, sizeof(LinksValueSchemeValue)); memset(&header, 0, sizeof(header)); header.service.name = (char *)OGS_SBI_SERVICE_NAME_NAUSF_AUTH; header.api.version = (char *)OGS_SBI_API_V1; header.resource.component[0] = (char *)OGS_SBI_RESOURCE_NAME_UE_AUTHENTICATIONS; header.resource.component[1] = ausf_ue->ctx_id; header.resource.component[2] = (char *)OGS_SBI_RESOURCE_NAME_5G_AKA_CONFIRMATION; LinksValueSchemeValue.href = ogs_sbi_server_uri(server, &header); LinksValueScheme = OpenAPI_map_create( (char *)links_member_name(UeAuthenticationCtx.auth_type), &LinksValueSchemeValue); ogs_assert(LinksValueScheme); UeAuthenticationCtx._links = OpenAPI_list_create(); ogs_assert(UeAuthenticationCtx._links); OpenAPI_list_add(UeAuthenticationCtx._links, LinksValueScheme); memset(&sendmsg, 0, sizeof(sendmsg)); memset(&header, 0, sizeof(header)); header.service.name = (char *)OGS_SBI_SERVICE_NAME_NAUSF_AUTH; header.api.version = (char *)OGS_SBI_API_V1; header.resource.component[0] = (char *)OGS_SBI_RESOURCE_NAME_UE_AUTHENTICATIONS; header.resource.component[1] = ausf_ue->ctx_id; sendmsg.http.location = ogs_sbi_server_uri(server, &header); sendmsg.http.content_type = (char *)OGS_SBI_CONTENT_3GPPHAL_TYPE; sendmsg.UeAuthenticationCtx = &UeAuthenticationCtx; response = ogs_sbi_build_response(&sendmsg, OGS_SBI_HTTP_STATUS_CREATED); ogs_assert(response); ogs_assert(true == ogs_sbi_server_send_response(stream, response)); OpenAPI_list_free(UeAuthenticationCtx._links); OpenAPI_map_free(LinksValueScheme); ogs_free(LinksValueSchemeValue.href); ogs_free(sendmsg.http.location); return true; } bool ausf_nudm_ueau_handle_auth_removal_ind(ausf_ue_t *ausf_ue, ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg) { ogs_sbi_message_t sendmsg; ogs_sbi_response_t *response = NULL; ogs_assert(ausf_ue); ogs_assert(stream); memset(&sendmsg, 0, sizeof(sendmsg)); response = ogs_sbi_build_response(&sendmsg, OGS_SBI_HTTP_STATUS_NO_CONTENT); ogs_assert(response); ogs_assert(true == ogs_sbi_server_send_response(stream, response)); return true; } bool ausf_nudm_ueau_handle_result_confirmation_inform(ausf_ue_t *ausf_ue, ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg) { ogs_sbi_message_t sendmsg; ogs_sbi_response_t *response = NULL; char kseaf_string[OGS_KEYSTRLEN(OGS_SHA256_DIGEST_SIZE)]; OpenAPI_confirmation_data_response_t ConfirmationDataResponse; OpenAPI_auth_event_t *AuthEvent = NULL; ogs_assert(ausf_ue); ogs_assert(stream); ogs_assert(recvmsg); AuthEvent = recvmsg->AuthEvent; if (!AuthEvent) { ogs_error("[%s] No AuthEvent", ausf_ue->suci); ogs_assert(true == ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, recvmsg, "No AuthEvent", ausf_ue->suci, NULL)); return false; } if (!recvmsg->http.location) { ogs_error("[%s] No Location", ausf_ue->suci); ogs_assert(true == ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, recvmsg, "No Location", ausf_ue->suci, NULL)); return false; } if (ausf_ue->auth_events_url) ogs_free(ausf_ue->auth_events_url); ausf_ue->auth_events_url = ogs_strdup(recvmsg->http.location); ogs_assert(ausf_ue->auth_events_url); memset(&ConfirmationDataResponse, 0, sizeof(ConfirmationDataResponse)); if (AuthEvent->success == true) ausf_ue->auth_result = OpenAPI_auth_result_AUTHENTICATION_SUCCESS; else ausf_ue->auth_result = OpenAPI_auth_result_AUTHENTICATION_FAILURE; ConfirmationDataResponse.auth_result = ausf_ue->auth_result; ConfirmationDataResponse.supi = ausf_ue->supi; ogs_kdf_kseaf(ausf_ue->serving_network_name, ausf_ue->kausf, ausf_ue->kseaf); ogs_hex_to_ascii(ausf_ue->kseaf, sizeof(ausf_ue->kseaf), kseaf_string, sizeof(kseaf_string)); ConfirmationDataResponse.kseaf = kseaf_string; memset(&sendmsg, 0, sizeof(sendmsg)); sendmsg.ConfirmationDataResponse = &ConfirmationDataResponse; response = ogs_sbi_build_response(&sendmsg, OGS_SBI_HTTP_STATUS_OK); ogs_assert(response); ogs_assert(true == ogs_sbi_server_send_response(stream, response)); return true; }