[Freeswitch-svn] [commit] r7244 - in freeswitch/trunk/src: . include mod/applications/mod_esf mod/endpoints/mod_dingaling mod/endpoints/mod_sofia

Freeswitch SVN anthm at freeswitch.org
Wed Jan 16 01:01:53 EST 2008


Author: anthm
Date: Wed Jan 16 01:01:53 2008
New Revision: 7244

Modified:
   freeswitch/trunk/src/include/switch_rtp.h
   freeswitch/trunk/src/include/switch_utils.h
   freeswitch/trunk/src/mod/applications/mod_esf/mod_esf.c
   freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c
   freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c
   freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h
   freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c
   freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c
   freeswitch/trunk/src/switch_rtp.c
   freeswitch/trunk/src/switch_utils.c

Log:
RFC4568 support, you don't need the cone of silence anymore...

Modified: freeswitch/trunk/src/include/switch_rtp.h
==============================================================================
--- freeswitch/trunk/src/include/switch_rtp.h	(original)
+++ freeswitch/trunk/src/include/switch_rtp.h	Wed Jan 16 01:01:53 2008
@@ -41,12 +41,50 @@
 
 SWITCH_BEGIN_EXTERN_C
 #define SWITCH_RTP_MAX_BUF_LEN 16384
+#define SWITCH_RTP_MAX_CRYPTO_LEN 64
+#define SWITCH_RTP_KEY_LEN 30
+#define SWITCH_RTP_CRYPTO_KEY_32 "AES_CM_128_HMAC_SHA1_32"
+#define SWITCH_RTP_CRYPTO_KEY_80 "AES_CM_128_HMAC_SHA1_80"
+
+
+typedef enum {
+	SWITCH_RTP_CRYPTO_SEND,
+	SWITCH_RTP_CRYPTO_RECV,
+	SWITCH_RTP_CRYPTO_MAX
+} switch_rtp_crypto_direction_t;
+
+typedef enum {
+	NO_CRYPTO,
+	AES_CM_128_HMAC_SHA1_80,
+	AES_CM_128_HMAC_SHA1_32
+} switch_rtp_crypto_key_type_t;
+
+struct switch_rtp_crypto_key {
+	uint32_t index;
+	switch_rtp_crypto_key_type_t type;
+	unsigned char key[SWITCH_RTP_MAX_CRYPTO_LEN];
+	switch_size_t keylen;
+	struct switch_rtp_crypto_key *next;
+};
+typedef struct switch_rtp_crypto_key switch_rtp_crypto_key_t;
+
+
+
+SWITCH_DECLARE(switch_status_t) switch_rtp_add_crypto_key(switch_rtp_t *rtp_session,
+														  switch_rtp_crypto_direction_t direction,
+														  uint32_t index,
+														  switch_rtp_crypto_key_type_t type,
+														  unsigned char *key,
+														  switch_size_t keylen);
+
 ///\defgroup rtp RTP (RealTime Transport Protocol)
 ///\ingroup core1
 ///\{
 typedef void (*switch_rtp_invalid_handler_t) (switch_rtp_t *rtp_session,
 											  switch_socket_t * sock, void *data, switch_size_t datalen, switch_sockaddr_t * from_addr);
 
