Commit Graph

573 Commits

Author SHA1 Message Date
William Lallemand
786188f6bf BUG/MINOR: ssl: fix error messages for OCSP loading
The error messages for OCSP in ssl_sock_load_crt_file_into_ckch() add a
double extension to the filename, that can be confusing. The messages
reference a .issuer.issuer file.
2019-10-15 13:50:20 +02:00
William Lallemand
4a66013069 BUG/MINOR: ssl: fix OCSP build with BoringSSL
246c024 broke the build of the OCSP code with BoringSSL.

Rework it a little so it could load the OCSP buffer of the ckch.

Issue #322.
2019-10-14 15:07:44 +02:00
William Lallemand
104a7a6c14 BUILD: ssl: wrong #ifdef for SSL engines code
The SSL engines code was written below the OCSP #ifdef, which means you
can't build the engines code if the OCSP is deactived in the SSL lib.

Could be backported in every version since 1.8.
2019-10-14 15:07:44 +02:00
William Lallemand
963b2e70ba BUG/MINOR: ssl: fix build without multi-cert bundles
Commit 150bfa8 broke the build with ssl libs that does not support
multi certificate bundles.

Issue #322.
2019-10-14 11:41:18 +02:00
William Lallemand
e15029bea9 BUG/MEDIUM: ssl: NULL dereference in ssl_sock_load_cert_sni()
A NULL dereference can occur when inserting SNIs. In the case of
checking for duplicates, if there is already several sni_ctx with the
same key.

Fix issue #321.
2019-10-14 10:57:16 +02:00
William Lallemand
246c0246d3 MINOR: ssl: load the ocsp in/from the ckch
Don't try to load the files containing the issuer and the OCSP response
each time we generate a SSL_CTX.

The .ocsp and the .issuer are now loaded in the struct
cert_key_and_chain only once and then loaded from this structure when
creating a SSL_CTX.
2019-10-11 17:32:03 +02:00
William Lallemand
a17f4116d5 MINOR: ssl: load the sctl in/from the ckch
Don't try to load the file containing the sctl each time we generate a
SSL_CTX.

The .sctl is now loaded in the struct cert_key_and_chain only once and
then loaded from this structure when creating a SSL_CTX.

Note that this now make possible the use of sctl with multi-cert
bundles.
2019-10-11 17:32:03 +02:00
William Lallemand
150bfa84e3 MEDIUM: ssl/cli: 'set ssl cert' updates a certificate from the CLI
$ echo -e "set ssl cert certificate.pem <<\n$(cat certificate2.pem)\n" | \
    socat stdio /var/run/haproxy.stat
    Certificate updated!

The operation is locked at the ckch level with a HA_SPINLOCK_T which
prevents the ckch architecture (ckch_store, ckch_inst..) to be modified
at the same time. So you can't do a certificate update at the same time
from multiple CLI connections.

SNI trees are also locked with a HA_RWLOCK_T so reading operations are
locked only during a certificate update.

Bundles are supported but you need to update each file (.rsa|ecdsa|.dsa)
independently. If a file is used in the configuration as a bundle AND
as a unique certificate, both will be updated.

Bundles, directories and crt-list are supported, however filters in
crt-list are currently unsupported.

The code tries to allocate every SNIs and certificate instances first,
so it can rollback the operation if that was unsuccessful.

If you have too much instances of the certificate (at least 20000 in my
tests on my laptop), the function can take too much time and be killed
by the watchdog. This will be fixed later. Also with too much
certificates it's possible that socat exits before the end of the
generation without displaying a message, consider changing the socat
timeout in this case (-t2 for example).

The size of the certificate is currently limited by the maximum size of
a payload, that must fit in a buffer.
2019-10-11 17:32:03 +02:00
William Lallemand
f11365b26a MINOR: ssl: ssl_sock_load_crt_file_into_ckch() is filling from a BIO
The function ssl_sock_load_crt_file_into_ckch() is now able to fill a
ckch using a BIO in input.
2019-10-11 17:32:03 +02:00
William Lallemand
614ca0d370 MEDIUM: ssl: ssl_sock_load_ckchs() alloc a ckch_inst
The ssl_sock_load_{multi}_ckchs() function were renamed and modified:

