| /* |
| * Copyright (c) 2003-2018, Great Software Laboratory Pvt. Ltd. |
| * Copyright (c) 2017 Intel Corporation |
| * Copyright (c) 2019, Infosys Ltd. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <pthread.h> |
| #include <string.h> |
| #include <unistd.h> |
| #include <freeDiameter/freeDiameter-host.h> |
| #include <freeDiameter/libfdcore.h> |
| #include <freeDiameter/libfdproto.h> |
| |
| #include "log.h" |
| #include "err_codes.h" |
| #include "message_queues.h" |
| #include "ipc_api.h" |
| #include "s6a_fd.h" |
| #include "s6a.h" |
| #include "msgType.h" |
| //#include "stage1_s6a_msg.h" |
| #include "hss_message.h" |
| |
| #define DIAMETER_SUCCESS 2001 |
| |
| /** Global and externs**/ |
| extern struct fd_dict_objects g_fd_dict_objs; |
| extern struct fd_dict_data g_fd_dict_data; |
| |
| extern int g_Q_mme_S6a_fd; |
| /**global and externs end**/ |
| |
| /** |
| * @brief Parse authentication information avp recvd in AIA. This contains |
| * important security information for the UE |
| * @param [in] avp_data - AVP value received |
| * @param [out] aia - Security info is filled in to aia msg Q |
| * @return int - error code |
| */ |
| static int |
| get_aia_sec_vector(struct avp *avp_data, struct aia_Q_msg *aia) |
| { |
| struct avp *sub_avp = NULL; |
| struct avp_hdr *element = NULL; |
| |
| CHECK_FCT_DO(fd_msg_avp_hdr(avp_data, &element), |
| return S6A_FD_ERROR); |
| |
| /*Authentication-Info*/ |
| if ((NULL == element) || |
| (element->avp_code != g_fd_dict_data.auth_info.avp_code)) |
| return S6A_FD_ERROR; |
| |
| /*Find first sub child of Authentication-Info*/ |
| CHECK_FCT_DO(fd_msg_browse(avp_data, MSG_BRW_FIRST_CHILD, &sub_avp, |
| NULL), |
| return S6A_FD_ERROR); |
| |
| /*Lookup for sub element "E-UTRAN-Vector" in loop*/ |
| while (NULL != sub_avp) { |
| |
| fd_msg_avp_hdr(sub_avp, &element); |
| |
| if ((NULL != element) && (element->avp_code == |
| g_fd_dict_data.E_UTRAN_vector.avp_code)) |
| /*Found the entry*/ |
| break; |
| |
| /*Iterate sub entries*/ |
| CHECK_FCT_DO(fd_msg_browse(sub_avp, MSG_BRW_NEXT, &sub_avp, |
| NULL), |
| return S6A_FD_ERROR); |
| } |
| |
| /*Element "E-UTRAN-Vector" not found, then return*/ |
| if (NULL == sub_avp) return S6A_FD_ERROR; |
| |
| CHECK_FCT_DO(fd_msg_browse(sub_avp, MSG_BRW_FIRST_CHILD, |
| &sub_avp, NULL), |
| return S6A_FD_ERROR); |
| |
| /*Iterate all sub elements of E-UTRAN-Vector and filter sec vector params*/ |
| for (; |
| NULL != sub_avp; /*Till null*/ |
| // CHECK_FCT_DO(fd_msg_browse(sub_avp, MSG_BRW_NEXT, &sub_avp, NULL), |
| // return S6A_FD_ERROR) /*Iterate elements*/ |
| ) { |
| |
| fd_msg_avp_hdr(sub_avp, &element); |
| |
| /*AVP: RAND(1447) l=28 f=VM- vnd=TGPP*/ |
| if (element->avp_code == g_fd_dict_data.RAND.avp_code) { |
| |
| //if (element->avp_value->os.len > sizeof(aia->sec.rand.val)) |
| if (element->avp_value->os.len > AIA_RAND_SIZE) |
| return S6A_FD_ERROR; |
| |
| aia->sec.rand.len = element->avp_value->os.len; |
| memcpy(aia->sec.rand.val, element->avp_value->os.data, |
| aia->sec.rand.len); |
| } |
| |
| /*AVP: XRES(1448) l=20 f=VM- vnd=TGPP*/ |
| if (element->avp_code == g_fd_dict_data.XRES.avp_code) { |
| |
| if (element->avp_value->os.len > AIA_RES_SIZE) |
| return S6A_FD_ERROR; |
| |
| aia->sec.xres.len = element->avp_value->os.len; |
| memcpy(aia->sec.xres.val, element->avp_value->os.data, |
| aia->sec.xres.len); |
| } |
| |
| /*AVP: AUTN(1449) l=28 f=VM- vnd=TGPP*/ |
| if (element->avp_code == g_fd_dict_data.AUTN.avp_code) { |
| |
| if (element->avp_value->os.len > AIA_AUTN_SIZE) |
| return S6A_FD_ERROR; |
| |
| aia->sec.autn.len = element->avp_value->os.len; |
| memcpy(aia->sec.autn.val, element->avp_value->os.data, |
| aia->sec.autn.len); |
| } |
| |
| /*AVP: KASME(1450) l=44 f=VM- vnd=TGPP*/ |
| if (element->avp_code == g_fd_dict_data.KASME.avp_code) { |
| |
| if (element->avp_value->os.len > AIA_KASME_SIZE) |
| return S6A_FD_ERROR; |
| |
| aia->sec.kasme.len = element->avp_value->os.len; |
| memcpy(aia->sec.kasme.val, element->avp_value->os.data, |
| aia->sec.kasme.len); |
| } |
| |
| CHECK_FCT_DO(fd_msg_browse(sub_avp, MSG_BRW_NEXT, &sub_avp, NULL), |
| return S6A_FD_ERROR) /*Iterate elements*/ |
| |
| } |
| |
| return SUCCESS; |
| } |
| |
| static |
| void send_to_stage2(struct s6_incoming_msg_data_t *incoming_msg_p) |
| { |
| TRACE_ENTRY("\n****************WRITE TO g_Q_mme_S6a_fd"); |
| |
| incoming_msg_p->destInstAddr = htonl(mmeAppInstanceNum_c); |
| incoming_msg_p->srcInstAddr = htonl(s6AppInstanceNum_c); |
| |
| /*Send to stage2 queue*/ |
| send_tipc_message(g_Q_mme_S6a_fd, mmeAppInstanceNum_c, (char*)incoming_msg_p, S6_READ_MSG_BUF_SIZE); |
| } |
| |
| int aia_resp_callback(struct msg **buf, struct avp *_avp, |
| struct session *session, void *data, |
| enum disp_action * action) |
| { |
| TRACE_ENTRY("\n****************ANJANA ****** Callback ----- >AIA recvd\n"); |
| int res = SUCCESS, sess_id_len; |
| struct msg *resp = *buf; |
| struct avp *avp_ptr = NULL; |
| unsigned char *sess_id= NULL; |
| struct s6_incoming_msg_data_t s6_incoming_msgs; |
| struct avp_hdr *avp_hdr = NULL; |
| |
| log_msg(LOG_INFO, "\nCallback ----- >AIA recvd\n"); |
| |
| dump_fd_msg(resp); |
| //TODO - workaround for dump call. Remove this. |
| { |
| char * buf = NULL; |
| size_t len = 0; |
| printf("*********AIA CALLBACK******%s\n", fd_msg_dump_treeview(&buf, &len, NULL, resp, |
| fd_g_config->cnf_dict, 0, 1)); |
| free(buf); |
| } |
| |
| CHECK_FCT_DO(fd_sess_getsid(session, &sess_id, (size_t*)&sess_id_len), |
| return S6A_FD_ERROR); |
| |
| log_msg(LOG_INFO, "\nCallback ----- >session id=%s \n",sess_id); |
| |
| s6_incoming_msgs.msg_type = auth_info_answer; |
| /*Retrieve UE index embedded in to session ID string at AIR time*/ |
| s6_incoming_msgs.ue_idx = get_ue_idx_from_fd_resp(sess_id, sess_id_len); |
| |
| /*AVP: Result-Code(268)*/ |
| fd_msg_search_avp(resp, g_fd_dict_objs.res_code, &avp_ptr); |
| |
| if (NULL != avp_ptr) { |
| fd_msg_avp_hdr(avp_ptr, &avp_hdr); |
| res = avp_hdr->avp_value->u32; |
| |
| if (DIAMETER_SUCCESS != res) { |
| log_msg(LOG_ERROR, "Diameter error with HSS\n"); |
| } |
| //Vikram: chk res = SUCCESS; |
| |
| } else { |
| struct fd_result fd_res; |
| |
| avp_ptr = NULL; |
| fd_msg_search_avp(resp, g_fd_dict_objs.exp_res, |
| &avp_ptr); |
| |
| if (NULL == avp_ptr) { |
| res = S6A_FD_ERROR; |
| } else if (parse_fd_result(avp_ptr, &fd_res) != 0) { |
| res = S6A_FD_ERROR; |
| } else res = fd_res.result_code; |
| } |
| |
| if (DIAMETER_SUCCESS == res) { |
| /*AVP: Authentication-Info*/ |
| fd_msg_search_avp(resp, g_fd_dict_objs.auth_info, |
| &avp_ptr); |
| |
| if (NULL != avp_ptr) { |
| if (get_aia_sec_vector(avp_ptr, &s6_incoming_msgs.msg_data.aia_Q_msg_m) != SUCCESS) |
| res = S6A_FD_ERROR; |
| } else { |
| res = S6A_FD_ERROR; |
| } |
| } |
| |
| /*Handled fd msg, do cleanup*/ |
| fd_msg_free(*buf); |
| |
| *buf = NULL; |
| |
| if (DIAMETER_SUCCESS != res) s6_incoming_msgs.msg_data.aia_Q_msg_m.res = S6A_AIA_FAILED; |
| |
| send_to_stage2(&s6_incoming_msgs); |
| |
| return SUCCESS; |
| } |
| |
| void |
| handle_perf_hss_aia(int ue_idx, struct hss_aia_msg *aia) |
| { |
| struct s6_incoming_msg_data_t msg; |
| |
| msg.ue_idx = ue_idx; |
| msg.msg_type = auth_info_answer; |
| msg.msg_data.aia_Q_msg_m.res= 0; |
| memcpy(&(msg.msg_data.aia_Q_msg_m.sec.rand), &(aia->rand), sizeof(RAND)); |
| memcpy(&(msg.msg_data.aia_Q_msg_m.sec.xres), &(aia->xres), sizeof(XRES)); |
| memcpy(&(msg.msg_data.aia_Q_msg_m.sec.autn), &(aia->autn), sizeof(AUTN)); |
| memcpy(&(msg.msg_data.aia_Q_msg_m.sec.kasme), &(aia->kasme), sizeof(KASME)); |
| |
| send_to_stage2(&msg);/*handle diameter error*/ |
| } |