[Home]

Summary:ASTERISK-28657: SIPS TLS connection fails when session ticket extension is used
Reporter:Marcel Dischinger (marceldischinger)Labels:
Date Opened:2019-12-13 03:53:50.000-0600Date Closed:
Priority:MajorRegression?No
Status:Open/NewComponents:Channels/chan_sip/General
Versions:13.21.0 Frequency of
Occurrence
Constant
Related
Issues:
Environment:Tested with LTS certified, but according to the code this problem should apply to all newer versions as well. Using Debian Stretch and the dependencies used there (e.g., OpenSSL 1.1.0k). Using Asterisk with SIPS.Attachments:( 0) sip.conf
( 1) tls_sessionticket_test.pl
( 2) tlstest.pcap
Description:The TLS implementation of Asterisk using OpenSSL has a flaw that results in OpenSSL bailing with an internal error when a client tries to use session-reuse with the session ticket extension. This happens when Asterisk is used as a server for SIPS connections, i.e., SIPS-clients set up a TLS connection to Asterisk.

h2. How does this work?
# Client contacts Asterisk to set up a TLS connection
# Certificates are exchanged, keys are derived
# TLS session established
# Asterisk sends a TLS NewSessionTicket extension message (see RFC 5077) to the client
# TLS session is closed
# Client starts a new TLS session, sends the session ticket from 4. with the ClientHello
# Asterisk/OpenSSL should use this ticket to establish a new TLS session reusing the exchanged keys from the previous session.

h2. Bug analysis
From the asterisk log:
{quote}ERROR tcptls.c: Problem setting up ssl connection: error:00000001:lib(0):func(0):reason(1), Internal SSL error
WARNING tcptls.c: FILE * open {quote}

Reason for this is described in the warning for ssl_ctx_set_session_id_context in OpenSSL (see, e.g.,
https://linux.die.net/man/3/ssl_ctx_set_session_id_context): session id context is not set.

h2. Bugfix
To fix this, this context has to be set in  tcptls.c:__ssl_setup, e.g., directly before setting up the TLS options, right after setting up the general SSL-contect. There, add the following line:
SSL_CTX_set_session_id_context(cfg->ssl_ctx, (const unsigned char *) "asterisk", 8);

As an alternative, you can also disable the usage of RFC5077 by setting the SSL option SSL_OP_NO_TICKET. With this, Asterisk will no longer send the NewSessionTicket extension message, hence for the second TLS setup a SessionTicket is not included in the ClientHello.
Comments:By: Asterisk Team (asteriskteam) 2019-12-13 03:53:55.046-0600

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].

Please note that once your issue enters an open state it has been accepted. As Asterisk is an open source project there is no guarantee or timeframe on when your issue will be looked into. If you need expedient resolution you will need to find and pay a suitable developer. Asking for an update on your issue will not yield any progress on it and will not result in a response. All updates are posted to the issue when they occur.

By: Marcel Dischinger (marceldischinger) 2019-12-13 03:56:11.344-0600

Trace of TLS setup with Asterisk.
First, a TLS session is successfully established. See there the NewSessionTicket part.
The TLS session is then terminated by the client.
The client sets up a new session, sending the session ticket from the NewSessionTicket part now in the ClientHello, triggering the internal error in OpenSSL, leading to Asterisk closing the connection.

By: Marcel Dischinger (marceldischinger) 2019-12-13 04:00:59.331-0600

Perl script to test this behavior. You need an Asterisk setup to use SIPS.
The script requires some perl modules (in Ubuntu/Debian, these are libio-socket-ssl-perl, libnet-sip-perl).
perl tls_sessionticket_test.pl --cafile ca.pem --cert client.pem <AsteriskIp>:5061

The script sets up a TLS session, then closes it. A second TLS session is set up, reusing the session context (and thus the session ticket) of the previous session if possible.

By: Kevin Harwell (kharwell) 2019-12-17 14:00:22.881-0600

[~mdspam@gmx.de],

Thanks for the script to replicate. Unfortunately even with the script I am unable to replicate the problem. Even going back to 13.21.0 I run the script and see no errors in Asterisk. The script outputs the following:

connection 1 success, resume=no
connection 2 success, resume=yes

So it appears the connection gets reused. Maybe I am missing something. Can you attach the _sip.conf_ you used?

By: Marcel Dischinger (marceldischinger) 2019-12-18 08:32:02.884-0600

@kharwell
Thanks for looking into this. I am attaching my sip.conf.
According to the manpage of ssl_ctx_set_session_id_context the problem only occurs if client certificates are used. Maybe the clientverify-option does the trick.

By: Kevin Harwell (kharwell) 2019-12-18 18:16:40.919-0600