- allocate a ckch_inst and loads the sni in it
- return a ckch_inst or NULL
- the sni_ctx are not added anymore in the sni trees from there
- renamed in ckch_inst_new_load_{multi}_store()
- new ssl_sock_load_ckchs() function calls
ckch_inst_new_load_{multi}_store() and add the sni_ctx to the sni trees.
2019-10-11 17:32:03 +02:00
William Lallemand
0c6d12fb66 MINOR: ssl: ssl_sock_load_multi_ckchs() can properly fail
ssl_sock_load_multi_ckchs() is now able to fail without polluting the
bind_conf trees and leaking memory.

It is a prerequisite to load certificate on-the-fly with the CLI.

The insertion of the sni_ctxs in the trees are done once everything has
been allocated correctly.
2019-10-11 17:32:03 +02:00
William Lallemand
d919937991 MINOR: ssl: ssl_sock_load_ckchn() can properly fail
ssl_sock_load_ckchn() is now able to fail without polluting the
bind_conf trees and leaking memory.

It is a prerequisite to load certificate on-the-fly with the CLI.

The insertion of the sni_ctxs in the trees are done once everything has
been allocated correctly.
2019-10-11 17:32:03 +02:00
William Lallemand
1d29c7438e MEDIUM: ssl: split ssl_sock_add_cert_sni()
In order to allow the creation of sni_ctx in runtime, we need to split
the function to allow rollback.

We need to be able to allocate all sni_ctxs required before inserting
them in case we need to rollback if we didn't succeed the allocation.

The function was splitted in 2 parts.

The first one ckch_inst_add_cert_sni() allocates a struct sni_ctx, fill
it with the right data and insert it in the ckch_inst's list of sni_ctx.

The second will take every sni_ctx in the ckch_inst and insert them in
the bind_conf's sni tree.
2019-10-11 17:32:03 +02:00
William Lallemand
9117de9e37 MEDIUM: ssl: introduce the ckch instance structure
struct ckch_inst represents an instance of a certificate (ckch_node)
used in a bind_conf. Every sni_ctx created for 1 ckch_node in a
bind_conf are linked in this structure.

This patch allocate the ckch_inst for each bind_conf and inserts the
sni_ctx in its linked list.
2019-10-11 17:32:03 +02:00
William Lallemand
28a8fce485 BUG/MINOR: ssl: abort on sni_keytypes allocation failure
The ssl_sock_populate_sni_keytypes_hplr() function does not return an
error upon an allocation failure.

The process would probably crash during the configuration parsing if the
allocation fail since it tries to copy some data in the allocated
memory.

This patch could be backported as far as 1.5.
2019-10-11 17:32:02 +02:00
William Lallemand
8ed5b96587 BUG/MINOR: ssl: free the sni_keytype nodes
This patch frees the sni_keytype nodes once the sni_ctxs have been
allocated in ssl_sock_load_multi_ckchn();

Could be backported in every version using the multi-cert SSL bundles.
2019-10-11 17:32:02 +02:00
William Lallemand
fe49bb3d0c BUG/MINOR: ssl: abort on sni allocation failure
The ssl_sock_add_cert_sni() function never return an error when a
sni_ctx allocation fail. It silently ignores the problem and continues
to try to allocate other snis.

It is unlikely that a sni allocation will succeed after one failure and
start a configuration without all the snis. But to avoid any problem we
return a -1 upon an sni allocation error and stop the configuration
parsing.

This patch must be backported in every version supporting the crt-list
sni filters. (as far as 1.5)
2019-10-11 17:32:02 +02:00
William Lallemand
4b989f2fac MINOR: ssl: initialize the sni_keytypes_map as EB_ROOT
The sni_keytypes_map was initialized to {0}, it's better to initialize
it explicitly to EB_ROOT
2019-10-11 17:32:02 +02:00
William Lallemand
f6adbe9f28 REORG: ssl: move structures to ssl_sock.h 2019-10-11 17:32:02 +02:00
William Lallemand
e3af8fbad3 REORG: ssl: rename ckch_node to ckch_store
A ckch_store is a storage which contains a pointer to one or several
cert_key_and_chain structures.

