Merge branch '3.2' into co_header

This commit is contained in:
Dirk 2025-01-22 22:50:00 +01:00
commit 207b902109
8 changed files with 175 additions and 92 deletions

View File

@ -23,7 +23,7 @@ jobs:
- name: Setup QEMU - name: Setup QEMU
id: qemu id: qemu
uses: docker/setup-qemu-action@v3.2.0 uses: docker/setup-qemu-action@v3.3.0
- name: Setup Buildx - name: Setup Buildx
id: buildx id: buildx
@ -48,7 +48,7 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push - name: Build and push
uses: docker/build-push-action@v6.9.0 uses: docker/build-push-action@v6.12.0
with: with:
push: ${{ github.event_name != 'pull_request' }} push: ${{ github.event_name != 'pull_request' }}
context: . context: .

View File

@ -137,7 +137,7 @@
* Trust chain check against certificate stores from Apple (OS), Linux (OS), * Trust chain check against certificate stores from Apple (OS), Linux (OS),
Microsoft (OS), Mozilla (Firefox Browser), works for openssl >=1.0.1 Microsoft (OS), Mozilla (Firefox Browser), works for openssl >=1.0.1
* IPv6 (status: 80% working, details see * IPv6 (status: 80% working, details see
https://github.com/drwetter/testssl.sh/issues/11 https://github.com/testssl/testssl.sh/issues/11
* works now on servers requiring a x509 certificate for authentication * works now on servers requiring a x509 certificate for authentication
* extensive CN <--> hostname check * extensive CN <--> hostname check
* SSL Session ID check * SSL Session ID check
@ -183,7 +183,7 @@
* quite some LibreSSL fixes, still not recommended to use though (see https://testssl.sh/) * quite some LibreSSL fixes, still not recommended to use though (see https://testssl.sh/)
* lots of fixes, code improvements, even more robust * lots of fixes, code improvements, even more robust
Full log @ https://github.com/drwetter/testssl.sh/commits/2.6/testssl.sh Full log @ https://github.com/testssl/testssl.sh/commits/2.6/testssl.sh
### New in 2.4 ### New in 2.4
* "only one cmd line option at a time" is completely gone * "only one cmd line option at a time" is completely gone
@ -198,7 +198,7 @@ Full log @ https://github.com/drwetter/testssl.sh/commits/2.6/testssl.sh
* lots of cosmetic and maintainability code cleanups * lots of cosmetic and maintainability code cleanups
* bugfixing * bugfixing
Full changelog: https://github.com/drwetter/testssl.sh/commits/2.4/testssl.sh Full changelog: https://github.com/testssl/testssl.sh/commits/2.4/testssl.sh
### 2.2. new features: ### 2.2. new features:
* Works fully under FreeBSD (openssl >=1.0) * Works fully under FreeBSD (openssl >=1.0)
@ -214,7 +214,7 @@ Full changelog: https://github.com/drwetter/testssl.sh/commits/2.4/testssl.sh
* RFC <---> OpenSSL name space mapping of ciphers everywhere * RFC <---> OpenSSL name space mapping of ciphers everywhere
* includes a lot of fixes * includes a lot of fixes
Full changelog @ https://github.com/drwetter/testssl.sh/commits/2.2/testssl.sh Full changelog @ https://github.com/testssl/testssl.sh/commits/2.2/testssl.sh
### 2.0 major release, new features: ### 2.0 major release, new features:
* SNI * SNI

View File

@ -5,7 +5,7 @@ is always welcome, here @ github or via e-mail.
Note please the following Note please the following
* Please read at least the [coding convention](https://github.com/drwetter/testssl.sh/Coding_Convention.md). * Please read at least the [coding convention](https://github.com/testssl/testssl.sh/Coding_Convention.md).
* One PR per feature or bug fix or improvement. Please do not mix issues. * One PR per feature or bug fix or improvement. Please do not mix issues.
* Document your PR, both in the PR and/or commit message and in the code. * Document your PR, both in the PR and/or commit message and in the code.
* Please test your changes thoroughly as reliability is important for this project. You may want to check different servers with different settings. * Please test your changes thoroughly as reliability is important for this project. You may want to check different servers with different settings.

View File

@ -5,8 +5,8 @@ FROM alpine:3.20
WORKDIR /home/testssl WORKDIR /home/testssl
ARG BUILD_VERSION ARG BUILD_VERSION
ARG ARCHIVE_URL=https://github.com/drwetter/testssl.sh/archive/ ARG ARCHIVE_URL=https://github.com/testssl/testssl.sh/archive/
ARG URL=https://github.com/drwetter/testssl.sh.git ARG URL=https://github.com/testssl/testssl.sh.git
RUN test -n "${BUILD_VERSION}" \ RUN test -n "${BUILD_VERSION}" \
&& apk update \ && apk update \

View File

@ -1,10 +1,11 @@
## Intro ## Intro
[![CI tests](https://github.com/drwetter/testssl.sh/actions/workflows/unit_tests.yml/badge.svg)](https://github.com/drwetter/testssl.sh/actions/workflows/unit_tests.yml) [![CI tests](https://github.com/testssl/testssl.sh/actions/workflows/unit_tests.yml/badge.svg)](https://github.com/testssl/testssl.sh/actions/workflows/unit_tests.yml)
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/drwetter/testssl.sh?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/testssl/testssl.sh?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![License](https://img.shields.io/github/license/drwetter/testssl.sh)](https://github.com/drwetter/testssl.sh/LICENSE) [![License](https://img.shields.io/github/license/testssl/testssl.sh)](https://github.com/testssl/testssl.sh/LICENSE)
[![Docker](https://img.shields.io/docker/pulls/drwetter/testssl.sh)](https://github.com/drwetter/testssl.sh/blob/3.2/Dockerfile.md) [![Docker](https://img.shields.io/docker/pulls/testssl/testssl.sh)](https://github.com/testssl/testssl.sh/blob/3.2/Dockerfile.md)
`testssl.sh` is a free command line tool which checks a server's service on `testssl.sh` is a free command line tool which checks a server's service on
any port for the support of TLS/SSL ciphers, protocols as well as some any port for the support of TLS/SSL ciphers, protocols as well as some
@ -44,16 +45,16 @@ due to bash-socket-based checks. As a result you can also use e.g. LibreSSL or O
(silent) check for binaries is done when you start testssl.sh . System V needs probably (silent) check for binaries is done when you start testssl.sh . System V needs probably
to have GNU grep installed. MacOS X and Windows (using MSYS2, Cygwin or WSL) work too. to have GNU grep installed. MacOS X and Windows (using MSYS2, Cygwin or WSL) work too.
Update notification here or @ [mastodon](https://infosec.exchange/@testssl) (old: [twitter](https://twitter.com/drwetter)) Update notification here or @ [mastodon](https://infosec.exchange/@testssl or [bluesky](https://bsky.app/profile/testssl.bsky.social). Please note the [twitter](https://twitter.com/drwetter) account is not being used anymore.
### Installation ### Installation
You can download testssl.sh branch 3.2 just by cloning this git repository: You can download testssl.sh branch 3.2 just by cloning this git repository:
git clone --depth 1 https://github.com/drwetter/testssl.sh.git git clone --depth 1 https://github.com/testssl/testssl.sh.git
3.2 is now the latest branch which evolved from 3.1dev. It's in the release candidate phase. 3.2 is now the latest branch which evolved from 3.1dev. It's in the release candidate phase and considered as stable.
For the former stable version help yourself by downloading the [ZIP](https://codeload.github.com/drwetter/testssl.sh/zip/v3.0.8) or [tar.gz](https://codeload.github.com/drwetter/testssl.sh/tar.gz/v3.0.8) archive. Just ``cd`` to the directory created (=INSTALLDIR) and run it off there. For the former stable version named oldstable please help yourself by downloading the [ZIP](https://codeload.github.com/testssl/testssl.sh/zip/v3.0.9) or [tar.gz](https://codeload.github.com/testssl/testssl.sh/tar.gz/v3.0.9) archive. Just ``cd`` to the directory created (=INSTALLDIR) and run it off there.
#### Docker #### Docker
@ -68,19 +69,19 @@ Or if you have cloned this repo you also can just ``cd`` to the INSTALLDIR and r
docker build . -t imagefoo && docker run --rm -t imagefoo example.com docker build . -t imagefoo && docker run --rm -t imagefoo example.com
``` ```
For more please consult [Dockerfile.md](https://github.com/drwetter/testssl.sh/blob/3.2/Dockerfile.md). For more please consult [Dockerfile.md](https://github.com/testssl/testssl.sh/blob/3.2/Dockerfile.md).
### No Warranty ### No Warranty
Usage of the program is without any warranty. Use it at your own risk. Usage of the program is without any warranty. Use it at your own risk.
Testssl.sh is intended to be used as a standalone CLI tool. While we tried to apply best practise security measures, we can't guarantee that the program is without any vulnerabilities. Running as a service may pose security risks and you're recommended to apply additional security measures. Testssl.sh is intended to be used as a standalone CLI tool. While we tried to apply best practise security measures, we can't guarantee that the program is without any vulnerabilities. Running as a service may pose security risks and you're recommended to apply additional security measures.
### Status ### Status
We're currently in the release candidate phase for version 3.2. Bigger features will be developed in a separate branch before merged into a 3.3dev to avoid hiccups or inconsistencies. We're currently in the release candidate phase for version 3.2. You should use it despite the label "RC". Bigger features will be developed in a separate branch before merged into a 3.3dev to avoid hiccups or inconsistencies.
Version 3.0.X receives bugfixes, labeled as 3.0.1, 3.0.2 and so on. This will happen until 3.2 is released. Version 3.0.X receives bugfixes, labeled as 3.0.1, 3.0.2 and so on. This will happen until 3.2 is finally released.
Support for 2.9.5 has been dropped. Supported is >= 3.0.x only. Support for 2.9.5 has been dropped. Supported is >= 3.0.x only.
@ -92,16 +93,19 @@ Support for 2.9.5 has been dropped. Supported is >= 3.0.x only.
### Contributing ### Contributing
Contributions are welcome! See [CONTRIBUTING.md](https://github.com/drwetter/testssl.sh/blob/3.2/CONTRIBUTING.md) for details. Please also have a look at the [Coding Convention](https://github.com/drwetter/testssl.sh/blob/3.2/Coding_Convention.md). Contributions are welcome! See [CONTRIBUTING.md](https://github.com/testssl/testssl.sh/blob/3.2/CONTRIBUTING.md) for details. Please also have a look at the [Coding Convention](https://github.com/testssl/testssl.sh/blob/3.2/Coding_Convention.md). A lot of contributors already helped to push the project where it currently is, see [CREDITS.md](https://github.com/testssl/testssl.sh/blob/3.2/CREDITS.md). We still you use your help now. A start would be look for issues which are labeled as [good first issue](https://github.com/testssl/testssl.sh/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22), [for grabs](https://github.com/testssl/testssl.sh/issues?q=is%3Aissue+is%3Aopen+label%3A%22for+grabs%22) or [help wanted](https://github.com/testssl/testssl.sh/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22). The latter is more advanced.
In general there's some maintenance burden, like maintaining handshakes and CA stores, writing unit tests, improving github actions. If you believe you can contribute, speak up.
### Bug reports ### Bug reports
Bug reports are important. It makes this project more robust. Bug reports are important. It makes this project more robust.
Please file bugs in the issue tracker @ GitHub. Do not forget to provide detailed information, see template for issue, and further details @ Please file bugs in the issue tracker @ GitHub. Do not forget to provide detailed information, see template for issue, and further details @
https://github.com/drwetter/testssl.sh/wiki/Bug-reporting. Nobody can read your thoughts -- yet. And only agencies your screen ;-) https://github.com/testssl/testssl.sh/wiki/Bug-reporting. Nobody can read your thoughts -- yet. And only agencies your screen ;-)
You can also debug yourself, see [here](https://github.com/drwetter/testssl.sh/wiki/Findings-and-HowTo-Fix-them). You can also debug yourself, see [here](https://github.com/testssl/testssl.sh/wiki/Findings-and-HowTo-Fix-them).
---- ----
@ -128,7 +132,7 @@ Please address questions not specifically to the code of testssl.sh to the respe
#### Brew package #### Brew package
* see [#233](https://github.com/drwetter/testssl.sh/issues/233) and * see [#233](https://github.com/testssl/testssl.sh/issues/233) and
[https://github.com/Homebrew/homebrew](https://github.com/Homebrew/homebrew) [https://github.com/Homebrew/homebrew](https://github.com/Homebrew/homebrew)
#### Daemon for batch execution of testssl.sh command files #### Daemon for batch execution of testssl.sh command files

View File

@ -45,3 +45,7 @@
0x01,0x02 - ffdhe4096 ffdhe4096 0x01,0x02 - ffdhe4096 ffdhe4096
0x01,0x03 - ffdhe6144 ffdhe6144 0x01,0x03 - ffdhe6144 ffdhe6144
0x01,0x04 - ffdhe8192 ffdhe8192 0x01,0x04 - ffdhe8192 ffdhe8192
0x11,0xeb - SecP256r1MLKEM768 SecP256r1MLKEM768
0x11,0xec - X25519MLKEM768 X25519MLKEM768
0x11,0xed - SecP384r1MLKEM1024 SecP384r1MLKEM1024
0x63,0x99 - X25519Kyber768Draft00 X25519Kyber768Draft00

File diff suppressed because one or more lines are too long

View File

@ -7,9 +7,9 @@
# vulnerabilities or features. It may or may be not distributed by your distribution. # vulnerabilities or features. It may or may be not distributed by your distribution.
# The upstream versions are available (please leave the links intact): # The upstream versions are available (please leave the links intact):
# #
# Development version https://github.com/drwetter/testssl.sh # Development version https://github.com/testssl/testssl.sh
# Stable version https://testssl.sh # Stable version https://testssl.sh
# File bugs at GitHub https://github.com/drwetter/testssl.sh/issues # File bugs at GitHub https://github.com/testssl/testssl.sh/issues
# #
# Project lead and initiator: Dirk Wetter, copyleft: 2007-today, contributions so far see CREDITS.md # Project lead and initiator: Dirk Wetter, copyleft: 2007-today, contributions so far see CREDITS.md
# Main contributions from David Cooper # Main contributions from David Cooper
@ -399,7 +399,7 @@ RSA_CERT_FINGERPRINT_SHA2=""
STARTTLS_PROTOCOL="" STARTTLS_PROTOCOL=""
OPTIMAL_PROTO="" # Need this for IIS6 (sigh) + OpenSSL 1.0.2, otherwise some handshakes will fail see OPTIMAL_PROTO="" # Need this for IIS6 (sigh) + OpenSSL 1.0.2, otherwise some handshakes will fail see
# https://github.com/PeterMosmans/openssl/issues/19#issuecomment-100897892 # https://github.com/PeterMosmans/openssl/issues/19#issuecomment-100897892
STARTTLS_OPTIMAL_PROTO="" # Same for STARTTLS, see https://github.com/drwetter/testssl.sh/issues/188 STARTTLS_OPTIMAL_PROTO="" # Same for STARTTLS, see https://github.com/testssl/testssl.sh/issues/188
OPTIMAL_SOCKETS_PROTO="" # Same for tls_sockets(). -- not yet used OPTIMAL_SOCKETS_PROTO="" # Same for tls_sockets(). -- not yet used
ALL_FAILED_SOCKETS=true # Set to true if all attempts to connect to server using tls_sockets/sslv2_sockets failed ALL_FAILED_SOCKETS=true # Set to true if all attempts to connect to server using tls_sockets/sslv2_sockets failed
TLS_TIME="" # To keep the value of TLS server timestamp TLS_TIME="" # To keep the value of TLS server timestamp
@ -617,7 +617,7 @@ tmln_cyan() { tm_cyan "$1"; tmln_out; }
pr_cyan() { tm_cyan "$1"; [[ "$COLOR" -ge 2 ]] && html_out "<span style=\"color:#0d7ea2;font-weight:bold;\">$(html_reserved "$1")</span>" || html_out "$(html_reserved "$1")"; } pr_cyan() { tm_cyan "$1"; [[ "$COLOR" -ge 2 ]] && html_out "<span style=\"color:#0d7ea2;font-weight:bold;\">$(html_reserved "$1")</span>" || html_out "$(html_reserved "$1")"; }
prln_cyan() { pr_cyan "$1"; outln; } prln_cyan() { pr_cyan "$1"; outln; }
tm_litegrey() { [[ "$COLOR" -ne 0 ]] && tm_out "\033[0;37m$1" || tm_out "$1"; tm_off; } # ... https://github.com/drwetter/testssl.sh/pull/600#issuecomment-276129876 tm_litegrey() { [[ "$COLOR" -ne 0 ]] && tm_out "\033[0;37m$1" || tm_out "$1"; tm_off; } # ... https://github.com/testssl/testssl.sh/pull/600#issuecomment-276129876
tmln_litegrey() { tm_litegrey "$1"; tmln_out; } # not really usable on a black background, see .. tmln_litegrey() { tm_litegrey "$1"; tmln_out; } # not really usable on a black background, see ..
prln_litegrey() { pr_litegrey "$1"; outln; } prln_litegrey() { pr_litegrey "$1"; outln; }
pr_litegrey() { tm_litegrey "$1"; [[ "$COLOR" -ne 0 ]] && html_out "<span style=\"color:#71767a;\">$(html_reserved "$1")</span>" || html_out "$(html_reserved "$1")"; } pr_litegrey() { tm_litegrey "$1"; [[ "$COLOR" -ne 0 ]] && html_out "<span style=\"color:#71767a;\">$(html_reserved "$1")</span>" || html_out "$(html_reserved "$1")"; }
@ -1037,7 +1037,7 @@ get_cipher() {
# However there seem to be cases where the preferred $(< "$1") logic has a problem. # However there seem to be cases where the preferred $(< "$1") logic has a problem.
# Especially with bash 3.2 (Mac OS X) and when on the server side binary chars # Especially with bash 3.2 (Mac OS X) and when on the server side binary chars
# are returned, see https://stackoverflow.com/questions/7427262/how-to-read-a-file-into-a-variable-in-shell#22607352 # are returned, see https://stackoverflow.com/questions/7427262/how-to-read-a-file-into-a-variable-in-shell#22607352
# and https://github.com/drwetter/testssl.sh/issues/1292 # and https://github.com/testssl/testssl.sh/issues/1292
# Performance measurements showed no to barely measurable penalty (1s displayed in 9 tries). # Performance measurements showed no to barely measurable penalty (1s displayed in 9 tries).
if [[ "$server_hello" =~ Cipher\ *:\ ([A-Z0-9]+-[A-Za-z0-9\-]+|TLS_[A-Za-z0-9_]+|SSL_[A-Za-z0-9_]+) ]]; then if [[ "$server_hello" =~ Cipher\ *:\ ([A-Z0-9]+-[A-Za-z0-9\-]+|TLS_[A-Za-z0-9_]+|SSL_[A-Za-z0-9_]+) ]]; then
@ -4935,9 +4935,9 @@ client_simulation_sockets() {
data+=", ${clienthello:i:2}" data+=", ${clienthello:i:2}"
done done
# same as above. If a CIPHER_SUITES string was provided, then check that it is in the ServerHello # same as above. If a CIPHER_SUITES string was provided, then check that it is in the ServerHello
# this appeared 1st in yassl + MySQL (https://github.com/drwetter/testssl.sh/pull/784) but adds # this appeared 1st in yassl + MySQL (https://github.com/testssl/testssl.sh/pull/784) but adds
# robustness to the implementation # robustness to the implementation
# see also https://github.com/drwetter/testssl.sh/pull/797 # see also https://github.com/testssl/testssl.sh/pull/797
if [[ "${1:0:4}" == 1603 ]]; then if [[ "${1:0:4}" == 1603 ]]; then
# Extract list of cipher suites from SSLv3 or later ClientHello # Extract list of cipher suites from SSLv3 or later ClientHello
sid_len=4*$(hex2dec "${data:174:2}") sid_len=4*$(hex2dec "${data:174:2}")
@ -5295,7 +5295,9 @@ run_client_simulation() {
fi fi
if [[ -n "$what_dh" ]]; then if [[ -n "$what_dh" ]]; then
[[ -n "$curve" ]] && curve="($curve)" [[ -n "$curve" ]] && curve="($curve)"
if [[ "$what_dh" == ECDH ]]; then if [[ "$what_dh" =~ MLKEM ]] || [[ "$what_dh" =~ Kyber ]]; then
pr_kem_quality "$bits" "$(printf -- "%-12s" "$what_dh")"
elif [[ "$what_dh" == ECDH ]]; then
pr_ecdh_quality "$bits" "$(printf -- "%-12s" "$bits bit $what_dh") $curve" pr_ecdh_quality "$bits" "$(printf -- "%-12s" "$bits bit $what_dh") $curve"
else else
pr_dh_quality "$bits" "$(printf -- "%-12s" "$bits bit $what_dh") $curve" pr_dh_quality "$bits" "$(printf -- "%-12s" "$bits bit $what_dh") $curve"
@ -6484,7 +6486,7 @@ pr_ecdh_quality() {
elif [[ "$bits" -le 163 ]]; then elif [[ "$bits" -le 163 ]]; then
pr_svrty_medium "$string" pr_svrty_medium "$string"
elif [[ "$bits" -le 193 ]]; then # hmm, according to https://wiki.openssl.org/index.php/Elliptic_Curve_Cryptography it should ok elif [[ "$bits" -le 193 ]]; then # hmm, according to https://wiki.openssl.org/index.php/Elliptic_Curve_Cryptography it should ok
pr_svrty_low "$string" # but openssl removed it https://github.com/drwetter/testssl.sh/issues/299#issuecomment-220905416 pr_svrty_low "$string" # but openssl removed it https://github.com/testssl/testssl.sh/issues/299#issuecomment-220905416
elif [[ "$bits" -le 224 ]]; then elif [[ "$bits" -le 224 ]]; then
out "$string" out "$string"
elif [[ "$bits" -gt 224 ]]; then elif [[ "$bits" -gt 224 ]]; then
@ -6533,6 +6535,30 @@ pr_ecdh_curve_quality() {
pr_ecdh_quality "$bits" "$curve" pr_ecdh_quality "$bits" "$curve"
} }
pr_kem_quality() {
local bits="$1"
local string="$2"
# At the moment all KEMs offer at least 128 bits of security strength
# (comparable to 256-bit elliptic curve key). So, all KEMs should be
# considered good.
pr_svrty_good "$string"
}
pr_kem_param_set_quality() {
kem="$1"
local -i bits=0
case "$kem" in
"SecP256r1MLKEM768") bits=192 ;;
"X25519MLKEM768") bits=192 ;;
"SecP384r1MLKEM1024") bits=256 ;;
"X25519Kyber768Draft00") bits=128 ;;
esac
pr_kem_quality "$bits" "$kem"
}
# Return a value that is an indicator of the quality of the cipher in $1: # Return a value that is an indicator of the quality of the cipher in $1:
# 0 = $1 is empty # 0 = $1 is empty
# 1 = pr_svrty_critical, 2 = pr_svrty_high, 3 = pr_svrty_medium, 4 = pr_svrty_low # 1 = pr_svrty_critical, 2 = pr_svrty_high, 3 = pr_svrty_medium, 4 = pr_svrty_low
@ -6685,6 +6711,10 @@ read_dhtype_from_file() {
kx="Kx=${temp%%,*}" kx="Kx=${temp%%,*}"
[[ "$kx" == "Kx=X25519" ]] && kx="Kx=ECDH" [[ "$kx" == "Kx=X25519" ]] && kx="Kx=ECDH"
[[ "$kx" == "Kx=X448" ]] && kx="Kx=ECDH" [[ "$kx" == "Kx=X448" ]] && kx="Kx=ECDH"
[[ "$kx" == "Kx=SecP256r1MLKEM768" ]] && kx="Kx=ECDH/MLKEM"
[[ "$kx" == "Kx=X25519MLKEM768" ]] && kx="Kx=ECDH/MLKEM"
[[ "$kx" == "Kx=SecP384r1MLKEM1024" ]] && kx="Kx=ECDH/MLKEM"
[[ "$kx" == "Kx=X25519Kyber768Draft00" ]] && kx="Kx=ECDH/Kyber"
tm_out "$kx" tm_out "$kx"
return 0 return 0
} }
@ -8395,12 +8425,14 @@ wildcard_match()
# 8, if the server name provided is a wildcard match against the CN # 8, if the server name provided is a wildcard match against the CN
# 9, if the server name provided matches a name in the SAN AND is a wildcard match against the CN # 9, if the server name provided matches a name in the SAN AND is a wildcard match against the CN
# 10, if the server name provided is a wildcard match against the CN AND a name in the SAN # 10, if the server name provided is a wildcard match against the CN AND a name in the SAN
#
# Add 128 to the return value if the CN or a DNS name in the SAN is a wildcard.
compare_server_name_to_cert() { compare_server_name_to_cert() {
local cert="$1" local cert="$1"
local servername cns cn dns_sans ip_sans san dercert tag local servername cns cn dns_sans ip_sans san dercert tag
local srv_id="" xmppaddr="" local srv_id="" xmppaddr=""
local -i i len len1 cn_match=0 local -i i len len1 cn_match=0 wildcard_cert=0
local -i subret=0 # no error condition, passing results local -i subret=0 # no error condition, passing results
HAS_DNS_SANS=false HAS_DNS_SANS=false
@ -8545,10 +8577,16 @@ compare_server_name_to_cert() {
fi fi
# Check whether any of the DNS names in the certificate are wildcard names # Check whether any of the DNS names in the certificate are wildcard names
# that match the servername # and if they match the servername
if [[ $subret -eq 0 ]]; then if [[ $subret -eq 0 ]]; then
while read san; do while read san; do
[[ -n "$san" ]] || continue [[ -n "$san" ]] || continue
is_wildcard "$san"
if [[ $? -eq 0 ]]; then
wildcard_cert=128
else
continue
fi
wildcard_match "$servername" "$san" wildcard_match "$servername" "$san"
[[ $? -eq 0 ]] && subret=2 && break [[ $? -eq 0 ]] && subret=2 && break
done <<< "$dns_sans" done <<< "$dns_sans"
@ -8564,13 +8602,20 @@ compare_server_name_to_cert() {
# Check whether the CN matches the servername # Check whether the CN matches the servername
[[ $(toupper "$cn") == "$servername" ]] && cn_match=4 && break [[ $(toupper "$cn") == "$servername" ]] && cn_match=4 && break
# Check whether the CN is a wildcard name that matches the servername # Check whether the CN is a wildcard name and if it matches the servername
# NOTE: Don't stop loop on a wildcard match in case there is another CN # NOTE: Don't stop loop on a wildcard match in case there is another CN
# that is an exact match. # that is an exact match.
is_wildcard "$cn"
if [[ $? -eq 0 ]]; then
wildcard_cert=128
else
continue
fi
wildcard_match "$servername" "$cn" wildcard_match "$servername" "$cn"
[[ $? -eq 0 ]] && cn_match=8 [[ $? -eq 0 ]] && cn_match=8
done <<< "$cns" done <<< "$cns"
subret+=$cn_match subret+=$cn_match
subret+=$wildcard_cert
return $subret return $subret
} }
@ -9465,7 +9510,7 @@ certificate_info() {
# supported by the client. # supported by the client.
has_dns_sans=$HAS_DNS_SANS has_dns_sans=$HAS_DNS_SANS
case $trust_sni in case $((trust_sni%128)) in
0) trustfinding="certificate does not match supplied URI" 0) trustfinding="certificate does not match supplied URI"
set_grade_cap "M" "Domain name mismatch" set_grade_cap "M" "Domain name mismatch"
;; ;;
@ -9492,10 +9537,10 @@ certificate_info() {
;; ;;
esac esac
if [[ $trust_sni -eq 0 ]]; then if [[ $((trust_sni%128)) -eq 0 ]]; then
pr_svrty_high "$trustfinding" pr_svrty_high "$trustfinding"
trust_sni_finding="HIGH" trust_sni_finding="HIGH"
elif [[ $trust_sni -eq 4 ]] || [[ $trust_sni -eq 8 ]]; then elif [[ $((trust_sni%128)) -eq 4 ]] || [[ $((trust_sni%128)) -eq 8 ]]; then
if [[ $SERVICE == HTTP ]] || "$ASSUME_HTTP"; then if [[ $SERVICE == HTTP ]] || "$ASSUME_HTTP"; then
# https://bugs.chromium.org/p/chromium/issues/detail?id=308330 # https://bugs.chromium.org/p/chromium/issues/detail?id=308330
# https://bugzilla.mozilla.org/show_bug.cgi?id=1245280 # https://bugzilla.mozilla.org/show_bug.cgi?id=1245280
@ -9522,17 +9567,17 @@ certificate_info() {
# See issue #733. # See issue #733.
if [[ -z "$sni_used" ]]; then if [[ -z "$sni_used" ]]; then
trustfinding_nosni="" trustfinding_nosni=""
elif [[ $trust_sni -eq $trust_nosni && "$has_dns_sans" == "$has_dns_sans_nosni" ]] || \ elif [[ $((trust_sni%128)) -eq $((trust_nosni%128)) && "$has_dns_sans" == "$has_dns_sans_nosni" ]] || \
[[ $trust_sni -eq 0 && $trust_nosni -eq 0 ]]; then [[ $((trust_sni%128)) -eq 0 && $((trust_nosni%128)) -eq 0 ]]; then
trustfinding_nosni=" (same w/o SNI)" trustfinding_nosni=" (same w/o SNI)"
elif [[ $trust_nosni -eq 0 ]]; then elif [[ $((trust_nosni%128)) -eq 0 ]]; then
if [[ $trust_sni -eq 4 ]] || [[ $trust_sni -eq 8 ]]; then if [[ $((trust_sni%128)) -eq 4 ]] || [[ $((trust_sni%128)) -eq 8 ]]; then
trustfinding_nosni=" (w/o SNI: certificate does not match supplied URI)" trustfinding_nosni=" (w/o SNI: certificate does not match supplied URI)"
else else
trustfinding_nosni=" (SNI mandatory)" trustfinding_nosni=" (SNI mandatory)"
fi fi
elif [[ $trust_nosni -eq 4 ]] || [[ $trust_nosni -eq 8 ]] || [[ $trust_sni -eq 4 ]] || [[ $trust_sni -eq 8 ]]; then elif [[ $((trust_nosni%128)) -eq 4 ]] || [[ $((trust_nosni%128)) -eq 8 ]] || [[ $((trust_sni%128)) -eq 4 ]] || [[ $((trust_sni%128)) -eq 8 ]]; then
case $trust_nosni in case $((trust_nosni%128)) in
1) trustfinding_nosni=" (w/o SNI: Ok via SAN)" ;; 1) trustfinding_nosni=" (w/o SNI: Ok via SAN)" ;;
2) trustfinding_nosni=" (w/o SNI: Ok via SAN wildcard)" ;; 2) trustfinding_nosni=" (w/o SNI: Ok via SAN wildcard)" ;;
4) if "$has_dns_sans_nosni"; then 4) if "$has_dns_sans_nosni"; then
@ -9552,12 +9597,12 @@ certificate_info() {
9) trustfinding_nosni=" (w/o SNI: Ok via CN wildcard and SAN)" ;; 9) trustfinding_nosni=" (w/o SNI: Ok via CN wildcard and SAN)" ;;
10) trustfinding_nosni=" (w/o SNI: Ok via SAN wildcard and CN wildcard)" ;; 10) trustfinding_nosni=" (w/o SNI: Ok via SAN wildcard and CN wildcard)" ;;
esac esac
elif [[ $trust_sni -ne 0 ]]; then elif [[ $((trust_sni%128)) -ne 0 ]]; then
trustfinding_nosni=" (works w/o SNI)" trustfinding_nosni=" (works w/o SNI)"
else else
trustfinding_nosni=" (however, works w/o SNI)" trustfinding_nosni=" (however, works w/o SNI)"
fi fi
if [[ -n "$sni_used" ]] || [[ $trust_nosni -eq 0 ]] || [[ $trust_nosni -ne 4 && $trust_nosni -ne 8 ]]; then if [[ -n "$sni_used" ]] || [[ $((trust_nosni%128)) -eq 0 ]] || [[ $((trust_nosni%128)) -ne 4 && $((trust_nosni%128)) -ne 8 ]]; then
outln "$trustfinding_nosni" outln "$trustfinding_nosni"
elif [[ $SERVICE == HTTP ]] || "$ASSUME_HTTP"; then elif [[ $SERVICE == HTTP ]] || "$ASSUME_HTTP"; then
prln_svrty_high "$trustfinding_nosni" prln_svrty_high "$trustfinding_nosni"
@ -9567,7 +9612,7 @@ certificate_info() {
fileout "cert_trust${json_postfix}" "$trust_sni_finding" "${trustfinding}${trustfinding_nosni}" fileout "cert_trust${json_postfix}" "$trust_sni_finding" "${trustfinding}${trustfinding_nosni}"
if [[ "$trust_sni" =~ ^(2|6|8|9|10)$ ]] || [[ "$trust_nosni" =~ ^(2|6|8|9|10)$ ]]; then if [[ $((trust_sni&128)) -eq 128 ]] || [[ $((trust_nosni&128)) -eq 128 ]]; then
out "${spaces}" out "${spaces}"
pr_svrty_low "wildcard certificate" ; outln " could be problematic, see other hosts at" pr_svrty_low "wildcard certificate" ; outln " could be problematic, see other hosts at"
outln "${spaces}https://search.censys.io/search?resource=hosts&virtual_hosts=INCLUDE&q=$cert_fingerprint_sha2" outln "${spaces}https://search.censys.io/search?resource=hosts&virtual_hosts=INCLUDE&q=$cert_fingerprint_sha2"
@ -10173,7 +10218,7 @@ run_server_defaults() {
# $NODE being tested or if it has the same subject # $NODE being tested or if it has the same subject
# (CN and SAN) as other certificates for this host. # (CN and SAN) as other certificates for this host.
compare_server_name_to_cert "$HOSTCERT" compare_server_name_to_cert "$HOSTCERT"
[[ $? -ne 0 ]] && success[n]=0 || success[n]=1 [[ $(($?%128)) -ne 0 ]] && success[n]=0 || success[n]=1
if [[ ${success[n]} -ne 0 ]]; then if [[ ${success[n]} -ne 0 ]]; then
cn_nosni="$(toupper "$(get_cn_from_cert $HOSTCERT)")" cn_nosni="$(toupper "$(get_cn_from_cert $HOSTCERT)")"
@ -10506,13 +10551,13 @@ run_fs() {
local fs_cipher_list="DHE-DSS-AES128-GCM-SHA256:DHE-DSS-AES128-SHA256:DHE-DSS-AES128-SHA:DHE-DSS-AES256-GCM-SHA384:DHE-DSS-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-DSS-CAMELLIA128-SHA256:DHE-DSS-CAMELLIA128-SHA:DHE-DSS-CAMELLIA256-SHA256:DHE-DSS-CAMELLIA256-SHA:DHE-DSS-SEED-SHA:DHE-RSA-AES128-CCM8:DHE-RSA-AES128-CCM:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-CCM8:DHE-RSA-AES256-CCM:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-CAMELLIA128-SHA256:DHE-RSA-CAMELLIA128-SHA:DHE-RSA-CAMELLIA256-SHA256:DHE-RSA-CAMELLIA256-SHA:DHE-RSA-CHACHA20-POLY1305-OLD:DHE-RSA-CHACHA20-POLY1305:DHE-RSA-SEED-SHA:ECDHE-ECDSA-AES128-CCM8:ECDHE-ECDSA-AES128-CCM:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES256-CCM8:ECDHE-ECDSA-AES256-CCM:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-CAMELLIA128-SHA256:ECDHE-ECDSA-CAMELLIA256-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305-OLD:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-RSA-CAMELLIA128-SHA256:ECDHE-RSA-CAMELLIA256-SHA384:ECDHE-RSA-CHACHA20-POLY1305-OLD:ECDHE-RSA-CHACHA20-POLY1305" local fs_cipher_list="DHE-DSS-AES128-GCM-SHA256:DHE-DSS-AES128-SHA256:DHE-DSS-AES128-SHA:DHE-DSS-AES256-GCM-SHA384:DHE-DSS-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-DSS-CAMELLIA128-SHA256:DHE-DSS-CAMELLIA128-SHA:DHE-DSS-CAMELLIA256-SHA256:DHE-DSS-CAMELLIA256-SHA:DHE-DSS-SEED-SHA:DHE-RSA-AES128-CCM8:DHE-RSA-AES128-CCM:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-CCM8:DHE-RSA-AES256-CCM:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-CAMELLIA128-SHA256:DHE-RSA-CAMELLIA128-SHA:DHE-RSA-CAMELLIA256-SHA256:DHE-RSA-CAMELLIA256-SHA:DHE-RSA-CHACHA20-POLY1305-OLD:DHE-RSA-CHACHA20-POLY1305:DHE-RSA-SEED-SHA:ECDHE-ECDSA-AES128-CCM8:ECDHE-ECDSA-AES128-CCM:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES256-CCM8:ECDHE-ECDSA-AES256-CCM:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-CAMELLIA128-SHA256:ECDHE-ECDSA-CAMELLIA256-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305-OLD:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-RSA-CAMELLIA128-SHA256:ECDHE-RSA-CAMELLIA256-SHA384:ECDHE-RSA-CHACHA20-POLY1305-OLD:ECDHE-RSA-CHACHA20-POLY1305"
local fs_hex_cipher_list="" ciphers_to_test tls13_ciphers_to_test local fs_hex_cipher_list="" ciphers_to_test tls13_ciphers_to_test
local ecdhe_cipher_list="" tls13_cipher_list="" ecdhe_cipher_list_hex="" ffdhe_cipher_list_hex="" local ecdhe_cipher_list="" tls13_cipher_list="" ecdhe_cipher_list_hex="" ffdhe_cipher_list_hex=""
local curves_hex=("00,01" "00,02" "00,03" "00,04" "00,05" "00,06" "00,07" "00,08" "00,09" "00,0a" "00,0b" "00,0c" "00,0d" "00,0e" "00,0f" "00,10" "00,11" "00,12" "00,13" "00,14" "00,15" "00,16" "00,17" "00,18" "00,19" "00,1a" "00,1b" "00,1c" "00,1d" "00,1e" "00,1f" "00,20" "00,21") local curves_hex=("00,01" "00,02" "00,03" "00,04" "00,05" "00,06" "00,07" "00,08" "00,09" "00,0a" "00,0b" "00,0c" "00,0d" "00,0e" "00,0f" "00,10" "00,11" "00,12" "00,13" "00,14" "00,15" "00,16" "00,17" "00,18" "00,19" "00,1a" "00,1b" "00,1c" "00,1d" "00,1e" "00,1f" "00,20" "00,21" "11,eb" "11,ec" "11,ed" "63,99")
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") 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" "SecP256r1MLKEM768" "X25519MLKEM768" "SecP384r1MLKEM1024" "X25519Kyber768Draft00")
local -a curves_ossl_output=("K-163" "sect163r1" "B-163" "sect193r1" "sect193r2" "K-233" "B-233" "sect239k1" "K-283" "B-283" "K-409" "B-409" "K-571" "B-571" "secp160k1" "secp160r1" "secp160r2" "secp192k1" "P-192" "secp224k1" "P-224" "secp256k1" "P-256" "P-384" "P-521" "brainpoolP256r1" "brainpoolP384r1" "brainpoolP512r1" "X25519" "X448" "brainpoolP256r1tls13" "brainpoolP384r1tls13" "brainpoolP512r1tls13") local -a curves_ossl_output=("K-163" "sect163r1" "B-163" "sect193r1" "sect193r2" "K-233" "B-233" "sect239k1" "K-283" "B-283" "K-409" "B-409" "K-571" "B-571" "secp160k1" "secp160r1" "secp160r2" "secp192k1" "P-192" "secp224k1" "P-224" "secp256k1" "P-256" "P-384" "P-521" "brainpoolP256r1" "brainpoolP384r1" "brainpoolP512r1" "X25519" "X448" "brainpoolP256r1tls13" "brainpoolP384r1tls13" "brainpoolP512r1tls13" "SecP256r1MLKEM768" "X25519MLKEM768" "SecP384r1MLKEM1024" "X25519Kyber768Draft00")
local -ai curves_bits=(163 162 163 193 193 232 233 238 281 282 407 409 570 570 161 161 161 192 192 225 224 256 256 384 521 256 384 512 253 448 256 384 512) local -ai curves_bits=(163 162 163 193 193 232 233 238 281 282 407 409 570 570 161 161 161 192 192 225 224 256 256 384 521 256 384 512 253 448 256 384 512 192 192 256 128)
# Many curves have been deprecated, and RFC 8446, Appendix B.3.1.4, states # Many curves have been deprecated, and RFC 8446, Appendix B.3.1.4, states
# that these curves MUST NOT be offered in a TLS 1.3 ClientHello. # that these curves MUST NOT be offered in a TLS 1.3 ClientHello.
local -a curves_deprecated=("true" "true" "true" "true" "true" "true" "true" "true" "true" "true" "true" "true" "true" "true" "true" "true" "true" "true" "true" "true" "true" "true" "false" "false" "false" "true" "true" "true" "false" "false" "false" "false" "false") local -a curves_deprecated=("true" "true" "true" "true" "true" "true" "true" "true" "true" "true" "true" "true" "true" "true" "true" "true" "true" "true" "true" "true" "true" "true" "false" "false" "false" "true" "true" "true" "false" "false" "false" "false" "false" "false" "false" "false" "false")
local -a ffdhe_groups_hex=("01,00" "01,01" "01,02" "01,03" "01,04") local -a ffdhe_groups_hex=("01,00" "01,01" "01,02" "01,03" "01,04")
local -a ffdhe_groups_output=("ffdhe2048" "ffdhe3072" "ffdhe4096" "ffdhe6144" "ffdhe8192") local -a ffdhe_groups_output=("ffdhe2048" "ffdhe3072" "ffdhe4096" "ffdhe6144" "ffdhe8192")
local -a supported_curve local -a supported_curve
@ -10523,7 +10568,7 @@ run_fs() {
local rsa_cipher="" ecdsa_cipher="" dss_cipher="" local rsa_cipher="" ecdsa_cipher="" dss_cipher=""
local sigalgs_to_test tls12_supported_sigalg_list="" tls13_supported_sigalg_list="" local sigalgs_to_test tls12_supported_sigalg_list="" tls13_supported_sigalg_list=""
local -i nr_supported_ciphers=0 nr_curves=0 nr_ossl_curves=0 i j low high local -i nr_supported_ciphers=0 nr_curves=0 nr_ossl_curves=0 i j low high
local fs_ciphers curves_offered="" curves_to_test temp local fs_ciphers curves_offered="" kems_offered="" curves_to_test temp
local curves_option="" curves_list1="" curves_list2="" local curves_option="" curves_list1="" curves_list2=""
local len1 len2 curve_found sigalg_found local len1 len2 curve_found sigalg_found
local key_bitstring quality_str local key_bitstring quality_str
@ -10713,7 +10758,7 @@ run_fs() {
else else
! "$fs_tls12_offered" && [[ "$(get_protocol "$TMPFILE")" == TLSv1.2 ]] && fs_tls12_offered=true ! "$fs_tls12_offered" && [[ "$(get_protocol "$TMPFILE")" == TLSv1.2 ]] && fs_tls12_offered=true
fi fi
if "$WIDE"; then if "$WIDE" && [[ ${kx[i]} == Kx=ECDH || ${kx[i]} == Kx=DH || ${kx[i]} == Kx=EDH ]]; then
dhlen=$(read_dhbits_from_file "$TMPFILE" quiet) dhlen=$(read_dhbits_from_file "$TMPFILE" quiet)
kx[i]="${kx[i]} $dhlen" kx[i]="${kx[i]} $dhlen"
fi fi
@ -10749,7 +10794,7 @@ run_fs() {
fs_tls13_offered=true fs_tls13_offered=true
"$WIDE" && kx[i]="$(read_dhtype_from_file "$TEMPDIR/$NODEIP.parse_tls_serverhello.txt")" "$WIDE" && kx[i]="$(read_dhtype_from_file "$TEMPDIR/$NODEIP.parse_tls_serverhello.txt")"
fi fi
if "$WIDE"; then if "$WIDE" && [[ ${kx[i]} == Kx=ECDH || ${kx[i]} == Kx=DH || ${kx[i]} == Kx=EDH ]]; then
dhlen=$(read_dhbits_from_file "$TEMPDIR/$NODEIP.parse_tls_serverhello.txt" quiet) dhlen=$(read_dhbits_from_file "$TEMPDIR/$NODEIP.parse_tls_serverhello.txt" quiet)
kx[i]="${kx[i]} $dhlen" kx[i]="${kx[i]} $dhlen"
fi fi
@ -10813,7 +10858,7 @@ run_fs() {
fi fi
fi fi
debugme echo $fs_offered debugme echo $fs_offered
"$WIDE" || outln outln
fileout "${jsonID}_ciphers" "INFO" "$fs_ciphers" fileout "${jsonID}_ciphers" "INFO" "$fs_ciphers"
fi fi
@ -10924,12 +10969,21 @@ run_fs() {
low=1000 low=1000
for (( i=0; i < nr_curves; i++ )); do for (( i=0; i < nr_curves; i++ )); do
if "${supported_curve[i]}"; then if "${supported_curve[i]}"; then
curves_offered+="${curves_ossl[i]} " if [[ "${curves_ossl[i]}" =~ KEM ]] || [[ "${curves_ossl[i]}" =~ Kyber ]]; then
[[ ${curves_bits[i]} -lt $low ]] && low=${curves_bits[i]} kems_offered+="${curves_ossl[i]} "
else
curves_offered+="${curves_ossl[i]} "
[[ ${curves_bits[i]} -lt $low ]] && low=${curves_bits[i]}
fi
fi fi
done done
if [[ -n "$kems_offered" ]]; then
pr_bold " KEMs offered "
out_row_aligned_max_width_by_entry "$kems_offered" " " $TERM_WIDTH pr_kem_param_set_quality
outln
fileout "${jsonID}_KEMs" "OK" "$kems_offered"
fi
if [[ -n "$curves_offered" ]]; then if [[ -n "$curves_offered" ]]; then
"$WIDE" && outln
pr_bold " Elliptic curves offered: " pr_bold " Elliptic curves offered: "
out_row_aligned_max_width_by_entry "$curves_offered" " " $TERM_WIDTH pr_ecdh_curve_quality out_row_aligned_max_width_by_entry "$curves_offered" " " $TERM_WIDTH pr_ecdh_curve_quality
outln outln
@ -11088,25 +11142,27 @@ run_fs() {
# A few servers get confused if the signature_algorithms extension contains too many entries. So: # A few servers get confused if the signature_algorithms extension contains too many entries. So:
# * For TLS 1.3, break the list into two and test each half separately. # * For TLS 1.3, break the list into two and test each half separately.
# * For TLS 1.2, generally limit the signature_algorithms extension to algorithms that are consistent with the key type. # * For TLS 1.2, generally limit the signature_algorithms extension to algorithms that are consistent with the key type.
# At least one server gets confused if RSA+MD5 is offered first. So, the ordering is reversed so that the strongest
# options appear in $sigalgs_to_test first.
for hexc in "${sigalgs_hex[@]}"; do for hexc in "${sigalgs_hex[@]}"; do
if [[ "$proto" == 04* ]]; then if [[ "$proto" == 04* ]]; then
if ! "${tls13_supported_sigalgs[i]}"; then if ! "${tls13_supported_sigalgs[i]}"; then
if [[ "${proto##*-}" == 01 ]]; then if [[ "${proto##*-}" == 01 ]]; then
[[ $i -le 16 ]] && sigalgs_to_test+=", $hexc" [[ $i -le 16 ]] && sigalgs_to_test=", $hexc$sigalgs_to_test"
else else
[[ $i -gt 16 ]] && sigalgs_to_test+=", $hexc" [[ $i -gt 16 ]] && sigalgs_to_test=", $hexc$sigalgs_to_test"
fi fi
fi fi
elif ! "${tls12_supported_sigalgs[i]}"; then elif ! "${tls12_supported_sigalgs[i]}"; then
if [[ "$proto" =~ rsa ]]; then if [[ "$proto" =~ rsa ]]; then
if [[ "${hexc:3:2}" == 01 ]] || [[ "${hexc:0:2}" == 08 ]]; then if [[ "${hexc:3:2}" == 01 ]] || [[ "${hexc:0:2}" == 08 ]]; then
sigalgs_to_test+=", $hexc" sigalgs_to_test=", $hexc$sigalgs_to_test"
fi fi
elif [[ "$proto" =~ dss ]]; then elif [[ "$proto" =~ dss ]]; then
[[ "${hexc:3:2}" == 02 ]] && sigalgs_to_test+=", $hexc" [[ "${hexc:3:2}" == 02 ]] && sigalgs_to_test=", $hexc$sigalgs_to_test"
else else
if [[ "${hexc:3:2}" == 03 ]] || [[ "${hexc:0:2}" == 08 ]]; then if [[ "${hexc:3:2}" == 03 ]] || [[ "${hexc:0:2}" == 08 ]]; then
sigalgs_to_test+=", $hexc" sigalgs_to_test=", $hexc$sigalgs_to_test"
fi fi
fi fi
fi fi
@ -14505,6 +14561,10 @@ parse_tls_serverhello() {
"0102") echo -n "ffdhe4096" >> $TMPFILE ;; "0102") echo -n "ffdhe4096" >> $TMPFILE ;;
"0103") echo -n "ffdhe6144" >> $TMPFILE ;; "0103") echo -n "ffdhe6144" >> $TMPFILE ;;
"0104") echo -n "ffdhe8192" >> $TMPFILE ;; "0104") echo -n "ffdhe8192" >> $TMPFILE ;;
"11EB") echo -n "SecP256r1MLKEM768" >> $TMPFILE ;;
"11EC") echo -n "X25519MLKEM768" >> $TMPFILE ;;
"11ED") echo -n "SecP384r1MLKEM1024" >> $TMPFILE ;;
"6399") echo -n "X25519Kyber768Draft00" >> $TMPFILE ;;
*) echo -n "unknown (${tls_serverhello_ascii:offset:4})" >> $TMPFILE ;; *) echo -n "unknown (${tls_serverhello_ascii:offset:4})" >> $TMPFILE ;;
esac esac
offset=$((offset+4)) offset=$((offset+4))
@ -14600,6 +14660,10 @@ parse_tls_serverhello() {
258) dh_bits=4096 ; named_curve_str="ffdhe4096" ;; 258) dh_bits=4096 ; named_curve_str="ffdhe4096" ;;
259) dh_bits=6144 ; named_curve_str="ffdhe6144" ;; 259) dh_bits=6144 ; named_curve_str="ffdhe6144" ;;
260) dh_bits=8192 ; named_curve_str="ffdhe8192" ;; 260) dh_bits=8192 ; named_curve_str="ffdhe8192" ;;
4587) dh_bits=192 ; named_curve_str="SecP256r1MLKEM768" ;;
4588) dh_bits=192 ; named_curve_str="X25519MLKEM768" ;;
4589) dh_bits=256 ; named_curve_str="SecP384r1MLKEM1024" ;;
25497) dh_bits=128 ; named_curve_str="X25519Kyber768Draft00" ;;
*) named_curve_str="" ; named_curve_oid="" ;; *) named_curve_str="" ; named_curve_oid="" ;;
esac esac
offset=$((extns_offset+20+i)) offset=$((extns_offset+20+i))
@ -14787,9 +14851,9 @@ parse_tls_serverhello() {
fi fi
echo "Cipher : $rfc_cipher_suite" >> $TMPFILE echo "Cipher : $rfc_cipher_suite" >> $TMPFILE
if [[ $dh_bits -ne 0 ]]; then if [[ $dh_bits -ne 0 ]]; then
if [[ "$named_curve_str" =~ "ffdhe" ]]; then if [[ "$named_curve_str" =~ ffdhe ]]; then
echo "Server Temp Key: DH, $named_curve_str, $dh_bits bits" >> $TMPFILE echo "Server Temp Key: DH, $named_curve_str, $dh_bits bits" >> $TMPFILE
elif [[ "$named_curve_str" == "X25519" ]] || [[ "$named_curve_str" == "X448" ]]; then elif [[ "$named_curve_str" == X25519 ]] || [[ "$named_curve_str" == X448 ]] || [[ "$named_curve_str" =~ KEM ]] || [[ "$named_curve_str" =~ Kyber ]]; then
echo "Server Temp Key: $named_curve_str, $dh_bits bits" >> $TMPFILE echo "Server Temp Key: $named_curve_str, $dh_bits bits" >> $TMPFILE
else else
echo "Server Temp Key: ECDH, $named_curve_str, $dh_bits bits" >> $TMPFILE echo "Server Temp Key: ECDH, $named_curve_str, $dh_bits bits" >> $TMPFILE
@ -14832,9 +14896,9 @@ parse_tls_serverhello() {
echo "" echo ""
fi fi
if [[ $dh_bits -ne 0 ]]; then if [[ $dh_bits -ne 0 ]]; then
if [[ "$named_curve_str" =~ "ffdhe" ]]; then if [[ "$named_curve_str" =~ ffdhe ]]; then
echo " dh_bits: DH, $named_curve_str, $dh_bits bits" echo " dh_bits: DH, $named_curve_str, $dh_bits bits"
elif [[ "$named_curve_str" == "X25519" ]] || [[ "$named_curve_str" == "X448" ]]; then elif [[ "$named_curve_str" == X25519 ]] || [[ "$named_curve_str" == X448 ]] || [[ "$named_curve_str" =~ KEM ]] || [[ "$named_curve_str" =~ Kyber ]]; then
echo " dh_bits: $named_curve_str, $dh_bits bits" echo " dh_bits: $named_curve_str, $dh_bits bits"
else else
echo " dh_bits: ECDH, $named_curve_str, $dh_bits bits" echo " dh_bits: ECDH, $named_curve_str, $dh_bits bits"
@ -14870,7 +14934,7 @@ parse_tls_serverhello() {
fi fi
# If a CIPHER_SUITES string was provided, then check that $tls_cipher_suite is in the string. # If a CIPHER_SUITES string was provided, then check that $tls_cipher_suite is in the string.
# this appeared in yassl + MySQL (https://github.com/drwetter/testssl.sh/pull/784) but adds robustness # this appeared in yassl + MySQL (https://github.com/testssl/testssl.sh/pull/784) but adds robustness
# to the implementation # to the implementation
if [[ -n "$cipherlist" ]]; then if [[ -n "$cipherlist" ]]; then
tls_cipher_suite="$(tolower "$tls_cipher_suite")" tls_cipher_suite="$(tolower "$tls_cipher_suite")"
@ -15623,7 +15687,15 @@ prepare_tls_clienthello() {
00, 01, 00, 02, 00, 03, 00, 0f, 00, 10, 00, 11, 01, 00, 01, 01" 00, 01, 00, 02, 00, 03, 00, 0f, 00, 10, 00, 11, 01, 00, 01, 01"
elif [[ 0x$tls_low_byte -gt 0x03 ]]; then elif [[ 0x$tls_low_byte -gt 0x03 ]]; then
# Supported Groups Extension # Supported Groups Extension
if [[ ! "$process_full" =~ all ]] || { "$HAS_X25519" && "$HAS_X448"; }; then if [[ ! "$process_full" =~ all ]]; then
extension_supported_groups="
00,0a, # Type: Supported Groups, see RFC 8446
00,1e, 00,1c, # lengths
00,1d, 00,17, 00,1e, 00,18, 00,19, 00,1f, 00,20, 00,21,
01,00, 01,01, 11,eb, 11,ec, 11,ed, 63,99"
# Only include ML-KEM and Kyber hybrids as options if the response does
# not need to be decrypted.
elif [[ ! "$process_full" =~ all ]] || { "$HAS_X25519" && "$HAS_X448"; }; then
extension_supported_groups=" extension_supported_groups="
00,0a, # Type: Supported Groups, see RFC 8446 00,0a, # Type: Supported Groups, see RFC 8446
00,16, 00,14, # lengths 00,16, 00,14, # lengths
@ -15645,7 +15717,7 @@ prepare_tls_clienthello() {
00,1d, 00,17, 00,18, 00,19, 00,1f, 00,20, 00,21, 00,1d, 00,17, 00,18, 00,19, 00,1f, 00,20, 00,21,
01,00, 01,01, 00,1e" 01,00, 01,01, 00,1e"
# OpenSSL prior to 1.1.0 does not support either X25519 or X448, # OpenSSL prior to 1.1.0 does not support either X25519 or X448,
# so list them as the least referred options if the response # so list them as the least preferred options if the response
# needs to be decrypted, and do not list them at all if the # needs to be decrypted, and do not list them at all if the
# response MUST be decrypted. # response MUST be decrypted.
elif [[ "$process_full" == all+ ]]; then elif [[ "$process_full" == all+ ]]; then
@ -15735,7 +15807,7 @@ prepare_tls_clienthello() {
# There does not seem to be any reason to include this extension. However, it appears that # There does not seem to be any reason to include this extension. However, it appears that
# OpenSSL, Firefox, and Chrome include it in TLS 1.3 ClientHello messages, and there is at # OpenSSL, Firefox, and Chrome include it in TLS 1.3 ClientHello messages, and there is at
# least one server that will fail the connection if it is absent # least one server that will fail the connection if it is absent
# (see https://github.com/drwetter/testssl.sh/issues/990). # (see https://github.com/testssl/testssl.sh/issues/990).
if [[ "0x$tls_low_byte" -ge 0x04 ]] && [[ ! "$extra_extensions_list" =~ \ 002d\ ]]; then if [[ "0x$tls_low_byte" -ge 0x04 ]] && [[ ! "$extra_extensions_list" =~ \ 002d\ ]]; then
[[ -n "$all_extensions" ]] && all_extensions+="," [[ -n "$all_extensions" ]] && all_extensions+=","
all_extensions+="$extn_psk_mode" all_extensions+="$extn_psk_mode"
@ -17208,7 +17280,7 @@ run_renego() {
# 1 means client tried to renegotiating but the server side errored then. You still see RENEGOTIATING in the output # 1 means client tried to renegotiating but the server side errored then. You still see RENEGOTIATING in the output
if tail -5 $TMPFILE| grep -qa '^closed'; then if tail -5 $TMPFILE| grep -qa '^closed'; then
# Exemption from above: server closed the connection but return value was zero # Exemption from above: server closed the connection but return value was zero
# See https://github.com/drwetter/testssl.sh/issues/1725 and referenced issue @haproxy # See https://github.com/testssl/testssl.sh/issues/1725 and referenced issue @haproxy
sec_client_renego=1 sec_client_renego=1
fi fi
case "$sec_client_renego" in case "$sec_client_renego" in
@ -18017,7 +18089,7 @@ run_tls_fallback_scsv() {
elif grep -qa "alert handshake failure" "$TMPFILE"; then elif grep -qa "alert handshake failure" "$TMPFILE"; then
pr_svrty_good "Probably OK. " pr_svrty_good "Probably OK. "
fileout "$jsonID" "OK" "Probably oK" fileout "$jsonID" "OK" "Probably oK"
# see RFC 7507, https://github.com/drwetter/testssl.sh/issues/121 # see RFC 7507, https://github.com/testssl/testssl.sh/issues/121
# other case reported by Nicolas was F5 and at customer of mine: the same # other case reported by Nicolas was F5 and at customer of mine: the same
pr_svrty_medium "But received non-RFC-compliant \"handshake failure\" instead of \"inappropriate fallback\"" pr_svrty_medium "But received non-RFC-compliant \"handshake failure\" instead of \"inappropriate fallback\""
fileout "$jsonID" "MEDIUM" "received non-RFC-compliant \"handshake failure\" instead of \"inappropriate fallback\"" fileout "$jsonID" "MEDIUM" "received non-RFC-compliant \"handshake failure\" instead of \"inappropriate fallback\""
@ -20346,8 +20418,8 @@ find_openssl_binary() {
$OPENSSL s_client -tls1_3 </dev/null 2>&1 | grep -aiq "unknown option" || HAS_TLS13=true $OPENSSL s_client -tls1_3 </dev/null 2>&1 | grep -aiq "unknown option" || HAS_TLS13=true
$OPENSSL s_client -no_ssl2 </dev/null 2>&1 | grep -aiq "unknown option" || HAS_NO_SSL2=true $OPENSSL s_client -no_ssl2 </dev/null 2>&1 | grep -aiq "unknown option" || HAS_NO_SSL2=true
$OPENSSL genpkey -algorithm X448 2>&1 | grep -aq "not found" || HAS_X448=true $OPENSSL genpkey -algorithm X448 2>&1 | grep -Eaq "not found|unsupported" || HAS_X448=true
$OPENSSL genpkey -algorithm X25519 2>&1 | grep -aq "not found" || HAS_X25519=true $OPENSSL genpkey -algorithm X25519 2>&1 | grep -Eaq "not found|unsupported" || HAS_X25519=true
$OPENSSL pkey -help 2>&1 | grep -q Error || HAS_PKEY=true $OPENSSL pkey -help 2>&1 | grep -q Error || HAS_PKEY=true
$OPENSSL pkeyutl 2>&1 | grep -q Error || HAS_PKUTIL=true $OPENSSL pkeyutl 2>&1 | grep -q Error || HAS_PKUTIL=true
@ -21294,7 +21366,7 @@ get_local_a() {
check_resolver_bins() { check_resolver_bins() {
local saved_openssl_conf="$OPENSSL_CONF" local saved_openssl_conf="$OPENSSL_CONF"
OPENSSL_CONF="" # see https://github.com/drwetter/testssl.sh/issues/134 OPENSSL_CONF="" # see https://github.com/testssl/testssl.sh/issues/134
type -p dig &> /dev/null && HAS_DIG=true type -p dig &> /dev/null && HAS_DIG=true
type -p host &> /dev/null && HAS_HOST=true type -p host &> /dev/null && HAS_HOST=true
type -p drill &> /dev/null && HAS_DRILL=true type -p drill &> /dev/null && HAS_DRILL=true
@ -21316,7 +21388,7 @@ check_resolver_bins() {
HAS_DIG_NOIDNOUT=true HAS_DIG_NOIDNOUT=true
fi fi
fi fi
OPENSSL_CONF="$saved_openssl_conf" # see https://github.com/drwetter/testssl.sh/issues/134 OPENSSL_CONF="$saved_openssl_conf" # see https://github.com/testssl/testssl.sh/issues/134
return 0 return 0
} }
@ -21339,7 +21411,7 @@ get_a_record() {
echo $1 echo $1
return 0 return 0
fi fi
OPENSSL_CONF="" # see https://github.com/drwetter/testssl.sh/issues/134 OPENSSL_CONF="" # see https://github.com/testssl/testssl.sh/issues/134
if [[ "$NODE" == *.local ]]; then if [[ "$NODE" == *.local ]]; then
if "$HAS_AVAHIRESOLVE"; then if "$HAS_AVAHIRESOLVE"; then
ip4=$(filter_ip4_address $(avahi-resolve -4 -n "$1" 2>/dev/null | awk '{ print $2 }')) ip4=$(filter_ip4_address $(avahi-resolve -4 -n "$1" 2>/dev/null | awk '{ print $2 }'))
@ -21364,7 +21436,7 @@ get_a_record() {
if [[ -z "$ip4" ]] && "$HAS_NSLOOKUP"; then if [[ -z "$ip4" ]] && "$HAS_NSLOOKUP"; then
ip4=$(filter_ip4_address $(strip_lf "$(nslookup -querytype=a "$1" 2>/dev/null | awk '/^Name/ { getline; print $NF }')")) ip4=$(filter_ip4_address $(strip_lf "$(nslookup -querytype=a "$1" 2>/dev/null | awk '/^Name/ { getline; print $NF }')"))
fi fi
OPENSSL_CONF="$saved_openssl_conf" # see https://github.com/drwetter/testssl.sh/issues/134 OPENSSL_CONF="$saved_openssl_conf" # see https://github.com/testssl/testssl.sh/issues/134
echo "$ip4" echo "$ip4"
} }
@ -21377,7 +21449,7 @@ get_aaaa_record() {
"$HAS_DIG_NOIDNOUT" && noidnout="+noidnout" "$HAS_DIG_NOIDNOUT" && noidnout="+noidnout"
[[ "$NODNS" == none ]] && return 0 # if no DNS lookup was instructed, leave here [[ "$NODNS" == none ]] && return 0 # if no DNS lookup was instructed, leave here
OPENSSL_CONF="" # see https://github.com/drwetter/testssl.sh/issues/134 OPENSSL_CONF="" # see https://github.com/testssl/testssl.sh/issues/134
if is_ipv6addr "$1"; then if is_ipv6addr "$1"; then
# This saves walking through this. Also it avoids hangs e.g. if you run docker locally without reachable DNS # This saves walking through this. Also it avoids hangs e.g. if you run docker locally without reachable DNS
echo "$1" echo "$1"
@ -21411,7 +21483,7 @@ get_aaaa_record() {
ip6=$(filter_ip6_address $(strip_lf "$(nslookup -type=aaaa "$1" 2>/dev/null | awk '/'"^${a}"'.*AAAA/ { print $NF }')")) ip6=$(filter_ip6_address $(strip_lf "$(nslookup -type=aaaa "$1" 2>/dev/null | awk '/'"^${a}"'.*AAAA/ { print $NF }')"))
fi fi
fi fi
OPENSSL_CONF="$saved_openssl_conf" # see https://github.com/drwetter/testssl.sh/issues/134 OPENSSL_CONF="$saved_openssl_conf" # see https://github.com/testssl/testssl.sh/issues/134
echo "$ip6" echo "$ip6"
} }
@ -21457,7 +21529,7 @@ get_caa_rr_record() {
return 1 return 1
# No dig, drill, host, or nslookup --> complaint was elsewhere already # No dig, drill, host, or nslookup --> complaint was elsewhere already
fi fi
OPENSSL_CONF="$saved_openssl_conf" # see https://github.com/drwetter/testssl.sh/issues/134 OPENSSL_CONF="$saved_openssl_conf" # see https://github.com/testssl/testssl.sh/issues/134
debugme echo $raw_caa debugme echo $raw_caa
if [[ "$raw_caa" =~ \#\ [0-9][0-9] ]]; then if [[ "$raw_caa" =~ \#\ [0-9][0-9] ]]; then
@ -21505,7 +21577,7 @@ get_mx_record() {
local noidnout="" local noidnout=""
"$HAS_DIG_NOIDNOUT" && noidnout="+noidnout" "$HAS_DIG_NOIDNOUT" && noidnout="+noidnout"
OPENSSL_CONF="" # see https://github.com/drwetter/testssl.sh/issues/134 OPENSSL_CONF="" # see https://github.com/testssl/testssl.sh/issues/134
# we need the last two columns here # we need the last two columns here
if "$HAS_HOST"; then if "$HAS_HOST"; then
mx="$(host -t MX "$1" 2>/dev/null | awk '/is handled by/ { print $(NF-1), $NF }')" mx="$(host -t MX "$1" 2>/dev/null | awk '/is handled by/ { print $(NF-1), $NF }')"
@ -21532,7 +21604,7 @@ get_txt_record() {
local noidnout="" local noidnout=""
"$HAS_DIG_NOIDNOUT" && noidnout="+noidnout" "$HAS_DIG_NOIDNOUT" && noidnout="+noidnout"
OPENSSL_CONF="" # see https://github.com/drwetter/testssl.sh/issues/134 OPENSSL_CONF="" # see https://github.com/testssl/testssl.sh/issues/134
# we need the last two columns here and strip any remaining double quotes later # we need the last two columns here and strip any remaining double quotes later
if "$HAS_HOST"; then if "$HAS_HOST"; then
record="$(host -t TXT "$1" 2>/dev/null | awk -F\" '/descriptive text/ { print $(NF-1) }')" record="$(host -t TXT "$1" 2>/dev/null | awk -F\" '/descriptive text/ { print $(NF-1) }')"
@ -21633,7 +21705,7 @@ determine_rdns() {
[[ "$NODNS" == none ]] && rDNS="(instructed to skip DNS queries)" && return 0 # No DNS lookups at all [[ "$NODNS" == none ]] && rDNS="(instructed to skip DNS queries)" && return 0 # No DNS lookups at all
[[ "$NODNS" == min ]] && rDNS="(instructed to minimize DNS queries)" && return 0 # PTR records were not asked for [[ "$NODNS" == min ]] && rDNS="(instructed to minimize DNS queries)" && return 0 # PTR records were not asked for
local nodeip="$(tr -d '[]' <<< $NODEIP)" # for DNS we do not need the square brackets of IPv6 addresses local nodeip="$(tr -d '[]' <<< $NODEIP)" # for DNS we do not need the square brackets of IPv6 addresses
OPENSSL_CONF="" # see https://github.com/drwetter/testssl.sh/issues/134 OPENSSL_CONF="" # see https://github.com/testssl/testssl.sh/issues/134
if [[ "$NODE" == *.local ]]; then if [[ "$NODE" == *.local ]]; then
if "$HAS_AVAHIRESOLVE"; then if "$HAS_AVAHIRESOLVE"; then
rDNS=$(avahi-resolve -a $nodeip 2>/dev/null | awk '{ print $2 }') rDNS=$(avahi-resolve -a $nodeip 2>/dev/null | awk '{ print $2 }')
@ -21650,7 +21722,7 @@ determine_rdns() {
elif "$HAS_NSLOOKUP"; then elif "$HAS_NSLOOKUP"; then
rDNS=$(strip_lf "$(nslookup -type=PTR $nodeip 2>/dev/null | grep -v 'canonical name =' | grep 'name = ' | awk '{ print $NF }' | sed 's/\.$//')") rDNS=$(strip_lf "$(nslookup -type=PTR $nodeip 2>/dev/null | grep -v 'canonical name =' | grep 'name = ' | awk '{ print $NF }' | sed 's/\.$//')")
fi fi
OPENSSL_CONF="$saved_openssl_conf" # see https://github.com/drwetter/testssl.sh/issues/134 OPENSSL_CONF="$saved_openssl_conf" # see https://github.com/testssl/testssl.sh/issues/134
# First, rDNS can contain multilines due to multiple PTR DNS records, though this is not recommended. # First, rDNS can contain multilines due to multiple PTR DNS records, though this is not recommended.
# So we use a loop to check for each FQDN returned. There we remove chars which under weird # So we use a loop to check for each FQDN returned. There we remove chars which under weird
# circumstances (see #1506) can show up here. The blacklist is taken from RFC 1912 ("Allowable characters in a # circumstances (see #1506) can show up here. The blacklist is taken from RFC 1912 ("Allowable characters in a
@ -22046,7 +22118,7 @@ determine_optimal_proto() {
>$ERRFILE >$ERRFILE
if [[ -n "$1" ]]; then if [[ -n "$1" ]]; then
# STARTTLS workaround needed see https://github.com/drwetter/testssl.sh/issues/188 -- kind of odd # STARTTLS workaround needed see https://github.com/testssl/testssl.sh/issues/188 -- kind of odd
for STARTTLS_OPTIMAL_PROTO in -tls1_2 -tls1 -ssl3 -tls1_1 -tls1_3 -ssl2; do for STARTTLS_OPTIMAL_PROTO in -tls1_2 -tls1 -ssl3 -tls1_1 -tls1_3 -ssl2; do
sclient_supported "$STARTTLS_OPTIMAL_PROTO" || continue sclient_supported "$STARTTLS_OPTIMAL_PROTO" || continue
$OPENSSL s_client $(s_client_options "$STARTTLS_OPTIMAL_PROTO $BUGS -connect "$NODEIP:$PORT" $PROXY -msg $STARTTLS $SNI") </dev/null >$TMPFILE 2>>$ERRFILE $OPENSSL s_client $(s_client_options "$STARTTLS_OPTIMAL_PROTO $BUGS -connect "$NODEIP:$PORT" $PROXY -msg $STARTTLS $SNI") </dev/null >$TMPFILE 2>>$ERRFILE