+
+SWITCH_DECLARE(void) switch_rtp_get_random(void *buf, uint32_t len);
 /*! 
   \brief Initilize the RTP System
   \param pool the memory pool to use for long term allocations
@@ -83,7 +121,6 @@
   \param samples_per_interval the default samples_per_interval
   \param ms_per_packet time in microseconds per packet
   \param flags flags to control behaviour
-  \param crypto_key optional crypto key
   \param timer_name timer interface to use
   \param err a pointer to resolve error messages
   \param pool a memory pool to use for the session
@@ -93,7 +130,9 @@
 												  switch_payload_t payload,
 												  uint32_t samples_per_interval,
 												  uint32_t ms_per_packet,
-												  switch_rtp_flag_t flags, char *crypto_key, char *timer_name, const char **err,
+												  switch_rtp_flag_t flags,
+												  char *timer_name, 
+												  const char **err,
 												  switch_memory_pool_t *pool);
 
 
@@ -107,7 +146,6 @@
   \param samples_per_interval the default samples_per_interval
   \param ms_per_packet time in microseconds per packet
   \param flags flags to control behaviour
-  \param crypto_key optional crypto key
   \param timer_name timer interface to use
   \param err a pointer to resolve error messages
   \param pool a memory pool to use for the session
@@ -120,7 +158,10 @@
 											  switch_payload_t payload,
 											  uint32_t samples_per_interval,
 											  uint32_t ms_per_packet,
-											  switch_rtp_flag_t flags, char *crypto_key, char *timer_name, const char **err, switch_memory_pool_t *pool);
+											  switch_rtp_flag_t flags,
+											  char *timer_name,
+											  const char **err,
+											  switch_memory_pool_t *pool);
 
 
 /*! 

Modified: freeswitch/trunk/src/include/switch_utils.h
==============================================================================
--- freeswitch/trunk/src/include/switch_utils.h	(original)
+++ freeswitch/trunk/src/include/switch_utils.h	Wed Jan 16 01:01:53 2008
@@ -56,7 +56,7 @@
 #endif
 
 SWITCH_DECLARE(switch_status_t) switch_b64_encode(unsigned char *in, switch_size_t ilen, unsigned char *out, switch_size_t olen);
-SWITCH_DECLARE(switch_status_t) switch_b64_decode(char *in, char *out, switch_size_t olen);
+SWITCH_DECLARE(switch_size_t) switch_b64_decode(char *in, char *out, switch_size_t olen);
 SWITCH_DECLARE(char *) switch_amp_encode(char *s, char *buf, switch_size_t len);
 
 static inline switch_bool_t switch_is_digit_string(const char *s) {

Modified: freeswitch/trunk/src/mod/applications/mod_esf/mod_esf.c
==============================================================================
--- freeswitch/trunk/src/mod/applications/mod_esf/mod_esf.c	(original)
+++ freeswitch/trunk/src/mod/applications/mod_esf/mod_esf.c	Wed Jan 16 01:01:53 2008
@@ -167,7 +167,7 @@
 									 read_codec->implementation->samples_per_frame,
 									 read_codec->implementation->microseconds_per_frame,
 									 (switch_rtp_flag_t) flags,
-									 NULL, "soft", &err, switch_core_session_get_pool(session));
+									 "soft", &err, switch_core_session_get_pool(session));
 	
 		if (!switch_rtp_ready(rtp_session)) {
 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "RTP Error\n");

Modified: freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c	Wed Jan 16 01:01:53 2008
@@ -877,7 +877,7 @@
 												 tech_pvt->codec_num,
 												 tech_pvt->read_codec.implementation->samples_per_frame,
 												 tech_pvt->read_codec.implementation->microseconds_per_frame,
-												 flags, NULL, tech_pvt->profile->timer_name, &err, switch_core_session_get_pool(tech_pvt->session)))) {
+												 flags, tech_pvt->profile->timer_name, &err, switch_core_session_get_pool(tech_pvt->session)))) {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "RTP ERROR %s\n", err);
 		switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
 		return 0;

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c	Wed Jan 16 01:01:53 2008
@@ -90,6 +90,19 @@
 	}
 
 	if (switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
+		const char *var;
+
+		if ((var = switch_channel_get_variable(channel, SOFIA_SECURE_MEDIA_VARIABLE)) && !switch_strlen_zero(var)) {
+			if (switch_true(var) || !strcasecmp(var, SWITCH_RTP_CRYPTO_KEY_32)) {
+				switch_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)) {
+				switch_set_flag_locked(tech_pvt, TFLAG_SECURE);
+				sofia_glue_build_crypto(tech_pvt, 1, AES_CM_128_HMAC_SHA1_80, SWITCH_RTP_CRYPTO_SEND);
+			}
+		}
+
+
 		if (sofia_glue_do_invite(session) != SWITCH_STATUS_SUCCESS) {
 			switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
 			return SWITCH_STATUS_FALSE;
@@ -786,6 +799,13 @@
 	tech_pvt = (private_object_t *) switch_core_session_get_private(session);
 	switch_assert(tech_pvt != NULL);
 
+	if (msg->message_id == SWITCH_MESSAGE_INDICATE_ANSWER || msg->message_id == SWITCH_MESSAGE_INDICATE_PROGRESS) {
+		const char *var;
+		if ((var = switch_channel_get_variable(channel, SOFIA_SECURE_MEDIA_VARIABLE)) && switch_true(var)) {
+			switch_set_flag_locked(tech_pvt, TFLAG_SECURE);
+		}
+	}
+
 	switch (msg->message_id) {
 	case SWITCH_MESSAGE_INDICATE_BROADCAST: {
 		const char *ip = NULL, *port = NULL;
@@ -1746,6 +1766,7 @@
 	*pool = NULL;
 
   done:
+
 	if (profile) {
 		sofia_glue_release_profile(profile);
 	}

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h	Wed Jan 16 01:01:53 2008
@@ -73,6 +73,9 @@
 #define SOFIA_DEFAULT_PORT "5060"
 #define SOFIA_DEFAULT_TLS_PORT "5061"
 #define SOFIA_REFER_TO_VARIABLE "sip_refer_to"
+#define SOFIA_SECURE_MEDIA_VARIABLE "sip_secure_media"
+#define SOFIA_SECURE_MEDIA_CONFIRMED_VARIABLE "sip_secure_media_confirmed"
+#define SOFIA_HAS_CRYPTO_VARIABLE "sip_has_crypto"
 
 #include <sofia-sip/nua.h>
 #include <sofia-sip/sip_status.h>
@@ -124,7 +127,8 @@
 	PFLAG_MULTIREG = (1 << 11),
 	PFLAG_SUPRESS_CNG = (1 << 12),
 	PFLAG_TLS = (1 << 13),
-	PFLAG_CHECKUSER = (1 << 14)
+	PFLAG_CHECKUSER = (1 << 14),
+	PFLAG_SECURE = (1 << 15)
 } PFLAGS;
 
 typedef enum {
@@ -339,6 +343,13 @@
 	char *invite_contact;
 	char *local_url;
 	char *gateway_name;
+	char *local_crypto_key;
+	char *remote_crypto_key;
+	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;
 	unsigned long rm_rate;
 	switch_payload_t pt;
 	switch_mutex_t *flag_mutex;
@@ -561,3 +572,4 @@
 
 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);

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c	Wed Jan 16 01:01:53 2008
@@ -1010,6 +1010,10 @@
 						if (switch_true(val)) {
 							profile->pflags |= PFLAG_PRESENCE;
 						}
+					} else if (!strcasecmp(var, "require-secure-rtp")) {
+						if (switch_true(val)) {
+							profile->pflags |= PFLAG_SECURE;
+						}
 					} else if (!strcasecmp(var, "multiple-registrations")) {
 						if (switch_true(val)) {
 							profile->pflags |= PFLAG_MULTIREG;

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c	Wed Jan 16 01:01:53 2008
@@ -89,6 +89,8 @@
 			 "a=%s\n" 
 			 "m=audio %d RTP/AVP", tech_pvt->owner_id, tech_pvt->session_id, ip, ip, sr, port);
 	
+
+
 	if (tech_pvt->rm_encoding) {
 		switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %d", tech_pvt->pt);
 	} else if (tech_pvt->num_codecs) {
@@ -126,6 +128,7 @@
 
 	switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "\n");
 
+
 	if (tech_pvt->rm_encoding) {
 		rate = tech_pvt->rm_rate;
 		switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=rtpmap:%d %s/%d\n", tech_pvt->pt, tech_pvt->rm_encoding, rate);
@@ -181,6 +184,11 @@
 		switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=ptime:%d\n", ptime);
 	}
 
+	if (!switch_strlen_zero(tech_pvt->local_crypto_key) && switch_test_flag(tech_pvt, TFLAG_SECURE)) {
+		switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=crypto:%s\n", tech_pvt->local_crypto_key);
+		switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=encryption:optional\n");
+	}
+
 	if (switch_test_flag(tech_pvt, TFLAG_VIDEO) && tech_pvt->video_rm_encoding) {
 		sofia_glue_tech_choose_video_port(tech_pvt);
 		if ((v_port = tech_pvt->adv_sdp_video_port)) {
@@ -928,7 +936,7 @@
 
 void sofia_glue_deactivate_rtp(private_object_t *tech_pvt)
 {
-	int loops = 0;				//, sock = -1;
+	int loops = 0;
 	if (switch_rtp_ready(tech_pvt->rtp_session)) {
 		while (loops < 10 && (switch_test_flag(tech_pvt, TFLAG_READING) || switch_test_flag(tech_pvt, TFLAG_WRITING))) {
 			switch_yield(10000);
@@ -1077,6 +1085,102 @@
 	return SWITCH_STATUS_SUCCESS;
 }
 
+
+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;
+
+	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_LOG, SWITCH_LOG_DEBUG, "Set Local Key [%s]\n", tech_pvt->local_crypto_key);
+	tech_pvt->crypto_type = type;
+
+
+	return SWITCH_STATUS_SUCCESS;
+}
+
+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];
+	int index;
+	switch_rtp_crypto_key_type_t type;
+	char *p;
+
+
+	if (!switch_rtp_ready(tech_pvt->rtp_session)) {
+		goto bad;
+	}
+	
+	index = atoi(key_str);
+
+	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) {
+				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_LOG, SWITCH_LOG_ERROR, "Error!\n");
+	return SWITCH_STATUS_FALSE;
+
+}
+
+
 switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_flag_t myflags)
 {
 	int bw, ms;
@@ -1175,8 +1279,10 @@
 										   tech_pvt->read_codec.implementation->samples_per_frame,
 										   tech_pvt->codec_ms * 1000,
 										   (switch_rtp_flag_t) flags,
-										   NULL, tech_pvt->profile->timer_name, &err, switch_core_session_get_pool(tech_pvt->session));
-
+										   tech_pvt->profile->timer_name,
+										   &err,
+										   switch_core_session_get_pool(tech_pvt->session));
+	
 	if (switch_rtp_ready(tech_pvt->rtp_session)) {
 		uint8_t vad_in = switch_test_flag(tech_pvt, TFLAG_VAD_IN) ? 1 : 0;
 		uint8_t vad_out = switch_test_flag(tech_pvt, TFLAG_VAD_OUT) ? 1 : 0;
@@ -1243,6 +1349,14 @@
 			switch_rtp_set_cng_pt(tech_pvt->rtp_session, tech_pvt->cng_pt);
 		}
 		
+		if (tech_pvt->remote_crypto_key && switch_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, 1, 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");
+		}
+
+
 		sofia_glue_check_video_codecs(tech_pvt);
 
 		if (switch_test_flag(tech_pvt, TFLAG_VIDEO) && tech_pvt->video_rm_encoding) {
@@ -1250,16 +1364,16 @@
 			sofia_glue_tech_set_video_codec(tech_pvt, 0);
 
 			tech_pvt->video_rtp_session = switch_rtp_new(tech_pvt->local_sdp_audio_ip,
-													 tech_pvt->local_sdp_video_port,
-													 tech_pvt->remote_sdp_video_ip,
-													 tech_pvt->remote_sdp_video_port,
-													 tech_pvt->video_agreed_pt,
-													 tech_pvt->video_read_codec.implementation->samples_per_frame,
-													 0,
-													 (switch_rtp_flag_t) flags,
-													 NULL, 
-													 NULL,
-													 &err, switch_core_session_get_pool(tech_pvt->session));
+														 tech_pvt->local_sdp_video_port,
+														 tech_pvt->remote_sdp_video_ip,
+														 tech_pvt->remote_sdp_video_port,
+														 tech_pvt->video_agreed_pt,
+														 tech_pvt->video_read_codec.implementation->samples_per_frame,
+														 0,
+														 (switch_rtp_flag_t) flags,
+														 NULL,
+														 &err, 
+														 switch_core_session_get_pool(tech_pvt->session));
 
 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "VIDEO RTP [%s] %s:%d->%s:%d codec: %u ms: %d [%s]\n",
 							  switch_channel_get_name(tech_pvt->channel),
@@ -1396,7 +1510,6 @@
 			}
 
 			if (stream) {
-				//switch_ivr_displace_session(tech_pvt->session, stream, 0, "rl");
 				switch_ivr_broadcast(switch_channel_get_variable(tech_pvt->channel, SWITCH_SIGNAL_BOND_VARIABLE), stream, SMF_ECHO_ALEG | SMF_LOOP);
 			}
 		}
@@ -1405,8 +1518,6 @@
 			const char *uuid;
 			switch_core_session_t *b_session;
 			
-			//const char *stream;
-
 			if (tech_pvt->max_missed_packets) {
 				switch_rtp_set_max_missed_packets(tech_pvt->rtp_session, tech_pvt->max_missed_packets);
 			}
@@ -1418,14 +1529,6 @@
 				switch_core_session_rwunlock(b_session);
 			}
 
-			//if (!(stream = switch_channel_get_variable(tech_pvt->channel, SWITCH_HOLD_MUSIC_VARIABLE))) {
-			//stream = tech_pvt->profile->hold_music;
-            //}
-
-			//if (stream) {
-			//switch_ivr_stop_displace_session(tech_pvt->session, stream);
-			//}
-
 			switch_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
 			switch_channel_presence(tech_pvt->channel, "unknown", "unhold");
 		}
@@ -1444,6 +1547,24 @@
 					ptime = atoi(a->a_value);
 				} else if (!strcasecmp(a->a_name, "crypto") && a->a_value) {
 					crypto = a->a_value;
+					if (tech_pvt->remote_crypto_key) {
+						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Already have a key\n");
+					} else {
+						tech_pvt->remote_crypto_key = switch_core_session_strdup(tech_pvt->session, crypto);
+						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Set Remote Key [%s]\n", tech_pvt->remote_crypto_key);
+
+						if (switch_strlen_zero(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_LOG, SWITCH_LOG_ERROR, "Crypto Setup Failed!.\n");
+							}
+						}
+					}
 				}
 			}
 
@@ -1461,7 +1582,6 @@
 		greed:
 			x = 0;
 
-			//xxxxxx
 			if (tech_pvt->rm_encoding) {
 				for (map = m->m_rtpmaps; map; map = map->rm_next) {
 					if (map->rm_pt < 96) {
@@ -1486,7 +1606,6 @@
 				const char *rm_encoding;
 				
 				if (x++ < skip) {
-					//printf("skip %s\n", map->rm_encoding);
 					continue;
 				}
 

Modified: freeswitch/trunk/src/switch_rtp.c
==============================================================================
--- freeswitch/trunk/src/switch_rtp.c	(original)
+++ freeswitch/trunk/src/switch_rtp.c	Wed Jan 16 01:01:53 2008
@@ -43,14 +43,16 @@
 #undef inline
 #include <datatypes.h>
 #include <srtp.h>
+
+
 #include "stfu.h"
-#define MAX_KEY_LEN      64
+
 #define rtp_header_len 12
 #define RTP_START_PORT 16384
 #define RTP_END_PORT 32768
-#define MAX_KEY_LEN      64
 #define MASTER_KEY_LEN   30
 #define RTP_MAGIC_NUMBER 42
+#define MAX_SRTP_ERRS 10
 
 static switch_port_t START_PORT = RTP_START_PORT;
 static switch_port_t END_PORT = RTP_END_PORT;
@@ -121,14 +123,19 @@
 
 	switch_sockaddr_t *local_addr;
 	rtp_msg_t send_msg;
-	srtp_ctx_t *send_ctx;
 
 	switch_sockaddr_t *remote_addr;
 	rtp_msg_t recv_msg;
-	srtp_ctx_t *recv_ctx;
+
 	uint32_t autoadj_window;
 	uint32_t autoadj_tally;
 
+	srtp_ctx_t *send_ctx;
+	srtp_ctx_t *recv_ctx;
+	srtp_policy_t send_policy;
+	srtp_policy_t recv_policy;
+	uint32_t srtp_errs;
+	
 	uint16_t seq;
 	uint32_t ssrc;
 	uint8_t sending_dtmf;
@@ -168,6 +175,7 @@
 	uint32_t max_missed_packets;
 	uint32_t missed_count;
 	rtp_msg_t write_msg;
+	switch_rtp_crypto_key_t *crypto_keys[SWITCH_RTP_CRYPTO_MAX];
 };
 
 static int global_init = 0;
@@ -277,6 +285,12 @@
 	global_init = 1;
 }
 
+SWITCH_DECLARE(void) switch_rtp_get_random(void *buf, uint32_t len)
+{
+	crypto_get_random(buf, len);
+}
+
+
 SWITCH_DECLARE(void) switch_rtp_shutdown(void)
 {
 	switch_core_hash_destroy(&alloc_hash);
@@ -470,16 +484,89 @@
 	return SWITCH_STATUS_SUCCESS;
 }
 
+SWITCH_DECLARE(switch_status_t) switch_rtp_add_crypto_key(switch_rtp_t *rtp_session,
+														  switch_rtp_crypto_direction_t direction,
+														  uint32_t index,
+														  switch_rtp_crypto_key_type_t type,
+														  unsigned char *key,
+														  switch_size_t keylen) 
+{
+	
+	switch_rtp_crypto_key_t *crypto_key;
+	srtp_policy_t *policy;
+	err_status_t stat;
+
+	crypto_key = switch_core_alloc(rtp_session->pool, sizeof(*crypto_key));
+	
+	policy = direction == SWITCH_RTP_CRYPTO_RECV ? &rtp_session->recv_policy : &rtp_session->send_policy;
+	
+
+	crypto_key->type = type;
+	crypto_key->index = index;
+	memcpy(crypto_key->key, key, keylen);
+	crypto_key->next = rtp_session->crypto_keys[direction];
+	rtp_session->crypto_keys[direction] = crypto_key;
+
+
+	memset(policy, 0, sizeof(*policy));
+	switch_set_flag_locked(rtp_session, SWITCH_RTP_FLAG_SECURE);
+
+	switch(crypto_key->type) {
+	case AES_CM_128_HMAC_SHA1_80:
+		crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy->rtp);
+		break;
+	case AES_CM_128_HMAC_SHA1_32:
+		crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy->rtp);
+		break;
+	default:
+		break;
+	}
+
+	
+	policy->next = NULL;	
+	policy->key = (uint8_t *) crypto_key->key;
+	crypto_policy_set_rtcp_default(&policy->rtcp);
+	policy->rtcp.sec_serv = sec_serv_none;
+
+	policy->rtp.sec_serv = sec_serv_conf_and_auth;
+	switch(direction) {
+	case SWITCH_RTP_CRYPTO_RECV:
+		policy->ssrc.type = ssrc_any_inbound;
+		if ((stat = srtp_create(&rtp_session->recv_ctx, policy))) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error allocating srtp [%d]\n", stat);
+			return SWITCH_STATUS_FALSE;
+		}
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Activating Secure RTP RECV\n");
+		break;
+	case SWITCH_RTP_CRYPTO_SEND:
+		policy->ssrc.type = ssrc_specific;
+		policy->ssrc.value = rtp_session->ssrc;
+
+		if ((stat = srtp_create(&rtp_session->send_ctx, policy))) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error allocating srtp [%d]\n", stat);
+			return SWITCH_STATUS_FALSE;
+		}
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Activating Secure RTP SEND\n");
+		break;
+	default:
+		abort();
+		break;
+	}
+
+	return SWITCH_STATUS_SUCCESS;
+
+}
+
 SWITCH_DECLARE(switch_status_t) switch_rtp_create(switch_rtp_t **new_rtp_session,
 												  switch_payload_t payload,
 												  uint32_t samples_per_interval,
 												  uint32_t ms_per_packet,
-												  switch_rtp_flag_t flags, char *crypto_key, char *timer_name, const char **err,
+												  switch_rtp_flag_t flags, 
+												  char *timer_name, 
+												  const char **err,
 												  switch_memory_pool_t *pool)
 {
 	switch_rtp_t *rtp_session = NULL;
-	srtp_policy_t policy;
-	char key[MAX_KEY_LEN];
 	uint32_t ssrc = rand() & 0xffff;
 
 	*new_rtp_session = NULL;
@@ -507,44 +594,10 @@
 	/* for from address on recvfrom calls */
 	switch_sockaddr_info_get(&rtp_session->from_addr, NULL, SWITCH_UNSPEC, 0, 0, pool);
 