This patch renames ckch_node to ckch_store, and ckch_n, ckchn to ckchs.
2019-10-11 17:32:02 +02:00
William Lallemand
eed4bf234e MINOR: ssl: crt-list do ckchn_lookup 2019-10-11 17:32:02 +02:00
William Lallemand
1633e39d91 BUILD: ssl: fix a warning when built with openssl < 1.0.2
src/ssl_sock.c:2928:12: warning: ‘ssl_sock_is_ckch_valid’ defined but not used [-Wunused-function]
 static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)

This function is only used with openssl >= 1.0.2, this patch adds a
condition to build the function.
2019-09-30 13:40:53 +02:00
Christopher Faulet
82004145d4 BUG/MINOR: ssl: always check for ssl connection before getting its XPRT context
In several SSL functions, the XPRT context is retrieved before any check on the
connection. In the function ssl_sock_is_ssl(), a test suggests the connection
may be null. So, it is safer to test the ssl connection before retrieving its
XPRT context. It removes any ambiguities and prevents possible null pointer
dereferences.

This patch fixes the issue #265. It must be backported to 2.0.
2019-09-10 10:29:54 +02:00
Emeric Brun
5762a0db0a BUG/MAJOR: ssl: ssl_sock was not fully initialized.
'ssl_sock' wasn't fully initialized so a new session can inherit some
flags from an old one.

This causes some fetches, related to client's certificate presence or
its verify status and errors, returning erroneous values.

This issue could generate other unexpected behaviors because a new
session could also inherit other flags such as SSL_SOCK_ST_FL_16K_WBFSIZE,
SSL_SOCK_SEND_UNLIMITED, or SSL_SOCK_RECV_HEARTBEAT from an old session.

This must be backported to 2.0 but it's useless for previous.
2019-09-06 17:33:33 +02:00
Willy Tarreau
9d00869323 CLEANUP: cli: replace all occurrences of manual handling of return messages
There were 221 places where a status message or an error message were built
to be returned on the CLI. All of them were replaced to use cli_err(),
cli_msg(), cli_dynerr() or cli_dynmsg() depending on what was expected.
This removed a lot of duplicated code because most of the times, 4 lines
are replaced by a single, safer one.
2019-08-09 11:26:10 +02:00
Emmanuel Hocdet
c9858010c2 MINOR: ssl: ssl_fc_has_early should work for BoringSSL
CO_FL_EARLY_SSL_HS/CO_FL_EARLY_DATA are removed for BoringSSL. Early
data can be checked via BoringSSL API and ssl_fc_has_early can used it.

This should be backported to all versions till 1.8.
2019-08-07 18:44:49 +02:00
Emmanuel Hocdet
f967c31e75 BUG/MINOR: ssl: fix 0-RTT for BoringSSL
Since BoringSSL commit 777a2391 "Hold off flushing NewSessionTicket until write.",
0-RTT doesn't work. It appears that half-RTT data (response from 0-RTT) never
worked before the BoringSSL fix. For HAProxy the regression come from 010941f8
"BUG/MEDIUM: ssl: Use the early_data API the right way.": the problem is link to
the logic of CO_FL_EARLY_SSL_HS used for OpenSSL. With BoringSSL, handshake is
done before reading early data, 0-RTT data and half-RTT data are processed as
normal data: CO_FL_EARLY_SSL_HS/CO_FL_EARLY_DATA is not needed, simply remove
it.

This should be backported to all versions till 1.8.
2019-08-07 18:44:48 +02:00
William Lallemand
6e5f2ceead BUG/MEDIUM: ssl: open the right path for multi-cert bundle
Multi-cert bundle was not working anymore because we tried to open the
wrong path.
2019-08-01 14:47:57 +02:00
Emmanuel Hocdet
1503e05362 BUG/MINOR: ssl: fix ressource leaks on error
Commit 36b84637 "MEDIUM: ssl: split the loading of the certificates"
introduce leaks on fd/memory in case of error.
2019-08-01 11:27:24 +02:00
William Lallemand
6dee29d63d BUG/MEDIUM: ssl: don't free the ckch in multi-cert bundle
When using a ckch we should never try to free its content, because it
won't be usable  after and can result in a NULL derefence during
parsing.

