From 0fe60e82a804d617eeffc7f268b5ffee5a2e7fea Mon Sep 17 00:00:00 2001 From: David Cooper Date: Tue, 1 Oct 2019 15:48:02 -0400 Subject: [PATCH 1/2] Fix sub_session_resumption() This PR fixes an issue with sub_session_resumption() when using OpenSSL 1.1.1. As noted in #1335, some servers will return a session ticket for TLSv1.2, but not for TLSv1.3. OpenSSL 1.1.1 does not support the "-no_ssl2" option, and so when using OpenSSL 1.1.1 sub_session_resumption() adds $OPTIMAL_PROTO to the $OPENSSL s_client command line. When determine_optimal_proto_sockets_helper() is called, $OPTIMAL_PROTO will generally be set to "-tls1_2" (or "-tls1_1" or "-tls1") unless the server is a TLSv1.3-only server. As a result sub_session_resumption() will specify that same protocol on the command line if OpenSSL 1.1.1 is being used. If "--ssl-native" is used, however, then determine_optimal_proto() will set $OPTIMAL_PROTO to "-tls1_3" if the server supports TLSv1.3 (and doesn't use STARTTLS). Similarly, if the version of determine_optimal_proto() in #1336 is used, then $OPTIMAL_PROTO will usually be empty. In either case, sub_session_resumption() will send a TLSv1.3 ClientHello, even if the server only supports session tickets for TLSv1.2 and below. This PR appears to fix the problem. This PR makes no changes when using a version of OpenSSL that supports "-no_ssl2". When using a version of OpenSSL that does not support "-no_ssl2", however, rather than using $OPTIMAL_PROTO, this PR has sub_session_resumption() use whatever protocol version the server connected with when $sessticket_lifetime_hint was set. --- testssl.sh | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/testssl.sh b/testssl.sh index 30cda19..f070d8b 100755 --- a/testssl.sh +++ b/testssl.sh @@ -6055,8 +6055,9 @@ sub_session_resumption() { local sess_data=$(mktemp $TEMPDIR/sub_session_data_resumption.$NODEIP.XXXXXX) local -a rw_line local not_new_reused=false + local protocol="$1" - if [[ "$1" == ID ]]; then + if [[ "$2" == ID ]]; then local byID=true local addcmd="-no_ticket" else @@ -6067,7 +6068,10 @@ sub_session_resumption() { fi fi "$CLIENT_AUTH" && return 3 - "$HAS_NO_SSL2" && addcmd+=" -no_ssl2" || addcmd+=" $OPTIMAL_PROTO" + protocol=${protocol/\./_} + protocol=${protocol/v/} + protocol="-$(tolower $protocol)" + "$HAS_NO_SSL2" && addcmd+=" -no_ssl2" || addcmd+=" $protocol" $OPENSSL s_client $(s_client_options "$STARTTLS $BUGS -connect $NODEIP:$PORT $PROXY $SNI $addcmd -sess_out $sess_data") /dev/null ret1=$? @@ -8823,7 +8827,7 @@ certificate_info() { run_server_defaults() { local ciph newhostcert sni local match_found - local sessticket_lifetime_hint="" lifetime unit + local sessticket_lifetime_hint="" sessticket_proto="" lifetime unit local -i i n local -i certs_found=0 local -i ret=0 @@ -8890,6 +8894,7 @@ run_server_defaults() { >$ERRFILE if [[ -z "$sessticket_lifetime_hint" ]]; then sessticket_lifetime_hint=$(awk '/session ticket life/ { if (!found) print; found=1 }' $TMPFILE) + sessticket_proto="$(get_protocol "$TMPFILE")" fi if [[ $n -le 7 ]]; then @@ -9042,7 +9047,10 @@ run_server_defaults() { if [[ $? -eq 0 ]] && [[ "$OPTIMAL_PROTO" != -ssl2 ]]; then cp "$TEMPDIR/$NODEIP.determine_tls_extensions.txt" $TMPFILE >$ERRFILE - [[ -z "$sessticket_lifetime_hint" ]] && sessticket_lifetime_hint=$(awk '/session ticket lifetime/ { if (!found) print; found=1 }' $TMPFILE) + if [[ -z "$sessticket_lifetime_hint" ]]; then + sessticket_lifetime_hint=$(awk '/session ticket lifetime/ { if (!found) print; found=1 }' $TMPFILE) + sessticket_proto="$(get_protocol "$TMPFILE")" + fi fi if "$using_sockets" && ! "$TLS13_ONLY" && [[ -z "$sessticket_lifetime_hint" ]] && [[ "$OPTIMAL_PROTO" != -ssl2 ]]; then if "$HAS_TLS13" && ( [[ -z "$OPTIMAL_PROTO" ]] || [[ "$OPTIMAL_PROTO" == -tls1_3 ]] ) ; then @@ -9052,7 +9060,10 @@ run_server_defaults() { else $OPENSSL s_client $(s_client_options "$STARTTLS $BUGS "$OPTIMAL_PROTO" -connect $NODEIP:$PORT $PROXY $SNI") $ERRFILE >$TMPFILE fi - sclient_connect_successful $? $TMPFILE && sessticket_lifetime_hint=$(awk '/session ticket lifetime/ { if (!found) print; found=1 }' $TMPFILE) + if sclient_connect_successful $? $TMPFILE; then + sessticket_lifetime_hint=$(awk '/session ticket lifetime/ { if (!found) print; found=1 }' $TMPFILE) + sessticket_proto="$(get_protocol "$TMPFILE")" + fi fi [[ -z "$sessticket_lifetime_hint" ]] && TLS_TICKETS=false || TLS_TICKETS=true @@ -9122,7 +9133,7 @@ run_server_defaults() { pr_bold " Session Resumption " jsonID="sessionresumption_ticket" - sub_session_resumption + sub_session_resumption "$sessticket_proto" case $? in 0) SESS_RESUMPTION[2]="ticket=yes" out "Tickets: yes, " @@ -9154,7 +9165,7 @@ run_server_defaults() { outln "ID: no" fileout "$jsonID" "INFO" "No Session ID, no resumption" else - sub_session_resumption ID + sub_session_resumption "$sessticket_proto" ID case $? in 0) SESS_RESUMPTION[1]="ID=yes" outln "ID: yes" From 644d7c839ed9c6b02c7263dff18859a10a2b559d Mon Sep 17 00:00:00 2001 From: David Cooper Date: Tue, 1 Oct 2019 16:25:51 -0400 Subject: [PATCH 2/2] Update This commit addresses TLSv1.3 servers that do not support session tickets by that support session resumption by ID, but only with TLSv1.2 or earlier. --- testssl.sh | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/testssl.sh b/testssl.sh index f070d8b..6300d43 100755 --- a/testssl.sh +++ b/testssl.sh @@ -6068,10 +6068,21 @@ sub_session_resumption() { fi fi "$CLIENT_AUTH" && return 3 - protocol=${protocol/\./_} - protocol=${protocol/v/} - protocol="-$(tolower $protocol)" - "$HAS_NO_SSL2" && addcmd+=" -no_ssl2" || addcmd+=" $protocol" + if "$HAS_NO_SSL2"; then + addcmd+=" -no_ssl2" + else + protocol=${protocol/\./_} + protocol=${protocol/v/} + protocol="-$(tolower $protocol)" + # In some cases a server will not support session tickets, but will support session resumption + # by ID. In such a case, it may be more likely to support session resumption with TLSv1.2 than + # with TLSv1.3. So, if testing a server that does not support session tickets and that supports + # both TLSv1.3 and TLSv1.2 for session resumption by ID, then use a TLSv1.2 ClientHello. (Note that + # the line below assumes that if $protocol is -tls1_3, then the server either supports TLSv1.2 or + # is TLSv1.3-only. + ! "$TLS_TICKETS" && "$byID" && [[ $(has_server_protocol "tls1_2") -eq 0 ]] && protocol="-tls1_2" + addcmd+=" $protocol" + fi $OPENSSL s_client $(s_client_options "$STARTTLS $BUGS -connect $NODEIP:$PORT $PROXY $SNI $addcmd -sess_out $sess_data") /dev/null ret1=$?