Review Board 1.7.16


WebRTC: Add SHA-256 support, change DTLS-SRTP negotiation, add finer grain control of things.

Review Request #3679 - Created June 26, 2014 and submitted

Joshua Colp
sha256-a-harsh-reality
ASTERISK-22961, ASTERISK-23026
Reviewers
asterisk-dev
Asterisk
This change does the following:

1. Adds SHA-256 support for DTLS-SRTP. This is done in an extensible way so if we need to add other hashes it should be relatively easy to.
2. Adds the ability to force "AVP" for DTLS streams for greater interoperability.
3. Sets the ICE role to controlled or controlling depending on offer/answer.
4. Provides the ability to verify only fingerprint, certificate, or both.
5. Adds DTLS negotiation to RTCP.
6. Changes DTLS negotiation to occur after ICE negotiation completes.
7. Adds handling of DTLS traffic before ICE negotiation has formally completed.
Tested inbound and outbound calls against:

Chrome
Yandex Browser
Opera
Maxthon
Firefox

Note that hold/unhold only currently works against Chrome based browsers.

Diff revision 2

This is not the most recent revision of the diff. The latest diff is revision 3. See what's changed.

1 2 3
1 2 3

  1. /channels/chan_sip.c: Loading...
  2. /channels/sip/include/sip.h: Loading...
  3. /configs/sip.conf.sample: Loading...
  4. /include/asterisk/rtp_engine.h: Loading...
  5. /main/rtp_engine.c: Loading...
  6. /res/res_rtp_asterisk.c: Loading...
/branches/11/channels/chan_sip.c /channels/chan_sip.c
Revision 417585 New Change
[20] 1384 lines
[+20] [+] static int process_sdp_a_dtls(const char *a, struct sip_pvt *p, struct ast_rtp_instance *instance);
1385
static int process_sdp_a_video(const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newvideortp, int *last_rtpmap_codec);
1385
static int process_sdp_a_video(const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newvideortp, int *last_rtpmap_codec);
1386
static int process_sdp_a_text(const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newtextrtp, char *red_fmtp, int *red_num_gen, int *red_data_pt, int *last_rtpmap_codec);
1386
static int process_sdp_a_text(const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newtextrtp, char *red_fmtp, int *red_num_gen, int *red_data_pt, int *last_rtpmap_codec);
1387
static int process_sdp_a_image(const char *a, struct sip_pvt *p);
1387
static int process_sdp_a_image(const char *a, struct sip_pvt *p);
1388
static void add_ice_to_sdp(struct ast_rtp_instance *instance, struct ast_str **a_buf);
1388
static void add_ice_to_sdp(struct ast_rtp_instance *instance, struct ast_str **a_buf);
1389
static void add_dtls_to_sdp(struct ast_rtp_instance *instance, struct ast_str **a_buf);
1389
static void add_dtls_to_sdp(struct ast_rtp_instance *instance, struct ast_str **a_buf);
1390
static void start_ice(struct ast_rtp_instance *instance);
1390
static void start_ice(struct ast_rtp_instance *instance, int offer);
1391
static void add_codec_to_sdp(const struct sip_pvt *p, struct ast_format *codec,
1391
static void add_codec_to_sdp(const struct sip_pvt *p, struct ast_format *codec,
1392
			     struct ast_str **m_buf, struct ast_str **a_buf,
1392
			     struct ast_str **m_buf, struct ast_str **a_buf,
1393
			     int debug, int *min_packet_size);
1393
			     int debug, int *min_packet_size);
1394
static void add_noncodec_to_sdp(const struct sip_pvt *p, int format,
1394
static void add_noncodec_to_sdp(const struct sip_pvt *p, int format,
1395
				struct ast_str **m_buf, struct ast_str **a_buf,
1395
				struct ast_str **m_buf, struct ast_str **a_buf,
[+20] [20] 8656 lines
[+20] [+] static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action)
10052
				processed = TRUE;
10052
				processed = TRUE;
10053
			}
