Synss / python-mbedtls

Cryptographic library with an mbed TLS back end
MIT License
79 stars 28 forks source link

TLSWrappedSocket.shutdown(int) does not send DTLS Alert Close Notify message (mbedtls_ssl_close_notify) #87

Closed derhex3r closed 1 year ago

derhex3r commented 1 year ago

I am submitting a …

Description

After the call of TLSWrappedSocket.shutdown(int) with different integers I do not see DTLS Alert message in Wireshark. I suppose that this method should be used for that because it calls mbedtls_ssl_close_notify()

Current behavior

With the use of TLSWrappedSocket.shutdown(0) we can see write a close notify message in mbedtls debug log, but wireshark does not show a Close Notify alert message (as it in the case with OpenSSL s_client).

Expected behavior

Call TLSWrappedSocket.shutdown(int) should send a Close Notify alert message.

Steps to reproduce

With use of programs/server.py --dtls --debug 2 --psk-store CLI=SECRET and programs/client.py --dtls --debug 2 --psk CLI=SECRET test we can observe DTLS handshake and no DTLS Alert close notify message after an application-level data transfer. But even if we will add a call of .shutdown() method to the client which calls mbedtls_ssl_close_notify() we can not see it.

Minimal demo of the problem

To test you can add cli._sock.shutdown(0) string into the programs/client.py --dtls --debug 2 --psk CLI=SECRET test

    with Client(
        conf, args.proto, (args.address, args.port), args.server_name
    ) as cli:
        if args.debug is not None:
            _enable_debug_output(cli.context)
            _set_debug_level(args.debug)

        cli.do_handshake()
        received = cli.echo(args.message.encode("utf-8"), 1024)
        cli._sock.shutdown(0)

To see in Wireshark how encrypted alert after application-layer data should look like possible to use:

ssl_server2 dtls=1 server_addr=0.0.0.0 server_port=9000 debug_level=5
ssl_client2 dtls=1 server_addr=0.0.0.0 server_port=9000 debug_level=5 
Synss commented 1 year ago

Thank you for your very clear and detailed report.

The C function is actually called here before resetting the connection. Most likely, the I/O is missing. The C call buffers the notification but it isn't passed to the socket before the connection is reset.

If I'm right, then it shouldn't be very hard to fix. Let's see!

derhex3r commented 1 year ago

Thanks. When a new version with this fix will be available?

Synss commented 1 year ago

The next one. 😊 Most likely during the week.

Synss commented 1 year ago

Hi! I just released 2.7.1 with the fix.