Commit Graph

220 Commits

Author SHA1 Message Date
Maxim Dounin c4f8e285b7 SSL: enabled TLSv1.3 by default. 2023-03-24 02:57:43 +03:00
Maxim Dounin 23958e4a5c Mail: fixed handling of blocked client read events in proxy.
When establishing a connection to the backend, nginx blocks reading
from the client with ngx_mail_proxy_block_read().  Previously, such
events were lost, and in some cases this resulted in connection hangs.

Notably, this affected mail_imap_ssl.t on Windows, since the test
closes connections after requesting authentication, but without
waiting for any responses (so the connection close events might be
lost).

Fix is to post an event to read from the client after connecting to
the backend if there were blocked events.
2023-03-24 02:53:21 +03:00
Valentin Bartenev 3f617b7149 Fixed port ranges support in the listen directive.
Ports difference must be respected when checking addresses for duplicates,
otherwise configurations like this are broken:

  listen 127.0.0.1:6000-6005

It was broken by 4cc2bfeff46c (nginx 1.23.3).
2022-12-18 21:29:02 +03:00
Maxim Dounin 6fb2777ad2 Filtering duplicate addresses in listen (ticket #2400).
Due to the glibc bug[1], getaddrinfo("localhost") with AI_ADDRCONFIG
on a typical host with glibc and without IPv6 returns two 127.0.0.1
addresses, and therefore "listen localhost:80;" used to result in
"duplicate ... address and port pair" after 4f9b72a229c1.

Fix is to explicitly filter out duplicate addresses returned during
resolution of a name.

[1] https://sourceware.org/bugzilla/show_bug.cgi?id=14969
2022-11-23 17:30:08 +03:00
Roman Arutyunyan 1d87a364e9 Increased maximum read PROXY protocol header size.
Maximum size for reading the PROXY protocol header is increased to 4096 to
accommodate a bigger number of TLVs, which are supported since cca4c8a715de.

Maximum size for writing the PROXY protocol header is not changed since only
version 1 is currently supported.
2022-11-02 13:46:16 +04:00
Sergey Kandaurov a86de64900 SSL: improved validation of ssl_session_cache and ssl_ocsp_cache.
Now it properly detects invalid shared zone configuration with omitted size.
Previously it used to read outside of the buffer boundary.

Found with AddressSanitizer.
2022-10-17 16:24:53 +04:00
Vladimir Homutov 3235758443 Mail: connections with wrong ALPN protocols are now rejected.
This is a recommended behavior by RFC 7301 and is useful
for mitigation of protocol confusion attacks [1].

For POP3 and IMAP protocols IANA-assigned ALPN IDs are used [2].
For the SMTP protocol "smtp" is used.

[1] https://alpaca-attack.com/
[2] https://www.iana.org/assignments/tls-extensiontype-values/
2021-10-20 09:45:34 +03:00
Rob Mueller 94deaa03f7 Mail: Auth-SSL-Protocol and Auth-SSL-Cipher headers (ticket #2134).
This adds new Auth-SSL-Protocol and Auth-SSL-Cipher headers to
the mail proxy auth protocol when SSL is enabled.

This can be useful for detecting users using older clients that
negotiate old ciphers when you want to upgrade to newer
TLS versions of remove suppport for old and insecure ciphers.
You can use your auth backend to notify these users before the
upgrade that they either need to upgrade their client software
or contact your support team to work out an upgrade path.
2021-08-13 03:57:47 -04:00
Maxim Dounin 9129c52b05 SSL: ciphers now set before loading certificates (ticket #2035).
To load old/weak server or client certificates it might be needed to adjust
the security level, as introduced in OpenSSL 1.1.0.  This change ensures that
ciphers are set before loading the certificates, so security level changes
via the cipher string apply to certificate loading.
2021-08-16 22:40:31 +03:00
Maxim Dounin d326c76aae Mail: max_errors directive.
Similarly to smtpd_hard_error_limit in Postfix and smtp_max_unknown_commands
in Exim, specifies the number of errors after which the connection is closed.
2021-05-19 03:13:31 +03:00
Maxim Dounin ac3cf225a5 Mail: IMAP pipelining support.
The change is mostly the same as the SMTP one (04e43d03e153 and 3f5d0af4e40a),
and ensures that nginx is able to properly handle or reject multiple IMAP
commands.  The s->cmd field is not really used and set for consistency.

Non-synchronizing literals handling in invalid/unknown commands is limited,
so when a non-synchronizing literal is detected at the end of a discarded
line, the connection is closed.
2021-05-19 03:13:28 +03:00
Maxim Dounin 0021187890 Mail: stricter checking of IMAP tags.
Only "A-Za-z0-9-._" characters now allowed (which is stricter than what
RFC 3501 requires, but expected to be enough for all known clients),
and tags shouldn't be longer than 32 characters.
2021-05-19 03:13:26 +03:00
Maxim Dounin 92253f5878 Mail: fixed backslash handling in IMAP literals.
Previously, s->backslash was set if any of the arguments was a quoted
string with a backslash character.  After successful command parsing
this resulted in all arguments being filtered to remove backslashes.
This is, however, incorrect, as backslashes should not be removed from
IMAP literals.  For example:

   S: * OK IMAP4 ready
   C: a01 login {9}
   S: + OK
   C: user\name "pass\"word"
   S: * BAD internal server error

resulted in "Auth-User: username" instead of "Auth-User: user\name"
as it should.

Fix is to apply backslash filtering on per-argument basis during parsing.
2021-05-19 03:13:23 +03:00
Maxim Dounin 8130c4e2ca Mail: removed dead s->arg_start handling.
As discussed in the previous change, s->arg_start handling in the "done"
labels of ngx_mail_pop3_parse_command(), ngx_mail_imap_parse_command(),
and ngx_mail_smtp_parse_command() is wrong: s->arg_start cannot be
set there, as it is handled and cleared on all code paths where the
"done" labels are reached.  The relevant code is dead and now removed.
2021-05-19 03:13:22 +03:00
Maxim Dounin b0b3391617 Mail: fixed s->arg_start clearing on invalid IMAP commands.
Previously, s->arg_start was left intact after invalid IMAP commands,
and this might result in an argument incorrectly added to the following
command.  Similarly, s->backslash was left intact as well, leading
to unneeded backslash removal.

For example (LFs from the client are explicitly shown as "<LF>"):

  S: * OK IMAP4 ready
  C: a01 login "\<LF>
  S: a01 BAD invalid command
  C: a0000000000\2 authenticate <LF>
  S: a00000000002 aBAD invalid command

The backslash followed by LF generates invalid command with s->arg_start
and s->backslash set, the following command incorrectly treats anything
from the old s->arg_start to the space after the command as an argument,
and removes the backslash from the tag.  If there is no space, s->arg_end
will be NULL.

Both things seem to be harmless though.  In particular:

- This can be used to provide an incorrect argument to a command without
  arguments.  The only command which seems to look at the single argument
  is AUTHENTICATE, and it checks the argument length before trying to
  access it.

- Backslash removal uses the "end" pointer, and stops due to "src < end"
  condition instead of scanning all the process memory if s->arg_end is
  NULL (and arg[0].len is huge).

- There should be no backslashes in unquoted strings.

An obvious fix is to clear s->arg_start and s->backslash on invalid commands,
similarly to how it is done in POP3 parsing (added in 810:e3aa8f305d21) and
SMTP parsing.

This, however, makes it clear that s->arg_start handling in the "done"
label is wrong: s->arg_start cannot be legitimately set there, as it
is expected to be cleared in all possible cases when the "done" label is
reached.  The relevant code is dead and will be removed by the following
change.
2021-05-19 03:13:20 +03:00
Maxim Dounin 65d69a19a7 Mail: POP3 pipelining support.
The change is mostly the same as the SMTP one (04e43d03e153 and 3f5d0af4e40a),
and ensures that nginx is able to properly handle or reject multiple POP3
commands, as required by the PIPELINING capability (RFC 2449).  The s->cmd
field is not really used and set for consistency.
2021-05-19 03:13:18 +03:00
Maxim Dounin 2de54c2867 Mail: optimized discarding invalid SMTP commands.
There is no need to scan buffer from s->buffer->pos, as we already scanned
the buffer till "p" and wasn't able to find an LF.

There is no real need for this change in SMTP, since it is at most a
microoptimization of a non-common code path.  Similar code in IMAP, however,
will have to start scanning from "p" to be correct, since there can be
newlines in IMAP literals.
2021-05-19 03:13:17 +03:00
Maxim Dounin 29532d2781 Mail: fixed handling of invalid SMTP commands split between reads.
Previously, if an invalid SMTP command was split between reads, nginx failed
to wait for LF before returning an error, and interpreted the rest of the
command received later as a separate command.

The sw_invalid state in ngx_mail_smtp_parse_command(), introduced in
04e43d03e153, did not work, since ngx_mail_smtp_auth_state() clears
s->state when returning an error due to NGX_MAIL_PARSE_INVALID_COMMAND.
And not clearing s->state will introduce another problem: the rest
of the command would trigger duplicate error when rest of the command is
received.

Fix is to return NGX_AGAIN from ngx_mail_smtp_parse_command() until full
command is received.
2021-05-19 03:13:15 +03:00
Maxim Dounin c511a147a1 Mail: fixed SMTP pipelining to send the response immediately.
Previously, if there were some pipelined SMTP data in the buffer when
a proxied connection with the backend was established, nginx called
ngx_mail_proxy_handler() to send these data, and not tried to send the
response to the last command.  In most cases, this response was later sent
along with the response to the pipelined command, but if for some reason
client decides to wait for the response before finishing the next command
this might result in a connection hang.

Fix is to always call ngx_mail_proxy_handler() to send the response, and
additionally post an event to send the pipelined data if needed.
2021-05-19 03:13:12 +03:00
Maxim Dounin 70bd2beda2 Mail: fixed reading with fully filled buffer (ticket #2159).
With SMTP pipelining, ngx_mail_read_command() can be called with s->buffer
without any space available, to parse additional commands received to the
buffer on previous calls.  Previously, this resulted in recv() being called
with zero length, resulting in zero being returned, which was interpreted
as a connection close by the client, so nginx silently closed connection.

Fix is to avoid calling c->recv() if there is no free space in the buffer,
but continue parsing of the already received commands.
2021-04-21 23:24:59 +03:00
Maxim Dounin a86eac0ec0 Mail: fixed build without SSL.
Broken by d84f13618277 and 12ea1de7d87c (1.19.8).

Reported by Sergey Osokin.
2021-03-11 04:46:26 +03:00
Maxim Dounin 00ef7bd79a Mail: sending of the PROXY protocol to backends.
Activated with the "proxy_protocol" directive.  Can be combined with
"listen ... proxy_protocol;" and "set_real_ip_from ...;" to pass
client address provided to nginx in the PROXY protocol header.
2021-03-05 17:16:32 +03:00
Maxim Dounin 4b2da5d364 Mail: realip module.
When configured with the "set_real_ip_from", it can set client's IP
address as visible in logs to the one obtained via the PROXY protocol.
2021-03-05 17:16:29 +03:00
Maxim Dounin aa60a47253 Mail: parsing of the PROXY protocol from clients.
Activated with the "proxy_protocol" parameter of the "listen" directive.
Obtained information is passed to the auth_http script in Proxy-Protocol-Addr,
Proxy-Protocol-Port, Proxy-Protocol-Server-Addr, and Proxy-Protocol-Server-Port
headers.
2021-03-05 17:16:24 +03:00
Maxim Dounin 05d4191476 Mail: made auth http creating request easier to extend. 2021-03-05 17:16:23 +03:00
Maxim Dounin 79523aa96d Mail: fixed log action after SSL handshake. 2021-03-05 17:16:20 +03:00
Maxim Dounin 189fcceb07 Mail: postponed session initialization under accept mutex.
Similarly to 40e8ce405859 in the stream module, this reduces the time
accept mutex is held.  This also simplifies following changes to
introduce PROXY protocol support.
2021-03-05 17:16:19 +03:00
Maxim Dounin 41c0e54f68 Mail: added missing event handling after reading data.
If we need to be notified about further events, ngx_handle_read_event()
needs to be called after a read event is processed.  Without this,
an event can be removed from the kernel and won't be reported again,
notably when using oneshot event methods, such as eventport on Solaris.

For consistency, existing ngx_handle_read_event() call removed from
ngx_mail_read_command(), as this call only covers one of the code paths
where ngx_mail_read_command() returns NGX_AGAIN.  Instead, appropriate
processing added to the callers, covering all code paths where NGX_AGAIN
is returned.
2021-03-05 17:16:17 +03:00
Maxim Dounin 7a6f694d81 Mail: added missing event handling after blocking events.
As long as a read event is blocked (ignored), ngx_handle_read_event()
needs to be called to make sure no further notifications will be
triggered when using level-triggered event methods, such as select() or
poll().
2021-03-05 17:16:16 +03:00
Maxim Dounin a079c32706 SSL: fixed build by Sun C with old OpenSSL versions.
Sun C complains about "statement not reached" if a "return" is followed
by additional statements.
2021-03-05 17:16:13 +03:00
Maxim Dounin 4caf623ede SSL: ssl_conf_command directive.
With the ssl_conf_command directive it is now possible to set
arbitrary OpenSSL configuration parameters as long as nginx is compiled
with OpenSSL 1.0.2 or later.  Full list of available configuration
commands can be found in the SSL_CONF_cmd manual page
(https://www.openssl.org/docs/man1.1.1/man3/SSL_CONF_cmd.html).

In particular, this allows configuring PrioritizeChaCha option
(ticket #1445):

    ssl_conf_command Options PrioritizeChaCha;

It can be also used to configure TLSv1.3 ciphers in OpenSSL,
which fails to configure them via the SSL_CTX_set_cipher_list()
interface (ticket #1529):

    ssl_conf_command Ciphersuites TLS_CHACHA20_POLY1305_SHA256;

Configuration commands are applied after nginx own configuration
for SSL, so they can be used to override anything set by nginx.
Note though that configuring OpenSSL directly with ssl_conf_command
might result in a behaviour nginx does not expect, and should be
done with care.
2020-10-22 18:00:22 +03:00
Maxim Dounin 5addcc5141 Mail: proxy_smtp_auth directive.
The proxy_smtp_auth directive instructs nginx to authenticate users
on backend via the AUTH command (using the PLAIN SASL mechanism),
similar to what is normally done for IMAP and POP3.

If xclient is enabled along with proxy_smtp_auth, the XCLIENT command
won't try to send the LOGIN parameter.
2020-10-03 21:04:57 +03:00
Sergey Kandaurov f406afdae4 SSL: fixed ssl_verify_client error message. 2019-09-16 19:26:42 +03:00
Maxim Dounin 8c636fc214 Mail: fixed duplicate resolving.
When using SMTP with SSL and resolver, read events might be enabled
during address resolving, leading to duplicate ngx_mail_ssl_handshake_handler()
calls if something arrives from the client, and duplicate session
initialization - including starting another resolving.  This can lead
to a segmentation fault if the session is closed after first resolving
finished.  Fix is to block read events while resolving.

Reported by Robert Norris,
http://mailman.nginx.org/pipermail/nginx/2019-July/058204.html.
2019-08-01 13:50:07 +03:00
Roman Arutyunyan 35d3e3f15e Multiple addresses in "listen".
Previously only one address was used by the listen directive handler even if
host name resolved to multiple addresses.  Now a separate listening socket is
created for each address.
2019-03-15 15:45:56 +03:00
Maxim Dounin b7553b6b05 SSL: fixed potential leak on memory allocation errors.
If ngx_pool_cleanup_add() fails, we have to clean just created SSL context
manually, thus appropriate call added.

Additionally, ngx_pool_cleanup_add() moved closer to ngx_ssl_create() in
the ngx_http_ssl_module, to make sure there are no leaks due to intermediate
code.
2019-03-03 16:48:39 +03:00
Maxim Dounin 974fc671fc SSL: adjusted session id context with dynamic certificates.
Dynamic certificates re-introduce problem with incorrect session
reuse (AKA "virtual host confusion", CVE-2014-3616), since there are
no server certificates to generate session id context from.

To prevent this, session id context is now generated from ssl_certificate
directives as specified in the configuration.  This approach prevents
incorrect session reuse in most cases, while still allowing sharing
sessions across multiple machines with ssl_session_ticket_key set as
long as configurations are identical.
2019-02-25 16:42:54 +03:00
Ruslan Ermilov 2282376037 SSL: deprecated the "ssl" directive. 2018-04-25 14:57:24 +03:00
Maxim Dounin 294e16c34a SSL: detect "listen ... ssl" without certificates (ticket #178).
In mail and stream modules, no certificate provided is a fatal condition,
much like with the "ssl" and "starttls" directives.

In http, "listen ... ssl" can be used in a non-default server without
certificates as long as there is a certificate in the default one, so
missing certificate is only fatal for default servers.
2018-04-24 15:29:01 +03:00
Maxim Dounin 7b197ba357 Mail: fixed error message about missing ssl_certificate_key.
In 51e1f047d15d, the "ssl" directive name was incorrectly hardcoded
in the error message shown when there are some SSL keys defined, but
not for all certificates.  Right approach is to use the "mode" variable,
which can be either "ssl" or "starttls".
2018-04-24 15:28:58 +03:00
Sergey Kandaurov 4cc53b092e SSL: using default server context in session remove (closes #1464).
This fixes segfault in configurations with multiple virtual servers sharing
the same port, where a non-default virtual server block misses certificate.
2018-01-30 17:46:31 +03:00
Maxim Dounin edc9f594a8 Fixed worker_shutdown_timeout in various cases.
The ngx_http_upstream_process_upgraded() did not handle c->close request,
and upgraded connections do not use the write filter.  As a result,
worker_shutdown_timeout did not affect upgraded connections (ticket #1419).
Fix is to handle c->close in the ngx_http_request_handler() function, thus
covering most of the possible cases in http handling.

Additionally, mail proxying did not handle neither c->close nor c->error,
and thus worker_shutdown_timeout did not work for mail connections.  Fix is
to add c->close handling to ngx_mail_proxy_handler().

Also, added explicit handling of c->close to stream proxy,
ngx_stream_proxy_process_connection().  This improves worker_shutdown_timeout
handling in stream, it will no longer wait for some data being transferred
in a connection before closing it, and will also provide appropriate
logging at the "info" level.
2017-11-20 16:31:07 +03:00
Maxim Dounin 2a256d6081 Style: changed checks of ngx_ssl_create_connection() to != NGX_OK.
In http these checks were changed in a6d6d762c554, though mail module
was missed at that time.  Since then, the stream module was introduced
based on mail, using "== NGX_ERROR" check.
2017-05-29 16:34:35 +03:00
Sergey Kandaurov 13cc565639 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
Vladimir Homutov 939e9f2c7c Mail: configurable socket buffer sizes.
The "rcvbuf" and "sndbuf" parameters are now supported by
the "listen" directive.
2017-04-03 17:30:34 +03:00
Sergey Kandaurov de13f11b01 Mail: don't emit separator in capability lists for APOP.
Notably, this fixes CAPA and AUTH output.

The bug had appeared in nginx 1.11.6 (73b451d304c0).
2017-03-06 17:56:23 +03:00
Sergey Kandaurov 1ec676905e Mail: make it possible to disable SASL EXTERNAL. 2017-01-12 19:22:03 +03:00
Maxim Dounin 740895228e Win32: fixed some warnings reported by Borland C.
Most notably, warning W8012 (comparing signed and unsigned values) reported
in multiple places where an unsigned value of small type (e.g., u_short) is
promoted to an int and compared to an unsigned value.

Warning W8072 (suspicious pointer arithmetic) disabled, it is reported
when we increment base pointer in ngx_shm_alloc().
2016-12-24 18:01:14 +03:00
Rob N ★ 42dca0fee6 Mail: support SASL EXTERNAL (RFC 4422).
This is needed to allow TLS client certificate auth to work. With
ssl_verify_client configured, the auth daemon can choose to allow the
connection to proceed based on the certificate data.

This has been tested with Thunderbird for IMAP only. I've not yet found a
client that will do client certificate auth for POP3 or SMTP, and the method is
not really documented anywhere that I can find. That said, its simple enough
that the way I've done is probably right.
2016-10-08 18:05:00 +11:00
Maxim Dounin f34e5a0217 Mail: extensible auth methods in pop3 module. 2016-10-18 19:38:46 +03:00