10053
			}
10054

    
   
10054

   
10055
			if (process_sdp_a_dtls(value, p, p->rtp)) {
10055
			if (process_sdp_a_dtls(value, p, p->rtp)) {
10056
				processed = TRUE;
10056
				processed = TRUE;

    
   
10057
				if (p->srtp) {

    
   
10058
					ast_set_flag(p->srtp, SRTP_CRYPTO_OFFER_OK);

    
   
10059
				}
10057
			}
10060
			}
10058
			if (process_sdp_a_dtls(value, p, p->vrtp)) {
10061
			if (process_sdp_a_dtls(value, p, p->vrtp)) {
10059
				processed = TRUE;
10062
				processed = TRUE;

    
   
10063
				if (p->vsrtp) {

    
   
10064
					ast_set_flag(p->vsrtp, SRTP_CRYPTO_OFFER_OK);

    
   
10065
				}
10060
			}
10066
			}
10061
			if (process_sdp_a_dtls(value, p, p->trtp)) {
10067
			if (process_sdp_a_dtls(value, p, p->trtp)) {
10062
				processed = TRUE;
10068
				processed = TRUE;

    
   
10069
				if (p->tsrtp) {

    
   
10070
					ast_set_flag(p->tsrtp, SRTP_CRYPTO_OFFER_OK);

    
   
10071
				}
10063
			}
10072
			}
10064

    
   
10073

   
10065
			break;
10074
			break;
10066
		}
10075
		}
10067

    
   
10076

   
[+20] [20] 395 lines
[+20] static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action)
10463
				/* Audio specific scanning */
10472
				/* Audio specific scanning */
