[asterisk-commits] file: trunk r417679 - in /trunk: ./ channels/ channels/sip/include/ configs/ ...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Jun 30 14:51:33 CDT 2014


Author: file
Date: Mon Jun 30 14:51:28 2014
New Revision: 417679

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=417679
Log:
Recorded merge of revisions 417677 from http://svn.asterisk.org/svn/asterisk/branches/11

........
res_rtp_asterisk: Add SHA-256 support for DTLS and perform DTLS negotiation on RTCP.

This change fixes up DTLS support in res_rtp_asterisk so it can accept and provide
a SHA-256 fingerprint, so it occurs on RTCP, and so it occurs after ICE negotiation
completes. Configuration options to chan_sip and chan_pjsip have also been added to
allow behavior to be tweaked (such as forcing the AVP type media transports in SDP).

ASTERISK-22961 #close
Reported by: Jay Jideliov

Review: https://reviewboard.asterisk.org/r/3679/
Review: https://reviewboard.asterisk.org/r/3686/
........

Merged revisions 417678 from http://svn.asterisk.org/svn/asterisk/branches/12

Added:
    trunk/contrib/ast-db-manage/config/versions/51f8cb66540e_add_further_dtls_options.py
      - copied unchanged from r417678, branches/12/contrib/ast-db-manage/config/versions/51f8cb66540e_add_further_dtls_options.py
Modified:
    trunk/   (props changed)
    trunk/channels/chan_sip.c
    trunk/channels/sip/include/sip.h
    trunk/configs/sip.conf.sample
    trunk/include/asterisk/res_pjsip.h
    trunk/include/asterisk/res_pjsip_session.h
    trunk/include/asterisk/rtp_engine.h
    trunk/include/asterisk/sdp_srtp.h
    trunk/main/rtp_engine.c
    trunk/main/sdp_srtp.c
    trunk/res/res_pjsip.c
    trunk/res/res_pjsip/pjsip_configuration.c
    trunk/res/res_pjsip_sdp_rtp.c
    trunk/res/res_rtp_asterisk.c

Propchange: trunk/
------------------------------------------------------------------------------
Binary property 'branch-12-merged' - no diff available.

Modified: trunk/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_sip.c?view=diff&rev=417679&r1=417678&r2=417679
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Mon Jun 30 14:51:28 2014
@@ -1251,7 +1251,7 @@
 static int process_sdp_a_image(const char *a, struct sip_pvt *p);
 static void add_ice_to_sdp(struct ast_rtp_instance *instance, struct ast_str **a_buf);
 static void add_dtls_to_sdp(struct ast_rtp_instance *instance, struct ast_str **a_buf);
-static void start_ice(struct ast_rtp_instance *instance);
+static void start_ice(struct ast_rtp_instance *instance, int offer);
 static void add_codec_to_sdp(const struct sip_pvt *p, struct ast_format *codec,
 			     struct ast_str **m_buf, struct ast_str **a_buf,
 			     int debug, int *min_packet_size, int *max_packet_size);
@@ -10163,12 +10163,21 @@
 
 			if (process_sdp_a_dtls(value, p, p->rtp)) {
 				processed = TRUE;
+				if (p->srtp) {
+					ast_set_flag(p->srtp, AST_SRTP_CRYPTO_OFFER_OK);
+				}
 			}
 			if (process_sdp_a_dtls(value, p, p->vrtp)) {
 				processed = TRUE;
+				if (p->vsrtp) {
+					ast_set_flag(p->vsrtp, AST_SRTP_CRYPTO_OFFER_OK);
+				}
 			}
 			if (process_sdp_a_dtls(value, p, p->trtp)) {
 				processed = TRUE;
+				if (p->tsrtp) {
+					ast_set_flag(p->tsrtp, AST_SRTP_CRYPTO_OFFER_OK);
+				}
 			}
 
 			break;
