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

Reply via email to