-	memset(&policy, 0, sizeof(policy));
-	if (crypto_key) {
-		int len;
-
-		switch_set_flag_locked(rtp_session, SWITCH_RTP_FLAG_SECURE);
-		crypto_policy_set_rtp_default(&policy.rtp);
-		crypto_policy_set_rtcp_default(&policy.rtcp);
-		policy.ssrc.type = ssrc_any_inbound;
-		policy.ssrc.value = ssrc;
-		policy.key = (uint8_t *) key;
-		policy.next = NULL;
-		policy.rtp.sec_serv = sec_serv_conf_and_auth;
-		policy.rtcp.sec_serv = sec_serv_none;
-
-		/* read key from hexadecimal on command line into an octet string */
-		len = hex_string_to_octet_string(key, crypto_key, MASTER_KEY_LEN * 2);
-
-		/* check that hex string is the right length */
-		if (len < MASTER_KEY_LEN * 2) {
-			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
-							  "error: too few digits in key/salt " "(should be %d hexadecimal digits, found %d)\n", MASTER_KEY_LEN * 2, len);
-			*err = "Crypt Error";
-			return SWITCH_STATUS_FALSE;
-		}
-		if (strlen(crypto_key) > MASTER_KEY_LEN * 2) {
-			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
-							  "error: too many digits in key/salt "
-							  "(should be %d hexadecimal digits, found %u)\n", MASTER_KEY_LEN * 2, (unsigned) strlen(crypto_key));
-			*err = "Crypt Error";
-			return SWITCH_STATUS_FALSE;
-		}
-
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Activating Secure RTP!\n");
-	}
 
 	rtp_session->seq = (uint16_t) rand();
 	rtp_session->ssrc = ssrc;
