Commit Graph

820 Commits

Author SHA1 Message Date
Maxim Dounin
61cec6f01b SSL: disabled renegotiation checks with SSL_OP_NO_RENEGOTIATION.
Following 7319:dcab86115261, as long as SSL_OP_NO_RENEGOTIATION is
defined, it is OpenSSL library responsibility to prevent renegotiation,
so the checks are meaningless.

Additionally, with TLSv1.3 OpenSSL tends to report SSL_CB_HANDSHAKE_START
at various unexpected moments - notably, on KeyUpdate messages and
when sending tickets.  This change prevents unexpected connection
close on KeyUpdate messages and when finishing handshake with upcoming
early data changes.
2018-09-21 20:31:32 +03:00
Maxim Dounin
05029e775f SSL: restore handlers after blocking.
It is possible that after SSL_read() will return SSL_ERROR_WANT_WRITE,
further calls will return SSL_ERROR_WANT_READ without reading any
application data.  We have to call ngx_handle_write_event() and
switch back to normal write handling much like we do if there are some
application data, or the write there will be reported again and again.

Similarly, we have to switch back to normal read handling if there
is saved read handler and SSL_write() returns SSL_ERROR_WANT_WRITE.
2018-09-10 18:57:39 +03:00
Maxim Dounin
c2f90de0c5 SSL: corrected SSL_ERROR_WANT_WRITE / SSL_ERROR_WANT_READ logging.
While SSL_read() most likely to return SSL_ERROR_WANT_WRITE (and SSL_write()
accordingly SSL_ERROR_WANT_READ) during an SSL renegotiation, it is
not necessary mean that a renegotiation was started.  In particular,
it can never happen during a renegotiation or can happen multiple times
during a renegotiation.

Because of the above, misleading "peer started SSL renegotiation" info
messages were replaced with "SSL_read: want write" and "SSL_write: want read"
debug ones.

