2017-03-02 02:43:26 +00:00
|
|
|
#define TRACE_MODULE _s6a_hss_init
|
2017-02-28 03:03:53 +00:00
|
|
|
|
2017-02-27 14:01:15 +00:00
|
|
|
#include "core_debug.h"
|
2017-03-02 02:43:26 +00:00
|
|
|
#include "core_pool.h"
|
2017-03-02 05:18:24 +00:00
|
|
|
#include "core_lib.h"
|
2017-02-24 01:50:49 +00:00
|
|
|
|
2017-03-03 07:22:09 +00:00
|
|
|
#include "3gpp_kdf.h"
|
2017-03-02 13:47:43 +00:00
|
|
|
#include "milenage.h"
|
|
|
|
|
2017-03-02 02:43:26 +00:00
|
|
|
#include "hss_ctx.h"
|
2017-02-24 01:50:49 +00:00
|
|
|
#include "s6a_app.h"
|
|
|
|
|
2017-03-03 07:22:09 +00:00
|
|
|
#define MAX_SQN_LEN 6
|
|
|
|
#define MAX_AK_LEN 6
|
|
|
|
#define MAX_XRES_LEN 8
|
|
|
|
#define MAX_KASME_LEN 32
|
|
|
|
|
2017-03-03 05:10:06 +00:00
|
|
|
static struct disp_hdl *hdl_fb = NULL; /* handler for fallback cb */
|
|
|
|
static struct disp_hdl *hdl_air = NULL; /* handler for Auth-Info-Request cb */
|
2017-03-03 03:57:19 +00:00
|
|
|
|
2017-02-24 01:50:49 +00:00
|
|
|
/* Default callback for the application. */
|
2017-03-02 02:43:26 +00:00
|
|
|
static int hss_fb_cb(struct msg **msg, struct avp *avp,
|
2017-02-28 12:55:19 +00:00
|
|
|
struct session *sess, void *opaque, enum disp_action *act)
|
2017-02-24 01:50:49 +00:00
|
|
|
{
|
|
|
|
/* This CB should never be called */
|
2017-02-27 14:01:15 +00:00
|
|
|
d_warn("Unexpected message received!");
|
2017-02-24 01:50:49 +00:00
|
|
|
|
|
|
|
return ENOTSUP;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Callback for incoming Test-Request messages */
|
2017-03-02 02:43:26 +00:00
|
|
|
static int hss_air_cb( struct msg **msg, struct avp *avp,
|
2017-02-28 12:55:19 +00:00
|
|
|
struct session *sess, void *opaque, enum disp_action *act)
|
2017-02-24 01:50:49 +00:00
|
|
|
{
|
|
|
|
struct msg *ans, *qry;
|
2017-02-28 15:21:20 +00:00
|
|
|
struct avp *avpch1, *avpch2;
|
2017-03-02 13:47:43 +00:00
|
|
|
struct avp_hdr *hdr;
|
2017-02-28 15:21:20 +00:00
|
|
|
union avp_value val;
|
2017-03-02 13:47:43 +00:00
|
|
|
|
|
|
|
ue_ctx_t *ue = NULL;
|
2017-03-03 07:22:09 +00:00
|
|
|
c_uint8_t sqn[MAX_SQN_LEN];
|
|
|
|
c_uint8_t autn[MAX_KEY_LEN];
|
|
|
|
c_uint8_t ik[MAX_KEY_LEN];
|
|
|
|
c_uint8_t ck[MAX_KEY_LEN];
|
|
|
|
c_uint8_t ak[MAX_AK_LEN];
|
|
|
|
c_uint8_t xres[MAX_XRES_LEN];
|
|
|
|
c_uint8_t kasme[MAX_KASME_LEN];
|
|
|
|
size_t xres_len;
|
|
|
|
c_uint8_t plmn[3];
|
2017-02-24 01:50:49 +00:00
|
|
|
|
2017-03-03 03:57:19 +00:00
|
|
|
d_assert(msg, return EINVAL,);
|
2017-02-24 01:50:49 +00:00
|
|
|
|
2017-03-03 05:10:06 +00:00
|
|
|
/* Create answer header */
|
2017-02-24 01:50:49 +00:00
|
|
|
qry = *msg;
|
2017-03-03 05:10:06 +00:00
|
|
|
fd_msg_new_answer_from_req(fd_g_config->cnf_dict, msg, 0);
|
|
|
|
ans = *msg;
|
2017-03-02 13:47:43 +00:00
|
|
|
|
2017-03-03 05:10:06 +00:00
|
|
|
d_assert(fd_msg_search_avp(qry, s6a_user_name, &avp) == 0 && avp, goto out,);
|
|
|
|
d_assert(fd_msg_avp_hdr(avp, &hdr) == 0 && hdr,,);
|
2017-03-02 13:47:43 +00:00
|
|
|
|
2017-03-03 03:57:19 +00:00
|
|
|
ue = hss_ue_ctx_find_by_imsi(
|
|
|
|
hdr->avp_value->os.data, hdr->avp_value->os.len);
|
2017-03-03 05:10:06 +00:00
|
|
|
if (!ue)
|
|
|
|
{
|
|
|
|
char imsi[MAX_IMSI_LEN];
|
|
|
|
strncpy(imsi, (char*)hdr->avp_value->os.data, hdr->avp_value->os.len);
|
|
|
|
d_warn("Cannot find IMSI:%s\n", imsi);
|
|
|
|
goto out;
|
|
|
|
}
|
2017-03-02 13:47:43 +00:00
|
|
|
|
|
|
|
core_generate_random_bytes(ue->rand, MAX_KEY_LEN);
|
2017-03-03 07:22:09 +00:00
|
|
|
milenage_opc(ue->k, ue->op, ue->opc);
|
|
|
|
milenage_generate(ue->opc, ue->amf, ue->k,
|
2017-03-03 08:33:41 +00:00
|
|
|
core_uint64_to_buffer(ue->sqn, sqn), ue->rand,
|
2017-03-03 07:22:09 +00:00
|
|
|
autn, ik, ck, ak, xres, &xres_len);
|
|
|
|
derive_kasme(ck, ik, plmn, sqn, ak, kasme);
|
2017-03-02 13:47:43 +00:00
|
|
|
|
2017-03-03 07:22:09 +00:00
|
|
|
ue->sqn = (ue->sqn + 32) & 0x7ffffffffff;
|
2017-02-24 01:50:49 +00:00
|
|
|
|
2017-03-03 03:57:19 +00:00
|
|
|
/* Set the Origin-Host, Origin-Realm, andResult-Code AVPs */
|
2017-02-28 12:55:19 +00:00
|
|
|
d_assert(fd_msg_rescode_set(ans, "DIAMETER_SUCCESS", NULL, NULL, 1) == 0,
|
2017-03-03 05:10:06 +00:00
|
|
|
goto out,);
|
2017-02-28 15:21:20 +00:00
|
|
|
|
|
|
|
/* Set the Auth-Session-Statee AVP */
|
2017-03-03 05:10:06 +00:00
|
|
|
d_assert(fd_msg_avp_new(s6a_auth_session_state, 0, &avp) == 0, goto out,);
|
2017-02-28 15:21:20 +00:00
|
|
|
val.i32 = 1;
|
2017-03-03 05:10:06 +00:00
|
|
|
d_assert(fd_msg_avp_setvalue(avp, &val) == 0, goto out,);
|
|
|
|
d_assert(fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp) == 0, goto out,);
|
2017-02-28 15:21:20 +00:00
|
|
|
|
|
|
|
/* Set the Authentication-Info */
|
2017-03-03 05:10:06 +00:00
|
|
|
d_assert(fd_msg_avp_new(s6a_authentication_info, 0, &avp) == 0, goto out,);
|
|
|
|
d_assert(fd_msg_avp_new(s6a_e_utran_vector, 0, &avpch1) == 0, goto out,);
|
2017-02-28 15:21:20 +00:00
|
|
|
|
2017-03-03 05:10:06 +00:00
|
|
|
d_assert(fd_msg_avp_new(s6a_rand, 0, &avpch2) == 0, goto out,);
|
2017-03-03 07:22:09 +00:00
|
|
|
val.os.data = ue->rand;
|
|
|
|
val.os.len = MAX_KEY_LEN;
|
2017-03-03 05:10:06 +00:00
|
|
|
d_assert(fd_msg_avp_setvalue(avpch2, &val) == 0, goto out,);
|
2017-02-28 15:21:20 +00:00
|
|
|
d_assert(fd_msg_avp_add(avpch1, MSG_BRW_LAST_CHILD, avpch2) == 0,
|
2017-03-03 05:10:06 +00:00
|
|
|
goto out,);
|
2017-02-28 15:21:20 +00:00
|
|
|
|
2017-03-03 05:10:06 +00:00
|
|
|
d_assert(fd_msg_avp_new(s6a_xres, 0, &avpch2) == 0, goto out,);
|
2017-03-03 07:22:09 +00:00
|
|
|
val.os.data = xres;
|
|
|
|
val.os.len = xres_len;
|
2017-03-03 05:10:06 +00:00
|
|
|
d_assert(fd_msg_avp_setvalue(avpch2, &val) == 0, goto out,);
|
2017-02-28 15:21:20 +00:00
|
|
|
d_assert(fd_msg_avp_add(avpch1, MSG_BRW_LAST_CHILD, avpch2) == 0,
|
2017-03-03 05:10:06 +00:00
|
|
|
goto out,);
|
2017-02-28 15:21:20 +00:00
|
|
|
|
2017-03-03 05:10:06 +00:00
|
|
|
d_assert(fd_msg_avp_new(s6a_autn, 0, &avpch2) == 0, goto out,);
|
2017-03-03 07:22:09 +00:00
|
|
|
val.os.data = autn;
|
|
|
|
val.os.len = MAX_KEY_LEN;
|
2017-03-03 05:10:06 +00:00
|
|
|
d_assert(fd_msg_avp_setvalue(avpch2, &val) == 0, goto out,);
|
2017-02-28 15:21:20 +00:00
|
|
|
d_assert(fd_msg_avp_add(avpch1, MSG_BRW_LAST_CHILD, avpch2) == 0,
|
2017-03-03 05:10:06 +00:00
|
|
|
goto out,);
|
2017-02-28 15:21:20 +00:00
|
|
|
|
2017-03-03 05:10:06 +00:00
|
|
|
d_assert(fd_msg_avp_new(s6a_kasme, 0, &avpch2) == 0, goto out,);
|
2017-03-03 07:22:09 +00:00
|
|
|
val.os.data = kasme;
|
|
|
|
val.os.len = MAX_KASME_LEN;
|
2017-03-03 05:10:06 +00:00
|
|
|
d_assert(fd_msg_avp_setvalue(avpch2, &val) == 0, goto out,);
|
2017-02-28 15:21:20 +00:00
|
|
|
d_assert(fd_msg_avp_add(avpch1, MSG_BRW_LAST_CHILD, avpch2) == 0,
|
2017-03-03 05:10:06 +00:00
|
|
|
goto out,);
|
2017-02-28 15:21:20 +00:00
|
|
|
|
2017-03-03 05:10:06 +00:00
|
|
|
d_assert(fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avpch1) == 0, goto out,);
|
|
|
|
d_assert(fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp) == 0, goto out,);
|
2017-02-24 01:50:49 +00:00
|
|
|
|
|
|
|
/* Send the answer */
|
2017-03-03 05:10:06 +00:00
|
|
|
fd_msg_send(msg, NULL, NULL);
|
2017-02-24 01:50:49 +00:00
|
|
|
|
|
|
|
/* Add this value to the stats */
|
2017-03-03 05:10:06 +00:00
|
|
|
pthread_mutex_lock(&s6a_config->stats_lock);
|
2017-02-28 02:21:10 +00:00
|
|
|
s6a_config->stats.nb_echoed++;
|
2017-03-03 05:10:06 +00:00
|
|
|
pthread_mutex_unlock(&s6a_config->stats_lock);
|
2017-02-28 12:55:19 +00:00
|
|
|
|
2017-02-24 01:50:49 +00:00
|
|
|
return 0;
|
2017-03-03 03:57:19 +00:00
|
|
|
|
2017-03-03 05:10:06 +00:00
|
|
|
out:
|
|
|
|
fd_msg_rescode_set(ans, "DIAMETER_AUTHENTICATION_REJECTED", NULL, NULL, 1);
|
|
|
|
fd_msg_send(msg, NULL, NULL);
|
2017-03-03 03:57:19 +00:00
|
|
|
|
2017-03-03 05:10:06 +00:00
|
|
|
return 0;
|
2017-02-24 01:50:49 +00:00
|
|
|
}
|
|
|
|
|
2017-03-02 02:43:26 +00:00
|
|
|
int hss_init(void)
|
2017-02-24 01:50:49 +00:00
|
|
|
{
|
|
|
|
struct disp_when data;
|
2017-03-02 02:43:26 +00:00
|
|
|
|
|
|
|
hss_ctx_init();
|
|
|
|
|
|
|
|
/* FIXME : this is a sample UE for testing */
|
|
|
|
{
|
|
|
|
ue_ctx_t *ue;
|
2017-03-02 13:47:43 +00:00
|
|
|
char buf[MAX_KEY_LEN];
|
2017-03-02 02:43:26 +00:00
|
|
|
|
2017-03-02 05:18:24 +00:00
|
|
|
#define K "465B5CE8B199B49FAA5F0A2EE238A6BC"
|
2017-03-02 13:47:43 +00:00
|
|
|
#define UE1_IMSI "001010123456800"
|
|
|
|
#define UE2_IMSI "001010123456796"
|
2017-03-02 02:43:26 +00:00
|
|
|
|
|
|
|
ue = hss_ue_ctx_add();
|
|
|
|
d_assert(ue, return -1, "UE context add failed");
|
|
|
|
|
|
|
|
strcpy((char*)ue->imsi, UE1_IMSI);
|
|
|
|
ue->imsi_len = strlen(UE1_IMSI);
|
2017-03-02 13:47:43 +00:00
|
|
|
memcpy(ue->k, core_ascii_to_hex(K, strlen(K), buf), MAX_KEY_LEN);
|
2017-03-03 07:22:09 +00:00
|
|
|
ue->sqn = 32;
|
2017-03-02 02:43:26 +00:00
|
|
|
|
|
|
|
ue = hss_ue_ctx_add();
|
|
|
|
d_assert(ue, return -1, "UE context add failed");
|
|
|
|
|
|
|
|
strcpy((char*)ue->imsi, UE2_IMSI);
|
|
|
|
ue->imsi_len = strlen(UE2_IMSI);
|
2017-03-02 13:47:43 +00:00
|
|
|
memcpy(ue->k, core_ascii_to_hex(K, strlen(K), buf), MAX_KEY_LEN);
|
2017-03-03 07:22:09 +00:00
|
|
|
ue->sqn = 32;
|
2017-03-02 02:43:26 +00:00
|
|
|
}
|
|
|
|
|
2017-02-24 01:50:49 +00:00
|
|
|
memset(&data, 0, sizeof(data));
|
2017-02-27 14:01:15 +00:00
|
|
|
data.app = s6a_appli;
|
|
|
|
data.command = s6a_cmd_air;
|
2017-02-24 01:50:49 +00:00
|
|
|
|
2017-02-27 14:01:15 +00:00
|
|
|
/* fallback CB if command != unexpected message received */
|
2017-03-02 02:43:26 +00:00
|
|
|
d_assert(fd_disp_register(hss_fb_cb, DISP_HOW_APPID, &data, NULL,
|
2017-03-03 05:10:06 +00:00
|
|
|
&hdl_fb) == 0, return -1,);
|
2017-02-24 01:50:49 +00:00
|
|
|
|
2017-02-27 14:01:15 +00:00
|
|
|
/* Now specific handler for Authentication-Information-Request */
|
2017-03-02 02:43:26 +00:00
|
|
|
d_assert(fd_disp_register(hss_air_cb, DISP_HOW_CC, &data, NULL,
|
2017-03-03 05:10:06 +00:00
|
|
|
&hdl_air) == 0, return -1,);
|
2017-02-24 01:50:49 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-03-02 02:43:26 +00:00
|
|
|
void hss_final(void)
|
2017-02-24 01:50:49 +00:00
|
|
|
{
|
2017-03-03 05:10:06 +00:00
|
|
|
if (hdl_fb) {
|
|
|
|
(void) fd_disp_unregister(&hdl_fb, NULL);
|
2017-02-24 01:50:49 +00:00
|
|
|
}
|
2017-03-03 05:10:06 +00:00
|
|
|
if (hdl_air) {
|
|
|
|
(void) fd_disp_unregister(&hdl_air, NULL);
|
2017-02-24 01:50:49 +00:00
|
|
|
}
|
2017-03-02 02:43:26 +00:00
|
|
|
|
|
|
|
/* FIXME : this is a sample UE for testing */
|
|
|
|
{
|
|
|
|
hss_ue_ctx_remove_all();
|
|
|
|
}
|
|
|
|
|
|
|
|
hss_ctx_final();
|
2017-02-24 01:50:49 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|