With TLS 1.3 enabled, gnutls_handshake() succeeds in client when client fails to send required certificate
Description of problem:
If TLS 1.2 is in use, and a server connection requires client authentication (GNUTLS_CERT_REQUIRE
passed to gnutls_certificate_server_set_request
), and the client connection fails to provide any authentication (by failing to fill in the pcert
, pcert_length
, and pkey
parameters of its gnutls_certificate_retrieve_function2
), then the call to gnutls_handshake
will fail with GNUTLS_E_NO_CERTIFICATE_FOUND
. This is the behavior glib-networking expects.
But if TLS 1.3 is in use, the call to gnutls_handshake
unexpectedly succeeds in the client. The client doesn't receive any error until it later attempts to read from the session. Then the client receives GNUTLS_E_INVALID_SESSION
and GNUTLS_E_PUSH_ERROR
. This results in the glib-networking testsuite failing.
Is the behavior change expected? Shouldn't the handshake fail, as with TLS 1.2? Or is this different by design?
Version of gnutls used:
gnutls-3.6.4.fc29
Also reproduced with 90708656 built from git
Distributor of gnutls (e.g., Ubuntu, Fedora, RHEL)
Fedora, also manual build from git
How reproducible:
Steps to Reproduce:
- Build glib-networking (instructions tested on Fedora 29):
$ sudo dnf builddep glib-networking
$ git clone https://gitlab.gnome.org/GNOME/glib-networking.git
$ mkdir -p glib-networking/build
$ cd glib-networking/build
$ meson ..
$ ninja
- Run the testsuite:
$ ninja test
Actual results:
5/6 connection-gnutls FAIL 1.02 s (killed by signal 6 SIGABRT)
--- command ---
G_TEST_SRCDIR='/home/mcatanzaro/glib-networking/tls/tests' GIO_MODULE_DIR='/home/mcatanzaro/glib-networking/build/tls/gnutls' G_TEST_BUILDDIR='/home/mcatanzaro/glib-networking/build/tls/tests' /home/mcatanzaro/glib-networking/build/tls/tests/connection-gnutls
--- stdout ---
/tls/connection/basic: OK
/tls/connection/verified: OK
/tls/connection/verified-chain: OK
/tls/connection/verified-chain-with-redundant-root-cert: OK
/tls/connection/verified-chain-with-duplicate-server-cert: OK
/tls/connection/verified-unordered-chain: OK
/tls/connection/verified-chain-with-alternative-ca-cert: OK
/tls/connection/invalid-chain-with-alternative-ca-cert: OK
/tls/connection/client-auth: OK
/tls/connection/client-auth-rehandshake: OK
/tls/connection/client-auth-failure:
--- stderr ---
**
GLib-Net:ERROR:../tls/tests/connection.c:437:on_client_connection_close_finish: assertion failed (error == NULL): Error sending data: Broken pipe (g-io-error-quark, 44)
-------
Full log written to /home/mcatanzaro/glib-networking/build/meson-logs/testlog.txt
FAILED: meson-test
/usr/bin/meson test --no-rebuild --print-errorlogs
ninja: build stopped: subcommand failed.
The test /tls/connection/client-auth-failure
fails inside on_client_connection_close_finish
, a function that is not expected to be reached during this test. The test expects the connection to fail earlier, during the handshake stage.
The test succeeds with TLS 1.3 disabled:
$ G_TLS_GNUTLS_PRIORITY="@SYSTEM:-VERS-TLS1.3" ninja test
Or:
$ G_TLS_GNUTLS_PRIORITY="NORMAL:-VERS-TLS1.3" ninja test
Expected results:
The call to gnutls_handshake
should fail with GNUTLS_E_NO_CERTIFICATE_FOUND
, allowing /tls/connection/client-auth-failure
to pass. (Right?)