Hrm, not really sure what could be the problem here. It seems pretty straight forward, but I am unable to replicate. I installed Debian 9, and installed the same version of openssl just to make sure that wasn't it:
{noformat}
$ openssl version
OpenSSL 1.1.0k  28 May 2019
{noformat}
I also used your _sip.conf_ file. As far as the {{tlsverifyclient}} configuration option goes that is not used, and is ignored by chan_sip so I don't think that could be it.

And attempting to replicate using pjsip causes a different error down in pjproject, which I suspect has more to do with test client.

By: Marcel Dischinger (marceldischinger) 2019-12-19 03:58:17.791-0600

Ah, there might be an explanation. I patched chan_sip.c to use tlsverifyclient, which works for me just fine (the code below omits the check of the return value of ast_tls_read_conf for brevity).
{noformat}
if (!strcasecmp(v->name, "tlsverifyclient")) {
- ast_log(LOG_WARNING, "Ignoring unsupported option 'tlsverifyclient'\n");
- continue;
+                       ast_tls_read_conf(&default_tls_cfg, &sip_tls_desc, v->name, v->value);
}
{noformat}

But this would then mean that there is in fact no problem in Asterisk (at least not in the setup I described), but the patch I did had side effects.

Nevertheless, I learned from this problem that it is rather easy to mess up OpenSSL usage. So it may be a safeguard to set up the session ID context just to avoid future problems.

By: Kevin Harwell (kharwell) 2019-12-19 09:03:51.675-0600

Ah yeah that's probably it then.

While I do agree having the safeguard could be a good thing, it's not something we will get to without a known bug directly causing the issue, or a provided patch. That being said do you have any interest in providing a patch to add the safeguard? If so I'll leave this issue open.

If you are interested please see the wiki on how to contribute a patch [1]. It'll guide you through signing a contributor's license [2] if haven't already, and getting the patch submitted to gerrit [3] for code review [4].

[1] https://wiki.asterisk.org/wiki/display/AST/Patch+Contribution+Process
[2] https://issues.asterisk.org/jira/secure/DigiumLicense.jspa
[3] https://wiki.asterisk.org/wiki/display/AST/Gerrit+Usage
[4] https://wiki.asterisk.org/wiki/display/AST/Code+Review

Thanks!

By: Marcel Dischinger (marceldischinger) 2019-12-20 03:36:32.500-0600

OK, I will provide a patch then.

By: Marcel Dischinger (marceldischinger) 2020-04-21 09:07:48.634-0500

I tried the instructions for [3] (following it step by step), but I fail to make it work.
Clone works (git clone ssh://asterisk/asterisk), 'git review -s' works (at least no errors).
But then I want to checkout the branch for version 13 (git checkout 13), which does not work, as with git review I have now two remotes with a branch 13 each, gerrit and origin (or do I overlook something here?)
So I tried the rest with both (git checkout remotes/origin/13 and git checkout remotes/gerrit/13 - as other things also do not work) and created a local branch with the name of the ticket, as described.

I made my changes and want to commit it using git commit. I do not get the Change-Id field in the commit-comment, so this is clearly wrong and a problem.
So something is wrong, not sure if it is my setup or the description in [3].
Can someone please give me advice how to get this work (I am trying this in an up-to-date Debian Stable installation)?

By: Kevin Harwell (kharwell) 2020-04-21 11:05:53.042-0500

Any kind of error message shown when issuing any of the commands?

If "git checkout 13" doesn't work try the the following when checking out a remote branch:
{noformat}
$ git checkout -b 13 origin/13
{noformat}
Once on the mainline branch then create another branch for the issue:
{noformat}
$ git checkout -b ASTERISK-<issue num>
{noformat}
The "Change-Id" is added after committing your change locally. If it's not there try the following again:
{noformat}
$ git review -s
{noformat}
and then
{noformat}
$ git commit --amend
{noformat}
and then save/close. A "git log" , or "git show" will show the commit and you can verify if the "Change-Id" now exists. If not, or you got an error when downloading the script try something like the following:
{noformat}
$ scp -p -P 29418 <username>@gerrit.asterisk.org:hooks/commit-msg ".git/hooks/"
{noformat}
Then "git commit --amend", etc...

By: Kevin Harwell (kharwell) 2020-04-21 11:09:42.674-0500

Also if you are still having trouble you might try out the #asterisk-dev IRC [1] channel. It'd might be easier to explain things there, and get help in realtime for a quicker turnaround.

[1] https://wiki.asterisk.org/wiki/display/AST/IRC

By: Marcel Dischinger (marceldischinger) 2020-04-22 07:00:01.067-0500

Thanks a lot, the Wiki is not up to date here apparently. The --amend for the commit did the trick.