diff --git a/.gitignore b/.gitignore index 6961e5f7e..3878eca51 100644 --- a/.gitignore +++ b/.gitignore @@ -51,3 +51,7 @@ cmake_install.cmake # Ignore autogenerated version.h. /include/version.cmake /version.h + +.idea +cmake-build-debug +*.pcap \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 6a65f2e10..995f171f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -252,4 +252,6 @@ if(USE_SCTP) endif() endif() +add_subdirectory(calc_keys) + install(TARGETS sipp DESTINATION bin) diff --git a/calc_keys/CMakeLists.txt b/calc_keys/CMakeLists.txt new file mode 100644 index 000000000..b5f5cade4 --- /dev/null +++ b/calc_keys/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.4) + +# set the project name +project(SIPp) + +# specify the C++ standard +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED True) +set(CMAKE_CXX_EXTENSIONS False) +# specify the C++ standard on older CMake (<3.8) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") + +add_executable(calc_ck calc_ck.cpp ../src/milenage.c ../src/md5.c ../src/rijndael.c ../src/strings.cpp) +target_include_directories(calc_ck PRIVATE ../include) \ No newline at end of file diff --git a/calc_keys/calc_ck.cpp b/calc_keys/calc_ck.cpp new file mode 100644 index 000000000..9fc292fb0 --- /dev/null +++ b/calc_keys/calc_ck.cpp @@ -0,0 +1,122 @@ +// +// Created by dbori on 18.06.2023. +// + +#include +#include +#include +#include "auth.hpp" +#include "milenage.h" +#include "strings.hpp" + +#define STR_K_LEN (CKLEN * 2 + 2 + 1) +typedef char STR_KEY[STR_K_LEN]; + +char digit_to_hex(const char c) { + if (c > 15 || c < 0) + return 0; + if (c > 9) + return 'a' + c - 10; + return '0' + c; +} + +void key_to_hex(const CK key, STR_KEY res) { + bzero(res, STR_K_LEN); + int i = 2; + res[0] = '0'; + res[1] = 'x'; + while (i < STR_K_LEN - 1) { + res[i] = digit_to_hex(key[(i - 2) / 2] >> 4); + res[i + 1] = digit_to_hex(key[(i - 2) / 2] & 0x0f); + i += 2; + } + res[STR_K_LEN - 1] = '\0'; +} + +void parse_key_str(const char *key_str, K key, size_t key_len) { + size_t pos; + bzero(key, key_len); + size_t len = strlen(key_str); + if (key_str[0] == '0' && key_str[1] == 'x') { + pos = 2; + while (pos < strlen(key_str)) { + if (key_str[pos] == '\0') + break; + if (!(pos % 2)) + key[pos / 2 - 1] += get_decimal_from_hex(key_str[pos]) << 4; + else + key[pos / 2 - 1] += get_decimal_from_hex(key_str[pos]); + pos++; + } + return; + } else if (len && key_str[0] == '"' && key_str[len - 1] == '"') { + int pos_s = 1, pos_k = 0; + while (pos_s < len - 1 && pos_k < key_len) { + if (key_str[pos_s] != '\\') + key[pos_k] = key_str[pos_s]; + else + ++pos_s; + ++pos_s; + ++pos_k; + } + return; + } else { + int pos_s = 0, pos_k = 0; + while (pos_s < len && pos_k < key_len) { + if (key_str[pos_s] != '\\') + key[pos_k] = key_str[pos_s]; + else + ++pos_s; + ++pos_s; + ++pos_k; + } + } +} + +int main(int argc, char *argv[]) { + OP op; + RAND rnd; + K k; + RES res; + AK ak; + CK ck; + IK ik; + + + if (argc != 5) + exit(-1); + if (!strcmp(argv[3], "null")) { + std::cout << "''"; + exit(0); + } + int nonce_len; + auto nonce = base64_decode_string(argv[2], strlen(argv[2]), &nonce_len); + + if (nonce_len < RANDLEN + AUTNLEN) { + if (nonce) + free(nonce); + std::cerr << "Incorrect length of nonce, expected " << RANDLEN + AUTNLEN << std::endl; + exit(-1); + } + + memcpy(rnd, nonce, RANDLEN); + parse_key_str(argv[1], k, sizeof k); + parse_key_str(argv[4], op, sizeof op); + + bzero(op, sizeof op); + bzero(ak, sizeof ak); + + f2345(k, rnd, res, ck, ik, ak, op); + if (strstr(argv[0], "calc_ck")) { + STR_KEY s_ck; + key_to_hex(ck, s_ck); + std::cout << s_ck; + } else if (strstr(argv[0], "calc_ik")) { + STR_KEY s_ik; + key_to_hex(ik, s_ik); + std::cout << s_ik; + } else { + std::cout << "Program should be called as 'calc_ck' or 'calc_ik' but called as " << argv[0] << std::endl; + exit(-1); + } +} \ No newline at end of file diff --git a/example/ipsec/ipsec/ipsec_E_Drop.sh b/example/ipsec/ipsec/ipsec_E_Drop.sh new file mode 100644 index 000000000..58ee382b4 --- /dev/null +++ b/example/ipsec/ipsec/ipsec_E_Drop.sh @@ -0,0 +1,35 @@ +#!/bin/bash +# +# User Endpoint drop all 4 SA +# +# \author Dragos Vingarzan vingarzan -at- fokus dot fraunhofer dot de +# \author xfrm Serge S. Yuriev nevian -at- nevian dot org +# + +ue=$1 +port_uc=$2 +port_us=$3 + +pcscf=$4 +port_pc=$5 +port_ps=$6 + +spi_uc=$7 +spi_us=$8 + +spi_pc=$9 +spi_ps=${10} + + + +ip xfrm policy del src $ue dst $pcscf sport $port_uc dport $port_ps dir out +ip xfrm state del src $ue dst $pcscf proto esp spi $spi_ps + +ip xfrm policy del src $ue dst $pcscf sport $port_us dport $port_pc dir out +ip xfrm state del src $ue dst $pcscf proto esp spi $spi_pc + +ip xfrm policy del src $pcscf dst $ue sport $port_ps dport $port_uc dir in +ip xfrm state del src $pcscf dst $ue proto esp spi $spi_uc + +ip xfrm policy del src $pcscf dst $ue sport $port_pc dport $port_us dir in +ip xfrm state del src $pcscf dst $ue proto esp spi $spi_us diff --git a/example/ipsec/ipsec/ipsec_E_Inc_Req.sh b/example/ipsec/ipsec/ipsec_E_Inc_Req.sh new file mode 100644 index 000000000..121402e60 --- /dev/null +++ b/example/ipsec/ipsec/ipsec_E_Inc_Req.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# +# UserEndpoint SA for Incoming Requests ( US <- PC ) +# +# \author Dragos Vingarzan vingarzan -at- fokus dot fraunhofer dot de +# \author xfrm Serge S. Yuriev nevian -at- nevian dot org +# + +ue=$1 +port_us=$2 +pcscf=$3 +port_pc=$4 + +spi_us=$5 + +ealg=$6 +ck=$7 +alg=$8 +ik=$9 + +if [ "$6" = "null" ] +then + ck='""' +fi + +case "$ealg" in + "aes-cbc" ) + ealg="cbc(aes)" + ;; + "des-ede3-cbc" ) + ealg="cbc(des3_ede)" + ;; + "null" ) + ealg="ecb(cipher_null)" + ;; + * ) + echo Unknown EALG $ealg exiting.. + exit 127 + ;; +esac + +case "$alg" in + "null" ) + alg="digest_null" + ;; + "hmac-sha-1-96" ) + alg="hmac(sha1)" + ;; + "hmac-md5-96" ) + alg="hmac(md5)" + ;; + * ) + echo Unknown ALG $alg exiting.. + exit 127 + ;; +esac + +ip xfrm policy add src $pcscf dst $ue sport $port_pc dport $port_us dir in tmpl proto esp reqid $$ mode transport +ip xfrm state add src $pcscf dst $ue proto esp spi $spi_us mode transport enc $ealg $ck auth $alg $ik reqid $$ diff --git a/example/ipsec/ipsec/ipsec_E_Inc_Rpl.sh b/example/ipsec/ipsec/ipsec_E_Inc_Rpl.sh new file mode 100644 index 000000000..760788758 --- /dev/null +++ b/example/ipsec/ipsec/ipsec_E_Inc_Rpl.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# +# UserEndpoint SA for Incoming Replies ( UC <- PS ) +# +# \author Dragos Vingarzan vingarzan -at- fokus dot fraunhofer dot de +# \author xfrm Serge S. Yuriev nevian -at- nevian dot org +# + +ue=$1 +port_uc=$2 +pcscf=$3 +port_ps=$4 + +spi_uc=$5 + +ealg=$6 +ck=$7 +alg=$8 +ik=$9 + +if [ "$6" = "null" ] +then + ck='""' +fi + +case "$ealg" in + "aes-cbc" ) + ealg="cbc(aes)" + ;; + "des-ede3-cbc" ) + ealg="cbc(des3_ede)" + ;; + "null" ) + ealg="ecb(cipher_null)" + ;; + * ) + echo Unknown EALG $ealg exiting.. + exit 127 + ;; +esac + +case "$alg" in + "null" ) + alg="digest_null" + ;; + "hmac-sha-1-96" ) + alg="hmac(sha1)" + ;; + "hmac-md5-96" ) + alg="hmac(md5)" + ;; + * ) + echo Unknown ALG $alg exiting.. + exit 127 + ;; +esac + +ip xfrm policy add src $pcscf dst $ue sport $port_ps dport $port_uc dir in tmpl proto esp reqid $$ mode transport +ip xfrm state add src $pcscf dst $ue proto esp spi $spi_uc mode transport enc $ealg $ck auth $alg $ik reqid $$ diff --git a/example/ipsec/ipsec/ipsec_E_Out_Req.sh b/example/ipsec/ipsec/ipsec_E_Out_Req.sh new file mode 100644 index 000000000..7089892bd --- /dev/null +++ b/example/ipsec/ipsec/ipsec_E_Out_Req.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# +# UserEndpoint SA for Outgoing Requests ( UC -> PS ) +# +# \author Dragos Vingarzan vingarzan -at- fokus dot fraunhofer dot de +# \author xfrm Serge S. Yuriev nevian -at- nevian dot org +# + +ue=$1 +port_uc=$2 +pcscf=$3 +port_ps=$4 + +spi_ps=$5 + +ealg=$6 +ck=$7 +alg=$8 +ik=$9 + +if [ "$6" = "null" ] +then + ck='""' +fi + +case "$ealg" in + "aes-cbc" ) + ealg="cbc(aes)" + ;; + "des-ede3-cbc" ) + ealg="cbc(des3_ede)" + ;; + "null" ) + ealg="ecb(cipher_null)" + ;; + * ) + echo Unknown EALG $ealg exiting.. + exit 127 + ;; +esac + +case "$alg" in + "null" ) + alg="digest_null" + ;; + "hmac-sha-1-96" ) + alg="hmac(sha1)" + ;; + "hmac-md5-96" ) + alg="hmac(md5)" + ;; + * ) + echo Unknown ALG $alg exiting.. + exit 127 + ;; +esac + +ip xfrm policy add src $ue dst $pcscf sport $port_uc dport $port_ps dir out tmpl proto esp reqid $$ mode transport +ip xfrm state add src $ue dst $pcscf proto esp spi $spi_ps mode transport enc $ealg $ck auth $alg $ik reqid $$ diff --git a/example/ipsec/ipsec/ipsec_E_Out_Rpl.sh b/example/ipsec/ipsec/ipsec_E_Out_Rpl.sh new file mode 100644 index 000000000..1f0a63983 --- /dev/null +++ b/example/ipsec/ipsec/ipsec_E_Out_Rpl.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# +# UserEndpoint SA for Outgoing Replies ( US -> PC ) +# +# \author Dragos Vingarzan vingarzan -at- fokus dot fraunhofer dot de +# \author xfrm Serge S. Yuriev nevian -at- nevian dot org +# + +ue=$1 +port_us=$2 +pcscf=$3 +port_pc=$4 + +spi_pc=$5 + +ealg=$6 +ck=$7 +alg=$8 +ik=$9 + +if [ "$6" = "null" ] +then + ck='""' +fi + +case "$ealg" in + "aes-cbc" ) + ealg="cbc(aes)" + ;; + "des-ede3-cbc" ) + ealg="cbc(des3_ede)" + ;; + "null" ) + ealg="ecb(cipher_null)" + ;; + * ) + echo Unknown EALG $ealg exiting.. + exit 127 + ;; +esac + +case "$alg" in + "null" ) + alg="digest_null" + ;; + "hmac-sha-1-96" ) + alg="hmac(sha1)" + ;; + "hmac-md5-96" ) + alg="hmac(md5)" + ;; + * ) + echo Unknown ALG $alg exiting.. + exit 127 + ;; +esac + +ip xfrm policy add src $ue dst $pcscf sport $port_us dport $port_pc dir out tmpl proto esp reqid $$ mode transport +ip xfrm state add src $ue dst $pcscf proto esp spi $spi_pc mode transport enc $ealg $ck auth $alg $ik reqid $$ diff --git a/example/ipsec/runIPSEC.sh b/example/ipsec/runIPSEC.sh new file mode 100644 index 000000000..cf3ba995d --- /dev/null +++ b/example/ipsec/runIPSEC.sh @@ -0,0 +1,4 @@ +#!/bin/bash +./sipp 127.0.0.3 -t t1 -p 3061 -sf scenarios/regIPSEC1.xml -m 1 -trace_err -trace_msg -au 001019901003516@ims.mnc001.mcc001.3gppnetwork.org -ap test -auth_pipe b.dat +./sipp 127.0.0.3:`cut -s -d";" -f4 spis.csv` -t t1 -p 12345 -sf scenarios/regIPSEC2.xml -m 1 -trace_err -trace_msg -inf spis.csv -au 001019901003516@ims.mnc001.mcc001.3gppnetwork.org -ap test -auth_pipe b.dat +./sipp 127.0.0.3 -t t1 -p 3062 -sf scenarios/regIPSEC3.xml -m 1 -trace_err -trace_msg diff --git a/example/ipsec/scenarios/regIPSEC1.xml b/example/ipsec/scenarios/regIPSEC1.xml new file mode 100644 index 000000000..519afa5c3 --- /dev/null +++ b/example/ipsec/scenarios/regIPSEC1.xml @@ -0,0 +1,199 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;tag=[call_number] +To: +P-Access-Network-Info: 3GPP-UTRAN-TDD;utran-cell-id-3gpp=C359A3913B20E +Call-ID: [call_id] +CSeq: 1 REGISTER +Contact: ;+g.3gpp.accesstype="cellular2";+g.3gpp.ps-data-off="inactive";audio;+g.3gpp.nw-init-ussi;+g.3gpp.smsip;+g.3gpp.icsi-ref="urn%3Aurn-7%3A3gpp-service.ims.icsi.mmtel";+sip.instance="" +Expires: 300 +Require: sec-agree +Proxy-Require: sec-agree +Supported: path,sec-agree +Allow: INVITE,BYE,CANCEL,ACK,NOTIFY,UPDATE,PRACK,INFO,MESSAGE,OPTIONS +Security-Client: ipsec-3gpp; ealg=null; alg=hmac-md5-96; spi-c=[$spic]; spi-s=[$spis]; port-c=[$portc]; port-s=[$ports]; q=0.1 +User-Agent: Sipp v1.1-TLS, version 20061124 +Authorization: Digest uri="sip:ims.mnc001.mcc001.3gppnetwork.org", username="[field0]@ims.mnc001.mcc001.3gppnetwork.org", response="", realm="ims.mnc001.mcc001.3gppnetwork.org", nonce="" +Content-Length: 0 + +]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;tag=[call_number] +To: +P-Access-Network-Info: 3GPP-UTRAN-TDD;utran-cell-id-3gpp=C359A3913B20E +Call-ID: [call_id] +CSeq: 2 REGISTER +Contact: ;+g.3gpp.accesstype="cellular2";+g.3gpp.ps-data-off="inactive";audio;+g.3gpp.nw-init-ussi;+g.3gpp.smsip;+g.3gpp.icsi-ref="urn%3Aurn-7%3A3gpp-service.ims.icsi.mmtel";+sip.instance="" +P-Access-Network-Info: 3GPP-UTRAN-TDD;utran-cell-id-3gpp=C359A3913B20E +Expires: 300 +Require: sec-agree +Proxy-Require: sec-agree +Supported: path,sec-agree +Allow: INVITE,BYE,CANCEL,ACK,NOTIFY,UPDATE,PRACK,INFO,MESSAGE,OPTIONS +Security-Client: ipsec-3gpp; alg=hmac-md5-96; ealg=null; spi-c=[$spic]; spi-s=[$spis]; port-c=[$portc]; port-s=[$ports] +Security-Verify: ipsec-3gpp; ealg=null; alg=hmac-md5-96; spi-c=[$rspic]; spi-s=[$rspis]; port-c=[$rportc]; port-s=[$rports]; q=0.1 +User-Agent: Sipp v1.1-TLS, version 20061124 +[field3] +Supported: path +Content-Length: 0 + +]]> + + + + + + + + + + + + + + + ;tag=[call_number] +To: +P-Access-Network-Info: 3GPP-UTRAN-TDD;utran-cell-id-3gpp=C359A3913B20E +Call-ID: [call_id] +CSeq: 3 REGISTER +Contact: ;+g.3gpp.accesstype="cellular2";+g.3gpp.ps-data-off="inactive";audio;+g.3gpp.nw-init-ussi;+g.3gpp.smsip;+g.3gpp.icsi-ref="urn%3Aurn-7%3A3gpp-service.ims.icsi.mmtel";+sip.instance="" +P-Access-Network-Info: 3GPP-UTRAN-TDD;utran-cell-id-3gpp=C359A3913B20E +Expires: 0 +Require: sec-agree +Proxy-Require: sec-agree +Supported: path,sec-agree +Allow: INVITE,BYE,CANCEL,ACK,NOTIFY,UPDATE,PRACK,INFO,MESSAGE,OPTIONS +User-Agent: Sipp v1.1-TLS, version 20061124 +Supported: path +[field3] +Content-Length: 0 + +]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example/ipsec/scenarios/regIPSEC2.xml b/example/ipsec/scenarios/regIPSEC2.xml new file mode 100644 index 000000000..fd2ed077a --- /dev/null +++ b/example/ipsec/scenarios/regIPSEC2.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + ;tag=[call_number] +To: "alice" +P-Access-Network-Info: 3GPP-UTRAN-TDD;utran-cell-id-3gpp=C359A3913B20E +Call-ID: [call_id] +CSeq: 2 REGISTER +Contact: +Expires: 300 +Content-Length: 0 +Security-Client: ipsec-3gpp; alg=hmac-md5-96; ealg=des-ede3-cbc; spi-c=2721834714; spi-s=1075014941; port-c=12345; port-s=3062,ipsec-3gpp; alg=hmac-md5-96; ealg=aes-cbc; spi-c=2721834714; spi-s=1075014941; port-c=12345; port-s=3062,ipsec-3gpp; alg=hmac-md5-96; ealg=null; spi-c=2721834714; spi-s=1075014941; port-c=12345; port-s=3062,ipsec-3gpp; alg=hmac-sha-1-96; ealg=des-ede3-cbc; spi-c=2721834714; spi-s=1075014941; port-c=12345; port-s=3062,ipsec-3gpp; alg=hmac-sha-1-96; ealg=aes-cbc; spi-c=2721834714; spi-s=1075014941; port-c=12345; port-s=3062,ipsec-3gpp; alg=hmac-sha-1-96; ealg=null; spi-c=2721834714; spi-s=1075014941; port-c=12345; port-s=3062 +Security-Verify: ipsec-3gpp; ealg=null; alg=hmac-md5-96; spi-c=[$10]; spi-s=[$11]; port-c=[$12]; port-s=[$13]; q=0.1 +User-Agent: Sipp v1.1-TLS, version 20061124 +[authentication username=001019901003516@ims.mnc001.mcc001.3gppnetwork.org password=test] +Supported: path +]]> + + + + + + + + + + + + + + \ No newline at end of file diff --git a/example/ipsec/scenarios/regIPSEC3.xml b/example/ipsec/scenarios/regIPSEC3.xml new file mode 100644 index 000000000..be1ec5b18 --- /dev/null +++ b/example/ipsec/scenarios/regIPSEC3.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/example/ipsec/scripts/ipsec_E_Drop.sh b/example/ipsec/scripts/ipsec_E_Drop.sh new file mode 100644 index 000000000..58ee382b4 --- /dev/null +++ b/example/ipsec/scripts/ipsec_E_Drop.sh @@ -0,0 +1,35 @@ +#!/bin/bash +# +# User Endpoint drop all 4 SA +# +# \author Dragos Vingarzan vingarzan -at- fokus dot fraunhofer dot de +# \author xfrm Serge S. Yuriev nevian -at- nevian dot org +# + +ue=$1 +port_uc=$2 +port_us=$3 + +pcscf=$4 +port_pc=$5 +port_ps=$6 + +spi_uc=$7 +spi_us=$8 + +spi_pc=$9 +spi_ps=${10} + + + +ip xfrm policy del src $ue dst $pcscf sport $port_uc dport $port_ps dir out +ip xfrm state del src $ue dst $pcscf proto esp spi $spi_ps + +ip xfrm policy del src $ue dst $pcscf sport $port_us dport $port_pc dir out +ip xfrm state del src $ue dst $pcscf proto esp spi $spi_pc + +ip xfrm policy del src $pcscf dst $ue sport $port_ps dport $port_uc dir in +ip xfrm state del src $pcscf dst $ue proto esp spi $spi_uc + +ip xfrm policy del src $pcscf dst $ue sport $port_pc dport $port_us dir in +ip xfrm state del src $pcscf dst $ue proto esp spi $spi_us diff --git a/example/ipsec/scripts/ipsec_E_Inc_Req.sh b/example/ipsec/scripts/ipsec_E_Inc_Req.sh new file mode 100644 index 000000000..121402e60 --- /dev/null +++ b/example/ipsec/scripts/ipsec_E_Inc_Req.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# +# UserEndpoint SA for Incoming Requests ( US <- PC ) +# +# \author Dragos Vingarzan vingarzan -at- fokus dot fraunhofer dot de +# \author xfrm Serge S. Yuriev nevian -at- nevian dot org +# + +ue=$1 +port_us=$2 +pcscf=$3 +port_pc=$4 + +spi_us=$5 + +ealg=$6 +ck=$7 +alg=$8 +ik=$9 + +if [ "$6" = "null" ] +then + ck='""' +fi + +case "$ealg" in + "aes-cbc" ) + ealg="cbc(aes)" + ;; + "des-ede3-cbc" ) + ealg="cbc(des3_ede)" + ;; + "null" ) + ealg="ecb(cipher_null)" + ;; + * ) + echo Unknown EALG $ealg exiting.. + exit 127 + ;; +esac + +case "$alg" in + "null" ) + alg="digest_null" + ;; + "hmac-sha-1-96" ) + alg="hmac(sha1)" + ;; + "hmac-md5-96" ) + alg="hmac(md5)" + ;; + * ) + echo Unknown ALG $alg exiting.. + exit 127 + ;; +esac + +ip xfrm policy add src $pcscf dst $ue sport $port_pc dport $port_us dir in tmpl proto esp reqid $$ mode transport +ip xfrm state add src $pcscf dst $ue proto esp spi $spi_us mode transport enc $ealg $ck auth $alg $ik reqid $$ diff --git a/example/ipsec/scripts/ipsec_E_Inc_Rpl.sh b/example/ipsec/scripts/ipsec_E_Inc_Rpl.sh new file mode 100644 index 000000000..760788758 --- /dev/null +++ b/example/ipsec/scripts/ipsec_E_Inc_Rpl.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# +# UserEndpoint SA for Incoming Replies ( UC <- PS ) +# +# \author Dragos Vingarzan vingarzan -at- fokus dot fraunhofer dot de +# \author xfrm Serge S. Yuriev nevian -at- nevian dot org +# + +ue=$1 +port_uc=$2 +pcscf=$3 +port_ps=$4 + +spi_uc=$5 + +ealg=$6 +ck=$7 +alg=$8 +ik=$9 + +if [ "$6" = "null" ] +then + ck='""' +fi + +case "$ealg" in + "aes-cbc" ) + ealg="cbc(aes)" + ;; + "des-ede3-cbc" ) + ealg="cbc(des3_ede)" + ;; + "null" ) + ealg="ecb(cipher_null)" + ;; + * ) + echo Unknown EALG $ealg exiting.. + exit 127 + ;; +esac + +case "$alg" in + "null" ) + alg="digest_null" + ;; + "hmac-sha-1-96" ) + alg="hmac(sha1)" + ;; + "hmac-md5-96" ) + alg="hmac(md5)" + ;; + * ) + echo Unknown ALG $alg exiting.. + exit 127 + ;; +esac + +ip xfrm policy add src $pcscf dst $ue sport $port_ps dport $port_uc dir in tmpl proto esp reqid $$ mode transport +ip xfrm state add src $pcscf dst $ue proto esp spi $spi_uc mode transport enc $ealg $ck auth $alg $ik reqid $$ diff --git a/example/ipsec/scripts/ipsec_E_Out_Req.sh b/example/ipsec/scripts/ipsec_E_Out_Req.sh new file mode 100644 index 000000000..7089892bd --- /dev/null +++ b/example/ipsec/scripts/ipsec_E_Out_Req.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# +# UserEndpoint SA for Outgoing Requests ( UC -> PS ) +# +# \author Dragos Vingarzan vingarzan -at- fokus dot fraunhofer dot de +# \author xfrm Serge S. Yuriev nevian -at- nevian dot org +# + +ue=$1 +port_uc=$2 +pcscf=$3 +port_ps=$4 + +spi_ps=$5 + +ealg=$6 +ck=$7 +alg=$8 +ik=$9 + +if [ "$6" = "null" ] +then + ck='""' +fi + +case "$ealg" in + "aes-cbc" ) + ealg="cbc(aes)" + ;; + "des-ede3-cbc" ) + ealg="cbc(des3_ede)" + ;; + "null" ) + ealg="ecb(cipher_null)" + ;; + * ) + echo Unknown EALG $ealg exiting.. + exit 127 + ;; +esac + +case "$alg" in + "null" ) + alg="digest_null" + ;; + "hmac-sha-1-96" ) + alg="hmac(sha1)" + ;; + "hmac-md5-96" ) + alg="hmac(md5)" + ;; + * ) + echo Unknown ALG $alg exiting.. + exit 127 + ;; +esac + +ip xfrm policy add src $ue dst $pcscf sport $port_uc dport $port_ps dir out tmpl proto esp reqid $$ mode transport +ip xfrm state add src $ue dst $pcscf proto esp spi $spi_ps mode transport enc $ealg $ck auth $alg $ik reqid $$ diff --git a/example/ipsec/scripts/ipsec_E_Out_Rpl.sh b/example/ipsec/scripts/ipsec_E_Out_Rpl.sh new file mode 100644 index 000000000..1f0a63983 --- /dev/null +++ b/example/ipsec/scripts/ipsec_E_Out_Rpl.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# +# UserEndpoint SA for Outgoing Replies ( US -> PC ) +# +# \author Dragos Vingarzan vingarzan -at- fokus dot fraunhofer dot de +# \author xfrm Serge S. Yuriev nevian -at- nevian dot org +# + +ue=$1 +port_us=$2 +pcscf=$3 +port_pc=$4 + +spi_pc=$5 + +ealg=$6 +ck=$7 +alg=$8 +ik=$9 + +if [ "$6" = "null" ] +then + ck='""' +fi + +case "$ealg" in + "aes-cbc" ) + ealg="cbc(aes)" + ;; + "des-ede3-cbc" ) + ealg="cbc(des3_ede)" + ;; + "null" ) + ealg="ecb(cipher_null)" + ;; + * ) + echo Unknown EALG $ealg exiting.. + exit 127 + ;; +esac + +case "$alg" in + "null" ) + alg="digest_null" + ;; + "hmac-sha-1-96" ) + alg="hmac(sha1)" + ;; + "hmac-md5-96" ) + alg="hmac(md5)" + ;; + * ) + echo Unknown ALG $alg exiting.. + exit 127 + ;; +esac + +ip xfrm policy add src $ue dst $pcscf sport $port_us dport $port_pc dir out tmpl proto esp reqid $$ mode transport +ip xfrm state add src $ue dst $pcscf proto esp spi $spi_pc mode transport enc $ealg $ck auth $alg $ik reqid $$ diff --git a/example/tel.xml b/example/tel.xml new file mode 100644 index 000000000..cc0b5056d --- /dev/null +++ b/example/tel.xml @@ -0,0 +1,103 @@ + + + + + + + + + ;tag=[call_number] + To: + Call-ID: [call_id] + CSeq: 10 INVITE + Contact: + Content-Type: application/sdp + Max-Forwards: 70 + User-Agent: SIPp + Session-Expires: 3600;refresher=uas + Content-Length: [len] + + v=0 + o=16001 0 0 IN IP[local_ip_type] [local_ip] + s=- + c=IN IP[media_ip_type] [media_ip] + t=0 0 + m=audio [media_port] RTP/AVP 0 8 9 103 101 + a=rtcp:[media_port+1] + a=sendrecv + a=rtpmap:0 PCMU/8000 + a=rtpmap:8 PCMA/8000 + a=rtpmap:9 G722/16000 + a=fmtp:9 bitrate=64000 + a=rtpmap:103 G7221/16000 + a=fmtp:103 bitrate=32000 + a=rtpmap:101 telephone-event/8000 + a=fmtp:101 0-11,16 + + ]]> + + + + + + + + + + + + + + + + + + + ;tag=[call_number] + To: [peer_tag_param] + Call-ID: [call_id] + CSeq: 10 ACK + Content-Length: 0 + + ]]> + + + + + + ;tag=[call_number] + To: [peer_tag_param] + Call-ID: [call_id] + CSeq: 12 BYE + Contact: + Max-Forwards: 70 + Subject: Conference + User-Agent: VIRTUAL Mitel-UC-Endpoint (Mitel UC360 Collaboration Point/2.1.0.99; 08:00:0F:74:80:E1) + Content-Length: 0 + + ]]> + + + + + + + + + + + + diff --git a/example/tls/runTLS.sh b/example/tls/runTLS.sh new file mode 100644 index 000000000..435102eb3 --- /dev/null +++ b/example/tls/runTLS.sh @@ -0,0 +1,3 @@ +#!/bin/bash +./sipp -t u1 -i 127.0.0.1 -p 3062 127.0.0.1:4060 -sf scenarios/regbob.xml -m 1 -trace_err -auth_pipe b.dat +./sipp -t l1 -i 127.0.0.1 -p 3063 127.0.0.1:4061 -sf scenarios/regbob2.xml -m 1 -trace_err -auth_pipe b.dat diff --git a/example/tls/runTLS2.sh b/example/tls/runTLS2.sh new file mode 100644 index 000000000..624444708 --- /dev/null +++ b/example/tls/runTLS2.sh @@ -0,0 +1,3 @@ +#!/bin/bash +./sipp -t l1 -i 127.0.0.1 -p 3062 127.0.0.1:4061 -sf scenarios/regbob_tls.xml -m 1 -trace_err + diff --git a/example/tls/scenarios/reg_auth.xml b/example/tls/scenarios/reg_auth.xml new file mode 100644 index 000000000..e04b0ad7e --- /dev/null +++ b/example/tls/scenarios/reg_auth.xml @@ -0,0 +1,51 @@ + + + + + + +;tag=[call_number] +To: "alice" +Call-ID: reg///[call_id] +CSeq: 1 REGISTER +Contact: +Expires: 300 +Content-Length: 0 +User-Agent: Sipp v1.1-TLS, version 20061124 +Authorization: Digest username="alice@open-ims.test", realm="open-ims.test" +Supported: path +]]> + + + + + + +;tag=[call_number] +To: "alice" +Call-ID: reg///[call_id] +CSeq: 2 REGISTER +Contact: +Expires: 300 +Content-Length: 0 +User-Agent: Sipp v1.1-TLS, version 20061124 +[authentication username=alice@open-ims.test password=alice] +Supported: path +]]> + + + + + + + + + \ No newline at end of file diff --git a/example/tls/scenarios/regalice2TLS.xml b/example/tls/scenarios/regalice2TLS.xml new file mode 100644 index 000000000..6f76dcc78 --- /dev/null +++ b/example/tls/scenarios/regalice2TLS.xml @@ -0,0 +1,33 @@ + + + + + + +;tag=[call_number] +To: "alice" +P-Access-Network-Info: 3GPP-UTRAN-TDD;utran-cell-id-3gpp=C359A3913B20E +Call-ID: reg///[call_id] +CSeq: 2 REGISTER +Contact: +Expires: 300 +Content-Length: 0 +Security-Verify: tls +User-Agent: Sipp v1.1-TLS, version 20061124 +[authentication username=alice@open-ims.test password=alice] +Supported: path +]]> + + + + + + + + + + \ No newline at end of file diff --git a/example/tls/scenarios/regaliceTLS.xml b/example/tls/scenarios/regaliceTLS.xml new file mode 100644 index 000000000..84219db3b --- /dev/null +++ b/example/tls/scenarios/regaliceTLS.xml @@ -0,0 +1,32 @@ + + + + + + +;tag=[call_number] +To: "alice" +P-Access-Network-Info: 3GPP-UTRAN-TDD;utran-cell-id-3gpp=C359A3913B20E +Call-ID: reg///[call_id] +CSeq: 1 REGISTER +Contact: +Expires: 300 +Content-Length: 0 +Security-Client: tls +User-Agent: Sipp v1.1-TLS, version 20061124 +Authorization: Digest username="alice@open-ims.test", realm="open-ims.test" +Supported: path +]]> + + + + + + + + + \ No newline at end of file diff --git a/example/tls/scenarios/regbob.xml b/example/tls/scenarios/regbob.xml new file mode 100644 index 000000000..b60d6cdac --- /dev/null +++ b/example/tls/scenarios/regbob.xml @@ -0,0 +1,33 @@ + + + + + + +;tag=[call_number] +To: "bob" +P-Access-Network-Info: 3GPP-UTRAN-TDD;utran-cell-id-3gpp=C359A3913B20E +Call-ID: reg///[call_id] +CSeq: 1 REGISTER +Contact: +Expires: 300 +Content-Length: 0 +Security-Client: tls +User-Agent: Sipp v1.1-TLS, version 20061124 +Authorization: Digest username="bob@open-ims.test", realm="open-ims.test" +Supported: path +]]> + + + + + + + + + + \ No newline at end of file diff --git a/example/tls/scenarios/regbob2.xml b/example/tls/scenarios/regbob2.xml new file mode 100644 index 000000000..9db48353f --- /dev/null +++ b/example/tls/scenarios/regbob2.xml @@ -0,0 +1,34 @@ + + + + + + +;tag=[call_number] +To: "bob" +P-Access-Network-Info: 3GPP-UTRAN-TDD;utran-cell-id-3gpp=C359A3913B20E +Call-ID: reg///[call_id] +CSeq: 2 REGISTER +Contact: +Expires: 300 +Content-Length: 0 +Security-Client: tls +Security-Verify: tls +User-Agent: Sipp v1.1-TLS, version 20061124 +[authentication username=bob@open-ims.test password=bob] +Supported: path +]]> + + + + + + + + + \ No newline at end of file diff --git a/example/tls/scenarios/regbob_tls.xml b/example/tls/scenarios/regbob_tls.xml new file mode 100644 index 000000000..817b49c22 --- /dev/null +++ b/example/tls/scenarios/regbob_tls.xml @@ -0,0 +1,58 @@ + + + + + + +;tag=[call_number] +To: "bob" +P-Access-Network-Info: 3GPP-UTRAN-TDD;utran-cell-id-3gpp=C359A3913B20E +Call-ID: reg///[call_id] +CSeq: 1 REGISTER +Contact: +Expires: 300 +Content-Length: 0 +Security-Client: tls +User-Agent: Sipp v1.1-TLS, version 20061124 +Authorization: Digest username="bob@open-ims.test", realm="open-ims.test" +Supported: path +]]> + + + + + + + +;tag=[call_number] +To: "bob" +P-Access-Network-Info: 3GPP-UTRAN-TDD;utran-cell-id-3gpp=C359A3913B20E +Call-ID: reg///[call_id] +CSeq: 2 REGISTER +Contact: +Expires: 300 +Content-Length: 0 +Security-Client: tls +Security-Verify: tls +User-Agent: Sipp v1.1-TLS, version 20061124 +[authentication username=bob@open-ims.test password=bob] +Supported: path +]]> + + + + + + + + + \ No newline at end of file diff --git a/include/actions.hpp b/include/actions.hpp index 2f50ab47e..fccef7d74 100644 --- a/include/actions.hpp +++ b/include/actions.hpp @@ -32,7 +32,7 @@ class CSample; #endif #include "rtpstream.hpp" -#define MAX_ACTION_MESSAGE 3 +#define MAX_ACTION_MESSAGE 4 class CAction { @@ -68,6 +68,7 @@ class CAction E_AT_VAR_URLENCODE, E_AT_VERIFY_AUTH, E_AT_SET_DEST, + E_AT_SET_DEST_W_SPORT, E_AT_CLOSE_CON, #ifdef PCAPPLAY E_AT_PLAY_PCAP_AUDIO, diff --git a/include/auth.hpp b/include/auth.hpp index f4a0c8d1f..9111cc7b4 100644 --- a/include/auth.hpp +++ b/include/auth.hpp @@ -14,20 +14,236 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -int createAuthHeader(const char *user, - const char *password, - const char *method, - const char *uri, - const char *msgbody, - const char *auth, - const char *aka_OP, - const char *aka_AMF, - const char *aka_K, - unsigned int nonce_count, - char *result, - size_t result_len); +#pragma once + +#define CKLEN 16 +typedef u_char CK[CKLEN]; +#define IKLEN 16 +typedef u_char IK[IKLEN]; + +/* AKA */ + +#define KLEN 16 +typedef u_char K[KLEN]; +#define RANDLEN 16 +typedef u_char RAND[RANDLEN]; +#define AUTNLEN 16 +typedef u_char AUTN[AUTNLEN]; + +#define AKLEN 6 +typedef u_char AK[AKLEN]; +#define AMFLEN 2 +typedef u_char AMF[AMFLEN]; +#define MACLEN 8 +typedef u_char MAC[MACLEN]; +#define SQNLEN 6 +typedef u_char SQN[SQNLEN]; +#define AUTSLEN 14 +typedef char AUTS[AUTSLEN]; +#define AUTS64LEN 29 +typedef char AUTS64[AUTS64LEN]; +#define RESLEN 8 +typedef unsigned char RES[RESLEN + 1]; +#define RESHEXLEN 17 +typedef char RESHEX[RESHEXLEN]; +#define OPLEN 16 +typedef u_char OP[OPLEN]; + +//AMF amfstar="\0"; + +/* end AKA */ + +int createAuthHeader(const char *user, const char *password, const char *method, const char *uri, const char *msgbody, + const char *auth, const char *aka_OP, const char *aka_AMF, const char *aka_K, + unsigned int nonce_count, char *result, size_t result_len, CK ck, IK ik); + int verifyAuthHeader(const char *user, const char *password, const char *method, const char *auth, const char *msgbody); + int getAuthParameter(const char *name, const char *header, char *result, int len); + +static char base64[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/*" +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";*/ +static int base64_val(char x) { + switch(x) { + case '=': + return -1; + case 'A': + return 0; + case 'B': + return 1; + case 'C': + return 2; + case 'D': + return 3; + case 'E': + return 4; + case 'F': + return 5; + case 'G': + return 6; + case 'H': + return 7; + case 'I': + return 8; + case 'J': + return 9; + case 'K': + return 10; + case 'L': + return 11; + case 'M': + return 12; + case 'N': + return 13; + case 'O': + return 14; + case 'P': + return 15; + case 'Q': + return 16; + case 'R': + return 17; + case 'S': + return 18; + case 'T': + return 19; + case 'U': + return 20; + case 'V': + return 21; + case 'W': + return 22; + case 'X': + return 23; + case 'Y': + return 24; + case 'Z': + return 25; + case 'a': + return 26; + case 'b': + return 27; + case 'c': + return 28; + case 'd': + return 29; + case 'e': + return 30; + case 'f': + return 31; + case 'g': + return 32; + case 'h': + return 33; + case 'i': + return 34; + case 'j': + return 35; + case 'k': + return 36; + case 'l': + return 37; + case 'm': + return 38; + case 'n': + return 39; + case 'o': + return 40; + case 'p': + return 41; + case 'q': + return 42; + case 'r': + return 43; + case 's': + return 44; + case 't': + return 45; + case 'u': + return 46; + case 'v': + return 47; + case 'w': + return 48; + case 'x': + return 49; + case 'y': + return 50; + case 'z': + return 51; + case '0': + return 52; + case '1': + return 53; + case '2': + return 54; + case '3': + return 55; + case '4': + return 56; + case '5': + return 57; + case '6': + return 58; + case '7': + return 59; + case '8': + return 60; + case '9': + return 61; + case '+': + return 62; + case '/': + return 63; + } + return 0; +} + +static char *base64_decode_string(const char *buf, unsigned int len, int *newlen) { + unsigned long i; + int j, x1, x2, x3, x4; + char *out; + out = (char *) malloc((len * 3 / 4) + 8); + for (i = 0, j = 0; i + 3 < len; i += 4) { + x1 = base64_val(buf[i]); + x2 = base64_val(buf[i + 1]); + x3 = base64_val(buf[i + 2]); + x4 = base64_val(buf[i + 3]); + out[j++] = (x1 << 2) | ((x2 & 0x30) >> 4); + out[j++] = ((x2 & 0x0F) << 4) | ((x3 & 0x3C) >> 2); + out[j++] = ((x3 & 0x03) << 6) | (x4 & 0x3F); + } + if (i < len) { + x1 = base64_val(buf[i]); + if (i + 1 < len) + x2 = base64_val(buf[i + 1]); + else + x2 = -1; + if (i + 2 < len) + x3 = base64_val(buf[i + 2]); + else + x3 = -1; + if (i + 3 < len) + x4 = base64_val(buf[i + 3]); + else x4 = -1; + if (x2 != -1) { + out[j++] = (x1 << 2) | ((x2 & 0x30) >> 4); + if (x3 == -1) { + out[j++] = ((x2 & 0x0F) << 4) | ((x3 & 0x3C) >> 2); + if (x4 == -1) { + out[j++] = ((x3 & 0x03) << 6) | (x4 & 0x3F); + } + } + } + + } + + out[j++] = 0; + *newlen = j; + return out; +} diff --git a/include/call.hpp b/include/call.hpp index 5abe0219d..935cdfcc5 100644 --- a/include/call.hpp +++ b/include/call.hpp @@ -41,6 +41,7 @@ #define MAX(a, b) ((a) > (b) ? (a) : (b)) #endif #include "sip_parser.hpp" +#include "auth.hpp" #define UDP_MAX_RETRANS_INVITE_TRANSACTION 5 #define UDP_MAX_RETRANS_NON_INVITE_TRANSACTION 9 @@ -260,7 +261,11 @@ class call : virtual public task, virtual public listener, public virtual socket /* call to continue and mark it as failed */ T_ActionResult last_action_result; - /* rc == true means call not deleted by processing */ + /* ck_key and ik_key from AKA authentication that can be used to create ipsec association via external command */ + CK _ck; + IK _ik; + + /* rc == true means call not deleted by processing */ void formatNextReqUrl(const char* contact); void computeRouteSetAndRemoteTargetUri(const char* rrList, const char* contact, bool bRequestIncoming); bool matches_scenario(unsigned int index, int reply_code, char * request, char * responsecseqmethod, char *txn); diff --git a/include/message.hpp b/include/message.hpp index bb2cf893e..5ea57d56d 100644 --- a/include/message.hpp +++ b/include/message.hpp @@ -88,6 +88,8 @@ typedef enum { E_Message_Custom, E_Message_RTPStream_Audio_Port, E_Message_RTPStream_Video_Port, + E_Message_CKey, + E_Message_IKey, #ifdef USE_TLS E_Message_CryptoTag1Audio, E_Message_CryptoTag2Audio, diff --git a/include/socket.hpp b/include/socket.hpp index 01dc9f937..9aecd5499 100644 --- a/include/socket.hpp +++ b/include/socket.hpp @@ -54,7 +54,7 @@ int gai_getsockaddr(struct sockaddr_storage* ss, const char* host, unsigned short port, int flags, int family); int gai_getsockaddr(struct sockaddr_storage* ss, const char* host, const char *service, int flags, int family); -void sockaddr_update_port(struct sockaddr_storage* ss, short port); +void sockaddr_update_port(struct sockaddr_storage* ss, unsigned short port); /* This is an abstraction of a socket, which provides buffers for input and diff --git a/run/runIPSEC.sh b/run/runIPSEC.sh new file mode 100644 index 000000000..91d740c55 --- /dev/null +++ b/run/runIPSEC.sh @@ -0,0 +1,4 @@ +#!/bin/bash +./sipp 127.0.0.3 -t t1 -p 3061 -sf scenarios/regIPSEC1.xml -m 1 -trace_err -trace_msg -au 001019901003516@ims.mnc001.mcc001.3gppnetwork.org -ap test +./sipp 127.0.0.3:`cut -s -d";" -f4 spis.csv` -t t1 -p 12345 -sf scenarios/regIPSEC2.xml -m 1 -trace_err -trace_msg -inf spis.csv -au 001019901003516@ims.mnc001.mcc001.3gppnetwork.org -ap test +./sipp 127.0.0.3 -t t1 -p 3062 -sf scenarios/regIPSEC3.xml -m 1 -trace_err -trace_msg diff --git a/run/scenarios/regIPSEC1.xml b/run/scenarios/regIPSEC1.xml new file mode 100644 index 000000000..efe39cc8d --- /dev/null +++ b/run/scenarios/regIPSEC1.xml @@ -0,0 +1,55 @@ + + + + + + +;tag=[call_number] +To: "alice" +P-Access-Network-Info: 3GPP-UTRAN-TDD;utran-cell-id-3gpp=C359A3913B20E +Call-ID: reg///[call_id] +CSeq: 1 REGISTER +Contact: +Expires: 300 +Content-Length: 0 +Security-Client: ipsec-3gpp; alg=hmac-md5-96; ealg=des-ede3-cbc; spi-c=2721834714; spi-s=1075014941; port-c=12345; port-s=3062,ipsec-3gpp; alg=hmac-md5-96; ealg=aes-cbc; spi-c=2721834714; spi-s=1075014941; port-c=12345; port-s=3062,ipsec-3gpp; alg=hmac-md5-96; ealg=null; spi-c=2721834714; spi-s=1075014941; port-c=12345; port-s=3062,ipsec-3gpp; alg=hmac-sha-1-96; ealg=des-ede3-cbc; spi-c=2721834714; spi-s=1075014941; port-c=12345; port-s=3062,ipsec-3gpp; alg=hmac-sha-1-96; ealg=aes-cbc; spi-c=2721834714; spi-s=1075014941; port-c=12345; port-s=3062,ipsec-3gpp; alg=hmac-sha-1-96; ealg=null; spi-c=2721834714; spi-s=1075014941; port-c=12345; port-s=3062 +User-Agent: Sipp v1.1-TLS, version 20061124 +Authorization: Digest username="001019901003516@ims.mnc001.mcc001.3gppnetwork.org", realm="ims.mnc001.mcc001.3gppnetwork.org" +Supported: path +]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/run/scenarios/regIPSEC2.xml b/run/scenarios/regIPSEC2.xml new file mode 100644 index 000000000..554b109af --- /dev/null +++ b/run/scenarios/regIPSEC2.xml @@ -0,0 +1,31 @@ + + + + + + +;tag=[call_number] +To: "alice" +P-Access-Network-Info: 3GPP-UTRAN-TDD;utran-cell-id-3gpp=C359A3913B20E +Call-ID: reg///[call_id] +CSeq: 2 REGISTER +Contact: +Expires: 300 +Content-Length: 0 +Security-Client: ipsec-3gpp; alg=hmac-md5-96; ealg=des-ede3-cbc; spi-c=2721834714; spi-s=1075014941; port-c=12345; port-s=3062,ipsec-3gpp; alg=hmac-md5-96; ealg=aes-cbc; spi-c=2721834714; spi-s=1075014941; port-c=12345; port-s=3062,ipsec-3gpp; alg=hmac-md5-96; ealg=null; spi-c=2721834714; spi-s=1075014941; port-c=12345; port-s=3062,ipsec-3gpp; alg=hmac-sha-1-96; ealg=des-ede3-cbc; spi-c=2721834714; spi-s=1075014941; port-c=12345; port-s=3062,ipsec-3gpp; alg=hmac-sha-1-96; ealg=aes-cbc; spi-c=2721834714; spi-s=1075014941; port-c=12345; port-s=3062,ipsec-3gpp; alg=hmac-sha-1-96; ealg=null; spi-c=2721834714; spi-s=1075014941; port-c=12345; port-s=3062 +Security-Verify: ipsec-3gpp; ealg=null; alg=hmac-md5-96; spi-c=[field0]; spi-s=[field1]; port-c=[field2]; port-s=[field3]; q=0.1 +User-Agent: Sipp v1.1-TLS, version 20061124 +[authentication username=001019901003516@ims.mnc001.mcc001.3gppnetwork.org password=test] +Supported: path +]]> + + + + + + + \ No newline at end of file diff --git a/run/scenarios/regIPSEC3.xml b/run/scenarios/regIPSEC3.xml new file mode 100644 index 000000000..256648210 --- /dev/null +++ b/run/scenarios/regIPSEC3.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/run/scripts/ipsec_E_Drop.sh b/run/scripts/ipsec_E_Drop.sh new file mode 100644 index 000000000..58ee382b4 --- /dev/null +++ b/run/scripts/ipsec_E_Drop.sh @@ -0,0 +1,35 @@ +#!/bin/bash +# +# User Endpoint drop all 4 SA +# +# \author Dragos Vingarzan vingarzan -at- fokus dot fraunhofer dot de +# \author xfrm Serge S. Yuriev nevian -at- nevian dot org +# + +ue=$1 +port_uc=$2 +port_us=$3 + +pcscf=$4 +port_pc=$5 +port_ps=$6 + +spi_uc=$7 +spi_us=$8 + +spi_pc=$9 +spi_ps=${10} + + + +ip xfrm policy del src $ue dst $pcscf sport $port_uc dport $port_ps dir out +ip xfrm state del src $ue dst $pcscf proto esp spi $spi_ps + +ip xfrm policy del src $ue dst $pcscf sport $port_us dport $port_pc dir out +ip xfrm state del src $ue dst $pcscf proto esp spi $spi_pc + +ip xfrm policy del src $pcscf dst $ue sport $port_ps dport $port_uc dir in +ip xfrm state del src $pcscf dst $ue proto esp spi $spi_uc + +ip xfrm policy del src $pcscf dst $ue sport $port_pc dport $port_us dir in +ip xfrm state del src $pcscf dst $ue proto esp spi $spi_us diff --git a/run/scripts/ipsec_E_Inc_Req.sh b/run/scripts/ipsec_E_Inc_Req.sh new file mode 100644 index 000000000..121402e60 --- /dev/null +++ b/run/scripts/ipsec_E_Inc_Req.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# +# UserEndpoint SA for Incoming Requests ( US <- PC ) +# +# \author Dragos Vingarzan vingarzan -at- fokus dot fraunhofer dot de +# \author xfrm Serge S. Yuriev nevian -at- nevian dot org +# + +ue=$1 +port_us=$2 +pcscf=$3 +port_pc=$4 + +spi_us=$5 + +ealg=$6 +ck=$7 +alg=$8 +ik=$9 + +if [ "$6" = "null" ] +then + ck='""' +fi + +case "$ealg" in + "aes-cbc" ) + ealg="cbc(aes)" + ;; + "des-ede3-cbc" ) + ealg="cbc(des3_ede)" + ;; + "null" ) + ealg="ecb(cipher_null)" + ;; + * ) + echo Unknown EALG $ealg exiting.. + exit 127 + ;; +esac + +case "$alg" in + "null" ) + alg="digest_null" + ;; + "hmac-sha-1-96" ) + alg="hmac(sha1)" + ;; + "hmac-md5-96" ) + alg="hmac(md5)" + ;; + * ) + echo Unknown ALG $alg exiting.. + exit 127 + ;; +esac + +ip xfrm policy add src $pcscf dst $ue sport $port_pc dport $port_us dir in tmpl proto esp reqid $$ mode transport +ip xfrm state add src $pcscf dst $ue proto esp spi $spi_us mode transport enc $ealg $ck auth $alg $ik reqid $$ diff --git a/run/scripts/ipsec_E_Inc_Rpl.sh b/run/scripts/ipsec_E_Inc_Rpl.sh new file mode 100644 index 000000000..760788758 --- /dev/null +++ b/run/scripts/ipsec_E_Inc_Rpl.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# +# UserEndpoint SA for Incoming Replies ( UC <- PS ) +# +# \author Dragos Vingarzan vingarzan -at- fokus dot fraunhofer dot de +# \author xfrm Serge S. Yuriev nevian -at- nevian dot org +# + +ue=$1 +port_uc=$2 +pcscf=$3 +port_ps=$4 + +spi_uc=$5 + +ealg=$6 +ck=$7 +alg=$8 +ik=$9 + +if [ "$6" = "null" ] +then + ck='""' +fi + +case "$ealg" in + "aes-cbc" ) + ealg="cbc(aes)" + ;; + "des-ede3-cbc" ) + ealg="cbc(des3_ede)" + ;; + "null" ) + ealg="ecb(cipher_null)" + ;; + * ) + echo Unknown EALG $ealg exiting.. + exit 127 + ;; +esac + +case "$alg" in + "null" ) + alg="digest_null" + ;; + "hmac-sha-1-96" ) + alg="hmac(sha1)" + ;; + "hmac-md5-96" ) + alg="hmac(md5)" + ;; + * ) + echo Unknown ALG $alg exiting.. + exit 127 + ;; +esac + +ip xfrm policy add src $pcscf dst $ue sport $port_ps dport $port_uc dir in tmpl proto esp reqid $$ mode transport +ip xfrm state add src $pcscf dst $ue proto esp spi $spi_uc mode transport enc $ealg $ck auth $alg $ik reqid $$ diff --git a/run/scripts/ipsec_E_Out_Req.sh b/run/scripts/ipsec_E_Out_Req.sh new file mode 100644 index 000000000..7089892bd --- /dev/null +++ b/run/scripts/ipsec_E_Out_Req.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# +# UserEndpoint SA for Outgoing Requests ( UC -> PS ) +# +# \author Dragos Vingarzan vingarzan -at- fokus dot fraunhofer dot de +# \author xfrm Serge S. Yuriev nevian -at- nevian dot org +# + +ue=$1 +port_uc=$2 +pcscf=$3 +port_ps=$4 + +spi_ps=$5 + +ealg=$6 +ck=$7 +alg=$8 +ik=$9 + +if [ "$6" = "null" ] +then + ck='""' +fi + +case "$ealg" in + "aes-cbc" ) + ealg="cbc(aes)" + ;; + "des-ede3-cbc" ) + ealg="cbc(des3_ede)" + ;; + "null" ) + ealg="ecb(cipher_null)" + ;; + * ) + echo Unknown EALG $ealg exiting.. + exit 127 + ;; +esac + +case "$alg" in + "null" ) + alg="digest_null" + ;; + "hmac-sha-1-96" ) + alg="hmac(sha1)" + ;; + "hmac-md5-96" ) + alg="hmac(md5)" + ;; + * ) + echo Unknown ALG $alg exiting.. + exit 127 + ;; +esac + +ip xfrm policy add src $ue dst $pcscf sport $port_uc dport $port_ps dir out tmpl proto esp reqid $$ mode transport +ip xfrm state add src $ue dst $pcscf proto esp spi $spi_ps mode transport enc $ealg $ck auth $alg $ik reqid $$ diff --git a/run/scripts/ipsec_E_Out_Rpl.sh b/run/scripts/ipsec_E_Out_Rpl.sh new file mode 100644 index 000000000..1f0a63983 --- /dev/null +++ b/run/scripts/ipsec_E_Out_Rpl.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# +# UserEndpoint SA for Outgoing Replies ( US -> PC ) +# +# \author Dragos Vingarzan vingarzan -at- fokus dot fraunhofer dot de +# \author xfrm Serge S. Yuriev nevian -at- nevian dot org +# + +ue=$1 +port_us=$2 +pcscf=$3 +port_pc=$4 + +spi_pc=$5 + +ealg=$6 +ck=$7 +alg=$8 +ik=$9 + +if [ "$6" = "null" ] +then + ck='""' +fi + +case "$ealg" in + "aes-cbc" ) + ealg="cbc(aes)" + ;; + "des-ede3-cbc" ) + ealg="cbc(des3_ede)" + ;; + "null" ) + ealg="ecb(cipher_null)" + ;; + * ) + echo Unknown EALG $ealg exiting.. + exit 127 + ;; +esac + +case "$alg" in + "null" ) + alg="digest_null" + ;; + "hmac-sha-1-96" ) + alg="hmac(sha1)" + ;; + "hmac-md5-96" ) + alg="hmac(md5)" + ;; + * ) + echo Unknown ALG $alg exiting.. + exit 127 + ;; +esac + +ip xfrm policy add src $ue dst $pcscf sport $port_us dport $port_pc dir out tmpl proto esp reqid $$ mode transport +ip xfrm state add src $ue dst $pcscf proto esp spi $spi_pc mode transport enc $ealg $ck auth $alg $ik reqid $$ diff --git a/sipp.dtd b/sipp.dtd index ce8f4672f..0ede4c1f7 100644 --- a/sipp.dtd +++ b/sipp.dtd @@ -67,7 +67,7 @@ - + @@ -76,8 +76,9 @@ - + + @@ -108,9 +109,57 @@ + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -118,6 +167,8 @@ + + @@ -125,3 +176,24 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/src/auth.cpp b/src/auth.cpp index 524d2f13a..0680aca46 100644 --- a/src/auth.cpp +++ b/src/auth.cpp @@ -39,61 +39,35 @@ #define MD5_HASH_SIZE 16 #define HASH_HEX_SIZE 2*MD5_HASH_SIZE -/* AKA */ - -#define KLEN 16 -typedef u_char K[KLEN]; -#define RANDLEN 16 -typedef u_char RAND[RANDLEN]; -#define AUTNLEN 16 -typedef u_char AUTN[AUTNLEN]; - -#define AKLEN 6 -typedef u_char AK[AKLEN]; -#define AMFLEN 2 -typedef u_char AMF[AMFLEN]; -#define MACLEN 8 -typedef u_char MAC[MACLEN]; -#define CKLEN 16 -typedef u_char CK[CKLEN]; -#define IKLEN 16 -typedef u_char IK[IKLEN]; -#define SQNLEN 6 -typedef u_char SQN[SQNLEN]; -#define AUTSLEN 14 -typedef char AUTS[AUTSLEN]; -#define AUTS64LEN 29 -typedef char AUTS64[AUTS64LEN]; -#define RESLEN 8 -typedef unsigned char RES[RESLEN+1]; -#define RESHEXLEN 17 -typedef char RESHEX[RESHEXLEN]; -#define OPLEN 16 -typedef u_char OP[OPLEN]; - -AMF amfstar="\0"; SQN sqn_he= {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -/* end AKA */ - - static int createAuthHeaderMD5( const char* user, const char* password, int password_len, const char* method, const char* uri, const char* msgbody, const char* auth, const char* algo, unsigned int nonce_count, char* result, size_t result_len); -static int createAuthHeaderAKAv1MD5( - const char* user, const char* OP, const char* AMF, const char* K, - const char* method, const char* uri, const char* msgbody, - const char* auth, const char* algo, unsigned int nonce_count, - char* result, size_t result_len); +static int createAuthHeaderAKAv1MD5(const char *user, const char *aka_OP, const char *aka_AMF, const char *aka_K, + const char *method, const char *uri, const char *msgbody, const char *auth, + const char *algo, unsigned int nonce_count, char *result, size_t result_len, CK ck, + IK ik); + +static void hashToHex_(const unsigned char *hash, const size_t hash_len, unsigned char *res) { + for (size_t i = 0; i < hash_len; ++i) { + unsigned char j = (hash[i] >> 4) & 0xf; + res[i * 2] = j <= 9 ? j + '0' : j + 'a' - 10; + j = hash[i] & 0xf; + res[i * 2 + 1] = j <= 9 ? j + '0' : j + 'a' - 10; + } + res[hash_len*2] = '\0'; +} /* This function is from RFC 2617 Section 5 */ - static void hashToHex(md5_byte_t* _b_raw, unsigned char* _h) { + hashToHex_(_b_raw, MD5_HASH_SIZE, _h); +/* unsigned short i; unsigned char j; unsigned char *_b = (unsigned char *) _b_raw; @@ -113,6 +87,7 @@ static void hashToHex(md5_byte_t* _b_raw, unsigned char* _h) } }; _h[HASH_HEX_SIZE] = '\0'; +*/ } static char *stristr(const char* s1, const char* s2) @@ -142,11 +117,9 @@ static char *stristr(const char* s1, const char* s2) return 0; } -int createAuthHeader( - const char* user, const char* password, const char* method, - const char* uri, const char* msgbody, const char* auth, - const char* aka_OP, const char* aka_AMF, const char* aka_K, - unsigned int nonce_count, char* result, size_t result_len) +int createAuthHeader(const char *user, const char *password, const char *method, const char *uri, const char *msgbody, + const char *auth, const char *aka_OP, const char *aka_AMF, const char *aka_K, + unsigned int nonce_count, char *result, size_t result_len, CK ck, IK ik) { char algo[32] = "MD5"; @@ -183,8 +156,8 @@ int createAuthHeader( return 0; } return createAuthHeaderAKAv1MD5( - user, aka_OP, aka_AMF, aka_K, method, uri, msgbody, auth, - algo, nonce_count, result, result_len); + user, aka_OP, aka_AMF, aka_K, method, uri, msgbody, auth, + algo, nonce_count, result, result_len, ck, ik); } else { snprintf(result, result_len, "createAuthHeader: authentication must use MD5 or AKAv1-MD5"); return 0; @@ -451,200 +424,12 @@ int verifyAuthHeader(const char *user, const char *password, const char *method, } } - - -/*" -ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";*/ -static int base64_val(char x) { - switch(x) { - case '=': - return -1; - case 'A': - return 0; - case 'B': - return 1; - case 'C': - return 2; - case 'D': - return 3; - case 'E': - return 4; - case 'F': - return 5; - case 'G': - return 6; - case 'H': - return 7; - case 'I': - return 8; - case 'J': - return 9; - case 'K': - return 10; - case 'L': - return 11; - case 'M': - return 12; - case 'N': - return 13; - case 'O': - return 14; - case 'P': - return 15; - case 'Q': - return 16; - case 'R': - return 17; - case 'S': - return 18; - case 'T': - return 19; - case 'U': - return 20; - case 'V': - return 21; - case 'W': - return 22; - case 'X': - return 23; - case 'Y': - return 24; - case 'Z': - return 25; - case 'a': - return 26; - case 'b': - return 27; - case 'c': - return 28; - case 'd': - return 29; - case 'e': - return 30; - case 'f': - return 31; - case 'g': - return 32; - case 'h': - return 33; - case 'i': - return 34; - case 'j': - return 35; - case 'k': - return 36; - case 'l': - return 37; - case 'm': - return 38; - case 'n': - return 39; - case 'o': - return 40; - case 'p': - return 41; - case 'q': - return 42; - case 'r': - return 43; - case 's': - return 44; - case 't': - return 45; - case 'u': - return 46; - case 'v': - return 47; - case 'w': - return 48; - case 'x': - return 49; - case 'y': - return 50; - case 'z': - return 51; - case '0': - return 52; - case '1': - return 53; - case '2': - return 54; - case '3': - return 55; - case '4': - return 56; - case '5': - return 57; - case '6': - return 58; - case '7': - return 59; - case '8': - return 60; - case '9': - return 61; - case '+': - return 62; - case '/': - return 63; - } - return 0; -} - -static char* base64_decode_string(const char* buf, unsigned int len, int* newlen) -{ - unsigned long i; - int j, x1, x2, x3, x4; - char *out; - out = (char *)malloc( ( len * 3/4 ) + 8 ); - for(i=0, j=0; i + 3 < len; i += 4) { - x1=base64_val(buf[i]); - x2=base64_val(buf[i+1]); - x3=base64_val(buf[i+2]); - x4=base64_val(buf[i+3]); - out[j++]=(x1<<2) | ((x2 & 0x30)>>4); - out[j++]=((x2 & 0x0F)<<4) | ((x3 & 0x3C)>>2); - out[j++]=((x3 & 0x03)<<6) | (x4 & 0x3F); - } - if (i>4); - if (x3==-1) { - out[j++]=((x2 & 0x0F)<<4) | ((x3 & 0x3C)>>2); - if (x4==-1) { - out[j++]=((x3 & 0x03)<<6) | (x4 & 0x3F); - } - } - } - - } - - out[j++] = 0; - *newlen=j; - return out; -} - -char base64[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - char hexa[17] = "0123456789abcdef"; -static int createAuthHeaderAKAv1MD5( - const char* user, const char* aka_OP, const char* aka_AMF, - const char* aka_K, const char* method, const char* uri, - const char* msgbody, const char* auth, const char* algo, - unsigned int nonce_count, char* result, size_t result_len) +static int createAuthHeaderAKAv1MD5(const char *user, const char *aka_OP, const char *aka_AMF, const char *aka_K, + const char *method, const char *uri, const char *msgbody, const char *auth, + const char *algo, unsigned int nonce_count, char *result, size_t result_len, CK ck, + IK ik) { char tmp[MAX_HEADER_LEN]; @@ -662,8 +447,6 @@ static int createAuthHeaderAKAv1MD5( SQN sqn, sqnxoraka, sqn_ms; K k; RES res; - CK ck; - IK ik; AK ak; int i; @@ -695,8 +478,9 @@ static int createAuthHeaderAKAv1MD5( memcpy(rnd, nonce, RANDLEN); memcpy(sqnxoraka, nonce + RANDLEN, SQNLEN); memcpy(mac, nonce + RANDLEN + SQNLEN + AMFLEN, MACLEN); + memcpy(amf, nonce + RANDLEN + SQNLEN, AMFLEN); memcpy(k, aka_K, KLEN); - memcpy(amf, aka_AMF, AMFLEN); +// memcpy(amf, aka_AMF, AMFLEN); memcpy(op, aka_OP, OPLEN); /* Compute the AK, response and keys CK IK */ @@ -707,13 +491,34 @@ static int createAuthHeaderAKAv1MD5( for (i=0; i < SQNLEN; i++) sqn[i] = sqnxoraka[i] ^ ak[i]; - /* compute XMAC */ - f1(k, rnd, sqn, (unsigned char *) aka_AMF, xmac, op); +/* compute XMAC */ + f1(k, rnd, sqn, amf, xmac, op); if (memcmp(mac, xmac, MACLEN) != 0) { - free(nonce); + unsigned char mac_rec[MACLEN*2+1], mac_expected[MACLEN*2+1]; + hashToHex_(mac, MACLEN, mac_rec); + hashToHex_(xmac, MACLEN, mac_expected); + WARNING("MAC received %s != MAC expected %s\n", mac_rec, mac_expected); + unsigned char str_[128]; + hashToHex_(k, sizeof(k), str_); + WARNING("AKA_key: %s\n", str_); + hashToHex_(amf, sizeof(amf), str_); + WARNING("AKA_amf: %s\n", str_); + hashToHex_(op, sizeof(op), str_); + WARNING("AKA_op: %s\n", str_); + hashToHex_(reinterpret_cast(nonce), noncelen, str_); + WARNING("NONCE: %s\n", str_); + hashToHex_(rnd, sizeof(rnd), str_); + WARNING("RAND: %s\n", str_); + hashToHex_(sqn, sizeof(sqn), str_); + WARNING("SQN: %s\n", str_); + hashToHex_(ak, sizeof(ak), str_); + WARNING("AK: %s\n", str_); + hashToHex_(sqnxoraka, sizeof(sqnxoraka), str_); + ERROR("SQN ^ AK: %s\n", str_); + free(nonce); snprintf( result, result_len, - "createAuthHeaderAKAv1MD5 : MAC != expectedMAC -> Server might not know the secret (man-in-the-middle attack?)\n"); + "createAuthHeaderAKAv1MD5: MAC != expectedMAC -> Server might not know the secret (man-in-the-middle attack?)"); return 0; } @@ -732,7 +537,7 @@ static int createAuthHeaderAKAv1MD5( free(nonce); snprintf( result, result_len, - "createAuthHeaderAKAv1MD5 : Unexpected return value from createAuthHeaderMD5\n"); + "createAuthHeaderAKAv1MD5: Unexpected return value from createAuthHeaderMD5\n"); return 0; } } else { @@ -802,7 +607,8 @@ TEST(DigestAuth, BasicVerification) { " nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\"\r\n," " opaque=\"5ccc069c403ebaf9f0171e9517f40e41\"")); char result[255]; - createAuthHeader("testuser", "secret", "REGISTER", "sip:example.com", "hello world", header, NULL, NULL, NULL, 1, result, 255); + createAuthHeader("testuser", "secret", "REGISTER", "sip:example.com", "hello world", header, NULL, NULL, NULL, 1, + result, 255, nullptr, nullptr); EXPECT_STREQ("Digest username=\"testuser\",realm=\"testrealm@host.com\",uri=\"sip:sip:example.com\",nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\",response=\"db94e01e92f2b09a52a234eeca8b90f7\",algorithm=MD5,opaque=\"5ccc069c403ebaf9f0171e9517f40e41\"", result); EXPECT_EQ(1, verifyAuthHeader("testuser", "secret", "REGISTER", result, "hello world")); free(header); @@ -815,18 +621,18 @@ TEST(DigestAuth, qop) { "\tqop=\"auth,auth-int\",\r\n" "\tnonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\"\r\n," "\topaque=\"5ccc069c403ebaf9f0171e9517f40e41\"")); - createAuthHeader("testuser", - "secret", - "REGISTER", - "sip:example.com", - "hello world", - header, - NULL, - NULL, - NULL, - 1, - result, - 1024); + createAuthHeader("testuser", + "secret", + "REGISTER", + "sip:example.com", + "hello world", + header, + NULL, + NULL, + NULL, + 1, + result, + 1024, nullptr, nullptr); EXPECT_EQ(1, !!strstr(result, ",qop=auth-int,")); // no double quotes around qop-value EXPECT_EQ(1, verifyAuthHeader("testuser", "secret", "REGISTER", result, "hello world")); free(header); diff --git a/src/call.cpp b/src/call.cpp index af3e5630b..38b035240 100644 --- a/src/call.cpp +++ b/src/call.cpp @@ -57,7 +57,6 @@ #endif #include "sipp.hpp" -#include "auth.hpp" #include "urlcoder.hpp" #include "deadcall.hpp" #include "config.h" @@ -1062,6 +1061,8 @@ void call::init(scenario * call_scenario, SIPpSocket *socket, struct sockaddr_st recv_timeout = 0; send_timeout = 0; timewait = false; + memset(_ck, 0, sizeof _ck); + memset(_ik, 0, sizeof _ik); if (!isAutomatic) { /* Not advancing the number is safe, because for automatic calls we do not @@ -2065,7 +2066,7 @@ bool call::executeMessage(message *curmsg) WARNING("Call-Id: %s, receive timeout on message %s:%d, jumping to label %d", id, curmsg->desc, curmsg->index, curmsg->on_timeout); /* FIXME: We should do something like set index here, but it probably - * does not matter too much as only nops are allowed in the init stanza. */ + * does not matter too much as only nops are allowed in the init stanza. */ msg_index = curmsg->on_timeout; recv_timeout = 0; if (msg_index < (int)call_scenario->messages.size()) return true; @@ -3841,6 +3842,12 @@ char* call::createSendingMessage(SendingMessage *src, int P_index, char *msg_buf /* Drop the initial "v" from the SIPP_VERSION string for legacy reasons. */ dest += snprintf(dest, left, "%s", (const char*)SIPP_VERSION + 1); break; + case E_Message_CKey: + dest += snprintf(dest, left, "%s", _ck); + break; + case E_Message_IKey: + dest += snprintf(dest, left, "%s", _ik); + break; case E_Message_Variable: { int varId = comp->varId; CCallVariable *var = M_callVariableTable->getVar(varId); @@ -4032,7 +4039,7 @@ char* call::createSendingMessage(SendingMessage *src, int P_index, char *msg_buf authlen = sprintf(result, "Proxy-Authorization: "); } - /* Build the auth credenticals */ + /* Build the auth credentials */ char uri[MAX_HEADER_LEN]; sprintf (uri, "%s:%d", remote_ip, remote_port); /* These cause this function to not be reentrant. */ @@ -4042,19 +4049,33 @@ char* call::createSendingMessage(SendingMessage *src, int P_index, char *msg_buf static char my_aka_AMF[MAX_HEADER_LEN + 2]; static char my_aka_K[MAX_HEADER_LEN + 2]; + bzero(my_auth_user, sizeof my_auth_user); + bzero(my_auth_pass, sizeof my_auth_pass); + bzero(my_aka_OP, sizeof my_aka_OP); + bzero(my_aka_K, sizeof my_aka_K); + bzero(my_aka_AMF, sizeof my_aka_AMF); + createSendingMessage(auth_comp->comp_param.auth_param.auth_user, SM_UNUSED, my_auth_user, sizeof(my_auth_user)); createSendingMessage(auth_comp->comp_param.auth_param.auth_pass, SM_UNUSED, my_auth_pass, sizeof(my_auth_pass)); createSendingMessage(auth_comp->comp_param.auth_param.aka_K, SM_UNUSED, my_aka_K, sizeof(my_aka_K)); createSendingMessage(auth_comp->comp_param.auth_param.aka_AMF, SM_UNUSED, my_aka_AMF, sizeof(my_aka_AMF)); createSendingMessage(auth_comp->comp_param.auth_param.aka_OP, SM_UNUSED, my_aka_OP, sizeof(my_aka_OP)); + CK ck; + IK ik; + memset(ck, 0, sizeof ck); + memset(ik, 0, sizeof ik); if (createAuthHeader( - my_auth_user, my_auth_pass, src->getMethod(), uri, - auth_body, dialog_authentication, my_aka_OP, my_aka_AMF, - my_aka_K, next_nonce_count++, result + authlen, - MAX_HEADER_LEN - authlen) == 0) { - ERROR("%s", result + authlen); - } + my_auth_user, my_auth_pass, src->getMethod(), uri, + auth_body, dialog_authentication, my_aka_OP, my_aka_AMF, + my_aka_K, next_nonce_count++, result + authlen, + MAX_HEADER_LEN - authlen, ck, ik) == 0) { + WARNING("%s", result + authlen); +// ERROR("%s", result + authlen); + } else { + memcpy(_ck, ck, sizeof ck); + memcpy(_ik, ik, sizeof ik); + } authlen = strlen(result); /* Shift the end of the message to its rightful place. */ @@ -5251,9 +5272,9 @@ bool call::process_incoming(const char* msg, const struct sockaddr_storage* src) found = true; /* TODO : this is a little buggy: If a 100 trying from an INVITE - * is delayed by the network until the BYE is sent, it may - * stop BYE transmission erroneously, if the BYE also expects - * a 100 trying. */ + * is delayed by the network until the BYE is sent, it may + * stop BYE transmission erroneously, if the BYE also expects + * a 100 trying. */ break; } @@ -5718,13 +5739,28 @@ call::T_ActionResult call::executeAction(const char* msg, message* curmsg) call_socket->close(); call_socket = NULL; } - } else if (currentAction->getActionType() == CAction::E_AT_SET_DEST) { + } else if (currentAction->getActionType() == CAction::E_AT_SET_DEST || + currentAction->getActionType() == CAction::E_AT_SET_DEST_W_SPORT) { /* Change the destination for this call. */ char *str_host = strdup(createSendingMessage(currentAction->getMessage(0))); char *str_port = strdup(createSendingMessage(currentAction->getMessage(1))); char *str_protocol = strdup(createSendingMessage(currentAction->getMessage(2))); - char *endptr; + char *str_s_port = nullptr; + char *endptr; + int s_port = 0; + if (currentAction->getActionType() == CAction::E_AT_SET_DEST_W_SPORT) { + str_s_port = strdup(createSendingMessage(currentAction->getMessage(3))); + if (str_s_port) { + s_port = (int) strtod(str_s_port, &endptr); + if (*endptr) { + ERROR("Invalid source port for setdest: %s", str_port); + } + free(str_s_port); + } + } + + endptr = nullptr; int port = (int)strtod(str_port, &endptr); if (*endptr) { ERROR("Invalid port for setdest: %s", str_port); @@ -5788,6 +5824,10 @@ call::T_ActionResult call::executeAction(const char* msg, message* curmsg) } memcpy(&call_socket->ss_dest, &call_peer, sizeof(call_peer)); + if (s_port) { + call_socket->set_bind_port(s_port); + } + free(str_host); free(str_port); free(str_protocol); diff --git a/src/message.cpp b/src/message.cpp index 535d0496f..777d00e41 100644 --- a/src/message.cpp +++ b/src/message.cpp @@ -118,11 +118,13 @@ struct KeywordMap SimpleKeywords[] = { {"timestamp", E_Message_Timestamp }, {"date", E_Message_Date }, {"sipp_version", E_Message_SippVersion }, + {"ck_key", E_Message_CKey}, + {"ik_key", E_Message_IKey}, }; #define KEYWORD_SIZE 256 -static char* quoted_strchr(const char* s, int c) +static char* quoted_strchr(const char* s, char c) { const char* p; diff --git a/src/milenage.c b/src/milenage.c index a9bfd591a..2b4a022e4 100644 --- a/src/milenage.c +++ b/src/milenage.c @@ -156,8 +156,6 @@ void f2345(uint8_t k[16], uint8_t rand[16], for (i=0; i<16; i++) ik[i] = out[i]; - - return; } /* end of function f2345 */ diff --git a/src/scenario.cpp b/src/scenario.cpp index fc3a424f6..46a9b50c2 100644 --- a/src/scenario.cpp +++ b/src/scenario.cpp @@ -1071,8 +1071,13 @@ void clear_int_int(int_int_map m) scenario::~scenario() { - for (msgvec::iterator i = messages.begin(); i != messages.end(); i++) { - delete *i; + for (auto & i : initmessages) { + delete i; + } + initmessages.clear(); + + for (auto & message : messages) { + delete message; } messages.clear(); @@ -1081,8 +1086,8 @@ scenario::~scenario() allocVars->putTable(); delete stats; - for (unsigned int i = 0; i < transactions.size(); i++) { - free(transactions[i].name); + for (auto & transaction : transactions) { + free(transaction.name); } transactions.clear(); @@ -1561,23 +1566,51 @@ void scenario::parseAction(CActions *actions) username_ptr = password_ptr = NULL; } else if(!strcmp(actionElem, "lookup")) { tmpAction->setVarId(xp_get_var("assign_to", "lookup")); - tmpAction->setMessage(xp_get_string("file", "lookup"), 0); - tmpAction->setMessage(xp_get_string("key", "lookup"), 1); + auto _c = xp_get_string("file", "lookup"); + tmpAction->setMessage(_c, 0); + free(_c); + _c = xp_get_string("key", "lookup"); + tmpAction->setMessage(_c, 1); + free(_c); tmpAction->setActionType(CAction::E_AT_LOOKUP); } else if(!strcmp(actionElem, "insert")) { - tmpAction->setMessage(xp_get_string("file", "insert"), 0); - tmpAction->setMessage(xp_get_string("value", "insert"), 1); + auto _c = xp_get_string("file", "insert"); + tmpAction->setMessage(_c, 0); + free(_c); + _c = xp_get_string("value", "insert"); + tmpAction->setMessage(_c, 1); + free(_c); tmpAction->setActionType(CAction::E_AT_INSERT); } else if(!strcmp(actionElem, "replace")) { - tmpAction->setMessage(xp_get_string("file", "replace"), 0); - tmpAction->setMessage(xp_get_string("line", "replace"), 1); - tmpAction->setMessage(xp_get_string("value", "replace"), 2); + auto _c = xp_get_string("file", "replace"); + tmpAction->setMessage(_c, 0); + free(_c); + _c = xp_get_string("line", "replace"); + tmpAction->setMessage(_c, 1); + free(_c); + _c = xp_get_string("value", "replace"); + tmpAction->setMessage(_c, 2); + free(_c); tmpAction->setActionType(CAction::E_AT_REPLACE); } else if(!strcmp(actionElem, "setdest")) { - tmpAction->setMessage(xp_get_string("host", actionElem), 0); - tmpAction->setMessage(xp_get_string("port", actionElem), 1); - tmpAction->setMessage(xp_get_string("protocol", actionElem), 2); - tmpAction->setActionType(CAction::E_AT_SET_DEST); + auto _c = xp_get_string("host", actionElem); + tmpAction->setMessage(_c, 0); + free(_c); + _c = xp_get_string("port", actionElem); + tmpAction->setMessage(_c, 1); + free(_c); + _c = xp_get_string("protocol", actionElem); + tmpAction->setMessage(_c, 2); + free(_c); + const char *_ptr = xp_get_value("local_port"); + if (_ptr) { + _c = xp_get_string("local_port", actionElem); + tmpAction->setMessage(_c, 3); + free(_c); + tmpAction->setActionType(CAction::E_AT_SET_DEST_W_SPORT); + } else { + tmpAction->setActionType(CAction::E_AT_SET_DEST); + } } else if(!strcmp(actionElem, "closecon")) { tmpAction->setActionType(CAction::E_AT_CLOSE_CON); } else if(!strcmp(actionElem, "strcmp")) { diff --git a/src/screen.cpp b/src/screen.cpp index 28f9e8f6d..bd06ca0c7 100644 --- a/src/screen.cpp +++ b/src/screen.cpp @@ -699,8 +699,8 @@ void ScreenPrinter::draw_stats_screen() GET_TIME (¤tTime); // computing the real call rate - globalElapsedTime = s->computeDiffTimeInMs (¤tTime, &s->M_startTime); - localElapsedTime = s->computeDiffTimeInMs (¤tTime, &s->M_pdStartTime); + globalElapsedTime = CStat::computeDiffTimeInMs (¤tTime, &s->M_startTime); + localElapsedTime = CStat::computeDiffTimeInMs (¤tTime, &s->M_pdStartTime); // the call rate is for all the call : incoming and outgoing numberOfCall = (s->M_counters[s->CPT_C_IncomingCallCreated] + s->M_counters[s->CPT_C_OutgoingCallCreated]); @@ -741,7 +741,7 @@ void ScreenPrinter::draw_stats_screen() DISPLAY_PERIO ("Current Calls", s->M_counters[s->CPT_C_CurrentCall]); - if (s->M_genericMap.size()) { + if (!s->M_genericMap.empty()) { DISPLAY_CROSS_LINE (); } for (unsigned int i = 1; i < s->M_genericMap.size() + 1; i++) { diff --git a/src/sipp.cpp b/src/sipp.cpp index 49d53ba66..b1ba6540d 100644 --- a/src/sipp.cpp +++ b/src/sipp.cpp @@ -478,7 +478,7 @@ static void traffic_thread(int &rtp_errors, int &echo_errors) stattask::report(); screentask::report(false); - while (1) { + while (true) { scheduling_loops++; update_clock_tick(); @@ -1990,7 +1990,7 @@ int main(int argc, char *argv[]) // required number of signalling channels, and warn // if this may not allow enough media channels. if (!skip_rlimit) { - struct rlimit rlimit; + struct rlimit rlimit{}; unsigned max_sockets_needed = multisocket ? max_multi_socket : 1; if (getrlimit (RLIMIT_NOFILE, &rlimit) < 0) { @@ -2019,7 +2019,7 @@ int main(int argc, char *argv[]) } */ display_scenario = main_scenario; - aa_scenario = new scenario(0, find_scenario("ooc_dummy")); + aa_scenario = new scenario(nullptr, find_scenario("ooc_dummy")); aa_scenario->stats->setFileName("ooc_dummy", ".csv"); init_default_messages(); diff --git a/src/socket.cpp b/src/socket.cpp index 44ffbad0f..9c8f1ae66 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -101,7 +101,7 @@ int gai_getsockaddr(struct sockaddr_storage* ss, const char* host, } } -void sockaddr_update_port(struct sockaddr_storage* ss, short port) +void sockaddr_update_port(struct sockaddr_storage* ss, unsigned short port) { switch (ss->ss_family) { case AF_INET: @@ -1241,7 +1241,7 @@ void process_message(SIPpSocket *socket, char *msg, ssize_t msg_size, struct soc } SIPpSocket::SIPpSocket(bool use_ipv6, int transport, int fd, int accepting): - ss_count(1), + ss_count(0), ss_ipv6(use_ipv6), ss_transport(transport), ss_control(false), @@ -2921,7 +2921,7 @@ void SIPpSocket::pollset_process(int wait) if (!twinSippMode) { ERROR_NO("Accepting new TCP connection on Twin SIPp Socket"); } - twinSippSocket->ss_control = 1; + twinSippSocket->ss_control = true; } else { /* 3pcc extended mode: open a local socket which will be used for reading the infos sent by this remote @@ -2931,7 +2931,7 @@ void SIPpSocket::pollset_process(int wait) } SIPpSocket *localSocket = sock->accept(); - localSocket->ss_control = 1; + localSocket->ss_control = true; local_sockets[local_nb] = localSocket; local_nb++; if (!peers_connected) {