-	rtp_session->send_msg.header.ssrc = htonl(ssrc);
+	rtp_session->send_msg.header.ssrc = htonl(rtp_session->ssrc);
 	rtp_session->send_msg.header.ts = 0;
 	rtp_session->send_msg.header.m = 0;
 	rtp_session->send_msg.header.pt = (switch_payload_t) htonl(payload);
@@ -553,7 +606,7 @@
 	rtp_session->send_msg.header.x = 0;
 	rtp_session->send_msg.header.cc = 0;
 
-	rtp_session->recv_msg.header.ssrc = htonl(ssrc);
+	rtp_session->recv_msg.header.ssrc = 0;
 	rtp_session->recv_msg.header.ts = 0;
 	rtp_session->recv_msg.header.seq = 0;
 	rtp_session->recv_msg.header.m = 0;
@@ -568,20 +621,6 @@
 	rtp_session->samples_per_interval = rtp_session->conf_samples_per_interval = samples_per_interval;
 	rtp_session->timer_name = switch_core_strdup(pool, timer_name);
 
-	if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_SECURE)) {
-		err_status_t stat;
-
-		if ((stat = srtp_create(&rtp_session->recv_ctx, &policy))) {
-			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error allocating srtp [%d]\n", stat);
-			*err = "Crypt Error";
-			return SWITCH_STATUS_FALSE;
-		}
-		if ((stat = srtp_create(&rtp_session->send_ctx, &policy))) {
-			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error allocating srtp [%d]\n", stat);
-			*err = "Crypt Error";
-			return SWITCH_STATUS_FALSE;
-		}
-	}
 
 	if (!switch_strlen_zero(timer_name)) {
 		switch_set_flag_locked(rtp_session, SWITCH_RTP_FLAG_USE_TIMER);
@@ -615,11 +654,14 @@
 											  switch_payload_t payload,
 											  uint32_t samples_per_interval,
 											  uint32_t ms_per_packet,
-											  switch_rtp_flag_t flags, char *crypto_key, char *timer_name, const char **err, switch_memory_pool_t *pool)
+											  switch_rtp_flag_t flags,
+											  char *timer_name, 
+											  const char **err, 
+											  switch_memory_pool_t *pool)
 {
 	switch_rtp_t *rtp_session = NULL;
 	
-	if (switch_rtp_create(&rtp_session, payload, samples_per_interval, ms_per_packet, flags, crypto_key, timer_name, err, pool) != SWITCH_STATUS_SUCCESS) {
+	if (switch_rtp_create(&rtp_session, payload, samples_per_interval, ms_per_packet, flags, timer_name, err, pool) != SWITCH_STATUS_SUCCESS) {
 		goto end;
 	}
 	
@@ -928,6 +970,29 @@
 			return -1;
 		}
 
+		if (bytes && switch_test_flag(rtp_session, SWITCH_RTP_FLAG_SECURE)) {
+			int sbytes = (int) bytes;
+			err_status_t stat;
+
+
+			stat = srtp_unprotect(rtp_session->recv_ctx, &rtp_session->recv_msg.header, &sbytes);
+			if (stat && rtp_session->recv_msg.header.pt != rtp_session->te && rtp_session->recv_msg.header.pt != rtp_session->cng_pt) {
+				if (++rtp_session->srtp_errs >= MAX_SRTP_ERRS) {
+					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
+									  "error: srtp unprotection failed with code %d%s\n", stat,
+									  stat == err_status_replay_fail ? " (replay check failed)" : stat == err_status_auth_fail ? " (auth check failed)" : "");
+					return -1;
+				} else {
+					sbytes = 0;
+				}
+			} else {
+				rtp_session->srtp_errs = 0;
+			}
+
+			bytes = sbytes;
+
+		}
+
 		if (rtp_session->jb && bytes && rtp_session->recv_msg.header.pt == rtp_session->payload) {
 			if (rtp_session->recv_msg.header.m) {
 				stfu_n_reset(rtp_session->jb);
@@ -1028,20 +1093,6 @@
 			return 2 + rtp_header_len;
 		}
 
-		if (bytes && switch_test_flag(rtp_session, SWITCH_RTP_FLAG_SECURE)) {
-			int sbytes = (int) bytes;
-			err_status_t stat;
-
-			stat = srtp_unprotect(rtp_session->recv_ctx, &rtp_session->recv_msg.header, &sbytes);
-			if (stat) {
-				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
-								  "error: srtp unprotection failed with code %d%s\n", stat,
-								  stat == err_status_replay_fail ? " (replay check failed)" : stat == err_status_auth_fail ? " (auth check failed)" : "");
-				return -1;
-			}
-			bytes = sbytes;
-		}
-
 		if (bytes > 0) {
 			rtp_session->missed_count = 0;
 		}
