From 3152cdf864aee35ee0862b0fb69a698204ae25db Mon Sep 17 00:00:00 2001 From: Dirk Date: Wed, 5 Mar 2025 14:41:12 +0100 Subject: [PATCH 1/3] Banner change + minor fix for curve detection In order to tell openssl binaries better apart the short banner below the hash tag signs contain now also the date. That is the short version of the build date unless it is not supplied which is the case of opensuse. Then the name contains the date and it's taken from there. The start and end banner lines have the same length now. "sieve" was added in a comment and the sequence where sieve appears in a pattern was trying to match other occurences (i.e. after nntp) While testing the banners it appeared under Linux that a) the vendor supplied openssl sometimes hangs during startup when determining the supported curves using -connect b) a pattern was missing to detect whether the curve was not supported which falsely labeled all supplied curves as supported when using /usr/bin/openssl . The pattern for the latter was added (b). For a) there needs to be a follow up PR to avoid the long delays. --- testssl.sh | 80 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 30 deletions(-) diff --git a/testssl.sh b/testssl.sh index 7f8d98a..c782c18 100755 --- a/testssl.sh +++ b/testssl.sh @@ -3512,7 +3512,7 @@ prettyprint_local() { fi if [[ -z "$1" ]]; then - pr_headline " Displaying all $OPENSSL_NR_CIPHERS local ciphers "; + pr_headline " Displaying all $OPENSSL_NR_CIPHERS local OpenSSL ciphers "; else pr_headline " Displaying all local ciphers "; # pattern provided; which one? @@ -20345,25 +20345,25 @@ find_openssl_binary() { fi fi - # https://www.openssl.org/news/changelog.html - # https://web.archive.org/web/20150815130800/http://openssl.org/news/openssl-notes.html - OSSL_NAME=$($OPENSSL version 2>/dev/null | awk '{ print $1 }') - OSSL_VER=$($OPENSSL version 2>/dev/null | awk -F' ' '{ print $2 }') + $OPENSSL version -a 2>/dev/null >$TEMPDIR/openssl_version_all + ossl_line1=$(head -1 $TEMPDIR/openssl_version_all) + OSSL_NAME=$(awk '{ print $1 }' <<< "${ossl_line1}") + OSSL_VER=$(awk -F' ' '{ print $2 }' <<< "${ossl_line1}") OSSL_VER_MAJOR="${OSSL_VER%%\.*}" - ossl_wo_dev_info="${OSSL_VER%%-*}" - OSSL_VER_MINOR="${ossl_wo_dev_info#$OSSL_VER_MAJOR\.}" + OSSL_VER_MINOR="${OSSL_VER%%-*}" + OSSL_VER_MINOR="${OSSL_VER_MINOR#$OSSL_VER_MAJOR\.}" OSSL_VER_MINOR="${OSSL_VER_MINOR%%[a-zA-Z]*}" + # like -bad -fips etc: OSSL_VER_APPENDIX="${OSSL_VER#$OSSL_VER_MAJOR\.$OSSL_VER_MINOR}" - OSSL_VER_PLATFORM=$($OPENSSL version -p 2>/dev/null | sed 's/^platform: //') - OSSL_BUILD_DATE=$($OPENSSL version -a 2>/dev/null | grep '^built' | sed -e 's/built on//' -e 's/: ... //' -e 's/: //' -e 's/ UTC//' -e 's/ +0000//' -e 's/.000000000//') + OSSL_VER_PLATFORM="$(awk '/^platform: / { print $2 }' < $TEMPDIR/openssl_version_all)" + OSSL_BUILD_DATE="$(awk '/^built on/' < $TEMPDIR/openssl_version_all)" + OSSL_BUILD_DATE=${OSSL_BUILD_DATE#*: } - # Determine an OpenSSL short string for the banner - # E.g MacOS' homebrew and Debian add a library string: OpenSSL 3.3.1 4 Jun 2024 (Library: OpenSSL 3.3.1 4 Jun 2024), + # MacOS' homebrew and Debian add a library string: OpenSSL 3.3.1 4 Jun 2024 (Library: OpenSSL 3.3.1 4 Jun 2024), # so we omit the part after the round bracket as it breaks formatting and doesn't provide more useful info - OSSL_SHORT_STR=$($OPENSSL version 2>/dev/null) - OSSL_SHORT_STR=${OSSL_SHORT_STR%\(*} - # Now handle strings like this: OpenSSL 1.1.1l-fips 24 Aug 2021 SUSE release 150500.17.34.1 - # we find the year, remove until first occurrence, re-add it + OSSL_SHORT_STR=${ossl_line1%\(*} + # Now handle strings like "OpenSSL 1.1.1l-fips 24 Aug 2021 SUSE release 150500.17.34.1". So we look for + # the year, remove it until the end and then re-add just the year for yr in {2014..2029} ; do if [[ $OSSL_SHORT_STR =~ \ $yr ]] ; then OSSL_SHORT_STR=${OSSL_SHORT_STR%%$yr*} @@ -20371,6 +20371,22 @@ find_openssl_binary() { break fi done + # Now OSSL_SHORT_STR contains for newer binaries "OpenSSL 3.3.1 4 Jun 2024" and for the supplied "OpenSSL 1.0.2-bad". + # Now, determine the build date if there is one, Opensuse doesn't seem to have one, then we pick the date instead from the first line + if [[ -z ${OSSL_BUILD_DATE} ]]; then + # determine date from the form. And take that as a built date internally + OSSL_NAME=${OSSL_SHORT_STR/?? ??? 20??/} + OSSL_BUILD_DATE=${OSSL_SHORT_STR/$OSSL_NAME/} + else + # Remove TZ + OSSL_BUILD_DATE=${OSSL_BUILD_DATE/UTC/} + fi + # opensuse e.g. has also the version in the name which we don't want there + OSSL_NAME=${OSSL_NAME/$OSSL_VER/} + # Reduce double spaces to just one and remove trailing space + OSSL_BUILD_DATE=${OSSL_BUILD_DATE/ / } + OSSL_BUILD_DATE="$(strip_trailing_space "$OSSL_BUILD_DATE")" + OSSL_NAME=${OSSL_NAME// /} # see #190, reverting logic: unless otherwise proved openssl has no dh bits case "$OSSL_VER_MAJOR.$OSSL_VER_MINOR" in @@ -20470,13 +20486,11 @@ find_openssl_binary() { $OPENSSL s_client -no_comp &1 | grep -aiq "unknown option" || HAS_NO_COMP=true OPENSSL_NR_CIPHERS=$(count_ciphers "$(actually_supported_osslciphers 'ALL:COMPLEMENTOFALL' 'ALL')") - # The following statement works with OpenSSL 1.0.2, 1.1.1 and 3.0 and LibreSSL 3.4 if $OPENSSL s_client -curves &1 | grep -aiq "unknown option"; then - # This is e.g. for LibreSSL (tested with version 3.4.1): WSL users will get "127.0.0.1:0" here, - # all other "invalid.:0". We need a port here, in any case! - # The $OPENSSL connect call deliberately fails: when the curve isn't available with - # "getaddrinfo: Name or service not known", newer LibreSSL with "Failed to set groups". + # LibreSSL (tested with version 3.4.1 and 3.0.2) need -groups instead of -curve + # WSL users connect to "127.0.0.1:0", others to "invalid." or "invalid.:0" + # The $OPENSSL connect call deliberately fails: when the curve isn't available with the described error messages for curve in "${curves_ossl[@]}"; do $OPENSSL s_client -groups $curve -connect ${NXCONNECT%:*}:0 &1 | grep -Eiaq "Error with command|unknown option|Failed to set groups" [[ $? -ne 0 ]] && OSSL_SUPPORTED_CURVES+=" $curve " @@ -20485,7 +20499,8 @@ find_openssl_binary() { HAS_CURVES=true for curve in "${curves_ossl[@]}"; do # Same as above, we just don't need a port for invalid. - $OPENSSL s_client -curves $curve -connect $NXCONNECT &1 | grep -Eiaq "Error with command|unknown option" + #FIXME: openssl 3 sometimes seems somtimes to hang when using '-connect invalid.' for up to 10 seconds + $OPENSSL s_client -curves $curve -connect $NXCONNECT &1 | grep -Eiaq "Error with command|unknown option|cannot be set" [[ $? -ne 0 ]] && OSSL_SUPPORTED_CURVES+=" $curve " done fi @@ -20712,7 +20727,7 @@ help() { and [options] is/are: -t, --starttls Does a run against a STARTTLS enabled service which is one of ftp, smtp, lmtp, pop3, imap, - sieve, xmpp, xmpp-server, telnet, ldap, nntp, postgres, mysql + xmpp, xmpp-server, telnet, ldap, nntp, sieve, postgres, mysql --xmpphost For STARTTLS xmpp or xmpp-server checks it supplies the domainname (like SNI) --mx Tests MX records from high to low priority (STARTTLS, port 25) --file/-iL Mass testing option: Reads one testssl.sh command line per line from . @@ -21012,11 +21027,11 @@ prepare_arrays() { mybanner() { local bb1 bb2 bb3 local spaces=" " - local full="$1" + local full="$1" # we have a short version and a longer one (two liner vs 4 liner) + local short_built_date="" # a reduced version of the build date in the short banner "$QUIET" && return "$CHILD_MASS_TESTING" && return - OPENSSL_NR_CIPHERS=$(count_ciphers "$(actually_supported_osslciphers 'ALL:COMPLEMENTOFALL:@STRENGTH' 'ALL')") bb1=$(cat <> $node_banner <<--" else - pr_reverse "$1 $(date +%F) $(date +%T) -->> $node_banner <<--" + pr_reverse "$1 $(date +%F) $(date +%T) -->> $node_banner <<--" fi outln "\n" [[ "$1" =~ Start ]] && display_rdns_etc From 5ffcd086ebba1608262a9e48c2d7e9b3517bb8a4 Mon Sep 17 00:00:00 2001 From: Dirk Date: Wed, 5 Mar 2025 15:02:15 +0100 Subject: [PATCH 2/3] Add missing local vars --- testssl.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/testssl.sh b/testssl.sh index c782c18..c4f31ba 100755 --- a/testssl.sh +++ b/testssl.sh @@ -20310,6 +20310,7 @@ find_openssl_binary() { local openssl_location cwd="" local ossl_wo_dev_info local curve + local ossl_line1="" yr="" local -a curves_ossl=("sect163k1" "sect163r1" "sect163r2" "sect193r1" "sect193r2" "sect233k1" "sect233r1" "sect239k1" "sect283k1" "sect283r1" "sect409k1" "sect409r1" "sect571k1" "sect571r1" "secp160k1" "secp160r1" "secp160r2" "secp192k1" "prime192v1" "secp224k1" "secp224r1" "secp256k1" "prime256v1" "secp384r1" "secp521r1" "brainpoolP256r1" "brainpoolP384r1" "brainpoolP512r1" "X25519" "X448" "brainpoolP256r1tls13" "brainpoolP384r1tls13" "brainpoolP512r1tls13" "ffdhe2048" "ffdhe3072" "ffdhe4096" "ffdhe6144" "ffdhe8192") # 0. check environment variable whether it's executable @@ -21062,7 +21063,7 @@ EOF pr_bold "$bb3" outln "\n" - # remove clock and dow if the first word if it is a dow and not a dom (suse) + # remove clock and dow if the first word is a dow and not a dom (suse) short_built_date=${OSSL_BUILD_DATE/??:??:?? /} if [[ ${short_built_date%% *} =~ [A-Za-z]{3} ]]; then short_built_date=${short_built_date#* } From e2ee8b24b420fb6baf5c621364451bf393dccf81 Mon Sep 17 00:00:00 2001 From: Dirk Date: Wed, 5 Mar 2025 15:06:41 +0100 Subject: [PATCH 3/3] fix typo in comment --- testssl.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testssl.sh b/testssl.sh index c4f31ba..ee2d55f 100755 --- a/testssl.sh +++ b/testssl.sh @@ -20500,7 +20500,7 @@ find_openssl_binary() { HAS_CURVES=true for curve in "${curves_ossl[@]}"; do # Same as above, we just don't need a port for invalid. - #FIXME: openssl 3 sometimes seems somtimes to hang when using '-connect invalid.' for up to 10 seconds + #FIXME: openssl 3 sometimes seems to hang when using '-connect invalid.' for up to 10 seconds $OPENSSL s_client -curves $curve -connect $NXCONNECT &1 | grep -Eiaq "Error with command|unknown option|cannot be set" [[ $? -ne 0 ]] && OSSL_SUPPORTED_CURVES+=" $curve " done