]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
pull srtp negotiation stuff into the core stage 1
authorAnthony Minessale <anthm@freeswitch.org>
Wed, 19 Dec 2012 02:35:44 +0000 (20:35 -0600)
committerAnthony Minessale <anthm@freeswitch.org>
Mon, 1 Apr 2013 02:27:13 +0000 (21:27 -0500)
src/include/switch_core_media.h
src/include/switch_types.h
src/mod/endpoints/mod_sofia/mod_sofia.c
src/mod/endpoints/mod_sofia/mod_sofia.h
src/mod/endpoints/mod_sofia/sofia.c
src/mod/endpoints/mod_sofia/sofia_glue.c
src/mod/endpoints/mod_sofia/sofia_media.c
src/switch_core_media.c

index 976de00aa0adf8f1ad78a4846d2b8c5e20296f70..b0374e0990bcdfa3a808588382e7c456da1555f3 100644 (file)
@@ -39,7 +39,8 @@ SWITCH_BEGIN_EXTERN_C
 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;
@@ -52,6 +53,16 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_media_handle_ready(switch_co
 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
index 5a35f81e4b0330f78b8c53bd378c957e2e03b63a..50e3377671e7c680272b24503b741cd6ca195814 100644 (file)
@@ -1280,6 +1280,8 @@ typedef enum {
        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
@@ -1463,6 +1465,7 @@ typedef enum {
        SWITCH_MEDIA_TYPE_AUDIO,
        SWITCH_MEDIA_TYPE_VIDEO
 } switch_media_type_t;
+#define SWITCH_MEDIA_TYPE_TOTAL 2
 
 
 /*!
index edd4711549594c3adb529335d17cb175d5c3fea0..da88a181cdd8721e7e1e8a36e26c970651b00e46 100644 (file)
@@ -93,17 +93,8 @@ static switch_status_t sofia_on_init(switch_core_session_t *session)
        }
 
        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) {
@@ -1871,7 +1862,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
 
                        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)) {
index 93fe66c8b967e2286d524ab5f63600532cf94909..abcfebbcaca4e63206dac12d4e1838c3ef331a4e 100644 (file)
@@ -224,7 +224,6 @@ typedef enum {
        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,
@@ -309,7 +308,6 @@ typedef enum {
        TFLAG_BYE,
        TFLAG_ANS,
        TFLAG_EARLY_MEDIA,
-       TFLAG_SECURE,
        TFLAG_VAD_IN,
        TFLAG_VAD_OUT,
        TFLAG_VAD,
@@ -349,7 +347,6 @@ typedef enum {
        TFLAG_SLA_BARGE,
        TFLAG_SLA_BARGING,
        TFLAG_PASS_ACK,
-       TFLAG_CRYPTO_RECOVER,
        TFLAG_DROP_DTMF,
        /* No new flags below this line */
        TFLAG_MAX
@@ -754,12 +751,6 @@ struct private_object {
        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;
@@ -777,8 +768,6 @@ struct private_object {
        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;
@@ -1125,7 +1114,7 @@ char *sofia_glue_strip_uri(const char *str);
 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);
index b6296ac37eb1308009149d6386da9a5a220f796f..a0a998ccfa30e8cab73d887296b0ed2c15f90662 100644 (file)
@@ -3923,7 +3923,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
                                        } 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);
@@ -6187,7 +6187,8 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
 
 
                                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)) {
index a4cfebbcbf0048eced540912cd3144fbaf90503b..7d57e6eb7f9eaf8dc06ee0d4d408249647f0c3ea 100644 (file)
@@ -186,6 +186,7 @@ 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 *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" : "");
@@ -323,7 +324,7 @@ static void generate_m(private_object_t *tech_pvt, char *buf, size_t buflen,
        }
 
        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");
        }
 
@@ -395,7 +396,8 @@ 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 *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);
@@ -513,7 +515,7 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch
 
        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);
 
@@ -571,8 +573,8 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch
                        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");
                }
 
@@ -595,7 +597,7 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch
                        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));
 
@@ -631,7 +633,7 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch
 
                                        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));
 
@@ -3109,51 +3111,6 @@ switch_status_t sofia_glue_tech_set_codec(private_object_t *tech_pvt, int force)
 }
 
 
-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;
@@ -4131,10 +4088,8 @@ int sofia_recover_callback(switch_core_session_t *session)
        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);
index d9d72c6a48561e1219e9ec18a18e7e6759597509..5d3704b87241d1730bceb6cab4c302dfcdd1f235 100644 (file)
@@ -311,61 +311,6 @@ switch_t38_options_t *sofia_glue_extract_t38_options(switch_core_session_t *sess
 
 }
 
-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)
 {
@@ -676,67 +621,9 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
                                        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");
-                                                       }
-                                               }
-                                       }
                                }
                        }
 
@@ -1171,7 +1058,7 @@ switch_status_t sofia_media_activate_rtp(private_object_t *tech_pvt)
        }
 
        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)) {
@@ -1376,6 +1263,9 @@ switch_status_t sofia_media_activate_rtp(private_object_t *tech_pvt)
                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);
@@ -1582,15 +1472,7 @@ switch_status_t sofia_media_activate_rtp(private_object_t *tech_pvt)
                        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);
@@ -1754,6 +1636,7 @@ switch_status_t sofia_media_activate_rtp(private_object_t *tech_pvt)
 
                        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)) {
index 970620fa562e5f37a4a062ea25f0ec24f443405e..61bed621a0f481aa076cb283cc22f97bd11c284a 100644 (file)
@@ -46,13 +46,295 @@ typedef enum {
 } 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;
@@ -61,7 +343,7 @@ SWITCH_DECLARE(switch_status_t) switch_media_handle_create(switch_media_handle_t
        *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;