@@ -10576,7 +10585,11 @@
 					if (process_sdp_a_ice(value, p, p->rtp)) {
 						processed = TRUE;
 					} else if (process_sdp_a_dtls(value, p, p->rtp)) {
+						processed_crypto = TRUE;
 						processed = TRUE;
+						if (p->srtp) {
+							ast_set_flag(p->srtp, AST_SRTP_CRYPTO_OFFER_OK);
+						}
 					} else if (process_sdp_a_sendonly(value, &sendonly)) {
 						processed = TRUE;
 					} else if (!processed_crypto && process_crypto(p, p->rtp, &p->srtp, value)) {
@@ -10591,7 +10604,11 @@
 					if (process_sdp_a_ice(value, p, p->vrtp)) {
 						processed = TRUE;
 					} else if (process_sdp_a_dtls(value, p, p->vrtp)) {
+						processed_crypto = TRUE;
 						processed = TRUE;
+						if (p->vsrtp) {
+							ast_set_flag(p->vsrtp, AST_SRTP_CRYPTO_OFFER_OK);
+						}
 					} else if (!processed_crypto && process_crypto(p, p->vrtp, &p->vsrtp, value)) {
 						processed_crypto = TRUE;
 						processed = TRUE;
@@ -10742,7 +10759,7 @@
 	/* Setup audio address and port */
 	if (p->rtp) {
 		if (sa && portno > 0) {
-			start_ice(p->rtp);
+			start_ice(p->rtp, (req->method != SIP_RESPONSE) ? 0 : 1);
 			ast_sockaddr_set_port(sa, portno);
 			ast_rtp_instance_set_remote_address(p->rtp, sa);
 			if (debug) {
@@ -10790,7 +10807,7 @@
 	/* Setup video address and port */
 	if (p->vrtp) {
 		if (vsa && vportno > 0) {
-			start_ice(p->vrtp);
+			start_ice(p->vrtp, (req->method != SIP_RESPONSE) ? 0 : 1);
 			ast_sockaddr_set_port(vsa, vportno);
 			ast_rtp_instance_set_remote_address(p->vrtp, vsa);
 			if (debug) {
@@ -10808,7 +10825,7 @@
 	/* Setup text address and port */
 	if (p->trtp) {
 		if (tsa && tportno > 0) {
-			start_ice(p->trtp);
+			start_ice(p->trtp, (req->method != SIP_RESPONSE) ? 0 : 1);
 			ast_sockaddr_set_port(tsa, tportno);
 			ast_rtp_instance_set_remote_address(p->trtp, tsa);
 			if (debug) {
@@ -11137,7 +11154,7 @@
 {
 	struct ast_rtp_engine_dtls *dtls;
 	int found = FALSE;
-	char value[256], hash[6];
+	char value[256], hash[32];
 
 	if (!instance || !p->dtls_cfg.enabled || !(dtls = ast_rtp_instance_get_dtls(instance))) {
 		return found;
@@ -11169,11 +11186,13 @@
 			ast_log(LOG_WARNING, "Unsupported connection attribute value '%s' received on dialog '%s'\n",
 				value, p->callid);
 		}
-	} else if (sscanf(a, "fingerprint: %5s %255s", hash, value) == 2) {
+	} else if (sscanf(a, "fingerprint: %31s %255s", hash, value) == 2) {
 		found = TRUE;
 
 		if (!strcasecmp(hash, "sha-1")) {
 			dtls->set_fingerprint(instance, AST_RTP_DTLS_HASH_SHA1, value);
+		} else if (!strcasecmp(hash, "sha-256")) {
+			dtls->set_fingerprint(instance, AST_RTP_DTLS_HASH_SHA256, value);
 		} else {
 			ast_log(LOG_WARNING, "Unsupported fingerprint hash type '%s' received on dialog '%s'\n",
 				hash, p->callid);
@@ -12820,7 +12839,7 @@
 }
 
 /*! \brief Start ICE negotiation on an RTP instance */
-static void start_ice(struct ast_rtp_instance *instance)
+static void start_ice(struct ast_rtp_instance *instance, int offer)
 {
 	struct ast_rtp_engine_ice *ice = ast_rtp_instance_get_ice(instance);
 
@@ -12828,6 +12847,8 @@
 		return;
 	}
 
+	/* If we are the offerer then we are the controlling agent, otherwise they are */
+	ice->set_role(instance, offer ? AST_RTP_ICE_ROLE_CONTROLLING : AST_RTP_ICE_ROLE_CONTROLLED);
 	ice->start(instance);
 }
 
@@ -12835,6 +12856,7 @@
 static void add_dtls_to_sdp(struct ast_rtp_instance *instance, struct ast_str **a_buf)
 {
 	struct ast_rtp_engine_dtls *dtls;
+	enum ast_rtp_dtls_hash hash;
 	const char *fingerprint;
 
 	if (!instance || !(dtls = ast_rtp_instance_get_dtls(instance)) || !dtls->active(instance)) {
@@ -12869,8 +12891,11 @@
 		break;
 	}
 
-	if ((fingerprint = dtls->get_fingerprint(instance, AST_RTP_DTLS_HASH_SHA1))) {
-		ast_str_append(a_buf, 0, "a=fingerprint:SHA-1 %s\r\n", fingerprint);
+	hash = dtls->get_fingerprint_hash(instance);
+	fingerprint = dtls->get_fingerprint(instance);
+	if (fingerprint && (hash == AST_RTP_DTLS_HASH_SHA1 || hash == AST_RTP_DTLS_HASH_SHA256)) {
+		ast_str_append(a_buf, 0, "a=fingerprint:%s %s\r\n", hash == AST_RTP_DTLS_HASH_SHA1 ? "SHA-1" : "SHA-256",
+			fingerprint);
 	}
 }
 
@@ -13343,7 +13368,8 @@
 				ast_test_flag(&p->flags[2], SIP_PAGE3_SRTP_TAG_32));
 			ast_str_append(&m_video, 0, "m=video %d %s", ast_sockaddr_port(&vdest),
 				ast_sdp_get_rtp_profile(v_a_crypto ? 1 : 0, p->vrtp,
-					ast_test_flag(&p->flags[2], SIP_PAGE3_USE_AVPF)));
+					ast_test_flag(&p->flags[2], SIP_PAGE3_USE_AVPF),
+					ast_test_flag(&p->flags[2], SIP_PAGE3_FORCE_AVP)));
 
 			/* Build max bitrate string */
 			if (p->maxcallbitrate)
@@ -13370,7 +13396,8 @@
 				ast_test_flag(&p->flags[2], SIP_PAGE3_SRTP_TAG_32));
 			ast_str_append(&m_text, 0, "m=text %d %s", ast_sockaddr_port(&tdest),
 				ast_sdp_get_rtp_profile(t_a_crypto ? 1 : 0, p->trtp,
-					ast_test_flag(&p->flags[2], SIP_PAGE3_USE_AVPF)));
+					ast_test_flag(&p->flags[2], SIP_PAGE3_USE_AVPF),
+					ast_test_flag(&p->flags[2], SIP_PAGE3_FORCE_AVP)));
 			if (debug) {  /* XXX should I use tdest below ? */
 				ast_verbose("Text is at %s\n", ast_sockaddr_stringify(&taddr));
 			}
@@ -13393,7 +13420,8 @@
 			ast_test_flag(&p->flags[2], SIP_PAGE3_SRTP_TAG_32));
 		ast_str_append(&m_audio, 0, "m=audio %d %s", ast_sockaddr_port(&dest),
 			ast_sdp_get_rtp_profile(a_crypto ? 1 : 0, p->rtp,
-				ast_test_flag(&p->flags[2], SIP_PAGE3_USE_AVPF)));
+				ast_test_flag(&p->flags[2], SIP_PAGE3_USE_AVPF),
+				ast_test_flag(&p->flags[2], SIP_PAGE3_FORCE_AVP)));
 
 		/* Now, start adding audio codecs. These are added in this order:
 		   - First what was requested by the calling channel
@@ -30870,6 +30898,8 @@
 				ast_set2_flag(&peer->flags[2], ast_true(v->value), SIP_PAGE3_IGNORE_PREFCAPS);
 			} else if (!strcasecmp(v->name, "discard_remote_hold_retrieval")) {
 				ast_set2_flag(&peer->flags[2], ast_true(v->value), SIP_PAGE3_DISCARD_REMOTE_HOLD_RETRIEVAL);
+			} else if (!strcasecmp(v->name, "force_avp")) {
+				ast_set2_flag(&peer->flags[2], ast_true(v->value), SIP_PAGE3_FORCE_AVP);
 			} else {
 				ast_rtp_dtls_cfg_parse(&peer->dtls_cfg, v->name, v->value);
 			}

Modified: trunk/channels/sip/include/sip.h
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/sip/include/sip.h?view=diff&rev=417679&r1=417678&r2=417679
==============================================================================
--- trunk/channels/sip/include/sip.h (original)
+++ trunk/channels/sip/include/sip.h Mon Jun 30 14:51:28 2014
@@ -384,11 +384,12 @@
 #define SIP_PAGE3_ICE_SUPPORT            (1 << 6)  /*!< DGP: Enable ICE support */
 #define SIP_PAGE3_IGNORE_PREFCAPS        (1 << 7)  /*!< DP: Ignore prefcaps when setting up an outgoing call leg */
 #define SIP_PAGE3_DISCARD_REMOTE_HOLD_RETRIEVAL  (1 << 8)  /*!< DGP: Stop telling the peer to start music on hold */
+#define SIP_PAGE3_FORCE_AVP              (1 << 9)  /*!< DGP: Force 'RTP/AVP' for all streams, even DTLS */
 
 #define SIP_PAGE3_FLAGS_TO_COPY \
 	(SIP_PAGE3_SNOM_AOC | SIP_PAGE3_SRTP_TAG_32 | SIP_PAGE3_NAT_AUTO_RPORT | SIP_PAGE3_NAT_AUTO_COMEDIA | \
 	 SIP_PAGE3_DIRECT_MEDIA_OUTGOING | SIP_PAGE3_USE_AVPF | SIP_PAGE3_ICE_SUPPORT | SIP_PAGE3_IGNORE_PREFCAPS | \
-	 SIP_PAGE3_DISCARD_REMOTE_HOLD_RETRIEVAL)
+	 SIP_PAGE3_DISCARD_REMOTE_HOLD_RETRIEVAL | SIP_PAGE3_FORCE_AVP)
 
 #define CHECK_AUTH_BUF_INITLEN   256
 

Modified: trunk/configs/sip.conf.sample
URL: http://svnview.digium.com/svn/asterisk/trunk/configs/sip.conf.sample?view=diff&rev=417679&r1=417678&r2=417679
==============================================================================
--- trunk/configs/sip.conf.sample (original)
+++ trunk/configs/sip.conf.sample Mon Jun 30 14:51:28 2014
@@ -1046,6 +1046,8 @@
 ;avpf=yes                       ; Enable inter-operability with media streams using the AVPF RTP profile.
 				; This will cause all offers and answers to use AVPF (or SAVPF). This
 				; option may be specified at the global or peer scope.
+;force_avp=yes			; Force 'RTP/AVP', 'RTP/AVPF', 'RTP/SAVP', and 'RTP/SAVPF' to be used for
+				; media streams when appropriate, even if a DTLS stream is present.
 ;----------------------------------------- REALTIME SUPPORT ------------------------
 ; For additional information on ARA, the Asterisk Realtime Architecture,
 ; please read https://wiki.asterisk.org/wiki/display/AST/Realtime+Database+Configuration
@@ -1302,6 +1304,7 @@
 ; dtlscafile
 ; dtlscapath
 ; dtlssetup
+; dtlsfingerprint
 ; ignore_requested_pref ; Ignore the requested codec and determine the preferred codec
 ;						; from the peer's configuration.
 ;
@@ -1312,7 +1315,11 @@
 ; DTLS-SRTP support is available if the underlying RTP engine in use supports it.
 ;
 ; dtlsenable = yes                   ; Enable or disable DTLS-SRTP support
-; dtlsverify = yes                   ; Verify that the provided peer certificate is valid
+; dtlsverify = yes                   ; Verify that provided peer certificate and fingerprint are valid
+;				     ; A value of 'yes' will perform both certificate and fingerprint verification
+;				     ; A value of 'no' will perform no certificate or fingerprint verification
+;				     ; A value of 'fingerprint' will perform ONLY fingerprint verification
+;				     ; A value of 'certificate' will perform ONLY certficiate verification
 ; dtlsrekey = 60                     ; Interval at which to renegotiate the TLS session and rekey the SRTP session
 ;                                    ; If this is not set or the value provided is 0 rekeying will be disabled
 ; dtlscertfile = file                ; Path to certificate file to present
@@ -1327,6 +1334,7 @@
 ;                                    ; accept connections only), and actpass (we will do both). This value will be used in
 ;                                    ; the outgoing SDP when offering and for incoming SDP offers when the remote party sends
 ;                                    ; actpass
+; dtlsfingerprint = sha-1            ; The hash to use for the fingerprint in SDP (valid options are sha-1 and sha-256)
 
 ;[sip_proxy]
 ; For incoming calls only. Example: FWD (Free World Dialup)

Modified: trunk/include/asterisk/res_pjsip.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/res_pjsip.h?view=diff&rev=417679&r1=417678&r2=417679
==============================================================================
--- trunk/include/asterisk/res_pjsip.h (original)
+++ trunk/include/asterisk/res_pjsip.h Mon Jun 30 14:51:28 2014
@@ -473,6 +473,10 @@
 	unsigned int use_ptime;
 	/*! Do we use AVPF exclusively for this endpoint? */
 	unsigned int use_avpf;
+	/*! Do we force AVP, AVPF, SAVP, or SAVPF even for DTLS media streams? */
+	unsigned int force_avp;
+	/*! Do we use the received media transport in our answer SDP */
+	unsigned int use_received_transport;
 	/*! \brief DTLS-SRTP configuration information */
 	struct ast_rtp_dtls_cfg dtls_cfg;
 	/*! Should SRTP use a 32 byte tag instead of an 80 byte tag? */

Modified: trunk/include/asterisk/res_pjsip_session.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/res_pjsip_session.h?view=diff&rev=417679&r1=417678&r2=417679
==============================================================================
--- trunk/include/asterisk/res_pjsip_session.h (original)
+++ trunk/include/asterisk/res_pjsip_session.h Mon Jun 30 14:51:28 2014
@@ -73,6 +73,8 @@
 	struct ast_sip_session_sdp_handler *handler;
 	/*! \brief Holds SRTP information */
 	struct ast_sdp_srtp *srtp;
+	/*! \brief The media transport in use for this stream */
+	pj_str_t transport;
 	/*! \brief Stream is on hold */
 	unsigned int held:1;
 	/*! \brief Stream type this session media handles */

Modified: trunk/include/asterisk/rtp_engine.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/rtp_engine.h?view=diff&rev=417679&r1=417678&r2=417679
==============================================================================
--- trunk/include/asterisk/rtp_engine.h (original)
+++ trunk/include/asterisk/rtp_engine.h Mon Jun 30 14:51:28 2014
@@ -390,6 +390,12 @@
 	AST_RTP_ICE_COMPONENT_RTCP = 2,
 };
 
