[Home]

Summary:ASTERISK-27031: res_pjsip: Unable to configure TLSv1.2 on TLS transport
Reporter:delvar (delvar)Labels:
Date Opened:2017-06-02 09:54:06Date Closed:2018-04-04 04:43:25
Priority:MajorRegression?
Status:Closed/CompleteComponents:Resources/res_pjsip
Versions:13.16.0 Frequency of
Occurrence
Constant
Related
Issues:
Environment:Centos 7Attachments:
Description:When setting up a transport i am unable to enforce TLS1.2, only TLS1.0.

h3. My pjsip.conf

{noformat}
[transport-tls]
type=transport
protocol=tls
bind=0.0.0.0:5061
cert_file=/etc/asterisk/keys/cert.pem
priv_key_file=/etc/asterisk/keys/privkey.pem
method=tlsv1
{noformat}


h3. When testing tls1.2 with OpenSSL
{noformat}
openssl s_client -tls1_2 -host gw03.dev -port 5061
CONNECTED(00000003)
140260503979936:error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number:s3_pkt.c:339:
{noformat}

When testing with OpenSSL and not using the -tls1_2 option it works as expected and the TLS handshake completes. (not shown here)

h3. Asterisk Code
https://github.com/asterisk/asterisk/blob/13.16/res/res_pjsip/config_transport.c we see the list of allowed values and the mapped PJSIP Methods on line 885+
{noformat}
if (ast_strlen_zero(var->value) || !strcasecmp(var->value, "default")) {
state->tls.method = PJSIP_SSL_DEFAULT_METHOD;
} else if (!strcasecmp(var->value, "unspecified")) {
state->tls.method = PJSIP_SSL_UNSPECIFIED_METHOD;
} else if (!strcasecmp(var->value, "tlsv1")) {
state->tls.method = PJSIP_TLSV1_METHOD;
} else if (!strcasecmp(var->value, "sslv2")) {
state->tls.method = PJSIP_SSLV2_METHOD;
} else if (!strcasecmp(var->value, "sslv3")) {
state->tls.method = PJSIP_SSLV3_METHOD;
} else if (!strcasecmp(var->value, "sslv23")) {
state->tls.method = PJSIP_SSLV23_METHOD;
} else {
return -1;
}
{noformat}
As you can see there is no mapping for PJSIP_TLSV1_2_METHOD,

h3. PJSIP Code

http://svn.pjsip.org/repos/pjproject/trunk/pjsip/src/pjsip/sip_transport_tls.c

{noformat}
  switch(ssl_method) {
   case PJSIP_SSLV2_METHOD:
out_proto = PJ_SSL_SOCK_PROTO_SSL2;
break;
   case PJSIP_SSLV3_METHOD:
out_proto = PJ_SSL_SOCK_PROTO_SSL3;
break;
   case PJSIP_TLSV1_METHOD:
out_proto = PJ_SSL_SOCK_PROTO_TLS1;
break;
   case PJSIP_TLSV1_1_METHOD:
out_proto = PJ_SSL_SOCK_PROTO_TLS1_1;
break;
   case PJSIP_TLSV1_2_METHOD:
out_proto = PJ_SSL_SOCK_PROTO_TLS1_2;
break;
   case PJSIP_SSLV23_METHOD:
out_proto = PJ_SSL_SOCK_PROTO_SSL23;
break;
   default:
out_proto = PJ_SSL_SOCK_PROTO_DEFAULT;
break;
   }  
{noformat}

h3. Critical
This is critical as TLS 1 and 1.1 are vulnerable to a range of exploits and should not be used.
https://blog.varonis.com/ssl-and-tls-1-0-no-longer-acceptable-for-pci-compliance/
Comments:By: Asterisk Team (asteriskteam) 2017-06-02 09:54:07.386-0500

Thanks for creating a report! The issue has entered the triage process. That means the issue will wait in this status until a Bug Marshal has an opportunity to review the issue. Once the issue has been reviewed you will receive comments regarding the next steps towards resolution.

