mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-05-30 18:33:46 +00:00
[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)
This commit is contained in:
parent
8a40ba20bd
commit
c41aa83b17
@ -3,7 +3,7 @@ include $(top_srcdir)/build/modmake.rulesam
|
|||||||
MODNAME=mod_sofia
|
MODNAME=mod_sofia
|
||||||
|
|
||||||
noinst_LTLIBRARIES = libsofiamod.la
|
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_LDFLAGS = -static
|
||||||
libsofiamod_la_CFLAGS = $(AM_CFLAGS) -I. $(SOFIA_SIP_CFLAGS) $(STIRSHAKEN_CFLAGS)
|
libsofiamod_la_CFLAGS = $(AM_CFLAGS) -I. $(SOFIA_SIP_CFLAGS) $(STIRSHAKEN_CFLAGS)
|
||||||
if HAVE_STIRSHAKEN
|
if HAVE_STIRSHAKEN
|
||||||
@ -15,7 +15,7 @@ mod_sofia_la_SOURCES =
|
|||||||
mod_sofia_la_LIBADD = $(switch_builddir)/libfreeswitch.la libsofiamod.la
|
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)
|
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_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\"
|
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_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)
|
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
|
if ISMAC
|
||||||
mod_sofia_la_LDFLAGS += -framework CoreFoundation -framework SystemConfiguration
|
mod_sofia_la_LDFLAGS += -framework CoreFoundation -framework SystemConfiguration
|
||||||
test_test_sofia_funcs_LDFLAGS += -framework CoreFoundation -framework SystemConfiguration
|
test_test_sofia_funcs_LDFLAGS += -framework CoreFoundation -framework SystemConfiguration
|
||||||
test_test_nuafail_LDFLAGS += -framework CoreFoundation -framework SystemConfiguration
|
test_test_nuafail_LDFLAGS += -framework CoreFoundation -framework SystemConfiguration
|
||||||
|
test_sipp_based_tests_LDFLAGS += -framework CoreFoundation -framework SystemConfiguration
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -91,6 +91,7 @@ typedef struct private_object private_object_t;
|
|||||||
#define MY_EVENT_REINVITE "sofia::reinvite"
|
#define MY_EVENT_REINVITE "sofia::reinvite"
|
||||||
#define MY_EVENT_GATEWAY_ADD "sofia::gateway_add"
|
#define MY_EVENT_GATEWAY_ADD "sofia::gateway_add"
|
||||||
#define MY_EVENT_GATEWAY_DEL "sofia::gateway_delete"
|
#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 "sofia::recovery_recv"
|
||||||
#define MY_EVENT_RECOVERY_SEND "sofia::recovery_send"
|
#define MY_EVENT_RECOVERY_SEND "sofia::recovery_send"
|
||||||
#define MY_EVENT_RECOVERY_RECOVERED "sofia::recovery_recovered"
|
#define MY_EVENT_RECOVERY_RECOVERED "sofia::recovery_recovered"
|
||||||
@ -570,6 +571,7 @@ struct sofia_gateway {
|
|||||||
sofia_cid_type_t cid_type;
|
sofia_cid_type_t cid_type;
|
||||||
char register_network_ip[80];
|
char register_network_ip[80];
|
||||||
int register_network_port;
|
int register_network_port;
|
||||||
|
char *gw_auth_acl;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -143,6 +143,8 @@
|
|||||||
#include "sofia-sip/su_alloc.h"
|
#include "sofia-sip/su_alloc.h"
|
||||||
#include "sofia-sip/su_string.h"
|
#include "sofia-sip/su_string.h"
|
||||||
#include "sofia-sip/hostdomain.h"
|
#include "sofia-sip/hostdomain.h"
|
||||||
|
#include "sip-dig.h"
|
||||||
|
#include "mod_sofia.h"
|
||||||
|
|
||||||
char const name[] = "sip-dig";
|
char const name[] = "sip-dig";
|
||||||
|
|
||||||
@ -151,52 +153,6 @@ char const name[] = "sip-dig";
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.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);
|
|
||||||
|
|
||||||
void _usage(int exitcode, 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");
|
stream->write_function(stream, "%s", "usage: sofia_dig [OPTIONS] [@dnsserver] uri\n");
|
||||||
@ -204,6 +160,44 @@ void _usage(int exitcode, switch_stream_handle_t *stream)
|
|||||||
|
|
||||||
#define usage(_x) _usage(_x, stream); goto fail
|
#define usage(_x) _usage(_x, stream); goto fail
|
||||||
|
|
||||||
|
switch_bool_t verify_ip(sres_record_t **answers, const char *ip, switch_bool_t ipv6)
|
||||||
|
{
|
||||||
|
char addr[64];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!answers) {
|
||||||
|
return SWITCH_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!*answers) {
|
||||||
|
return SWITCH_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ip && !strcmp(addr, ip)) {
|
||||||
|
return SWITCH_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SWITCH_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
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;
|
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,
|
int dig_all_srvs(struct dig *dig,
|
||||||
char const *tport,
|
char const *tport,
|
||||||
char const *host,
|
char const *host,
|
||||||
@ -735,6 +750,36 @@ int dig_srv(struct dig *dig,
|
|||||||
return count;
|
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,
|
int dig_srv_at(struct dig *dig,
|
||||||
char const *tport,
|
char const *tport,
|
||||||
sres_record_t **answers,
|
sres_record_t **answers,
|
||||||
@ -758,7 +803,6 @@ int dig_srv_at(struct dig *dig,
|
|||||||
if (srv->srv_priority != priority)
|
if (srv->srv_priority != priority)
|
||||||
continue;
|
continue;
|
||||||
snprintf(port, sizeof port, "%u", srv->srv_port);
|
snprintf(port, sizeof port, "%u", srv->srv_port);
|
||||||
|
|
||||||
count += dig_addr(dig, tport, srv->srv_target, port,
|
count += dig_addr(dig, tport, srv->srv_target, port,
|
||||||
weight * srv->srv_weight / pweight, stream);
|
weight * srv->srv_weight / pweight, stream);
|
||||||
}
|
}
|
||||||
@ -766,6 +810,17 @@ int dig_srv_at(struct dig *dig,
|
|||||||
return count;
|
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,
|
int dig_addr(struct dig *dig,
|
||||||
char const *tport,
|
char const *tport,
|
||||||
char const *host,
|
char const *host,
|
||||||
|
197
src/mod/endpoints/mod_sofia/sip-dig.h
Normal file
197
src/mod/endpoints/mod_sofia/sip-dig.h
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Sofia-SIP package
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Nokia Corporation.
|
||||||
|
*
|
||||||
|
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||||
|
*
|
||||||
|
* 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 <Pekka.Pessi@nokia.com>
|
||||||
|
*
|
||||||
|
* @date Original Created: Tue Jul 16 18:50:14 2002 ppessi
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**@page sip-dig Resolve SIP URIs.
|
||||||
|
*
|
||||||
|
* @section sip_dig_synopsis Synopsis
|
||||||
|
* <tt>sip-dig [OPTIONS] uri...</tt>
|
||||||
|
*
|
||||||
|
* @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:
|
||||||
|
* <dl>
|
||||||
|
* <dt>-p <em>protoname</em></dt>
|
||||||
|
* <dd>Use named transport protocol. The <em>protoname</em> 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.".
|
||||||
|
* </dd>
|
||||||
|
* <dt>--udp</dt>
|
||||||
|
* <dd>Use UDP transport protocol.
|
||||||
|
* </dd>
|
||||||
|
* <dt>--tcp</dt>
|
||||||
|
* <dd>Use TCP transport protocol.
|
||||||
|
* </dd>
|
||||||
|
* <dt>--tls</dt>
|
||||||
|
* <dd>Use TLS over TCP transport protocol.
|
||||||
|
* </dd>
|
||||||
|
* <dt>--sctp</dt>
|
||||||
|
* <dd>Use SCTP transport protocol.
|
||||||
|
* </dd>
|
||||||
|
* <dt>--tls-sctp</dt>
|
||||||
|
* <dd>Use TLS over SCTP transport protocol.
|
||||||
|
* </dd>
|
||||||
|
* <dt>--no-sctp</dt>
|
||||||
|
* <dd>Ignore SCTP or TLS-SCTP records in the list of default transports.
|
||||||
|
* This option has no effect if transport protocols has been explicitly
|
||||||
|
* listed.
|
||||||
|
* </dd>
|
||||||
|
* <dt>-4</dt>
|
||||||
|
* <dd>Query IP4 addresses (A records)
|
||||||
|
* </dd>
|
||||||
|
* <dt>-6</dt>
|
||||||
|
* <dd>Query IP6 addresses (AAAA records).
|
||||||
|
* </dd>
|
||||||
|
* <dt>-v</dt>
|
||||||
|
* <dd>Be verbatim.
|
||||||
|
* </dd>
|
||||||
|
* <dt></dt>
|
||||||
|
* <dd>
|
||||||
|
* </dd>
|
||||||
|
* </dl>
|
||||||
|
*
|
||||||
|
* @section sip_dig_return Return Codes
|
||||||
|
* <table>
|
||||||
|
* <tr><td>0<td>when successful (a 2XX-series response is received)
|
||||||
|
* <tr><td>1<td>when unsuccessful (a 3XX..6XX-series response is received)
|
||||||
|
* <tr><td>2<td>initialization failure
|
||||||
|
* </table>
|
||||||
|
*
|
||||||
|
* @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 <sofia-sip-devel@lists.sourceforge.net>.
|
||||||
|
*
|
||||||
|
* @section sip_dig_author Author
|
||||||
|
* Written by Pekka Pessi <pekka -dot pessi -at- nokia -dot- com>
|
||||||
|
*
|
||||||
|
* @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);
|
||||||
|
|
@ -3973,6 +3973,10 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag,
|
|||||||
}
|
}
|
||||||
|
|
||||||
gateway->register_transport = transport;
|
gateway->register_transport = transport;
|
||||||
|
} else if (!strcmp(var, "gw-auth-acl")) {
|
||||||
|
if (!zstr(val)) {
|
||||||
|
gateway->gw_auth_acl = switch_core_strdup(gateway->pool, val);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,6 +38,8 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#include "mod_sofia.h"
|
#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)
|
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,
|
void sofia_reg_handle_sip_r_register(int status,
|
||||||
char const *phrase,
|
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);
|
sofia_glue_get_addr(de->data->e_msg, network_ip, sizeof(network_ip), &gateway->register_network_port);
|
||||||
if (!zstr_buf(network_ip)) {
|
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);
|
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) {
|
if (sip_auth_username && sip_auth_password) {
|
||||||
switch_snprintf(authentication, sizeof(authentication), "%s:%s:%s:%s", scheme, realm, 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);
|
switch_snprintf(authentication, sizeof(authentication), "%s:%s:%s:%s", scheme, realm, gateway->auth_username, gateway->register_password);
|
||||||
} else {
|
} 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,
|
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;
|
goto cancel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1458
src/mod/endpoints/mod_sofia/test/conf-sipp/freeswitch.xml
Normal file
1458
src/mod/endpoints/mod_sofia/test/conf-sipp/freeswitch.xml
Normal file
File diff suppressed because it is too large
Load Diff
295
src/mod/endpoints/mod_sofia/test/sipp-based-tests.c
Normal file
295
src/mod/endpoints/mod_sofia/test/sipp-based-tests.c
Normal file
@ -0,0 +1,295 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||||
|
* Copyright (C) 2005-2021, Anthony Minessale II <anthm@freeswitch.org>
|
||||||
|
*
|
||||||
|
* 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 <anthm@freeswitch.org>
|
||||||
|
* Portions created by the Initial Developer are Copyright (C)
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Dragos Oancea <dragos@signalwire.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* sipp-based-tests.c - Test FreeSwitch using sipp (https://github.com/SIPp/sipp)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <switch.h>
|
||||||
|
#include <test/switch_test.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
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()
|
@ -0,0 +1,100 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||||
|
<!DOCTYPE scenario SYSTEM "sipp.dtd">
|
||||||
|
|
||||||
|
<!-- SIP digest leak test scenario -->
|
||||||
|
<!-- Note: realm at WWW-Authenticate may have to be changed if phone realm configuration is not empty -->
|
||||||
|
<!-- (empty realm at phone configuration = auth against any realm) -->
|
||||||
|
<!-- http://tomeko.net -->
|
||||||
|
|
||||||
|
<scenario name="SIP digest leak test">
|
||||||
|
<!-- In client mode (sipp placing calls), the Call-ID MUST be -->
|
||||||
|
<!-- generated by sipp. To do so, use [call_id] keyword. -->
|
||||||
|
|
||||||
|
<!-- FS: ipv4 in sdp is intentional -->
|
||||||
|
<send retrans="500">
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
INVITE sip:[service]@[remote_ip]:[remote_port] SIP/2.0
|
||||||
|
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
|
||||||
|
From: sipp <sip:1001@[local_ip]:[local_port]>;tag=[call_number]
|
||||||
|
To: sut <sip:[service]@[remote_ip]:[remote_port]>
|
||||||
|
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
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<recv response="100"
|
||||||
|
optional="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<recv response="183" optional="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<recv response="180" optional="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<!-- By adding rrs="true" (Record Route Sets), the route sets -->
|
||||||
|
<!-- are saved and used for following messages sent. Useful to test -->
|
||||||
|
<!-- against stateful SIP proxies/B2BUAs. -->
|
||||||
|
<recv response="200" rtd="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<!-- Packet lost can be simulated in any send/recv message by -->
|
||||||
|
<!-- by adding the 'lost = "10"'. Value can be [1-100] percent. -->
|
||||||
|
<send>
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
ACK sip:[service]@[remote_ip]:[remote_port] SIP/2.0
|
||||||
|
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
|
||||||
|
From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[call_number]
|
||||||
|
To: sut <sip:[service]@[remote_ip]:[remote_port]>[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
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<!-- At this moment second party is hanging up call (no audio there) -->
|
||||||
|
<recv request="BYE"></recv>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Test with SIP hardware phone: must use WWW-Authenticate instead of Proxy-Authenticate.
|
||||||
|
You could also try with SIP/2.0 401 Unauthorized. -->
|
||||||
|
|
||||||
|
<send>
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
SIP/2.0 407 Proxy Authentication Required
|
||||||
|
[last_Via:]
|
||||||
|
[last_From:]
|
||||||
|
[last_To:]
|
||||||
|
[last_Call-ID:]
|
||||||
|
[last_CSeq:]
|
||||||
|
Proxy-Authenticate: Digest algorithm=MD5, realm="freeswitch.org", nonce="69d327e5"
|
||||||
|
Content-Length: 0
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<recv request="BYE"></recv>
|
||||||
|
|
||||||
|
|
||||||
|
</scenario>
|
@ -0,0 +1,99 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||||
|
<!DOCTYPE scenario SYSTEM "sipp.dtd">
|
||||||
|
|
||||||
|
<!-- SIP digest leak test scenario -->
|
||||||
|
<!-- Note: realm at WWW-Authenticate may have to be changed if phone realm configuration is not empty -->
|
||||||
|
<!-- (empty realm at phone configuration = auth against any realm) -->
|
||||||
|
<!-- http://tomeko.net -->
|
||||||
|
|
||||||
|
<scenario name="SIP digest leak test">
|
||||||
|
<!-- In client mode (sipp placing calls), the Call-ID MUST be -->
|
||||||
|
<!-- generated by sipp. To do so, use [call_id] keyword. -->
|
||||||
|
<send retrans="500">
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
INVITE sip:[service]@[remote_ip]:[remote_port];transport=tcp SIP/2.0
|
||||||
|
Via: SIP/2.0/[transport] 127.0.0.1:[local_port];branch=[branch];transport=tcp
|
||||||
|
From: sipp <sip:1001@127.0.0.1:[local_port];transport=tcp>;tag=[call_number]
|
||||||
|
To: sut <sip:[service]@[remote_ip]:[remote_port];transport=tcp>
|
||||||
|
Call-ID: [call_id]
|
||||||
|
CSeq: 1 INVITE
|
||||||
|
Contact: <sip:1001@127.0.0.1:[local_port];transport=tcp>
|
||||||
|
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
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<recv response="100"
|
||||||
|
optional="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<recv response="183" optional="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<recv response="180" optional="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<!-- By adding rrs="true" (Record Route Sets), the route sets -->
|
||||||
|
<!-- are saved and used for following messages sent. Useful to test -->
|
||||||
|
<!-- against stateful SIP proxies/B2BUAs. -->
|
||||||
|
<recv response="200" rtd="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<!-- Packet lost can be simulated in any send/recv message by -->
|
||||||
|
<!-- by adding the 'lost = "10"'. Value can be [1-100] percent. -->
|
||||||
|
<send>
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
ACK sip:[service]@[remote_ip]:[remote_port];transport=tcp SIP/2.0
|
||||||
|
Via: SIP/2.0/[transport] 127.0.0.1:[local_port];branch=[branch];transport=tcp
|
||||||
|
From: sipp <sip:sipp@127.0.0.1:[local_port]>;tag=[call_number]
|
||||||
|
To: sut <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]
|
||||||
|
Call-ID: [call_id]
|
||||||
|
CSeq: 1 ACK
|
||||||
|
Contact: <sip:1001@127.0.0.1:[local_port];transport=tcp>
|
||||||
|
Max-Forwards: 70
|
||||||
|
Subject: Performance Test
|
||||||
|
Content-Length: 0
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<!-- At this moment second party is hanging up call (no audio there) -->
|
||||||
|
|
||||||
|
<recv request="BYE"></recv>
|
||||||
|
|
||||||
|
<!-- <pause milliseconds="1000"/> -->
|
||||||
|
<!-- Test with SIP hardware phone: must use WWW-Authenticate instead of Proxy-Authenticate.
|
||||||
|
You could also try with SIP/2.0 401 Unauthorized. -->
|
||||||
|
|
||||||
|
<send>
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
SIP/2.0 407 Proxy Authentication Required
|
||||||
|
[last_Via:]
|
||||||
|
[last_From:]
|
||||||
|
[last_To:]
|
||||||
|
[last_Call-ID:]
|
||||||
|
[last_CSeq:]
|
||||||
|
Proxy-Authenticate: Digest algorithm=MD5, realm="freeswitch.org", nonce="69d327e5"
|
||||||
|
Content-Length: 0
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<recv request="BYE"></recv>
|
||||||
|
|
||||||
|
|
||||||
|
</scenario>
|
@ -0,0 +1,98 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||||
|
<!DOCTYPE scenario SYSTEM "sipp.dtd">
|
||||||
|
|
||||||
|
<!-- SIP digest leak test scenario -->
|
||||||
|
<!-- Note: realm at WWW-Authenticate may have to be changed if phone realm configuration is not empty -->
|
||||||
|
<!-- (empty realm at phone configuration = auth against any realm) -->
|
||||||
|
<!-- http://tomeko.net -->
|
||||||
|
|
||||||
|
<scenario name="SIP digest leak test">
|
||||||
|
<!-- In client mode (sipp placing calls), the Call-ID MUST be -->
|
||||||
|
<!-- generated by sipp. To do so, use [call_id] keyword. -->
|
||||||
|
<send retrans="500">
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
INVITE sip:[service]@[remote_ip]:[remote_port] SIP/2.0
|
||||||
|
Via: SIP/2.0/[transport] 127.0.0.1:[local_port];branch=[branch]
|
||||||
|
From: sipp <sip:1001@127.0.0.1:[local_port]>;tag=[call_number]
|
||||||
|
To: sut <sip:[service]@[remote_ip]:[remote_port]>
|
||||||
|
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
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<recv response="100"
|
||||||
|
optional="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<recv response="183" optional="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<recv response="180" optional="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<!-- By adding rrs="true" (Record Route Sets), the route sets -->
|
||||||
|
<!-- are saved and used for following messages sent. Useful to test -->
|
||||||
|
<!-- against stateful SIP proxies/B2BUAs. -->
|
||||||
|
<recv response="200" rtd="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<!-- Packet lost can be simulated in any send/recv message by -->
|
||||||
|
<!-- by adding the 'lost = "10"'. Value can be [1-100] percent. -->
|
||||||
|
<send>
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
ACK sip:[service]@[remote_ip]:[remote_port] SIP/2.0
|
||||||
|
Via: SIP/2.0/[transport] 127.0.0.1:[local_port];branch=[branch]
|
||||||
|
From: sipp <sip:sipp@127.0.0.1:[local_port]>;tag=[call_number]
|
||||||
|
To: sut <sip:[service]@[remote_ip]:[remote_port]>[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
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<!-- At this moment second party is hanging up call (no audio there) -->
|
||||||
|
<recv request="BYE"></recv>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Test with SIP hardware phone: must use WWW-Authenticate instead of Proxy-Authenticate.
|
||||||
|
You could also try with SIP/2.0 401 Unauthorized. -->
|
||||||
|
|
||||||
|
<send>
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
SIP/2.0 407 Proxy Authentication Required
|
||||||
|
[last_Via:]
|
||||||
|
[last_From:]
|
||||||
|
[last_To:]
|
||||||
|
[last_Call-ID:]
|
||||||
|
[last_CSeq:]
|
||||||
|
Proxy-Authenticate: Digest algorithm=MD5, realm="freeswitch.org", nonce="69d327e5"
|
||||||
|
Content-Length: 0
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<recv request="BYE"></recv>
|
||||||
|
|
||||||
|
|
||||||
|
</scenario>
|
3
src/mod/endpoints/mod_sofia/test/test_run_sipp.sh
Executable file
3
src/mod/endpoints/mod_sofia/test/test_run_sipp.sh
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#/bin/sh
|
||||||
|
./sipp-based-tests
|
||||||
|
|
BIN
src/mod/endpoints/mod_sofia/test/voicemail/vm-goodbye.wav
Normal file
BIN
src/mod/endpoints/mod_sofia/test/voicemail/vm-goodbye.wav
Normal file
Binary file not shown.
BIN
src/mod/endpoints/mod_sofia/test/voicemail/vm-not_available.wav
Normal file
BIN
src/mod/endpoints/mod_sofia/test/voicemail/vm-not_available.wav
Normal file
Binary file not shown.
BIN
src/mod/endpoints/mod_sofia/test/voicemail/vm-person.wav
Normal file
BIN
src/mod/endpoints/mod_sofia/test/voicemail/vm-person.wav
Normal file
Binary file not shown.
BIN
src/mod/endpoints/mod_sofia/test/voicemail/vm-record_message.wav
Normal file
BIN
src/mod/endpoints/mod_sofia/test/voicemail/vm-record_message.wav
Normal file
Binary file not shown.
BIN
src/mod/endpoints/mod_sofia/test/voicemail/vm-too-small.wav
Normal file
BIN
src/mod/endpoints/mod_sofia/test/voicemail/vm-too-small.wav
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user