Additionally, "SSL write handler" and "SSL read handler" are now logged
by the SSL write and read handlers, to make it easier to understand that
temporary SSL handlers are called instead of normal handlers.
2018-09-10 18:57:19 +03:00
Maxim Dounin
1b1b632eed SSL: fixed build with LibreSSL 2.8.0 (ticket #1605).
LibreSSL 2.8.0 "added const annotations to many existing APIs from OpenSSL,
making interoperability easier for downstream applications".  This includes
the const change in the SSL_CTX_sess_set_get_cb() callback function (see
9dd43f4ef67e), which breaks compilation.

To fix this, added a condition on how we redefine OPENSSL_VERSION_NUMBER
when working with LibreSSL (see 382fc7069e3a).  With LibreSSL 2.8.0,
we now set OPENSSL_VERSION_NUMBER to 0x1010000fL (OpenSSL 1.1.0), so the
appropriate conditions in the code will use "const" as it happens with
OpenSSL 1.1.0 and later versions.
2018-08-10 20:49:06 +03:00
Maxim Dounin
3b1589173f SSL: support for TLSv1.3 early data with BoringSSL.
Early data AKA 0-RTT mode is enabled as long as "ssl_early_data on" is
specified in the configuration (default is off).

The $ssl_early_data variable evaluates to "1" if the SSL handshake
isn't yet completed, and can be used to set the Early-Data header as
per draft-ietf-httpbis-replay-04.
2018-08-07 02:16:07 +03:00
Maxim Dounin
9f30fda1c2 SSL: enabled TLSv1.3 with BoringSSL.
BoringSSL currently requires SSL_CTX_set_max_proto_version(TLS1_3_VERSION)
to be able to enable TLS 1.3.  This is because by default max protocol
version is set to TLS 1.2, and the SSL_OP_NO_* options are merely used
as a blacklist within the version range specified using the
SSL_CTX_set_min_proto_version() and SSL_CTX_set_max_proto_version()
functions.

With this change, we now call SSL_CTX_set_max_proto_version() with an
explicit maximum version set.  This enables TLS 1.3 with BoringSSL.
As a side effect, this change also limits maximum protocol version to
the newest protocol we know about, TLS 1.3.  This seems to be a good
change, as enabling unknown protocols might have unexpected results.

Additionally, we now explicitly call SSL_CTX_set_min_proto_version()
with 0.  This is expected to help with Debian system-wide default
of MinProtocol set to TLSv1.2, see
http://mailman.nginx.org/pipermail/nginx-ru/2017-October/060411.html.

Note that there is no SSL_CTX_set_min_proto_version macro in BoringSSL,
so we call SSL_CTX_set_min_proto_version() and SSL_CTX_set_max_proto_version()
as long as the TLS1_3_VERSION macro is defined.
2018-08-07 02:15:28 +03:00
Sergey Kandaurov
d5a27006e0 SSL: save sessions for upstream peers using a callback function.
In TLSv1.3, NewSessionTicket messages arrive after the handshake and
can come at any time.  Therefore we use a callback to save the session
when we know about it.  This approach works for < TLSv1.3 as well.
The callback function is set once per location on merge phase.

Since SSL_get_session() in BoringSSL returns an unresumable session for
TLSv1.3, peer save_session() methods have been updated as well to use a
session supplied within the callback.  To preserve API, the session is
cached in c->ssl->session.  It is preferably accessed in save_session()
methods by ngx_ssl_get_session() and ngx_ssl_get0_session() wrappers.
2018-07-17 12:53:23 +03:00
Maxim Dounin
e1bebd05cb SSL: use of the SSL_OP_NO_RENEGOTIATION option (ticket #1376).
The SSL_OP_NO_RENEGOTIATION option is available in OpenSSL 1.1.0h+ and can
save some CPU cycles on renegotiation attempts.
2018-07-16 17:47:48 +03:00
Maxim Dounin
1456129902 SSL: fixed SSL_clear_options() usage with OpenSSL 1.1.0+.
In OpenSSL 1.1.0 the SSL_CTRL_CLEAR_OPTIONS macro was removed, so
conditional compilation test on it results in SSL_clear_options()
and SSL_CTX_clear_options() not being used.  Notably, this caused
"ssl_prefer_server_ciphers off" to not work in SNI-based virtual
servers if server preference was switched on in the default server.

It looks like the only possible fix is to test OPENSSL_VERSION_NUMBER
explicitly.
2018-07-16 17:47:20 +03:00
Maxim Dounin
b1734fd800 SSL: logging levels of "unsupported protocol", "version too low".
Starting with OpenSSL 1.1.0, SSL_R_UNSUPPORTED_PROTOCOL instead of
SSL_R_UNKNOWN_PROTOCOL is reported when a protocol is disabled via
an SSL_OP_NO_* option.

Additionally, SSL_R_VERSION_TOO_LOW is reported when using MinProtocol
or when seclevel checks (as set by @SECLEVEL=n in the cipher string)
rejects a protocol, and this is what happens with SSLv3 and @SECLEVEL=1,
which is the default.

There is also the SSL_R_VERSION_TOO_HIGH error code, but it looks like
it is not possible to trigger it.
2018-07-16 17:47:18 +03:00
Maxim Dounin
85b44b46fb Events: added configuration check on the number of connections.
There should be at least one worker connection for each listening socket,
plus an additional connection for channel between worker and master,
or starting worker processes will fail.
2018-07-12 19:50:07 +03:00
Maxim Dounin
751bdd3bb2 Events: moved sockets cloning to ngx_event_init_conf().
Previously, listenings sockets were not cloned if the worker_processes
directive was specified after "listen ... reuseport".

This also simplifies upcoming configuration check on the number
of worker connections, as it needs to know the number of listening
sockets before cloning.
2018-07-12 19:50:02 +03:00
Maxim Dounin
f206a112c6 SSL: logging level of "https proxy request" errors.
The "http request" and "https proxy request" errors cannot happen
with HTTP due to pre-handshake checks in ngx_http_ssl_handshake(),
but can happen when SSL is used in stream and mail modules.
2018-07-05 20:45:29 +03:00
Sergey Kandaurov
1ef7b1ef61 SSL: removed extra prototype. 2018-06-06 13:31:05 +03:00
Maxim Dounin
8dc0f75d0b Added missing space after ngx_close_socket_n. 2018-06-05 17:41:34 +03:00
Roman Arutyunyan
96b6f215b8 Stream: udp streams.
Previously, only one client packet could be processed in a udp stream session
even though multiple response packets were supported.  Now multiple packets
coming from the same client address and port are delivered to the same stream
session.

If it's required to maintain a single stream of data, nginx should be
configured in a way that all packets from a client are delivered to the same
worker.  On Linux and DragonFly BSD the "reuseport" parameter should be
specified for this.  Other systems do not currently provide appropriate
mechanisms.  For these systems a single stream of udp packets is only
guaranteed in single-worker configurations.

The proxy_response directive now specifies how many packets are expected in
response to a single client packet.
2018-06-04 19:50:00 +03:00
Roman Arutyunyan
1028d71695 Events: moved ngx_recvmsg() to new file src/event/ngx_event_udp.c. 2018-06-01 16:55:49 +03:00
Roman Arutyunyan
20f8bfab34 Events: get remote addresses before creating udp connection.
Previously, ngx_event_recvmsg() got remote socket addresses after creating
the connection object.  In preparation to handling multiple UDP packets in a
single session, this code was moved up.
2018-06-01 13:12:57 +03:00
Roman Arutyunyan
26a57486f0 Events: fixed handling zero-length client address.
On Linux recvmsg() syscall may return a zero-length client address when
receiving a datagram from an unbound unix datagram socket.  It is usually
assumed that socket address has at least the sa_family member.  Zero-length
socket address caused buffer over-read in functions which receive socket
address, for example ngx_sock_ntop().  Typically the over-read resulted in
unexpected socket family followed by session close.  Now a fake socket address
is allocated instead of a zero-length client address.
2018-06-01 16:53:02 +03:00
Roman Arutyunyan
dd7dba520c Generate error for unsupported IPv6 transparent proxy.
On some platforms (for example, Linux with glibc 2.12-2.25) IPv4 transparent
proxying is available, but IPv6 transparent proxying is not.  The entire feature
is enabled in this case and NGX_HAVE_TRANSPARENT_PROXY macro is set to 1.
Previously, an attempt to enable transparency for an IPv6 socket was silently
ignored in this case and was usually followed by a bind(2) EADDRNOTAVAIL error
(ticket #1487).  Now the error is generated for unavailable IPv6 transparent
proxy.
2018-02-22 13:16:21 +03:00
Ruslan Ermilov
63a4dab7b0 Fixed --test-build-eventport on macOS 10.12 and later.
In macOS 10.12, CLOCK_REALTIME and clockid_t were added, but not timer_t.
2018-01-16 13:52:03 +03:00
Alessandro Ghedini
5fee8f76b5 SSL: include <openssl/hmac.h>.
This header carries the definition of HMAC_Init_ex(). In OpenSSL this
header is included by <openssl/ssl.h>, but it's not so in BoringSSL.

It's probably a good idea to explicitly include this header anyway,
regardless of whether it's included by other headers or not.
2017-10-11 15:43:50 -07:00
Maxim Dounin
2e1e65a5c0 Fixed buffer overread with unix sockets after accept().
Some OSes (notably macOS, NetBSD, and Solaris) allow unix socket addresses
larger than struct sockaddr_un.  Moreover, some of them (macOS, Solaris)
return socklen of the socket address before it was truncated to fit the
buffer provided.  As such, on these systems socklen must not be used without
additional check that it is within the buffer provided.

Appropriate checks added to ngx_event_accept() (after accept()),
ngx_event_recvmsg() (after recvmsg()), and ngx_set_inherited_sockets()
(after getsockname()).

We also obtain socket addresses via getsockname() in
ngx_connection_local_sockaddr(), but it does not need any checks as
it is only used for INET and INET6 sockets (as there can be no
wildcard unix sockets).
2017-10-04 21:19:33 +03:00
Maxim Dounin
ed0cc4d523 SSL: fixed possible use-after-free in $ssl_server_name.
The $ssl_server_name variable used SSL_get_servername() result directly,
but this is not safe: it references a memory allocation in an SSL
session, and this memory might be freed at any time due to renegotiation.
Instead, copy the name to memory allocated from the pool.
2017-08-22 17:36:12 +03:00
Maxim Dounin
50a0f25c60 SSL: the $ssl_client_escaped_cert variable (ticket #857).
This variable contains URL-encoded client SSL certificate.  In contrast
to $ssl_client_cert, it doesn't depend on deprecated header continuation.
The NGX_ESCAPE_URI_COMPONENT variant of encoding is used, so the resulting
variable can be safely used not only in headers, but also as a request
argument.

The $ssl_client_cert variable should be considered deprecated now.
The $ssl_client_raw_cert variable will be eventually renambed back
to $ssl_client_cert.
2017-08-22 15:18:10 +03:00
Maxim Dounin
dd5ab4a11f Restored ngx_event_aio_t layout for debug logging.
The "fd" field should be after 3 pointers for ngx_event_ident() to use it.
This was broken by ccad84a174e0.  While it does not seem to be currently used
for aio-related events, it should be a good idea to preserve the correct
layout nevertheless.
2017-08-10 22:21:22 +03:00
Sergey Kandaurov
b986b4314b Fixed calls to ngx_open_file() in certain places.
Pass NGX_FILE_OPEN to ngx_open_file() to fix "The parameter is incorrect"
error on win32 when using the ssl_session_ticket_key directive or loading
a binary geo base.  On UNIX, this change is a no-op.
2017-08-09 15:03:27 +03:00
Sergey Kandaurov
32c7bd5102 Style. 2017-08-09 14:59:46 +03:00
Sergey Kandaurov
9edd64fcd8 SSL: fixed typo in the error message. 2017-07-25 17:21:59 +03:00
Valentin Bartenev
9197a3c874 Parenthesized ASCII-related calculations.
This also fixes potential undefined behaviour in the range and slice filter
modules, caused by local overflows of signed integers in expressions.
2017-07-17 17:23:51 +03:00
Roman Arutyunyan
c83922b18d Fixed deferred accept with EPOLLRDHUP enabled (ticket #1278).
Previously, the read event of the accepted connection was marked ready, but not
available.  This made EPOLLRDHUP-related code (for example, in ngx_unix_recv())
expect more data from the socket, leading to unexpected behavior.

For example, if SSL, PROXY protocol and deferred accept were enabled on a listen
socket, the client connection was aborted due to unexpected return value of
c->recv().
2017-05-24 13:17:08 +03:00
Sergey Kandaurov
9961198879 SSL: allowed renegotiation in client mode with OpenSSL < 1.1.0.
In ac9b1df5b246 (1.13.0) we attempted to allow renegotiation in client mode,
but when using OpenSSL 1.0.2 or older versions it was additionally disabled
by SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS.
2017-05-03 15:15:56 +03:00
Sergey Kandaurov
e8c579a187 SSL: compatibility with OpenSSL master branch.
The SSL_CTRL_SET_CURVES_LIST macro is removed in the OpenSSL master branch.
SSL_CTX_set1_curves_list is preserved as compatibility with previous versions.
2017-04-18 16:08:46 +03:00
Sergey Kandaurov
36be79301e SSL: disabled renegotiation detection in client mode.
CVE-2009-3555 is no longer relevant and mitigated by the renegotiation
info extension (secure renegotiation).  On the other hand, unexpected
renegotiation still introduces potential security risks, and hence we do
not allow renegotiation on the server side, as we never request renegotiation.

On the client side the situation is different though.  There are backends
which explicitly request renegotiation, and disabled renegotiation
introduces interoperability problems.  This change allows renegotiation
on the client side, and fixes interoperability problems as observed with
such backends (ticket #872).

Additionally, with TLSv1.3 the SSL_CB_HANDSHAKE_START flag is currently set
by OpenSSL when receiving a NewSessionTicket message, and was detected by
nginx as a renegotiation attempt.  This looks like a bug in OpenSSL, though
this change also allows better interoperability till the problem is fixed.
2017-04-18 16:08:44 +03:00
Sergey Kandaurov
9a37eb3a62 SSL: added support for TLSv1.3 in ssl_protocols directive.
Support for the TLSv1.3 protocol will be introduced in OpenSSL 1.1.1.
2017-04-18 15:12:38 +03:00
Ruslan Ermilov
eb017e75cf Core: set nginx_shared_zone name via ngx_str_set(). 2017-03-28 11:28:51 +03:00
Ruslan Ermilov
05f5a7325d Fixed a comment. 2017-03-17 12:09:31 +03:00
Maxim Dounin
1a58418ae7 Cancelable timers are now preserved if there are other timers.
There is no need to cancel timers early if there are other timers blocking
shutdown anyway.  Preserving such timers allows nginx to continue some
periodic work till the shutdown is actually possible.

With the new approach, timers with ev->cancelable are simply ignored when
checking if there are any timers left during shutdown.
2017-03-07 18:51:15 +03:00
Ruslan Ermilov
0f89206a10 Added missing "static" specifiers found by gcc -Wtraditional. 2017-03-06 11:09:47 +03:00
Eran Kornblau
0759f088a5 Added missing static specifiers. 2017-03-02 08:46:00 -05:00
Sergey Kandaurov
9af7dc2b44 SSL: clear error queue after OPENSSL_init_ssl().
The function may leave error in the error queue while returning success,
e.g., when taking a DSO reference to itself as of OpenSSL 1.1.0d:
https://git.openssl.org/?p=openssl.git;a=commit;h=4af9f7f

Notably, this fixes alert seen with statically linked OpenSSL on some platforms.

While here, check OPENSSL_init_ssl() return value.
2017-02-06 18:38:06 +03:00
Maxim Dounin
e66073c4d3 Upstream: fixed cache corruption and socket leaks with aio_write.
The ngx_event_pipe() function wasn't called on write events with
wev->delayed set.  As a result, threaded writing results weren't
properly collected in ngx_event_pipe_write_to_downstream() when a
write event was triggered for a completed write.

Further, this wasn't detected, as p->aio was reset by a thread completion
handler, and results were later collected in ngx_event_pipe_read_upstream()
instead of scheduling a new write of additional data.  If this happened
on the last reading from an upstream, last part of the response was never
written to the cache file.

Similar problems might also happen in case of timeouts when writing to
client, as this also results in ngx_event_pipe() not being called on write
events.  In this scenario socket leaks were observed.

Fix is to check if p->writing is set in ngx_event_pipe_read_upstream(), and
therefore collect results of previous write operations in case of read events
as well, similar to how we do so in ngx_event_pipe_write_downstream().
This is enough to fix the wev->delayed case.  Additionally, we now call
ngx_event_pipe() from ngx_http_upstream_process_request() if there are
uncollected write operations (p->writing and !p->aio).  This also fixes
the wev->timedout case.
2017-01-20 21:14:19 +03:00
Maxim Dounin
c2d3d82ccb SSL: support AES256 encryption of tickets.
This implies ticket key size of 80 bytes instead of previously used 48,
as both HMAC and AES keys are 32 bytes now.  When an old 48-byte ticket key
is provided, we fall back to using backward-compatible AES128 encryption.

OpenSSL switched to using AES256 in 1.1.0, and we are providing equivalent
security.  While here, order of HMAC and AES keys was reverted to make
the implementation compatible with keys used by OpenSSL with
SSL_CTX_set_tlsext_ticket_keys().

Prodded by Christian Klinger.
2016-12-23 17:28:20 +03:00
Maxim Dounin
3294292b66 SSL: backed out changeset e7cb5deb951d, reimplemented properly.
Changeset e7cb5deb951d breaks build on CentOS 5 with "dereferencing
type-punned pointer will break strict-aliasing rules" warning.  It is
backed out.

Instead, to keep builds with BoringSSL happy, type of the "value"
variable changed to "char *", and an explicit cast added before calling
ngx_parse_http_time().
2016-12-15 19:00:23 +03:00
Piotr Sikora
592dbcc315 SSL: fix call to BIO_get_mem_data().
Fixes build with BoringSSL.

Signed-off-by: Piotr Sikora <piotrsikora@google.com>
2016-12-13 14:19:30 -08:00
Maxim Dounin
551091951a SSL: $ssl_curves (ticket #1088).
The variable contains a list of curves as supported by the client.
Known curves are listed by their names, unknown ones are shown
in hex, e.g., "0x001d:prime256v1:secp521r1:secp384r1".

Note that OpenSSL uses session data for SSL_get1_curves(), and
it doesn't store full list of curves supported by the client when
serializing a session.  As a result $ssl_curves is only available
for new sessions (and will be empty for reused ones).

The variable is only meaningful when using OpenSSL 1.0.2 and above.
With older versions the variable is empty.
2016-12-05 22:23:23 +03:00
Maxim Dounin
2daf78867b SSL: $ssl_ciphers (ticket #870).
The variable contains list of ciphers as supported by the client.
Known ciphers are listed by their names, unknown ones are shown
in hex, e.g., ""AES128-SHA:AES256-SHA:0x00ff".

The variable is fully supported only when using OpenSSL 1.0.2 and above.
With older version there is an attempt to provide some information
using SSL_get_shared_ciphers().  It only lists known ciphers though.
Moreover, as OpenSSL uses session data for SSL_get_shared_ciphers(),
and it doesn't store relevant data when serializing a session.  As
a result $ssl_ciphers is only available for new sessions (and not
available for reused ones) when using OpenSSL older than 1.0.2.
2016-12-05 22:23:23 +03:00
Maxim Dounin
53092ad782 SSL: $ssl_client_v_start, $ssl_client_v_end, $ssl_client_v_remain. 2016-12-05 22:23:23 +03:00
Maxim Dounin
919f536329 SSL: $ssl_client_verify extended with a failure reason.
Now in case of a verification failure $ssl_client_verify contains
"FAILED:<reason>", similar to Apache's SSL_CLIENT_VERIFY, e.g.,
"FAILED:certificate has expired".

Detailed description of possible errors can be found in the verify(1)
manual page as provided by OpenSSL.
2016-12-05 22:23:22 +03:00
Maxim Dounin
27bcceb24b OCSP stapling: improved error logging context.
It now logs the IP address of the responder used (if it's already known),
as well as the certificate name.
2016-12-05 22:23:22 +03:00