diff --git a/src/modules/ims_ipsec_pcscf/cmd.c b/src/modules/ims_ipsec_pcscf/cmd.c index b4344000168..82099367ba0 100644 --- a/src/modules/ims_ipsec_pcscf/cmd.c +++ b/src/modules/ims_ipsec_pcscf/cmd.c @@ -435,29 +435,29 @@ static int create_ipsec_tunnel(const struct ip_addr *remote_addr, ipsec_t* s) return -1; } - LM_DBG("Creating security associations: Local IP: %.*s port_pc: %d port_ps: %d; UE IP: %s; port_uc %d port_us %d; spi_pc %u, spi_ps %u, spi_uc %u, spi_us %u\n", + LM_DBG("Creating security associations: Local IP: %.*s port_pc: %d port_ps: %d; UE IP: %s; port_uc %d port_us %d; spi_pc %u, spi_ps %u, spi_uc %u, spi_us %u, alg %.*s, ealg %.*s\n", remote_addr->af == AF_INET ? ipsec_listen_addr.len : ipsec_listen_addr6.len, remote_addr->af == AF_INET ? ipsec_listen_addr.s : ipsec_listen_addr6.s, - s->port_pc, s->port_ps, remote_addr_str, s->port_uc, s->port_us, s->spi_pc, s->spi_ps, s->spi_uc, s->spi_us); + s->port_pc, s->port_ps, remote_addr_str, s->port_uc, s->port_us, s->spi_pc, s->spi_ps, s->spi_uc, s->spi_us, s->r_alg.len, s->r_alg.s, s->r_ealg.len, s->r_ealg.s); // SA1 UE client to P-CSCF server // src adrr dst addr src port dst port - add_sa (sock, remote_addr, ipsec_addr, s->port_uc, s->port_ps, s->spi_ps, s->ck, s->ik, s->r_alg); + add_sa (sock, remote_addr, ipsec_addr, s->port_uc, s->port_ps, s->spi_ps, s->ck, s->ik, s->r_alg, s->r_ealg); add_policy(sock, remote_addr, ipsec_addr, s->port_uc, s->port_ps, s->spi_ps, IPSEC_POLICY_DIRECTION_IN); // SA2 P-CSCF client to UE server // src adrr dst addr src port dst port - add_sa (sock, ipsec_addr, remote_addr, s->port_pc, s->port_us, s->spi_us, s->ck, s->ik, s->r_alg); + add_sa (sock, ipsec_addr, remote_addr, s->port_pc, s->port_us, s->spi_us, s->ck, s->ik, s->r_alg, s->r_ealg); add_policy(sock, ipsec_addr, remote_addr, s->port_pc, s->port_us, s->spi_us, IPSEC_POLICY_DIRECTION_OUT); // SA3 P-CSCF server to UE client // src adrr dst addr src port dst port - add_sa (sock, ipsec_addr, remote_addr, s->port_ps, s->port_uc, s->spi_uc, s->ck, s->ik, s->r_alg); + add_sa (sock, ipsec_addr, remote_addr, s->port_ps, s->port_uc, s->spi_uc, s->ck, s->ik, s->r_alg, s->r_ealg); add_policy(sock, ipsec_addr, remote_addr, s->port_ps, s->port_uc, s->spi_uc, IPSEC_POLICY_DIRECTION_OUT); // SA4 UE server to P-CSCF client // src adrr dst addr src port dst port - add_sa (sock, remote_addr, ipsec_addr, s->port_us, s->port_pc, s->spi_pc, s->ck, s->ik, s->r_alg); + add_sa (sock, remote_addr, ipsec_addr, s->port_us, s->port_pc, s->spi_pc, s->ck, s->ik, s->r_alg, s->r_ealg); add_policy(sock, remote_addr, ipsec_addr, s->port_us, s->port_pc, s->spi_pc, IPSEC_POLICY_DIRECTION_IN); close_mnl_socket(sock); @@ -846,11 +846,20 @@ int ipsec_forward(struct sip_msg* m, udomain_t* d, int _cflags) // for Reply get the dest proto from the received request dst_proto = req->rcv.proto; - // for Reply and TCP sends from P-CSCF server port, for Reply and UDP sends from P-CSCF client port - src_port = dst_proto == PROTO_TCP ? s->port_ps : s->port_pc; + // Check send socket + struct socket_info * client_sock = grep_sock_info(via_host.af == AF_INET ? &ipsec_listen_addr : &ipsec_listen_addr6, src_port, dst_proto); + if(client_sock) { + // for Reply and TCP sends from P-CSCF server port, for Reply and UDP sends from P-CSCF client port + src_port = dst_proto == PROTO_TCP ? s->port_ps : s->port_pc; - // for Reply and TCP sends to UE client port, for Reply and UDP sends to UE server port - dst_port = dst_proto == PROTO_TCP ? s->port_uc : s->port_us; + // for Reply and TCP sends to UE client port, for Reply and UDP sends to UE server port + dst_port = dst_proto == PROTO_TCP ? s->port_uc : s->port_us; + } + else + { + src_port = s->port_pc; + dst_port = s->port_us; + } }else{ // for Request get the dest proto from the saved contact dst_proto = pcontact->received_proto; diff --git a/src/modules/ims_ipsec_pcscf/ipsec.c b/src/modules/ims_ipsec_pcscf/ipsec.c index 45e82ddf3ed..03474745b28 100644 --- a/src/modules/ims_ipsec_pcscf/ipsec.c +++ b/src/modules/ims_ipsec_pcscf/ipsec.c @@ -100,8 +100,15 @@ static void string_to_key(char* dst, const str key_string) } } +static uint choose_nlmsg_seq (void) +{ + static double Tini=0; + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + return(1000*(ts.tv_sec - Tini + (ts.tv_nsec * 1E-9))); // us +} -int add_sa(struct mnl_socket* nl_sock, const struct ip_addr *src_addr_param, const struct ip_addr *dest_addr_param, int s_port, int d_port, int long id, str ck, str ik, str r_alg) +int add_sa(struct mnl_socket* nl_sock, const struct ip_addr *src_addr_param, const struct ip_addr *dest_addr_param, int s_port, int d_port, int long id, str ck, str ik, str r_alg, str r_ealg) { char l_msg_buf[MNL_SOCKET_BUFFER_SIZE]; char l_auth_algo_buf[XFRM_TMPLS_BUF_SIZE]; @@ -121,7 +128,7 @@ int add_sa(struct mnl_socket* nl_sock, const struct ip_addr *src_addr_param, con l_nlh = mnl_nlmsg_put_header(l_msg_buf); l_nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL; l_nlh->nlmsg_type = XFRM_MSG_NEWSA; - l_nlh->nlmsg_seq = time(NULL); + l_nlh->nlmsg_seq = choose_nlmsg_seq(); l_nlh->nlmsg_pid = id; // add Security association @@ -166,6 +173,8 @@ int add_sa(struct mnl_socket* nl_sock, const struct ip_addr *src_addr_param, con l_xsainfo->replay_window = 32; // Add authentication algorithm for this SA + // 3GPP TS 33.203 Annex I + // NOTE: hmac-md5-96 and des-ede3-cbc has been deprecated in Rel12+ // The cast below is performed because alg_key from struct xfrm_algo is char[0] // The point is to provide a continuous chunk of memory with the key in it @@ -189,7 +198,28 @@ int add_sa(struct mnl_socket* nl_sock, const struct ip_addr *src_addr_param, con // add encription algorithm for this SA l_enc_algo = (struct xfrm_algo *)l_enc_algo_buf; + // cipher_null, des, des3_ede, aes strcpy(l_enc_algo->alg_name,"cipher_null"); + if (strncasecmp(r_ealg.s,"aes-cbc",r_ealg.len) == 0) { + LM_DBG("Creating security associations: AES\n"); + strcpy(l_enc_algo->alg_name,"aes"); + l_enc_algo->alg_key_len = ck.len * 4; + string_to_key(l_enc_algo->alg_key, ck); + } + else if (strncasecmp(r_ealg.s,"des-ede3-cbc",r_ealg.len) == 0) { + LM_DBG("Creating security associations: DES, ck.len=%d\n",ck.len); + strcpy(l_enc_algo->alg_name,"des3_ede"); + str ck1; + ck1.s = pkg_malloc (128); + strncpy(ck1.s,ck.s,32); + strncat(ck1.s,ck.s,16); + ck1.len=32+16; + + l_enc_algo->alg_key_len = ck1.len * 4; + string_to_key(l_enc_algo->alg_key, ck1); + + pkg_free(ck1.s); + } mnl_attr_put(l_nlh, XFRMA_ALG_CRYPT, sizeof(struct xfrm_algo) + l_enc_algo->alg_key_len, l_enc_algo); diff --git a/src/modules/ims_ipsec_pcscf/ipsec.h b/src/modules/ims_ipsec_pcscf/ipsec.h index 5d6ea126fa9..ea83fc8a643 100644 --- a/src/modules/ims_ipsec_pcscf/ipsec.h +++ b/src/modules/ims_ipsec_pcscf/ipsec.h @@ -40,7 +40,7 @@ enum ipsec_policy_direction { struct mnl_socket* init_mnl_socket(); void close_mnl_socket(struct mnl_socket* sock); -int add_sa(struct mnl_socket* nl_sock, const struct ip_addr *src_addr_param, const struct ip_addr *dest_addr_param, int s_port, int d_port, int long id, str ck, str ik, str r_alg); +int add_sa(struct mnl_socket* nl_sock, const struct ip_addr *src_addr_param, const struct ip_addr *dest_addr_param, int s_port, int d_port, int long id, str ck, str ik, str r_alg, str r_ealg); int remove_sa(struct mnl_socket* nl_sock, str src_addr_param, str dest_addr_param, int s_port, int d_port, int long id, unsigned int af); int add_policy(struct mnl_socket* mnl_socket, const struct ip_addr *src_addr_param, const struct ip_addr *dest_addr_param, int src_port, int dst_port, int long p_id, enum ipsec_policy_direction dir);