Bug 55707 - SSLProtocol directive seem to be ignored over different virtualhosts on the same ip+port
Summary: SSLProtocol directive seem to be ignored over different virtualhosts on the s...
Status: NEW
Alias: None
Product: Apache httpd-2
Classification: Unclassified
Component: mod_ssl (show other bugs)
Version: 2.4.6
Hardware: All All
: P2 normal with 6 votes (vote)
Target Milestone: ---
Assignee: Apache HTTPD Bugs Mailing List
URL:
Keywords: PatchAvailable
Depends on:
Blocks:
 
Reported: 2013-10-25 19:35 UTC by cf0hay
Modified: 2018-06-01 17:34 UTC (History)
8 users (show)



Attachments
Reject connections not conforming to vhost SSLProtocol (1.86 KB, patch)
2018-04-09 05:06 UTC, Mike Haller
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description cf0hay 2013-10-25 19:35:22 UTC
I have more than one virtualhosts configured over the same IP address and port. The first one has these directives (uses RSA):

SSLProtocol TLSv1.2 +TLSv1.1 +TLSv1
SSLCipherSuite ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:DES-CBC3-SHA

The second one only these (uses EC):

SSLProtocol TLSv1.2
SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA
SSLStrictSNIVHostCheck on

Non-SNI clients get 403 properly. But if a client supports SNI, and negotiates with TLSv1.1 or TLSv1, the request will be accepted and the page served. With an SNI client, the SSLCipherSuite list will get used properly, but the SSLProtocol directive is totally ignored. From the ClientHello the SNI-capability can be detected, so does the used protocol version. TLS negotiation should be denied the same way if there is no common protocol version as it would without common ciphers.
Comment 1 Kaspar Brand 2013-11-30 08:06:17 UTC
Confirmed. It's due to a current limitation in OpenSSL, actually - when we use  SSL_set_SSL_CTX() in the SNI callback in ssl_engine_kernel.c, OpenSSL only switches the certificate, but not any of the other settings.

I have filed

  https://rt.openssl.org/Ticket/Display.html?user=guest&pass=guest&id=3183

meanwhile, and on the mod_ssl side, we are basically stuck with fixing this in a sane way until it's addressed in OpenSSL. If you're compiling against OpenSSL before 1.0.0, you could apply this patch, in theory (but note that this fiddles with OpenSSL internals, and is not the way forward to fix the issue):

--- ssl_engine_kernel.c (revision 1546692)
+++ ssl_engine_kernel.c (working copy)
@@ -2014,6 +2014,7 @@ static int ssl_find_vhost(void *servername, conn_r
             SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx),
                            SSL_CTX_get_verify_callback(ctx));
         }