+/*! \brief ICE role during negotiation */
+enum ast_rtp_ice_role {
+	AST_RTP_ICE_ROLE_CONTROLLED,
+	AST_RTP_ICE_ROLE_CONTROLLING,
+};
+
 /*! \brief Structure for an ICE candidate */
 struct ast_rtp_engine_ice_candidate {
 	char *foundation;                     /*!< Foundation identifier */
@@ -419,6 +425,8 @@
 	struct ao2_container *(*get_local_candidates)(struct ast_rtp_instance *instance);
 	/*! Callback for telling the ICE support that it is talking to an ice-lite implementation */
 	void (*ice_lite)(struct ast_rtp_instance *instance);
+	/*! Callback for changing our role in negotiation */
+	void (*set_role)(struct ast_rtp_instance *instance, enum ast_rtp_ice_role role);
 };
 
 /*! \brief DTLS setup types */
@@ -431,22 +439,31 @@
 
 /*! \brief DTLS connection states */
 enum ast_rtp_dtls_connection {
-        AST_RTP_DTLS_CONNECTION_NEW,      /*!< Endpoint wants to use a new connection */
+	AST_RTP_DTLS_CONNECTION_NEW,      /*!< Endpoint wants to use a new connection */
 	AST_RTP_DTLS_CONNECTION_EXISTING, /*!< Endpoint wishes to use existing connection */
 };
 
 /*! \brief DTLS fingerprint hashes */
 enum ast_rtp_dtls_hash {
-	AST_RTP_DTLS_HASH_SHA1, /*!< SHA-1 fingerprint hash */
+	AST_RTP_DTLS_HASH_SHA256, /*!< SHA-256 fingerprint hash */
+	AST_RTP_DTLS_HASH_SHA1,   /*!< SHA-1 fingerprint hash */
+};
+
+/*! \brief DTLS verification settings */
+enum ast_rtp_dtls_verify {
+	AST_RTP_DTLS_VERIFY_NONE = 0,               /*!< Don't verify anything */
+	AST_RTP_DTLS_VERIFY_FINGERPRINT = (1 << 0), /*!< Verify the fingerprint */
+	AST_RTP_DTLS_VERIFY_CERTIFICATE = (1 << 1), /*!< Verify the certificate */
 };
 
 /*! \brief DTLS configuration structure */
 struct ast_rtp_dtls_cfg {
 	unsigned int enabled:1;                /*!< Whether DTLS support is enabled or not */
-	unsigned int verify:1;                 /*!< Whether to request and verify a client certificate when acting as server */
 	unsigned int rekey;                    /*!< Interval at which to renegotiate and rekey - defaults to 0 (off) */
 	enum ast_rtp_dtls_setup default_setup; /*!< Default setup type to use for outgoing */
 	enum ast_srtp_suite suite;             /*!< Crypto suite in use */
+	enum ast_rtp_dtls_hash hash;		   /*!< Hash to use for fingerprint */
+	enum ast_rtp_dtls_verify verify;	   /*!< What should be verified */
 	char *certfile;                        /*!< Certificate file */
 	char *pvtfile;                         /*!< Private key file */
 	char *cipher;                          /*!< Cipher to use */
@@ -472,8 +489,10 @@
 	void (*set_setup)(struct ast_rtp_instance *instance, enum ast_rtp_dtls_setup setup);
 	/*! Set the remote fingerprint */
 	void (*set_fingerprint)(struct ast_rtp_instance *instance, enum ast_rtp_dtls_hash hash, const char *fingerprint);
+	/*! Get the local fingerprint hash type */
+	enum ast_rtp_dtls_hash (*get_fingerprint_hash)(struct ast_rtp_instance *instance);
 	/*! Get the local fingerprint */
-	const char *(*get_fingerprint)(struct ast_rtp_instance *instance, enum ast_rtp_dtls_hash hash);
+	const char *(*get_fingerprint)(struct ast_rtp_instance *instance);
 };
 
 /*! Structure that represents an RTP stack (engine) */

