From 98504fec8ee8fde7eb2a6378046f3d35bfba961a Mon Sep 17 00:00:00 2001 From: Kinsey Moore Date: Tue, 23 Jul 2013 13:52:06 +0000 Subject: [PATCH] Add DTLS-SRTP support to chan_pjsip This patch introduces DTLS-SRTP support to chan_pjsip and the options necessary to configure it including an option to allow choosing between 32 and 80 byte SRTP tag lengths. During the implementation and testing of this patch, three other bugs were found and their fixes are included with this patch. The two in chan_sip were a segfault relating to DTLS setup and mistaken call rejection. The third bug fix prevents chan_pjsip from attempting to perform bridge optimization between two endpoints if either of them is running any form of SRTP. Review: https://reviewboard.asterisk.org/r/2683/ (closes issue ASTERISK-21419) git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@395121 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- channels/chan_gulp.c | 12 ++ channels/chan_sip.c | 12 +- include/asterisk/res_sip.h | 6 + include/asterisk/res_sip_session.h | 3 +- res/res_sip.c | 84 +++++++++ res/res_sip/sip_configuration.c | 22 ++- res/res_sip_sdp_rtp.c | 265 +++++++++++++++++++++++++---- res/res_sip_session.c | 1 + 8 files changed, 362 insertions(+), 43 deletions(-) diff --git a/channels/chan_gulp.c b/channels/chan_gulp.c index 1aa6a3760c..e3d3ed0057 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 62afeb0614..ca4b25b7ba 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 7342d9d9d9..01d50bfb98 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 +/* 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 26299eb3e6..fb482db9bc 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 f44a8bc665..d904165339 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. + + res_sip will offer DTLS-SRTP setup. + @@ -476,6 +479,87 @@ Domain to user in From header for requests to this endpoint. + + Verify that the provided peer certificate is valid + + This option only applies if media_encryption is + set to dtls. + + + + Interval at which to renegotiate the TLS session and rekey the SRTP session + + This option only applies if media_encryption is + set to dtls. + + If this is not set or the value provided is 0 rekeying will be disabled. + + + + Path to certificate file to present to peer + + This option only applies if media_encryption is + set to dtls. + + + + Path to private key for certificate file + + This option only applies if media_encryption is + set to dtls. + + + + Cipher to use for DTLS negotiation + + This option only applies if media_encryption is + set to dtls. + + Many options for acceptable ciphers. See link for more: + http://www.openssl.org/docs/apps/ciphers.html#CIPHER_STRINGS + + + + Path to certificate authority certificate + + This option only applies if media_encryption is + set to dtls. + + + + Path to a directory containing certificate authority certificates + + This option only applies if media_encryption is + set to dtls. + + + + Whether we are willing to accept connections, connect to the other party, or both. + + + This option only applies if media_encryption is + set to dtls. + + + + res_sip will make a connection to the peer. + + + res_sip will accept connections from the peer. + + + res_sip will offer and accept connections from the peer. + + + + + + Determines whether 32 byte tags should be used instead of 80 byte tags. + + This option only applies if media_encryption is + set to sdes or dtls. + + Authentication type diff --git a/res/res_sip/sip_configuration.c b/res/res_sip/sip_configuration.c index 5911edba50..809430a275 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 b299ed7583..6e994116df 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; + 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 }; - if (!session_media->srtp && session->endpoint->media_encryption != AST_SIP_MEDIA_ENCRYPT_NONE) { - session_media->srtp = ast_sdp_srtp_alloc(); + 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; } + + 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; } - 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; 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 7028e0d06b..38a0604f59 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);