Author: file Date: Wed Nov 19 06:40:36 2014 New Revision: 428222 URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=428222 Log: res_pjsip_sdp_rtp: Add support for optimistic SRTP.
Optimistic SRTP is the ability to enable SRTP but not have it be a fatal requirement. If SRTP can be used it will be, if not it won't be. This gives you a better chance of using it without having your sessions fail when it can't be. Encrypt all the things! Review: https://reviewboard.asterisk.org/r/3992/ Added: branches/13/contrib/ast-db-manage/config/versions/eb88a14f2a_add_media_encryption_optimistic_to_pjsip.py (with props) Modified: branches/13/CHANGES branches/13/configs/samples/pjsip.conf.sample branches/13/include/asterisk/res_pjsip.h branches/13/include/asterisk/res_pjsip_session.h branches/13/res/res_pjsip.c branches/13/res/res_pjsip/pjsip_configuration.c branches/13/res/res_pjsip_sdp_rtp.c branches/13/res/res_pjsip_session.c Modified: branches/13/CHANGES URL: http://svnview.digium.com/svn/asterisk/branches/13/CHANGES?view=diff&rev=428222&r1=428221&r2=428222 ============================================================================== --- branches/13/CHANGES (original) +++ branches/13/CHANGES Wed Nov 19 06:40:36 2014 @@ -20,6 +20,14 @@ * transferinvalidsound For more information on what these options do, see the Asterisk wiki: https://wiki.asterisk.org/wiki/x/W4fAAQ + +Channel Drivers +------------------ + +chan_pjsip +------------------ + * New 'media_encryption_optimistic' endpoint setting. This will use SRTP + when possible but does not consider lack of it a failure. ------------------------------------------------------------------------------ --- Functionality changes from Asterisk 12 to Asterisk 13 -------------------- Modified: branches/13/configs/samples/pjsip.conf.sample URL: http://svnview.digium.com/svn/asterisk/branches/13/configs/samples/pjsip.conf.sample?view=diff&rev=428222&r1=428221&r2=428222 ============================================================================== --- branches/13/configs/samples/pjsip.conf.sample (original) +++ branches/13/configs/samples/pjsip.conf.sample Wed Nov 19 06:40:36 2014 @@ -646,6 +646,8 @@ ;media_encryption=no ; Determines whether res_pjsip will use and enforce ; usage of media encryption for this endpoint (default: ; "no") +;media_encryption_optimistic=no ; Use encryption if possible but don't fail the call + ; if not possible. ;inband_progress=no ; Determines whether chan_pjsip will indicate ringing ; using inband progress (default: "no") ;call_group= ; The numeric pickup groups for a channel (default: "") Added: branches/13/contrib/ast-db-manage/config/versions/eb88a14f2a_add_media_encryption_optimistic_to_pjsip.py URL: http://svnview.digium.com/svn/asterisk/branches/13/contrib/ast-db-manage/config/versions/eb88a14f2a_add_media_encryption_optimistic_to_pjsip.py?view=auto&rev=428222 ============================================================================== --- branches/13/contrib/ast-db-manage/config/versions/eb88a14f2a_add_media_encryption_optimistic_to_pjsip.py (added) +++ branches/13/contrib/ast-db-manage/config/versions/eb88a14f2a_add_media_encryption_optimistic_to_pjsip.py Wed Nov 19 06:40:36 2014 @@ -1,0 +1,31 @@ +"""add media encryption optimistic to pjsip + +Revision ID: eb88a14f2a +Revises: 10aedae86a32 +Create Date: 2014-11-19 07:08:55.423018 + +""" + +# revision identifiers, used by Alembic. +revision = 'eb88a14f2a' +down_revision = '10aedae86a32' + +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects.postgresql import ENUM + +YESNO_NAME = 'yesno_values' +YESNO_VALUES = ['yes', 'no'] + +def upgrade(): + ############################# Enums ############################## + + # yesno_values have already been created, so use postgres enum object + # type to get around "already created" issue - works okay with mysql + yesno_values = ENUM(*YESNO_VALUES, name=YESNO_NAME, create_type=False) + + op.add_column('ps_endpoints', sa.Column('media_encryption_optimistic', yesno_values)) + + +def downgrade(): + op.drop_column('ps_endpoints', 'media_encryption_optimistic') Propchange: branches/13/contrib/ast-db-manage/config/versions/eb88a14f2a_add_media_encryption_optimistic_to_pjsip.py ------------------------------------------------------------------------------ svn:eol-style = native Propchange: branches/13/contrib/ast-db-manage/config/versions/eb88a14f2a_add_media_encryption_optimistic_to_pjsip.py ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision Propchange: branches/13/contrib/ast-db-manage/config/versions/eb88a14f2a_add_media_encryption_optimistic_to_pjsip.py ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: branches/13/include/asterisk/res_pjsip.h URL: http://svnview.digium.com/svn/asterisk/branches/13/include/asterisk/res_pjsip.h?view=diff&rev=428222&r1=428221&r2=428222 ============================================================================== --- branches/13/include/asterisk/res_pjsip.h (original) +++ branches/13/include/asterisk/res_pjsip.h Wed Nov 19 06:40:36 2014 @@ -483,6 +483,8 @@ unsigned int srtp_tag_32; /*! Do we use media encryption? what type? */ enum ast_sip_session_media_encryption encryption; + /*! Do we want to optimistically support encryption if possible? */ + unsigned int encryption_optimistic; }; /*! Modified: branches/13/include/asterisk/res_pjsip_session.h URL: http://svnview.digium.com/svn/asterisk/branches/13/include/asterisk/res_pjsip_session.h?view=diff&rev=428222&r1=428221&r2=428222 ============================================================================== --- branches/13/include/asterisk/res_pjsip_session.h (original) +++ branches/13/include/asterisk/res_pjsip_session.h Wed Nov 19 06:40:36 2014 @@ -73,6 +73,8 @@ struct ast_sip_session_sdp_handler *handler; /*! \brief Holds SRTP information */ struct ast_sdp_srtp *srtp; + /*! \brief What type of encryption is in use on this stream */ + enum ast_sip_session_media_encryption encryption; /*! \brief The media transport in use for this stream */ pj_str_t transport; /*! \brief Stream is on hold */ Modified: branches/13/res/res_pjsip.c URL: http://svnview.digium.com/svn/asterisk/branches/13/res/res_pjsip.c?view=diff&rev=428222&r1=428221&r2=428222 ============================================================================== --- branches/13/res/res_pjsip.c (original) +++ branches/13/res/res_pjsip.c Wed Nov 19 06:40:36 2014 @@ -430,6 +430,14 @@ </enumlist> </description> </configOption> + <configOption name="media_encryption_optimistic" default="no"> + <synopsis>Determines whether encryption should be used if possible but does not terminate the + session if not achieved.</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> <configOption name="inband_progress" default="no"> <synopsis>Determines whether chan_pjsip will indicate ringing using inband progress.</synopsis> @@ -1493,6 +1501,9 @@ </parameter> <parameter name="MediaEncryption"> <para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='endpoint']/configOption[@name='media_encryption']/synopsis/node())"/></para> + </parameter> + <parameter name="MediaEncryptionOptimistic"> + <para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='endpoint']/configOption[@name='media_encryption_optimistic']/synopsis/node())"/></para> </parameter> <parameter name="UseAvpf"> <para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='endpoint']/configOption[@name='use_avpf']/synopsis/node())"/></para> Modified: branches/13/res/res_pjsip/pjsip_configuration.c URL: http://svnview.digium.com/svn/asterisk/branches/13/res/res_pjsip/pjsip_configuration.c?view=diff&rev=428222&r1=428221&r2=428222 ============================================================================== --- branches/13/res/res_pjsip/pjsip_configuration.c (original) +++ branches/13/res/res_pjsip/pjsip_configuration.c Wed Nov 19 06:40:36 2014 @@ -1762,6 +1762,7 @@ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_setup", "", dtls_handler, dtlssetup_to_str, NULL, 0, 0); ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_fingerprint", "", dtls_handler, dtlsfingerprint_to_str, NULL, 0, 0); ast_sorcery_object_field_register(sip_sorcery, "endpoint", "srtp_tag_32", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.srtp_tag_32)); + ast_sorcery_object_field_register(sip_sorcery, "endpoint", "media_encryption_optimistic", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.encryption_optimistic)); ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "redirect_method", "user", redirect_handler, NULL, NULL, 0, 0); ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "set_var", "", set_var_handler, set_var_to_str, set_var_to_vl, 0, 0); ast_sorcery_object_field_register(sip_sorcery, "endpoint", "message_context", "", OPT_STRINGFIELD_T, 1, STRFLDSET(struct ast_sip_endpoint, message_context)); Modified: branches/13/res/res_pjsip_sdp_rtp.c URL: http://svnview.digium.com/svn/asterisk/branches/13/res/res_pjsip_sdp_rtp.c?view=diff&rev=428222&r1=428221&r2=428222 ============================================================================== --- branches/13/res/res_pjsip_sdp_rtp.c (original) +++ branches/13/res/res_pjsip_sdp_rtp.c Wed Nov 19 06:40:36 2014 @@ -494,13 +494,40 @@ ice->start(session_media->rtp); } +/*! \brief figure out if media stream has crypto lines for sdes */ +static int media_stream_has_crypto(const struct pjmedia_sdp_media *stream) +{ + int i; + + for (i = 0; i < stream->attr_count; i++) { + pjmedia_sdp_attr *attr; + + /* check the stream for the required crypto attribute */ + attr = stream->attr[i]; + if (pj_strcmp2(&attr->name, "crypto")) { + continue; + } + + return 1; + } + + return 0; +} + /*! \brief figure out media transport encryption type from the media transport string */ -static enum ast_sip_session_media_encryption get_media_encryption_type(pj_str_t transport) +static enum ast_sip_session_media_encryption get_media_encryption_type(pj_str_t transport, + const struct pjmedia_sdp_media *stream, unsigned int *optimistic) { RAII_VAR(char *, transport_str, ast_strndup(transport.ptr, transport.slen), ast_free); + + *optimistic = 0; + if (strstr(transport_str, "UDP/TLS")) { return AST_SIP_MEDIA_ENCRYPT_DTLS; } else if (strstr(transport_str, "SAVP")) { + return AST_SIP_MEDIA_ENCRYPT_SDES; + } else if (media_stream_has_crypto(stream)) { + *optimistic = 1; return AST_SIP_MEDIA_ENCRYPT_SDES; } else { return AST_SIP_MEDIA_ENCRYPT_NONE; @@ -523,20 +550,29 @@ { enum ast_sip_session_media_encryption incoming_encryption; char transport_end = stream->desc.transport.ptr[stream->desc.transport.slen - 1]; + unsigned int optimistic; if ((transport_end == 'F' && !endpoint->media.rtp.use_avpf) || (transport_end != 'F' && endpoint->media.rtp.use_avpf)) { return AST_SIP_MEDIA_TRANSPORT_INVALID; } - incoming_encryption = get_media_encryption_type(stream->desc.transport); + incoming_encryption = get_media_encryption_type(stream->desc.transport, stream, &optimistic); if (incoming_encryption == endpoint->media.rtp.encryption) { return incoming_encryption; } - if (endpoint->media.rtp.force_avp) { + if (endpoint->media.rtp.force_avp || + endpoint->media.rtp.encryption_optimistic) { return incoming_encryption; + } + + /* If an optimistic offer has been made but encryption is not enabled consider it as having + * no offer of crypto at all instead of invalid so the session proceeds. + */ + if (optimistic) { + return AST_SIP_MEDIA_ENCRYPT_NONE; } return AST_SIP_MEDIA_TRANSPORT_INVALID; @@ -697,7 +733,7 @@ const struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_media *stream) { - switch (session->endpoint->media.rtp.encryption) { + switch (session_media->encryption) { case AST_SIP_MEDIA_ENCRYPT_SDES: if (setup_sdes_srtp(session_media, stream)) { return -1; @@ -726,6 +762,8 @@ char host[NI_MAXHOST]; RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free_ptr); enum ast_media_type media_type = stream_to_media_type(session_media->stream_type); + enum ast_sip_session_media_encryption encryption = AST_SIP_MEDIA_ENCRYPT_NONE; + int res; /* If port is 0, ignore this media stream */ if (!stream->desc.port) { @@ -740,9 +778,12 @@ } /* Ensure incoming transport is compatible with the endpoint's configuration */ - if (!session->endpoint->media.rtp.use_received_transport && - check_endpoint_media_transport(session->endpoint, stream) == AST_SIP_MEDIA_TRANSPORT_INVALID) { - return -1; + if (!session->endpoint->media.rtp.use_received_transport) { + encryption = check_endpoint_media_transport(session->endpoint, stream); + + if (encryption == AST_SIP_MEDIA_TRANSPORT_INVALID) { + return -1; + } } ast_copy_pj_str(host, stream->conn ? &stream->conn->addr : &sdp->conn->addr, sizeof(host)); @@ -758,13 +799,27 @@ return -1; } - if (session->endpoint->media.rtp.use_received_transport) { + res = setup_media_encryption(session, session_media, sdp, stream); + if (res) { + if (!session->endpoint->media.rtp.encryption_optimistic) { + /* If optimistic encryption is disabled and crypto should have been enabled + * but was not this session must fail. + */ + return -1; + } + /* There is no encryption, sad. */ + session_media->encryption = AST_SIP_MEDIA_ENCRYPT_NONE; + } + + /* If we've been explicitly configured to use the received transport OR if + * encryption is on and crypto is present use the received transport. + * This is done in case of optimistic because it may come in as RTP/AVP or RTP/SAVP depending + * on the configuration of the remote endpoint (optimistic themselves or mandatory). + */ + if ((session->endpoint->media.rtp.use_received_transport) || + ((encryption == AST_SIP_MEDIA_ENCRYPT_SDES) && !res)) { pj_strdup(session->inv_session->pool, &session_media->transport, &stream->desc.transport); - } - - if (setup_media_encryption(session, session_media, sdp, stream)) { - return -1; - } + } if (set_caps(session, session_media, stream)) { return 0; @@ -788,7 +843,7 @@ static const pj_str_t STR_ACTPASS = { "actpass", 7 }; static const pj_str_t STR_HOLDCONN = { "holdconn", 8 }; - switch (session->endpoint->media.rtp.encryption) { + switch (session_media->encryption) { case AST_SIP_MEDIA_ENCRYPT_NONE: case AST_SIP_MEDIA_TRANSPORT_INVALID: break; @@ -922,11 +977,14 @@ } media->desc.media = pj_str(session_media->stream_type); - if (session->endpoint->media.rtp.use_received_transport && pj_strlen(&session_media->transport)) { + if (pj_strlen(&session_media->transport)) { + /* If a transport has already been specified use it */ 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, + /* Optimistic encryption places crypto in the normal RTP/AVP profile */ + !session->endpoint->media.rtp.encryption_optimistic && + (session_media->encryption == AST_SIP_MEDIA_ENCRYPT_SDES), session_media->rtp, session->endpoint->media.rtp.use_avpf, session->endpoint->media.rtp.force_avp)); } @@ -1062,7 +1120,7 @@ RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free_ptr); enum ast_media_type media_type = stream_to_media_type(session_media->stream_type); char host[NI_MAXHOST]; - int fdno; + int fdno, res; if (!session->channel) { return 1; @@ -1083,8 +1141,16 @@ return -1; } - if (setup_media_encryption(session, session_media, remote, remote_stream)) { - return -1; + res = setup_media_encryption(session, session_media, remote, remote_stream); + if (!session->endpoint->media.rtp.encryption_optimistic && res) { + /* If optimistic encryption is disabled and crypto should have been enabled but was not + * this session must fail. + */ + return -1; + } + + if (!remote_stream->conn && !remote->conn) { + return 1; } ast_copy_pj_str(host, remote_stream->conn ? &remote_stream->conn->addr : &remote->conn->addr, sizeof(host)); @@ -1135,6 +1201,9 @@ ast_queue_frame(session->channel, &ast_null_frame); session_media->held = 0; } + + /* This purposely resets the encryption to the configured in case it gets added later */ + session_media->encryption = session->endpoint->media.rtp.encryption; return 1; } Modified: branches/13/res/res_pjsip_session.c URL: http://svnview.digium.com/svn/asterisk/branches/13/res/res_pjsip_session.c?view=diff&rev=428222&r1=428221&r2=428222 ============================================================================== --- branches/13/res/res_pjsip_session.c (original) +++ branches/13/res/res_pjsip_session.c Wed Nov 19 06:40:36 2014 @@ -1000,6 +1000,7 @@ if (!session_media) { return CMP_STOP; } + session_media->encryption = session->endpoint->media.rtp.encryption; /* Safe use of strcpy */ strcpy(session_media->stream_type, handler_list->stream_type); ao2_link(session->media, session_media); @@ -1046,6 +1047,8 @@ return NULL; } + session->endpoint = ao2_bump(endpoint); + session->media = ao2_container_alloc(MEDIA_BUCKETS, session_media_hash, session_media_cmp); if (!session->media) { return NULL; @@ -1061,7 +1064,6 @@ ast_sip_dialog_set_endpoint(inv_session->dlg, endpoint); pjsip_dlg_inc_session(inv_session->dlg, &session_module); inv_session->mod_data[session_module.id] = ao2_bump(session); - session->endpoint = ao2_bump(endpoint); session->contact = ao2_bump(contact); session->inv_session = inv_session; session->req_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); -- _____________________________________________________________________ -- Bandwidth and Colocation Provided by http://www.api-digital.com -- svn-commits mailing list To UNSUBSCRIBE or update options visit: http://lists.digium.com/mailman/listinfo/svn-commits
