From aef328d68bca957c27d324d9c3c3a60e984d6c65 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 13 Dec 2017 19:50:19 +0000 Subject: [PATCH] Added the ability to the HSS to be configured through a .csv. --- srsepc/epc.conf.example | 17 +++++++ srsepc/hdr/hss/hss.h | 23 +++++++-- srsepc/src/hss/hss.cc | 105 ++++++++++++++++++++++++++++++++++++---- srsepc/src/main.cc | 3 ++ srsepc/src/mme/s1ap.cc | 6 ++- srsepc/user_db.csv | 13 +++++ 6 files changed, 152 insertions(+), 15 deletions(-) create mode 100644 srsepc/user_db.csv diff --git a/srsepc/epc.conf.example b/srsepc/epc.conf.example index 1836f8fb8..544e153d1 100644 --- a/srsepc/epc.conf.example +++ b/srsepc/epc.conf.example @@ -21,6 +21,23 @@ mcc = 001 mnc = 01 mme_bind_addr = 127.0.0.0/24 +##################################################################### +# HSS configuration +# +# db_file: Location of .csv file that stores UEs information. +# +##################################################################### +[hss] +db_file = user_db.csv + + +##################################################################### +# SP-GW configuration +# +# gtpu_bind_addr: Location of .csv file that stores UEs information. +# +##################################################################### + [spgw] gtpu_bind_addr=127.0.0.2 sgi_if_addr=172.0.0.1 diff --git a/srsepc/hdr/hss/hss.h b/srsepc/hdr/hss/hss.h index f8a23809d..06ca26842 100644 --- a/srsepc/hdr/hss/hss.h +++ b/srsepc/hdr/hss/hss.h @@ -38,14 +38,22 @@ #include "srslte/common/logger_file.h" #include "srslte/common/log_filter.h" #include "srslte/common/buffer_pool.h" - +#include namespace srsepc{ typedef struct{ - std::string ue_file; + std::string db_file; }hss_args_t; +typedef struct{ + std::string name; + uint64_t imsi; + uint8_t key[16]; + uint8_t op[16]; + uint8_t amf[2]; +}hss_ue_ctx_t; + class hss @@ -54,12 +62,16 @@ public: static hss* get_instance(void); static void cleanup(void); int init(hss_args_t *hss_args, srslte::log_filter* hss_log); - + bool read_db_file(std::string db_file); + void get_sqn(uint8_t sqn[6]); void gen_rand(uint8_t rand_[16]); bool get_k_amf_op(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *op); bool gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t *rand, uint8_t *xres); - + + std::vector split_string(const std::string &str, char delimiter); + void get_uint_vec_from_hex_str(const std::string &key_str, uint8_t *key, uint len); + private: hss(); @@ -68,6 +80,9 @@ private: uint64_t m_sqn; //48 bits srslte::byte_buffer_pool *m_pool; + std::ifstream m_db_file; + + std::map m_imsi_to_ue_ctx; /*Logs*/ srslte::log_filter *m_hss_log; diff --git a/srsepc/src/hss/hss.cc b/srsepc/src/hss/hss.cc index 98058b77b..32bc1d54d 100644 --- a/srsepc/src/hss/hss.cc +++ b/srsepc/src/hss/hss.cc @@ -41,12 +41,16 @@ boost::mutex hss_instance_mutex; hss::hss() :m_sqn(0x112233445566) { - m_pool = srslte::byte_buffer_pool::get_instance(); + m_pool = srslte::byte_buffer_pool::get_instance(); return; } hss::~hss() { + if(m_db_file.is_open()) + { + m_db_file.close(); + } return; } @@ -73,15 +77,57 @@ hss::cleanup(void) int hss::init(hss_args_t *hss_args, srslte::log_filter *hss_log) { - /*Init loggers*/ srand(time(NULL)); - + /*Init loggers*/ m_hss_log = hss_log; m_hss_log->info("HSS Initialized\n"); m_hss_log->console("HSS Initialized\n"); + + /*Read user information from DB*/ + read_db_file(hss_args->db_file); return 0; } +bool +hss::read_db_file(std::string db_filename) +{ + m_db_file.open(db_filename.c_str()); + if(!m_db_file.is_open()) + { + return false; + } + m_hss_log->info("Opended DB file: %s\n", db_filename.c_str() ); + + std::string line; + while (std::getline(m_db_file, line)) + { + if(line[0] != '#') + { + std::vector split = split_string(line,','); + if(split.size()!=5) + { + m_hss_log->error("Error parsing .csv file %d\n"); + return false; + } + hss_ue_ctx_t *ue_ctx = new hss_ue_ctx_t; + ue_ctx->name = split[0]; + ue_ctx->imsi = atoll(split[1].c_str()); + get_uint_vec_from_hex_str(split[2],ue_ctx->key,16); + get_uint_vec_from_hex_str(split[3],ue_ctx->op,16); + get_uint_vec_from_hex_str(split[4],ue_ctx->amf,2); + + m_hss_log->debug("Added user from DB, IMSI: %015lu\n", ue_ctx->imsi); + m_hss_log->debug_hex(ue_ctx->key, 16, "User Key : "); + m_hss_log->debug_hex(ue_ctx->op, 16, "User OP : "); + m_hss_log->debug_hex(ue_ctx->amf, 2, "AMF : "); + + m_imsi_to_ue_ctx.insert(std::pair(ue_ctx->imsi,ue_ctx)); + } + } + + return true; +} + bool hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t *rand, uint8_t *xres) { @@ -154,22 +200,24 @@ bool hss::get_k_amf_op(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *op ) { + /* uint8_t k_tmp[16] ={0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff}; uint8_t amf_tmp[2]={0x80,0x00}; uint8_t op_tmp[16]={0x63,0xbf,0xA5,0x0E,0xE6,0x52,0x33,0x65,0xFF,0x14,0xC1,0xF4,0x5F,0x88,0x73,0x7D}; - - if(imsi != 1010123456789) + */ + std::map::iterator ue_ctx_it = m_imsi_to_ue_ctx.find(imsi); + if(ue_ctx_it == m_imsi_to_ue_ctx.end()) { m_hss_log->info("User not found. IMSI: %015lu\n",imsi); m_hss_log->console("User not found. IMSI: %015lu\n",imsi); return false; } - + hss_ue_ctx_t *ue_ctx = ue_ctx_it->second; m_hss_log->info("Found User %015lu\n",imsi); m_hss_log->console("Found User %015lu\n",imsi); - memcpy(k,k_tmp,16); - memcpy(amf,amf_tmp,2); - memcpy(op,op_tmp,16); + memcpy(k,ue_ctx->key,16); + memcpy(amf,ue_ctx->amf,2); + memcpy(op,ue_ctx->op,16); return true; } @@ -195,4 +243,43 @@ hss::gen_rand(uint8_t rand_[16]) return; } +/* Helper functions*/ +std::vector +hss::split_string(const std::string &str, char delimiter) +{ + std::vector tokens; + std::string token; + std::istringstream tokenStream(str); + + while (std::getline(tokenStream, token, delimiter)) + { + tokens.push_back(token); + } + return tokens; +} + +void +hss::get_uint_vec_from_hex_str(const std::string &key_str, uint8_t *key, uint len) +{ + const char *pos = key_str.c_str(); + + for (uint count = 0; count < len; count++) { + sscanf(pos, "%2hhx", &key[count]); + pos += 2; + } + + return; +} + + /* +uint64_t +string_to_imsi() +{ + uint64_t imsi = 0; + for(int i=0;i<=14;i++){ + imsi += attach_req.eps_mobile_id.imsi[i]*std::pow(10,14-i); + } + return imsi; +} + */ } //namespace srsepc diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index b75fcd32d..5db3235fa 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -73,6 +73,7 @@ parse_args(all_args_t *args, int argc, char* argv[]) { string mme_bind_addr; string spgw_bind_addr; string sgi_if_addr; + string hss_db_file; // Command line only options bpo::options_description general("General options"); @@ -92,6 +93,7 @@ parse_args(all_args_t *args, int argc, char* argv[]) { ("mme.mcc", bpo::value(&mcc)->default_value("001"), "Mobile Country Code") ("mme.mnc", bpo::value(&mnc)->default_value("01"), "Mobile Network Code") ("mme.mme_bind_addr", bpo::value(&mme_bind_addr)->default_value("127.0.0.1"),"IP address of MME for S1 connnection") + ("hss.db_file", bpo::value(&hss_db_file)->default_value("ue_db.csv"),".csv file that stores UE's keys") ("spgw.gtpu_bind_addr", bpo::value(&spgw_bind_addr)->default_value("127.0.0.1"),"IP address of SP-GW for the S1-U connection") ("spgw.sgi_if_addr", bpo::value(&sgi_if_addr)->default_value("176.16.0.1"),"IP address of TUN interface for the SGi connection") ; @@ -168,6 +170,7 @@ parse_args(all_args_t *args, int argc, char* argv[]) { args->mme_args.s1ap_args.mme_bind_addr = mme_bind_addr; args->spgw_args.gtpu_bind_addr = spgw_bind_addr; args->spgw_args.sgi_if_addr = sgi_if_addr; + args->hss_args.db_file = hss_db_file; return; } diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index a6bd64faf..370d7318a 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -627,6 +627,7 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: } erab_ctxt->transportLayerAddress.n_bits = 32; //IPv4 uint32_t sgw_s1u_ip = htonl(cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid.ipv4); + //uint32_t sgw_s1u_ip = cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid.ipv4; uint8_t *tmp_ptr = erab_ctxt->transportLayerAddress.buffer; liblte_value_2_bits(sgw_s1u_ip, &tmp_ptr, 32);//FIXME consider ipv6 @@ -833,9 +834,10 @@ s1ap::activate_eps_bearer(uint32_t mme_s1ap_id, uint8_t ebi) return; } ue_ctx_t * ue_ctx = ue_ctx_it->second; - if (ue_ctx->erabs_ctx[ebi].state != ERAB_CTX_REQUESTED) + if (ue_ctx->erabs_ctx[ebi].state != ERAB_CTX_SETUP) { - m_s1ap_log->error("EPS Bearer could not be activated. EPS Bearer id %d\n",ebi); + m_s1ap_log->error("EPS Bearer could not be activated. MME S1AP Id %d, EPS Bearer id %d, state %d\n",mme_s1ap_id,ebi,ue_ctx->erabs_ctx[ebi].state); + m_s1ap_log->console("EPS Bearer could not be activated. MME S1AP Id %d, EPS Bearer id %d\n",mme_s1ap_id,ebi,ue_ctx->erabs_ctx[ebi].state); return; } diff --git a/srsepc/user_db.csv b/srsepc/user_db.csv new file mode 100644 index 000000000..f306adaa3 --- /dev/null +++ b/srsepc/user_db.csv @@ -0,0 +1,13 @@ +# +# .csv to store UE's information in HSS +# Kept in the following format: "Name,IMSI,Key,OP,AMF" +# +# Name: Human readable name to help distinguish UE's. Largely ignored by the HSS +# IMSI: UE's IMSI value +# Key: UE's key, where other keys are derived from. Stored in hexadecimal +# OP: Operator's code, sotred in hexadecimal +# AMF: Authentication management feild, stored in hexadecimal +# +# Note: Lines starting by '#' are ignored +ue1,001010123456789,00112233445566778899aabbccddeeff,63BFA50EE6523365FF14C1F45F88737D,8000 +ue2,001010123456780,00112233445566778899aabbccddeeaa,63BFA50EE6523365FF14C1F45F88737D,2000