A good first step is for you to review the [Asterisk Issue Guidelines|https://wiki.asterisk.org/wiki/display/AST/Asterisk+Issue+Guidelines] if you haven't already. The guidelines detail what is expected from an Asterisk issue report.

Then, if you are submitting a patch, please review the [Patch Contribution Process|https://wiki.asterisk.org/wiki/display/AST/Patch+Contribution+Process].

By: Bernhard Schmidt (bschmidt) 2017-08-31 05:25:02.267-0500

The corresponding Debian bug for this is https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=873798.

Setting it to "default" (or not setting it at all) should, as far as I can see, do the following

PJSIP_SSL_DEFAULT_METHOD -> PJ_SSL_SOCK_PROTO_DEFAULT

{noformat}
   if (ssock->param.proto == PJ_SSL_SOCK_PROTO_DEFAULT)
       ssock->param.proto = PJ_SSL_SOCK_PROTO_SSL23;

   /* Determine SSL method to use */
   switch (ssock->param.proto) {
   case PJ_SSL_SOCK_PROTO_TLS1:
       ssl_method = (SSL_METHOD*)TLSv1_method();
       break;
#ifndef OPENSSL_NO_SSL2
   case PJ_SSL_SOCK_PROTO_SSL2:
       ssl_method = (SSL_METHOD*)SSLv2_method();
       break;
#endif
#ifndef OPENSSL_NO_SSL3_METHOD
   case PJ_SSL_SOCK_PROTO_SSL3:
       ssl_method = (SSL_METHOD*)SSLv3_method();
#endif
       break;
   }

   if (!ssl_method) {
       ssl_method = (SSL_METHOD*)SSLv23_method();

#ifdef SSL_OP_NO_SSLv2
       /** Check if SSLv2 is enabled */
       ssl_opt |= ((ssock->param.proto & PJ_SSL_SOCK_PROTO_SSL2)==0)?
                   SSL_OP_NO_SSLv2:0;
#endif

#ifdef SSL_OP_NO_SSLv3
       /** Check if SSLv3 is enabled */
       ssl_opt |= ((ssock->param.proto & PJ_SSL_SOCK_PROTO_SSL3)==0)?
                   SSL_OP_NO_SSLv3:0;
#endif

#ifdef SSL_OP_NO_TLSv1
       /** Check if TLSv1 is enabled */
       ssl_opt |= ((ssock->param.proto & PJ_SSL_SOCK_PROTO_TLS1)==0)?
                   SSL_OP_NO_TLSv1:0;
#endif

#ifdef SSL_OP_NO_TLSv1_1
       /** Check if TLSv1_1 is enabled */
       ssl_opt |= ((ssock->param.proto & PJ_SSL_SOCK_PROTO_TLS1_1)==0)?
                   SSL_OP_NO_TLSv1_1:0;
#endif

#ifdef SSL_OP_NO_TLSv1_2
       /** Check if TLSv1_2 is enabled */
       ssl_opt |= ((ssock->param.proto & PJ_SSL_SOCK_PROTO_TLS1_2)==0)?
                   SSL_OP_NO_TLSv1_2:0;

#endif
{noformat}

and

{noformat}
   /**
    * Certain backend implementation e.g:OpenSSL, has feature to enable all
    * protocol.
    */
   PJ_SSL_SOCK_PROTO_SSL23   = (1 << 16) - 1,
{noformat}

By: Bernhard Schmidt (bschmidt) 2017-08-31 05:31:25.376-0500

Note that the code above was from pjproject 2.5.5, it looks very different in 2.6

{noformat}
   if (openssl_cipher_num == 0 || openssl_curves_num == 0) {
       SSL_METHOD *meth = NULL;
       SSL_CTX *ctx;
       SSL *ssl;
       STACK_OF(SSL_CIPHER) *sk_cipher;
       unsigned i, n;
       int nid;
       const char *cname;

       meth = (SSL_METHOD*)SSLv23_server_method();
       if (!meth)
           meth = (SSL_METHOD*)TLSv1_server_method();
#ifndef OPENSSL_NO_SSL3_METHOD
       if (!meth)
           meth = (SSL_METHOD*)SSLv3_server_method();
#endif
#ifndef OPENSSL_NO_SSL2
       if (!meth)
           meth = (SSL_METHOD*)SSLv2_server_method();
#endif
       pj_assert(meth);

       ctx=SSL_CTX_new(meth);
{noformat}

so the default is SSLv23_server_method(), which is deprecated but should enable all of SSLv3, TLSv1, TLSv1.1 and TLSv1.2 according to  https://wiki.openssl.org/index.php/Manual:SSL_CTX_new(3).

My test Asterisk uses pjproject 2.5.5

By: Tzafrir Cohen (tzafrir) 2018-04-04 03:13:44.700-0500

In https://bugs.debian.org/873798 Bernhard Schmidt reported that this bug was resolved in https://github.com/asterisk/asterisk/commit/ec1f4bf48df6b893268ed36439a8680b7e4a253e and that Asterisk 13.19.0 and 15.2.0 are now OK.

By: Alexander Traud (traud) 2020-10-27 12:04:24.895-0500

[~tzafrir], I do not think the actual request was fixed. The reporter [~delvar] was looking for a way to raise the _minimum_ version from the system provided default {{method=sslv23}} to TLS 1.2 and newer. Now three years later with TLS 1.3, the issue reappeared in ASTERISK-29017…