openssl / openssl

TLS/SSL and crypto library
https://www.openssl.org
Apache License 2.0
25.45k stars 10.06k forks source link

s_client -reconnect option is broken with TLSv1.3 #10714

Open mattcaswell opened 4 years ago

mattcaswell commented 4 years ago

The "-reconnect" option to s_client is supposed to do this:

-reconnect Reconnects to the same server 5 times using the same session ID, this can be used as a test that session caching is working.

However this is not working when TLSv1.3 is in use. Each reconnection attempt uses a new session, instead of resuming the first one.

kaduk commented 4 years ago

"Uses a new session" in the sense of chaining session tickets from successive 1-RTT resumptions, or does it fall back to a full handshake? I expect that we got to this state via our initial overzealous interpretation of "single-use tickets" with a side order of our initial state where TLS 1.3 sessions were always unique per-connection. (I'm still not convinced that the change to the current state where we can attach multiple TLS 1.3 connections to a single SSL_SESSION object is the right long-term choice, though that's not really a discussion to have on this issue.)

mattcaswell commented 4 years ago

Full handshake every time.

raycoll commented 2 years ago

I was looking into this because I think the -reconnect option is useful in a pinch to inspect the resumption behavior of a server.

I think one challenge here is the timing of the new session ticket message. It may arrive after this block is hit:

https://github.com/openssl/openssl/blob/8547cd6790881cbba0f20aa4ce048243065a24bf/apps/s_client.c#L2799-L2807

One workaround I've thought of for this is to support a new command character to allow a user to interactively trigger a "reuse attempt". This allows us to workaround servers with varying new session ticket timing behaviors(some may delay sending of a ticket until after application data record(s)). Interactive command will help for use cases where a user wants to probe and endpoint for resumption behavior. It's not a like-for-like replacement for the -reconnect option, but this alternative satisfies most of the ways I've used it.

Here's a tiny diff(likely with a few errors) to support such a thing. Let me know if it's something the project would be interested in.

https://github.com/raycoll/openssl/commit/dde5a95ed3e49a1651da1ef358461d1094370731#

example usage:

> openssl s_client -connect 127.0.0.1:443
Connecting to 127.0.0.1
....
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: RSA-PSS
Server Temp Key: ECDH, prime256v1, 256 bits
---
SSL handshake has read 3834 bytes and written 751 bytes
Verification error: self-signed certificate in certificate chain
---
New, TLSv1.3, Cipher is TLS_AES_128_GCM_SHA256
Server public key is 2048 bit
This TLS version forbids renegotiation.
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 19 (self-signed certificate in certificate chain)
---
---
Post-Handshake New Session Ticket arrived:
SSL-Session:
    Protocol  : TLSv1.3
    Cipher    : TLS_AES_128_GCM_SHA256
    Session-ID: A80BE30C602BE9E3925D9831EFDE71D2BAC69B8044EBF342E1809EF78B56D2D9
    Session-ID-ctx:
    Resumption PSK: 81906C267B96D3E34B8C20989272E34810E351733E3D84735D130E39A8FDC492
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 172800 (seconds)
    TLS session ticket:
    0000 - 53 53 4b 2d 45 30 30 34-35 39 38 36 36 00 00 00   SSK-E00459866...
    0010 - 36 01 d1 d4 5d e1 67 c9-05 43 5f 16 ec a5 13 55   6...].g..C_....U
    0020 - 0b cf 04 af 95 93 33 6c-ec 7c c7 ee 80 a5 0a f0   ......3l.|......
    0030 - 63 ba 1e 8b 16 52 46 0d-cd d0 5f 55 4d 8e d1 53   c....RF..._UM..S
    0040 - fc f9 8b 62 c7 dd 2f 08-68 00 34 b8 53 1a 11 20   ...b../.h.4.S..
    0050 - 69 c6 5d 1a 21 9b e9 21-67 a4 1b 15 5f 45 e3 dd   i.].!..!g..._E..
    0060 - f1 d9 6b 36 af ee 9b a6-e7                        ..k6.....

    Start Time: 1655566562
    Timeout   : 7200 (sec)
    Verify return code: 19 (self-signed certificate in certificate chain)
    Extended master secret: no
    Max Early Data: 0
---
read R BLOCK
C
RECONNECTING
Connecting to 127.0.0.1
CONNECTED(00000005)
Verification error: self-signed certificate in certificate chain
---
Reused, TLSv1.3, Cipher is TLS_AES_128_GCM_SHA256
This TLS version forbids renegotiation.
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 19 (self-signed certificate in certificate chain)
---
---
Post-Handshake New Session Ticket arrived:
SSL-Session:
    Protocol  : TLSv1.3
    Cipher    : TLS_AES_128_GCM_SHA256
    Session-ID: EA17F26441383640827EA3E854335DB28E40C589D1E0457B856A088C7CBF5708
    Session-ID-ctx:
    Resumption PSK: 0F8D3D6D9E99EA87AAE7A5EB791E360511989BDCB073021FD0D7432FA537BAF4
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 172800 (seconds)
    TLS session ticket:
    0000 - 53 53 4b 2d 45 30 30 34-35 39 38 36 37 00 00 00   SSK-E00459867...
    0010 - dd b9 d4 8f 61 0d bb 84-30 37 e2 24 88 fc a1 dd   ....a...07.$....
    0020 - 74 f0 ca be 27 0b c1 61-7d 9e 17 6b fb 47 ce a1   t...'..a}..k.G..
    0030 - a2 6b 50 a6 96 1d 16 75-47 74 a9 33 6d de aa 8b   .kP....uGt.3m...
    0040 - 92 cd 0d c4 cc 96 09 44-79 72 15 f3 98 bc 7a b8   .......Dyr....z.
    0050 - 4f 1a 0d 0e 3c 55 f9 1b-e0 c0 52 48 62 6b e7 9b   O...<U....RHbk..
    0060 - 4f 74 e5 69 1a a0 63 27-61                        Ot.i..c'a

    Start Time: 1655566563
    Timeout   : 7200 (sec)
    Verify return code: 19 (self-signed certificate in certificate chain)
    Extended master secret: no
    Max Early Data: 0
---
read R BLOCK
kaduk commented 2 years ago

On a quick look, the analysis seems correct and the sketch of solution plausible. But s_client's code is ... not in a very maintainable state, so an in-depth review is not possible in the time I have available.

nhorman commented 3 months ago

@mattcaswell is this still an issue as far as you are aware?

mattcaswell commented 3 months ago

A quick test shows that this still seems to be a problem

nhorman commented 3 months ago

ok, thank you, moving to future minor consideration

christophe0 commented 2 months ago

I can confirm this. Tested with two hosts running nginx and haproxy (libssl 3.0.13), gnutls-cli is reporting session resumption for TLS1.3 and TLS1.2, openssl s_client (3.0.13) when downgraded to TLS1.2 only. TLS tickets are disabled.

# reuse/resume
gnutls-cli --resume [hostname] </dev/null
gnutls-cli --resume --priority NORMAL:-VERS-TLS1.3 [hostname] </dev/null
openssl s_client -connect [hostname]:443 -tls1_2 -reconnect </dev/null
# new
openssl s_client -connect [hostname]:443 -reconnect </dev/null