From: Dragos Oancea Date: Thu, 13 May 2021 13:49:09 +0000 (+0000) Subject: [mod_sofia] fix md5 digest infoleak X-Git-Tag: v1.10.7^2~296 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c41aa83b17e49f7bff44750fa815ec59a299fb12;p=thirdparty%2Ffreeswitch.git [mod_sofia] fix md5 digest infoleak [mod_sofia] refactor IP checks with sip-dig [mod_sofia] add sipp-based unit-tests (use spawn_instead_of_system) --- diff --git a/src/mod/endpoints/mod_sofia/Makefile.am b/src/mod/endpoints/mod_sofia/Makefile.am index 69343c455a..461db1e6e5 100644 --- a/src/mod/endpoints/mod_sofia/Makefile.am +++ b/src/mod/endpoints/mod_sofia/Makefile.am @@ -3,7 +3,7 @@ include $(top_srcdir)/build/modmake.rulesam MODNAME=mod_sofia noinst_LTLIBRARIES = libsofiamod.la -libsofiamod_la_SOURCES = mod_sofia.c sofia.c sofia_json_api.c sofia_glue.c sofia_presence.c sofia_reg.c sofia_media.c sip-dig.c rtp.c mod_sofia.h +libsofiamod_la_SOURCES = mod_sofia.c sofia.c sofia_json_api.c sofia_glue.c sofia_presence.c sofia_reg.c sofia_media.c sip-dig.c rtp.c mod_sofia.h sip-dig.h libsofiamod_la_LDFLAGS = -static libsofiamod_la_CFLAGS = $(AM_CFLAGS) -I. $(SOFIA_SIP_CFLAGS) $(STIRSHAKEN_CFLAGS) if HAVE_STIRSHAKEN @@ -15,7 +15,7 @@ mod_sofia_la_SOURCES = mod_sofia_la_LIBADD = $(switch_builddir)/libfreeswitch.la libsofiamod.la mod_sofia_la_LDFLAGS = -avoid-version -module -no-undefined -shared $(SOFIA_SIP_LIBS) $(STIRSHAKEN_LIBS) -noinst_PROGRAMS = test/test_sofia_funcs test/test_nuafail +noinst_PROGRAMS = test/test_sofia_funcs test/test_nuafail test/sipp-based-tests test_test_sofia_funcs_SOURCES = test/test_sofia_funcs.c test_test_sofia_funcs_CFLAGS = $(AM_CFLAGS) $(SOFIA_SIP_CFLAGS) $(STIRSHAKEN_CFLAGS) -DSWITCH_TEST_BASE_DIR_FOR_CONF=\"${abs_builddir}/test\" -DSWITCH_TEST_BASE_DIR_OVERRIDE=\"${abs_builddir}/test\" @@ -33,11 +33,17 @@ endif test_test_nuafail_LDFLAGS = $(AM_LDFLAGS) -avoid-version -no-undefined $(freeswitch_LDFLAGS) $(switch_builddir)/libfreeswitch.la $(CORE_LIBS) $(APR_LIBS) $(STIRSHAKEN_LIBS) test_test_nuafail_LDADD = libsofiamod.la $(SOFIA_SIP_LIBS) -TESTS = test/test_sofia_funcs.sh test/test_nuafail +test_sipp_based_tests_SOURCES = test/sipp-based-tests.c +test_sipp_based_tests_CFLAGS = $(AM_CFLAGS) $(SOFIA_SIP_CFLAGS) -DSWITCH_TEST_BASE_DIR_FOR_CONF=\"${abs_builddir}/test\" -DSWITCH_TEST_BASE_DIR_OVERRIDE=\"${abs_builddir}/test\" +test_sipp_based_tests_LDFLAGS = $(AM_LDFLAGS) -avoid-version -no-undefined $(freeswitch_LDFLAGS) $(switch_builddir)/libfreeswitch.la $(CORE_LIBS) $(APR_LIBS) +test_sipp_based_tests_LDADD = libsofiamod.la $(SOFIA_SIP_LIBS) + +TESTS = test/test_sofia_funcs.sh test/test_nuafail test/test_run_sipp.sh if ISMAC mod_sofia_la_LDFLAGS += -framework CoreFoundation -framework SystemConfiguration test_test_sofia_funcs_LDFLAGS += -framework CoreFoundation -framework SystemConfiguration test_test_nuafail_LDFLAGS += -framework CoreFoundation -framework SystemConfiguration +test_sipp_based_tests_LDFLAGS += -framework CoreFoundation -framework SystemConfiguration endif diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 02128bf2fd..63697dbbda 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -91,6 +91,7 @@ typedef struct private_object private_object_t; #define MY_EVENT_REINVITE "sofia::reinvite" #define MY_EVENT_GATEWAY_ADD "sofia::gateway_add" #define MY_EVENT_GATEWAY_DEL "sofia::gateway_delete" +#define MY_EVENT_GATEWAY_INVALID_DIGEST_REQ "sofia::gateway_invalid_digest_req" #define MY_EVENT_RECOVERY "sofia::recovery_recv" #define MY_EVENT_RECOVERY_SEND "sofia::recovery_send" #define MY_EVENT_RECOVERY_RECOVERED "sofia::recovery_recovered" @@ -570,6 +571,7 @@ struct sofia_gateway { sofia_cid_type_t cid_type; char register_network_ip[80]; int register_network_port; + char *gw_auth_acl; }; typedef enum { diff --git a/src/mod/endpoints/mod_sofia/sip-dig.c b/src/mod/endpoints/mod_sofia/sip-dig.c index 2d74eb66f6..e89f5aef44 100644 --- a/src/mod/endpoints/mod_sofia/sip-dig.c +++ b/src/mod/endpoints/mod_sofia/sip-dig.c @@ -143,6 +143,8 @@ #include "sofia-sip/su_alloc.h" #include "sofia-sip/su_string.h" #include "sofia-sip/hostdomain.h" +#include "sip-dig.h" +#include "mod_sofia.h" char const name[] = "sip-dig"; @@ -151,59 +153,51 @@ char const name[] = "sip-dig"; #include #include -enum { N_TPORT = 16 }; - -struct transport { char const *name, *service, *srv; }; - -struct dig { - sres_resolver_t *sres; - - unsigned preference, ip4, ip6, sips, print; - - struct transport tports[N_TPORT + 1]; -}; - -int dig_naptr(struct dig *dig, char const *host, double weight, switch_stream_handle_t *stream); - -int dig_all_srvs(struct dig *dig, char const *tport, char const *host, - double weight, switch_stream_handle_t *stream); +void _usage(int exitcode, switch_stream_handle_t *stream) +{ + stream->write_function(stream, "%s", "usage: sofia_dig [OPTIONS] [@dnsserver] uri\n"); +} -int dig_srv(struct dig *dig, char const *tport, char const *host, - double weight, switch_stream_handle_t *stream); +#define usage(_x) _usage(_x, stream); goto fail -int dig_srv_at(struct dig *dig, - char const *tport, sres_record_t **answers, - double weight, int pweight, - int priority, switch_stream_handle_t *stream); +switch_bool_t verify_ip(sres_record_t **answers, const char *ip, switch_bool_t ipv6) +{ + char addr[64]; + int i; -int dig_addr(struct dig *dig, - char const *tport, char const *host, char const *port, - double weight, switch_stream_handle_t *stream); + if (!answers) { + return SWITCH_FALSE; + } -void print_addr_results(struct transport const *tports, - char const *tport, char const *tport2, - sres_record_t **answers, int type, int af, - char const *port, - double weight, int preference, switch_stream_handle_t *stream); + if (!*answers) { + return SWITCH_FALSE; + } -void print_result(char const *addr, char const *port, char const *tport, - double weight, - unsigned preference, - switch_stream_handle_t *stream); + for (i = 0; answers[i]; i++) { + if (ipv6) { + if (answers[i]->sr_record->r_type != sres_type_aaaa) + continue; + } else { + if (answers[i]->sr_record->r_type != sres_type_a) + continue; + } + if (answers[i]->sr_record->r_status != 0) + continue; -int prepare_transport(struct dig *dig, char const *tport); + if (ipv6) { + su_inet_ntop(AF_INET6, &answers[i]->sr_aaaa->aaaa_addr, addr, sizeof addr); + } else { + su_inet_ntop(AF_INET, &answers[i]->sr_a->a_addr, addr, sizeof addr); + } -int count_transports(struct dig *dig, - char const *tp1, - char const *tp2); + if (ip && !strcmp(addr, ip)) { + return SWITCH_TRUE; + } + } -void _usage(int exitcode, switch_stream_handle_t *stream) -{ - stream->write_function(stream, "%s", "usage: sofia_dig [OPTIONS] [@dnsserver] uri\n"); + return SWITCH_FALSE; } -#define usage(_x) _usage(_x, stream); goto fail - switch_status_t sip_dig_function(_In_opt_z_ const char *cmd, _In_opt_ switch_core_session_t *session, _In_ switch_stream_handle_t *stream) { @@ -608,6 +602,27 @@ int dig_naptr(struct dig *dig, return count; } +switch_bool_t dig_all_srvs_simple(struct dig *dig, + char const *host, char const *ip, switch_bool_t ipv6) +{ + sres_record_t **answers; + char *domain = su_strcat(NULL, dig->tports[0].srv, host); + switch_bool_t ret; + int error = -1; + + if (domain) { + error = sres_blocking_query(dig->sres, sres_type_srv, domain, 0, &answers); + free(domain); + } + + if (error >= 0) { + ret = dig_srv_at_simple_verify(dig, dig->tports[0].name, answers, ip, ipv6); + if (ret) return SWITCH_TRUE; + } + + return SWITCH_FALSE; +} + int dig_all_srvs(struct dig *dig, char const *tport, char const *host, @@ -735,6 +750,36 @@ int dig_srv(struct dig *dig, return count; } +switch_bool_t dig_srv_at_simple_verify(struct dig *dig, + char const *tport, + sres_record_t **answers, const char *ip, switch_bool_t ipv6) +{ + int i; + sres_record_t **retanswers = { 0 }; + + if (!answers) { + return SWITCH_FALSE; + } + + for (i = 0; answers[i]; i++) { + sres_srv_record_t const *srv = answers[i]->sr_srv; + if (srv->srv_record->r_type != sres_type_srv) + continue; + if (srv->srv_record->r_status != 0) + continue; + retanswers = dig_addr_simple(dig, srv->srv_target, ipv6?sres_type_aaaa:sres_type_a); + if (verify_ip(retanswers, ip, ipv6)) { + sres_free_answers(dig->sres, retanswers); + return SWITCH_TRUE; + } + } + + if (retanswers && *retanswers) { + sres_free_answers(dig->sres, retanswers); + } + return SWITCH_FALSE; +} + int dig_srv_at(struct dig *dig, char const *tport, sres_record_t **answers, @@ -758,7 +803,6 @@ int dig_srv_at(struct dig *dig, if (srv->srv_priority != priority) continue; snprintf(port, sizeof port, "%u", srv->srv_port); - count += dig_addr(dig, tport, srv->srv_target, port, weight * srv->srv_weight / pweight, stream); } @@ -766,6 +810,17 @@ int dig_srv_at(struct dig *dig, return count; } +sres_record_t ** dig_addr_simple(struct dig *dig, + char const *host, + uint16_t type) +{ + sres_record_t **answers = NULL; + + sres_blocking_query(dig->sres, type, host, 0, &answers); + + return answers; +} + int dig_addr(struct dig *dig, char const *tport, char const *host, diff --git a/src/mod/endpoints/mod_sofia/sip-dig.h b/src/mod/endpoints/mod_sofia/sip-dig.h new file mode 100644 index 0000000000..10dd76a067 --- /dev/null +++ b/src/mod/endpoints/mod_sofia/sip-dig.h @@ -0,0 +1,197 @@ +/* + * This file is part of the Sofia-SIP package + * + * Copyright (C) 2006 Nokia Corporation. + * + * Contact: Pekka Pessi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * This is an example program for @b sresolv library in synchronous mode. + * + * @author Pekka Pessi + * + * @date Original Created: Tue Jul 16 18:50:14 2002 ppessi + */ + +/**@page sip-dig Resolve SIP URIs. + * + * @section sip_dig_synopsis Synopsis + * sip-dig [OPTIONS] uri... + * + * @section sip_dig_description Description + * The @em sip-dig utility resolves SIP URIs as described in @RFC3263. It + * queries NAPTR, SRV and A/AAAA records and prints out the resulting + * transport addresses. + * + * The default transports are: UDP, TCP, SCTP, TLS and TLS-SCTP. The SIPS + * URIs are resolved using only TLS transports, TLS and TLS-SCTP. If not + * otherwise indicated by NAPTR or SRV records, the sip-dig uses UDP and TCP + * as transports for SIP and TLS for SIPS URIs. + * + * The results are printed intended, with a preference followed by weight, + * then protocol name, port number and IP address in numeric format. + * + * @section sip_dig_options Command Line Options + * The @e sip-dig utility accepts following command line options: + *
+ *
-p protoname
+ *
Use named transport protocol. The protoname can be either + * well-known, e.g., "udp", or it can specify NAPTR service and SRV + * identifier, e.g., "tls-udp/SIPS+D2U/_sips._udp.". + *
+ *
--udp
+ *
Use UDP transport protocol. + *
+ *
--tcp
+ *
Use TCP transport protocol. + *
+ *
--tls
+ *
Use TLS over TCP transport protocol. + *
+ *
--sctp
+ *
Use SCTP transport protocol. + *
+ *
--tls-sctp
+ *
Use TLS over SCTP transport protocol. + *
+ *
--no-sctp
+ *
Ignore SCTP or TLS-SCTP records in the list of default transports. + * This option has no effect if transport protocols has been explicitly + * listed. + *
+ *
-4
+ *
Query IP4 addresses (A records) + *
+ *
-6
+ *
Query IP6 addresses (AAAA records). + *
+ *
-v
+ *
Be verbatim. + *
+ *
+ *
+ *
+ *
+ * + * @section sip_dig_return Return Codes + * + *
0when successful (a 2XX-series response is received) + *
1when unsuccessful (a 3XX..6XX-series response is received) + *
2initialization failure + *
+ * + * @section sip_dig_examples Examples + * + * Resolve sip:openlaboratory.net, prefer TLS over TCP, TCP over UDP: + * @code + * $ sip-dig --tls --tcp --udp sip:openlaboratory.net + * 1 0.333 tls 5061 212.213.221.127 + * 2 0.333 tcp 5060 212.213.221.127 + * 3 0.333 udp 5060 212.213.221.127 + * @endcode + * + * Resolve sips:example.net with TLS over SCTP (TLS-SCTP) and TLS: + * @code + * $ sip-dig -p tls-sctp --tls sips:example.net + * 1 0.500 tls-udp 5061 172.21.55.26 + * 2 0.500 tls 5061 172.21.55.26 + * @endcode + * + * @section sip_dig_environment Environment + * #SRESOLV_DEBUG, SRESOLV_CONF + * + * @section sip_dig_bugs Reporting Bugs + * Report bugs to . + * + * @section sip_dig_author Author + * Written by Pekka Pessi + * + * @section sip_dig_copyright Copyright + * Copyright (C) 2006 Nokia Corporation. + * + * This program is free software; see the source for copying conditions. + * There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. + */ + +#include "sofia-resolv/sres.h" +#include "sofia-resolv/sres_record.h" + +enum { N_TPORT = 16 }; + +struct transport { char const *name, *service, *srv; }; + +struct dig { + sres_resolver_t *sres; + + unsigned preference, ip4, ip6, sips, print; + + struct transport tports[N_TPORT + 1]; +}; + +int dig_naptr(struct dig *dig, char const *host, double weight, switch_stream_handle_t *stream); + +int dig_all_srvs(struct dig *dig, char const *tport, char const *host, + double weight, switch_stream_handle_t *stream); + +int dig_srv(struct dig *dig, char const *tport, char const *host, + double weight, switch_stream_handle_t *stream); + +int dig_srv_at(struct dig *dig, + char const *tport, sres_record_t **answers, + double weight, int pweight, + int priority, switch_stream_handle_t *stream); + +int dig_addr(struct dig *dig, + char const *tport, char const *host, char const *port, + double weight, switch_stream_handle_t *stream); + +void print_addr_results(struct transport const *tports, + char const *tport, char const *tport2, + sres_record_t **answers, int type, int af, + char const *port, + double weight, int preference, switch_stream_handle_t *stream); + +void print_result(char const *addr, char const *port, char const *tport, + double weight, + unsigned preference, + switch_stream_handle_t *stream); + +int prepare_transport(struct dig *dig, char const *tport); + +int count_transports(struct dig *dig, + char const *tp1, + char const *tp2); + +switch_bool_t dig_srv_at_simple_verify(struct dig *dig, + char const *tport, + sres_record_t **answers, const char *ip, switch_bool_t ipv6); + +switch_bool_t dig_all_srvs_simple(struct dig *dig, + char const *host, const char *ip, switch_bool_t ipv6); + +sres_record_t ** dig_addr_simple(struct dig *dig, + char const *host, + uint16_t type); + +switch_bool_t sofia_sip_resolve_compare(const char *domainname, const char *ip); + +switch_bool_t verify_ip(sres_record_t **answers, const char *ip, switch_bool_t ipv6); + diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 3474df96bd..54d0dbdfe8 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -3973,6 +3973,10 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag, } gateway->register_transport = transport; + } else if (!strcmp(var, "gw-auth-acl")) { + if (!zstr(val)) { + gateway->gw_auth_acl = switch_core_strdup(gateway->pool, val); + } } } diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 6263e05170..03cb0fb6d0 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -38,6 +38,8 @@ * */ #include "mod_sofia.h" +#include "sofia-sip/hostdomain.h" +#include "sip-dig.h" static void sofia_reg_new_handle(sofia_gateway_t *gateway_ptr, int attach) { @@ -2432,6 +2434,126 @@ void sofia_reg_handle_sip_i_register(nua_t *nua, sofia_profile_t *profile, nua_h } +switch_bool_t sip_resolve_prepare_transport(struct dig *dig, sofia_transport_t tport) +{ + struct transport *tports = dig->tports; + + if (tport == SOFIA_TRANSPORT_UDP) { + tports[0].name = "udp"; + tports[0].service = "SIP+D2U"; + tports[0].srv = "_sip._udp."; + } + else if (tport == SOFIA_TRANSPORT_TCP) { + tports[0].name = "tcp"; + tports[0].service = "SIP+D2T"; + tports[0].srv = "_sip._tcp."; + } + else if (tport == SOFIA_TRANSPORT_TCP_TLS) { + tports[0].name = "tls"; + tports[0].service = "SIPS+D2T"; + tports[0].srv = "_sips._tcp."; + } + else if (tport == SOFIA_TRANSPORT_SCTP) { + tports[0].name = "sctp"; + tports[0].service = "SIP+D2S"; + tports[0].srv = "_sip._sctp."; + } else { + return SWITCH_FALSE; + } + return SWITCH_TRUE; +} + +/* resolve domain name (SRV + A + AAAA) and compare result with passed IP address */ +switch_bool_t sip_resolve_compare(const char *domainname, const char *ip, sofia_transport_t transport) +{ + url_t *uri = NULL; + char const *host; + char const *port; + struct dig dig[1] = {{ NULL }}; + su_home_t *home = NULL; + sres_record_t **answers = NULL; + switch_bool_t ret = SWITCH_FALSE, ipv6 = SWITCH_FALSE; + + if (!host_is_domain(domainname)) { + return ret; + } + + if (!sip_resolve_prepare_transport(dig, transport)) { + return ret; + } + + home = su_home_new(sizeof(*home)); + + dig->sres = sres_resolver_new(getenv("SRESOLV_CONF")); + + uri = url_hdup(home, (void *)domainname); + + if (uri && uri->url_type == url_unknown) + url_sanitize(uri); + + if (uri && uri->url_type == url_any) { + goto out; + } + + if (!uri || (uri->url_type != url_sip && uri->url_type != url_sips)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "invalid uri\n"); + goto out; + } + + port = url_port(uri); + if (port && !port[0]) port = NULL; + + host = uri->url_host; + + if (strchr(ip, ':')) { + ipv6 = SWITCH_TRUE; + } + ret = dig_all_srvs_simple(dig, domainname, ip, ipv6); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "verify 1\n"); + + if (!ret) { + answers = dig_addr_simple(dig, host, ipv6?sres_type_aaaa:sres_type_a); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "verify 2\n"); + ret = verify_ip(answers, ip, ipv6); + } + +out: + su_home_unref(home); + sres_resolver_unref(dig->sres); + + return ret; +} + +static switch_bool_t is_legitimate_gateway(sofia_dispatch_event_t *de, sofia_gateway_t *gateway) +{ + char remote_ip[80] = { 0 }; + switch_bool_t ret = SWITCH_FALSE; + + sofia_glue_get_addr(de->data->e_msg, remote_ip, sizeof(remote_ip), NULL); + + if (gateway->gw_auth_acl) { + ret = switch_check_network_list_ip(remote_ip, gateway->gw_auth_acl); + if (!ret) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Challange from [%s] denied by gw-auth-acl.\n", remote_ip); + } + return ret; + } else { + char *register_host = sofia_glue_get_register_host(gateway->register_proxy); + const char *host = sofia_glue_strip_proto(register_host); + + if (host_is_ip_address(host)) { + if (host && !strcmp(host, remote_ip)) { + ret = SWITCH_TRUE; + } + switch_safe_free(register_host); + return ret; + } else { + ret = sip_resolve_compare(host, remote_ip, gateway->register_transport); + switch_safe_free(register_host); + return ret; + } + } +} void sofia_reg_handle_sip_r_register(int status, char const *phrase, @@ -2463,6 +2585,7 @@ void sofia_reg_handle_sip_r_register(int status, sofia_glue_get_addr(de->data->e_msg, network_ip, sizeof(network_ip), &gateway->register_network_port); if (!zstr_buf(network_ip)) { snprintf(gateway->register_network_ip, sizeof(gateway->register_network_ip), (msg_addrinfo(de->data->e_msg))->ai_addr->sa_family == AF_INET6 ? "[%s]" : "%s", network_ip); + } } @@ -2684,11 +2807,22 @@ void sofia_reg_handle_sip_r_challenge(int status, if (sip_auth_username && sip_auth_password) { switch_snprintf(authentication, sizeof(authentication), "%s:%s:%s:%s", scheme, realm, sip_auth_username, sip_auth_password); - } else if (gateway) { + } else if (gateway && is_legitimate_gateway(de, gateway)) { switch_snprintf(authentication, sizeof(authentication), "%s:%s:%s:%s", scheme, realm, gateway->auth_username, gateway->register_password); } else { + if (gateway) { + switch_event_t *s_event; + if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_GATEWAY_INVALID_DIGEST_REQ) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "Gateway", gateway->name); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", gateway->profile->name); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "realm", realm); + switch_event_fire(&s_event); + } + } + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, - "Cannot locate any authentication credentials to complete an authentication request for realm '%s'\n", realm); + "Cannot locate any authentication credentials to complete an authentication request for realm '%s'\n", realm); + goto cancel; } diff --git a/src/mod/endpoints/mod_sofia/test/conf-sipp/freeswitch.xml b/src/mod/endpoints/mod_sofia/test/conf-sipp/freeswitch.xml new file mode 100644 index 0000000000..088a7a545c --- /dev/null +++ b/src/mod/endpoints/mod_sofia/test/conf-sipp/freeswitch.xml @@ -0,0 +1,1458 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + diff --git a/src/mod/endpoints/mod_sofia/test/sipp-based-tests.c b/src/mod/endpoints/mod_sofia/test/sipp-based-tests.c new file mode 100644 index 0000000000..382dbc2970 --- /dev/null +++ b/src/mod/endpoints/mod_sofia/test/sipp-based-tests.c @@ -0,0 +1,295 @@ + +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005-2021, Anthony Minessale II + * + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * + * The Initial Developer of the Original Code is + * Anthony Minessale II + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Dragos Oancea + * + * + * sipp-based-tests.c - Test FreeSwitch using sipp (https://github.com/SIPp/sipp) + * + */ + +#include +#include +#include + +int test_success = 0; +int test_sofia_debug = 1; + +static switch_bool_t has_ipv6() +{ + switch_stream_handle_t stream = { 0 }; + SWITCH_STANDARD_STREAM(stream); + switch_api_execute("sofia", "status profile external-ipv6", NULL, &stream); + + if (strstr((char *)stream.data, "Invalid Profile")) { + + switch_safe_free(stream.data); + + return SWITCH_FALSE; + } + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "STATUS PROFILE: %s\n", (char *) stream.data); + + switch_safe_free(stream.data); + + return SWITCH_TRUE; +} + +static int start_sipp_uac(const char *ip, int remote_port,const char *scenario_uac, const char *extra) +{ + char *cmd = switch_mprintf("sipp %s:%d -nr -p 5062 -m 1 -s 1001 -recv_timeout 10000 -timeout 10s -sf %s -bg %s", ip, remote_port, scenario_uac, extra); + int sys_ret = switch_system(cmd, SWITCH_TRUE); + + printf("%s\n", cmd); + switch_safe_free(cmd); + switch_sleep(1000 * 1000); + return sys_ret; +} + +static void kill_sipp(void) +{ + switch_system("pkill -x sipp", SWITCH_TRUE); + switch_sleep(1000 * 1000); +} + +static void event_handler(switch_event_t *event) +{ + const char *new_ev = switch_event_get_header(event, "Event-Subclass"); + char *str; + + if (new_ev && !strcmp(new_ev, "sofia::gateway_invalid_digest_req")) { + test_success = 1; + } + + /*print the event*/ + switch_event_serialize_json(event, &str); + if (str) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s\n", str); + switch_safe_free(str); + } +} + +FST_CORE_EX_BEGIN("./conf-sipp", SCF_VG | SCF_USE_SQL) +{ + FST_MODULE_BEGIN(mod_sofia, uac-uas) + { + FST_SETUP_BEGIN() + { + switch_stream_handle_t stream = { 0 }; + SWITCH_STANDARD_STREAM(stream); + switch_api_execute("sofia", "global siptrace on", NULL, &stream); + if (test_sofia_debug) { + switch_api_execute("sofia", "loglevel all 9", NULL, &stream); + switch_api_execute("sofia", "tracelevel debug", NULL, &stream); + } + switch_safe_free(stream.data); + + switch_core_set_variable("spawn_instead_of_system", "true"); + + fst_requires_module("mod_sndfile"); + fst_requires_module("mod_voicemail"); + fst_requires_module("mod_sofia"); + fst_requires_module("mod_loopback"); + fst_requires_module("mod_console"); + fst_requires_module("mod_dptools"); + fst_requires_module("mod_dialplan_xml"); + fst_requires_module("mod_commands"); + fst_requires_module("mod_say_en"); + fst_requires_module("mod_tone_stream"); + + } + FST_SETUP_END() + + FST_TEARDOWN_BEGIN() + { + } + FST_TEARDOWN_END() + + FST_TEST_BEGIN(uac_digest_leak_udp) + { + switch_core_session_t *session; + switch_call_cause_t cause; + switch_status_t status; + switch_channel_t *channel; + const char *local_ip_v4 = switch_core_get_variable("local_ip_v4"); + int sipp_ret; + + switch_event_bind("sofia", SWITCH_EVENT_CUSTOM, NULL, event_handler, NULL); + + status = switch_ivr_originate(NULL, &session, &cause, "loopback/+15553334444", 2, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL, NULL); + sipp_ret = start_sipp_uac(local_ip_v4, 5080, "sipp-scenarios/uac_digest_leak.xml", ""); + if (sipp_ret < 0 || sipp_ret == 127) { + fst_requires(0); /* sipp not found */ + } + + fst_check(status == SWITCH_STATUS_SUCCESS); + if (!session) { + fst_requires(session); + } + + channel = switch_core_session_get_channel(session); + fst_xcheck(switch_channel_get_state(channel) < CS_HANGUP, "Expect call not to be hung up"); + + while (1) { + int ret; + switch_sleep(1000 * 1000); + ret = switch_system("pidof sipp", SWITCH_TRUE); + if (!ret) { + break; + } + } + + switch_sleep(5000 * 1000); + + switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); + + switch_core_session_rwunlock(session); + switch_sleep(1000 * 1000); + + switch_event_unbind_callback(event_handler); + /* sipp should timeout, attempt kill, just in case.*/ + kill_sipp(); + fst_check(test_success); + test_success = 0; + } + FST_TEST_END() + + FST_TEST_BEGIN(uac_digest_leak_tcp) + { + switch_core_session_t *session; + switch_call_cause_t cause; + switch_status_t status; + switch_channel_t *channel; + const char *local_ip_v4 = switch_core_get_variable("local_ip_v4"); + int sipp_ret; + + switch_event_bind("sofia", SWITCH_EVENT_CUSTOM, NULL, event_handler, NULL); + + status = switch_ivr_originate(NULL, &session, &cause, "loopback/+15553334444", 2, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL, NULL); + sipp_ret = start_sipp_uac(local_ip_v4, 5080, "sipp-scenarios/uac_digest_leak-tcp.xml", "-t t1"); + if (sipp_ret < 0 || sipp_ret == 127) { + fst_requires(0); /* sipp not found */ + } + + fst_check(status == SWITCH_STATUS_SUCCESS); + if (!session) { + fst_requires(session); + } + + channel = switch_core_session_get_channel(session); + fst_xcheck(switch_channel_get_state(channel) < CS_HANGUP, "Expect call not to be hung up"); + + while (1) { + int ret; + switch_sleep(1000 * 1000); + ret = switch_system("pidof sipp", SWITCH_TRUE); + if (!ret) { + break; + } + } + + switch_sleep(5000 * 1000); + + switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); + + switch_core_session_rwunlock(session); + switch_sleep(1000 * 1000); + + switch_event_unbind_callback(event_handler); + /* sipp should timeout, attempt kill, just in case.*/ + kill_sipp(); + fst_check(test_success); + test_success = 0; + } + FST_TEST_END() + + FST_TEST_BEGIN(uac_digest_leak_udp_ipv6) + { + switch_core_session_t *session; + switch_call_cause_t cause; + switch_status_t status; + switch_channel_t *channel; + const char *local_ip_v6 = switch_core_get_variable("local_ip_v6"); + int sipp_ret; + char *ipv6 = NULL; + + if (!has_ipv6()) { + goto skiptest; + } + switch_event_bind("sofia", SWITCH_EVENT_CUSTOM, NULL, event_handler, NULL); + + if (!strchr(local_ip_v6,'[')) { + ipv6 = switch_mprintf("[%s]", local_ip_v6); + } + status = switch_ivr_originate(NULL, &session, &cause, "loopback/+15553334444", 2, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL, NULL); + + if (!ipv6) { + sipp_ret = start_sipp_uac(local_ip_v6, 6060, "sipp-scenarios/uac_digest_leak-ipv6.xml", "-i [::1]"); + } else { + sipp_ret = start_sipp_uac(ipv6, 6060, "sipp-scenarios/uac_digest_leak-ipv6.xml", "-i [::1] -mi [::1]"); + } + + if (sipp_ret < 0 || sipp_ret == 127) { + fst_requires(0); /* sipp not found */ + } + + fst_check(status == SWITCH_STATUS_SUCCESS); + if (!session) { + fst_requires(session); + } + + channel = switch_core_session_get_channel(session); + fst_xcheck(switch_channel_get_state(channel) < CS_HANGUP, "Expect call not to be hung up"); + + while (1) { + int ret; + switch_sleep(1000 * 1000); + ret = switch_system("pidof sipp", SWITCH_TRUE); + if (!ret) { + break; + } + } + + switch_sleep(5000 * 1000); + + switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); + + switch_core_session_rwunlock(session); + switch_sleep(1000 * 1000); + + switch_event_unbind_callback(event_handler); + /* sipp should timeout, attempt kill, just in case.*/ + kill_sipp(); + switch_safe_free(ipv6); + fst_check(test_success); +skiptest: + test_success = 0; + } + FST_TEST_END() + + } + FST_MODULE_END() +} +FST_CORE_END() diff --git a/src/mod/endpoints/mod_sofia/test/sipp-scenarios/uac_digest_leak-ipv6.xml b/src/mod/endpoints/mod_sofia/test/sipp-scenarios/uac_digest_leak-ipv6.xml new file mode 100644 index 0000000000..6ddbe069da --- /dev/null +++ b/src/mod/endpoints/mod_sofia/test/sipp-scenarios/uac_digest_leak-ipv6.xml @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + ;tag=[call_number] + To: sut + Call-ID: [call_id] + CSeq: 1 INVITE + Contact: sip:1001@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Content-Type: application/sdp + Content-Length: [len] + + v=0 + o=user1 53655765 2353687637 IN IP[local_ip_type] 0000:0000:0000:0000:0000:0000:0000:0001 + s=- + c=IN IP6 0000:0000:0000:0000:0000:0000:0000:0001 + t=0 0 + m=audio [media_port] RTP/AVP 0 + a=rtpmap:0 PCMU/8000 + + ]]> + + + + + + + + + + + + + + + + + + + + + ;tag=[call_number] + To: sut [peer_tag_param] + Call-ID: [call_id] + CSeq: 1 ACK + Contact: sip:1001@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Content-Length: 0 + + ]]> + + + + + + + + + + + + + + + + diff --git a/src/mod/endpoints/mod_sofia/test/sipp-scenarios/uac_digest_leak-tcp.xml b/src/mod/endpoints/mod_sofia/test/sipp-scenarios/uac_digest_leak-tcp.xml new file mode 100644 index 0000000000..7276fa1d46 --- /dev/null +++ b/src/mod/endpoints/mod_sofia/test/sipp-scenarios/uac_digest_leak-tcp.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + ;tag=[call_number] + To: sut + Call-ID: [call_id] + CSeq: 1 INVITE + Contact: + Max-Forwards: 70 + Subject: Performance Test + Content-Type: application/sdp + Content-Length: [len] + + v=0 + o=user1 53655765 2353687637 IN IP[local_ip_type] 127.0.0.1 + s=- + c=IN IP[media_ip_type] 127.0.0.1 + t=0 0 + m=audio [media_port] RTP/AVP 0 + a=rtpmap:0 PCMU/8000 + + ]]> + + + + + + + + + + + + + + + + + + + + + ;tag=[call_number] + To: sut [peer_tag_param] + Call-ID: [call_id] + CSeq: 1 ACK + Contact: + Max-Forwards: 70 + Subject: Performance Test + Content-Length: 0 + + ]]> + + + + + + + + + + + + + + + + + diff --git a/src/mod/endpoints/mod_sofia/test/sipp-scenarios/uac_digest_leak.xml b/src/mod/endpoints/mod_sofia/test/sipp-scenarios/uac_digest_leak.xml new file mode 100644 index 0000000000..7c1e9ebd62 --- /dev/null +++ b/src/mod/endpoints/mod_sofia/test/sipp-scenarios/uac_digest_leak.xml @@ -0,0 +1,98 @@ + + + + + + + + + + + + + ;tag=[call_number] + To: sut + Call-ID: [call_id] + CSeq: 1 INVITE + Contact: sip:1001@127.0.0.1:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Content-Type: application/sdp + Content-Length: [len] + + v=0 + o=user1 53655765 2353687637 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 + a=rtpmap:0 PCMU/8000 + + ]]> + + + + + + + + + + + + + + + + + + + + + ;tag=[call_number] + To: sut [peer_tag_param] + Call-ID: [call_id] + CSeq: 1 ACK + Contact: sip:1001@127.0.0.1:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Content-Length: 0 + + ]]> + + + + + + + + + + + + + + + + diff --git a/src/mod/endpoints/mod_sofia/test/test_run_sipp.sh b/src/mod/endpoints/mod_sofia/test/test_run_sipp.sh new file mode 100755 index 0000000000..fbe01c144d --- /dev/null +++ b/src/mod/endpoints/mod_sofia/test/test_run_sipp.sh @@ -0,0 +1,3 @@ +#/bin/sh +./sipp-based-tests + diff --git a/src/mod/endpoints/mod_sofia/test/voicemail/vm-goodbye.wav b/src/mod/endpoints/mod_sofia/test/voicemail/vm-goodbye.wav new file mode 100644 index 0000000000..b656226bf1 Binary files /dev/null and b/src/mod/endpoints/mod_sofia/test/voicemail/vm-goodbye.wav differ diff --git a/src/mod/endpoints/mod_sofia/test/voicemail/vm-not_available.wav b/src/mod/endpoints/mod_sofia/test/voicemail/vm-not_available.wav new file mode 100644 index 0000000000..fc5358332f Binary files /dev/null and b/src/mod/endpoints/mod_sofia/test/voicemail/vm-not_available.wav differ diff --git a/src/mod/endpoints/mod_sofia/test/voicemail/vm-person.wav b/src/mod/endpoints/mod_sofia/test/voicemail/vm-person.wav new file mode 100644 index 0000000000..9d008b1b51 Binary files /dev/null and b/src/mod/endpoints/mod_sofia/test/voicemail/vm-person.wav differ diff --git a/src/mod/endpoints/mod_sofia/test/voicemail/vm-record_message.wav b/src/mod/endpoints/mod_sofia/test/voicemail/vm-record_message.wav new file mode 100644 index 0000000000..b591ec528f Binary files /dev/null and b/src/mod/endpoints/mod_sofia/test/voicemail/vm-record_message.wav differ diff --git a/src/mod/endpoints/mod_sofia/test/voicemail/vm-too-small.wav b/src/mod/endpoints/mod_sofia/test/voicemail/vm-too-small.wav new file mode 100644 index 0000000000..35ca061177 Binary files /dev/null and b/src/mod/endpoints/mod_sofia/test/voicemail/vm-too-small.wav differ