typedef enum {
SM_NDLB_ALLOW_BAD_IANANAME = (1 << 0),
SM_NDLB_ALLOW_NONDUP_SDP = (1 << 1),
- SM_NDLB_ALLOW_CRYPTO_IN_AVP = (1 << 2)
+ SM_NDLB_ALLOW_CRYPTO_IN_AVP = (1 << 2),
+ SM_NDLB_DISABLE_SRTP_AUTH = (1 << 3)
} switch_core_media_NDLB_t;
struct switch_media_handle_s;
SWITCH_DECLARE(void) switch_media_handle_set_ndlb(switch_media_handle_t *smh, switch_core_media_NDLB_t flag);
SWITCH_DECLARE(void) switch_media_handle_clear_ndlb(switch_media_handle_t *smh, switch_core_media_NDLB_t flag);
SWITCH_DECLARE(int32_t) switch_media_handle_test_ndlb(switch_media_handle_t *smh, switch_core_media_NDLB_t flag);
+SWITCH_DECLARE(void) switch_core_session_check_outgoing_crypto(switch_core_session_t *session, const char *sec_var);
+SWITCH_DECLARE(const char *) switch_core_sesson_local_crypto_key(switch_core_session_t *session, switch_media_type_t type);
+SWITCH_DECLARE(int) switch_core_session_check_incoming_crypto(switch_core_session_t *session,
+ const char *varname,
+ switch_media_type_t type, const char *crypto, int crypto_tag);
+
+SWITCH_DECLARE(void) switch_core_session_apply_crypto(switch_core_session_t *session, switch_media_type_t type, const char *varname);
+SWITCH_DECLARE(void) switch_core_session_get_recovery_crypto_key(switch_core_session_t *session, switch_media_type_t type, const char *varname);
+
+SWITCH_DECLARE(void) switch_core_media_set_rtp_session(switch_core_session_t *session, switch_media_type_t type, switch_rtp_t *rtp_session);
SWITCH_END_EXTERN_C
#endif
CF_EARLY_OK,
CF_MEDIA_TRANS,
CF_HOLD_ON_BRIDGE,
+ CF_SECURE,
+ CF_CRYPTO_RECOVER,
/* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */
/* IF YOU ADD NEW ONES CHECK IF THEY SHOULD PERSIST OR ZERO THEM IN switch_core_session.c switch_core_session_request_xml() */
CF_FLAG_MAX
SWITCH_MEDIA_TYPE_AUDIO,
SWITCH_MEDIA_TYPE_VIDEO
} switch_media_type_t;
+#define SWITCH_MEDIA_TYPE_TOTAL 2
/*!
}
if (sofia_test_flag(tech_pvt, TFLAG_OUTBOUND) || switch_channel_test_flag(tech_pvt->channel, CF_RECOVERING)) {
- const char *var;
- if ((var = switch_channel_get_variable(channel, SOFIA_SECURE_MEDIA_VARIABLE)) && !zstr(var)) {
- if (switch_true(var) || !strcasecmp(var, SWITCH_RTP_CRYPTO_KEY_32)) {
- sofia_set_flag_locked(tech_pvt, TFLAG_SECURE);
- sofia_glue_build_crypto(tech_pvt, 1, AES_CM_128_HMAC_SHA1_32, SWITCH_RTP_CRYPTO_SEND);
- } else if (!strcasecmp(var, SWITCH_RTP_CRYPTO_KEY_80)) {
- sofia_set_flag_locked(tech_pvt, TFLAG_SECURE);
- sofia_glue_build_crypto(tech_pvt, 1, AES_CM_128_HMAC_SHA1_80, SWITCH_RTP_CRYPTO_SEND);
- }
- }
+ switch_core_session_check_outgoing_crypto(session, SOFIA_SECURE_MEDIA_VARIABLE);
if (sofia_glue_do_invite(session) != SWITCH_STATUS_SUCCESS) {
if ((var = switch_channel_get_variable(channel, SOFIA_SECURE_MEDIA_VARIABLE)) &&
(switch_true(var) || !strcasecmp(var, SWITCH_RTP_CRYPTO_KEY_32) || !strcasecmp(var, SWITCH_RTP_CRYPTO_KEY_80))) {
- sofia_set_flag_locked(tech_pvt, TFLAG_SECURE);
+ switch_channel_set_flag(tech_pvt->channel, CF_SECURE);
}
if (sofia_test_pflag(tech_pvt->profile, PFLAG_AUTOFIX_TIMING)) {
PFLAG_RECIEVED_IN_NAT_REG_CONTACT,
PFLAG_3PCC,
PFLAG_DISABLE_RTP_AUTOADJ,
- PFLAG_DISABLE_SRTP_AUTH,
PFLAG_FUNNY_STUN,
PFLAG_STUN_ENABLED,
PFLAG_STUN_AUTO_DISABLE,
TFLAG_BYE,
TFLAG_ANS,
TFLAG_EARLY_MEDIA,
- TFLAG_SECURE,
TFLAG_VAD_IN,
TFLAG_VAD_OUT,
TFLAG_VAD,
TFLAG_SLA_BARGE,
TFLAG_SLA_BARGING,
TFLAG_PASS_ACK,
- TFLAG_CRYPTO_RECOVER,
TFLAG_DROP_DTMF,
/* No new flags below this line */
TFLAG_MAX
char *rm_fmtp;
char *fmtp_out;
char *remote_sdp_str;
- int crypto_tag;
- unsigned char local_raw_key[SWITCH_RTP_MAX_CRYPTO_LEN];
- unsigned char remote_raw_key[SWITCH_RTP_MAX_CRYPTO_LEN];
- switch_rtp_crypto_key_type_t crypto_send_type;
- switch_rtp_crypto_key_type_t crypto_recv_type;
- switch_rtp_crypto_key_type_t crypto_type;
char *early_sdp;
char *local_sdp_str;
char *last_sdp_str;
char *invite_contact;
char *local_url;
char *gateway_name;
- char *local_crypto_key;
- char *remote_crypto_key;
char *record_route;
char *extrtpip;
char *stun_ip;
int sofia_glue_check_nat(sofia_profile_t *profile, const char *network_ip);
int sofia_glue_transport_has_tls(const sofia_transport_t tp);
const char *sofia_glue_get_unknown_header(sip_t const *sip, const char *name);
-switch_status_t sofia_glue_build_crypto(private_object_t *tech_pvt, int index, switch_rtp_crypto_key_type_t type, switch_rtp_crypto_direction_t direction);
+switch_status_t sofia_media_build_crypto(private_object_t *tech_pvt, int index, switch_rtp_crypto_key_type_t type, switch_rtp_crypto_direction_t direction);
void sofia_glue_tech_patch_sdp(private_object_t *tech_pvt);
switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt, const char *sdp_str);
void sofia_presence_event_thread_start(void);
} else if (!strcasecmp(var, "disable-rtp-auto-adjust") && switch_true(val)) {
sofia_set_pflag(profile, PFLAG_DISABLE_RTP_AUTOADJ);
} else if (!strcasecmp(var, "NDLB-support-asterisk-missing-srtp-auth") && switch_true(val)) {
- sofia_set_pflag(profile, PFLAG_DISABLE_SRTP_AUTH);
+ profile->ndlb |= SM_NDLB_DISABLE_SRTP_AUTH;
} else if (!strcasecmp(var, "NDLB-funny-stun")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_FUNNY_STUN);
if (is_ok) {
- if (tech_pvt->local_crypto_key) {
+
+ if (switch_core_sesson_local_crypto_key(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO)) {
sofia_glue_set_local_sdp(tech_pvt, NULL, 0, NULL, 0);
}
if (sofia_use_soa(tech_pvt)) {
int rate;
int already_did[128] = { 0 };
int ptime = 0, noptime = 0;
+ const char *local_audio_crypto_key = switch_core_sesson_local_crypto_key(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "m=audio %d RTP/%sAVP",
port, secure ? "S" : "");
}
if (secure) {
- switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=crypto:%s\n", tech_pvt->local_crypto_key);
+ switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=crypto:%s\n", local_audio_crypto_key);
//switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=encryption:optional\n");
}
switch_event_t *map = NULL, *ptmap = NULL;
const char *b_sdp = NULL;
int verbose_sdp = 0;
-
+ const char *local_audio_crypto_key = switch_core_sesson_local_crypto_key(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
+
switch_zmalloc(buf, SDPBUFLEN);
sofia_glue_check_dtmf_type(tech_pvt);
if (tech_pvt->rm_encoding) {
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=audio %d RTP/%sAVP",
- port, (!zstr(tech_pvt->local_crypto_key) && sofia_test_flag(tech_pvt, TFLAG_SECURE)) ? "S" : "");
+ port, (!zstr(local_audio_crypto_key) && switch_channel_test_flag(tech_pvt->channel, CF_SECURE)) ? "S" : "");
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", tech_pvt->pt);
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=%s\n", sr);
}
- if (!zstr(tech_pvt->local_crypto_key) && sofia_test_flag(tech_pvt, TFLAG_SECURE)) {
- switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=crypto:%s\n", tech_pvt->local_crypto_key);
+ if (!zstr(local_audio_crypto_key) && switch_channel_test_flag(tech_pvt->channel, CF_SECURE)) {
+ switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=crypto:%s\n", local_audio_crypto_key);
//switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=encryption:optional\n");
}
char *bp = buf;
int both = 1;
- if ((!zstr(tech_pvt->local_crypto_key) && sofia_test_flag(tech_pvt, TFLAG_SECURE))) {
+ if ((!zstr(local_audio_crypto_key) && switch_channel_test_flag(tech_pvt->channel, CF_SECURE))) {
generate_m(tech_pvt, buf, SDPBUFLEN, port, 0, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 1);
bp = (buf + strlen(buf));
cur_ptime = this_ptime;
- if ((!zstr(tech_pvt->local_crypto_key) && sofia_test_flag(tech_pvt, TFLAG_SECURE))) {
+ if ((!zstr(local_audio_crypto_key) && switch_channel_test_flag(tech_pvt->channel, CF_SECURE))) {
generate_m(tech_pvt, bp, SDPBUFLEN - strlen(buf), port, cur_ptime, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 1);
bp = (buf + strlen(buf));
}
-switch_status_t sofia_glue_build_crypto(private_object_t *tech_pvt, int index, switch_rtp_crypto_key_type_t type, switch_rtp_crypto_direction_t direction)
-{
- unsigned char b64_key[512] = "";
- const char *type_str;
- unsigned char *key;
- const char *val;
-
- char *p;
-
- if (type == AES_CM_128_HMAC_SHA1_80) {
- type_str = SWITCH_RTP_CRYPTO_KEY_80;
- } else {
- type_str = SWITCH_RTP_CRYPTO_KEY_32;
- }
-
- if (direction == SWITCH_RTP_CRYPTO_SEND) {
- key = tech_pvt->local_raw_key;
- } else {
- key = tech_pvt->remote_raw_key;
-
- }
-
- switch_rtp_get_random(key, SWITCH_RTP_KEY_LEN);
- switch_b64_encode(key, SWITCH_RTP_KEY_LEN, b64_key, sizeof(b64_key));
- p = strrchr((char *) b64_key, '=');
-
- while (p && *p && *p == '=') {
- *p-- = '\0';
- }
-
- tech_pvt->local_crypto_key = switch_core_session_sprintf(tech_pvt->session, "%d %s inline:%s", index, type_str, b64_key);
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Set Local Key [%s]\n", tech_pvt->local_crypto_key);
-
- if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_SRTP_AUTH) &&
- !((val = switch_channel_get_variable(tech_pvt->channel, "NDLB_support_asterisk_missing_srtp_auth")) && switch_true(val))) {
- tech_pvt->crypto_type = type;
- } else {
- tech_pvt->crypto_type = AES_CM_128_NULL_AUTH;
- }
-
- return SWITCH_STATUS_SUCCESS;
-}
-
-
-
static void add_audio_codec(sdp_rtpmap_t *map, int ptime, char *buf, switch_size_t buflen)
{
int codec_ms = ptime;
sofia_glue_attach_private(session, profile, tech_pvt, NULL);
switch_channel_set_name(tech_pvt->channel, switch_channel_get_variable(channel, "channel_name"));
- if ((tmp = switch_channel_get_variable(channel, "srtp_remote_audio_crypto_key"))) {
- tech_pvt->remote_crypto_key = switch_core_session_strdup(session, tmp);
- sofia_set_flag(tech_pvt, TFLAG_CRYPTO_RECOVER);
- }
+
+ switch_core_session_get_recovery_crypto_key(session, SWITCH_MEDIA_TYPE_AUDIO, "srtp_remote_audio_crypto_key");
if ((tmp = switch_channel_get_variable(channel, "sip_local_sdp_str"))) {
tech_pvt->local_sdp_str = switch_core_session_strdup(session, tmp);
}
-switch_status_t sofia_glue_add_crypto(private_object_t *tech_pvt, const char *key_str, switch_rtp_crypto_direction_t direction)
-{
- unsigned char key[SWITCH_RTP_MAX_CRYPTO_LEN];
- switch_rtp_crypto_key_type_t type;
- char *p;
-
-
- if (!switch_rtp_ready(tech_pvt->rtp_session)) {
- goto bad;
- }
-
- p = strchr(key_str, ' ');
-
- if (p && *p && *(p + 1)) {
- p++;
- if (!strncasecmp(p, SWITCH_RTP_CRYPTO_KEY_32, strlen(SWITCH_RTP_CRYPTO_KEY_32))) {
- type = AES_CM_128_HMAC_SHA1_32;
- } else if (!strncasecmp(p, SWITCH_RTP_CRYPTO_KEY_80, strlen(SWITCH_RTP_CRYPTO_KEY_80))) {
- type = AES_CM_128_HMAC_SHA1_80;
- } else {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "Parse Error near [%s]\n", p);
- goto bad;
- }
-
- p = strchr(p, ' ');
- if (p && *p && *(p + 1)) {
- p++;
- if (strncasecmp(p, "inline:", 7)) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "Parse Error near [%s]\n", p);
- goto bad;
- }
-
- p += 7;
- switch_b64_decode(p, (char *) key, sizeof(key));
-
- if (direction == SWITCH_RTP_CRYPTO_SEND) {
- tech_pvt->crypto_send_type = type;
- memcpy(tech_pvt->local_raw_key, key, SWITCH_RTP_KEY_LEN);
- } else {
- tech_pvt->crypto_recv_type = type;
- memcpy(tech_pvt->remote_raw_key, key, SWITCH_RTP_KEY_LEN);
- }
- return SWITCH_STATUS_SUCCESS;
- }
-
- }
-
- bad:
-
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "Error!\n");
- return SWITCH_STATUS_FALSE;
-
-}
-
-
uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_sdp)
{
crypto = attr->a_value;
crypto_tag = atoi(crypto);
- if (tech_pvt->remote_crypto_key && switch_rtp_ready(tech_pvt->rtp_session)) {
- /* Compare all the key. The tag may remain the same even if key changed */
- if (crypto && !strcmp(crypto, tech_pvt->remote_crypto_key)) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Existing key is still valid.\n");
- } else {
- const char *a = switch_stristr("AES", tech_pvt->remote_crypto_key);
- const char *b = switch_stristr("AES", crypto);
-
- /* Change our key every time we can */
-
- if (sofia_test_flag(tech_pvt, TFLAG_CRYPTO_RECOVER)) {
- sofia_clear_flag(tech_pvt, TFLAG_CRYPTO_RECOVER);
- } else if (switch_stristr(SWITCH_RTP_CRYPTO_KEY_32, crypto)) {
- switch_channel_set_variable(tech_pvt->channel, SOFIA_HAS_CRYPTO_VARIABLE, SWITCH_RTP_CRYPTO_KEY_32);
- sofia_glue_build_crypto(tech_pvt, atoi(crypto), AES_CM_128_HMAC_SHA1_32, SWITCH_RTP_CRYPTO_SEND);
- switch_rtp_add_crypto_key(tech_pvt->rtp_session, SWITCH_RTP_CRYPTO_SEND, atoi(crypto), tech_pvt->crypto_type,
- tech_pvt->local_raw_key, SWITCH_RTP_KEY_LEN);
- } else if (switch_stristr(SWITCH_RTP_CRYPTO_KEY_80, crypto)) {
- switch_channel_set_variable(tech_pvt->channel, SOFIA_HAS_CRYPTO_VARIABLE, SWITCH_RTP_CRYPTO_KEY_80);
- sofia_glue_build_crypto(tech_pvt, atoi(crypto), AES_CM_128_HMAC_SHA1_80, SWITCH_RTP_CRYPTO_SEND);
- switch_rtp_add_crypto_key(tech_pvt->rtp_session, SWITCH_RTP_CRYPTO_SEND, atoi(crypto), tech_pvt->crypto_type,
- tech_pvt->local_raw_key, SWITCH_RTP_KEY_LEN);
- } else {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Crypto Setup Failed!.\n");
- }
+ got_crypto = switch_core_session_check_incoming_crypto(tech_pvt->session,
+ SOFIA_HAS_CRYPTO_VARIABLE, SWITCH_MEDIA_TYPE_AUDIO, crypto, crypto_tag);
- if (a && b && !strncasecmp(a, b, 23)) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Change Remote key to [%s]\n", crypto);
- tech_pvt->remote_crypto_key = switch_core_session_strdup(tech_pvt->session, crypto);
- switch_channel_set_variable(tech_pvt->channel, "srtp_remote_audio_crypto_key", crypto);
- tech_pvt->crypto_tag = crypto_tag;
-
- if (switch_rtp_ready(tech_pvt->rtp_session) && sofia_test_flag(tech_pvt, TFLAG_SECURE)) {
- sofia_glue_add_crypto(tech_pvt, tech_pvt->remote_crypto_key, SWITCH_RTP_CRYPTO_RECV);
- switch_rtp_add_crypto_key(tech_pvt->rtp_session, SWITCH_RTP_CRYPTO_RECV, tech_pvt->crypto_tag,
- tech_pvt->crypto_type, tech_pvt->remote_raw_key, SWITCH_RTP_KEY_LEN);
- }
- got_crypto++;
- } else {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Ignoring unacceptable key\n");
- }
- }
- } else if (!switch_rtp_ready(tech_pvt->rtp_session)) {
- tech_pvt->remote_crypto_key = switch_core_session_strdup(tech_pvt->session, crypto);
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set Remote Key [%s]\n", tech_pvt->remote_crypto_key);
- switch_channel_set_variable(tech_pvt->channel, "srtp_remote_audio_crypto_key", crypto);
- tech_pvt->crypto_tag = crypto_tag;
- got_crypto++;
-
- if (zstr(tech_pvt->local_crypto_key)) {
- if (switch_stristr(SWITCH_RTP_CRYPTO_KEY_32, crypto)) {
- switch_channel_set_variable(tech_pvt->channel, SOFIA_HAS_CRYPTO_VARIABLE, SWITCH_RTP_CRYPTO_KEY_32);
- sofia_glue_build_crypto(tech_pvt, atoi(crypto), AES_CM_128_HMAC_SHA1_32, SWITCH_RTP_CRYPTO_SEND);
- } else if (switch_stristr(SWITCH_RTP_CRYPTO_KEY_80, crypto)) {
- switch_channel_set_variable(tech_pvt->channel, SOFIA_HAS_CRYPTO_VARIABLE, SWITCH_RTP_CRYPTO_KEY_80);
- sofia_glue_build_crypto(tech_pvt, atoi(crypto), AES_CM_128_HMAC_SHA1_80, SWITCH_RTP_CRYPTO_SEND);
- } else {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Crypto Setup Failed!.\n");
- }
- }
- }
}
}
}
if ((var = switch_channel_get_variable(tech_pvt->channel, SOFIA_SECURE_MEDIA_VARIABLE)) && switch_true(var)) {
- sofia_set_flag_locked(tech_pvt, TFLAG_SECURE);
+ switch_channel_set_flag(tech_pvt->channel, CF_SECURE);
}
if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE)) {
uint32_t stun_ping = 0;
const char *ssrc;
+ switch_core_media_set_rtp_session(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, tech_pvt->rtp_session);
+
+
if ((ssrc = switch_channel_get_variable(tech_pvt->channel, "rtp_use_ssrc"))) {
uint32_t ssrc_ul = (uint32_t) strtoul(ssrc, NULL, 10);
switch_rtp_set_ssrc(tech_pvt->rtp_session, ssrc_ul);
switch_rtp_set_cng_pt(tech_pvt->rtp_session, tech_pvt->cng_pt);
}
- if (tech_pvt->remote_crypto_key && sofia_test_flag(tech_pvt, TFLAG_SECURE)) {
- sofia_glue_add_crypto(tech_pvt, tech_pvt->remote_crypto_key, SWITCH_RTP_CRYPTO_RECV);
- switch_rtp_add_crypto_key(tech_pvt->rtp_session, SWITCH_RTP_CRYPTO_SEND, 1, tech_pvt->crypto_type, tech_pvt->local_raw_key,
- SWITCH_RTP_KEY_LEN);
- switch_rtp_add_crypto_key(tech_pvt->rtp_session, SWITCH_RTP_CRYPTO_RECV, tech_pvt->crypto_tag, tech_pvt->crypto_type, tech_pvt->remote_raw_key,
- SWITCH_RTP_KEY_LEN);
- switch_channel_set_variable(tech_pvt->channel, SOFIA_SECURE_MEDIA_CONFIRMED_VARIABLE, "true");
- }
-
+ switch_core_session_apply_crypto(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, SOFIA_SECURE_MEDIA_CONFIRMED_VARIABLE);
switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->remote_sdp_audio_port);
switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, tech_pvt->remote_sdp_audio_ip);
if (switch_rtp_ready(tech_pvt->video_rtp_session)) {
switch_rtp_set_default_payload(tech_pvt->video_rtp_session, tech_pvt->video_agreed_pt);
+ switch_core_media_set_rtp_session(tech_pvt->session, SWITCH_MEDIA_TYPE_VIDEO, tech_pvt->video_rtp_session);
}
if (switch_rtp_ready(tech_pvt->video_rtp_session)) {
} smh_flag_t;
+typedef struct secure_settings_s {
+ int crypto_tag;
+ unsigned char local_raw_key[SWITCH_RTP_MAX_CRYPTO_LEN];
+ unsigned char remote_raw_key[SWITCH_RTP_MAX_CRYPTO_LEN];
+ switch_rtp_crypto_key_type_t crypto_send_type;
+ switch_rtp_crypto_key_type_t crypto_recv_type;
+ switch_rtp_crypto_key_type_t crypto_type;
+ char *local_crypto_key;
+ char *remote_crypto_key;
+} switch_secure_settings_t;
+
+typedef struct switch_rtp_engine_s {
+ switch_secure_settings_t ssec;
+ switch_rtp_t *rtp_session;
+ switch_media_type_t type;
+} switch_rtp_engine_t;
+
+
struct switch_media_handle_s {
switch_core_session_t *session;
switch_core_media_NDLB_t ndlb;
smh_flag_t flags;
+ switch_rtp_engine_t engines[SWITCH_MEDIA_TYPE_TOTAL];
};
+SWITCH_DECLARE(const char *) switch_core_sesson_local_crypto_key(switch_core_session_t *session, switch_media_type_t type)
+{
+ if (!session->media_handle) {
+ return NULL;
+ }
+
+ return session->media_handle->engines[type].ssec.local_crypto_key;
+
+}
+
+
+switch_status_t switch_core_media_build_crypto(switch_media_handle_t *smh,
+ switch_secure_settings_t *ssec,
+ int index, switch_rtp_crypto_key_type_t type, switch_rtp_crypto_direction_t direction)
+{
+ unsigned char b64_key[512] = "";
+ const char *type_str;
+ unsigned char *key;
+ const char *val;
+ switch_channel_t *channel;
+ char *p;
+
+ switch_assert(smh);
+ channel = switch_core_session_get_channel(smh->session);
+
+ if (type == AES_CM_128_HMAC_SHA1_80) {
+ type_str = SWITCH_RTP_CRYPTO_KEY_80;
+ } else {
+ type_str = SWITCH_RTP_CRYPTO_KEY_32;
+ }
+
+ if (direction == SWITCH_RTP_CRYPTO_SEND) {
+ key = ssec->local_raw_key;
+ } else {
+ key = ssec->remote_raw_key;
+
+ }
+
+ switch_rtp_get_random(key, SWITCH_RTP_KEY_LEN);
+ switch_b64_encode(key, SWITCH_RTP_KEY_LEN, b64_key, sizeof(b64_key));
+ p = strrchr((char *) b64_key, '=');
+
+ while (p && *p && *p == '=') {
+ *p-- = '\0';
+ }
+
+ ssec->local_crypto_key = switch_core_session_sprintf(smh->session, "%d %s inline:%s", index, type_str, b64_key);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "Set Local Key [%s]\n", ssec->local_crypto_key);
+
+ if (!(smh->ndlb & SM_NDLB_DISABLE_SRTP_AUTH) &&
+ !((val = switch_channel_get_variable(channel, "NDLB_support_asterisk_missing_srtp_auth")) && switch_true(val))) {
+ ssec->crypto_type = type;
+ } else {
+ ssec->crypto_type = AES_CM_128_NULL_AUTH;
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+
+
+
+switch_status_t switch_core_media_add_crypto(switch_secure_settings_t *ssec, const char *key_str, switch_rtp_crypto_direction_t direction)
+{
+ unsigned char key[SWITCH_RTP_MAX_CRYPTO_LEN];
+ switch_rtp_crypto_key_type_t type;
+ char *p;
+
+
+ p = strchr(key_str, ' ');
+
+ if (p && *p && *(p + 1)) {
+ p++;
+ if (!strncasecmp(p, SWITCH_RTP_CRYPTO_KEY_32, strlen(SWITCH_RTP_CRYPTO_KEY_32))) {
+ type = AES_CM_128_HMAC_SHA1_32;
+ } else if (!strncasecmp(p, SWITCH_RTP_CRYPTO_KEY_80, strlen(SWITCH_RTP_CRYPTO_KEY_80))) {
+ type = AES_CM_128_HMAC_SHA1_80;
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error near [%s]\n", p);
+ goto bad;
+ }
+
+ p = strchr(p, ' ');
+ if (p && *p && *(p + 1)) {
+ p++;
+ if (strncasecmp(p, "inline:", 7)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error near [%s]\n", p);
+ goto bad;
+ }
+
+ p += 7;
+ switch_b64_decode(p, (char *) key, sizeof(key));
+
+ if (direction == SWITCH_RTP_CRYPTO_SEND) {
+ ssec->crypto_send_type = type;
+ memcpy(ssec->local_raw_key, key, SWITCH_RTP_KEY_LEN);
+ } else {
+ ssec->crypto_recv_type = type;
+ memcpy(ssec->remote_raw_key, key, SWITCH_RTP_KEY_LEN);
+ }
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ }
+
+ bad:
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error!\n");
+ return SWITCH_STATUS_FALSE;
+
+}
+
+SWITCH_DECLARE(void) switch_core_media_set_rtp_session(switch_core_session_t *session, switch_media_type_t type, switch_rtp_t *rtp_session)
+{
+ switch_rtp_engine_t *engine;
+ if (!session->media_handle) return;
+ engine = &session->media_handle->engines[type];
+ engine->rtp_session = rtp_session;
+}
+
+
+SWITCH_DECLARE(void) switch_core_session_get_recovery_crypto_key(switch_core_session_t *session, switch_media_type_t type, const char *varname)
+{
+ const char *tmp;
+ switch_rtp_engine_t *engine;
+ if (!session->media_handle) return;
+ engine = &session->media_handle->engines[type];
+
+ if ((tmp = switch_channel_get_variable(session->channel, varname))) {
+ engine->ssec.remote_crypto_key = switch_core_session_strdup(session, tmp);
+ switch_channel_set_flag(session->channel, CF_CRYPTO_RECOVER);
+ }
+}
+
+
+SWITCH_DECLARE(void) switch_core_session_apply_crypto(switch_core_session_t *session, switch_media_type_t type, const char *varname)
+{
+ switch_rtp_engine_t *engine;
+ if (!session->media_handle) return;
+ engine = &session->media_handle->engines[type];
+
+
+ if (engine->ssec.remote_crypto_key && switch_channel_test_flag(session->channel, CF_SECURE)) {
+ switch_core_media_add_crypto(&engine->ssec, engine->ssec.remote_crypto_key, SWITCH_RTP_CRYPTO_RECV);
+
+
+ switch_rtp_add_crypto_key(engine->rtp_session, SWITCH_RTP_CRYPTO_SEND, 1,
+ engine->ssec.crypto_type, engine->ssec.local_raw_key, SWITCH_RTP_KEY_LEN);
+
+ switch_rtp_add_crypto_key(engine->rtp_session, SWITCH_RTP_CRYPTO_RECV, engine->ssec.crypto_tag,
+ engine->ssec.crypto_type, engine->ssec.remote_raw_key, SWITCH_RTP_KEY_LEN);
+
+ switch_channel_set_variable(session->channel, varname, "true");
+ }
+
+}
+
+
+SWITCH_DECLARE(int) switch_core_session_check_incoming_crypto(switch_core_session_t *session,
+ const char *varname,
+ switch_media_type_t type, const char *crypto, int crypto_tag)
+{
+ int got_crypto = 0;
+
+ switch_rtp_engine_t *engine;
+ if (!session->media_handle) return 0;
+ engine = &session->media_handle->engines[type];
+
+ if (engine->ssec.remote_crypto_key && switch_rtp_ready(engine->rtp_session)) {
+ /* Compare all the key. The tag may remain the same even if key changed */
+ if (crypto && !strcmp(crypto, engine->ssec.remote_crypto_key)) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Existing key is still valid.\n");
+ } else {
+ const char *a = switch_stristr("AES", engine->ssec.remote_crypto_key);
+ const char *b = switch_stristr("AES", crypto);
+
+ /* Change our key every time we can */
+
+ if (switch_channel_test_flag(session->channel, CF_CRYPTO_RECOVER)) {
+ switch_channel_clear_flag(session->channel, CF_CRYPTO_RECOVER);
+ } else if (switch_stristr(SWITCH_RTP_CRYPTO_KEY_32, crypto)) {
+ switch_channel_set_variable(session->channel, varname, SWITCH_RTP_CRYPTO_KEY_32);
+
+ switch_core_media_build_crypto(session->media_handle, &engine->ssec, crypto_tag, AES_CM_128_HMAC_SHA1_32, SWITCH_RTP_CRYPTO_SEND);
+ switch_rtp_add_crypto_key(engine->rtp_session, SWITCH_RTP_CRYPTO_SEND, atoi(crypto), engine->ssec.crypto_type,
+ engine->ssec.local_raw_key, SWITCH_RTP_KEY_LEN);
+ } else if (switch_stristr(SWITCH_RTP_CRYPTO_KEY_80, crypto)) {
+
+ switch_channel_set_variable(session->channel, varname, SWITCH_RTP_CRYPTO_KEY_80);
+ switch_core_media_build_crypto(session->media_handle, &engine->ssec, crypto_tag, AES_CM_128_HMAC_SHA1_80, SWITCH_RTP_CRYPTO_SEND);
+ switch_rtp_add_crypto_key(engine->rtp_session, SWITCH_RTP_CRYPTO_SEND, atoi(crypto), engine->ssec.crypto_type,
+ engine->ssec.local_raw_key, SWITCH_RTP_KEY_LEN);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Crypto Setup Failed!.\n");
+ }
+
+ if (a && b && !strncasecmp(a, b, 23)) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Change Remote key to [%s]\n", crypto);
+ engine->ssec.remote_crypto_key = switch_core_session_strdup(session, crypto);
+ switch_channel_set_variable(session->channel, "srtp_remote_audio_crypto_key", crypto);
+ engine->ssec.crypto_tag = crypto_tag;
+
+ if (switch_rtp_ready(engine->rtp_session) && switch_channel_test_flag(session->channel, CF_SECURE)) {
+ switch_core_media_add_crypto(&engine->ssec, engine->ssec.remote_crypto_key, SWITCH_RTP_CRYPTO_RECV);
+ switch_rtp_add_crypto_key(engine->rtp_session, SWITCH_RTP_CRYPTO_RECV, engine->ssec.crypto_tag,
+ engine->ssec.crypto_type, engine->ssec.remote_raw_key, SWITCH_RTP_KEY_LEN);
+ }
+ got_crypto++;
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Ignoring unacceptable key\n");
+ }
+ }
+ } else if (!switch_rtp_ready(engine->rtp_session)) {
+ engine->ssec.remote_crypto_key = switch_core_session_strdup(session, crypto);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set Remote Key [%s]\n", engine->ssec.remote_crypto_key);
+ switch_channel_set_variable(session->channel, "srtp_remote_audio_crypto_key", crypto);
+ engine->ssec.crypto_tag = crypto_tag;
+ got_crypto++;
+
+ if (zstr(engine->ssec.local_crypto_key)) {
+ if (switch_stristr(SWITCH_RTP_CRYPTO_KEY_32, crypto)) {
+ switch_channel_set_variable(session->channel, varname, SWITCH_RTP_CRYPTO_KEY_32);
+ switch_core_media_build_crypto(session->media_handle, &engine->ssec, crypto_tag, AES_CM_128_HMAC_SHA1_32, SWITCH_RTP_CRYPTO_SEND);
+ } else if (switch_stristr(SWITCH_RTP_CRYPTO_KEY_80, crypto)) {
+ switch_channel_set_variable(session->channel, varname, SWITCH_RTP_CRYPTO_KEY_80);
+ switch_core_media_build_crypto(session->media_handle, &engine->ssec, crypto_tag, AES_CM_128_HMAC_SHA1_80, SWITCH_RTP_CRYPTO_SEND);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Crypto Setup Failed!.\n");
+ }
+ }
+ }
+
+ return got_crypto;
+}
+
+
+SWITCH_DECLARE(void) switch_core_session_check_outgoing_crypto(switch_core_session_t *session, const char *sec_var)
+{
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ const char *var;
+
+ if (!switch_core_session_media_handle_ready(session)) return;
+
+ if ((var = switch_channel_get_variable(channel, sec_var)) && !zstr(var)) {
+ if (switch_true(var) || !strcasecmp(var, SWITCH_RTP_CRYPTO_KEY_32)) {
+ switch_channel_set_flag(channel, CF_SECURE);
+ switch_core_media_build_crypto(session->media_handle,
+ &session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].ssec, 1, AES_CM_128_HMAC_SHA1_32, SWITCH_RTP_CRYPTO_SEND);
+ switch_core_media_build_crypto(session->media_handle,
+ &session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].ssec, 1, AES_CM_128_HMAC_SHA1_32, SWITCH_RTP_CRYPTO_SEND);
+ } else if (!strcasecmp(var, SWITCH_RTP_CRYPTO_KEY_80)) {
+ switch_channel_set_flag(channel, CF_SECURE);
+ switch_core_media_build_crypto(session->media_handle,
+ &session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].ssec, 1, AES_CM_128_HMAC_SHA1_80, SWITCH_RTP_CRYPTO_SEND);
+ switch_core_media_build_crypto(session->media_handle,
+ &session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].ssec, 1, AES_CM_128_HMAC_SHA1_80, SWITCH_RTP_CRYPTO_SEND);
+ }
+ }
+
+}
+
+
SWITCH_DECLARE(switch_status_t) switch_media_handle_create(switch_media_handle_t **smhp, switch_core_session_t *session)
{
switch_status_t status = SWITCH_STATUS_FALSE;
*smhp = NULL;
if ((session->media_handle = switch_core_session_alloc(session, (sizeof(*smh))))) {
-
+ session->media_handle->session = session;
*smhp = session->media_handle;
switch_set_flag(session->media_handle, SMH_INIT);
status = SWITCH_STATUS_SUCCESS;