diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h
index 63697dbbda..1ffd39dc6e 100644
--- a/src/mod/endpoints/mod_sofia/mod_sofia.h
+++ b/src/mod/endpoints/mod_sofia/mod_sofia.h
@@ -527,6 +527,9 @@ struct sofia_gateway {
char *register_proxy;
char *register_sticky_proxy;
char *outbound_sticky_proxy;
+ char *register_proxy_host_cfg; /* hold only the IP or the hostname, no port, no "sip:" or "sips:" prefix */
+ char *outbound_proxy_host_cfg;
+ char *proxy_host_cfg;
char *register_context;
char *expires_str;
char *register_url;
@@ -1258,6 +1261,7 @@ void sofia_glue_pause_jitterbuffer(switch_core_session_t *session, switch_bool_t
void sofia_process_dispatch_event(sofia_dispatch_event_t **dep);
void sofia_process_dispatch_event_in_thread(sofia_dispatch_event_t **dep);
char *sofia_glue_get_host(const char *str, switch_memory_pool_t *pool);
+char *sofia_glue_get_host_from_cfg(const char *str, switch_memory_pool_t *pool);
void sofia_presence_check_subscriptions(sofia_profile_t *profile, time_t now);
void sofia_msg_thread_start(int idx);
void crtp_init(switch_loadable_module_interface_t *module_interface);
diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c
index 54d0dbdfe8..a752a4a8f4 100644
--- a/src/mod/endpoints/mod_sofia/sofia.c
+++ b/src/mod/endpoints/mod_sofia/sofia.c
@@ -3950,8 +3950,10 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag,
contact_host = val;
} else if (!strcmp(var, "register-proxy")) {
register_proxy = val;
+ gateway->register_proxy_host_cfg = sofia_glue_get_host_from_cfg(register_proxy, gateway->pool);
} else if (!strcmp(var, "outbound-proxy")) {
outbound_proxy = val;
+ gateway->outbound_proxy_host_cfg = sofia_glue_get_host_from_cfg(outbound_proxy, gateway->pool);
} else if (!strcmp(var, "distinct-to")) {
distinct_to = switch_true(val);
} else if (!strcmp(var, "destination-prefix")) {
@@ -4025,6 +4027,8 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag,
proxy = realm;
}
+ gateway->proxy_host_cfg = sofia_glue_get_host_from_cfg(proxy, gateway->pool);
+
if (!switch_true(register_str)) {
gateway->state = REG_STATE_NOREG;
gateway->status = SOFIA_GATEWAY_UP;
diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c
index 10282383d2..1f2afef85c 100644
--- a/src/mod/endpoints/mod_sofia/sofia_glue.c
+++ b/src/mod/endpoints/mod_sofia/sofia_glue.c
@@ -3539,6 +3539,42 @@ char *sofia_glue_get_profile_url(sofia_profile_t *profile, char *remote_ip, cons
return url;
}
+/* gets the IP or HOST from a sip uri or from x.x.x.x:port format */
+char *sofia_glue_get_host_from_cfg(const char *uri, switch_memory_pool_t *pool)
+{
+ char *host = NULL;
+ const char *s;
+ char *p = NULL;
+
+ if (zstr(uri)) {
+ return NULL;
+ }
+
+ if ((s = switch_stristr("sip:", uri)) && s == uri) {
+ s += 4;
+ } else if ((s = switch_stristr("sips:", uri)) && s == uri) {
+ s += 5;
+ }
+
+ if (!s) {
+ s = uri;
+ }
+
+ host = switch_core_strdup(pool, s);
+
+ if ((p = strchr(host, ']'))) {
+ if (*(p + 1) == ':') {
+ *(p + 1) = '\0';
+ }
+ } else {
+ if ((p = strrchr(host, ':'))) {
+ *p = '\0';
+ }
+ }
+
+ return host;
+}
+
/* For Emacs:
* Local Variables:
* mode:c
diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c
index 03cb0fb6d0..49dc8feeda 100644
--- a/src/mod/endpoints/mod_sofia/sofia_reg.c
+++ b/src/mod/endpoints/mod_sofia/sofia_reg.c
@@ -2508,12 +2508,11 @@ switch_bool_t sip_resolve_compare(const char *domainname, const char *ip, sofia_
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);
}
@@ -2524,6 +2523,36 @@ out:
return ret;
}
+static switch_bool_t is_host_from_gateway(const char *remote_ip, sofia_gateway_t *gateway)
+{
+ switch_bool_t ret = SWITCH_FALSE;
+ char *hosts[3]; /* check the 3 places where we keep IP/hostname */
+ int i;
+
+ hosts[0] = gateway->proxy_host_cfg;
+ hosts[1] = gateway->register_proxy_host_cfg;
+ hosts[2] = gateway->outbound_proxy_host_cfg;
+
+ for (i = 0; i < 3; i++) {
+ if (zstr(hosts[i])) {
+ continue;
+ }
+
+ if (host_is_ip_address(hosts[i])) {
+ if (!strcmp(hosts[i], remote_ip)) {
+ ret = SWITCH_TRUE;
+ }
+
+ if (ret) break;
+ } else {
+ ret = sip_resolve_compare(hosts[i], remote_ip, gateway->register_transport);
+ if (ret) break;
+ }
+ }
+
+ return ret;
+}
+
static switch_bool_t is_legitimate_gateway(sofia_dispatch_event_t *de, sofia_gateway_t *gateway)
{
char remote_ip[80] = { 0 };
@@ -2531,27 +2560,16 @@ static switch_bool_t is_legitimate_gateway(sofia_dispatch_event_t *de, sofia_gat
sofia_glue_get_addr(de->data->e_msg, remote_ip, sizeof(remote_ip), NULL);
+ /* setting param "gw-auth-acl" supersedes everything */
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;
- }
+ return is_host_from_gateway(remote_ip, gateway);
}
}
diff --git a/src/mod/endpoints/mod_sofia/test/conf-sipp/freeswitch.xml b/src/mod/endpoints/mod_sofia/test/conf-sipp/freeswitch.xml
index 088a7a545c..dee105561b 100644
--- a/src/mod/endpoints/mod_sofia/test/conf-sipp/freeswitch.xml
+++ b/src/mod/endpoints/mod_sofia/test/conf-sipp/freeswitch.xml
@@ -322,11 +322,41 @@
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -365,7 +395,7 @@
-
+
diff --git a/src/mod/endpoints/mod_sofia/test/sipp-based-tests.c b/src/mod/endpoints/mod_sofia/test/sipp-based-tests.c
index 382dbc2970..03a0e4a654 100644
--- a/src/mod/endpoints/mod_sofia/test/sipp-based-tests.c
+++ b/src/mod/endpoints/mod_sofia/test/sipp-based-tests.c
@@ -57,6 +57,22 @@ static switch_bool_t has_ipv6()
return SWITCH_TRUE;
}
+static void register_gw()
+{
+ switch_stream_handle_t stream = { 0 };
+ SWITCH_STANDARD_STREAM(stream);
+ switch_api_execute("sofia", "profile external register testgw", NULL, &stream);
+ switch_safe_free(stream.data);
+}
+
+static void unregister_gw()
+{
+ switch_stream_handle_t stream = { 0 };
+ SWITCH_STANDARD_STREAM(stream);
+ switch_api_execute("sofia", "profile external unregister testgw", NULL, &stream);
+ switch_safe_free(stream.data);
+}
+
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);
@@ -65,24 +81,29 @@ static int start_sipp_uac(const char *ip, int remote_port,const char *scenario_u
printf("%s\n", cmd);
switch_safe_free(cmd);
switch_sleep(1000 * 1000);
+
return sys_ret;
}
+static int start_sipp_uas(const char *ip, int listen_port, const char *scenario_uas, const char *extra)
+{
+ char *cmd = switch_mprintf("sipp %s -p %d -nr -m 1 -s 1001 -recv_timeout 10000 -timeout 10s -sf %s -bg %s", ip, listen_port, scenario_uas, 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");
+static void show_event(switch_event_t *event) {
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) {
@@ -91,6 +112,45 @@ static void event_handler(switch_event_t *event)
}
}
+static void event_handler(switch_event_t *event)
+{
+ const char *new_ev = switch_event_get_header(event, "Event-Subclass");
+
+ if (new_ev && !strcmp(new_ev, "sofia::gateway_invalid_digest_req")) {
+ test_success = 1;
+ }
+
+ show_event(event);
+}
+
+static void event_handler_reg_ok(switch_event_t *event)
+{
+ const char *new_ev = switch_event_get_header(event, "Event-Subclass");
+
+ if (new_ev && !strcmp(new_ev, "sofia::gateway_state")) {
+ const char *state = switch_event_get_header(event, "State");
+ if (state && !strcmp(state, "REGED")) {
+ test_success++;
+ }
+ }
+
+ show_event(event);
+}
+
+static void event_handler_reg_fail(switch_event_t *event)
+{
+ const char *new_ev = switch_event_get_header(event, "Event-Subclass");
+
+ if (new_ev && !strcmp(new_ev, "sofia::gateway_state")) {
+ const char *state = switch_event_get_header(event, "State");
+ if (state && !strcmp(state, "FAIL_WAIT")) {
+ test_success++;
+ }
+ }
+
+ show_event(event);
+}
+
FST_CORE_EX_BEGIN("./conf-sipp", SCF_VG | SCF_USE_SQL)
{
FST_MODULE_BEGIN(mod_sofia, uac-uas)
@@ -289,6 +349,132 @@ skiptest:
}
FST_TEST_END()
+ FST_TEST_BEGIN(register_ok)
+ {
+ 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_reg_ok, NULL);
+
+ sipp_ret = start_sipp_uas(local_ip_v4, 6080, "sipp-scenarios/uas_register.xml", "");
+ if (sipp_ret < 0 || sipp_ret == 127) {
+ fst_requires(0); /* sipp not found */
+ }
+
+ switch_sleep(1000 * 1000);
+
+ register_gw();
+
+ switch_sleep(5000 * 1000);
+
+ switch_event_unbind_callback(event_handler_reg_ok);
+ /* sipp should timeout, attempt kill, just in case.*/
+ kill_sipp();
+ fst_check(test_success);
+ test_success = 0;
+ }
+ FST_TEST_END()
+
+ FST_TEST_BEGIN(register_403)
+ {
+ 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_reg_fail, NULL);
+
+ sipp_ret = start_sipp_uas(local_ip_v4, 6080, "sipp-scenarios/uas_register_403.xml", "");
+ if (sipp_ret < 0 || sipp_ret == 127) {
+ fst_requires(0); /* sipp not found */
+ }
+
+ switch_sleep(1000 * 1000);
+
+ register_gw();
+
+ switch_sleep(5000 * 1000);
+
+ switch_event_unbind_callback(event_handler_reg_fail);
+ /* sipp should timeout, attempt kill, just in case.*/
+ kill_sipp();
+ fst_check(test_success);
+ test_success = 0;
+ }
+ FST_TEST_END()
+
+ FST_TEST_BEGIN(register_no_challange)
+ {
+ 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_reg_ok, NULL);
+
+ sipp_ret = start_sipp_uas(local_ip_v4, 6080, "sipp-scenarios/uas_register_no_challange.xml", "");
+ if (sipp_ret < 0 || sipp_ret == 127) {
+ fst_requires(0); /* sipp not found */
+ }
+
+ switch_sleep(1000 * 1000);
+
+ register_gw();
+
+ switch_sleep(5000 * 1000);
+
+ /*the REGISTER with Expires 0 */
+ unregister_gw();
+
+ switch_sleep(1000 * 1000);
+
+ register_gw();
+
+ switch_sleep(1000 * 1000);
+
+ switch_event_unbind_callback(event_handler_reg_ok);
+
+ /* sipp should timeout, attempt kill, just in case.*/
+ kill_sipp();
+ fst_check(test_success);
+ test_success = 0;
+ }
+ FST_TEST_END()
+
+ FST_TEST_BEGIN(invite_407)
+ {
+ const char *local_ip_v4 = switch_core_get_variable("local_ip_v4");
+ int sipp_ret;
+ switch_core_session_t *session;
+ switch_call_cause_t cause;
+ switch_status_t status;
+ switch_channel_t *channel;
+ char *to;
+ const int inv_sipp_port = 6082;
+
+ sipp_ret = start_sipp_uas(local_ip_v4, inv_sipp_port, "sipp-scenarios/uas_407.xml", "");
+ if (sipp_ret < 0 || sipp_ret == 127) {
+ fst_requires(0); /* sipp not found */
+ }
+
+ switch_sleep(1000 * 1000);
+ to = switch_mprintf("sofia/gateway/testgw-noreg/sipp@%s:%d", local_ip_v4, inv_sipp_port);
+ /*originate will fail if the 407 we get from sipp is dropped due to wrong IP.*/
+ status = switch_ivr_originate(NULL, &session, &cause, to, 2, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL, NULL);
+ fst_check(status == SWITCH_STATUS_SUCCESS);
+
+ /*test is considered PASSED if we get a session*/
+ if (!session) {
+ fst_requires(session);
+ }
+
+ switch_sleep(1000 * 1000);
+
+ channel = switch_core_session_get_channel(session);
+ switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
+ switch_core_session_rwunlock(session);
+ switch_safe_free(to);
+ /* sipp should timeout, attempt kill, just in case.*/
+ kill_sipp();
+ }
+ FST_TEST_END()
+
}
FST_MODULE_END()
}
diff --git a/src/mod/endpoints/mod_sofia/test/sipp-scenarios/uas_407.xml b/src/mod/endpoints/mod_sofia/test/sipp-scenarios/uas_407.xml
new file mode 100644
index 0000000000..62ac17babc
--- /dev/null
+++ b/src/mod/endpoints/mod_sofia/test/sipp-scenarios/uas_407.xml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+ Proxy-Authenticate: Digest realm="freeswitch.org", nonce="47ebe028cda119c35d4877b383027d28da013815"
+ Content-Length: [len]
+
+ ]]>
+
+
+
+
+
+
+
+
+ Content-Length: 0
+
+ ]]>
+
+
+
+
+ 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
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
diff --git a/src/mod/endpoints/mod_sofia/test/sipp-scenarios/uas_register.xml b/src/mod/endpoints/mod_sofia/test/sipp-scenarios/uas_register.xml
new file mode 100644
index 0000000000..ae9681663d
--- /dev/null
+++ b/src/mod/endpoints/mod_sofia/test/sipp-scenarios/uas_register.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+ WWW-Authenticate: Digest realm="freeswitch.org", nonce="47ebe028cda119c35d4877b383027d28da013815"
+ Content-Length: [len]
+
+ ]]>
+
+
+
+
+
+ Content-Length: 0
+ Expires: 60
+
+ ]]>
+
+
+
+
+
+
+
diff --git a/src/mod/endpoints/mod_sofia/test/sipp-scenarios/uas_register_403.xml b/src/mod/endpoints/mod_sofia/test/sipp-scenarios/uas_register_403.xml
new file mode 100644
index 0000000000..9a42f1a7a4
--- /dev/null
+++ b/src/mod/endpoints/mod_sofia/test/sipp-scenarios/uas_register_403.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+ WWW-Authenticate: Digest realm="freeswitch.org", nonce="81dc9bdb52d04dc20036dbd8313ed055"
+ Content-Length: [len]
+
+ ]]>
+
+
+
+
+
+ Content-Length: 0
+
+ ]]>
+
+
+
+
+
+
+
diff --git a/src/mod/endpoints/mod_sofia/test/sipp-scenarios/uas_register_no_challange.xml b/src/mod/endpoints/mod_sofia/test/sipp-scenarios/uas_register_no_challange.xml
new file mode 100644
index 0000000000..175149a026
--- /dev/null
+++ b/src/mod/endpoints/mod_sofia/test/sipp-scenarios/uas_register_no_challange.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+ ]]>
+
+
+
+
+
+
+
+ ]]>
+
+
+
+
+
+
+
+ ]]>
+
+
+
+
+
+
+
+
+