summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--channels/chan_gulp.c12
-rw-r--r--channels/chan_sip.c12
-rw-r--r--include/asterisk/res_sip.h6
-rw-r--r--include/asterisk/res_sip_session.h3
-rw-r--r--res/res_sip.c84
-rw-r--r--res/res_sip/sip_configuration.c22
-rw-r--r--res/res_sip_sdp_rtp.c265
-rw-r--r--res/res_sip_session.c1
8 files changed, 362 insertions, 43 deletions
diff --git a/channels/chan_gulp.c b/channels/chan_gulp.c
index 1aa6a3760..e3d3ed005 100644
--- a/channels/chan_gulp.c
+++ b/channels/chan_gulp.c
@@ -384,6 +384,10 @@ static enum ast_rtp_glue_result gulp_get_rtp_peer(struct ast_channel *chan, stru
ao2_ref(*instance, +1);
ast_assert(endpoint != NULL);
+ if (endpoint->media_encryption != AST_SIP_MEDIA_ENCRYPT_NONE) {
+ return AST_RTP_GLUE_RESULT_FORBID;
+ }
+
if (endpoint->direct_media) {
return AST_RTP_GLUE_RESULT_REMOTE;
}
@@ -396,14 +400,22 @@ static enum ast_rtp_glue_result gulp_get_vrtp_peer(struct ast_channel *chan, str
{
struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
struct gulp_pvt *pvt = channel->pvt;
+ struct ast_sip_endpoint *endpoint;
if (!pvt || !channel->session || !pvt->media[SIP_MEDIA_VIDEO]->rtp) {
return AST_RTP_GLUE_RESULT_FORBID;
}
+ endpoint = channel->session->endpoint;
+
*instance = pvt->media[SIP_MEDIA_VIDEO]->rtp;
ao2_ref(*instance, +1);
+ ast_assert(endpoint != NULL);
+ if (endpoint->media_encryption != AST_SIP_MEDIA_ENCRYPT_NONE) {
+ return AST_RTP_GLUE_RESULT_FORBID;
+ }
+
return AST_RTP_GLUE_RESULT_LOCAL;
}
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 62afeb061..ca4b25b7b 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -10193,6 +10193,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
} else if (!strcmp(protocol, "UDP/TLS/RTP/SAVP") || !strcmp(protocol, "UDP/TLS/RTP/SAVPF")) {
secure_audio = 1;
+ processed_crypto = 1;
if (p->srtp) {
ast_set_flag(p->srtp, AST_SRTP_CRYPTO_OFFER_OK);
}
@@ -10275,6 +10276,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
} else if (!strcmp(protocol, "UDP/TLS/RTP/SAVP") || !strcmp(protocol, "UDP/TLS/RTP/SAVPF")) {
secure_video = 1;
+ processed_crypto = 1;
if (p->vsrtp || (p->vsrtp = ast_sdp_srtp_alloc())) {
ast_set_flag(p->vsrtp, AST_SRTP_CRYPTO_OFFER_OK);
}
@@ -13036,13 +13038,17 @@ static void get_our_media_address(struct sip_pvt *p, int needvideo, int needtext
static char *crypto_get_attrib(struct ast_sdp_srtp *srtp, int dtls_enabled, int default_taglen_32)
{
char *a_crypto;
- char *orig_crypto;
+ const char *orig_crypto;
- if (!srtp) {
+ if (!srtp || dtls_enabled) {
+ return NULL;
+ }
+
+ orig_crypto = ast_sdp_srtp_get_attrib(srtp, dtls_enabled, default_taglen_32);
+ if (ast_strlen_zero(orig_crypto)) {
return NULL;
}
- orig_crypto = ast_strdupa(ast_sdp_srtp_get_attrib(srtp, dtls_enabled, default_taglen_32));
if (ast_asprintf(&a_crypto, "a=crypto:%s\r\n", orig_crypto) == -1) {
return NULL;
}
diff --git a/include/asterisk/res_sip.h b/include/asterisk/res_sip.h
index 7342d9d9d..01d50bfb9 100644
--- a/include/asterisk/res_sip.h
+++ b/include/asterisk/res_sip.h
@@ -34,6 +34,8 @@
#include "asterisk/endpoints.h"
/* Needed for pj_sockaddr */
#include <pjlib.h>
+/* Needed for ast_rtp_dtls_cfg struct */
+#include "asterisk/rtp_engine.h"
/* Forward declarations of PJSIP stuff */
struct pjsip_rx_data;
@@ -446,6 +448,10 @@ struct ast_sip_endpoint {
unsigned int allowsubscribe;
/*! The minimum allowed expiration for subscriptions from endpoint */
unsigned int subminexpiry;
+ /*! \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? */
+ unsigned int srtp_tag_32;
};
/*!
diff --git a/include/asterisk/res_sip_session.h b/include/asterisk/res_sip_session.h
index 26299eb3e..fb482db9b 100644
--- a/include/asterisk/res_sip_session.h
+++ b/include/asterisk/res_sip_session.h
@@ -26,7 +26,7 @@
#include "asterisk/channel.h"
/* Needed for ast_sockaddr struct */
#include "asterisk/netsock.h"
-/* Neeed for ast_sdp_srtp struct */
+/* Needed for ast_sdp_srtp struct */
#include "asterisk/sdp_srtp.h"
/* Forward declarations */
@@ -42,7 +42,6 @@ struct pjsip_rx_data;
struct ast_party_id;
struct pjmedia_sdp_media;
struct pjmedia_sdp_session;
-struct ast_rtp_instance;
struct ast_dsp;
struct ast_sip_session_sdp_handler;
diff --git a/res/res_sip.c b/res/res_sip.c
index f44a8bc66..d90416533 100644
--- a/res/res_sip.c
+++ b/res/res_sip.c
@@ -336,6 +336,9 @@
transport should be used in conjunction with this option to prevent
exposure of media encryption keys.
</para></enum>
+ <enum name="dtls"><para>
+ res_sip will offer DTLS-SRTP setup.
+ </para></enum>
</enumlist>
</description>
</configOption>
@@ -476,6 +479,87 @@
<configOption name="fromdomain">
<synopsis>Domain to user in From header for requests to this endpoint.</synopsis>
</configOption>
+ <configOption name="dtlsverify">
+ <synopsis>Verify that the provided peer certificate is valid</synopsis>
+ <description><para>
+ This option only applies if <replaceable>media_encryption</replaceable> is
+ set to <literal>dtls</literal>.
+ </para></description>
+ </configOption>
+ <configOption name="dtlsrekey">
+ <synopsis>Interval at which to renegotiate the TLS session and rekey the SRTP session</synopsis>
+ <description><para>
+ This option only applies if <replaceable>media_encryption</replaceable> is
+ set to <literal>dtls</literal>.
+ </para><para>
+ If this is not set or the value provided is 0 rekeying will be disabled.
+ </para></description>
+ </configOption>
+ <configOption name="dtlscertfile">
+ <synopsis>Path to certificate file to present to peer</synopsis>
+ <description><para>
+ This option only applies if <replaceable>media_encryption</replaceable> is
+ set to <literal>dtls</literal>.
+ </para></description>
+ </configOption>
+ <configOption name="dtlsprivatekey">
+ <synopsis>Path to private key for certificate file</synopsis>
+ <description><para>
+ This option only applies if <replaceable>media_encryption</replaceable> is
+ set to <literal>dtls</literal>.
+ </para></description>
+ </configOption>
+ <configOption name="dtlscipher">
+ <synopsis>Cipher to use for DTLS negotiation</synopsis>
+ <description><para>
+ This option only applies if <replaceable>media_encryption</replaceable> is
+ set to <literal>dtls</literal>.
+ </para><para>
+ Many options for acceptable ciphers. See link for more:
+ http://www.openssl.org/docs/apps/ciphers.html#CIPHER_STRINGS
+ </para></description>
+ </configOption>
+ <configOption name="dtlscafile">
+ <synopsis>Path to certificate authority certificate</synopsis>
+ <description><para>
+ This option only applies if <replaceable>media_encryption</replaceable> is
+ set to <literal>dtls</literal>.
+ </para></description>
+ </configOption>
+ <configOption name="dtlscapath">
+ <synopsis>Path to a directory containing certificate authority certificates</synopsis>
+ <description><para>
+ This option only applies if <replaceable>media_encryption</replaceable> is
+ set to <literal>dtls</literal>.
+ </para></description>
+ </configOption>
+ <configOption name="dtlssetup">
+ <synopsis>Whether we are willing to accept connections, connect to the other party, or both.</synopsis>
+ <description>
+ <para>
+ This option only applies if <replaceable>media_encryption</replaceable> is
+ set to <literal>dtls</literal>.
+ </para>
+ <enumlist>
+ <enum name="active"><para>
+ res_sip will make a connection to the peer.
+ </para></enum>
+ <enum name="passive"><para>
+ res_sip will accept connections from the peer.
+ </para></enum>
+ <enum name="actpass"><para>
+ res_sip will offer and accept connections from the peer.
+ </para></enum>
+ </enumlist>
+ </description>
+ </configOption>
+ <configOption name="srtp_tag_32">
+ <synopsis>Determines whether 32 byte tags should be used instead of 80 byte tags.</synopsis>
+ <description><para>
+ This option only applies if <replaceable>media_encryption</replaceable> is
+ set to <literal>sdes</literal> or <literal>dtls</literal>.
+ </para></description>
+ </configOption>
</configObject>
<configObject name="auth">
<synopsis>Authentication type</synopsis>
diff --git a/res/res_sip/sip_configuration.c b/res/res_sip/sip_configuration.c
index 5911edba5..809430a27 100644
--- a/res/res_sip/sip_configuration.c
+++ b/res/res_sip/sip_configuration.c
@@ -467,8 +467,9 @@ static int media_encryption_handler(const struct aco_option *opt, struct ast_var
endpoint->media_encryption = AST_SIP_MEDIA_ENCRYPT_NONE;
} else if (!strcasecmp("sdes", var->value)) {
endpoint->media_encryption = AST_SIP_MEDIA_ENCRYPT_SDES;
- /*} else if (!strcasecmp("dtls", var->value)) {
- endpoint->media_encryption = AST_SIP_MEDIA_ENCRYPT_DTLS;*/
+ } else if (!strcasecmp("dtls", var->value)) {
+ endpoint->media_encryption = AST_SIP_MEDIA_ENCRYPT_DTLS;
+ ast_rtp_dtls_cfg_parse(&endpoint->dtls_cfg, "dtlsenable", "yes");
} else {
return -1;
}
@@ -518,6 +519,14 @@ static int named_groups_handler(const struct aco_option *opt,
return 0;
}
+static int dtls_handler(const struct aco_option *opt,
+ struct ast_variable *var, void *obj)
+{
+ struct ast_sip_endpoint *endpoint = obj;
+
+ return ast_rtp_dtls_cfg_parse(&endpoint->dtls_cfg, var->name, var->value);
+}
+
static void *sip_nat_hook_alloc(const char *name)
{
return ast_sorcery_generic_alloc(sizeof(struct ast_sip_nat_hook), NULL);
@@ -676,6 +685,15 @@ int ast_res_sip_initialize_configuration(void)
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "fromuser", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, fromuser));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "fromdomain", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, fromdomain));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "mwifromuser", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, mwi_from));
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtlsverify", "", dtls_handler, NULL, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtlsrekey", "", dtls_handler, NULL, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtlscertfile", "", dtls_handler, NULL, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtlsprivatekey", "", dtls_handler, NULL, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtlscipher", "", dtls_handler, NULL, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtlscafile", "", dtls_handler, NULL, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtlscapath", "", dtls_handler, NULL, 0, 0);
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtlssetup", "", dtls_handler, NULL, 0, 0);
+ ast_sorcery_object_field_register(sip_sorcery, "endpoint", "srtp_tag_32", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, srtp_tag_32));
if (ast_sip_initialize_sorcery_transport(sip_sorcery)) {
ast_log(LOG_ERROR, "Failed to register SIP transport support with sorcery\n");
diff --git a/res/res_sip_sdp_rtp.c b/res/res_sip_sdp_rtp.c
index b299ed758..6e994116d 100644
--- a/res/res_sip_sdp_rtp.c
+++ b/res/res_sip_sdp_rtp.c
@@ -525,10 +525,6 @@ static enum ast_sip_session_media_encryption check_endpoint_media_transport(
}
incoming_encryption = get_media_encryption_type(stream->desc.transport);
- if (incoming_encryption == AST_SIP_MEDIA_ENCRYPT_DTLS) {
- /* DTLS not yet supported */
- return AST_SIP_MEDIA_TRANSPORT_INVALID;
- }
if (incoming_encryption == endpoint->media_encryption) {
return incoming_encryption;
@@ -537,6 +533,108 @@ static enum ast_sip_session_media_encryption check_endpoint_media_transport(
return AST_SIP_MEDIA_TRANSPORT_INVALID;
}
+static int setup_srtp(struct ast_sip_session_media *session_media)
+{
+ if (!session_media->srtp) {
+ session_media->srtp = ast_sdp_srtp_alloc();
+ if (!session_media->srtp) {
+ return -1;
+ }
+ }
+
+ if (!session_media->srtp->crypto) {
+ session_media->srtp->crypto = ast_sdp_crypto_alloc();
+ if (!session_media->srtp->crypto) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int setup_dtls_srtp(struct ast_sip_session *session,
+ struct ast_sip_session_media *session_media)
+{
+ struct ast_rtp_engine_dtls *dtls;
+
+ if (!session->endpoint->dtls_cfg.enabled || !session_media->rtp) {
+ return -1;
+ }
+
+ dtls = ast_rtp_instance_get_dtls(session_media->rtp);
+ if (!dtls) {
+ return -1;
+ }
+
+ session->endpoint->dtls_cfg.suite = ((session->endpoint->srtp_tag_32) ? AST_AES_CM_128_HMAC_SHA1_32 : AST_AES_CM_128_HMAC_SHA1_80);
+ if (dtls->set_configuration(session_media->rtp, &session->endpoint->dtls_cfg)) {
+ ast_log(LOG_ERROR, "Attempted to set an invalid DTLS-SRTP configuration on RTP instance '%p'\n",
+ session_media->rtp);
+ return -1;
+ }
+
+ if (setup_srtp(session_media)) {
+ return -1;
+ }
+ return 0;
+}
+
+static int parse_dtls_attrib(struct ast_sip_session_media *session_media,
+ const struct pjmedia_sdp_media *stream)
+{
+ int i;
+ struct ast_rtp_engine_dtls *dtls = ast_rtp_instance_get_dtls(session_media->rtp);
+
+ for (i = 0; i < stream->attr_count; i++) {
+ pjmedia_sdp_attr *attr = stream->attr[i];
+ pj_str_t *value;
+
+ if (!attr->value.ptr) {
+ continue;
+ }
+
+ value = pj_strtrim(&attr->value);
+
+ if (!pj_strcmp2(&attr->name, "setup")) {
+ if (!pj_stricmp2(value, "active")) {
+ dtls->set_setup(session_media->rtp, AST_RTP_DTLS_SETUP_ACTIVE);
+ } else if (!pj_stricmp2(value, "passive")) {
+ dtls->set_setup(session_media->rtp, AST_RTP_DTLS_SETUP_PASSIVE);
+ } else if (!pj_stricmp2(value, "actpass")) {
+ dtls->set_setup(session_media->rtp, AST_RTP_DTLS_SETUP_ACTPASS);
+ } else if (!pj_stricmp2(value, "holdconn")) {
+ dtls->set_setup(session_media->rtp, AST_RTP_DTLS_SETUP_HOLDCONN);
+ } else {
+ ast_log(LOG_WARNING, "Unsupported setup attribute value '%*s'\n", (int)value->slen, value->ptr);
+ }
+ } else if (!pj_strcmp2(&attr->name, "connection")) {
+ if (!pj_stricmp2(value, "new")) {
+ dtls->reset(session_media->rtp);
+ } else if (!pj_stricmp2(value, "existing")) {
+ /* Do nothing */
+ } else {
+ 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 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 (!strcasecmp(hash, "sha-1")) {
+ dtls->set_fingerprint(session_media->rtp, AST_RTP_DTLS_HASH_SHA1, hash_value);
+ } else {
+ ast_log(LOG_WARNING, "Unsupported fingerprint hash type '%s'\n",
+ hash);
+ }
+ }
+ }
+ }
+ ast_set_flag(session_media->srtp, AST_SRTP_CRYPTO_OFFER_OK);
+
+ return 0;
+}
+
static int setup_sdes_srtp(struct ast_sip_session_media *session_media,
const struct pjmedia_sdp_media *stream)
{
@@ -557,18 +655,8 @@ static int setup_sdes_srtp(struct ast_sip_session_media *session_media,
return -1;
}
- if (!session_media->srtp) {
- session_media->srtp = ast_sdp_srtp_alloc();
- if (!session_media->srtp) {
- return -1;
- }
- }
-
- if (!session_media->srtp->crypto) {
- session_media->srtp->crypto = ast_sdp_crypto_alloc();
- if (!session_media->srtp->crypto) {
- return -1;
- }
+ if (setup_srtp(session_media)) {
+ return -1;
}
if (!ast_sdp_crypto_process(session_media->rtp, session_media->srtp, crypto_str)) {
@@ -583,6 +671,32 @@ static int setup_sdes_srtp(struct ast_sip_session_media *session_media,
return -1;
}
+static int setup_media_encryption(struct ast_sip_session *session,
+ struct ast_sip_session_media *session_media,
+ const struct pjmedia_sdp_media *stream)
+{
+ switch (session->endpoint->media_encryption) {
+ case AST_SIP_MEDIA_ENCRYPT_SDES:
+ if (setup_sdes_srtp(session_media, stream)) {
+ return -1;
+ }
+ break;
+ case AST_SIP_MEDIA_ENCRYPT_DTLS:
+ if (setup_dtls_srtp(session, session_media)) {
+ return -1;
+ }
+ if (parse_dtls_attrib(session_media, stream)) {
+ return -1;
+ }
+ break;
+ case AST_SIP_MEDIA_TRANSPORT_INVALID:
+ case AST_SIP_MEDIA_ENCRYPT_NONE:
+ break;
+ }
+
+ return 0;
+}
+
/*! \brief Function which negotiates an incoming media stream */
static int negotiate_incoming_sdp_stream(struct ast_sip_session *session, struct ast_sip_session_media *session_media,
const struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_media *stream)
@@ -590,7 +704,6 @@ static int negotiate_incoming_sdp_stream(struct ast_sip_session *session, struct
char host[NI_MAXHOST];
RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free_ptr);
enum ast_format_type media_type = stream_to_media_type(session_media->stream_type);
- enum ast_sip_session_media_encryption incoming_encryption;
/* If no type formats have been configured reject this stream */
if (!ast_format_cap_has_type(session->endpoint->codecs, media_type)) {
@@ -598,8 +711,7 @@ static int negotiate_incoming_sdp_stream(struct ast_sip_session *session, struct
}
/* Ensure incoming transport is compatible with the endpoint's configuration */
- incoming_encryption = check_endpoint_media_transport(session->endpoint, stream);
- if (incoming_encryption == AST_SIP_MEDIA_TRANSPORT_INVALID) {
+ if (check_endpoint_media_transport(session->endpoint, stream) == AST_SIP_MEDIA_TRANSPORT_INVALID) {
return -1;
}
@@ -616,8 +728,7 @@ static int negotiate_incoming_sdp_stream(struct ast_sip_session *session, struct
return -1;
}
- if (incoming_encryption == AST_SIP_MEDIA_ENCRYPT_SDES
- && setup_sdes_srtp(session_media, stream)) {
+ if (setup_media_encryption(session, session_media, stream)) {
return -1;
}
@@ -631,24 +742,95 @@ static int add_crypto_to_stream(struct ast_sip_session *session,
pj_str_t stmp;
pjmedia_sdp_attr *attr;
const char *crypto_attribute;
-
- if (!session_media->srtp && session->endpoint->media_encryption != AST_SIP_MEDIA_ENCRYPT_NONE) {
- session_media->srtp = ast_sdp_srtp_alloc();
+ struct ast_rtp_engine_dtls *dtls;
+ static const pj_str_t STR_NEW = { "new", 3 };
+ static const pj_str_t STR_EXISTING = { "existing", 8 };
+ static const pj_str_t STR_ACTIVE = { "active", 6 };
+ static const pj_str_t STR_PASSIVE = { "passive", 7 };
+ static const pj_str_t STR_ACTPASS = { "actpass", 7 };
+ static const pj_str_t STR_HOLDCONN = { "holdconn", 8 };
+
+ switch (session->endpoint->media_encryption) {
+ case AST_SIP_MEDIA_ENCRYPT_NONE:
+ case AST_SIP_MEDIA_TRANSPORT_INVALID:
+ break;
+ case AST_SIP_MEDIA_ENCRYPT_SDES:
if (!session_media->srtp) {
+ session_media->srtp = ast_sdp_srtp_alloc();
+ if (!session_media->srtp) {
+ return -1;
+ }
+ }
+
+ crypto_attribute = ast_sdp_srtp_get_attrib(session_media->srtp,
+ 0 /* DTLS running? No */,
+ session->endpoint->srtp_tag_32 /* 32 byte tag length? */);
+ if (!crypto_attribute) {
+ /* No crypto attribute to add, bad news */
return -1;
}
- }
- crypto_attribute = ast_sdp_srtp_get_attrib(session_media->srtp,
- 0 /* DTLS can not be enabled for res_sip */,
- 0 /* don't prefer 32byte tag length */);
- if (!crypto_attribute) {
- /* No crypto attribute to add */
- return -1;
+ attr = pjmedia_sdp_attr_create(pool, "crypto", pj_cstr(&stmp, crypto_attribute));
+ media->attr[media->attr_count++] = attr;
+ break;
+ case AST_SIP_MEDIA_ENCRYPT_DTLS:
+ if (setup_dtls_srtp(session, session_media)) {
+ return -1;
+ }
+
+ dtls = ast_rtp_instance_get_dtls(session_media->rtp);
+ if (!dtls) {
+ return -1;
+ }
+
+ switch (dtls->get_connection(session_media->rtp)) {
+ case AST_RTP_DTLS_CONNECTION_NEW:
+ attr = pjmedia_sdp_attr_create(pool, "connection", &STR_NEW);
+ media->attr[media->attr_count++] = attr;
+ break;
+ case AST_RTP_DTLS_CONNECTION_EXISTING:
+ attr = pjmedia_sdp_attr_create(pool, "connection", &STR_EXISTING);
+ media->attr[media->attr_count++] = attr;
+ break;
+ default:
+ break;
+ }
+
+ switch (dtls->get_setup(session_media->rtp)) {
+ case AST_RTP_DTLS_SETUP_ACTIVE:
+ attr = pjmedia_sdp_attr_create(pool, "setup", &STR_ACTIVE);
+ media->attr[media->attr_count++] = attr;
+ break;
+ case AST_RTP_DTLS_SETUP_PASSIVE:
+ attr = pjmedia_sdp_attr_create(pool, "setup", &STR_PASSIVE);
+ media->attr[media->attr_count++] = attr;
+ break;
+ case AST_RTP_DTLS_SETUP_ACTPASS:
+ attr = pjmedia_sdp_attr_create(pool, "setup", &STR_ACTPASS);
+ media->attr[media->attr_count++] = attr;
+ break;
+ case AST_RTP_DTLS_SETUP_HOLDCONN:
+ attr = pjmedia_sdp_attr_create(pool, "setup", &STR_HOLDCONN);
+ media->attr[media->attr_count++] = attr;
+ break;
+ default:
+ break;
+ }
+
+ if ((crypto_attribute = dtls->get_fingerprint(session_media->rtp, AST_RTP_DTLS_HASH_SHA1))) {
+ 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);
+
+ attr = pjmedia_sdp_attr_create(pool, "fingerprint", pj_cstr(&stmp, ast_str_buffer(fingerprint)));
+ media->attr[media->attr_count++] = attr;
+ }
+ break;
}
- attr = pjmedia_sdp_attr_create(pool, "crypto", pj_cstr(&stmp, crypto_attribute));
- media->attr[media->attr_count++] = attr;
return 0;
}
@@ -672,7 +854,6 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
struct ast_format format;
RAII_VAR(struct ast_format_cap *, caps, NULL, ast_format_cap_destroy);
enum ast_format_type media_type = stream_to_media_type(session_media->stream_type);
- int crypto_res;
int direct_media_enabled = !ast_sockaddr_isnull(&session_media->direct_media_addr) &&
!ast_format_cap_is_empty(session->direct_media_cap);
@@ -694,11 +875,14 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
return -1;
}
- crypto_res = add_crypto_to_stream(session, session_media, pool, media);
+ if (add_crypto_to_stream(session, session_media, pool, media)) {
+ return -1;
+ }
media->desc.media = pj_str(session_media->stream_type);
media->desc.transport = pj_str(ast_sdp_get_rtp_profile(
- !crypto_res, session_media->rtp, session->endpoint->use_avpf));
+ session->endpoint->media_encryption == AST_SIP_MEDIA_ENCRYPT_SDES,
+ session_media->rtp, session->endpoint->use_avpf));
/* Add connection level details */
if (direct_media_enabled) {
@@ -823,11 +1007,20 @@ static int apply_negotiated_sdp_stream(struct ast_sip_session *session, struct a
return 1;
}
+ /* Ensure incoming transport is compatible with the endpoint's configuration */
+ if (check_endpoint_media_transport(session->endpoint, remote_stream) == AST_SIP_MEDIA_TRANSPORT_INVALID) {
+ return -1;
+ }
+
/* Create an RTP instance if need be */
if (!session_media->rtp && create_rtp(session, session_media, session->endpoint->rtp_ipv6)) {
return -1;
}
+ if (setup_media_encryption(session, session_media, remote_stream)) {
+ return -1;
+ }
+
ast_copy_pj_str(host, remote_stream->conn ? &remote_stream->conn->addr : &remote->conn->addr, sizeof(host));
/* Ensure that the address provided is valid */
diff --git a/res/res_sip_session.c b/res/res_sip_session.c
index 7028e0d06..38a0604f5 100644
--- a/res/res_sip_session.c
+++ b/res/res_sip_session.c
@@ -854,6 +854,7 @@ static void session_destructor(void *obj)
ast_taskprocessor_unreference(session->serializer);
ao2_cleanup(session->datastores);
ao2_cleanup(session->media);
+
AST_LIST_HEAD_DESTROY(&session->supplements);
while ((delay = AST_LIST_REMOVE_HEAD(&session->delayed_requests, next))) {
ast_free(delay);