The content was previously freed because the ckch wasn't stored in a
tree to be used later, now that we use it multiple time, we need to keep
the data.
2019-08-01 11:27:24 +02:00
William Lallemand
a8c73748f8 BUG/MEDIUM: ssl: does not try to free a DH in a ckch
ssl_sock_load_dh_params() should not free the DH * of a ckch, or the
ckch won't be usable during the next call.
2019-07-31 19:35:31 +02:00
William Lallemand
c4ecddf418 BUG/BUILD: ssl: fix build with openssl < 1.0.2
Recent changes use struct cert_key_and_chain to load all certificates in
frontends, this structure was previously used only to load multi-cert
bundle, which is supported only on >= 1.0.2.
2019-07-31 17:05:09 +02:00
Emmanuel Hocdet
a7a0f991c9 MINOR: ssl: clean ret variable in ssl_sock_load_ckchn
In ssl_sock_load_ckchn, ret variable is now in a half dead usage.
Remove it to clean compilation warnings.
2019-07-30 17:54:35 +02:00
Emmanuel Hocdet
efa4b95b78 CLEANUP: ssl: ssl_sock_load_crt_file_into_ckch
Fix comments for this function and remove free before alloc call: ckch
call is correctly balanced  (alloc/free).
2019-07-30 17:54:34 +02:00
Emmanuel Hocdet
54227d8add MINOR: ssl: do not look at DHparam with OPENSSL_NO_DH
OPENSSL_NO_DH can be defined to avoid obsolete and heavy DH processing.
With OPENSSL_NO_DH, parse the entire PEM file to look at DHparam is wast
of time.
2019-07-30 17:54:34 +02:00
Emmanuel Hocdet
03e09f3818 MINOR: ssl: check private key consistency in loading
Load a PEM certificate and use it in CTX are now decorrelated.
Checking the certificate and private key consistency can be done
earlier: in loading phase instead CTX set phase.
2019-07-30 15:53:54 +02:00
Emmanuel Hocdet
1c65fdd50e MINOR: ssl: add extra chain compatibility
cert_key_and_chain handling is now outside openssl 1.0.2 #if: the
code must be libssl compatible. SSL_CTX_add1_chain_cert and
SSL_CTX_set1_chain requires openssl >= 1.0.2, replace it by legacy
SSL_CTX_add_extra_chain_cert when SSL_CTX_set1_chain is not provided.
2019-07-30 15:53:54 +02:00
Emmanuel Hocdet
9246f8bc83 MINOR: ssl: use STACK_OF for chain certs
Used native cert chain manipulation with STACK_OF from ssl lib.
2019-07-30 15:53:54 +02:00
William Lallemand
fa8922285d MEDIUM: ssl: load DH param in struct cert_key_and_chain
Load the DH param at the same time as the certificate, we don't need to
open the file once more and read it again. We store it in the ckch_node.

There is a minor change comparing to the previous way of loading the DH
param in a bundle. With a bundle, the DH param in a certificate file was
never loaded, it only used the global DH or the default DH, now it's
able to use the DH param from a certificate file.
2019-07-29 15:28:46 +02:00
William Lallemand
6af03991da MEDIUM: ssl: lookup and store in a ckch_node tree
Don't read a certificate file again if it was already stored in the
ckchn tree. It allows HAProxy to start more quickly if the same
certificate is used at different places in the configuration.

HAProxy lookup in the ssl_sock_load_cert() function, doing it at this
level allows to skip the reading of the certificate in the filesystem.

If the certificate is not found in the tree, we insert the ckch_node in
the tree once the certificate is read on the filesystem, the filename or
the bundle name is used as the key.
2019-07-29 15:28:46 +02:00
William Lallemand
36b8463777 MEDIUM: ssl: split the loading of the certificates
Split the functions which open the certificates.

Instead of opening directly the certificates and inserting them directly
into a SSL_CTX, we use a struct cert_key_and_chain to store them in
memory and then we associate a SSL_CTX to the certificate stored in that
structure.

Introduce the struct ckch_node for the multi-cert bundles so we can
store multiple cert_key_and_chain in the same structure.

