diff options
-rw-r--r-- | channels/chan_gulp.c | 12 | ||||
-rw-r--r-- | channels/chan_sip.c | 12 | ||||
-rw-r--r-- | include/asterisk/res_sip.h | 6 | ||||
-rw-r--r-- | include/asterisk/res_sip_session.h | 3 | ||||
-rw-r--r-- | res/res_sip.c | 84 | ||||
-rw-r--r-- | res/res_sip/sip_configuration.c | 22 | ||||
-rw-r--r-- | res/res_sip_sdp_rtp.c | 265 | ||||
-rw-r--r-- | 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 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); |