Modified: trunk/include/asterisk/sdp_srtp.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/sdp_srtp.h?view=diff&rev=417679&r1=417678&r2=417679
==============================================================================
--- trunk/include/asterisk/sdp_srtp.h (original)
+++ trunk/include/asterisk/sdp_srtp.h Mon Jun 30 14:51:28 2014
@@ -118,8 +118,10 @@
  * \param sdes_active Whether the media session is using SDES-SRTP
  * \param instance The RTP instance associated with this media session
  * \param using_avpf Whether the media session is using early feedback (AVPF)
+ * \param force_avp Force SAVP or SAVPF profile when DTLS is in use
  *
  * \retval A non-allocated string describing the profile in use (does not need to be freed)
  */
-char *ast_sdp_get_rtp_profile(unsigned int sdes_active, struct ast_rtp_instance *instance, unsigned int using_avpf);
+char *ast_sdp_get_rtp_profile(unsigned int sdes_active, struct ast_rtp_instance *instance, unsigned int using_avpf,
+	unsigned int force_avp);
 #endif	/* _SDP_CRYPTO_H */

Modified: trunk/main/rtp_engine.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/rtp_engine.c?view=diff&rev=417679&r1=417678&r2=417679
==============================================================================
--- trunk/main/rtp_engine.c (original)
+++ trunk/main/rtp_engine.c Mon Jun 30 14:51:28 2014
@@ -1556,7 +1556,17 @@
 	if (!strcasecmp(name, "dtlsenable")) {
 		dtls_cfg->enabled = ast_true(value) ? 1 : 0;
 	} else if (!strcasecmp(name, "dtlsverify")) {
-		dtls_cfg->verify = ast_true(value) ? 1 : 0;
+		if (!strcasecmp(value, "yes")) {
+			dtls_cfg->verify = AST_RTP_DTLS_VERIFY_FINGERPRINT | AST_RTP_DTLS_VERIFY_CERTIFICATE;
+		} else if (!strcasecmp(value, "fingerprint")) {
+			dtls_cfg->verify = AST_RTP_DTLS_VERIFY_FINGERPRINT;
+		} else if (!strcasecmp(value, "certificate")) {
+			dtls_cfg->verify = AST_RTP_DTLS_VERIFY_CERTIFICATE;
+		} else if (!strcasecmp(value, "no")) {
+			dtls_cfg->verify = AST_RTP_DTLS_VERIFY_NONE;
+		} else {
+			return -1;
+		}
 	} else if (!strcasecmp(name, "dtlsrekey")) {
 		if (sscanf(value, "%30u", &dtls_cfg->rekey) != 1) {
 			return -1;
@@ -1584,6 +1594,12 @@
 		} else if (!strcasecmp(value, "actpass")) {
 			dtls_cfg->default_setup = AST_RTP_DTLS_SETUP_ACTPASS;
 		}
+	} else if (!strcasecmp(name, "dtlsfingerprint")) {
+		if (!strcasecmp(value, "sha-256")) {
+			dtls_cfg->hash = AST_RTP_DTLS_HASH_SHA256;
+		} else if (!strcasecmp(value, "sha-1")) {
+			dtls_cfg->hash = AST_RTP_DTLS_HASH_SHA1;
+		}
 	} else {
 		return -1;
 	}