+        SSL_set_ssl_method(ssl, ctx->method);

         /*
          * Adjust the session id context. ssl_init_ssl_connection()
Comment 2 Charles Parker 2017-05-16 12:10:45 UTC
(In reply to Kaspar Brand from comment #1)
> Confirmed. It's due to a current limitation in OpenSSL, actually - when we
> use  SSL_set_SSL_CTX() in the SNI callback in ssl_engine_kernel.c, OpenSSL
> only switches the certificate, but not any of the other settings.
> 
> I have filed
> 
>   https://rt.openssl.org/Ticket/Display.html?user=guest&pass=guest&id=3183
> 

This OpenSSL bug was marked as resolved on October 13, 2016. I don't see any indication of which version(s) contain the fix, however.
Comment 3 Rainer Jung 2017-05-16 21:34:31 UTC
The OpenSSL RT ticket was only closed as part of a mass update of old ticket. From a mail to the OpenSSL dev list:

Here is the list of old RT tickets that we are closing.  We sent email
to all of the originators, and it included the following text:

If you still think it is important for us to consider, please open an
issue on GitHub.  Don't be shy!  We are closing issues based purely
on the date, and the fact that despite several passes through our RT
tickets, we haven't closed them yet.

...

3183 SSL_set_SSL_CTX() should apply more settings from the SSL_CTX being switched to
...

So this wasn't actually fixed, at least not at that time.

Regards,

Rainer
Comment 4 Abir Ahmed 2017-09-01 00:15:32 UTC
Hey guys,

It's been a long time that it has been an issue. I am having the same trouble.

I contacted openssl git page and they said it's because how Apache handles openssl.

I tried with both 1.0.2 and 1.1.0 and it's still not working.

Is there any workaround I can apply? It's pretty urgent.

Thank you
Comment 5 nada 2017-09-01 09:31:14 UTC
Just for the reference: here is the re-reported issue for OpenSSL on GitHub: https://github.com/openssl/openssl/issues/4302
Comment 6 Abir Ahmed 2017-09-01 17:07:27 UTC
This is the issue where they replied. See their latest response.

Link: https://github.com/openssl/openssl/issues/4301
Comment 7 Mike Haller 2018-04-09 05:06:53 UTC
Created attachment 35848 [details]
Reject connections not conforming to vhost SSLProtocol

This was developed and tested with 2.4.27 and in production with that
version.  The patch was modified for 2.4.33 and lightly tested.

This checks the version of the connection against the SSLProtocol
configured for the virtual host that is matched based on the SNI.
Because the connection is initially made with the SSLProtocol configured
for the default host for the port, the default host must include all
protocols that will be supported by any virtual host.

This patch adds an additional return status of APR_EMISMATCH to the
init_vhost function so that the ssl_callback_ServerNameIndication
callback registered with OpenSSL can return fatal alert
SSL_AD_PROTOCOL_VERSION. This is intended to produce the same response
to the ClientHello as having an SSLProtocol specified that does not
include the version in question.  Because the SNI callback is called
during the processing of the ClientHello and before a response is
produced, it seems to do exactly that.

Feedback is welcome.
Comment 8 Stefan Eissing 2018-04-11 08:43:07 UTC
Feedback on the patch:

Yes, this will work and prevent connections to a vhost with an SSL protocol version that is not allowed there. However.

When I imagine being the user who typed a URL into my browser - and ran into this behaviour - what would I be expected to do? Is there, in this setup, a way to successfully connect to the vhost? I don't see it.

If we can agree that this is an undesirable situation, the only fix - besides re-implementing mod_ssl and vhosts in a non 2.4.x compatible way - is that the *server admin* gets an ERR/WARNING by a post config check in mod_ssl.

(Since we are talking about fixes in 2.4.x, WARNING is the only option unless we introduce a "SSLVHostChecks strict" or some such.)

So, IMO, the patch is good, but not enough.

Feedback?
Comment 9 Mike Haller 2018-04-11 14:45:12 UTC
Thanks for looking Stefan.

> Is there, in this setup, a way to successfully connect to the vhost?

The point of the patch is to prevent a successful connection to the vhost at
the TLS protocol layer. If that's not what you want and you instead wish to
produce a friendly error message for some versions, you can already configure
mod_ssl to accept all versions, and to publish the SSL_PROTOCOL env var, and
then use any number of ways (e.g. rewrite, setenvif) to produce an error page
if there is a version you do not wish to accept.

> ... the *server admin* gets an ERR/WARNING by a post config check in
> mod_ssl.

From a user's perspective, they see behavior no different than if they attempt
to connect with a TLS version that is not specified in the default server's
SSLProtocol: a protocol version alert. Is the startup warning suggestion
because this patch changes the existing behavior that current configurations
will accept versions that are not allowed by a vhost's SSLProtocol?
Comment 10 Stefan Eissing 2018-04-12 09:17:19 UTC
I am fine with the patch. What I am after is: is a configuration that triggers the patch not really a configuration error?

Simplified:
<vhost A>
  SSLProtocol TLSv1.2
</vhost>

<vhost B>
  SSLProtocol TLSv1.3
</vhost>

Is a client that speaks both TLSv1.2 and TLSv1.3 able to connect to vhost B at all?
Comment 11 Mike Haller 2018-04-12 14:16:53 UTC
> Is a client that speaks both TLSv1.2 and TLSv1.3 able to connect to vhost B
> at all?

Yes. Such a client could speak to both.

The case I am solving is this:

<vhost A>
  SSLProtocol +TLSV1 +TLSV1.1 +TLSV1.2
</vhost A>

<vhost B>
  SSLProtocol +TLSV1.2
</vhost B>

This configuration allows for vhost B to accept only the newest protocol
implemented in 2.4.33.

It will function as expected if you write "SSLProtocol +TLSV1.1" for vhost B.
However, I would not consider that a useful configuration because I think that
the concept "minimum TLS version needed to connect to this host" is more
likely than arbitrarily specifying versions. For example, PCI DSS (the credit
card security standard) is requiring that TLSv1 and TLSv1.1 can no longer be
used to connect after June 30, 2018, but allows for any newer protocols TLSv1.2, TLSv1.3, etc.
Comment 12 Stefan Eissing 2018-04-12 14:22:29 UTC
You are solving the puzzle by changing the puzzle. ;-)

Your example is valid and would be improved by the patch and work and no error should be logged. Okay?

Do you agree that in *my* example:
<vhost A>
  SSLProtocol TLSv1.2
</vhost>

<vhost B>
  SSLProtocol TLSv1.3
</vhost>

the configuration is in error and the admin should at least be WARNED that a connection to vhost B is not possible at all?
Comment 13 Mike Haller 2018-04-12 17:17:03 UTC
I made a mistake earlier in mentioning the default host. The default setting
appears to come from the root configuration ap_server_conf and not the default
server. The built-in default config is "all -SSLv3" which is why I state you
can connect to vhost B above. If your example is based on my mistake of
mentioning the default host, and we adapt it to:

SSLProtocol TLSv1.1
<vhost B>
  SSLProtocol TLSv1.2
</vhost>

Then this *does* lead to the situation where vhost B cannot be connected to.
And it does make sense to have a warning there.
Comment 14 Dennis Clarke 2018-05-28 07:55:35 UTC

Is testing possible with TLSv1.3 and Apache/2.4.33 (Unix) OpenSSL/1.1.1-pre6 ? 

I see the following error if I attempt to use a new tls 1.3 cipher from
latest beta openssl : 

AH00526: Syntax error on line 19 of /usr/local/www/conf/extra/httpd-ssl.conf:
SSLProtocol: Illegal protocol 'TLSv1.3'


# /usr/local/bin/openssl version 
OpenSSL 1.1.1-pre6 (beta) 1 May 2018

# /usr/local/bin/openssl ciphers -V -tls1_3 -s 
          0x13,0x02 - TLS_AES_256_GCM_SHA384  TLSv1.3 Kx=any      Au=any  Enc=AESGCM(256) Mac=AEAD
          0x13,0x03 - TLS_CHACHA20_POLY1305_SHA256 TLSv1.3 Kx=any      Au=any  Enc=CHACHA20/POLY1305(256) Mac=AEAD
          0x13,0x01 - TLS_AES_128_GCM_SHA256  TLSv1.3 Kx=any      Au=any  Enc=AESGCM(128) Mac=AEAD


However I should be able to run tests?
Comment 15 Dennis Clarke 2018-06-01 17:34:10 UTC
I am doing tests with TLSv1.3 on httpd-2.5-trunk per : 

    https://bz.apache.org/bugzilla/show_bug.cgi?id=62413

also :

    https://bz.apache.org/bugzilla/show_bug.cgi?id=62417

Thus far everything seems to be working fine with the obvious exception
that no browser can connect to the site. Yet. May be a CipherSuite 
issue wherein Mozilla FireFox ver 62.0a1 does support TLS1.3 and I have
tested this via https://tls13.crypto.mozilla.org/ which works fine and 
offers TLS 1.3 (draft 28) which seems to offer TLS_AES_128_GCM_SHA256
as the cipher.