mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-04-13 07:45:26 +00:00
add enhanced zrtp passthrough (zrtp passthru) mode
ZRTP passthrough mode allows two ZRTP-capable clients to negotiate an end-to-end security association through FreeSWITCH. The clients are therefore able to be certain that the FreeSWITCH instance mediating the call cannot eavesdrop on their conversation. Importantly, this capability is maintained across multiple FreeSWITCH hops. If widely deployed, this enables a global network architecture where two people can speak securely with strong cryptographically protected authentication and confidentiality. With this commit we implement a zrtp-passthru mode that handles all the details of the negotiation intelligently. This mode can be selected by setting the boolean parameter inbound-zrtp-passthru in the sofia profile. This will also force late-negotiation as it is essential for correctly negotiating an end-to-end ZRTP security association. When an incoming call with a zrtp-hash is received and this mode is enabled, we find the first audio and the first video zrtp-hash in the SDP and store them as remote values on this channel. Once a b-leg is available, we set the local zrtp-hash values on that channel to the remote zrtp-hash values collected from the a-leg. Because zrtp-passthru absolutely requires that the channels negotiate the same codec, we offer to the b-leg only codecs that the a-leg can speak. Once the b-leg accepts a codec, we will force that choice onto the a-leg. If the b-leg sends us zrtp-hash values in the signaling, we store those as remote values on the b-leg and copy them to the local values on the a-leg. At this point, each leg has the zrtp-hash values from the other, and we know we can do ZRTP passthrough mode on the call. We send the b-leg's zrtp-hash back to the a-leg in the 200 OK. We then enable UDPTL mode on the rtp streams for both the audio and the video so that we don't interfere in the ZRTP negotiation. If the b-leg fails to return a zrtp-hash in the signaling, we set up a ZRTP security association with the a-leg ourselves, if we are so equipped. Likewise, if the a-leg fails to send a zrtp-hash in the signaling, we attempt to set up a ZRTP security association ourselves with the b-leg. The zrtp-passthru mode can also be enabled in the dialplan by setting the boolean channel variable zrtp_passthru. If enabled in this manner, we can't force late-negotiation, so the user would need to be sure this is configured. If ZRTP passthrough mode is not enabled in either manner, this change should have no effect. Channel variables for each of the various zrtp-hash values are set, though it is anticipated that there is no good reason to use them, so they may be removed without warning. For checking whether zrtp passthrough mode was successful, we provide the channel variable zrtp_passthru_active which is set on both legs. Though not implemented by this commit, the changes here should make it more straightforward to add correct zrtp-hash values to the signaling and verify that correct hello hash values are received when FreeSWITCH is acting as a terminating leg of the ZRTP security association. A historical note... This commit replaces the recently-added sdp_zrtp_hash_string method, commit 2ab1605a8887adc62be1b75f6ef67af87ff080de. This prior method sets a channel variable from the a-leg's zrtp-hash, then relies on the dialplan to export this channel variable to the b-leg, where it is put into the SDP. While it was a great start and wonderful for testing, this approach has some drawbacks that motivated the present work: * There's no good way to pass the zrtp-hash from the b-leg back to the a-leg. In fact, the implementation seems to send the a-leg's zrtp-hash back to the originating client in the 200 OK. This is not correct. * To support video, we'd need to have a separate dialplan variable, and the dialplan author would need to deal with that explicitly. * The API is problematic as it requires the dialplan author to understand intricate details of how ZRTP works to implement a correct dialplan. Further, by providing too fine-grained control (but at the same time, not enough control) it would limit our ability to make the behavior smarter once people started relying on this.
This commit is contained in:
parent
8c889aa3a7
commit
23f8967c32
@ -170,6 +170,7 @@ SWITCH_BEGIN_EXTERN_C
|
||||
#define SWITCH_CACHE_SPEECH_HANDLES_OBJ_NAME "__cache_speech_handles_obj__"
|
||||
#define SWITCH_BYPASS_MEDIA_VARIABLE "bypass_media"
|
||||
#define SWITCH_PROXY_MEDIA_VARIABLE "proxy_media"
|
||||
#define SWITCH_ZRTP_PASSTHRU_VARIABLE "zrtp_passthru"
|
||||
#define SWITCH_ENDPOINT_DISPOSITION_VARIABLE "endpoint_disposition"
|
||||
#define SWITCH_HOLD_MUSIC_VARIABLE "hold_music"
|
||||
#define SWITCH_TEMP_HOLD_MUSIC_VARIABLE "temp_hold_music"
|
||||
@ -1213,8 +1214,9 @@ typedef enum {
|
||||
CF_VIDEO_REFRESH_REQ,
|
||||
CF_SERVICE_AUDIO,
|
||||
CF_SERVICE_VIDEO,
|
||||
CF_ZRTP_PASSTHRU_REQ,
|
||||
CF_ZRTP_PASSTHRU,
|
||||
CF_ZRTP_HASH,
|
||||
CF_ZRTP_PASS,
|
||||
CF_CHANNEL_SWAP,
|
||||
CF_PICKUP,
|
||||
CF_CONFIRM_BLIND_TRANSFER,
|
||||
|
@ -2997,6 +2997,7 @@ static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t
|
||||
stream->write_function(stream, "NOMEDIA \t%s\n", sofia_test_flag(profile, TFLAG_INB_NOMEDIA) ? "true" : "false");
|
||||
stream->write_function(stream, "LATE-NEG \t%s\n", sofia_test_flag(profile, TFLAG_LATE_NEGOTIATION) ? "true" : "false");
|
||||
stream->write_function(stream, "PROXY-MEDIA \t%s\n", sofia_test_flag(profile, TFLAG_PROXY_MEDIA) ? "true" : "false");
|
||||
stream->write_function(stream, "ZRTP-PASSTHRU \t%s\n", sofia_test_flag(profile, TFLAG_ZRTP_PASSTHRU) ? "true" : "false");
|
||||
stream->write_function(stream, "AGGRESSIVENAT \t%s\n",
|
||||
sofia_test_pflag(profile, PFLAG_AGGRESSIVE_NAT_DETECTION) ? "true" : "false");
|
||||
stream->write_function(stream, "STUN-ENABLED \t%s\n", sofia_test_pflag(profile, PFLAG_STUN_ENABLED) ? "true" : "false");
|
||||
@ -3275,6 +3276,7 @@ static switch_status_t cmd_xml_status(char **argv, int argc, switch_stream_handl
|
||||
stream->write_function(stream, " <nomedia>%s</nomedia>\n", sofia_test_flag(profile, TFLAG_INB_NOMEDIA) ? "true" : "false");
|
||||
stream->write_function(stream, " <late-neg>%s</late-neg>\n", sofia_test_flag(profile, TFLAG_LATE_NEGOTIATION) ? "true" : "false");
|
||||
stream->write_function(stream, " <proxy-media>%s</proxy-media>\n", sofia_test_flag(profile, TFLAG_PROXY_MEDIA) ? "true" : "false");
|
||||
stream->write_function(stream, " <zrtp-passthru>%s</zrtp-passthru>\n", sofia_test_flag(profile, TFLAG_ZRTP_PASSTHRU) ? "true" : "false");
|
||||
stream->write_function(stream, " <aggressive-nat>%s</aggressive-nat>\n",
|
||||
sofia_test_pflag(profile, PFLAG_AGGRESSIVE_NAT_DETECTION) ? "true" : "false");
|
||||
stream->write_function(stream, " <stun-enabled>%s</stun-enabled>\n",
|
||||
@ -4785,6 +4787,17 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
|
||||
sofia_clear_flag(ctech_pvt, TFLAG_ENABLE_SOA);
|
||||
}
|
||||
|
||||
if (switch_channel_test_flag(o_channel, CF_ZRTP_PASSTHRU_REQ)) {
|
||||
const char *x = NULL;
|
||||
sofia_glue_pass_zrtp_hash2(session, nsession);
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "[zrtp_passthru] Setting a-leg inherit_codec=true\n");
|
||||
switch_channel_set_variable(o_channel, "inherit_codec", "true");
|
||||
if ((x = switch_channel_get_variable(o_channel, "ep_codec_string"))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "[zrtp_passthru] Setting b-leg absolute_codec_string='%s'\n", x);
|
||||
switch_channel_set_variable(nchannel, "absolute_codec_string", x);
|
||||
}
|
||||
}
|
||||
|
||||
/* SNARK: lets copy this across so we can see if we're the other leg of 3PCC + bypass_media... */
|
||||
if (sofia_test_flag(ctech_pvt, TFLAG_3PCC) && (switch_channel_test_flag(o_channel, CF_PROXY_MODE) || switch_channel_test_flag(o_channel, CF_PROXY_MEDIA))) {
|
||||
sofia_set_flag(tech_pvt, TFLAG_3PCC_INVITE);
|
||||
|
@ -317,6 +317,7 @@ typedef enum {
|
||||
TFLAG_TPORT_LOG,
|
||||
TFLAG_SENT_UPDATE,
|
||||
TFLAG_PROXY_MEDIA,
|
||||
TFLAG_ZRTP_PASSTHRU,
|
||||
TFLAG_HOLD_LOCK,
|
||||
TFLAG_3PCC_HAS_ACK,
|
||||
TFLAG_PASS_RFC2833,
|
||||
@ -825,6 +826,11 @@ struct private_object {
|
||||
switch_payload_t ianacodes[SWITCH_MAX_CODECS];
|
||||
uint32_t session_timeout;
|
||||
enum nua_session_refresher session_refresher;
|
||||
/** ZRTP **/
|
||||
char *local_sdp_audio_zrtp_hash;
|
||||
char *local_sdp_video_zrtp_hash;
|
||||
char *remote_sdp_audio_zrtp_hash;
|
||||
char *remote_sdp_video_zrtp_hash;
|
||||
};
|
||||
|
||||
struct callback_t {
|
||||
@ -932,6 +938,8 @@ void launch_sofia_profile_thread(sofia_profile_t *profile);
|
||||
switch_status_t sofia_presence_chat_send(switch_event_t *message_event);
|
||||
|
||||
void sofia_glue_tech_absorb_sdp(private_object_t *tech_pvt);
|
||||
void sofia_glue_pass_zrtp_hash2(switch_core_session_t *aleg_session, switch_core_session_t *bleg_session);
|
||||
void sofia_glue_pass_zrtp_hash(switch_core_session_t *session);
|
||||
|
||||
/*
|
||||
* \brief Sets the "ep_codec_string" channel variable, parsing r_sdp and taing codec_string in consideration
|
||||
|
@ -3321,6 +3321,12 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile)
|
||||
} else {
|
||||
sofia_clear_flag(profile, TFLAG_PROXY_MEDIA);
|
||||
}
|
||||
} else if (!strcasecmp(var, "inbound-zrtp-passthru")) {
|
||||
if (switch_true(val)) {
|
||||
sofia_set_flag(profile, TFLAG_ZRTP_PASSTHRU);
|
||||
} else {
|
||||
sofia_clear_flag(profile, TFLAG_ZRTP_PASSTHRU);
|
||||
}
|
||||
} else if (!strcasecmp(var, "inbound-use-callid-as-uuid")) {
|
||||
if (switch_true(val)) {
|
||||
sofia_set_pflag(profile, PFLAG_CALLID_AS_UUID);
|
||||
@ -3695,6 +3701,10 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile)
|
||||
}
|
||||
}
|
||||
|
||||
if (sofia_test_flag(profile, TFLAG_ZRTP_PASSTHRU)) {
|
||||
sofia_set_flag(profile, TFLAG_LATE_NEGOTIATION);
|
||||
}
|
||||
|
||||
if ((gateways_tag = switch_xml_child(xprofile, "gateways"))) {
|
||||
parse_gateways(profile, gateways_tag);
|
||||
}
|
||||
@ -4171,6 +4181,8 @@ switch_status_t config_sofia(int reload, char *profile_name)
|
||||
}
|
||||
} else if (!strcasecmp(var, "inbound-proxy-media") && switch_true(val)) {
|
||||
sofia_set_flag(profile, TFLAG_PROXY_MEDIA);
|
||||
} else if (!strcasecmp(var, "inbound-zrtp-passthru") && switch_true(val)) {
|
||||
sofia_set_flag(profile, TFLAG_ZRTP_PASSTHRU);
|
||||
} else if (!strcasecmp(var, "force-subscription-expires")) {
|
||||
int tmp = atoi(val);
|
||||
if (tmp > 0) {
|
||||
@ -4801,6 +4813,10 @@ switch_status_t config_sofia(int reload, char *profile_name)
|
||||
}
|
||||
}
|
||||
|
||||
if (sofia_test_flag(profile, TFLAG_ZRTP_PASSTHRU)) {
|
||||
sofia_set_flag(profile, TFLAG_LATE_NEGOTIATION);
|
||||
}
|
||||
|
||||
if ((!profile->cng_pt) && (!sofia_test_pflag(profile, PFLAG_SUPPRESS_CNG))) {
|
||||
profile->cng_pt = SWITCH_RTP_CNG_PAYLOAD;
|
||||
}
|
||||
@ -8264,6 +8280,10 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
|
||||
switch_channel_set_flag(channel, CF_PROXY_MEDIA);
|
||||
}
|
||||
|
||||
if (sofia_test_flag(tech_pvt, TFLAG_ZRTP_PASSTHRU)) {
|
||||
switch_channel_set_flag(channel, CF_ZRTP_PASSTHRU_REQ);
|
||||
}
|
||||
|
||||
if (!tech_pvt->call_id && sip->sip_call_id && sip->sip_call_id->i_id) {
|
||||
tech_pvt->call_id = switch_core_session_strdup(session, sip->sip_call_id->i_id);
|
||||
switch_channel_set_variable(channel, "sip_call_id", tech_pvt->call_id);
|
||||
|
@ -184,7 +184,6 @@ static void generate_m(private_object_t *tech_pvt, char *buf, size_t buflen,
|
||||
int rate;
|
||||
int already_did[128] = { 0 };
|
||||
int ptime = 0, noptime = 0;
|
||||
const char *zrtp;
|
||||
|
||||
switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "m=audio %d RTP/%sAVP",
|
||||
port, secure ? "S" : "");
|
||||
@ -344,8 +343,11 @@ static void generate_m(private_object_t *tech_pvt, char *buf, size_t buflen,
|
||||
switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ptime:%d\n", cur_ptime);
|
||||
}
|
||||
|
||||
if ((zrtp = switch_channel_get_variable(tech_pvt->channel, "sdp_zrtp_hash_string"))) {
|
||||
switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=zrtp-hash:%s\n", zrtp);
|
||||
if (tech_pvt->local_sdp_audio_zrtp_hash) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Adding audio a=zrtp-hash:%s\n",
|
||||
tech_pvt->local_sdp_audio_zrtp_hash);
|
||||
switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=zrtp-hash:%s\n",
|
||||
tech_pvt->local_sdp_audio_zrtp_hash);
|
||||
}
|
||||
|
||||
if (sr) {
|
||||
@ -391,7 +393,6 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch
|
||||
switch_event_t *map = NULL, *ptmap = NULL;
|
||||
const char *b_sdp = NULL;
|
||||
int verbose_sdp = 0;
|
||||
const char *zrtp;
|
||||
|
||||
sofia_glue_check_dtmf_type(tech_pvt);
|
||||
|
||||
@ -545,8 +546,12 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch
|
||||
switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=ptime:%d\n", ptime);
|
||||
}
|
||||
|
||||
if ((zrtp = switch_channel_get_variable(tech_pvt->channel, "sdp_zrtp_hash_string"))) {
|
||||
switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=zrtp-hash:%s\n", zrtp);
|
||||
|
||||
if (tech_pvt->local_sdp_audio_zrtp_hash) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Adding audio a=zrtp-hash:%s\n",
|
||||
tech_pvt->local_sdp_audio_zrtp_hash);
|
||||
switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=zrtp-hash:%s\n",
|
||||
tech_pvt->local_sdp_audio_zrtp_hash);
|
||||
}
|
||||
|
||||
if (sr) {
|
||||
@ -747,6 +752,13 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (tech_pvt->local_sdp_video_zrtp_hash) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Adding video a=zrtp-hash:%s\n",
|
||||
tech_pvt->local_sdp_video_zrtp_hash);
|
||||
switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=zrtp-hash:%s\n",
|
||||
tech_pvt->local_sdp_video_zrtp_hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3563,9 +3575,11 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
|
||||
switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp);
|
||||
|
||||
|
||||
if (switch_channel_test_flag(tech_pvt->channel, CF_ZRTP_PASS)) {
|
||||
if (switch_channel_test_flag(tech_pvt->channel, CF_ZRTP_PASSTHRU)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_INFO, "Activating ZRTP PROXY MODE\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Disable NOTIMER_DURING_BRIDGE\n");
|
||||
sofia_clear_flag(tech_pvt, TFLAG_NOTIMER_DURING_BRIDGE);
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Activating audio UDPTL mode\n");
|
||||
switch_rtp_udptl_mode(tech_pvt->rtp_session);
|
||||
}
|
||||
|
||||
@ -3752,7 +3766,10 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (switch_channel_test_flag(tech_pvt->channel, CF_ZRTP_PASSTHRU)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Activating video UDPTL mode\n");
|
||||
switch_rtp_udptl_mode(tech_pvt->video_rtp_session);
|
||||
}
|
||||
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "VIDEO RTP REPORTS ERROR: [%s]\n", switch_str_nil(err));
|
||||
@ -3837,7 +3854,93 @@ static void add_audio_codec(sdp_rtpmap_t *map, int ptime, char *buf, switch_size
|
||||
|
||||
}
|
||||
|
||||
void sofia_glue_pass_zrtp_hash2(switch_core_session_t *aleg_session, switch_core_session_t *bleg_session)
|
||||
{
|
||||
switch_channel_t *aleg_channel = switch_core_session_get_channel(aleg_session);
|
||||
private_object_t *aleg_tech_pvt = switch_core_session_get_private(aleg_session);
|
||||
switch_channel_t *bleg_channel = switch_core_session_get_channel(bleg_session);
|
||||
private_object_t *bleg_tech_pvt = switch_core_session_get_private(bleg_session);
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(aleg_channel), SWITCH_LOG_DEBUG, "Deciding whether to pass zrtp-hash between a-leg and b-leg\n");
|
||||
if (!(switch_channel_test_flag(aleg_tech_pvt->channel, CF_ZRTP_PASSTHRU_REQ))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(aleg_channel), SWITCH_LOG_DEBUG, "CF_ZRTP_PASSTHRU_REQ not set on a-leg, so not propagating zrtp-hash\n");
|
||||
return;
|
||||
}
|
||||
if (aleg_tech_pvt->remote_sdp_audio_zrtp_hash) {
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(aleg_channel), SWITCH_LOG_DEBUG, "Passing a-leg remote zrtp-hash (audio) to b-leg\n");
|
||||
bleg_tech_pvt->local_sdp_audio_zrtp_hash = switch_core_session_strdup(bleg_tech_pvt->session, aleg_tech_pvt->remote_sdp_audio_zrtp_hash);
|
||||
switch_channel_set_variable(bleg_channel, "l_sdp_audio_zrtp_hash", bleg_tech_pvt->local_sdp_audio_zrtp_hash);
|
||||
}
|
||||
if (aleg_tech_pvt->remote_sdp_video_zrtp_hash) {
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(aleg_channel), SWITCH_LOG_DEBUG, "Passing a-leg remote zrtp-hash (video) to b-leg\n");
|
||||
bleg_tech_pvt->local_sdp_video_zrtp_hash = switch_core_session_strdup(bleg_tech_pvt->session, aleg_tech_pvt->remote_sdp_video_zrtp_hash);
|
||||
switch_channel_set_variable(bleg_channel, "l_sdp_video_zrtp_hash", bleg_tech_pvt->local_sdp_video_zrtp_hash);
|
||||
}
|
||||
if (bleg_tech_pvt->remote_sdp_audio_zrtp_hash) {
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(aleg_channel), SWITCH_LOG_DEBUG, "Passing b-leg remote zrtp-hash (audio) to a-leg\n");
|
||||
aleg_tech_pvt->local_sdp_audio_zrtp_hash = switch_core_session_strdup(aleg_tech_pvt->session, bleg_tech_pvt->remote_sdp_audio_zrtp_hash);
|
||||
switch_channel_set_variable(aleg_channel, "l_sdp_audio_zrtp_hash", aleg_tech_pvt->local_sdp_audio_zrtp_hash);
|
||||
}
|
||||
if (bleg_tech_pvt->remote_sdp_video_zrtp_hash) {
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(aleg_channel), SWITCH_LOG_DEBUG, "Passing b-leg remote zrtp-hash (video) to a-leg\n");
|
||||
aleg_tech_pvt->local_sdp_video_zrtp_hash = switch_core_session_strdup(aleg_tech_pvt->session, bleg_tech_pvt->remote_sdp_video_zrtp_hash);
|
||||
switch_channel_set_variable(aleg_channel, "l_sdp_video_zrtp_hash", aleg_tech_pvt->local_sdp_video_zrtp_hash);
|
||||
}
|
||||
}
|
||||
|
||||
void sofia_glue_pass_zrtp_hash(switch_core_session_t *session)
|
||||
{
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
private_object_t *tech_pvt = switch_core_session_get_private(session);
|
||||
switch_core_session_t *other_session;
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Deciding whether to pass zrtp-hash between legs\n");
|
||||
if (!(switch_channel_test_flag(tech_pvt->channel, CF_ZRTP_PASSTHRU_REQ))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "CF_ZRTP_PASSTHRU_REQ not set, so not propagating zrtp-hash\n");
|
||||
return;
|
||||
} else if (!(switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "No partner channel found, so not propagating zrtp-hash\n");
|
||||
return;
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Found peer channel; propagating zrtp-hash if set\n");
|
||||
sofia_glue_pass_zrtp_hash2(session, other_session);
|
||||
switch_core_session_rwunlock(other_session);
|
||||
}
|
||||
}
|
||||
|
||||
static void find_zrtp_hash(switch_core_session_t *session, sdp_session_t *sdp)
|
||||
{
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
private_object_t *tech_pvt = switch_core_session_get_private(session);
|
||||
sdp_media_t *m;
|
||||
sdp_attribute_t *attr;
|
||||
int got_audio = 0, got_video = 0;
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Looking for zrtp-hash\n");
|
||||
for (m = sdp->sdp_media; m; m = m->m_next) {
|
||||
if (got_audio && got_video) break;
|
||||
if (m->m_port && ((m->m_type == sdp_media_audio && !got_audio)
|
||||
|| (m->m_type == sdp_media_video && !got_video))) {
|
||||
for (attr = m->m_attributes; attr; attr = attr->a_next) {
|
||||
if (zstr(attr->a_name)) continue;
|
||||
if (strcasecmp(attr->a_name, "zrtp-hash") || !(attr->a_value)) continue;
|
||||
if (m->m_type == sdp_media_audio) {
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG,
|
||||
"Found audio zrtp-hash; setting r_sdp_audio_zrtp_hash=%s\n", attr->a_value);
|
||||
switch_channel_set_variable(channel, "r_sdp_audio_zrtp_hash", attr->a_value);
|
||||
tech_pvt->remote_sdp_audio_zrtp_hash = switch_core_session_strdup(tech_pvt->session, attr->a_value);
|
||||
got_audio++;
|
||||
} else if (m->m_type == sdp_media_video) {
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG,
|
||||
"Found video zrtp-hash; setting r_sdp_video_zrtp_hash=%s\n", attr->a_value);
|
||||
switch_channel_set_variable(channel, "r_sdp_video_zrtp_hash", attr->a_value);
|
||||
tech_pvt->remote_sdp_video_zrtp_hash = switch_core_session_strdup(tech_pvt->session, attr->a_value);
|
||||
got_video++;
|
||||
}
|
||||
switch_channel_set_flag(channel, CF_ZRTP_HASH);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sofia_glue_set_r_sdp_codec_string(switch_core_session_t *session, const char *codec_string, sdp_session_t *sdp)
|
||||
{
|
||||
@ -3887,18 +3990,8 @@ void sofia_glue_set_r_sdp_codec_string(switch_core_session_t *session, const cha
|
||||
}
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Looking for zrtp-hash to set sdp_zrtp_hash_string\n");
|
||||
for (m = sdp->sdp_media; m; m = m->m_next) {
|
||||
for (attr = m->m_attributes; attr; attr = attr->a_next) {
|
||||
if (zstr(attr->a_name)) continue;
|
||||
if (!strcasecmp(attr->a_name, "zrtp-hash") && attr->a_value) {
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Found zrtp-hash, setting sdp_zrtp_hash_string=%s\n", attr->a_value);
|
||||
switch_channel_set_variable(channel, "sdp_zrtp_hash_string", attr->a_value);
|
||||
switch_channel_set_flag(channel, CF_ZRTP_HASH);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
find_zrtp_hash(session, sdp);
|
||||
sofia_glue_pass_zrtp_hash(session);
|
||||
|
||||
for (m = sdp->sdp_media; m; m = m->m_next) {
|
||||
ptime = dptime;
|
||||
@ -4578,6 +4671,9 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
|
||||
switch_channel_set_variable(tech_pvt->channel, "t38_broken_boolean", "true");
|
||||
}
|
||||
|
||||
find_zrtp_hash(session, sdp);
|
||||
sofia_glue_pass_zrtp_hash(session);
|
||||
|
||||
for (m = sdp->sdp_media; m; m = m->m_next) {
|
||||
sdp_connection_t *connection;
|
||||
switch_core_session_t *other_session;
|
||||
@ -4699,9 +4795,6 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
|
||||
ptime = atoi(attr->a_value);
|
||||
} else if (!strcasecmp(attr->a_name, "maxptime") && attr->a_value) {
|
||||
maxptime = atoi(attr->a_value);
|
||||
} else if (!strcasecmp(attr->a_name, "zrtp-hash") && attr->a_value) {
|
||||
switch_channel_set_variable(tech_pvt->channel, "sdp_zrtp_hash_string", attr->a_value);
|
||||
switch_channel_set_flag(tech_pvt->channel, CF_ZRTP_HASH);
|
||||
} else if (!got_crypto && !strcasecmp(attr->a_name, "crypto") && !zstr(attr->a_value)) {
|
||||
int crypto_tag;
|
||||
|
||||
|
@ -2955,7 +2955,9 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_ring_ready_value(swi
|
||||
SWITCH_DECLARE(void) switch_channel_check_zrtp(switch_channel_t *channel)
|
||||
{
|
||||
|
||||
if (switch_channel_test_flag(channel, CF_ZRTP_HASH) && !switch_channel_test_flag(channel, CF_ZRTP_PASS)) {
|
||||
if (!switch_channel_test_flag(channel, CF_ZRTP_PASSTHRU)
|
||||
&& switch_channel_test_flag(channel, CF_ZRTP_PASSTHRU_REQ)
|
||||
&& switch_channel_test_flag(channel, CF_ZRTP_HASH)) {
|
||||
switch_core_session_t *other_session;
|
||||
switch_channel_t *other_channel;
|
||||
int doit = 1;
|
||||
@ -2963,14 +2965,16 @@ SWITCH_DECLARE(void) switch_channel_check_zrtp(switch_channel_t *channel)
|
||||
if (switch_core_session_get_partner(channel->session, &other_session) == SWITCH_STATUS_SUCCESS) {
|
||||
other_channel = switch_core_session_get_channel(other_session);
|
||||
|
||||
if (switch_channel_test_flag(other_channel, CF_ZRTP_HASH) && !switch_channel_test_flag(other_channel, CF_ZRTP_PASS)) {
|
||||
if (switch_channel_test_flag(other_channel, CF_ZRTP_HASH) && !switch_channel_test_flag(other_channel, CF_ZRTP_PASSTHRU)) {
|
||||
|
||||
switch_channel_set_flag(channel, CF_ZRTP_PASS);
|
||||
switch_channel_set_flag(other_channel, CF_ZRTP_PASS);
|
||||
switch_channel_set_flag(channel, CF_ZRTP_PASSTHRU);
|
||||
switch_channel_set_flag(other_channel, CF_ZRTP_PASSTHRU);
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(channel->session), SWITCH_LOG_INFO,
|
||||
"%s Activating ZRTP passthru mode.\n", switch_channel_get_name(channel));
|
||||
|
||||
switch_channel_set_variable(channel, "zrtp_passthru_active", "true");
|
||||
switch_channel_set_variable(other_channel, "zrtp_passthru_active", "true");
|
||||
switch_channel_set_variable(channel, "zrtp_secure_media", "false");
|
||||
switch_channel_set_variable(other_channel, "zrtp_secure_media", "false");
|
||||
doit = 0;
|
||||
@ -2980,18 +2984,20 @@ SWITCH_DECLARE(void) switch_channel_check_zrtp(switch_channel_t *channel)
|
||||
}
|
||||
|
||||
if (doit) {
|
||||
switch_channel_set_variable(channel, "zrtp_passthru_active", "false");
|
||||
switch_channel_set_variable(channel, "zrtp_secure_media", "true");
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(channel->session), SWITCH_LOG_INFO,
|
||||
"%s ZRTP not negotiated on both sides; disabling ZRTP passthru mode.\n", switch_channel_get_name(channel));
|
||||
|
||||
switch_channel_clear_flag(channel, CF_ZRTP_PASS);
|
||||
switch_channel_clear_flag(channel, CF_ZRTP_PASSTHRU);
|
||||
switch_channel_clear_flag(channel, CF_ZRTP_HASH);
|
||||
|
||||
if (switch_core_session_get_partner(channel->session, &other_session) == SWITCH_STATUS_SUCCESS) {
|
||||
other_channel = switch_core_session_get_channel(other_session);
|
||||
|
||||
switch_channel_set_variable(other_channel, "zrtp_passthru_active", "false");
|
||||
switch_channel_set_variable(other_channel, "zrtp_secure_media", "true");
|
||||
switch_channel_clear_flag(other_channel, CF_ZRTP_PASS);
|
||||
switch_channel_clear_flag(other_channel, CF_ZRTP_PASSTHRU);
|
||||
switch_channel_clear_flag(other_channel, CF_ZRTP_HASH);
|
||||
|
||||
switch_core_session_rwunlock(other_session);
|
||||
|
@ -577,6 +577,10 @@ SWITCH_DECLARE(switch_call_cause_t) switch_core_session_outgoing_channel(switch_
|
||||
}
|
||||
}
|
||||
|
||||
if (switch_channel_test_flag(channel, CF_ZRTP_PASSTHRU_REQ)) {
|
||||
switch_channel_set_flag(peer_channel, CF_ZRTP_PASSTHRU_REQ);
|
||||
}
|
||||
|
||||
if (profile) {
|
||||
if ((cloned_profile = switch_caller_profile_clone(*new_session, profile)) != 0) {
|
||||
switch_channel_set_originator_caller_profile(peer_channel, cloned_profile);
|
||||
|
@ -1820,7 +1820,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
|
||||
}
|
||||
|
||||
if (session) {
|
||||
const char *to_var, *bypass_media = NULL, *proxy_media = NULL;
|
||||
const char *to_var, *bypass_media = NULL, *proxy_media = NULL, *zrtp_passthru = NULL;
|
||||
caller_channel = switch_core_session_get_channel(session);
|
||||
switch_channel_set_flag(caller_channel, CF_ORIGINATOR);
|
||||
oglobals.session = session;
|
||||
@ -1833,6 +1833,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
|
||||
|
||||
proxy_media = switch_channel_get_variable(caller_channel, SWITCH_PROXY_MEDIA_VARIABLE);
|
||||
bypass_media = switch_channel_get_variable(caller_channel, SWITCH_BYPASS_MEDIA_VARIABLE);
|
||||
zrtp_passthru = switch_channel_get_variable(caller_channel, SWITCH_ZRTP_PASSTHRU_VARIABLE);
|
||||
|
||||
if (!zstr(proxy_media)) {
|
||||
if (switch_true(proxy_media)) {
|
||||
@ -1842,6 +1843,14 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
|
||||
}
|
||||
}
|
||||
|
||||
if (!zstr(zrtp_passthru)) {
|
||||
if (switch_true(zrtp_passthru)) {
|
||||
switch_channel_set_flag(caller_channel, CF_ZRTP_PASSTHRU_REQ);
|
||||
} else if (switch_channel_test_flag(caller_channel, CF_ZRTP_PASSTHRU_REQ)) {
|
||||
switch_channel_clear_flag(caller_channel, CF_ZRTP_PASSTHRU_REQ);
|
||||
}
|
||||
}
|
||||
|
||||
if (bypass_media && switch_channel_test_flag(caller_channel, CF_EARLY_MEDIA) && !switch_channel_test_flag(caller_channel, CF_ANSWERED)) {
|
||||
switch_core_session_message_t msg = { 0 };
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user