@@ -1597,6 +1613,7 @@
 	dst_cfg->verify = src_cfg->verify;
 	dst_cfg->rekey = src_cfg->rekey;
 	dst_cfg->suite = src_cfg->suite;
+	dst_cfg->hash = src_cfg->hash;
 	dst_cfg->certfile = ast_strdup(src_cfg->certfile);
 	dst_cfg->pvtfile = ast_strdup(src_cfg->pvtfile);
 	dst_cfg->cipher = ast_strdup(src_cfg->cipher);

Modified: trunk/main/sdp_srtp.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/sdp_srtp.c?view=diff&rev=417679&r1=417678&r2=417679
==============================================================================
--- trunk/main/sdp_srtp.c (original)
+++ trunk/main/sdp_srtp.c Mon Jun 30 14:51:28 2014
@@ -365,12 +365,17 @@
 	return NULL;
 }
 
-char *ast_sdp_get_rtp_profile(unsigned int sdes_active, struct ast_rtp_instance *instance, unsigned int using_avpf)
+char *ast_sdp_get_rtp_profile(unsigned int sdes_active, struct ast_rtp_instance *instance, unsigned int using_avpf,
+	unsigned int force_avp)
 {
 	struct ast_rtp_engine_dtls *dtls;
 
 	if ((dtls = ast_rtp_instance_get_dtls(instance)) && dtls->active(instance)) {
-		return using_avpf ? "UDP/TLS/RTP/SAVPF" : "UDP/TLS/RTP/SAVP";
+		if (force_avp) {
+			return using_avpf ? "RTP/SAVPF" : "RTP/SAVP";
+		} else {
+			return using_avpf ? "UDP/TLS/RTP/SAVPF" : "UDP/TLS/RTP/SAVP";
+		}
 	} else {
 		if (using_avpf) {
 			return sdes_active ? "RTP/SAVPF" : "RTP/AVPF";

Modified: trunk/res/res_pjsip.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/res_pjsip.c?view=diff&rev=417679&r1=417678&r2=417679
==============================================================================
--- trunk/res/res_pjsip.c (original)
+++ trunk/res/res_pjsip.c Mon Jun 30 14:51:28 2014
@@ -388,6 +388,28 @@
 						profile for all media offers on outbound calls and media updates, but will
 						accept either the AVP/AVPF or SAVP/SAVPF RTP profile for all inbound
 						media offers.
+					</para></description>
+				</configOption>
+				<configOption name="force_avp" default="no">
+					<synopsis>Determines whether res_pjsip will use and enforce usage of AVP,
+					regardless of the RTP profile in use for this endpoint.</synopsis>
+					<description><para>
+						If set to <literal>yes</literal>, res_pjsip will use the AVP, AVPF, SAVP, or
+						SAVPF RTP profile for all media offers on outbound calls and media updates including
+						those for DTLS-SRTP streams.
+					</para><para>
+						If set to <literal>no</literal>, res_pjsip will use the respective RTP profile
+						depending on configuration.
+					</para></description>
+				</configOption>
+				<configOption name="media_use_received_transport" default="no">
+					<synopsis>Determines whether res_pjsip will use the media transport received in the
+					offer SDP in the corresponding answer SDP.</synopsis>
+					<description><para>
+						If set to <literal>yes</literal>, res_pjsip will use the received media transport.
+					</para><para>
+						If set to <literal>no</literal>, res_pjsip will use the respective RTP profile
+						depending on configuration.
 					</para></description>
 				</configOption>
 				<configOption name="media_encryption" default="no">

Modified: trunk/res/res_pjsip/pjsip_configuration.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/res_pjsip/pjsip_configuration.c?view=diff&rev=417679&r1=417678&r2=417679
==============================================================================
--- trunk/res/res_pjsip/pjsip_configuration.c (original)
+++ trunk/res/res_pjsip/pjsip_configuration.c Mon Jun 30 14:51:28 2014
@@ -1686,6 +1686,8 @@
 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "aggregate_mwi", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, subscription.mwi.aggregate));
 	ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "media_encryption", "no", media_encryption_handler, media_encryption_to_str, NULL, 0, 0);
 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "use_avpf", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.use_avpf));
+	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "force_avp", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.force_avp));
+	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "media_use_received_transport", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.use_received_transport));
 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "one_touch_recording", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, info.recording.enabled));
 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "inband_progress", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, inband_progress));
 	ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "call_group", "", group_handler, callgroup_to_str, NULL, 0, 0);

Modified: trunk/res/res_pjsip_sdp_rtp.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/res_pjsip_sdp_rtp.c?view=diff&rev=417679&r1=417678&r2=417679
==============================================================================
--- trunk/res/res_pjsip_sdp_rtp.c (original)
+++ trunk/res/res_pjsip_sdp_rtp.c Mon Jun 30 14:51:28 2014
@@ -390,14 +390,26 @@
 		return;
 	}
 