The functions ssl_sock_load_multi_cert() and ssl_sock_load_cert_file()
were modified so they don't open the certicates anymore on the
filesystem. (they still open the sctl and ocsp though).  These functions
were renamed ssl_sock_load_ckchn() and ssl_sock_load_multi_ckchn().

The new function ckchn_load_cert_file() is in charge of loading the
files in the cert_key_and_chain. (TODO: load ocsp and sctl from there
too).

The ultimate goal is to be able to load a certificate from a certificate
tree without doing any filesystem access, so we don't try to open it
again if it was already loaded, and we share its configuration.
2019-07-29 15:28:46 +02:00
William Lallemand
a59191b894 MEDIUM: ssl: use cert_key_and_chain struct in ssl_sock_load_cert_file()
This structure was only used in the case of the multi-cert bundle.

Using these primitives everywhere when we load the file are a first step
in the deduplication of the code.
2019-07-29 15:28:46 +02:00
William Lallemand
c940207d39 MINOR: ssl: merge ssl_sock_load_cert_file() and ssl_sock_load_cert_chain_file()
This commit merges the function ssl_sock_load_cert_file() and
ssl_sock_load_cert_chain_file().

The goal is to refactor the SSL code and use the cert_key_and_chain
struct to load everything.
2019-07-29 15:28:46 +02:00
Willy Tarreau
085a1513ad MINOR: ssl-sock: use conn->dst instead of &conn->addr.to
This part can be definitive as the check was already in place.
2019-07-19 13:50:09 +02:00
Willy Tarreau
f5bdb64d35 MINOR: ssl: switch to conn_get_dst() to retrieve the destination address
This replaces conn_get_to_addr() and the subsequent check.
2019-07-19 13:50:09 +02:00
Christopher Faulet
fc9cfe4006 REORG: proto_htx: Move HTX analyzers & co to http_ana.{c,h} files
The old module proto_http does not exist anymore. All code dedicated to the HTTP
analysis is now grouped in the file proto_htx.c. So, to finish the polishing
after removing the legacy HTTP code, proto_htx.{c,h} files have been moved in
http_ana.{c,h} files.

In addition, all HTX analyzers and related functions prefixed with "htx_" have
been renamed to start with "http_" instead.
2019-07-19 09:24:12 +02:00
Lukas Tribus
4979916134 BUG/MINOR: ssl: revert empty handshake detection in OpenSSL <= 1.0.2
Commit 54832b97 ("BUILD: enable several LibreSSL hacks, including")
changed empty handshake detection in OpenSSL <= 1.0.2 and LibreSSL,
from accessing packet_length directly (not available in LibreSSL) to
calling SSL_state() instead.

However, SSL_state() appears to be fully broken in both OpenSSL and
LibreSSL.

Since there is no possibility in LibreSSL to detect an empty handshake,
let's not try (like BoringSSL) and restore this functionality for
OpenSSL 1.0.2 and older, by reverting to the previous behavior.

Should be backported to 2.0.
2019-07-09 04:47:18 +02:00
Olivier Houchard
e488ea865a BUG/MEDIUM: ssl: Don't attempt to set alpn if we're not using SSL.
Checks use ssl_sock_set_alpn() to set the ALPN if check-alpn is used, however
check-alpn failed to check if the connection was indeed using SSL, and thus,
would crash if check-alpn was used on a non-SSL connection. Fix this by
making sure the connection uses SSL before attempting to set the ALPN.

This should be backported to 2.0 and 1.9.
2019-06-28 14:12:28 +02:00
Olivier Houchard
0ff28651c1 BUG/MEDIUM: ssl: Don't do anything in ssl_subscribe if we have no ctx.
In ssl_subscribe(), make sure we have a ssl_sock_ctx before doing anything.
When ssl_sock_close() is called, it wakes any subscriber up, and that
subscriber may decide to subscribe again, for some reason. If we no longer
have a context, there's not much we can do.

This should be backported to 2.0.
2019-06-24 19:00:16 +02:00
Olivier Houchard
965e84e2df BUG/MEDIUM: ssl: Make sure we initiate the handshake after using early data.
When we're done sending/receiving early data, and we add the handshake
flags on the connection, make sure we wake the associated tasklet up, so that
the handshake will be initiated.
2019-06-15 21:00:39 +02:00