The negotiated MFL is always the one suggested by the client, even
if the server has a smaller MFL configured locally. Hence, in the test
where the client asks for an MFL of 4096 bytes while the server locally
has an MFL of 512 bytes configured, the client will still send datagrams
of up to ~4K size.
By the standard (RFC 6066, Sect. 4), the Maximum Fragment Length (MFL)
extension limits the maximum record payload size, but not the maximum
datagram size. However, not inferring any limitations on the MTU when
setting the MFL means that a party has no means to dynamically inform
the peer about MTU limitations.
This commit changes the function ssl_get_remaining_payload_in_datagram()
to never return more than
MFL - { Total size of all records within the current datagram }
thereby limiting the MTU to MFL + { Maximum Record Expansion }.
The previous code appended messages to flights only if their handshake type,
as derived from the first byte in the message, was different from
MBEDTLS_SSL_HS_HELLO_REQUEST. This check should only be performed
for handshake records, while CCS records should immediately be appended.
In SSLv3, the client sends a NoCertificate alert in response to
a CertificateRequest if it doesn't have a CRT. This previously
lead to failure in ssl_write_handshake_msg() which only accepted
handshake or CCS records.
Depending on the settings of the local machine, gnutls-cli will either try
IPv4 or IPv6 when trying to connect to localhost. With TLS, whatever it tries
first, it will notice if any failure happens and try the other protocol if
necessary. With DTLS it can't do that. Unfortunately for now there isn't
really any good way to specify an address and hostname independently, though
that might come soon: https://gitlab.com/gnutls/gnutls/issues/344
A work around is to specify an address directly and then use --insecure to
ignore certificate hostname mismatch; that is OK for tests that are completely
unrelated to certificate verification (such as the recent fragmenting tests)
but unacceptable for others.
For that reason, don't specify a default hostname for gnutls-cli, but instead
let each test choose between `--insecure 127.0.0.1` and `localhost` (or
`--insecure '::1'` if desired).
Alternatives include:
- having test certificates with 127.0.0.1 as the hostname, but having an IP as
the CN is unusual, and we would need to change our test certs;
- have our server open two sockets under the hood and listen on both IPv4 and
IPv6 (that's what gnutls-serv does, and IMO it's a good thing) but that
obviously requires development and testing (esp. for windows compatibility)
- wait for a newer version of GnuTLS to be released, install it on the CI and
developer machines, and use that in all tests - quite satisfying but can't
be done now (and puts stronger requirements on test environment).
The previous code appended messages to flights only if their handshake type,
as derived from the first byte in the message, was different from
MBEDTLS_SSL_HS_HELLO_REQUEST. This check should only be performed
for handshake records, while CCS records should immediately be appended.
In SSLv3, the client sends a NoCertificate alert in response to
a CertificateRequest if it doesn't have a CRT. This previously
lead to failure in ssl_write_handshake_msg() which only accepted
handshake or CCS records.
From Hanno:
When a server replies to a cookieless ClientHello with a HelloVerifyRequest,
it is supposed to reset the connection and wait for a subsequent ClientHello
which includes the cookie from the HelloVerifyRequest.
In testing environments, it might happen that the reset of the server
takes longer than for the client to replying to the HelloVerifyRequest
with the ClientHello+Cookie. In this case, the ClientHello gets lost
and the client will need retransmit. This may happen even if the underlying
datagram transport is reliable.
This commit continues commit 47db877 by removing resend guards in the
ssl-opt.sh tests 'DTLS fragmenting: proxy MTU, XXX' which sometimes made
the tests fail in case the log showed a resend from the client.
See 47db877 for more information.
When a server replies to a cookieless ClientHello with a HelloVerifyRequest,
it is supposed to reset the connection and wait for a subsequent ClientHello
which includes the cookie from the HelloVerifyRequest.
In testing environments, it might happen that the reset of the server
takes longer than for the client to replying to the HelloVerifyRequest
with the ClientHello+Cookie. In this case, the ClientHello gets lost
and the client will need retransmit. This may happen even if the underlying
datagram transport is reliable.
This commit removes a guard in the ssl-opt.sh test
'DTLS fragmenting: proxy MTU, resumed handshake' which made
the test fail in case the log showed a resend from the client.
Resolve conflicts in programs/ssl/ssl_mail_client.c. PR #930 already had
the fix, but not the comment. PR #1932 then just adds a comment about the
fix.
We previously observed random-looking failures from this test. I think they
were caused by a race condition where the client tries to reconnect while the
server is still closing the connection and has not yet returned to an
accepting state. In that case, the server would fail to see and reply to the
ClientHello, and the client would have to resend it.
I believe logs of failing runs are compatible with this interpretation:
- the proxy logs show the new ClientHello and the server's closing Alert are
sent the same millisecond.
- the client logs show the server's closing Alert is received after the new
handshake has been started (discarding message from wrong epoch).
The attempted fix is for the client to wait a bit before reconnecting, which
should vastly enhance the probability of the server reaching its accepting
state before the client tries to reconnect. The value of 1 second is arbitrary
but should be more than enough even on loaded machines.
The test was run locally 100 times in a row on a slightly loaded machine (an
instance of all.sh running in parallel) without any failure after this fix.