-	if ((attr = pjmedia_sdp_media_find_attr2(remote_stream, "ice-ufrag", NULL))) {
+	attr = pjmedia_sdp_media_find_attr2(remote_stream, "ice-ufrag", NULL);
+	if (!attr) {
+		attr = pjmedia_sdp_attr_find2(remote->attr_count, remote->attr, "ice-ufrag", NULL);
+	}
+	if (attr) {
 		ast_copy_pj_str(attr_value, (pj_str_t*)&attr->value, sizeof(attr_value));
 		ice->set_authentication(session_media->rtp, attr_value, NULL);
-	}
-
-	if ((attr = pjmedia_sdp_media_find_attr2(remote_stream, "ice-pwd", NULL))) {
+	} else {
+		return;
+	}
+
+	attr = pjmedia_sdp_media_find_attr2(remote_stream, "ice-pwd", NULL);
+	if (!attr) {
+		pjmedia_sdp_attr_find2(remote->attr_count, remote->attr, "ice-pwd", NULL);
+	}
+	if (attr) {
 		ast_copy_pj_str(attr_value, (pj_str_t*)&attr->value, sizeof(attr_value));
 		ice->set_authentication(session_media->rtp, NULL, attr_value);
+	} else {
+		return;
 	}
 
 	if (pjmedia_sdp_media_find_attr2(remote_stream, "ice-lite", NULL)) {
@@ -452,6 +464,8 @@
 		ice->add_remote_candidate(session_media->rtp, &candidate);
 	}
 
+	ice->set_role(session_media->rtp, pjmedia_sdp_neg_was_answer_remote(session->inv_session->neg) == PJ_TRUE ?
+		AST_RTP_ICE_ROLE_CONTROLLING : AST_RTP_ICE_ROLE_CONTROLLED);
 	ice->start(session_media->rtp);
 }
 
@@ -526,6 +540,10 @@
 	incoming_encryption = get_media_encryption_type(stream->desc.transport);
 
 	if (incoming_encryption == endpoint->media.rtp.encryption) {
+		return incoming_encryption;
+	}
+
+	if (endpoint->media.rtp.force_avp) {
 		return incoming_encryption;
 	}
 