@@ -1356,7 +1407,6 @@
 		if (flags && *flags & SFF_RFC2833) {
 			send_msg->header.pt = rtp_session->te;
 		}
-		send_msg->header.ssrc = htonl(rtp_session->ssrc);
 	} else {
 		uint8_t m = 0;
 		
@@ -1392,17 +1442,7 @@
 		bytes = datalen + rtp_header_len;
 	}
 
-	if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_SECURE)) {
-		int sbytes = (int) bytes;
-		err_status_t stat;
-
-		stat = srtp_protect(rtp_session->send_ctx, &send_msg->header, &sbytes);
-		if (stat) {
-			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error: srtp protection failed with code %d\n", stat);
-		}
-
-		bytes = sbytes;
-	}
+	send_msg->header.ssrc = htonl(rtp_session->ssrc);
 
 	if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_GOOGLEHACK) && rtp_session->send_msg.header.pt == 97) {
 		rtp_session->recv_msg.header.pt = 102;
@@ -1517,6 +1557,19 @@
 	if (send) {
 		send_msg->header.seq = htons(++rtp_session->seq);
 		
+
+		if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_SECURE)) {
+			int sbytes = (int) bytes;
+			err_status_t stat;
+			
+			stat = srtp_protect(rtp_session->send_ctx, &send_msg->header, &sbytes);
+			if (stat) {
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error: srtp protection failed with code %d\n", stat);
+			}
+			
+			bytes = sbytes;
+		}
+
 		if (switch_socket_sendto(rtp_session->sock, rtp_session->remote_addr, 0, (void *) send_msg, &bytes) != SWITCH_STATUS_SUCCESS) {
 			rtp_session->seq--;
 			return -1;

Modified: freeswitch/trunk/src/switch_utils.c
==============================================================================
--- freeswitch/trunk/src/switch_utils.c	(original)
+++ freeswitch/trunk/src/switch_utils.c	Wed Jan 16 01:01:53 2008
@@ -166,7 +166,7 @@
 }
 
 
-SWITCH_DECLARE(switch_status_t) switch_b64_decode(char *in, char *out, switch_size_t olen)
+SWITCH_DECLARE(switch_size_t) switch_b64_decode(char *in, char *out, switch_size_t olen)
 {
 
 	char l64[256];
@@ -203,7 +203,7 @@
 
 	op[ol++] = '\0';
 
-	return SWITCH_STATUS_SUCCESS;
+	return ol;
 }
 
 



More information about the Freeswitch-svn mailing list