10464
				if (audio) {
10473
				if (audio) {
10465
					if (process_sdp_a_ice(value, p, p->rtp)) {
10474
					if (process_sdp_a_ice(value, p, p->rtp)) {
10466
						processed = TRUE;
10475
						processed = TRUE;
10467
					} else if (process_sdp_a_dtls(value, p, p->rtp)) {
10476
					} else if (process_sdp_a_dtls(value, p, p->rtp)) {

    
   
10477
						processed_crypto = TRUE;
10468
						processed = TRUE;
10478
						processed = TRUE;

    
   
10479
						if (p->srtp) {

    
   
10480
							ast_set_flag(p->srtp, SRTP_CRYPTO_OFFER_OK);

    
   
10481
						}
10469
					} else if (process_sdp_a_sendonly(value, &sendonly)) {
10482
					} else if (process_sdp_a_sendonly(value, &sendonly)) {
10470
						processed = TRUE;
10483
						processed = TRUE;
10471
					} else if (!processed_crypto && process_crypto(p, p->rtp, &p->srtp, value)) {
10484
					} else if (!processed_crypto && process_crypto(p, p->rtp, &p->srtp, value)) {
10472
						processed_crypto = TRUE;
10485
						processed_crypto = TRUE;
10473
						processed = TRUE;
10486
						processed = TRUE;
[+20] [20] 4 lines
[+20] static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action)
10478
				/* Video specific scanning */
10491
				/* Video specific scanning */
10479
				else if (video) {
10492
				else if (video) {
10480
					if (process_sdp_a_ice(value, p, p->vrtp)) {
10493
					if (process_sdp_a_ice(value, p, p->vrtp)) {
10481
						processed = TRUE;
10494
						processed = TRUE;
10482
					} else if (process_sdp_a_dtls(value, p, p->vrtp)) {
10495
					} else if (process_sdp_a_dtls(value, p, p->vrtp)) {

    
   
10496
						processed_crypto = TRUE;
10483
						processed = TRUE;
10497
						processed = TRUE;

    
   
10498
						if (p->vsrtp) {

    
   
10499
							ast_set_flag(p->vsrtp, SRTP_CRYPTO_OFFER_OK);

    
   
10500
						}
10484
					} else if (!processed_crypto && process_crypto(p, p->vrtp, &p->vsrtp, value)) {
10501
					} else if (!processed_crypto && process_crypto(p, p->vrtp, &p->vsrtp, value)) {
10485
						processed_crypto = TRUE;
10502
						processed_crypto = TRUE;
10486
						processed = TRUE;
10503
						processed = TRUE;
10487
					} else if (process_sdp_a_video(value, p, &newvideortp, &last_rtpmap_codec)) {
10504
					} else if (process_sdp_a_video(value, p, &newvideortp, &last_rtpmap_codec)) {
10488
						processed = TRUE;
10505
						processed = TRUE;
[+20] [20] 140 lines
[+20] static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action)
10629
	}
10646
	}
10630

    
   
10647

   
10631
	/* Setup audio address and port */
10648
	/* Setup audio address and port */
10632
	if (p->rtp) {
10649
	if (p->rtp) {
10633
		if (sa && portno > 0) {
10650
		if (sa && portno > 0) {
10634
			start_ice(p->rtp);
10651
			start_ice(p->rtp, (req->method != SIP_RESPONSE) ? 0 : 1);
10635
			ast_sockaddr_set_port(sa, portno);
10652
			ast_sockaddr_set_port(sa, portno);
10636
			ast_rtp_instance_set_remote_address(p->rtp, sa);
10653
			ast_rtp_instance_set_remote_address(p->rtp, sa);
10637
			if (debug) {
10654
			if (debug) {
10638
				ast_verbose("Peer audio RTP is at port %s\n",
10655
				ast_verbose("Peer audio RTP is at port %s\n",
10639
					    ast_sockaddr_stringify(sa));
10656
					    ast_sockaddr_stringify(sa));
[+20] [20] 37 lines
[+20] static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action)
10677
	}
10694
	}
10678

    
   
10695

   
10679
	/* Setup video address and port */
10696
	/* Setup video address and port */
10680
	if (p->vrtp) {
10697
	if (p->vrtp) {
10681
		if (vsa && vportno > 0) {
10698
		if (vsa && vportno > 0) {
10682
			start_ice(p->vrtp);
10699
			start_ice(p->vrtp, (req->method != SIP_RESPONSE) ? 0 : 1);
10683
			ast_sockaddr_set_port(vsa, vportno);
10700
			ast_sockaddr_set_port(vsa, vportno);
10684
			ast_rtp_instance_set_remote_address(p->vrtp, vsa);
10701
			ast_rtp_instance_set_remote_address(p->vrtp, vsa);
10685
			if (debug) {
10702
			if (debug) {
10686
				ast_verbose("Peer video RTP is at port %s\n",
10703
				ast_verbose("Peer video RTP is at port %s\n",
10687
					    ast_sockaddr_stringify(vsa));
10704
					    ast_sockaddr_stringify(vsa));
[+20] [20] 7 lines
[+20] static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action)
10695
	}
10712
	}
10696

    
   
10713

   
10697
	/* Setup text address and port */
10714
	/* Setup text address and port */
10698
	if (p->trtp) {
10715
	if (p->trtp) {
10699
		if (tsa && tportno > 0) {
10716
		if (tsa && tportno > 0) {
10700
			start_ice(p->trtp);
10717
			start_ice(p->trtp, (req->method != SIP_RESPONSE) ? 0 : 1);
10701
			ast_sockaddr_set_port(tsa, tportno);
10718
			ast_sockaddr_set_port(tsa, tportno);
10702
			ast_rtp_instance_set_remote_address(p->trtp, tsa);
10719
			ast_rtp_instance_set_remote_address(p->trtp, tsa);
10703
			if (debug) {
10720
			if (debug) {
10704
				ast_verbose("Peer T.140 RTP is at port %s\n",
10721
				ast_verbose("Peer T.140 RTP is at port %s\n",
10705
					    ast_sockaddr_stringify(tsa));
10722
					    ast_sockaddr_stringify(tsa));
[+20] [20] 316 lines
[+20] [+] static int process_sdp_a_ice(const char *a, struct sip_pvt *p, struct ast_rtp_instance *instance)
11022

    
   
11039

   
11023
static int process_sdp_a_dtls(const char *a, struct sip_pvt *p, struct ast_rtp_instance *instance)
11040
static int process_sdp_a_dtls(const char *a, struct sip_pvt *p, struct ast_rtp_instance *instance)
11024
{
11041
{
11025
	struct ast_rtp_engine_dtls *dtls;
11042
	struct ast_rtp_engine_dtls *dtls;
11026
	int found = FALSE;
11043
	int found = FALSE;
11027
	char value[256], hash[6];
11044
	char value[256], hash[32];
11028

    
   
11045

   
11029
	if (!instance || !p->dtls_cfg.enabled || !(dtls = ast_rtp_instance_get_dtls(instance))) {
11046
	if (!instance || !p->dtls_cfg.enabled || !(dtls = ast_rtp_instance_get_dtls(instance))) {
11030
		return found;
11047
		return found;
11031
	}
11048
	}
11032

    
   
11049

   
[+20] [20] 21 lines
[+20] static int process_sdp_a_dtls(const char *a, struct sip_pvt *p, struct ast_rtp_instance *instance)
11054
			/* Since they want to just use what already exists we go on as if nothing happened */
11071
			/* Since they want to just use what already exists we go on as if nothing happened */
11055
		} else {
11072
		} else {
11056
			ast_log(LOG_WARNING, "Unsupported connection attribute value '%s' received on dialog '%s'\n",
11073
			ast_log(LOG_WARNING, "Unsupported connection attribute value '%s' received on dialog '%s'\n",
11057
				value, p->callid);
11074
				value, p->callid);
11058
		}
11075
		}
11059
	} else if (sscanf(a, "fingerprint: %5s %255s", hash, value) == 2) {
11076
	} else if (sscanf(a, "fingerprint: %31s %255s", hash, value) == 2) {
11060
		found = TRUE;
11077
		found = TRUE;
11061

    
   
11078

   
11062
		if (!strcasecmp(hash, "sha-1")) {
11079
		if (!strcasecmp(hash, "sha-1")) {
11063
			dtls->set_fingerprint(instance, AST_RTP_DTLS_HASH_SHA1, value);
11080
			dtls->set_fingerprint(instance, AST_RTP_DTLS_HASH_SHA1, value);

    
   
11081
		} else if (!strcasecmp(hash, "sha-256")) {

    
   
11082
			dtls->set_fingerprint(instance, AST_RTP_DTLS_HASH_SHA256, value);
11064
		} else {
11083
		} else {
11065
			ast_log(LOG_WARNING, "Unsupported fingerprint hash type '%s' received on dialog '%s'\n",
11084
			ast_log(LOG_WARNING, "Unsupported fingerprint hash type '%s' received on dialog '%s'\n",
11066
				hash, p->callid);
11085
				hash, p->callid);
11067
		}
11086
		}
11068
	}
11087
	}
[+20] [20] 1629 lines
[+20] [+] static void add_ice_to_sdp(struct ast_rtp_instance *instance, struct ast_str **a_buf)
12698

    
   
12717

   
12699
	ao2_ref(candidates, -1);
12718
	ao2_ref(candidates, -1);
12700
}
12719
}
12701

    
   
12720

   
12702
/*! \brief Start ICE negotiation on an RTP instance */
12721
/*! \brief Start ICE negotiation on an RTP instance */
12703
static void start_ice(struct ast_rtp_instance *instance)
12722
static void start_ice(struct ast_rtp_instance *instance, int offer)
12704
{
12723
{
12705
	struct ast_rtp_engine_ice *ice = ast_rtp_instance_get_ice(instance);
12724
	struct ast_rtp_engine_ice *ice = ast_rtp_instance_get_ice(instance);
12706

    
   
12725

   
12707
	if (!ice) {
12726
	if (!ice) {
12708
		return;
12727
		return;
12709
	}
12728
	}
12710

    
   
12729

   

    
   
12730
	/* If we are the offerer then we are the controlling agent, otherwise they are */

    
   
12731
	ice->set_role(instance, offer ? AST_RTP_ICE_ROLE_CONTROLLING : AST_RTP_ICE_ROLE_CONTROLLED);
12711
	ice->start(instance);
12732
	ice->start(instance);
12712
}
12733
}
12713

    
   
12734

   
12714
/*! \brief Add DTLS attributes to SDP */
12735
/*! \brief Add DTLS attributes to SDP */
12715
static void add_dtls_to_sdp(struct ast_rtp_instance *instance, struct ast_str **a_buf)
12736
static void add_dtls_to_sdp(struct ast_rtp_instance *instance, struct ast_str **a_buf)
12716
{
12737
{
12717
	struct ast_rtp_engine_dtls *dtls;
12738
	struct ast_rtp_engine_dtls *dtls;

    
   
12739
	enum ast_rtp_dtls_hash hash;
12718
	const char *fingerprint;
12740
	const char *fingerprint;
12719

    
   
12741

   
12720
	if (!instance || !(dtls = ast_rtp_instance_get_dtls(instance)) || !dtls->active(instance)) {
12742
	if (!instance || !(dtls = ast_rtp_instance_get_dtls(instance)) || !dtls->active(instance)) {
12721
		return;
12743
		return;
12722
	}
12744
	}
[+20] [20] 24 lines
[+20] static void add_dtls_to_sdp(struct ast_rtp_instance *instance, struct ast_str **a_buf)
12747
		break;
12769
		break;
12748
	default:
12770
	default:
12749
		break;
12771
		break;
12750
	}
12772
	}
12751

    
   
12773

   
12752
	if ((fingerprint = dtls->get_fingerprint(instance, AST_RTP_DTLS_HASH_SHA1))) {
12774
	hash = dtls->get_fingerprint_hash(instance);
12753
		ast_str_append(a_buf, 0, "a=fingerprint:SHA-1 %s\r\n", fingerprint);
12775
	fingerprint = dtls->get_fingerprint(instance);

    
   
12776
	if (fingerprint && (hash == AST_RTP_DTLS_HASH_SHA1 || hash == AST_RTP_DTLS_HASH_SHA256)) {

    
   
12777
		ast_str_append(a_buf, 0, "a=fingerprint:%s %s\r\n", hash == AST_RTP_DTLS_HASH_SHA1 ? "SHA-1" : "SHA-256",

    
   
12778
			fingerprint);
12754
	}
12779
	}
12755
}
12780
}
12756

    
   
12781

   
12757
/*! \brief Add codec offer to SDP offer/answer body in INVITE or 200 OK */
12782
/*! \brief Add codec offer to SDP offer/answer body in INVITE or 200 OK */
12758
static void add_codec_to_sdp(const struct sip_pvt *p,
12783
static void add_codec_to_sdp(const struct sip_pvt *p,
[+20] [20] 297 lines
[+20] [+] static void get_crypto_attrib(struct sip_pvt *p, struct sip_srtp *srtp, const char **a_crypto)
13056
static char *get_sdp_rtp_profile(const struct sip_pvt *p, unsigned int secure, struct ast_rtp_instance *instance)
13081
static char *get_sdp_rtp_profile(const struct sip_pvt *p, unsigned int secure, struct ast_rtp_instance *instance)
13057
{
13082
{
13058
	struct ast_rtp_engine_dtls *dtls;
13083
	struct ast_rtp_engine_dtls *dtls;
13059

    
   
13084

   
13060
	if ((dtls = ast_rtp_instance_get_dtls(instance)) && dtls->active(instance)) {
13085
	if ((dtls = ast_rtp_instance_get_dtls(instance)) && dtls->active(instance)) {

    
   
13086
		if (ast_test_flag(&p->flags[2], SIP_PAGE3_FORCE_AVP)) {

    
   
13087
			return ast_test_flag(&p->flags[2], SIP_PAGE3_USE_AVPF) ? "RTP/SAVPF" : "RTP/SAVP";

    
   
13088
		} else {
13061
		return ast_test_flag(&p->flags[2], SIP_PAGE3_USE_AVPF) ? "UDP/TLS/RTP/SAVPF" : "UDP/TLS/RTP/SAVP";
13089
			return ast_test_flag(&p->flags[2], SIP_PAGE3_USE_AVPF) ? "UDP/TLS/RTP/SAVPF" : "UDP/TLS/RTP/SAVP";

    
   
13090
		}
13062
	} else {
13091
	} else {
13063
		if (ast_test_flag(&p->flags[2], SIP_PAGE3_USE_AVPF)) {
13092
		if (ast_test_flag(&p->flags[2], SIP_PAGE3_USE_AVPF)) {
13064
			return secure ? "RTP/SAVPF" : "RTP/AVPF";
13093
			return secure ? "RTP/SAVPF" : "RTP/AVPF";
13065
		} else {
13094
		} else {
13066
			return secure ? "RTP/SAVP" : "RTP/AVP";
13095
			return secure ? "RTP/SAVP" : "RTP/AVP";
[+20] [20] 18034 lines
[+20] [+] static struct sip_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime, int devstate_only)
31101
				ast_set2_flag(&peer->flags[2], ast_true(v->value), SIP_PAGE3_SNOM_AOC);
31130
				ast_set2_flag(&peer->flags[2], ast_true(v->value), SIP_PAGE3_SNOM_AOC);
31102
			} else if (!strcasecmp(v->name, "avpf")) {
31131
			} else if (!strcasecmp(v->name, "avpf")) {
31103
				ast_set2_flag(&peer->flags[2], ast_true(v->value), SIP_PAGE3_USE_AVPF);
31132
				ast_set2_flag(&peer->flags[2], ast_true(v->value), SIP_PAGE3_USE_AVPF);
31104
			} else if (!strcasecmp(v->name, "icesupport")) {
31133
			} else if (!strcasecmp(v->name, "icesupport")) {
31105
				ast_set2_flag(&peer->flags[2], ast_true(v->value), SIP_PAGE3_ICE_SUPPORT);
31134
				ast_set2_flag(&peer->flags[2], ast_true(v->value), SIP_PAGE3_ICE_SUPPORT);

    
   
31135
			} else if (!strcasecmp(v->name, "force_avp")) {

    
   
31136
				ast_set2_flag(&peer->flags[2], ast_true(v->value), SIP_PAGE3_FORCE_AVP);
31106
			} else {
31137
			} else {
31107
				ast_rtp_dtls_cfg_parse(&peer->dtls_cfg, v->name, v->value);
31138
				ast_rtp_dtls_cfg_parse(&peer->dtls_cfg, v->name, v->value);
31108
			}
31139
			}
31109
		}
31140
		}
31110

    
   
31141

   
[+20] [20] 3898 lines
/branches/11/channels/sip/include/sip.h
Revision 417585 New Change
 
/branches/11/configs/sip.conf.sample
Revision 417585 New Change
 
/branches/11/include/asterisk/rtp_engine.h
Revision 417585 New Change
 
/branches/11/main/rtp_engine.c
Revision 417585 New Change
 
/branches/11/res/res_rtp_asterisk.c
Revision 417585 New Change
 
  1. /channels/chan_sip.c: Loading...
  2. /channels/sip/include/sip.h: Loading...
  3. /configs/sip.conf.sample: Loading...
  4. /include/asterisk/rtp_engine.h: Loading...
  5. /main/rtp_engine.c: Loading...
  6. /res/res_rtp_asterisk.c: Loading...

https://reviewboard.asterisk.org/ runs on a server provided by Digium, Inc. and uses bandwidth donated to the open source Asterisk community by API Digital Communications in Huntsville, AL USA.
Please report problems with this site to asteriskteam@digium.com.