@@ -615,13 +633,15 @@
 				ast_log(LOG_WARNING, "Unsupported connection attribute value '%*s'\n", (int)value->slen, value->ptr);
 			}
 		} else if (!pj_strcmp2(&attr->name, "fingerprint")) {
-			char hash_value[256], hash[6];
+			char hash_value[256], hash[32];
 			char fingerprint_text[value->slen + 1];
 			ast_copy_pj_str(fingerprint_text, value, sizeof(fingerprint_text));
 
-			if (sscanf(fingerprint_text, "%5s %255s", hash, hash_value) == 2) {
+			if (sscanf(fingerprint_text, "%31s %255s", hash, hash_value) == 2) {
 				if (!strcasecmp(hash, "sha-1")) {
 					dtls->set_fingerprint(session_media->rtp, AST_RTP_DTLS_HASH_SHA1, hash_value);
+				} else if (!strcasecmp(hash, "sha-256")) {
+					dtls->set_fingerprint(session_media->rtp, AST_RTP_DTLS_HASH_SHA256, hash_value);
 				} else {
 					ast_log(LOG_WARNING, "Unsupported fingerprint hash type '%s'\n",
 					hash);
@@ -710,7 +730,8 @@
 	}
 
 	/* Ensure incoming transport is compatible with the endpoint's configuration */
-	if (check_endpoint_media_transport(session->endpoint, stream) == AST_SIP_MEDIA_TRANSPORT_INVALID) {
+	if (!session->endpoint->media.rtp.use_received_transport &&
+		check_endpoint_media_transport(session->endpoint, stream) == AST_SIP_MEDIA_TRANSPORT_INVALID) {
 		return -1;
 	}
 
@@ -727,6 +748,10 @@
 		return -1;
 	}
 
+	if (session->endpoint->media.rtp.use_received_transport) {
+		pj_strdup(session->inv_session->pool, &session_media->transport, &stream->desc.transport);
+	}
+
 	if (setup_media_encryption(session, session_media, stream)) {
 		return -1;
 	}
@@ -748,6 +773,7 @@
 {
 	pj_str_t stmp;
 	pjmedia_sdp_attr *attr;
+	enum ast_rtp_dtls_hash hash;
 	const char *crypto_attribute;
 	struct ast_rtp_engine_dtls *dtls;
 	static const pj_str_t STR_NEW = { "new", 3 };
@@ -824,13 +850,19 @@
 			break;
 		}
 
-		if ((crypto_attribute = dtls->get_fingerprint(session_media->rtp, AST_RTP_DTLS_HASH_SHA1))) {
+		hash = dtls->get_fingerprint_hash(session_media->rtp);
+		crypto_attribute = dtls->get_fingerprint(session_media->rtp);
+		if (crypto_attribute && (hash == AST_RTP_DTLS_HASH_SHA1 || hash == AST_RTP_DTLS_HASH_SHA256)) {
 			RAII_VAR(struct ast_str *, fingerprint, ast_str_create(64), ast_free);
 			if (!fingerprint) {
 				return -1;
 			}
 
-			ast_str_set(&fingerprint, 0, "SHA-1 %s", crypto_attribute);
+			if (hash == AST_RTP_DTLS_HASH_SHA1) {
+				ast_str_set(&fingerprint, 0, "SHA-1 %s", crypto_attribute);
+			} else {
+				ast_str_set(&fingerprint, 0, "SHA-256 %s", crypto_attribute);
+			}
 
 			attr = pjmedia_sdp_attr_create(pool, "fingerprint", pj_cstr(&stmp, ast_str_buffer(fingerprint)));
 			media->attr[media->attr_count++] = attr;
@@ -889,9 +921,14 @@
 	}
 
 	media->desc.media = pj_str(session_media->stream_type);
-	media->desc.transport = pj_str(ast_sdp_get_rtp_profile(
-		session->endpoint->media.rtp.encryption == AST_SIP_MEDIA_ENCRYPT_SDES,
-		session_media->rtp, session->endpoint->media.rtp.use_avpf));
+	if (session->endpoint->media.rtp.use_received_transport && pj_strlen(&session_media->transport)) {
+		media->desc.transport = session_media->transport;
+	} else {
+		media->desc.transport = pj_str(ast_sdp_get_rtp_profile(
+			session->endpoint->media.rtp.encryption == AST_SIP_MEDIA_ENCRYPT_SDES,
+			session_media->rtp, session->endpoint->media.rtp.use_avpf,
+			session->endpoint->media.rtp.force_avp));
+	}
 
 	/* Add connection level details */
 	if (direct_media_enabled) {
@@ -1033,7 +1070,8 @@
 	}
 
 	/* Ensure incoming transport is compatible with the endpoint's configuration */
-	if (check_endpoint_media_transport(session->endpoint, remote_stream) == AST_SIP_MEDIA_TRANSPORT_INVALID) {
+	if (!session->endpoint->media.rtp.use_received_transport &&
+		check_endpoint_media_transport(session->endpoint, remote_stream) == AST_SIP_MEDIA_TRANSPORT_INVALID) {
 		return -1;
 	}
 

Modified: trunk/res/res_rtp_asterisk.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/res_rtp_asterisk.c?view=diff&rev=417679&r1=417678&r2=417679
==============================================================================
--- trunk/res/res_rtp_asterisk.c (original)
+++ trunk/res/res_rtp_asterisk.c Mon Jun 30 14:51:28 2014
@@ -180,6 +180,16 @@
 	int max_seq;	/*!< The highest sequence number received */
 	int packets;	/*!< The number of remaining packets before the source is accepted */
 };
+
+#ifdef HAVE_OPENSSL_SRTP
+struct dtls_details {
+	SSL *ssl;         /*!< SSL session */
+	BIO *read_bio;    /*!< Memory buffer for reading */
+	BIO *write_bio;   /*!< Memory buffer for writing */
+	enum ast_rtp_dtls_setup dtls_setup; /*!< Current setup state */
+	enum ast_rtp_dtls_connection connection; /*!< Whether this is a new or existing connection */
+};
+#endif
 
 /*! \brief RTP session description */
 struct ast_rtp {
@@ -280,19 +290,17 @@
 
 #ifdef HAVE_OPENSSL_SRTP
 	SSL_CTX *ssl_ctx; /*!< SSL context */
-	SSL *ssl;         /*!< SSL session */
-	BIO *read_bio;    /*!< Memory buffer for reading */
-	BIO *write_bio;   /*!< Memory buffer for writing */
 	ast_mutex_t dtls_timer_lock;           /*!< Lock for synchronization purposes */
-	enum ast_rtp_dtls_setup dtls_setup; /*!< Current setup state */
+	enum ast_rtp_dtls_verify dtls_verify; /*!< What to verify */
 	enum ast_srtp_suite suite;   /*!< SRTP crypto suite */
+	enum ast_rtp_dtls_hash local_hash; /*!< Local hash used for the fingerprint */
 	char local_fingerprint[160]; /*!< Fingerprint of our certificate */
+	enum ast_rtp_dtls_hash remote_hash; /*!< Remote hash used for the fingerprint */
 	unsigned char remote_fingerprint[EVP_MAX_MD_SIZE]; /*!< Fingerprint of the peer certificate */
-	enum ast_rtp_dtls_connection connection; /*!< Whether this is a new or existing connection */
-	unsigned int dtls_failure:1; /*!< Failure occurred during DTLS negotiation */
 	unsigned int rekey; /*!< Interval at which to renegotiate and rekey */
 	int rekeyid; /*!< Scheduled item id for rekeying */
 	int dtlstimerid; /*!< Scheduled item id for DTLS retransmission for RTP */
+	struct dtls_details dtls; /*!< DTLS state information */
 #endif
 };
 
@@ -358,6 +366,10 @@
 
 	/* VP8: sequence number for the RTCP FIR FCI */
 	int firseq;
+
+#ifdef HAVE_OPENSSL_SRTP
+	struct dtls_details dtls; /*!< DTLS state information */
+#endif
 };
 
 struct rtp_red {
@@ -404,7 +416,7 @@
 
 #ifdef HAVE_OPENSSL_SRTP
 static int ast_rtp_activate(struct ast_rtp_instance *instance);
-static void dtls_srtp_check_pending(struct ast_rtp_instance *instance, struct ast_rtp *rtp);
+static void dtls_srtp_check_pending(struct ast_rtp_instance *instance, struct ast_rtp *rtp, int rtcp);
 #endif
 
 static int __rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int rtcp, int *ice, int use_srtp);
@@ -542,9 +554,18 @@
 static int ice_reset_session(struct ast_rtp_instance *instance)
 {
 	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+	pj_ice_sess_role role = rtp->ice->role;
+	int res;
 
 	ast_rtp_ice_stop(instance);
-	return ice_create(instance, &rtp->ice_original_rtp_addr, rtp->ice_port, 1);
+
+	res = ice_create(instance, &rtp->ice_original_rtp_addr, rtp->ice_port, 1);
+	if (!res) {
+		/* Preserve the role that the old ICE session used */
+		pj_ice_sess_change_role(rtp->ice, role);
+	}
+
+	return res;
 }
 
 static int ice_candidates_compare(struct ao2_container *left, struct ao2_container *right)
@@ -699,6 +720,20 @@
 	pj_thread_register_check();
 
 	pj_ice_sess_change_role(rtp->ice, PJ_ICE_SESS_ROLE_CONTROLLING);
+}
+
+static void ast_rtp_ice_set_role(struct ast_rtp_instance *instance, enum ast_rtp_ice_role role)
+{
+	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+
+	if (!rtp->ice) {
+		return;
+	}
+
+	pj_thread_register_check();
+
+	pj_ice_sess_change_role(rtp->ice, role == AST_RTP_ICE_ROLE_CONTROLLED ?
+		PJ_ICE_SESS_ROLE_CONTROLLED : PJ_ICE_SESS_ROLE_CONTROLLING);
 }
 
 static void ast_rtp_ice_add_cand(struct ast_rtp *rtp, unsigned comp_id, unsigned transport_id, pj_ice_cand_type type, pj_uint16_t local_pref,
@@ -781,25 +816,83 @@
 	.get_password = ast_rtp_ice_get_password,
 	.get_local_candidates = ast_rtp_ice_get_local_candidates,
 	.ice_lite = ast_rtp_ice_lite,
+	.set_role = ast_rtp_ice_set_role,
 };
 #endif
 
 #ifdef HAVE_OPENSSL_SRTP
-static void dtls_info_callback(const SSL *ssl, int where, int ret)
-{
-	struct ast_rtp *rtp = SSL_get_ex_data(ssl, 0);
-
-	/* We only care about alerts */
-	if (!(where & SSL_CB_ALERT)) {
-		return;
-	}
-
-	rtp->dtls_failure = 1;
+static int dtls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
+{
+	/* We don't want to actually verify the certificate so just accept what they have provided */
+	return 1;
+}
+
+static int dtls_details_initialize(struct dtls_details *dtls, SSL_CTX *ssl_ctx,
+	enum ast_rtp_dtls_setup setup)
+{
+	dtls->dtls_setup = setup;
+
+	if (!(dtls->ssl = SSL_new(ssl_ctx))) {
+		ast_log(LOG_ERROR, "Failed to allocate memory for SSL\n");
+		goto error;
+	}
+
+	if (!(dtls->read_bio = BIO_new(BIO_s_mem()))) {
+		ast_log(LOG_ERROR, "Failed to allocate memory for inbound SSL traffic\n");
+		goto error;
+	}
+	BIO_set_mem_eof_return(dtls->read_bio, -1);
+
+	if (!(dtls->write_bio = BIO_new(BIO_s_mem()))) {
+		ast_log(LOG_ERROR, "Failed to allocate memory for outbound SSL traffic\n");
+		goto error;
+	}
+	BIO_set_mem_eof_return(dtls->write_bio, -1);
+
+	SSL_set_bio(dtls->ssl, dtls->read_bio, dtls->write_bio);
+
+	if (dtls->dtls_setup == AST_RTP_DTLS_SETUP_PASSIVE) {
+		SSL_set_accept_state(dtls->ssl);
+	} else {
+		SSL_set_connect_state(dtls->ssl);
+	}
+	dtls->connection = AST_RTP_DTLS_CONNECTION_NEW;
+
+	return 0;
+
+error:
+	if (dtls->read_bio) {
+		BIO_free(dtls->read_bio);
+		dtls->read_bio = NULL;
+	}
+
+	if (dtls->write_bio) {
+		BIO_free(dtls->write_bio);
+		dtls->write_bio = NULL;
+	}
+
+	if (dtls->ssl) {
+		SSL_free(dtls->ssl);
+		dtls->ssl = NULL;
+	}
+	return -1;
+}
+
+static int dtls_setup_rtcp(struct ast_rtp_instance *instance)
+{
+	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+
+	if (!rtp->ssl_ctx || !rtp->rtcp) {
+		return 0;
+	}
+
+	return dtls_details_initialize(&rtp->rtcp->dtls, rtp->ssl_ctx, rtp->dtls.dtls_setup);
 }
 
 static int ast_rtp_dtls_set_configuration(struct ast_rtp_instance *instance, const struct ast_rtp_dtls_cfg *dtls_cfg)
 {
 	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+	int res;
 
 	if (!dtls_cfg->enabled) {
 		return 0;
@@ -813,7 +906,11 @@
 		return -1;
 	}
 
-	SSL_CTX_set_verify(rtp->ssl_ctx, dtls_cfg->verify ? SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT : SSL_VERIFY_NONE, NULL);
+	rtp->dtls_verify = dtls_cfg->verify;
+
+	SSL_CTX_set_verify(rtp->ssl_ctx, (rtp->dtls_verify & AST_RTP_DTLS_VERIFY_FINGERPRINT) || (rtp->dtls_verify & AST_RTP_DTLS_VERIFY_CERTIFICATE) ?
+		SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT : SSL_VERIFY_NONE, !(rtp->dtls_verify & AST_RTP_DTLS_VERIFY_CERTIFICATE) ?
+		dtls_verify_callback : NULL);
 
 	if (dtls_cfg->suite == AST_AES_CM_128_HMAC_SHA1_80) {
 		SSL_CTX_set_tlsext_use_srtp(rtp->ssl_ctx, "SRTP_AES128_CM_SHA1_80");
@@ -821,13 +918,16 @@
 		SSL_CTX_set_tlsext_use_srtp(rtp->ssl_ctx, "SRTP_AES128_CM_SHA1_32");
 	} else {
 		ast_log(LOG_ERROR, "Unsupported suite specified for DTLS-SRTP on RTP instance '%p'\n", instance);
-		goto error;
-	}
+		return -1;
+	}
+
+	rtp->local_hash = dtls_cfg->hash;
 
 	if (!ast_strlen_zero(dtls_cfg->certfile)) {
 		char *private = ast_strlen_zero(dtls_cfg->pvtfile) ? dtls_cfg->certfile : dtls_cfg->pvtfile;
 		BIO *certbio;
 		X509 *cert;
+		const EVP_MD *type;
 		unsigned int size, i;
 		unsigned char fingerprint[EVP_MAX_MD_SIZE];
 		char *local_fingerprint = rtp->local_fingerprint;
@@ -835,30 +935,40 @@
 		if (!SSL_CTX_use_certificate_file(rtp->ssl_ctx, dtls_cfg->certfile, SSL_FILETYPE_PEM)) {
 			ast_log(LOG_ERROR, "Specified certificate file '%s' for RTP instance '%p' could not be used\n",
 				dtls_cfg->certfile, instance);
-			goto error;
+			return -1;
 		}
 
 		if (!SSL_CTX_use_PrivateKey_file(rtp->ssl_ctx, private, SSL_FILETYPE_PEM) ||
 		    !SSL_CTX_check_private_key(rtp->ssl_ctx)) {
 			ast_log(LOG_ERROR, "Specified private key file '%s' for RTP instance '%p' could not be used\n",
 				private, instance);
-			goto error;
+			return -1;
 		}
 
 		if (!(certbio = BIO_new(BIO_s_file()))) {

[... 685 lines stripped ...]



More information about the asterisk-commits mailing list