diff --git a/.github/workflows/docker-3.2.yml b/.github/workflows/docker-3.2.yml index 2c6128b..0335c0f 100644 --- a/.github/workflows/docker-3.2.yml +++ b/.github/workflows/docker-3.2.yml @@ -23,7 +23,7 @@ jobs: - name: Setup QEMU id: qemu - uses: docker/setup-qemu-action@v3.2.0 + uses: docker/setup-qemu-action@v3.3.0 - name: Setup Buildx id: buildx @@ -48,7 +48,7 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Build and push - uses: docker/build-push-action@v6.7.0 + uses: docker/build-push-action@v6.12.0 with: push: ${{ github.event_name != 'pull_request' }} context: . diff --git a/.github/workflows/test.yml b/.github/workflows/unit_tests.yml similarity index 100% rename from .github/workflows/test.yml rename to .github/workflows/unit_tests.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index dca42a3..2942f07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -137,7 +137,7 @@ * Trust chain check against certificate stores from Apple (OS), Linux (OS), Microsoft (OS), Mozilla (Firefox Browser), works for openssl >=1.0.1 * 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 * extensive CN <--> hostname check * SSL Session ID check @@ -183,7 +183,7 @@ * quite some LibreSSL fixes, still not recommended to use though (see https://testssl.sh/) * 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 * "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 * 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: * 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 * 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: * SNI diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5953205..1029fbe 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,21 +1,25 @@ -### Contributions / participation +### Contributing / participating -is always welcome, here @ github or via e-mail. +Contributing / participating is always welcome! -Note please the following +Please note the following: -* Please read at least the [coding convention](https://github.com/drwetter/testssl.sh/Coding_Convention.md). -* 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. +* Please read the [coding convention](https://github.com/testssl/testssl.sh/blob/3.2/Coding_Convention.md). +* If you have something new and/or bigger which you like to contribute, better open an issue first before you get frustrated. +* Please one pull request per feature or bug fix or improvement. Please do not mix issues. +* Documentation pays off in the long run. So please your document your code and the pull request and/or commit message. * Please test your changes thoroughly as reliability is important for this project. You may want to check different servers with different settings. -* Travis runs automatically when anything is committed/PR'd. You should check any complains from Travis. Beforehand you can check with `prove -v`. -* If it's a new feature please consider writing a unit test for it. You can use e.g. `t/20_baseline_ipv4_http.t` as a template. The general documentation for [Test::More](https://perldoc.perl.org/Test/More.html) is a good start. -* If it's a new feature it would need to be documented in the appropriate section in `help()` and in `~/doc/testssl.1.md` +* GitHub actions are running automatically when anything is committed. You should see any complains. Beforehand you can check with `prove -v` from the "root dir" of this project. +* If it's a new feature, please consider writing a unit test for it. You can use e.g. `t/10_baseline_ipv4_http.t` or `t/61_diff_testsslsh.t` as a template. The general documentation for [Test::More](https://perldoc.perl.org/Test/More.html) is a good start. +* If it's a new feature, it would need to be documented in the appropriate section in `help()` and in `~/doc/testssl.1.md` -For questions just open an issue or feel free to send me an e-mail. +If you're interested in contributing and wonder how you can help, you can search for different tags in the issues (somewhat increasing degree of difficulty): +* [documentation](https://github.com/testssl/testssl.sh/issues?q=is:issue%20state:open%20label:documentation) +* [good first issue](https://github.com/testssl/testssl.sh/issues?q=is:issue%20state:open%20label:%22good%20first%20issue%22) +* [help wanted](https://github.com/testssl/testssl.sh/issues?q=is:issue%20state:open%20label:%22help%20wanted%22) +* [for grabs](https://github.com/testssl/testssl.sh/issues?q=is:issue%20state:open%20label:%22good%20first%20issue%22) + +For questions just open an issue. Thanks for reading this! -#### Patches via e-mail -Of course it is fine when you want to send in patches to use e-mail. For the address please grep for SWCONTACT in testssl.sh . -Let me know how you like them to be attributed. diff --git a/Dockerfile b/Dockerfile index 3767781..6c5db47 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ # syntax=docker.io/docker/dockerfile:1 -ARG LEAP_VERSION=15.5 +ARG LEAP_VERSION=15.6 ARG INSTALL_ROOT=/rootfs FROM opensuse/leap:${LEAP_VERSION} as builder @@ -18,7 +18,7 @@ RUN source /etc/os-release \ && zypper "${ZYPPER_OPTIONS[@]}" --gpg-auto-import-keys refresh \ && rpm -e util-linux --nodeps \ && zypper "${ZYPPER_OPTIONS[@]}" --non-interactive install --download-in-advance --no-recommends \ - bash procps grep gawk sed coreutils busybox-util-linux busybox-vi ldns libidn2-0 socat openssl curl \ + bash procps grep gawk sed coreutils busybox ldns libidn2-0 socat openssl curl \ && zypper up -y \ && zypper "${ZYPPER_OPTIONS[@]}" clean --all ## Cleanup (reclaim approx 13 MiB): @@ -35,6 +35,7 @@ ARG INSTALL_ROOT COPY --link --from=builder ${INSTALL_ROOT} / # Link busybox to tar, see #2403. Create user + (home with SGID set): RUN ln -s /usr/bin/busybox /usr/bin/tar \ + && ln -s /usr/bin/busybox /usr/bin/hexdump \ && echo 'testssl:x:1000:1000::/home/testssl:/bin/bash' >> /etc/passwd \ && echo 'testssl:x:1000:' >> /etc/group \ && echo 'testssl:!::0:::::' >> /etc/shadow \ diff --git a/Dockerfile.git b/Dockerfile.git index e822163..8e69382 100644 --- a/Dockerfile.git +++ b/Dockerfile.git @@ -5,8 +5,8 @@ FROM alpine:3.20 WORKDIR /home/testssl ARG BUILD_VERSION -ARG ARCHIVE_URL=https://github.com/drwetter/testssl.sh/archive/ -ARG URL=https://github.com/drwetter/testssl.sh.git +ARG ARCHIVE_URL=https://github.com/testssl/testssl.sh/archive/ +ARG URL=https://github.com/testssl/testssl.sh.git RUN test -n "${BUILD_VERSION}" \ && apk update \ diff --git a/Readme.md b/Readme.md index 3fb943e..6736329 100644 --- a/Readme.md +++ b/Readme.md @@ -1,11 +1,11 @@ ## Intro - -[![Build Status](https://github.com/drwetter/testssl.sh/actions/workflows/test.yml/badge.svg)](https://github.com/drwetter/testssl.sh/actions/workflows/test.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) -[![License](https://img.shields.io/github/license/drwetter/testssl.sh)](https://github.com/drwetter/testssl.sh/LICENSE) -[![Docker](https://img.shields.io/docker/pulls/drwetter/testssl.sh)](https://github.com/drwetter/testssl.sh/blob/3.2/Dockerfile.md) +[![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/testssl/testssl.sh?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![License](https://img.shields.io/github/license/testssl/testssl.sh)](https://github.com/testssl/testssl.sh/LICENSE) +[![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 any port for the support of TLS/SSL ciphers, protocols as well as some @@ -45,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 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 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. -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. +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 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 @@ -69,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 ``` -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 -Usage of the program is without any warranty. Use it at yor 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. ### 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. @@ -93,16 +93,19 @@ Support for 2.9.5 has been dropped. Supported is >= 3.0.x only. ### 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 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 @ -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). ---- @@ -129,7 +132,7 @@ Please address questions not specifically to the code of testssl.sh to the respe #### 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) #### Daemon for batch execution of testssl.sh command files diff --git a/etc/cipher-mapping.txt b/etc/cipher-mapping.txt index e0b542f..1125f87 100644 --- a/etc/cipher-mapping.txt +++ b/etc/cipher-mapping.txt @@ -342,6 +342,8 @@ 0x02,0x00,0x80 - EXP-RC4-MD5 SSL_CK_RC4_128_EXPORT40_WITH_MD5 SSLv2 Kx=RSA(512) Au=RSA Enc=RC4(40) Mac=MD5 export 0x00,0x28 - EXP-KRB5-RC4-SHA TLS_KRB5_EXPORT_WITH_RC4_40_SHA SSLv3 Kx=KRB5 Au=KRB5 Enc=RC4(40) Mac=SHA1 export 0x00,0x2B - EXP-KRB5-RC4-MD5 TLS_KRB5_EXPORT_WITH_RC4_40_MD5 SSLv3 Kx=KRB5 Au=KRB5 Enc=RC4(40) Mac=MD5 export + 0xC0,0xB4 - TLS_SHA256_SHA256 TLS_SHA256_SHA256 TLSv1.3 Kx=any Au=any Enc=None Mac=SHA256 + 0xC0,0xB5 - TLS_SHA384_SHA384 TLS_SHA384_SHA384 TLSv1.3 Kx=any Au=any Enc=None Mac=SHA384 0xC0,0x10 - ECDHE-RSA-NULL-SHA TLS_ECDHE_RSA_WITH_NULL_SHA SSLv3 Kx=ECDH Au=RSA Enc=None Mac=SHA1 0xC0,0x06 - ECDHE-ECDSA-NULL-SHA TLS_ECDHE_ECDSA_WITH_NULL_SHA SSLv3 Kx=ECDH Au=ECDSA Enc=None Mac=SHA1 0xC0,0x15 - AECDH-NULL-SHA TLS_ECDH_anon_WITH_NULL_SHA SSLv3 Kx=ECDH Au=None Enc=None Mac=SHA1 diff --git a/etc/curves-mapping.txt b/etc/curves-mapping.txt index 444f92d..2120f0a 100644 --- a/etc/curves-mapping.txt +++ b/etc/curves-mapping.txt @@ -45,3 +45,7 @@ 0x01,0x02 - ffdhe4096 ffdhe4096 0x01,0x03 - ffdhe6144 ffdhe6144 0x01,0x04 - ffdhe8192 ffdhe8192 + 0x11,0xeb - SecP256r1MLKEM768 SecP256r1MLKEM768 + 0x11,0xec - X25519MLKEM768 X25519MLKEM768 + 0x11,0xed - SecP384r1MLKEM1024 SecP384r1MLKEM1024 + 0x63,0x99 - X25519Kyber768Draft00 X25519Kyber768Draft00 diff --git a/etc/tls_data.txt b/etc/tls_data.txt index 5fc5b7c..42483d9 100644 --- a/etc/tls_data.txt +++ b/etc/tls_data.txt @@ -3,9 +3,9 @@ # see #807 and #806 (especially # https://github.com/drwetter/testssl.sh/issues/806#issuecomment-318686374) -# All 5 ciphers defined for TLS 1.3 +# 7 ciphers defined for TLS 1.3 in RFCs 8446 and 9150 readonly TLS13_CIPHER=" -13,01, 13,02, 13,03, 13,04, 13,05" +13,01, 13,02, 13,03, 13,04, 13,05, c0,b4, c0,b5" # 123 standard cipher + 4x GOST for TLS 1.2 and SPDY/NPN HTTP2/ALPN declare TLS12_CIPHER=" @@ -339,5 +339,8 @@ readonly -a TLS13_PUBLIC_KEY_SHARES=( "01,02,02,00,8f,b3,b5,3f,0b,de,23,e1,5c,4a,77,ed,b2,4d,1c,4b,76,91,12,c4,fe,5b,15,23,13,a4,f3,b6,5b,23,8d,88,d5,77,0e,e4,1d,60,0b,58,1b,af,67,ee,31,fb,b6,ce,f5,1b,36,10,c1,f2,f0,83,e6,b9,23,13,1e,b2,9f,ae,e0,9e,42,64,4c,bd,1e,87,18,bd,a6,9b,ae,59,20,e8,9f,52,78,e6,f7,35,56,b6,3a,e6,82,8e,87,b5,c8,23,07,e1,f5,6e,95,8d,c6,83,83,88,b8,41,d8,63,58,33,fe,39,20,d4,9c,37,0e,68,5b,e9,1f,48,0e,85,d6,36,70,a2,06,a8,dc,5c,62,75,4d,bd,bd,3a,6f,03,b0,25,33,11,20,67,0f,76,23,d9,ab,5b,e9,c4,bc,ff,a8,1f,49,c0,e1,42,c7,3c,cb,25,7a,d3,c8,39,e2,f7,b1,22,ca,14,b2,3a,2e,7a,a0,80,a9,e0,dc,96,53,ca,d7,48,be,6d,bc,68,a9,38,b0,be,b0,1b,8c,85,9e,51,42,69,24,f0,28,c8,7c,f1,bc,e3,0f,1f,9c,f3,8b,3a,96,3b,52,ed,36,b1,88,10,9f,c8,02,89,2b,5a,eb,d5,fc,af,03,46,fa,cf,8a,ba,80,ae,8f,89,f7,fd,0f,77,f3,4e,24,35,32,35,e9,c4,82,97,25,51,ab,2b,01,dd,ca,53,5f,7c,3b,25,89,d2,54,69,30,48,6b,4a,03,25,dd,be,c6,ea,33,c2,86,7f,e9,d0,9b,31,fd,70,37,54,c2,8c,dc,96,6d,5a,2e,b6,c2,6d,85,ee,f2,32,b8,95,b0,66,40,44,1e,a2,bf,25,ed,1f,41,9d,37,5b,56,e0,1d,95,1d,ec,d8,f6,24,68,d4,06,17,16,7e,8c,31,7e,40,c2,88,29,d1,f9,8e,eb,4d,4e,5a,9d,65,c8,a2,43,83,4c,04,8b,93,eb,40,23,5f,80,8f,2f,29,ff,c3,13,47,ad,b0,c1,5a,28,08,dc,1e,83,e7,ed,26,4e,30,2c,6e,5a,0e,f1,db,68,ab,89,bb,61,63,6d,55,97,b2,94,16,cd,6f,d5,60,92,e8,71,ef,a3,b2,ae,0c,40,26,d5,35,1d,c8,ed,12,94,86,8c,1c,97,bd,cc,1d,53,0f,4c,99,21,fc,34,5a,79,8c,ca,ea,ae,99,bc,8b,a9,52,fe,f9,63,75,6f,7d,51,79,e6,ca,92,6c,b8,7e,7b,20,a9,c0,2a,15,1d,bb,c0,c2,b1,52,42,7f,dd,1c,8d,e5,a7,7f,26,f5,29,cb,4b,91,5b,80,c2,3a,94,e8,c5,2f,6d,7a,0d" "01,03,03,00,13,37,f3,03,0c,1f,cf,3d,2f,9c,e1,aa,a2,d5,90,ab,4a,e0,e6,b3,87,d2,a2,16,1e,26,7b,21,17,7d,82,39,ce,d4,50,94,17,b4,d0,5a,37,6e,ba,82,2b,fa,0f,7c,b6,e2,1d,01,7d,40,ca,a9,c3,fb,0d,4e,ef,ce,8a,b8,f8,61,54,14,02,6c,50,f9,dd,86,a8,2c,a8,5b,06,ff,60,4d,19,a9,ff,77,77,ba,6d,96,72,b4,d2,46,71,e2,2b,45,d8,5e,1f,84,64,07,ef,56,f9,64,1b,11,ff,ad,05,19,f9,2b,5d,af,50,91,24,c1,ca,ff,c8,78,92,32,13,fc,90,f3,12,24,62,c6,97,7f,5d,73,90,70,72,43,e2,bc,90,3f,3b,a4,85,3e,53,2e,43,a2,4f,c6,c6,38,88,0b,07,52,3d,98,b7,e3,4d,24,86,02,86,36,b8,2c,fa,49,28,e2,b9,a8,8c,75,16,32,8b,c8,e4,90,47,ba,d8,da,a6,ae,2e,af,4c,1e,ae,a1,99,70,c9,cf,1d,a8,e1,5c,fc,1f,61,25,f8,e5,5c,d2,27,8c,32,a6,28,51,42,91,91,08,e5,8f,48,d0,33,ad,7f,45,1a,5f,ee,30,f7,29,2c,23,88,b0,5c,6e,76,2d,56,7c,bc,63,73,a0,d6,13,71,58,82,91,79,4c,9b,aa,22,05,61,48,b5,51,af,d0,0e,9c,7d,94,a7,f5,6a,b9,cb,57,97,55,ca,d1,cc,b8,f5,3e,f7,bc,93,05,1a,af,c4,57,54,4c,a3,83,80,53,90,ac,16,5b,ec,6d,5f,82,83,e5,ca,fa,12,c2,8d,2b,a6,36,a8,b2,38,50,fc,f0,a5,fb,52,2d,eb,68,95,4d,f7,94,6d,75,f7,41,1f,46,db,86,71,d0,37,16,91,34,df,2f,89,78,4c,88,27,7d,2a,46,39,f0,8b,ec,75,e1,f3,5c,3f,98,b4,03,f3,c4,ea,70,af,67,0d,ee,97,d0,31,cd,3e,c1,c9,6e,4c,97,a0,64,19,44,9f,ad,16,4c,be,10,b6,e4,cc,9c,9d,2d,4f,79,02,a4,ea,09,2c,1d,2e,fd,c2,12,1a,de,ba,c9,a1,98,77,41,1c,14,56,ca,d9,19,02,46,87,7c,8d,a1,c4,3f,90,99,ca,2e,99,18,40,7e,ae,93,91,c3,4a,5f,68,f8,62,f9,34,83,ae,2e,64,c6,cf,a7,6d,80,eb,28,8b,ac,90,3b,1a,a2,a2,13,26,f3,91,40,bb,3a,44,2b,d2,0c,58,74,fc,9d,60,a9,d2,a6,34,c4,21,65,f6,00,c2,73,e1,e4,29,9d,c8,a9,88,33,38,c7,dd,83,23,d8,4b,66,d5,7c,78,7f,c3,62,23,34,12,1a,ee,a1,62,84,fe,62,3a,09,6b,72,69,58,d8,1b,fd,b0,89,e9,e1,da,fa,35,db,83,5f,93,a5,62,ad,c7,f7,e2,a7,6d,db,00,9e,7e,ea,9f,53,ef,d4,bd,32,e7,9e,2a,d1,90,a4,37,1b,b2,cd,cc,21,28,4a,96,3f,35,54,78,88,90,3b,e5,22,94,e4,2a,9f,d2,ef,7f,75,3d,b2,83,34,fe,66,45,4c,c2,ca,06,f3,fd,46,29,6b,40,32,66,a2,64,30,16,ee,04,cb,3d,28,bd,bf,a7,f1,84,9d,23,bf,61,e1,59,c7,36,b5,60,b5,39,39,eb,fd,ff,06,9e,52,99,69,97,d4,8b,bb,8f,84,90,fd,e2,0d,fd,7b,85,49,cc,81,3c,1d,c1,37,1e,5f,34,cd,52,4f,61,9a,85,c5,29,1d,b4,42,8c,c4,8d,94,43,cb,6a,e2,af,90,a6,ec,09,89,07,ae,62,9d,66,bd,fe,87,4d,76,0c,ce,e4,70,87,74,89,02,00,6c,54,4b,86,45,b5,f2,d6,fe,6e,f1,74,ae,c5,1f,67,f0,19,44,44,32,5d,d1,8a,a4,71,17,b0,9c,a4,5d,90,d4,29,b6,24" "01,04,04,00,67,47,f0,4b,9c,5b,75,a3,4d,9b,1f,b2,b4,32,56,a4,dd,23,69,70,4c,c3,ee,f2,0f,82,51,bc,54,8c,0d,a3,21,bf,94,88,82,7c,69,e8,55,d3,1d,8d,80,be,71,4d,4c,48,f8,ce,1e,f8,72,ac,a5,4c,74,aa,8f,a7,e0,51,99,ad,51,35,14,e7,98,02,1b,9d,07,e5,d1,07,d0,15,d2,9b,33,81,62,b7,7e,52,d5,b1,37,ea,55,f7,80,74,4c,25,cb,61,e9,75,c0,c9,7b,4e,19,4d,d1,69,46,ca,01,c9,14,06,a8,17,e0,f4,e5,c4,5d,e9,f6,2a,d5,02,b8,8b,6e,4a,26,ec,8c,a4,c0,bd,17,a6,48,5c,46,4f,bf,6f,c9,f1,4a,27,fa,4c,d1,93,e7,22,8c,2b,32,55,0c,2b,c6,ea,73,19,7d,e8,b7,fc,64,0d,f0,f9,bf,0d,3a,8b,3c,a9,30,a1,03,1b,e3,1b,d6,94,a8,39,4b,23,ce,ea,7b,2a,3a,af,4f,6c,15,cd,13,ca,67,84,05,9c,a7,d0,f6,7f,97,0b,e0,b3,bb,fd,ca,10,f6,35,57,5f,9b,e7,c2,5f,5c,16,f8,31,0c,23,34,7b,0b,f0,d1,b0,e4,e6,6a,45,db,32,be,fa,fc,92,df,01,3d,ca,bc,c8,d2,c9,57,8e,6b,eb,7b,f4,8c,23,b4,cf,16,73,a3,20,50,e7,f6,98,7a,19,f8,be,e4,72,3f,45,e7,e9,df,69,10,dd,72,24,94,d4,ce,c9,70,13,49,9d,af,bd,61,7a,a8,ee,82,9f,ce,2e,0f,4f,cf,c0,26,9b,98,a6,9e,a7,06,ed,b6,d7,f0,db,c6,c4,f0,db,55,94,87,92,af,11,dc,07,47,eb,e4,b5,3b,c8,5a,24,31,f2,d7,06,c5,a5,19,80,75,88,5e,45,f1,0f,e0,94,ea,9f,1b,65,4d,1a,ec,18,db,b0,c8,05,ca,25,46,6a,85,8a,49,d1,e7,06,9d,84,1f,ca,7e,48,02,34,b2,0d,4c,5e,61,d5,5d,b5,51,8c,19,18,2c,87,9e,69,b2,81,c1,4c,62,09,25,1f,e9,8d,0b,23,81,d3,36,a1,c5,41,f8,db,c6,8c,cf,1c,55,54,41,d0,5b,92,a8,3f,a5,ae,dd,69,98,c4,f3,8f,7b,26,70,43,f6,62,e5,89,4f,e4,cb,c7,de,63,13,f7,a9,6b,51,e4,41,dc,fe,9e,50,32,32,32,04,bd,d2,d7,8b,4d,29,9a,78,91,28,6e,56,30,5e,89,ba,1e,62,c5,8a,27,05,bc,ad,1e,2c,d1,cf,d4,bc,c0,69,a7,2d,3f,07,3c,77,f9,69,ca,16,1f,a7,14,4e,c8,0b,fa,e7,3a,9e,38,a6,c0,aa,b6,1e,66,30,a8,18,51,8f,76,27,fa,5c,c2,07,e8,e6,f0,98,6e,bb,b0,d7,53,d3,db,d4,2e,d6,1f,83,49,23,a3,1f,c4,0c,12,8c,67,ed,1c,01,a6,40,a8,ad,68,9a,6e,af,ee,ad,5f,d0,78,5f,15,5d,09,8e,e6,80,a4,f0,f3,c8,55,27,f1,44,6f,58,07,16,ed,87,1f,8e,26,d6,3c,a0,17,2e,79,d0,72,12,dc,81,d5,ae,a0,ad,86,31,8e,6d,45,d7,d1,3a,94,e7,e5,7b,3d,b7,5f,50,3c,af,e8,ea,2b,f0,e2,3c,eb,14,b6,16,31,0c,70,3b,92,e8,a2,f9,84,d1,aa,ba,73,80,89,ec,54,3c,23,a9,d5,87,87,b9,27,9a,87,bb,c5,06,96,9a,37,2b,d8,d9,af,32,e8,fd,8d,b0,49,c1,cb,81,bc,0d,0b,fe,dc,40,fb,b1,50,41,ed,71,3b,87,cc,95,6d,df,80,85,92,c6,66,cb,4c,75,16,46,f1,b1,08,ed,be,91,21,c5,b0,e8,83,58,96,24,16,28,15,e2,fe,94,e4,42,99,84,77,43,7b,1f,ac,a7,55,ff,33,09,6a,6e,b4,66,21,d6,c0,6f,88,35,94,6f,ab,1d,c6,74,7b,4c,30,a9,e0,70,36,7f,94,aa,c0,c7,98,71,ec,10,c9,96,86,32,08,83,37,16,60,cf,19,f0,19,11,4c,f4,65,87,d8,5f,16,ad,c6,80,89,1d,37,d6,26,91,bf,ef,de,47,62,c5,05,b8,b9,c1,a8,6c,19,ec,80,af,ec,dd,d8,ee,d3,c4,b5,13,77,88,20,fe,68,64,b3,bd,f1,90,67,c4,d7,29,e5,b9,4e,7c,29,34,a8,14,4f,09,60,9b,5f,87,c5,23,d2,49,da,e6,da,2a,cf,c4,c6,3d,c8,9a,5f,37,ca,fb,08,d0,28,1e,88,f0,30,37,74,b0,c3,8f,3f,2c,b3,bc,39,3a,96,27,d6,c0,c7,91,bb,d1,fc,f0,28,be,82,3b,ac,2b,28,72,9d,31,2d,42,5d,d8,36,d8,a8,c9,ca,58,b9,f9,4a,14,b8,38,52,c9,ea,aa,8d,05,52,d5,4b,22,87,8f,09,d3,0d,c9,16,f1,d3,26,61,e5,5c,bd,84,64,88,7d,32,8d,ea,6d,8a,00,dc,54,a5,75,50,a4,3b,99,33,b1,e2,ef,8d,e5,f6,78,d8,dd,71,1a,64,02,6f,ac,37,a5,2a,fc,5d,c8,af,f9,87,3b,77,f3,1c,2c,cc,db,a6" - "105" "106" "107" "108" "109" "10a" "10b" "10c" "10d" "10e" "10f" ) + [4587]="11,eb,04,e1,04,4e,42,eb,6e,46,64,d1,91,3e,88,28,08,ee,82,61,a2,2b,db,42,50,96,ff,0c,ae,4b,c7,1f,5b,b1,50,99,5f,37,77,b3,70,53,3f,96,2f,23,6a,83,07,eb,b2,91,ce,c0,ea,0e,aa,33,42,80,ce,cf,3b,ce,02,58,46,4f,58,ba,e1,68,65,e7,ba,7b,79,2b,05,03,89,dd,48,91,d4,d2,be,bc,ba,0e,9d,86,1f,fe,42,a6,91,f4,43,5a,33,34,59,f6,6e,26,c3,11,1b,08,0d,7f,a1,5b,fd,75,2f,61,f6,5e,f9,91,24,94,d9,97,d8,f5,43,f9,6a,c8,20,da,84,b9,35,7a,04,45,1c,d2,10,4b,e2,2b,05,28,30,be,85,1a,75,4a,d8,25,91,6c,6a,47,12,95,7d,f6,aa,8d,57,55,b1,24,c1,7c,13,9d,bf,f0,06,9a,56,5c,fc,d5,2c,af,39,0d,12,59,17,91,02,3f,39,c8,28,a3,24,2b,8d,fb,57,c1,02,94,23,94,0c,a4,9a,31,8d,08,87,d6,01,15,d1,dc,b6,12,93,03,3a,57,3f,1b,bb,94,30,3a,71,20,72,54,b1,50,12,13,03,0e,61,da,85,7e,f3,12,fe,08,a5,ef,9c,3c,6d,30,af,03,c6,62,02,41,55,46,ba,8c,59,a6,48,2e,4a,92,a4,d5,ae,61,97,16,1b,f0,4a,58,48,45,d7,9c,1b,63,b6,b8,b8,46,0f,c8,7b,be,f0,91,57,8f,20,7e,93,1a,97,10,bc,a3,6f,23,92,ce,c5,59,8b,b1,94,a6,95,85,08,41,62,8e,8b,2c,b4,f7,af,9c,e6,17,70,58,24,90,bb,0e,09,a1,a1,1f,b2,03,98,7a,61,a7,a3,5a,89,37,b5,eb,97,18,9a,17,22,43,53,bf,88,ab,6b,0f,a0,57,b5,74,71,f6,41,28,0b,84,85,31,b2,2f,c7,08,0e,b8,40,12,8f,87,c4,38,99,b0,80,43,13,ba,eb,54,ab,b6,6e,b7,43,9c,64,69,7b,3f,66,5f,35,5b,03,c1,bb,78,54,47,8b,9e,c8,70,68,42,75,c9,e1,47,2d,39,38,a0,9c,66,f3,bc,b4,75,b1,98,b8,77,85,bf,01,70,6e,81,49,c5,8b,59,5b,6a,b3,f9,cc,0c,4f,1b,2c,2c,d3,50,ef,b1,89,1d,54,2c,5d,22,2a,a0,fa,53,60,02,05,e0,b0,13,fe,e9,85,cc,57,5a,88,97,38,63,45,56,d3,2b,69,c4,00,1e,e3,92,22,2f,e4,55,8e,86,13,c8,a4,16,98,d3,3d,51,53,77,ea,d8,37,ca,41,0e,16,94,68,66,b5,c9,ca,06,28,de,78,02,94,d0,8e,67,5c,9b,57,ac,74,a4,73,66,10,d4,4c,74,14,68,01,db,1a,a9,b8,aa,56,91,71,3c,f6,75,23,bb,99,e5,5c,89,47,a3,7c,9f,d6,a4,82,a1,39,a9,35,42,49,94,29,0c,a5,22,e6,03,5d,fd,59,28,63,8c,05,b3,1a,84,8a,99,86,1a,02,10,c1,ec,c5,4f,58,0a,50,67,c0,c3,a5,7d,22,01,b5,57,c6,68,63,37,cb,74,e8,44,18,17,1f,ce,54,59,2a,4c,5f,e1,bb,96,85,77,81,d6,d9,88,54,02,69,51,1c,41,e4,03,3f,6c,62,94,e2,68,2e,9c,03,cb,b3,5b,73,a3,9c,36,ab,c4,29,0c,b5,c1,e6,b6,5a,bd,f4,89,3b,93,97,0c,33,59,a5,71,71,fc,2c,7a,d9,46,b3,11,1c,10,fe,55,9e,01,82,42,60,ec,3d,e5,83,c7,84,eb,8e,10,f9,8d,eb,7b,b3,82,0a,88,2f,50,53,20,1c,7b,de,27,39,1a,68,86,be,db,80,b6,4c,29,11,68,4f,3d,f0,76,eb,b5,4e,e1,65,7c,a4,82,2b,30,23,15,1d,65,7b,a8,06,24,3f,77,65,ab,80,84,d1,7b,a4,10,1b,08,c3,f6,a7,9d,c5,bb,e9,c5,02,2d,47,c0,22,47,6b,32,8b,2f,a4,5c,02,6d,7c,38,72,23,6d,a7,09,ba,7f,45,b1,04,76,cd,0e,12,0b,61,75,81,1a,94,68,88,c9,c5,1c,d5,7a,42,a4,c4,f3,dc,51,ed,6a,78,e6,45,a6,1f,31,74,de,9c,9c,61,32,51,67,e3,a5,bb,19,88,77,77,76,52,59,27,49,82,8c,c2,59,00,df,80,67,8c,82,ad,13,f0,13,17,21,43,3c,40,76,71,96,72,40,57,38,d9,e0,80,56,d7,bc,40,fb,9a,a4,8a,a1,a6,bb,99,94,31,96,38,b8,57,8b,68,08,27,d7,9e,18,1b,1b,3f,a1,9a,92,5b,6b,b8,73,72,8e,d7,3d,86,c7,24,73,98,ba,6e,07,17,0e,11,36,44,69,b8,7d,aa,b7,de,e6,71,5f,13,1a,55,c9,bb,e9,06,bd,4e,d7,04,df,e5,29,9f,c6,59,cf,77,4c,11,b1,41,ef,5c,68,2d,22,9d,8f,13,80,2c,cc,a9,35,8b,b3,1e,73,2c,0f,61,13,0f,2b,8f,a2,69,b4,bf,22,2e,23,4c,b5,24,66,39,a9,a3,19,12,56,44,3a,f4,15,e2,f4,cb,b7,36,08,bf,79,c1,fa,90,71,e8,84,4c,ec,95,73,e7,41,62,7f,f2,57,95,ca,13,3c,f3,ba,36,03,cd,e1,37,6f,31,b0,9f,17,8b,b8,a6,85,44,e3,26,71,8b,b1,05,b1,91,73,96,7b,bb,04,35,19,a5,44,a0,d8,17,c8,73,5b,58,d5,e9,b1,dc,9a,71,3d,16,84,a4,10,37,67,cc,0c,d4,77,94,e4,f2,5e,f1,e9,36,b0,61,93,68,59,bb,e0,24,c0,4c,e8,58,1e,83,2d,a9,88,7a,15,52,16,6b,94,18,2e,2b,2d,60,93,78,b1,32,98,4f,a7,5c,4d,2a,7e,4d,b5,27,04,79,20,d5,83,bf,37,1a,68,11,0a,b5,1b,45,31,3a,31,b9,4f,a7,ba,e5,49,20,2d,d1,19,ab,38,3c,7d,f1,cd,bf,db,1e,13,8c,70,0c,ab,bd,23,24,53,3b,39,bb,01,b2,56,e2,3c,96,94,22,92,f6,89,86,31,fb,ad,59,ea,07,64,e3,d7,68,35,6f,33,41,b7,c9,38,2e,08,b7,3a,01,10,9a,96,9d,e0,d1,92,24,e5,d6,26,af,45" + [4588]="11,ec,04,c0,15,45,8a,33,c6,16,72,fb,44,02,c9,c1,42,63,5d,2e,d0,30,a8,9b,a8,84,19,33,bf,23,10,ec,05,67,68,d9,12,0e,88,07,0a,39,85,85,6c,52,6e,24,70,69,38,aa,a1,a7,10,41,b5,4f,5a,99,2f,38,dc,07,0e,ab,a8,a2,44,40,49,7c,47,5d,3a,bd,7c,ea,af,63,11,47,5f,d2,8c,ef,81,b1,4d,e1,57,40,e6,32,0c,49,5d,43,63,62,7e,a8,49,71,7a,85,ea,00,9f,42,54,85,71,97,16,0e,43,35,4b,d1,26,2c,73,c8,cc,f2,43,63,c3,66,17,b4,7c,a7,d2,66,98,b4,60,e8,0b,a7,94,49,75,03,e3,4f,bf,69,ba,e7,67,68,89,c2,8a,4b,24,a2,42,f4,74,92,e3,44,85,bc,9e,da,e3,40,e9,e4,bd,4c,02,20,88,dc,67,2d,25,ba,4f,0a,4b,7c,dc,1f,96,d3,6a,01,86,5b,ad,75,b2,23,c5,c7,39,10,35,34,59,6e,23,fc,c9,cd,c0,17,e0,16,79,4b,04,82,70,d9,1f,62,a4,36,67,d3,00,a9,db,a4,25,09,21,38,f0,0b,d1,17,6a,3d,d5,22,51,1a,a6,0b,97,23,c7,67,32,0b,7c,a0,b3,a7,0d,06,49,01,52,69,9c,4f,f5,37,dd,0c,a7,bc,d0,c2,72,d5,6f,9c,26,aa,c3,ca,0d,84,6b,27,40,f8,1b,e3,55,bb,e4,f0,9a,15,52,2f,a3,da,06,45,c2,10,6e,a3,2a,07,87,61,89,1c,39,b1,52,26,2a,80,a5,a6,4b,2c,b3,3c,40,d7,42,0d,8b,67,90,d6,c6,49,09,a7,6e,d3,f2,c2,ac,b5,46,75,2c,8c,0d,03,0a,d8,f2,b7,19,a7,a4,84,f4,90,48,34,29,aa,00,28,e8,01,bf,2b,02,94,57,e2,62,36,59,61,d2,c0,0e,1c,69,04,57,b0,ba,c3,2c,a4,aa,e7,46,03,45,c9,a1,b6,58,13,ba,3f,ea,80,b3,ef,dc,5c,7f,28,8b,c6,92,18,db,81,0b,43,e1,07,65,b4,be,96,33,58,f0,31,c0,8c,29,9c,4c,d9,a8,95,91,58,e1,e7,61,b5,b5,23,0e,fa,39,62,63,38,3e,d4,3c,df,c1,09,81,ea,4f,0b,a2,7c,e3,08,1f,e6,e1,0f,5e,e0,5f,f1,02,c3,99,fa,6a,6f,45,96,87,31,18,f6,d8,48,13,15,6b,ed,7a,02,1e,da,a5,ec,da,67,07,67,ab,c2,ab,94,a5,07,01,17,54,8e,9c,35,12,55,60,53,02,8b,48,46,06,79,9f,da,6c,f3,51,86,a6,34,16,af,ba,45,ac,77,68,10,0b,c1,ce,f0,0a,c5,20,98,37,42,22,f8,e8,2e,9b,80,52,23,e4,90,f3,01,6e,f9,40,a7,19,c1,9d,59,97,9d,2e,57,06,d2,2a,75,28,c5,5b,aa,0c,a8,94,62,7b,ff,80,c4,6c,01,67,7f,c5,98,61,06,a3,bf,2c,19,32,77,86,7c,1c,42,36,0c,8c,7b,6b,62,01,d7,5a,2c,62,6f,a5,18,1b,19,c3,47,f7,e9,c9,ff,a9,c1,89,31,1d,46,79,2c,35,51,63,4a,f7,66,91,4a,b8,93,f9,40,b9,28,71,29,85,9a,0d,c5,16,c7,7b,ae,b9,4a,cc,50,d3,39,37,54,5f,31,fc,1b,fc,5a,76,23,e5,49,6b,c0,bd,11,1b,a2,b0,ca,36,55,07,54,40,0a,08,c8,49,ca,09,ea,29,73,02,80,d5,30,4c,e6,00,ae,0a,a4,2f,b8,57,4c,2d,75,58,05,8b,b6,c5,55,be,22,e6,48,63,75,c5,aa,f9,8d,e9,4c,8a,51,84,b7,96,b0,2e,14,58,18,99,48,29,de,36,7d,be,e5,8e,01,7c,9d,0f,71,2f,f8,84,7d,6e,d2,88,d0,67,b2,5b,e3,bb,63,bc,53,fa,80,88,29,26,c5,22,54,42,d8,21,82,5d,6a,4a,b1,b7,a2,8f,48,68,c2,c7,2f,79,fa,8d,25,f4,85,7b,47,a5,46,a5,af,3e,88,37,06,f5,41,40,71,02,89,f9,3e,1d,46,43,3e,34,5e,7e,39,4b,f2,25,c8,30,33,59,45,8a,c2,95,4b,94,37,53,b3,f0,03,73,21,d5,36,51,fc,6f,e9,1c,69,dd,a6,47,2b,39,5e,fc,35,c4,a8,84,7e,34,32,b3,76,f5,23,1b,67,07,e7,c8,b3,99,82,36,ec,9b,c7,a3,2c,80,de,09,46,c9,c9,22,cd,19,b9,a7,e0,c8,cb,a3,20,f7,f4,3a,7c,48,44,86,db,96,a4,b0,9d,bd,63,84,54,d9,c6,09,16,03,1e,45,89,65,da,57,2d,b3,33,0a,7b,1a,98,5a,cc,e5,08,ba,8c,35,7e,fe,4a,36,fa,f4,58,c3,fb,c8,e1,66,14,9e,91,b6,02,88,6f,fe,a9,6e,41,cb,63,6d,92,cc,65,c4,a9,9e,69,38,75,ec,6f,0f,89,c7,65,aa,2a,a1,8b,90,ad,e5,83,4b,b2,3e,68,60,84,be,a0,98,32,e6,47,53,41,c4,35,49,ca,10,16,c5,52,53,47,2b,ac,4f,44,1b,6a,04,7a,ab,95,7b,ae,20,b6,cc,be,21,9d,66,0a,c9,b0,a4,0b,2c,36,48,f2,6c,70,1d,56,11,b5,54,0a,7a,75,41,f1,fc,94,97,fc,5f,1c,53,c2,80,d5,64,6e,f9,c4,32,a1,69,fb,f6,b4,d7,63,a9,86,b8,7a,70,30,2f,45,22,47,19,1a,0e,54,b6,c4,58,81,b8,36,c1,2f,b5,67,6e,07,05,7b,68,37,aa,a8,73,46,c7,1b,1c,d8,34,44,83,83,b8,d7,07,76,5a,e9,32,38,30,9f,17,78,b0,c0,11,73,43,f2,c9,10,b1,cc,59,e9,59,f8,44,60,a0,1b,9c,98,f2,43,2e,5b,5a,b1,6a,07,e7,9a,73,79,56,cf,73,05,9a,a6,6a,79,a5,49,1f,c0,97,22,fe,89,e2,e4,66,6d,9a,18,ac,5e,d1,41,ba,dc,99,b4,01,0d,b0,43,11,3e,be,a0,50,d6,39,8a,4f,58,7d,cc,30,ba,c0,e6,41,51,ab,4e" + [4589]="11,ed,06,81,04,28,4e,85,ac,80,07,2c,4d,65,e1,21,0b,bb,ef,c5,1b,a6,0e,34,8b,9f,4b,c7,2a,3a,7b,dd,46,85,32,47,c4,00,dd,17,4b,7b,e6,18,fd,b5,77,bd,0e,90,8d,fe,4c,75,e0,b1,ca,68,d1,6b,cd,ce,7c,06,91,c2,f5,97,9d,3c,3c,46,e4,07,64,96,3a,8b,fd,dc,92,cb,f1,b8,56,7d,76,1f,bd,db,c7,af,3b,de,b9,74,75,13,3c,10,6f,ee,12,c4,68,60,39,4b,6b,cd,4d,5b,6f,55,03,5a,bc,70,40,78,15,9e,74,81,9a,68,b2,4c,4c,40,ce,02,32,5a,d7,89,10,48,e4,63,f9,f2,bc,e8,d6,0c,80,db,24,2f,27,2a,9d,29,22,55,a2,b7,c1,bb,92,a4,b9,a5,32,42,cf,41,e1,09,55,0b,68,21,c1,07,50,6c,0a,8b,cc,18,db,bb,7a,9f,91,4c,de,72,53,c4,5a,7e,17,10,c8,ed,34,16,11,9b,2b,a0,10,84,1b,48,60,bf,17,42,3f,84,56,0b,d1,19,55,3c,56,ea,83,26,f4,e8,a6,82,6a,7d,c0,49,c3,5b,b6,36,89,d0,8f,1f,b5,3b,d1,52,34,cd,c3,3f,8a,f8,04,b7,68,84,df,e8,75,f8,9b,23,65,c7,2f,05,aa,cd,ea,48,28,6e,54,57,44,99,76,c1,68,6a,c8,3b,6c,18,1c,50,54,c5,ba,96,71,ac,d8,0a,00,8d,41,0e,f3,41,c2,9f,8b,21,4a,ec,af,d7,64,5a,29,37,54,5a,a2,11,f7,ba,60,04,b6,b7,77,0c,bf,6f,30,ac,dd,00,3f,de,53,23,f3,a9,9e,de,c1,6e,ad,4a,00,9f,da,6d,a4,73,4d,57,83,a3,2d,5a,32,d2,76,3b,85,b2,5a,b8,89,5e,93,79,8b,aa,24,8e,a3,5c,16,d6,21,0f,15,08,c9,19,0c,6f,6d,fa,b9,00,4d,69,43,43,29,34,3c,99,77,2a,29,ef,d7,1c,fb,02,a2,4c,41,90,07,d5,78,03,0c,74,e4,03,7f,bc,d2,61,f4,da,aa,b2,89,5f,23,0a,9f,73,a4,ac,a3,e2,bf,1c,23,4c,c4,95,42,8e,44,18,4a,92,0f,f5,13,89,07,12,a7,8d,11,4b,43,07,7a,62,eb,cf,25,49,ce,73,11,c1,b0,f3,c2,4d,24,1e,94,69,30,19,c1,ba,57,66,72,d9,52,b5,1a,35,4e,af,f6,9c,85,26,80,73,92,22,1c,54,90,3d,67,01,11,01,2f,4c,7c,57,06,c8,6f,bb,87,14,88,d1,2f,4b,a9,92,4b,57,ce,59,c3,76,db,b6,71,6e,27,9c,d8,60,52,07,77,0c,10,c9,6e,32,74,bc,d6,75,c7,77,80,81,5f,6a,a9,f0,c2,42,8c,79,83,db,75,15,68,1c,1d,78,59,96,7b,82,98,0f,74,49,ef,c0,b4,82,d7,c0,cd,a3,27,4d,ac,18,cd,bb,38,43,ac,04,70,73,6c,f3,d1,80,d1,88,28,c2,83,0e,54,89,61,01,8b,81,b0,27,45,46,1c,b8,11,81,23,45,b9,12,4c,a4,06,85,00,3e,75,0c,0c,1a,d6,99,d0,79,cf,2d,a0,00,94,09,34,e5,d9,1c,80,08,ca,71,3c,03,df,12,02,c8,77,92,9f,4b,7d,cf,3c,75,08,c2,16,39,73,b8,d1,ab,6a,bb,05,32,35,2a,70,b4,d7,03,4c,74,76,3e,eb,ac,f7,c5,70,4f,18,62,3a,55,86,0b,6c,13,82,45,c0,33,b5,2c,57,36,5a,1b,a7,7b,32,b3,4b,89,78,c2,d9,04,ca,66,f5,2b,32,26,c1,c0,76,a5,87,93,2f,0d,b9,6f,1a,c2,a4,48,32,c9,b4,98,98,b4,c2,4a,cf,74,ae,b6,fb,9f,ff,5c,c2,c7,66,47,35,89,9d,32,02,79,34,aa,c7,f7,44,a3,cb,f8,7a,dc,b6,66,21,51,93,d4,e4,c0,3f,f7,0f,e9,56,57,84,b9,81,3b,d3,8d,ea,73,40,45,22,34,e2,cc,c5,8b,b3,b3,b6,4b,cf,71,14,61,a5,31,36,5f,c6,64,de,19,0a,67,7c,0c,df,90,16,b0,78,0b,b3,88,54,80,ea,5e,6b,eb,44,c5,bb,4d,ea,11,1c,52,b6,39,8d,72,1b,ac,02,cf,bc,36,6b,9d,a9,5b,db,87,3d,72,66,20,20,5c,6f,43,86,1f,aa,3c,95,90,0c,60,e2,86,c4,57,57,21,b6,47,33,40,a2,4d,c5,70,50,8d,11,0a,ce,77,2b,f3,70,39,64,42,81,49,18,c1,ae,79,0d,43,55,01,99,bb,55,7a,5a,19,20,a7,a6,6c,75,6a,39,cc,87,4b,73,61,a4,9c,13,c3,d1,25,a3,51,39,b9,8b,a0,82,2c,2f,67,db,b9,de,65,34,eb,8a,3d,56,6a,7e,23,32,91,d4,86,70,30,11,03,e9,54,3b,87,bc,47,7d,eb,17,b1,b5,84,c0,10,59,50,f5,24,08,e6,59,0b,28,b9,c8,7c,3a,ad,e1,b8,28,cc,28,52,a6,b2,1f,1b,17,30,28,10,aa,b9,06,13,55,86,41,35,7b,98,20,10,94,65,2e,7a,42,09,d2,f4,62,b2,b5,39,6c,c8,88,99,f4,0f,bf,69,03,5a,63,79,05,b4,19,4b,72,43,ba,26,14,44,6a,70,dc,82,2f,32,47,68,28,91,87,30,87,70,4b,93,1c,75,9a,28,fb,a8,ac,cf,95,2e,5e,89,4f,1b,0b,31,72,77,0a,6b,f0,0b,41,a1,45,fb,65,5a,09,6c,54,7a,c7,00,ef,e9,97,6f,2c,a1,82,47,50,7e,3a,1b,41,56,99,15,97,a0,71,50,c1,77,9b,bc,d8,bb,9c,3a,43,90,c1,ea,4e,10,88,41,61,31,33,60,01,30,44,f1,37,e0,ca,88,fa,14,45,d5,d5,8e,20,a5,6e,53,62,77,93,13,8b,ea,cb,63,f7,05,25,cd,2c,a0,81,33,a3,6e,d0,7e,07,c1,98,fc,19,87,47,5a,a5,6e,cb,7b,47,f1,ae,ac,f4,bc,e4,30,a1,0e,36,4c,0e,04,76,5b,08,a9,10,d7,c7,ac,67,0b,0b,88,a5,09,03,54,ef,e7,18,ab,47,69,18,74,af,06,11,43,4b,a1,73,bd,66,7b,e7,15,8c,16,d6,43,cb,6a,2c,a0,32,c2,e0,46,95,81,f0,cb,49,b4,1e,4b,5a,0a,6f,c8,4e,d7,3b,47,93,08,8e,c2,78,3b,95,d6,02,b4,5c,8d,ac,b9,a6,ac,16,50,1a,8b,63,34,20,4d,bc,2b,23,9f,cb,a1,de,8c,15,95,98,cf,50,e7,30,f4,1b,3f,2f,a8,1d,cf,c5,5c,19,84,35,9e,1b,21,ef,95,4d,58,49,6a,5a,50,1b,c6,20,47,b6,78,3e,1e,59,3d,df,91,63,75,4b,c6,dd,58,b4,1e,12,2a,58,16,8d,44,68,8f,40,db,1d,c7,34,02,aa,3a,43,c4,f1,44,a7,47,c7,37,82,0b,05,31,c7,a8,a6,71,74,58,89,1e,f9,b9,78,67,c5,ef,b2,b8,fb,14,22,f2,ac,8e,c3,73,a2,f8,c2,5a,42,e3,33,8f,fc,9d,33,6a,ac,d2,67,43,8e,a2,44,5b,30,0d,74,f2,8a,d1,82,84,c5,11,a7,80,ca,b3,ab,5c,11,97,b9,92,68,82,46,3b,34,53,15,62,bb,b2,86,14,1b,68,90,a0,0a,c5,a4,e7,34,38,95,4d,66,61,3e,6c,6a,91,d8,44,a6,9a,85,b9,9f,d3,82,65,c1,8a,4d,11,75,3c,86,0b,b5,1b,25,ab,e0,7f,9c,7c,cd,ff,1b,29,8e,dc,15,63,25,ba,be,40,84,ae,11,b9,fa,09,17,36,f0,21,47,11,9d,fc,3c,8b,6e,08,22,eb,c5,a7,25,c3,86,9d,c1,a3,a0,4c,00,d5,66,3f,d5,d0,be,8b,59,09,d8,3c,1b,a8,a0,b0,8a,c1,16,5c,94,1d,50,42,b9,b0,95,3e,22,26,b2,45,89,b1,b9,b6,bd,b3,33,75,e9,69,6b,d6,11,28,cd,61,47,cc,c8,28,60,99,42,a1,c7,b7,f9,2a,61,f7,fb,12,91,99,71,94,1b,8c,69,c5,67,25,b6,50,12,e1,6d,ed,f9,3b,bb,f0,57,e9,e5,13,8d,d8,46,9f,4e,dc,8c,06,fd,b1,67,f4,66,fe,e8,06,79,97,ee,fd,07,aa,26,90,86,f2,1a,c4,9d,c5,f5,33,6a,ca,59" +[25497]="63,99,04,c0,15,45,8a,33,c6,16,72,fb,44,02,c9,c1,42,63,5d,2e,d0,30,a8,9b,a8,84,19,33,bf,23,10,ec,05,67,68,d9,12,0e,88,07,0a,39,85,85,6c,52,6e,24,70,69,38,aa,a1,a7,10,41,b5,4f,5a,99,2f,38,dc,07,0e,ab,a8,a2,44,40,49,7c,47,5d,3a,bd,7c,ea,af,63,11,47,5f,d2,8c,ef,81,b1,4d,e1,57,40,e6,32,0c,49,5d,43,63,62,7e,a8,49,71,7a,85,ea,00,9f,42,54,85,71,97,16,0e,43,35,4b,d1,26,2c,73,c8,cc,f2,43,63,c3,66,17,b4,7c,a7,d2,66,98,b4,60,e8,0b,a7,94,49,75,03,e3,4f,bf,69,ba,e7,67,68,89,c2,8a,4b,24,a2,42,f4,74,92,e3,44,85,bc,9e,da,e3,40,e9,e4,bd,4c,02,20,88,dc,67,2d,25,ba,4f,0a,4b,7c,dc,1f,96,d3,6a,01,86,5b,ad,75,b2,23,c5,c7,39,10,35,34,59,6e,23,fc,c9,cd,c0,17,e0,16,79,4b,04,82,70,d9,1f,62,a4,36,67,d3,00,a9,db,a4,25,09,21,38,f0,0b,d1,17,6a,3d,d5,22,51,1a,a6,0b,97,23,c7,67,32,0b,7c,a0,b3,a7,0d,06,49,01,52,69,9c,4f,f5,37,dd,0c,a7,bc,d0,c2,72,d5,6f,9c,26,aa,c3,ca,0d,84,6b,27,40,f8,1b,e3,55,bb,e4,f0,9a,15,52,2f,a3,da,06,45,c2,10,6e,a3,2a,07,87,61,89,1c,39,b1,52,26,2a,80,a5,a6,4b,2c,b3,3c,40,d7,42,0d,8b,67,90,d6,c6,49,09,a7,6e,d3,f2,c2,ac,b5,46,75,2c,8c,0d,03,0a,d8,f2,b7,19,a7,a4,84,f4,90,48,34,29,aa,00,28,e8,01,bf,2b,02,94,57,e2,62,36,59,61,d2,c0,0e,1c,69,04,57,b0,ba,c3,2c,a4,aa,e7,46,03,45,c9,a1,b6,58,13,ba,3f,ea,80,b3,ef,dc,5c,7f,28,8b,c6,92,18,db,81,0b,43,e1,07,65,b4,be,96,33,58,f0,31,c0,8c,29,9c,4c,d9,a8,95,91,58,e1,e7,61,b5,b5,23,0e,fa,39,62,63,38,3e,d4,3c,df,c1,09,81,ea,4f,0b,a2,7c,e3,08,1f,e6,e1,0f,5e,e0,5f,f1,02,c3,99,fa,6a,6f,45,96,87,31,18,f6,d8,48,13,15,6b,ed,7a,02,1e,da,a5,ec,da,67,07,67,ab,c2,ab,94,a5,07,01,17,54,8e,9c,35,12,55,60,53,02,8b,48,46,06,79,9f,da,6c,f3,51,86,a6,34,16,af,ba,45,ac,77,68,10,0b,c1,ce,f0,0a,c5,20,98,37,42,22,f8,e8,2e,9b,80,52,23,e4,90,f3,01,6e,f9,40,a7,19,c1,9d,59,97,9d,2e,57,06,d2,2a,75,28,c5,5b,aa,0c,a8,94,62,7b,ff,80,c4,6c,01,67,7f,c5,98,61,06,a3,bf,2c,19,32,77,86,7c,1c,42,36,0c,8c,7b,6b,62,01,d7,5a,2c,62,6f,a5,18,1b,19,c3,47,f7,e9,c9,ff,a9,c1,89,31,1d,46,79,2c,35,51,63,4a,f7,66,91,4a,b8,93,f9,40,b9,28,71,29,85,9a,0d,c5,16,c7,7b,ae,b9,4a,cc,50,d3,39,37,54,5f,31,fc,1b,fc,5a,76,23,e5,49,6b,c0,bd,11,1b,a2,b0,ca,36,55,07,54,40,0a,08,c8,49,ca,09,ea,29,73,02,80,d5,30,4c,e6,00,ae,0a,a4,2f,b8,57,4c,2d,75,58,05,8b,b6,c5,55,be,22,e6,48,63,75,c5,aa,f9,8d,e9,4c,8a,51,84,b7,96,b0,2e,14,58,18,99,48,29,de,36,7d,be,e5,8e,01,7c,9d,0f,71,2f,f8,84,7d,6e,d2,88,d0,67,b2,5b,e3,bb,63,bc,53,fa,80,88,29,26,c5,22,54,42,d8,21,82,5d,6a,4a,b1,b7,a2,8f,48,68,c2,c7,2f,79,fa,8d,25,f4,85,7b,47,a5,46,a5,af,3e,88,37,06,f5,41,40,71,02,89,f9,3e,1d,46,43,3e,34,5e,7e,39,4b,f2,25,c8,30,33,59,45,8a,c2,95,4b,94,37,53,b3,f0,03,73,21,d5,36,51,fc,6f,e9,1c,69,dd,a6,47,2b,39,5e,fc,35,c4,a8,84,7e,34,32,b3,76,f5,23,1b,67,07,e7,c8,b3,99,82,36,ec,9b,c7,a3,2c,80,de,09,46,c9,c9,22,cd,19,b9,a7,e0,c8,cb,a3,20,f7,f4,3a,7c,48,44,86,db,96,a4,b0,9d,bd,63,84,54,d9,c6,09,16,03,1e,45,89,65,da,57,2d,b3,33,0a,7b,1a,98,5a,cc,e5,08,ba,8c,35,7e,fe,4a,36,fa,f4,58,c3,fb,c8,e1,66,14,9e,91,b6,02,88,6f,fe,a9,6e,41,cb,63,6d,92,cc,65,c4,a9,9e,69,38,75,ec,6f,0f,89,c7,65,aa,2a,a1,8b,90,ad,e5,83,4b,b2,3e,68,60,84,be,a0,98,32,e6,47,53,41,c4,35,49,ca,10,16,c5,52,53,47,2b,ac,4f,44,1b,6a,04,7a,ab,95,7b,ae,20,b6,cc,be,21,9d,66,0a,c9,b0,a4,0b,2c,36,48,f2,6c,70,1d,56,11,b5,54,0a,7a,75,41,f1,fc,94,97,fc,5f,1c,53,c2,80,d5,64,6e,f9,c4,32,a1,69,fb,f6,b4,d7,63,a9,86,b8,7a,70,30,2f,45,22,47,19,1a,0e,54,b6,c4,58,81,b8,36,c1,2f,b5,67,6e,07,05,7b,68,37,aa,a8,73,46,c7,1b,1c,d8,34,44,83,83,b8,d7,07,76,5a,e9,32,38,30,9f,17,78,b0,c0,11,73,43,f2,c9,10,b1,cc,59,e9,59,f8,44,60,a0,1b,9c,98,f2,43,2e,5b,5a,b1,6a,07,e7,9a,73,79,56,cf,73,05,9a,a6,6a,79,a5,49,1f,c0,97,22,fe,89,e2,e4,66,6d,9a,18,ac,5e,d1,41,ba,dc,99,b4,01,0d,b0,43,11,3e,be,a0,50,d6,39,8a,4f,58,7d,cc,30,ba,c0,e6,41,51,ab,4e" ) diff --git a/openssl-iana.mapping.html b/openssl-iana.mapping.html index 8b6363d..9e90ce2 100644 --- a/openssl-iana.mapping.html +++ b/openssl-iana.mapping.html @@ -425,6 +425,10 @@ xB9 TLS_RSA_PSK_WITH_NULL_SHA384 [0xc0ae] ECDHE-ECDSA-AES128-CCM8 ECDH AESCCM 128 TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 [0xc0af] ECDHE-ECDSA-AES256-CCM8 ECDH AESCCM 256 TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 + + [0xc0b4] TLS_SHA256_SHA256 ECDH Null 0 TLS_SHA256_SHA256 + [0xc0b5] TLS_SHA384_SHA384 ECDH Null 0 TLS_SHA384_SHA384 + [0xcc13] ECDHE-RSA-CHACHA20-POLY1305-OLD ECDH ChaCha20-Poly1305 TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256_OLD [0xcc14] ECDHE-ECDSA-CHACHA20-POLY1305-OLD ECDH ChaCha20-Poly1305 TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256_OLD diff --git a/t/00_testssl_help.t b/t/00_testssl_help.t index bedcb8c..b979fa8 100755 --- a/t/00_testssl_help.t +++ b/t/00_testssl_help.t @@ -24,10 +24,10 @@ printf "\n%s\n", "Testing whether just calling \"./testssl.sh\" produces no erro my $info = stat($prg); my $retMode = $info->mode; -is($retMode & 0400, 0400, "Checking \"./testssl.sh\" for read permission"); +is($retMode & 0400, 0400, "Checking \"./testssl.sh\" for read permission"); $tests++; -is($retMode & 0100, 0100, "Checking \"./testssl.sh\" for execute permission"); +is($retMode & 0100, 0100, "Checking \"./testssl.sh\" for execute permission"); $tests++; $fileout = `timeout 10 bash $prg 2>&1`; @@ -55,7 +55,7 @@ $out=`grep -E "$debug_regexp" $prg`; unlike($out, qr/$debug_regexp/, "Debug RegEx"); $tests++; -printf "\n"; +printf "\n\n"; done_testing($tests); diff --git a/t/05_ca_hashes_up_to_date.t b/t/05_ca_hashes_up_to_date.t index 434b7a0..7124e5f 100755 --- a/t/05_ca_hashes_up_to_date.t +++ b/t/05_ca_hashes_up_to_date.t @@ -6,7 +6,7 @@ use Test::More; printf "\n%s\n", "Testing whether CA certificates are newer their SPKI hashes \"~/etc/ca_hashes.txt\" ..."; my $newer_bundles=`find etc/*.pem -newer etc/ca_hashes.txt`; -is($newer_bundles,"","If there's an output with a *.pem file run \"~/utils/create_ca_hashes.sh\""); +is($newer_bundles,"","Checking if there's an output with a *.pem file run \"~/utils/create_ca_hashes.sh\""); printf "\n"; done_testing; diff --git a/t/32_isHTML_valid.t b/t/32_isHTML_valid.t index 84db98d..afb5d64 100755 --- a/t/32_isHTML_valid.t +++ b/t/32_isHTML_valid.t @@ -46,15 +46,16 @@ $edited_html =~ s/>/>/g; $edited_html =~ s/"/"/g; $edited_html =~ s/'/'/g; -cmp_ok($edited_html, "eq", $out, "HTML file matches terminal output"); -$tests++; - $diff = diff \$edited_html, \$out; -printf "\n%s\n", "$diff"; + +cmp_ok($edited_html, "eq", $out, "Checking if HTML file matches terminal output") or + diag ("\n%s\n", "$diff"); + +$tests++; #2 -printf "\n%s\n", " .. running again $prg against \"$uri\", now with --debug 4 to create HTML output (may take another ~2 minutes)"; +printf "%s\n", " .. running again $prg against \"$uri\", now with --debug 4 to create HTML output (may take another ~2 minutes)"; # Redirect stderr to /dev/null in order to avoid some unexplained "date: invalid date" error messages $out = `TERM_WIDTH=120 $prg $check2run --debug 4 $uri 2> /dev/null`; $debughtml = `cat $htmlfile`; @@ -79,15 +80,14 @@ $debughtml =~ s/.*built: .*\n//g; $debughtml =~ s/.*Using bash .*\n//g; # is whole line: s/.* .*\n//g; -cmp_ok($debughtml, "eq", $html, "HTML file created with --debug 4 matches HTML file created without --debug"); +$diff = diff \$debughtml, \$html; + +cmp_ok($debughtml, "eq", $html, "Checking if HTML file created with --debug 4 matches HTML file created without --debug") or + diag ("\n%s\n", "$diff"); $tests++; -$diff = diff \$debughtml, \$html; -printf "\n%s\n", "$diff"; - - -printf "\n"; +printf "\n\n"; done_testing($tests); diff --git a/t/51_badssl.com.t b/t/51_badssl.com.t index 40b6e91..db734e4 100755 --- a/t/51_badssl.com.t +++ b/t/51_badssl.com.t @@ -17,7 +17,7 @@ pass("Running testssl.sh against badssl.com to create a baseline (may take 2~3 m my $okout = `./testssl.sh -S -e --freak --logjam --drown --rc4 --sweet32 --breach --winshock --crime --jsonfile tmp.json --color 0 badssl.com`; my $okjson = json('tmp.json'); unlink 'tmp.json'; -cmp_ok(@$okjson,'>',10,"We have more then 10 findings"); $tests++; +cmp_ok(@$okjson,'>',10,"We should have more then 10 findings"); $tests++; # Expiration pass("Running testssl against expired.badssl.com"); $tests++; @@ -35,7 +35,7 @@ foreach my $f ( @$json ) { last; } } -is($found,1,"We had a finding for this in the JSON output"); $tests++; +is($found,1,"We should have a finding for this in the JSON output"); $tests++; # Self signed and not-expired pass("Running testssl against self-signed.badssl.com"); $tests++; @@ -52,7 +52,7 @@ foreach my $f ( @$json ) { last; } } -is($found,1,"We had a finding for this in the JSON output"); $tests++; +is($found,1,"We should a finding for this in the JSON output"); $tests++; like($out, qr/Chain of trust.*?NOT ok.*\(self signed\)/,"Chain of trust should fail because of self signed"); $tests++; $found = 0; @@ -64,7 +64,7 @@ foreach my $f ( @$json ) { last; } } -is($found,1,"We had a finding for this in the JSON output"); $tests++; +is($found,1,"We should have a finding for this in the JSON output"); $tests++; like($okout, qr/Chain of trust[^\n]*?Ok/,"Chain of trust should be ok"); $tests++; $found = 0; @@ -77,7 +77,7 @@ foreach my $f ( @$okjson ) { last; } } -is($found,1,"We had a finding for this in the JSON output"); $tests++; +is($found,1,"We should have a finding for this in the JSON output"); $tests++; # Wrong host #pass("Running testssl against wrong.host.badssl.com"); $tests++; @@ -111,7 +111,7 @@ foreach my $f ( @$json ) { last; } } -is($found,1,"We had a finding for this in the JSON output"); $tests++; +is($found,1,"We should have a finding for this in the JSON output"); $tests++; # TODO: RSA 8192 diff --git a/t/61_diff_testsslsh.t b/t/61_diff_testsslsh.t index f4070b1..18c3bfb 100755 --- a/t/61_diff_testsslsh.t +++ b/t/61_diff_testsslsh.t @@ -3,11 +3,10 @@ # Baseline diff test against testssl.sh (csv output) # # We don't use a full run yet and only the certificate section. -# There we would need to blacklist at least: +# There we would need to blacklist more, like: # cert_serialNumber, cert_fingerprintSHA1, cert_fingerprintSHA256, cert # cert_expirationStatus, cert_notBefore, cert_notAfter, cert_caIssuers, intermediate_cert # -# help is appreciated here use strict; use Test::More; @@ -16,55 +15,54 @@ use Text::Diff; my $tests = 0; my $prg="./testssl.sh"; -my $master_socket_csv="./t/baseline_data/default_testssl.csvfile"; -my $socket_csv="tmp.csv"; -my $check2run="-p -s -P --fs -h -U -c -q --ip=one --color 0 --csvfile $socket_csv"; -#my $check2run="-p --color 0 --csvfile $socket_csv"; +my $baseline_csv="./t/baseline_data/default_testssl.csvfile"; +my $cat_csv="tmp.csv"; +my $check2run="-p -s -P --fs -h -U -c -q --ip=one --color 0 --csvfile $cat_csv"; my $uri="testssl.sh"; my $diff=""; die "Unable to open $prg" unless -f $prg; -die "Unable to open $master_socket_csv" unless -f $master_socket_csv; - +die "Unable to open $baseline_csv" unless -f $baseline_csv; # Provide proper start conditions -unlink "tmp.csv"; +unlink $cat_csv; -# Title -printf "\n%s\n", "Diff unit test IPv4 against \"$uri\""; +my @args=("$prg", "$check2run", "$uri", "2>&1"); #1 run -`$prg $check2run $uri 2>&1`; +printf "\n%s\n", "Diff unit test (IPv4) against \"$uri\""; +printf "@args\n"; +system("@args") == 0 + or die ("FAILED: \"@args\" "); -$diff = diff $socket_csv, $master_socket_csv; - -$socket_csv=`cat tmp.csv`; -$master_socket_csv=`cat $master_socket_csv`; +$cat_csv=`cat $cat_csv`; +$baseline_csv=`cat $baseline_csv`; # Filter for changes that are allowed to occur -$socket_csv=~ s/HTTP_clock_skew.*\n//g; -$master_socket_csv=~ s/HTTP_clock_skew.*\n//g; - -# DROWN -$socket_csv=~ s/censys.io.*\n//g; -$master_socket_csv=~ s/censys.io.*\n//g; +$cat_csv =~ s/HTTP_clock_skew.*\n//g; +$baseline_csv =~ s/HTTP_clock_skew.*\n//g; # HTTP time -$socket_csv=~ s/HTTP_headerTime.*\n//g; -$master_socket_csv=~ s/HTTP_headerTime.*\n//g; +$cat_csv =~ s/HTTP_headerTime.*\n//g; +$baseline_csv =~ s/HTTP_headerTime.*\n//g; -# Compare the differences to the master file -- and print differences if there were detected. +# DROWN +$cat_csv =~ s/censys.io.*\n//g; +$baseline_csv =~ s/censys.io.*\n//g; + +$diff = diff \$cat_csv, \$baseline_csv; + +# Compare the differences to the baseline file -- and print differences if there were detected. # -cmp_ok($socket_csv, "eq", $master_socket_csv, "Check whether CSV output matches master file from $uri") or +ok($cat_csv eq $baseline_csv, "Check whether CSV output matches baseline file from $uri") or diag ("\n%s\n", "$diff"); -$tests++; - unlink "tmp.csv"; +$tests++; done_testing($tests); printf "\n"; -# vim:ts=5:sw=5:expandtab +# vim:ts=5:sw=5:expandtab diff --git a/t/baseline_data/default_testssl.csvfile b/t/baseline_data/default_testssl.csvfile index 28118ba..bb91a05 100644 --- a/t/baseline_data/default_testssl.csvfile +++ b/t/baseline_data/default_testssl.csvfile @@ -70,7 +70,7 @@ "FS_TLS13_sig_algs","testssl.sh/81.169.166.184","443","INFO","RSA-PSS-RSAE+SHA256 RSA-PSS-RSAE+SHA384 RSA-PSS-RSAE+SHA512","","" "HTTP_status_code","testssl.sh/81.169.166.184","443","INFO","200 OK ('/')","","" "HTTP_clock_skew","testssl.sh/81.169.166.184","443","INFO","0 seconds from localtime","","" -"HTTP_headerTime","testssl.sh/81.169.166.184","443","INFO","1654006271","","" +"HTTP_headerTime","testssl.sh/81.169.166.184","443","INFO","1737570310","","" "HSTS_time","testssl.sh/81.169.166.184","443","OK","362 days (=31337000 seconds) > 15552000 seconds","","" "HSTS_subdomains","testssl.sh/81.169.166.184","443","INFO","only for this domain","","" "HSTS_preload","testssl.sh/81.169.166.184","443","INFO","domain is NOT marked for preloading","","" @@ -81,6 +81,8 @@ "X-Frame-Options","testssl.sh/81.169.166.184","443","OK","DENY","","" "X-Content-Type-Options","testssl.sh/81.169.166.184","443","OK","nosniff","","" "Content-Security-Policy","testssl.sh/81.169.166.184","443","OK","script-src 'unsafe-inline'; style-src 'unsafe-inline' 'self'; object-src 'self'; base-uri 'none'; form-action 'none'; img-src 'self' ; default-src 'self'; frame-ancestors 'self'; upgrade-insecure-requests;","","" +"Cross-Origin-Opener-Policy","testssl.sh/81.169.166.184","443","INFO","same-origin-allow-popups","","" +"Cross-Origin-Resource-Policy","testssl.sh/81.169.166.184","443","INFO","same-site","","" "banner_reverseproxy","testssl.sh/81.169.166.184","443","INFO","--","","CWE-200" "heartbleed","testssl.sh/81.169.166.184","443","OK","not vulnerable, no heartbeat extension","CVE-2014-0160","CWE-119" "CCS","testssl.sh/81.169.166.184","443","OK","not vulnerable","CVE-2014-0224","CWE-310" @@ -95,7 +97,7 @@ "SWEET32","testssl.sh/81.169.166.184","443","OK","not vulnerable","CVE-2016-2183 CVE-2016-6329","CWE-327" "FREAK","testssl.sh/81.169.166.184","443","OK","not vulnerable","CVE-2015-0204","CWE-310" "DROWN","testssl.sh/81.169.166.184","443","OK","not vulnerable on this host and port","CVE-2016-0800 CVE-2016-0703","CWE-310" -"DROWN_hint","testssl.sh/81.169.166.184","443","INFO","Make sure you don't use this certificate elsewhere with SSLv2 enabled services, see https://search.censys.io/search?resource=hosts&virtual_hosts=INCLUDE&q=31B44391529821C6A77F3C78B02D716A07F99B8FDB342BF5A78F263C25375968","CVE-2016-0800 CVE-2016-0703","CWE-310" +"DROWN_hint","testssl.sh/81.169.166.184","443","INFO","Make sure you don't use this certificate elsewhere with SSLv2 enabled services, see https://search.censys.io/search?resource=hosts&virtual_hosts=INCLUDE&q=5B4BC205947AED96ECB1879F2668F7F69D696C143BA8D1C69DBB4DC873C92AE9","CVE-2016-0800 CVE-2016-0703","CWE-310" "LOGJAM","testssl.sh/81.169.166.184","443","OK","not vulnerable, no DH EXPORT ciphers,","CVE-2015-4000","CWE-310" "LOGJAM-common_primes","testssl.sh/81.169.166.184","443","OK","--","CVE-2015-4000","CWE-310" "BEAST_CBC_TLS1","testssl.sh/81.169.166.184","443","MEDIUM","ECDHE-RSA-AES256-SHA ECDHE-RSA-AES128-SHA DHE-RSA-CAMELLIA256-SHA DHE-RSA-CAMELLIA128-SHA DHE-RSA-AES256-SHA DHE-RSA-AES128-SHA AES256-SHA","CVE-2011-3389","CWE-20" diff --git a/testssl.sh b/testssl.sh index cf02a8f..7794353 100755 --- a/testssl.sh +++ b/testssl.sh @@ -7,9 +7,9 @@ # vulnerabilities or features. It may or may be not distributed by your distribution. # 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 -# 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 # Main contributions from David Cooper @@ -399,7 +399,7 @@ RSA_CERT_FINGERPRINT_SHA2="" STARTTLS_PROTOCOL="" 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 -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 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 @@ -454,7 +454,7 @@ declare TLS_CIPHER_AUTH=() declare TLS_CIPHER_ENC=() declare TLS_CIPHER_EXPORT=() declare TLS_CIPHER_OSSL_SUPPORTED=() -declare TLS13_OSSL_CIPHERS="TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_CCM_SHA256:TLS_AES_128_CCM_8_SHA256" +declare TLS13_OSSL_CIPHERS="TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_CCM_SHA256:TLS_AES_128_CCM_8_SHA256:TLS_SHA256_SHA256:TLS_SHA384_SHA384" ########### Some predefinitions: date, sed (we always use tests for binaries and NOT try to determine @@ -582,8 +582,6 @@ tmln_out() { printf -- "%b" "$1\n"; } out() { printf -- "%b" "$1"; html_out "$(html_reserved "$1")"; } outln() { printf -- "%b" "$1\n"; html_out "$(html_reserved "$1")\n"; } -#TODO: Still no shell injection safe but if just run it from the cmd line: that's fine - # Color print functions, see also https://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x329.html tm_liteblue() { [[ "$COLOR" -ge 2 ]] && { "$COLORBLIND" && tm_out "\033[0;32m$1" || tm_out "\033[0;34m$1"; } || tm_out "$1"; tm_off; } # not yet used pr_liteblue() { tm_liteblue "$1"; [[ "$COLOR" -ge 2 ]] && { "$COLORBLIND" && html_out "$(html_reserved "$1")" || html_out "$(html_reserved "$1")"; } || html_out "$(html_reserved "$1")"; } @@ -617,7 +615,7 @@ tmln_cyan() { tm_cyan "$1"; tmln_out; } pr_cyan() { tm_cyan "$1"; [[ "$COLOR" -ge 2 ]] && html_out "$(html_reserved "$1")" || html_out "$(html_reserved "$1")"; } 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 .. prln_litegrey() { pr_litegrey "$1"; outln; } pr_litegrey() { tm_litegrey "$1"; [[ "$COLOR" -ne 0 ]] && html_out "$(html_reserved "$1")" || html_out "$(html_reserved "$1")"; } @@ -972,9 +970,14 @@ join_by() { actually_supported_osslciphers() { local ciphers="$1" local tls13_ciphers="$TLS13_OSSL_CIPHERS" + local cipher tls13_supported_ciphers="" local options="$3 " [[ "$2" != ALL ]] && tls13_ciphers="$2" + for cipher in ${tls13_ciphers//:/ }; do + [[ "$TLS13_OSSL_CIPHERS" =~ $cipher ]] && tls13_supported_ciphers+=":$cipher" + done + tls13_ciphers="${tls13_supported_ciphers:1}" "$HAS_SECLEVEL" && [[ -n "$ciphers" ]] && ciphers="@SECLEVEL=0:$1" # With OpenSSL 1.0.2 the only way to exclude SSLv2 ciphers is to use the -tls1 option. # However, with newer versions of OpenSSL, the -tls1 option excludes TLSv1.2 ciphers. @@ -1001,7 +1004,10 @@ strip_inconsistent_ciphers() { local -i proto=0x$1 local cipherlist="$2" - [[ $proto -lt 4 ]] && cipherlist="${cipherlist//, 13,0[0-9a-fA-F]/}" + if [[ $proto -lt 4 ]]; then + cipherlist="${cipherlist//, 13,0[0-9a-fA-F]/}" + cipherlist="${cipherlist//, [cC]0,[bB][45]/}" + fi if [[ $proto -lt 3 ]]; then cipherlist="${cipherlist//, 00,3[b-fB-F]/}" cipherlist="${cipherlist//, 00,40/}" @@ -1029,7 +1035,7 @@ get_cipher() { # 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 # 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). if [[ "$server_hello" =~ Cipher\ *:\ ([A-Z0-9]+-[A-Za-z0-9\-]+|TLS_[A-Za-z0-9_]+|SSL_[A-Za-z0-9_]+) ]]; then @@ -1363,13 +1369,17 @@ fileout_insert_warning() { [[ "$CMDLINE=" =~ -iL ]] && return 0 # Note we still have the message on screen + in HTML which is not as optimal as it could be - if "$do_pretty_json" && "$JSONHEADER"; then + # See #2599. The "clientProblem" wrapper should only be added if fileout_insert_warning() + # is called before fileout_banner(). The only instance in which this function is called + # after fileout_banner() is in the case of a TLS 1.3 only server when $OPENSSL does not + # support TLS 1.3. + if "$do_pretty_json" && "$JSONHEADER" && ! "$TLS13_ONLY"; then echo -e " \"clientProblem${CLIENT_PROB_NO}\" : [" >>"$JSONFILE" CLIENT_PROB_NO=$((CLIENT_PROB_NO + 1)) FIRST_FINDING=true # make sure we don't have a comma here fi fileout "$1" "$2" "$3" - if "$do_pretty_json"; then + if "$do_pretty_json" && ! "$TLS13_ONLY"; then if "$JSONHEADER"; then echo -e "\n ]," >>"$JSONFILE" else @@ -2035,7 +2045,7 @@ check_revocation_ocsp() { local stapled_response="$2" local jsonID="$3" local tmpfile="" - local -i success + local -i success=1 local response="" local host_header="" @@ -2052,9 +2062,20 @@ check_revocation_ocsp() { tmpfile=$TEMPDIR/${NODE}-${NODEIP}.${uri##*\/} || exit $ERR_FCREATE if [[ -n "$stapled_response" ]]; then hex2binary "$stapled_response" > "$TEMPDIR/stapled_ocsp_response.dd" - $OPENSSL ocsp -no_nonce -respin "$TEMPDIR/stapled_ocsp_response.dd" \ - -issuer $TEMPDIR/hostcert_issuer.pem -verify_other $TEMPDIR/intermediatecerts.pem \ - -CAfile <(cat $ADDTL_CA_FILES "$GOOD_CA_BUNDLE") -cert $HOSTCERT -text &> "$tmpfile" + if [[ "$stapled_response" =~ 06052[bB]0[eE]03021[aA] ]]; then + # Response appears to use SHA-1 in CertID + $OPENSSL ocsp -no_nonce -respin "$TEMPDIR/stapled_ocsp_response.dd" \ + -issuer $TEMPDIR/hostcert_issuer.pem -verify_other $TEMPDIR/intermediatecerts.pem \ + -CAfile <(cat $ADDTL_CA_FILES "$GOOD_CA_BUNDLE") -cert $HOSTCERT -text &> "$tmpfile" + success=$? + fi + if [[ $success -ne 0 ]] && [[ "$stapled_response" =~ 0609608648016503040201 ]]; then + # Response appears to use SHA-256 in CertID + $OPENSSL ocsp -sha256 -no_nonce -respin "$TEMPDIR/stapled_ocsp_response.dd" \ + -issuer $TEMPDIR/hostcert_issuer.pem -verify_other $TEMPDIR/intermediatecerts.pem \ + -CAfile <(cat $ADDTL_CA_FILES "$GOOD_CA_BUNDLE") -cert $HOSTCERT -text &> "$tmpfile" + success=$? + fi else host_header=${uri##http://} host_header=${host_header%%/*} @@ -2069,8 +2090,9 @@ check_revocation_ocsp() { $OPENSSL ocsp -no_nonce ${host_header} -url "$uri" \ -issuer $TEMPDIR/hostcert_issuer.pem -verify_other $TEMPDIR/intermediatecerts.pem \ -CAfile <(cat $ADDTL_CA_FILES "$GOOD_CA_BUNDLE") -cert $HOSTCERT -text &> "$tmpfile" + success=$? fi - if [[ $? -eq 0 ]] && grep -Fq "Response verify OK" "$tmpfile"; then + if [[ $success -eq 0 ]] && grep -Fq "Response verify OK" "$tmpfile"; then response="$(grep -F "$HOSTCERT: " "$tmpfile")" response="${response#$HOSTCERT: }" response="${response%\.}" @@ -2220,6 +2242,7 @@ string_to_asciihex() { s_client_options() { local options=" $1" local ciphers="notpresent" tls13_ciphers="notpresent" + local cipher tls13_supported_ciphers="" # Extract the TLSv1.3 ciphers and the non-TLSv1.3 ciphers if [[ " $options " =~ \ -cipher\ ]]; then @@ -2236,6 +2259,10 @@ s_client_options() { tls13_ciphers="${tls13_ciphers##\'}" tls13_ciphers="${tls13_ciphers%%\'}" [[ "$tls13_ciphers" == ALL ]] && tls13_ciphers="$TLS13_OSSL_CIPHERS" + for cipher in ${tls13_ciphers//:/ }; do + [[ "$TLS13_OSSL_CIPHERS" =~ $cipher ]] && tls13_supported_ciphers+=":$cipher" + done + tls13_ciphers="${tls13_supported_ciphers:1}" fi # Don't include the -servername option for an SSLv2 or SSLv3 ClientHello. @@ -2288,6 +2315,13 @@ s_client_options() { if "$HAS_SECLEVEL"; then if [[ "$ciphers" == notpresent ]]; then [[ ! " $options " =~ \ -tls1_3\ ]] && ciphers="@SECLEVEL=0:ALL:COMPLEMENTOFALL" + if "$HAS_CIPHERSUITES" && [[ "$tls13_ciphers" == notpresent ]] && \ + [[ ! " $options " =~ \ -ssl[2|3]\ ]] && \ + [[ ! " $options " =~ \ -tls1\ ]] && \ + [[ ! " $options " =~ \ -tls1_[1|2]\ ]] && \ + [[ ! " $options " =~ \ -no_tls1_3\ ]]; then + tls13_ciphers="$TLS13_OSSL_CIPHERS" + fi elif [[ -n "$ciphers" ]]; then ciphers="@SECLEVEL=0:$ciphers" fi @@ -3091,11 +3125,13 @@ emphasize_stuff_in_headers(){ -e "s/X-Powered-By/${yellow}X-Powered-By${off}/g" \ -e "s/X-UA-Compatible/${yellow}X-UA-Compatible${off}/g" \ -e "s/Link/${yellow}Link${off}/g" \ + -e "s/X-DNS-Prefetch-Control/${yellow}X-DNS-Prefetch-Control${off}/g" \ -e "s/X-Rack-Cache/${yellow}X-Rack-Cache${off}/g" \ -e "s/X-Runtime/${yellow}X-Runtime${off}/g" \ -e "s/X-Pingback/${yellow}X-Pingback${off}/g" \ -e "s/X-Permitted-Cross-Domain-Policies/${yellow}X-Permitted-Cross-Domain-Policies${off}/g" \ -e "s/X-AspNet-Version/${yellow}X-AspNet-Version${off}/g" \ + -e "s/X-AspNetMvc-Version/${yellow}X-AspNetMvc-Version${off}/g" \ -e "s/x-note/${yellow}x-note${off}/g" \ -e "s/x-global-transaction-id/${yellow}x-global-transaction-id${off}/g" \ -e "s/X-Global-Transaction-ID/${yellow}X-Global-Transaction-ID${off}/g" \ @@ -3105,7 +3141,7 @@ emphasize_stuff_in_headers(){ if "$do_html"; then if [[ $COLOR -ge 2 ]]; then html_out "$(tm_out "$1" | sed -e 's/\&/\&/g' \ - -e 's//\>/g' -e 's/"/\"/g' -e "s/'/\'/g" \ + -e 's//\>/g' -e 's/\"/\"/g' -e "s/\'/\'/g" \ -e "s/\([0-9]\)/${html_brown}\1${html_off}/g" \ -e "s/Unix/${html_yellow}Unix${html_off}/g" \ -e "s/Debian/${html_yellow}Debian${html_off}/g" \ @@ -3141,18 +3177,19 @@ emphasize_stuff_in_headers(){ -e "s/Link/${html_yellow}Link${html_off}/g" \ -e "s/X-Runtime/${html_yellow}X-Runtime${html_off}/g" \ -e "s/X-Rack-Cache/${html_yellow}X-Rack-Cache${html_off}/g" \ + -e "s/X-DNS-Prefetch-Control/${html_yellow}X-DNS-Prefetch-Control${html_off}/g" \ -e "s/X-Pingback/${html_yellow}X-Pingback${html_off}/g" \ -e "s/X-Permitted-Cross-Domain-Policies/${html_yellow}X-Permitted-Cross-Domain-Policies${html_off}/g" \ - -e "s/X-AspNet-Version/${html_yellow}X-AspNet-Version${html_off}/g")" \ + -e "s/X-AspNet-Version/${html_yellow}X-AspNet-Version${html_off}/g" \ + -e "s/X-AspNetMvc-Version/${html_yellow}X-AspNetMvc-Version${html_off}/g" \ -e "s/x-note/${html_yellow}x-note${html_off}/g" \ -e "s/X-Global-Transaction-ID/${html_yellow}X-Global-Transaction-ID${html_off}/g" \ -e "s/x-global-transaction-id/${html_yellow}x-global-transaction-id${html_off}/g" \ -e "s/Alt-Svc/${html_yellow}Alt-Svc${html_off}/g" \ - -e "s/system-wsgw-management-loopback/${html_yellow}system-wsgw-management-loopback${html_off}/g" -#FIXME: this is double code. The pattern to emphasize would fit better into -# one function. -# Also we need another function like run_other_header as otherwise "Link" "Alt-Svc" will never be found. -# And: I matches case sensitive only which might not detect all banners. (sed ignorecase is not possible w/ BSD sed) + -e "s/system-wsgw-management-loopback/${html_yellow}system-wsgw-management-loopback${html_off}/g" \ + )" +#FIXME: this is double code. The pattern to emphasize headers should be better in one single function +# And: It matches case sensitive headers only which won't detect all banners. (sed ignorecase is not a/v for OpenBSD sed) else html_out "$(html_reserved "$1")" fi @@ -3284,7 +3321,7 @@ sub_f5_bigip_check() { [[ -z "$cookievalue" ]] && break cookievalue=${cookievalue/;/} debugme echo $cookiename : $cookievalue - if grep -Eq '[0-9]{9,10}\.[0-9]{3,5}\.0000' <<< "$cookievalue"; then + if grep -Eq '[0-9]{8,10}\.[0-9]{3,5}\.0000' <<< "$cookievalue"; then ip="$(f5_ip_oldstyle "$cookievalue")" port="$(f5_port_decode $cookievalue)" out "${spaces}F5 cookie (default IPv4 pool member): "; pr_italic "$cookiename "; prln_svrty_medium "${ip}:${port}" @@ -3399,16 +3436,22 @@ run_security_headers() { pr_bold " Security headers " # X-XSS-Protection is useless and at worst harmful, see https://news.ycombinator.com/item?id=20472947 + # Expect-CT is deprecated, see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Expect-CT for header_and_svrty in "X-Frame-Options OK" \ "X-Content-Type-Options OK" \ "Content-Security-Policy OK" \ - "X-Content-Security-Policy OK" \ - "X-WebKit-CSP OK" \ + "X-Content-Security-Policy INFO" \ + "X-WebKit-CSP INFO" \ "Content-Security-Policy-Report-Only OK" \ - "Expect-CT OK" \ + "Expect-CT INFO" \ "Permissions-Policy OK" \ + "Cross-Origin-Opener-Policy INFO" \ + "Cross-Origin-Resource-Policy INFO" \ + "Cross-Origin-Embedder-Policy INFO" \ "X-XSS-Protection INFO" \ "Access-Control-Allow-Origin INFO" \ + "Access-Control-Allow-Credentials INFO" \ + "Permissions-Policy INFO" \ "Upgrade INFO" \ "X-Served-By INFO" \ "Referrer-Policy INFO" \ @@ -3989,7 +4032,7 @@ run_cipher_match(){ ! "${ciphers_found2[i]}" && ciphers_to_test+=", ${hexcode2[i]}" done [[ -z "$ciphers_to_test" ]] && break - [[ "$proto" == 04 ]] && [[ ! "$ciphers_to_test" =~ ,\ 13,[0-9a-f][0-9a-f] ]] && break + [[ "$proto" == 04 ]] && [[ ! "$ciphers_to_test" =~ ,\ 13,[0-9a-f][0-9a-f] ]] && [[ ! "$ciphers_to_test" =~ ,\ [cC]0,[bB][45] ]] && break ciphers_to_test="$(strip_inconsistent_ciphers "$proto" "$ciphers_to_test")" [[ -z "$ciphers_to_test" ]] && break if "$SHOW_SIGALGO"; then @@ -4264,7 +4307,7 @@ run_allciphers() { ! "${ciphers_found2[i]}" && ciphers_to_test+=", ${hexcode2[i]}" done [[ -z "$ciphers_to_test" ]] && break - [[ "$proto" == 04 ]] && [[ ! "$ciphers_to_test" =~ ,\ 13,[0-9a-f][0-9a-f] ]] && break + [[ "$proto" == 04 ]] && [[ ! "$ciphers_to_test" =~ ,\ 13,[0-9a-f][0-9a-f] ]] && [[ ! "$ciphers_to_test" =~ ,\ [cC]0,[bB][45] ]] && break ciphers_to_test="$(strip_inconsistent_ciphers "$proto" "$ciphers_to_test")" [[ -z "$ciphers_to_test" ]] && break if "$SHOW_SIGALGO"; then @@ -4380,9 +4423,9 @@ ciphers_by_strength() { if { "$using_sockets" || "${TLS_CIPHER_OSSL_SUPPORTED[i]}"; }; then if [[ ${#hexc} -eq 9 ]] && [[ "$proto" != -ssl2 ]]; then if [[ "$proto" == -tls1_3 ]]; then - [[ "${hexc:2:2}" == 13 ]] && nr_ciphers+=1 + [[ "${TLS_CIPHER_SSLVERS[i]}" == TLSv1.3 ]] && nr_ciphers+=1 elif [[ "$proto" == -tls1_2 ]]; then - [[ "${hexc:2:2}" != 13 ]] && nr_ciphers+=1 + [[ "${TLS_CIPHER_SSLVERS[i]}" != TLSv1.3 ]] && nr_ciphers+=1 elif [[ ! "${TLS_CIPHER_RFC_NAME[i]}" =~ SHA256 ]] && [[ ! "${TLS_CIPHER_RFC_NAME[i]}" =~ SHA384 ]] && \ [[ "${TLS_CIPHER_RFC_NAME[i]}" != *_CCM ]] && [[ "${TLS_CIPHER_RFC_NAME[i]}" != *_CCM_8 ]]; then nr_ciphers+=1 @@ -4890,9 +4933,9 @@ client_simulation_sockets() { data+=", ${clienthello:i:2}" done # 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 - # 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 # Extract list of cipher suites from SSLv3 or later ClientHello sid_len=4*$(hex2dec "${data:174:2}") @@ -5250,7 +5293,9 @@ run_client_simulation() { fi if [[ -n "$what_dh" ]]; then [[ -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" else pr_dh_quality "$bits" "$(printf -- "%-12s" "$bits bit $what_dh") $curve" @@ -5487,7 +5532,8 @@ run_protocols() { fileout "$jsonID" "OK" "not offered" add_proto_offered ssl2 no ;; - 4) out "likely "; pr_svrty_best "not offered (OK), " + 4) # STARTTLS problem + out "likely "; pr_svrty_best "not offered (OK), " fileout "$jsonID" "OK" "likely not offered" add_proto_offered ssl2 no pr_warning "received 4xx/5xx after STARTTLS handshake"; outln "$debug_recomm" @@ -5665,7 +5711,7 @@ run_protocols() { pr_warning "TLS downgraded to STARTTLS plaintext"; outln fileout "$jsonID" "WARN" "TLS downgraded to STARTTLS plaintext" ;; - 4) out "likely not offered, " + 4) out "likely not offered, " # STARTTLS problem fileout "$jsonID" "INFO" "likely not offered" add_proto_offered tls1 no pr_warning "received 4xx/5xx after STARTTLS handshake"; outln "$debug_recomm" @@ -5750,8 +5796,8 @@ run_protocols() { pr_warning "TLS downgraded to STARTTLS plaintext"; outln fileout "$jsonID" "WARN" "TLS downgraded to STARTTLS plaintext" ;; - 4) out "likely not offered, " - fileout "$jsonID" "INFO" "not offered" + 4) out "likely not offered, " # STARTTLS problem + fileout "$jsonID" "INFO" "likely not offered" add_proto_offered tls1_1 no pr_warning "received 4xx/5xx after STARTTLS handshake"; outln "$debug_recomm" fileout "$jsonID" "WARN" "received 4xx/5xx after STARTTLS handshake${debug_recomm}" @@ -6022,8 +6068,8 @@ run_protocols() { pr_warning "TLS downgraded to STARTTLS plaintext"; outln fileout "$jsonID" "WARN" "TLS downgraded to STARTTLS plaintext" ;; - 4) out "likely not offered, " - fileout "$jsonID" "INFO" "not offered" + 4) out "likely not offered, " # STARTTLS problem + fileout "$jsonID" "INFO" "likely not offered" add_proto_offered tls1_3 no pr_warning "received 4xx/5xx after STARTTLS handshake"; outln "$debug_recomm" fileout "$jsonID" "WARN" "received 4xx/5xx after STARTTLS handshake${debug_recomm}" @@ -6066,10 +6112,15 @@ listciphers() { local -i ret local debugname="" local ciphers="$1" - local tls13_ciphers="$TLS13_OSSL_CIPHERS" + local tls13_ciphers="$TLS13_OSSL_CIPHERS" cipher tls13_supported_ciphers="" local options="$3 " [[ "$2" != ALL ]] && tls13_ciphers="$2" + for cipher in ${tls13_ciphers//:/ }; do + [[ "$TLS13_OSSL_CIPHERS" =~ $cipher ]] && tls13_supported_ciphers+=":$cipher" + done + tls13_ciphers="${tls13_supported_ciphers:1}" + "$HAS_SECLEVEL" && [[ -n "$ciphers" ]] && ciphers="@SECLEVEL=0:$1" ! "$HAS_TLS1" && options="${options//-tls1 /}" if "$HAS_CIPHERSUITES"; then @@ -6138,7 +6189,7 @@ sub_cipherlists() { for proto in 04 03 02 01 00; do # If $cipherlist doesn't contain any TLSv1.3 ciphers, then there is # no reason to try a TLSv1.3 ClientHello. - [[ "$proto" == 04 ]] && [[ ! "$6" =~ 13,0 ]] && continue + [[ "$proto" == 04 ]] && [[ ! "$6" =~ 13,0 ]] && [[ ! "$6" =~ [cC]0,[bB][45] ]] && continue [[ $(has_server_protocol "$proto") -eq 1 ]] && continue cipherlist="$(strip_inconsistent_ciphers "$proto" ", $6")" cipherlist="${cipherlist:2}" @@ -6277,13 +6328,14 @@ run_cipherlists() { local hexc hexcode strength local -i i local -i ret=0 - local ossl_null_ciphers null_ciphers sslv2_null_ciphers + local ossl_null_ciphers ossl_null_ciphersuites null_ciphers sslv2_null_ciphers local ossl_anon_ciphers anon_ciphers sslv2_anon_ciphers local ossl_exp_ciphers exp_ciphers sslv2_exp_ciphers local ossl_low_ciphers low_ciphers sslv2_low_ciphers local ossl_tdes_ciphers tdes_ciphers sslv2_tdes_ciphers local ossl_obsoleted_ciphers obsoleted_ciphers - local strong_ciphers + local ossl_good_ciphers good_ciphers + local ossl_strong_ciphers ossl_strong_ciphersuites strong_ciphers local cwe="CWE-327" local cwe2="CWE-310" local cve="" @@ -6297,7 +6349,8 @@ run_cipherlists() { # conversion 2 byte ciphers via: echo "$@" | sed -e 's/[[:xdigit:]]\{2\},/0x&/g' -e 's/, /\n/g' | while read ci; do grep -wi $ci etc/cipher-mapping.txt; done ossl_null_ciphers='NULL:eNULL' - null_ciphers="c0,10, c0,06, c0,15, c0,0b, c0,01, c0,3b, c0,3a, c0,39, 00,b9, 00,b8, 00,b5, 00,b4, 00,2e, 00,2d, 00,b1, 00,b0, 00,2c, 00,3b, 00,02, 00,01, 00,82, 00,83, ff,87, 00,ff" + ossl_null_ciphersuites="TLS_SHA256_SHA256:TLS_SHA384_SHA384" + null_ciphers="c0,10, c0,06, c0,15, c0,0b, c0,01, c0,3b, c0,3a, c0,39, 00,b9, 00,b8, 00,b5, 00,b4, 00,2e, 00,2d, 00,b1, 00,b0, 00,2c, 00,3b, 00,02, 00,01, 00,82, 00,83, c0,b4, c0,b5, ff,87, 00,ff" sslv2_null_ciphers="FF,80,10, 00,00,00" ossl_anon_ciphers='aNULL:ADH' @@ -6333,6 +6386,7 @@ run_cipherlists() { good_ciphers="00,9C, 00,9D, 00,A0, 00,A1, 00,A4, 00,A5, 00,A8, 00,A9, 00,AC, 00,AD, C0,2D, C0,2E, C0,31, C0,32, C0,50, C0,51, C0,54, C0,55, C0,58, C0,59, C0,5E, C0,5F, C0,62, C0,63, C0,6A, C0,6B, C0,6E, C0,6F, C0,7A, C0,7B, C0,7E, C0,7F, C0,82, C0,83, C0,88, C0,89, C0,8C, C0,8D, C0,8E, C0,8F, C0,92, C0,93, C0,9C, C0,9D, C0,A0, C0,A1, C0,A4, C0,A5, C0,A8, C0,A9, CC,AB, CC,AE, 00,FF" ossl_strong_ciphers='AESGCM:CHACHA20:CamelliaGCM:AESCCM:ARIAGCM:!kPSK:!kRSAPSK:!kRSA:!kDH:!kECDH:!aNULL' + ossl_strong_ciphersuites="TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_CCM_SHA256:TLS_AES_128_CCM_8_SHA256" # grep AEAD etc/cipher-mapping.txt | grep -E 'TLS_ECDHE|TLS_DHE|TLS_PSK_DHE|TLSv1.3' strong_ciphers="00,9E, 00,9F, 00,A2, 00,A3, 00,AA, 00,AB, 13,01, 13,02, 13,03, 13,04, 13,05, 16,B7, 16,B8, 16,B9, 16,BA, C0,2B, C0,2C, C0,2F, C0,30, C0,52, C0,53, C0,56, C0,57, C0,5C, C0,5D, C0,60, C0,61, C0,6C, C0,6D, C0,7C, C0,7D, C0,80, C0,81, C0,86, C0,87, C0,8A, C0,8B, C0,90, C0,91, C0,9E, C0,9F, C0,A2, C0,A3, C0,A6, C0,A7, C0,AA, C0,AB, C0,AC, C0,AD, C0,AE, C0,AF, CC,13, CC,14, CC,15, CC,A8, CC,A9, CC,AA, CC,AC, CC,AD, 00,FF" @@ -6347,7 +6401,7 @@ run_cipherlists() { # argv[9]: CVE # argv[10]: CWE - sub_cipherlists "$ossl_null_ciphers" "" " NULL ciphers (no encryption) " 1 "NULL" "$null_ciphers" "$sslv2_null_ciphers" "$using_sockets" "$cve" "$cwe" + sub_cipherlists "$ossl_null_ciphers" "$ossl_null_ciphersuites" " NULL ciphers (no encryption) " 1 "NULL" "$null_ciphers" "$sslv2_null_ciphers" "$using_sockets" "$cve" "$cwe" ret=$? sub_cipherlists "$ossl_anon_ciphers" "" " Anonymous NULL Ciphers (no authentication) " 1 "aNULL" "$anon_ciphers" "$sslv2_anon_ciphers" "$using_sockets" "$cve" "$cwe" ret=$((ret + $?)) @@ -6361,7 +6415,7 @@ run_cipherlists() { ret=$((ret + $?)) sub_cipherlists "$ossl_good_ciphers" "" " Strong encryption (AEAD ciphers) with no FS " 6 "STRONG_NOFS" "$good_ciphers" "" "$using_sockets" "" "" ret=$((ret + $?)) - sub_cipherlists "$ossl_strong_ciphers" 'ALL' " Forward Secrecy strong encryption (AEAD ciphers)" 7 "STRONG_FS" "$strong_ciphers" "" "$using_sockets" "" "" + sub_cipherlists "$ossl_strong_ciphers" "$ossl_strong_ciphersuites" " Forward Secrecy strong encryption (AEAD ciphers)" 7 "STRONG_FS" "$strong_ciphers" "" "$using_sockets" "" "" ret=$((ret + $?)) outln @@ -6430,7 +6484,7 @@ pr_ecdh_quality() { elif [[ "$bits" -le 163 ]]; then pr_svrty_medium "$string" 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 out "$string" elif [[ "$bits" -gt 224 ]]; then @@ -6479,6 +6533,30 @@ pr_ecdh_curve_quality() { 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: # 0 = $1 is empty # 1 = pr_svrty_critical, 2 = pr_svrty_high, 3 = pr_svrty_medium, 4 = pr_svrty_low @@ -6502,7 +6580,7 @@ get_cipher_quality() { # We have an OpenSSL name and can't convert it to the RFC name which is rarely # the case, see "prepare_arrays()" and "./etc/cipher-mapping.txt" case "$cipher" in - *NULL*|EXP*|ADH*|AECDH*|*anon*) + *NULL*|EXP*|ADH*|AECDH*|*anon*|TLS_SHA*) return 1 ;; *RC4*|*RC2*|*MD5|*M1) @@ -6544,7 +6622,7 @@ get_cipher_quality() { # Now we look at the RFC cipher names. The sequence matters - as above. case "$cipher" in - *NULL*|*EXP*|*_DES40_*|*anon*) + *NULL*|*EXP*|*_DES40_*|*anon*|TLS_SHA*) return 1 ;; *RC4*|*RC2*|*MD5|*MD5_1) @@ -6631,6 +6709,10 @@ read_dhtype_from_file() { kx="Kx=${temp%%,*}" [[ "$kx" == "Kx=X25519" ]] && 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" return 0 } @@ -6869,7 +6951,7 @@ run_server_preference() { "c0,2c, c0,30, 00,9f, cc,a9, cc,a8, cc,aa, c0,2b, c0,2f, 00,9a, 00,96, 00,9e, c0,24, c0,28, 00,6b, c0,23, c0,27, 00,67, c0,0a, c0,14, 00,39, c0,09, c0,13, 00,33, 00,9d, 00,9c, 13,02, - 13,03, 13,01, 13,04, 13,05, 00,3d, 00,3c, 00,35, 00,2f, 00,ff" \ + 13,03, 13,01, 13,04, 13,05, c0,b4, c0,b5, 00,3d, 00,3c, 00,35, 00,2f, 00,ff" \ "ephemeralkey" sclient_success=$? if [[ $sclient_success -eq 0 ]]; then @@ -6911,12 +6993,12 @@ run_server_preference() { # Some servers don't have a TLS 1.3 cipher order, see #1163 if [[ "$default_proto" == TLSv1.3 ]]; then - tls_sockets "04" "13,05, 13,04, 13,03, 13,02, 13,01, 00,ff" + tls_sockets "04" "c0,b5, c0,b4, 13,05, 13,04, 13,03, 13,02, 13,01, 00,ff" [[ $? -ne 0 ]] && ret=1 && prln_fixme "something weird happened around line $((LINENO - 1))" cp "$TEMPDIR/$NODEIP.parse_tls_serverhello.txt" $TMPFILE tls13_cipher1=$(get_cipher $TMPFILE) debugme tm_out "TLS 1.3: --> $tls13_cipher1\n" - tls_sockets "04" "13,01, 13,02, 13,03, 13,04, 13,05, 00,ff" + tls_sockets "04" "13,01, 13,02, 13,03, 13,04, 13,05, c0,b4, c0,b5, 00,ff" [[ $? -ne 0 ]] && ret=1 && prln_fixme "something weird happened around line $((LINENO - 1))" cp "$TEMPDIR/$NODEIP.parse_tls_serverhello.txt" $TMPFILE tls13_cipher2=$(get_cipher $TMPFILE) @@ -7303,9 +7385,9 @@ cipher_pref_check() { index[nr_nonossl_ciphers]=$i # Only test ciphers that are relevant to the protocol. if [[ $proto == tls1_3 ]]; then - [[ "${hexc:2:2}" == 13 ]] && nr_nonossl_ciphers+=1 + [[ "${TLS_CIPHER_SSLVERS[i]}" == TLSv1.3 ]] && nr_nonossl_ciphers+=1 elif [[ $proto == tls1_2 ]]; then - [[ "${hexc:2:2}" != 13 ]] && nr_nonossl_ciphers+=1 + [[ "${TLS_CIPHER_SSLVERS[i]}" != TLSv1.3 ]] && nr_nonossl_ciphers+=1 elif [[ ! "${TLS_CIPHER_RFC_NAME[i]}" =~ SHA256 ]] && \ [[ ! "${TLS_CIPHER_RFC_NAME[i]}" =~ SHA384 ]] && \ [[ "${TLS_CIPHER_RFC_NAME[i]}" != *_CCM ]] && \ @@ -7377,9 +7459,9 @@ cipher_pref_check() { hexcode[nr_ciphers]="${hexc:2:2},${hexc:7:2}" rfc_ciph[nr_ciphers]="${TLS_CIPHER_RFC_NAME[i]}" if [[ $proto == tls1_3 ]]; then - [[ "${hexc:2:2}" == 13 ]] && nr_ciphers+=1 + [[ "${TLS_CIPHER_SSLVERS[i]}" == TLSv1.3 ]] && nr_ciphers+=1 elif [[ $proto == tls1_2 ]]; then - [[ "${hexc:2:2}" != 13 ]] && nr_ciphers+=1 + [[ "${TLS_CIPHER_SSLVERS[i]}" != TLSv1.3 ]] && nr_ciphers+=1 elif [[ ! "${TLS_CIPHER_RFC_NAME[i]}" =~ SHA256 ]] && \ [[ ! "${TLS_CIPHER_RFC_NAME[i]}" =~ SHA384 ]] && \ [[ "${TLS_CIPHER_RFC_NAME[i]}" != *_CCM ]] && \ @@ -7396,9 +7478,9 @@ cipher_pref_check() { hexcode[nr_ciphers]="${hexc:2:2},${hexc:7:2}" rfc_ciph[nr_ciphers]="${TLS_CIPHER_RFC_NAME[i]}" if [[ $proto == tls1_3 ]]; then - [[ "${hexc:2:2}" == 13 ]] && nr_ciphers+=1 + [[ "${TLS_CIPHER_SSLVERS[i]}" == TLSv1.3 ]] && nr_ciphers+=1 elif [[ $proto == tls1_2 ]]; then - [[ "${hexc:2:2}" != 13 ]] && nr_ciphers+=1 + [[ "${TLS_CIPHER_SSLVERS[i]}" != TLSv1.3 ]] && nr_ciphers+=1 elif [[ ! "${TLS_CIPHER_RFC_NAME[i]}" =~ SHA256 ]] && \ [[ ! "${TLS_CIPHER_RFC_NAME[i]}" =~ SHA384 ]] && \ [[ "${TLS_CIPHER_RFC_NAME[i]}" != *_CCM ]] && \ @@ -7624,7 +7706,7 @@ determine_trust() { [[ -n $json_postfix ]] && spaces=" " case $OSSL_VER_MAJOR.$OSSL_VER_MINOR in - 1.0.2|1.1.0|1.1.1|2.[1-9].*|3.*) # 2.x is LibreSSL. 2.1.1 was tested to work, below is not sure + 1.0.2|1.1.0|1.1.1|2.[1-9].*|3.*|4.*) # 2.x is LibreSSL. 2.1.1 was tested to work, below is not sure : ;; *) addtl_warning="Your $OPENSSL <= 1.0.2 might be too unreliable to determine trust" @@ -8341,12 +8423,14 @@ wildcard_match() # 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 # 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() { local cert="$1" local servername cns cn dns_sans ip_sans san dercert tag 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 HAS_DNS_SANS=false @@ -8491,10 +8575,16 @@ compare_server_name_to_cert() { fi # 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 while read san; do [[ -n "$san" ]] || continue + is_wildcard "$san" + if [[ $? -eq 0 ]]; then + wildcard_cert=128 + else + continue + fi wildcard_match "$servername" "$san" [[ $? -eq 0 ]] && subret=2 && break done <<< "$dns_sans" @@ -8510,13 +8600,20 @@ compare_server_name_to_cert() { # Check whether the CN matches the servername [[ $(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 # that is an exact match. + is_wildcard "$cn" + if [[ $? -eq 0 ]]; then + wildcard_cert=128 + else + continue + fi wildcard_match "$servername" "$cn" [[ $? -eq 0 ]] && cn_match=8 done <<< "$cns" subret+=$cn_match + subret+=$wildcard_cert return $subret } @@ -8774,7 +8871,7 @@ certificate_transparency() { if [[ $number_of_certificates -gt 1 ]] && ! "$SSL_NATIVE"; then if [[ "$tls_version" == 0304 ]]; then - ciphers=", 13,01, 13,02, 13,03, 13,04, 13,05" + ciphers=", 13,01, 13,02, 13,03, 13,04, 13,05, c0,b4, c0,b5" if [[ "$cipher" == tls1_3_RSA ]]; then extra_extns=", 00,0d,00,10,00,0e,08,04,08,05,08,06,04,01,05,01,06,01,02,01" elif [[ "$cipher" == tls1_3_ECDSA ]]; then @@ -9411,7 +9508,7 @@ certificate_info() { # supported by the client. has_dns_sans=$HAS_DNS_SANS - case $trust_sni in + case $((trust_sni%128)) in 0) trustfinding="certificate does not match supplied URI" set_grade_cap "M" "Domain name mismatch" ;; @@ -9438,10 +9535,10 @@ certificate_info() { ;; esac - if [[ $trust_sni -eq 0 ]]; then + if [[ $((trust_sni%128)) -eq 0 ]]; then pr_svrty_high "$trustfinding" 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 # https://bugs.chromium.org/p/chromium/issues/detail?id=308330 # https://bugzilla.mozilla.org/show_bug.cgi?id=1245280 @@ -9468,17 +9565,17 @@ certificate_info() { # See issue #733. if [[ -z "$sni_used" ]]; then trustfinding_nosni="" - elif [[ $trust_sni -eq $trust_nosni && "$has_dns_sans" == "$has_dns_sans_nosni" ]] || \ - [[ $trust_sni -eq 0 && $trust_nosni -eq 0 ]]; then + elif [[ $((trust_sni%128)) -eq $((trust_nosni%128)) && "$has_dns_sans" == "$has_dns_sans_nosni" ]] || \ + [[ $((trust_sni%128)) -eq 0 && $((trust_nosni%128)) -eq 0 ]]; then trustfinding_nosni=" (same w/o SNI)" - elif [[ $trust_nosni -eq 0 ]]; then - if [[ $trust_sni -eq 4 ]] || [[ $trust_sni -eq 8 ]]; then + elif [[ $((trust_nosni%128)) -eq 0 ]]; then + if [[ $((trust_sni%128)) -eq 4 ]] || [[ $((trust_sni%128)) -eq 8 ]]; then trustfinding_nosni=" (w/o SNI: certificate does not match supplied URI)" else trustfinding_nosni=" (SNI mandatory)" fi - elif [[ $trust_nosni -eq 4 ]] || [[ $trust_nosni -eq 8 ]] || [[ $trust_sni -eq 4 ]] || [[ $trust_sni -eq 8 ]]; then - case $trust_nosni in + 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%128)) in 1) trustfinding_nosni=" (w/o SNI: Ok via SAN)" ;; 2) trustfinding_nosni=" (w/o SNI: Ok via SAN wildcard)" ;; 4) if "$has_dns_sans_nosni"; then @@ -9498,12 +9595,12 @@ certificate_info() { 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)" ;; esac - elif [[ $trust_sni -ne 0 ]]; then + elif [[ $((trust_sni%128)) -ne 0 ]]; then trustfinding_nosni=" (works w/o SNI)" else trustfinding_nosni=" (however, works w/o SNI)" 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" elif [[ $SERVICE == HTTP ]] || "$ASSUME_HTTP"; then prln_svrty_high "$trustfinding_nosni" @@ -9513,7 +9610,7 @@ certificate_info() { 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}" 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" @@ -10119,7 +10216,7 @@ run_server_defaults() { # $NODE being tested or if it has the same subject # (CN and SAN) as other certificates for this host. 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 cn_nosni="$(toupper "$(get_cn_from_cert $HOSTCERT)")" @@ -10452,13 +10549,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_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 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 -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_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 -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 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" "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" "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 192 192 256 128) # 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. - 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_output=("ffdhe2048" "ffdhe3072" "ffdhe4096" "ffdhe6144" "ffdhe8192") local -a supported_curve @@ -10469,7 +10566,7 @@ run_fs() { local rsa_cipher="" ecdsa_cipher="" dss_cipher="" 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 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 len1 len2 curve_found sigalg_found local key_bitstring quality_str @@ -10529,13 +10626,10 @@ run_fs() { sigalg[nr_supported_ciphers]="" ossl_supported[nr_supported_ciphers]=true nr_supported_ciphers+=1 - done < <(actually_supported_osslciphers "$fs_cipher_list" "ALL" "-V") + done < <(actually_supported_osslciphers "$fs_cipher_list" "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_CCM_SHA256:TLS_AES_128_CCM_8_SHA256" "-V") fi - if [[ $(has_server_protocol "tls1_3") -eq 0 ]]; then - # All TLSv1.3 cipher suites offer robust FS. - sclient_success=0 - elif "$using_sockets"; then + if "$using_sockets"; then tls_sockets "04" "${fs_hex_cipher_list:2}, 00,ff" sclient_success=$? [[ $sclient_success -eq 2 ]] && sclient_success=0 @@ -10547,7 +10641,7 @@ run_fs() { fi else debugme echo $nr_supported_ciphers - debugme echo $(actually_supported_osslciphers $fs_cipher_list "ALL") + debugme echo $(actually_supported_osslciphers $fs_cipher_list "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_CCM_SHA256:TLS_AES_128_CCM_8_SHA256") if [[ "$nr_supported_ciphers" -le "$CLIENT_MIN_FS" ]]; then outln prln_local_problem "You only have $nr_supported_ciphers FS ciphers on the client side " @@ -10568,7 +10662,7 @@ run_fs() { curves_list2="${curves_list2// /:}" fi curves_list1="${curves_list1// /:}" - $OPENSSL s_client $(s_client_options "-cipher $fs_cipher_list -ciphersuites ALL $STARTTLS $BUGS -connect $NODEIP:$PORT $PROXY $SNI") >$TMPFILE 2>$ERRFILE $TMPFILE 2>$ERRFILE > $TMPFILE ;; "0103") echo -n "ffdhe6144" >> $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 ;; esac offset=$((offset+4)) @@ -14492,6 +14658,10 @@ parse_tls_serverhello() { 258) dh_bits=4096 ; named_curve_str="ffdhe4096" ;; 259) dh_bits=6144 ; named_curve_str="ffdhe6144" ;; 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="" ;; esac offset=$((extns_offset+20+i)) @@ -14679,9 +14849,9 @@ parse_tls_serverhello() { fi echo "Cipher : $rfc_cipher_suite" >> $TMPFILE 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 - 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 else echo "Server Temp Key: ECDH, $named_curve_str, $dh_bits bits" >> $TMPFILE @@ -14724,9 +14894,9 @@ parse_tls_serverhello() { echo "" fi 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" - 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" else echo " dh_bits: ECDH, $named_curve_str, $dh_bits bits" @@ -14762,7 +14932,7 @@ parse_tls_serverhello() { fi # 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 if [[ -n "$cipherlist" ]]; then tls_cipher_suite="$(tolower "$tls_cipher_suite")" @@ -15515,7 +15685,15 @@ prepare_tls_clienthello() { 00, 01, 00, 02, 00, 03, 00, 0f, 00, 10, 00, 11, 01, 00, 01, 01" elif [[ 0x$tls_low_byte -gt 0x03 ]]; then # 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=" 00,0a, # Type: Supported Groups, see RFC 8446 00,16, 00,14, # lengths @@ -15537,7 +15715,7 @@ prepare_tls_clienthello() { 00,1d, 00,17, 00,18, 00,19, 00,1f, 00,20, 00,21, 01,00, 01,01, 00,1e" # 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 # response MUST be decrypted. elif [[ "$process_full" == all+ ]]; then @@ -15627,7 +15805,7 @@ prepare_tls_clienthello() { # 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 # 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 [[ -n "$all_extensions" ]] && all_extensions+="," all_extensions+="$extn_psk_mode" @@ -16226,7 +16404,12 @@ tls_sockets() { else finished_msg="14000030$(hmac-transcript "-sha384" "$finished_key" "$msg_transcript")" fi - [[ "$cipher" =~ CCM_8 ]] && tag_len=8 || tag_len=16 + case "$cipher" in + TLS_SHA256_SHA256) tag_len=32 ;; + TLS_SHA384_SHA384) tag_len=48 ;; + *CCM_8*) tag_len=8 ;; + *) tag_len=16 ;; + esac aad="170303$(printf "%04X" "$(( ${#finished_msg}/2 + tag_len + 1 ))")" if "$include_headers"; then # The header information was added to additional data in TLSv1.3 draft 25. @@ -16303,7 +16486,12 @@ send_app_data() { read -r tls_version cipher server_key server_iv server_seq client_key client_iv client_seq <<< "$APP_TRAF_KEY_INFO" [[ "${tls_version:0:2}" == 7F ]] && [[ 0x${tls_version:2:2} -lt 25 ]] && include_headers=false - [[ "$cipher" =~ CCM_8 ]] && tag_len=8 || tag_len=16 + case "$cipher" in + TLS_SHA256_SHA256) tag_len=32 ;; + TLS_SHA384_SHA384) tag_len=48 ;; + *CCM_8*) tag_len=8 ;; + *) tag_len=16 ;; + esac aad="170303$(printf "%04X" "$(( ${#plaintext}/2 + tag_len + 1 ))")" if "$include_headers"; then @@ -17084,13 +17272,13 @@ run_renego() { sec_client_renego=1 else # second try in the foreground as we are sure now it won't hang - echo R | $OPENSSL s_client $(s_client_options "$proto $legacycmd $STARTTLS $BUGS -connect $NODEIP:$PORT $PROXY $SNI") >$TMPFILE 2>>$ERRFILE + (echo R; sleep 1) | $OPENSSL s_client $(s_client_options "$proto $legacycmd $STARTTLS $BUGS -connect $NODEIP:$PORT $PROXY $SNI") >$TMPFILE 2>>$ERRFILE sec_client_renego=$? # 0 means client is renegotiating & doesn't return an error --> vuln! # 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 # 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 fi case "$sec_client_renego" in @@ -17899,7 +18087,7 @@ run_tls_fallback_scsv() { elif grep -qa "alert handshake failure" "$TMPFILE"; then pr_svrty_good "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 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\"" @@ -19321,7 +19509,7 @@ run_starttls_injection() { esac uds="$TEMPDIR/uds" - $SOCAT FD:5 UNIX-LISTEN:$uds & + $SOCAT FD:5 UNIX-LISTEN:$uds 2>/dev/null & socat_pid=$! if "$HAS_UDS"; then @@ -20228,8 +20416,8 @@ find_openssl_binary() { $OPENSSL s_client -tls1_3 &1 | grep -aiq "unknown option" || HAS_TLS13=true $OPENSSL s_client -no_ssl2 &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 X25519 2>&1 | grep -aq "not found" || HAS_X25519=true + $OPENSSL genpkey -algorithm X448 2>&1 | grep -Eaq "not found|unsupported" || HAS_X448=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 pkeyutl 2>&1 | grep -q Error || HAS_PKUTIL=true @@ -20504,7 +20692,7 @@ single check as ("$PROG_NAME URI" does everything except -E and -g): -e, --each-cipher checks each local cipher remotely -E, --cipher-per-proto checks those per protocol -s, --std, --categories tests standard cipher categories by strength - -f, --fs, --nsa checks forward secrecy settings + -f, --fs, --forward-secrecy checks forward secrecy settings -p, --protocols checks TLS/SSL protocols (including SPDY/HTTP2) -g, --grease tests several server implementation bugs like GREASE and size limitations -S, --server-defaults displays the server's default picks and certificate info @@ -20769,7 +20957,7 @@ prepare_arrays() { if [[ -n "$ossl_ciph" ]]; then TLS_CIPHER_OSSL_SUPPORTED[i]=true [[ "$ossl_ciph" != ${TLS_CIPHER_OSSL_NAME[i]} ]] && TLS_CIPHER_OSSL_NAME[i]="$ossl_ciph" - [[ "${hexc:2:2}" == 13 ]] && TLS13_OSSL_CIPHERS+=":$ossl_ciph" + [[ "${TLS_CIPHER_SSLVERS[i]}" == TLSv1.3 ]] && TLS13_OSSL_CIPHERS+=":$ossl_ciph" fi fi elif [[ $OSSL_VER_MAJOR -lt 1 ]]; then @@ -21176,7 +21364,7 @@ get_local_a() { check_resolver_bins() { 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 host &> /dev/null && HAS_HOST=true type -p drill &> /dev/null && HAS_DRILL=true @@ -21198,7 +21386,7 @@ check_resolver_bins() { HAS_DIG_NOIDNOUT=true 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 } @@ -21221,7 +21409,7 @@ get_a_record() { echo $1 return 0 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 "$HAS_AVAHIRESOLVE"; then ip4=$(filter_ip4_address $(avahi-resolve -4 -n "$1" 2>/dev/null | awk '{ print $2 }')) @@ -21246,7 +21434,7 @@ get_a_record() { if [[ -z "$ip4" ]] && "$HAS_NSLOOKUP"; then ip4=$(filter_ip4_address $(strip_lf "$(nslookup -querytype=a "$1" 2>/dev/null | awk '/^Name/ { getline; print $NF }')")) 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" } @@ -21259,7 +21447,7 @@ get_aaaa_record() { "$HAS_DIG_NOIDNOUT" && noidnout="+noidnout" [[ "$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 # This saves walking through this. Also it avoids hangs e.g. if you run docker locally without reachable DNS echo "$1" @@ -21293,7 +21481,7 @@ get_aaaa_record() { ip6=$(filter_ip6_address $(strip_lf "$(nslookup -type=aaaa "$1" 2>/dev/null | awk '/'"^${a}"'.*AAAA/ { 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 "$ip6" } @@ -21339,7 +21527,7 @@ get_caa_rr_record() { return 1 # No dig, drill, host, or nslookup --> complaint was elsewhere already 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 if [[ "$raw_caa" =~ \#\ [0-9][0-9] ]]; then @@ -21387,7 +21575,7 @@ get_mx_record() { local 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 if "$HAS_HOST"; then mx="$(host -t MX "$1" 2>/dev/null | awk '/is handled by/ { print $(NF-1), $NF }')" @@ -21414,7 +21602,7 @@ get_txt_record() { local 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 if "$HAS_HOST"; then record="$(host -t TXT "$1" 2>/dev/null | awk -F\" '/descriptive text/ { print $(NF-1) }')" @@ -21515,7 +21703,7 @@ determine_rdns() { [[ "$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 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 "$HAS_AVAHIRESOLVE"; then rDNS=$(avahi-resolve -a $nodeip 2>/dev/null | awk '{ print $2 }') @@ -21532,7 +21720,7 @@ determine_rdns() { 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/\.$//')") 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. # 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 @@ -21928,7 +22116,7 @@ determine_optimal_proto() { >$ERRFILE 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 sclient_supported "$STARTTLS_OPTIMAL_PROTO" || continue $OPENSSL s_client $(s_client_options "$STARTTLS_OPTIMAL_PROTO $BUGS -connect "$NODEIP:$PORT" $PROXY -msg $STARTTLS $SNI") $TMPFILE 2>>$ERRFILE @@ -22933,15 +23121,21 @@ run_rating() { pr_headlineln " Rating (experimental) " outln - [[ -n "$STARTTLS_PROTOCOL" ]] && set_grade_cap "T" "STARTTLS encryption is not mandatory for clients. STARTTLS can only be secured client-side" + [[ -n "$STARTTLS_PROTOCOL" ]] && set_grade_cap "T" "STARTTLS is prone to MITM downgrade attacks. A secure TLS upgrade can only be ensured client-side. As per RFC 8314 you should use implicit TLS rather than STARTTLS. For SMTP (port 25) and SIEVE this is not possible." - # TL;DR: E-mail transfer via port 25 is broken and the amendments suggested so far are duct tape. So please do not expect testssl.sh to shut up. + # TL;DR: STARTTLS connections are inherently insecure. A MITM can always intercept the connection, unless the client checks e.g. the + # certificate accordingly. A secure STARTTLS client is the key but we can't test for it. Especially e-mail transfer via port 25 is broken + # as message delivery is still more important than security. Amendments like DANE and MTA-STS are duct tape and depend on the client. - # Explanation: For other than SMTP you should use TLS as per RFC 8314 . For SMTP however there's this thing named reality: A mail server cannot - # just switch to the mail submission port 587 only and continue to receive mail from everyone. Even if you advertise this via SRV record (RFC 6186). - # For STARTTLS there's no way to tell for testssl.sh whether it is secure. A MitM can always intercept the connection, unless the client checks - # the certificate accordingly (it's getting better but some just don't). TLSA Records/DANE and MTA-STS (RFC-8461) on the server side can help too. - # But as said, it's useless unless the client MTA checks all that which no tool can check. + # Explanation: There are active MitM attacks possible when using STARTTLS like https://github.com/tintinweb/striptls or + # https://github.com/libcrack/starttlsstrip. It depends on the client only whether it can detect such downgrade attack. + # As some SMTP servers are still misconfigured with wrong certificates it's is still common practice for SMTP client MTAs to + # accept those wrong certificates -- delivering e-mails is more important. There is an e-mail submission port 587 but a mail server + # cannot just switch to it and continue to receive mail from everyone. Even if you advertise this via SRV record (RFC 6186). + # TLSA Records/DANE and MTA-STS (RFC-8461) on the server side can help too, + # + # For other than SMTP on port 25 and port 587 and SIEVE (there's no implicit TLS port) you should use implicit TLS as per RFC 8314. + # Instead of port 587 (STARTTLS) implicit TLS on port 465 should be considered. pr_bold " Rating specs"; out " (not complete) "; outln "SSL Labs's 'SSL Server Rating Guide' (version 2009q from 2020-01-30)" pr_bold " Specification documentation "; pr_url "https://github.com/ssllabs/research/wiki/SSL-Server-Rating-Guide" @@ -23127,9 +23321,11 @@ run_rating() { # Pretty print - again, it's just nicer to read for reason in "${sorted_reasons[@]}"; do if [[ $reason_nr -eq 0 ]]; then - pr_bold " Grade cap reasons "; outln "$reason" + pr_bold " Grade cap reasons " + outln "$(out_row_aligned_max_width "$reason" " " $TERM_WIDTH)" else - outln " $reason" + outln "$(out_row_aligned_max_width " $reason" " " $TERM_WIDTH)" + fi ((reason_nr++)) fileout "grade_cap_reason_${reason_nr}" "INFO" "$reason" diff --git a/utils/update_client_sim_data.pl b/utils/update_client_sim_data.pl index 61bf0d1..700f553 100755 --- a/utils/update_client_sim_data.pl +++ b/utils/update_client_sim_data.pl @@ -72,6 +72,10 @@ foreach my $client ( @$ssllabs ) { push @ciphersuites, "TLS_AES_128_CCM_SHA256"; } elsif ( $suite == "4869" ) { push @ciphersuites, "TLS_AES_128_CCM_8_SHA256"; } + elsif ( $suite == "49332" ) { + push @ciphersuites, "TLS_SHA256_SHA256"; } + elsif ( $suite == "49333" ) { + push @ciphersuites, "TLS_SHA384_SHA384"; } elsif ( exists $ciphers{$suite} ) { push @ciphers, $ciphers{$suite}; } elsif ( $suite == "255" ) {