pax_global_header00006660000000000000000000000064145247641640014527gustar00rootroot0000000000000052 comment=e497dfb325d9a47cea916cee7c4b1a753346e2fb sslscan-2.1.2/000077500000000000000000000000001452476416400131775ustar00rootroot00000000000000sslscan-2.1.2/.dockerignore000066400000000000000000000000101452476416400156420ustar00rootroot00000000000000openssl sslscan-2.1.2/.github/000077500000000000000000000000001452476416400145375ustar00rootroot00000000000000sslscan-2.1.2/.github/workflows/000077500000000000000000000000001452476416400165745ustar00rootroot00000000000000sslscan-2.1.2/.github/workflows/ci.yml000066400000000000000000000011611452476416400177110ustar00rootroot00000000000000name: ci on: push jobs: build: runs-on: ubuntu-latest strategy: fail-fast: false matrix: cc: [clang, gcc] steps: - uses: actions/checkout@v2 - name: build with ${{ matrix.cc }} run: | make sslscan make static env: CC: ${{ matrix.cc }} build_mingw: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: install mingw-w64 run: | sudo apt-get update -qq sudo apt-get install -qq mingw-w64 - name: build with mingw-w64 run: | make -f Makefile.mingw sslscan-2.1.2/.gitignore000066400000000000000000000003721452476416400151710ustar00rootroot00000000000000# object files *.o *.obj # compiled binary sslscan sslscan.exe # debian build of openssl openssl-*/ openssl_* libcrypto* libssl* # custom openssl build openssl/ .openssl.is.fresh .openssl_mingw.is.fresh # custom zlib build for Windows zlib_mingw/sslscan-2.1.2/Changelog000066400000000000000000000470671452476416400150270ustar00rootroot00000000000000Changelog ========= Version: 2.1.2 Date : 14/11/2023 Author : rbsec Changes: The following are a list of changes > Fix certificate and cipher enumeration when unsafe renegotiation is required(credit jtesta) Version: 2.1.1 Date : 19/09/2023 Author : rbsec Changes: The following are a list of changes > Work around several dodgy TLS implementations (credit jtesta) Version: 2.1.0 Date : 05/09/2023 Author : rbsec Changes: The following are a list of changes > Build against OpenSSL 3.0 instead of 1.1.0 (credit jtesta) > Improve CPU detection on OSX (tetlowgm) Version: 2.0.16 Date : 08/04/2023 Author : rbsec Changes: The following are a list of changes > Fix incorret detection of TLSv1.3 on Server 2019 (credit jtesta) > Fix incorrect XML certificate output Version: 2.0.15 Date : 03/07/2022 Author : rbsec Changes: The following are a list of changes > Obtain certificate info even if we can't connect properly Version: 2.0.14 Date : 23/06/2022 Author : rbsec Changes: The following are a list of changes > Strip out https:// from lines in a target file Version: 2.0.13 Date : 03/04/2022 Author : rbsec Changes: The following are a list of changes > Fix TLSv1.3 detection against Server 2022 (credit jtesta) Version: 2.0.12 Date : 23/02/2022 Author : rbsec Changes: The following are a list of changes > Add XML element (credit lucacapacci) Version: 2.0.11 Date : 16/12/2021 Author : rbsec Changes: The following are a list of changes > Add --iana-names option to use IANA/RFC cipher names > Improve signature algorithm detection Version: 2.0.10 Date : 27/04/2021 Author : rbsec Changes: The following are a list of changes > Add the --connect-timeout option (credit alkalim) > Fix a typo in output Version: 2.0.9 Date : 24/03/2021 Author : rbsec Changes: The following are a list of changes > Warn on TLSv1.1, as it's now deprecated by RFC 8996 Version: 2.0.8 Date : 12/02/2021 Author : rbsec Changes: The following are a list of changes > Fix a bug with LDAP STARTTLS > Fix certificate detection on some broken servers > Fix missing SCSV Fallback in XML output Version: 2.0.7 Date : 10/02/2021 Author : rbsec Changes: The following are a list of changes > Don't show server signature algorithms by default > Use --show-sigs to display them Version: 2.0.6 Date : 31/10/2020 Author : rbsec Changes: The following are a list of changes > Flag certificates in red if CN is the same as issuer Version: 2.0.5 Date : 24/10/2020 Author : rbsec Changes: The following are a list of changes > Fix --targets not working properly Version: 2.0.4 Date : 13/10/2020 Author : rbsec Changes: The following are a list of changes > Remove the broken HTTP request scanning option (--http) Version: 2.0.3 Date : 11/10/2020 Author : rbsec Changes: The following are a list of changes > Fix the extraneous padding of HTTP responses in XML > Update the HTTP request to HTTP/1.1 > More robust checking the HTTP response is valid > Display "No response" when no HTTP response is returned Version: 2.0.2 Date : 04/10/2020 Author : rbsec Changes: The following are a list of changes > Add element to XML output Version: 2.0.1 Date : 20/09/2020 Author : rbsec Changes: The following are a list of changes > Fix SNI name when using --targets Version: 2.0.0 Date : 22/07/2020 Author : rbsec Changes: The following are a list of changes > Documentation updates Version: 2.0.0-beta6 Date : 02/07/2020 Author : rbsec Changes: The following are a list of changes > Report servers that accept any signature algorithm in the XML Version: 2.0.0-beta5 Date : 30/06/2020 Author : rbsec Changes: The following are a list of changes > Remove the "Signature Algorithm:" text and spacing from the XML. Version: 2.0.0-beta4 Date : 10/06/2020 Author : rbsec Changes: The following are a list of changes > Add a new "" element to the XML output. Version: 2.0.0-beta3 Date : 10/06/2020 Author : rbsec Changes: The following are a list of changes > Fix a few compiler warnings. > Fix a regression where the "strength" attribute was missing. Version: 2.0.0-beta2 Date : 10/05/2020 Author : rbsec Changes: The following are a list of changes > Fix a bug with servers that return incorrect cipher IDs. > Portability improvements. > Fix x86 windows build. Version: 2.0.0-beta1 Date : 29/02/2020 Author : rbsec Changes: The following are a list of changes > Print curve name and key strength for ECC certs > Various documentation updates Version: 2.0.0-alpha2 Date : 29/02/2020 Author : rbsec Changes: The following are a list of changes > Fix compilation on old versions of GCC. > Minor changes to protocol support output. > Strip a trailing slash from the specified target. > Various other minor bugfixes. Version: 2.0.0-alpha1 Date : 22/02/2020 Author : rbsec Changes: The following are a list of changes > Major rewrite of backend scanning code. > Support for additional cipher suites. > Support for TLSv1.3 > Support for SSLv2 and SSLv3 protocol detection regardless of OpenSSL. > Checks for server key exchange groups. > Checks for server signature algorithms. Version: 1.11.13 Date : 24/03/2019 Author : rbsec Changes: The following are a list of changes > Added strength attribute to XML to reflect colouring in stdout Version: 1.11.12 Date : 18/10/2018 Author : rbsec Changes: The following are a list of changes > Enable colours in Windows console output if supported > Include SCSV fallback in XML output > Various bugfixes Version: 1.11.11 Date : 31/12/2017 Author : rbsec Changes: The following are a list of changes > Added -4 and -6 options to force IPv4 and IPv6. > Fix build on Solaris and Windows. > Fix cross-compiling. Version: 1.11.10 Date : 04/05/2017 Author : rbsec Changes: The following are a list of changes > Build against Peter Mosmans' branch of OpenSSL > Support for ChaCha ciphers > NOTE: you will need to run `make clean && make static`. Version: 1.11.9 Date : 09/04/2017 Author : rbsec Changes: The following are a list of changes > Add support for STARTTLS on mysql (--starttls-mysql) > Display SNI information in XML output > Fix some compiler warnings > Mark SHA-1 certificates as weak > Fix build on some platforms Version: 1.11.8 Date : 06/11/2016 Author : rbsec Changes: The following are a list of changes > Support alternate SNI hostnames (--sni=) > Allow building with no support for TLS SCSV Fallback Version: 1.11.7 Date : 13/06/2016 Author : rbsec Changes: The following are a list of changes > Check for TLS Fallback SCSV > Allow xml to be output on stdout (--xml=-) Version: 1.11.6 Date : 09/04/2016 Author : rbsec Changes: The following are a list of changes > Re-eanble support for weak (<1024) DH keys in OpenSSL Version: 1.11.5 Date : 24/03/2016 Author : rbsec Changes: The following are a list of changes > Fix bug in heartbleed check (credit nuxi) > Makefile improvements and fixes for OSX and FreeBSD > Optimize OpenSSL clone > Implement --show-times to display handshake times in milliseconds Version: 1.11.4 Date : 06/03/2016 Author : rbsec Changes: The following are a list of changes > Fix compression detection (credit nuxi) > Added support for PostgreSQL (credit nuxi) Version: 1.11.3 Date : 03/03/2016 Author : rbsec Changes: The following are a list of changes > Properly fix missing SSLv2 EXPORT ciphers by patching OpenSSL Version: 1.11.2 Date : 02/03/2016 Author : rbsec Changes: The following are a list of changes > Makefile improvements > Update OpenSSL from Git when statically building > Use enable-ssl2 and enable-weak-ciphers when building statically Version: 1.11.1 Date : 11/12/2015 Author : rbsec Changes: The following are a list of changes > Show cipher IDs with --show-cipher-ids (credit maurice2k) > Warn when building agsinst system OpenSSL rather than statically > Allow building statically on OSX (experimental) Version: 1.11.0 Date : 24/09/2015 Author : rbsec Changes: The following are a list of changes > Rewrote ciphersuite scanning engine to be much faster > Ciphers are now output in order of server preference > Most secure protocols are scanned first (TLSv1.2 -> SSLv2) > All protocols are tried when trying to obtain the certificate > Obselete --failed and --no-preferred-ciphers options removed > Flag TLSv1.0 ciphers in output > Flag 56 bit ciphers as red, not yellow > Fix building on OpenBSD (credit Stuart Henderson) > Fix incorrect output when server prefers NULL ciphers Version: 1.10.6 Date : 06/08/2015 Author : rbsec Changes: The following are a list of changes > Fix --sleep only working for whole seconds (credit dmke) > Fix compiling against OpenSSL 0.9.8 (credit aclemons) > Flag expired certificates (credit jacktrice) Version: 1.10.5 Date : 07/07/2015 Author : rbsec Changes: The following are a list of changes > Added IRC STARTTLS support (--starttls-irc, credit jkent) > Highlight weak RSA keys in output > Added option to show OCSP status (--ocsp, credit kelbyludwig) > Fix a segfault with certificate parsing Version: 1.10.4 Date : 21/06/2015 Author : rbsec Changes: The following are a list of changes > Display cipher details by default (hide with --no-cipher-details) > Fix scanning multiple targets if one fails (credit shellster) > Fix bug with --no-color and --failed (credit yasulib) > Minor bugfixes to output Version: 1.10.3 Date : 22/05/2015 Author : rbsec Changes: The following are a list of changes > Flag weak DHE keys in --cipher-details > Report DHE key bits in XML > Change ECDHE key bits to "ecdhebits" rather than "dhebits" in XML Version: 1.10.2 Date : 12/05/2015 Author : rbsec Changes: The following are a list of changes > Wrap TLS extensions in CDATA blocks in XML output. > Fix incorrect TLS versions in heartbleed checks Version: 1.10.1 Date : 06/04/2015 Author : rbsec Changes: The following are a list of changes > Fix XML output to use "TLSv1.0" in preferred ciphers, not "TLSv1" > Added --cipher-details option to display EC curves and EDH keys Note that this feature requires OpenSSL >= 1.0.2 > Update static build options to compile against OpenSSL 1.0.2 Version: 1.10.0 Date : 28/02/2015 Author : rbsec Changes: The following are a list of changes > Experimental build support (credit jtesta). > Support XMPP server-to-server connections (--xmpp-server). Version: 1.9.11 Date : 03/02/2015 Author : rbsec Changes: The following are a list of changes > Makefile updates to assist packaging in Kali. > Fix missing static build number when compiling from tarball. Version: 1.9.10 Date : 24/01/2015 Author : rbsec Changes: The following are a list of changes > Display certificate CN, Altnames and Issuer in default output. > Flag certificates where CN == issuer, or CN = * > Highlight GCM ciphersuites as good Version: 1.9.9 Date : 22/01/2015 Author : kyprizel Changes: The following are a list of changes > Added --show-client-cas option to determine trusted CAs for client authentication > Added --no-preferred option to disable any output except specified Version: 1.9.8 Date : 08/12/2014 Author : rbsec Changes: The following are a list of changes > Added --sleep option to pause between request > Only check for heartbleed against specified TLS version > Added --sleep option to pause between request > Fix issues compiling against OpenSSL 0.9.8 > Highlight CBC ciphersuites on SSLv3 (POODLE) > Experimental build support on OSX (credit MikeSchroll) Version: 1.9.7 Date : 26/10/2014 Author : rbsec Changes: The following are a list of changes > Added option for static compilation with OpenSSL (credit dmke) > Added "sslmethod" attribute to Heartbleed XML output (credit dmke) > Split headers into sslscan.h (credit dmke) Version: 1.9.6 Date : 10/10/2014 Author : rbsec Changes: The following are a list of changes > Highlight NULL ciphers in output. > Highlight SSLv3 ciphers. > Added --rdp option to support RDP servers (credit skettler). > Added --timeout option to set socket timeout (default 3s). Version: 1.9.5 Date : 13/09/2014 Author : rbsec Changes: The following are a list of changes > Renamed --get-certificate option to --show-certficate. > Display certificate signing algorithm highlighting weak algorithms. > Display certificate key strength highlighting weak keys. > Bumped XML version to 1.9.5 due to minor changes. Version: 1.9.4 Date : 22/05/2014 Author : rbsec Changes: The following are a list of changes > Check for SSLv2 and SSLv3 ciphers over STARTTLS. Version: 1.9.3 Date : 20/05/2014 Author : rbsec Changes: The following are a list of changes > Fixed broken STARTTLS SMTP check. Version: 1.9.2 Date : 09/04/2014 Author : rbsec Changes: The following are a list of changes > Added check for OpenSSL Heartbleed (CVE-2014-0160). Version: 1.9.1 Date : 06/03/2014 Author : rbsec Changes: The following are a list of changes > Added --tlsall option to only scan TLS ciphersuites. > Scan all TLS versions by default for STARTTLS services. > Added support for IPv6 addresses using square bracket notation [:1]. > Highlight anonymous (ADH and AECDH) ciphers in output. > Added option to disable colour in output (--no-colour). > Removed undocumented -p output option. > Removed old references to titania.co.uk domain. Version: 1.9 Date : 30/12/2013 Author : rbsec Changes: The following are a list of changes > Highlight SSLv2 ciphers > Highlight weak (n <= 40 bit) and medium (40 < n <= 56 bit) ciphers > Highlight RC4 ciphers > Highlight anonymous (ADH) ciphers > Hide certificate information by default > Hide rejected ciphers by default (display with --failed). > Added TLSv1.1 and TLSv1.2 support (merged from twwbond/sslscan). > Compiles if OpenSSL does not support SSLv2 ciphers (merged from digineo/sslscan). > Supports IPv6 hostnames (can be forced with --ipv6). > Check for TLS compression (CRIME, disable with --no-compression) Version: 1.8.4 Date : xx/xx/2010 Author : Jacob Appelbaum Changes: The following are a list of changes > Add demo targets in Makefile > Refactoring of code by Adam Langley > Add SNI patch from Tim Brown > Bug fixes from craSH and Cygwin build improvements Version: 1.8.3 Date : 11/08/2010 Author : Jacob Appelbaum Changes: The following are a list of changes > Improve new protocol setup support for STARTTLS: POP3, IMAP, FTP, and XMPP This modeled after the support found in OpenSSL's s_client > Add verbose option to print more info > Add default ports when a STARTTLS setup flag is called without any port at all Version: 1.8.2 Date : 19/06/2009 Author : Ian Ventura-Whiting (Fizz) Changes: The following are a list of changes since the previous version: > Fixed output with HTML disabled > Fixed XML critical Version: 1.8.1 Date : 25/05/2009 Author : Ian Ventura-Whiting (Fizz) Changes: The following are a list of changes since the previous version: > Fixed some compiler warnings. Version: 1.8.0 Date : 19/05/2009 Author : Ian Ventura-Whiting (Fizz) Thanks : John Nichols Changes: The following are a list of changes since the previous version: > Added SSL implementation workaround option. > Added HTTP connection testing. > Fixed Certification validation XML output. Version: 1.7.1 Date : 20/04/2008 Author : Ian Ventura-Whiting (Fizz) Thanks : Mark Lowe Changes: The following are a list of changes since the previous version: > Added HELO for SMTP checks > Increased read buffer size Version: 1.7 Date : 18/04/2008 Author : Ian Ventura-Whiting (Fizz) Changes: The following are a list of changes since the previous version: > Added STARTTLS SMTP capability > Fixed XML output format bug Version: 1.6 Date : 30/12/2007 Author : Ian Ventura-Whiting (Fizz) Changes: The following are a list of changes since the previous version: > Added man page. > Improved certificate checking > Added Makefile Version: 1.5 Date : 25/09/2007 Author : Ian Ventura-Whiting (Fizz) Changes: The following are a list of changes since the previous version: > Update to the license to make it BINARY compatible with OpenSSL. Its then easier for the packagers. Version: 1.4 Date : 03/09/2007 Author : Ian Ventura-Whiting (Fizz) Changes: The following are a list of changes since the previous version: > Added Server Certificate ouput. > Added support for client certs. > Added support for private keys and password. > Added support for PKCS#12. > Fixed xml output. Version: 1.3 Date : 06/08/2007 Author : Ian Ventura-Whiting (Fizz) Changes: The following are a list of changes since the previous version: > Added XML file output option. > Improved help text. > Added program URL. Version: 1.2 Date : 16/07/2007 Author : Ian Ventura-Whiting (Fizz) Changes: The following are a list of changes since the previous version: > Removed unused variable > Other minor changes. Version: 1.1 Date : 13/07/2007 Author : Ian Ventura-Whiting (Fizz) Changes: The following are a list of changes since the previous version: > Correction in banner text > Host:Port now directly from the command-line. Version: 1.0 Date : 13/07/2007 Author : Ian Ventura-Whiting (Fizz) Notes : Initial version of sslscan sslscan-2.1.2/Dockerfile000066400000000000000000000020761452476416400151760ustar00rootroot00000000000000FROM alpine:latest as builder # Ensure no packages are cached before we try to do an update. RUN apk cache clean 2> /dev/null || exit 0 RUN apk update && apk add gcc make ca-certificates git libc-dev linux-headers openssl perl zlib-dev RUN update-ca-certificates ADD . builddir # Make a static build of sslscan, then strip it of debugging symbols. RUN cd builddir && make static RUN strip --strip-all /builddir/sslscan # Print the output of ldd so we can see what dynamic libraries that sslscan is still dependent upon. RUN echo "ldd output:" && ldd /builddir/sslscan RUN echo "ls -al output:" && ls -al /builddir/sslscan # Start with an empty container for our final build. FROM scratch # Copy over the sslscan executable from the intermediate build container, along with the dynamic libraries it is dependent upon (see output of ldd, above). COPY --from=builder /builddir/sslscan /sslscan COPY --from=builder /lib/libz.so.1 /lib/libz.so.1 COPY --from=builder /lib/ld-musl-x86_64.so.1 /lib/ld-musl-x86_64.so.1 # Drop root privileges. USER 65535:65535 ENTRYPOINT ["/sslscan"] sslscan-2.1.2/INSTALL000066400000000000000000000046411452476416400142350ustar00rootroot00000000000000Requirements: OpenSSL 0.9.8o or better Makefile build: make make install (as root) Manual Build: sslscan can be built manually using the following commands: gcc -lssl -o sslscan sslscan.c clang -lssl -o sslscan sslscan.c ---- There are two ways to build a Windows executable: 1.) By cross-compiling on a Linux build machine using MinGW or Mingw-w64. 2.) By compiling on a Windows build machine using Visual Studio 2013 (other versions may also work, but are untested). If you have a Debian-like Linux machine (such as Ubuntu or Kali), option #1 is BY FAR the easiest. Note that installing Visual Studio and additional tools requires downloading gigabytes of data! In any case, it is necessary to compile OpenSSL to ensure that all protocols and algorithms are enabled (note that some systems that package OpenSSL have some deprecated features such as SSLv2 turned off for safety reasons; we actually need those to test with). Please note that building on Windows (especially x86) is not supported, and you may well encounter issues when trying to do so. Cross-compiling for x86 from Debian Buster (10) is reported to work, but your mileage may vary. I. Cross-compiling from Linux A. Building a 64-bit Windows executable 0.) Install Mingw-w64. On Debian-like systems, this can be done with: apt-get install mingw-w64 1.) Compile sslscan. It will download the OpenSSL sources from GitHub automatically: make -f Makefile.mingw B. Building a 32-bit Windows executable 0.) Install MinGW. On Debian-like systems, this can be done with: apt-get install mingw32 1.) Compile sslscan. It will download the OpenSSL sources from GitHub automatically: make -f Makefile.mingw BUILD_32BIT=1 II. Compiling on Windows using Visual Studio 2013 Express for Windows Desktop A. Install Visual Studio 2013 Express for Windows Desktop: http://go.microsoft.com/?linkid=9832280 B. Install the Windows Driver Kit 8.1: http://go.microsoft.com/fwlink/p/?linkid=393659 C. Install ActivePerl Community Edition: http://www.activestate.com/activeperl/downloads D. In the VS2013 x64 Cross Tools Command Prompt, compile OpenSSL with: perl Configure VC-WIN64A ms\do_win64a nmake -f ms\nt.mak E. Inside the sslscan folder, compile sslscan with: nmake -f Makefile.vs OPENSSL_PATH=path/to/openssl sslscan-2.1.2/LICENSE000066400000000000000000000773311452476416400142170ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS sslscan-2.1.2/Makefile000066400000000000000000000116331452476416400146430ustar00rootroot00000000000000# set gcc as default if CC is not set GIT_VERSION = $(shell git describe --tags --always --dirty=-wip) # Ugly hack to get version if git isn't installed ifeq ($(GIT_VERSION),) GIT_VERSION = $(shell grep -E -o -m 1 "[0-9]+\.[0-9]+\.[0-9]+" Changelog) endif # Detect OS OS := $(shell uname) ARCH := $(shell uname -m) # Handle different version of Make ifeq ($(OS), SunOS) ifndef $(CC) CC=gcc endif ifndef $(PREFIX) PREFIX = /usr endif else CC ?= gcc PREFIX ?= /usr endif SRCS = sslscan.c BINDIR = $(PREFIX)/bin MANDIR = $(PREFIX)/share/man MAN1DIR = $(MANDIR)/man1 WARNINGS = -Wall -Wformat=2 -Wformat-security -Wno-deprecated-declarations DEFINES = -DVERSION=\"$(GIT_VERSION)\" # for dynamic linking LIBS = -lssl -lcrypto ifneq ($(OS), FreeBSD) LIBS += -ldl endif ifeq ($(OS), SunOS) CFLAGS += -m64 LIBS += -lsocket -lnsl endif # Enable checks for buffer overflows, add stack protectors, generate position # independent code, mark the relocation table read-only, and mark the global # offset table read-only. CFLAGS += -D_FORTIFY_SOURCE=2 -fstack-protector-all -fPIE # Don't enable some hardening flags on OS X because it uses an old version of Clang ifneq ($(OS), Darwin) ifneq ($(OS), SunOS) LDFLAGS += -pie -z relro -z now endif endif # Force C11 mode to fix the build on very old version of GCC CFLAGS += -std=gnu11 # for static linking ifeq ($(STATIC_BUILD), TRUE) PWD = $(shell pwd)/openssl LDFLAGS += -L${PWD}/ CFLAGS += -I${PWD}/include/ -I${PWD}/ ifeq ($(OS), Darwin) LIBS = ./openssl/libssl.a ./openssl/libcrypto.a -lz -lpthread else LIBS = -lssl -lcrypto -lz -lpthread endif ifneq ($(OS), FreeBSD) LIBS += -ldl endif ifeq ($(OS), SunOS) LIBS += -lsocket -lnsl endif GIT_VERSION := $(GIT_VERSION)-static else # for dynamic linking LDFLAGS += -L/usr/local/lib -L/usr/local/ssl/lib -L/usr/local/opt/openssl/lib -L/opt/local/lib CFLAGS += -I/usr/local/include -I/usr/local/ssl/include -I/usr/local/ssl/include/openssl -I/usr/local/opt/openssl/include -I/opt/local/include -I/opt/local/include/openssl endif # Find the number of processors on the system (used in -j option in building OpenSSL). # Uses /usr/bin/nproc if available, otherwise defaults to 1. NUM_PROCS = 1 ifneq (,$(wildcard /usr/bin/nproc)) NUM_PROCS = `/usr/bin/nproc --all` endif ifeq ($(OS), Darwin) NUM_PROCS = `sysctl -n hw.ncpu` endif .PHONY: all sslscan clean install uninstall static opensslpull all: sslscan @echo @echo "===========" @echo "| WARNING |" @echo "===========" @echo @echo "Building against system OpenSSL. Compression and other checks may not be possible." @echo "It is recommended that you statically build sslscan with \`make static\`." @echo sslscan: $(SRCS) $(CC) -o $@ ${WARNINGS} ${LDFLAGS} ${CFLAGS} ${CPPFLAGS} ${DEFINES} ${SRCS} ${LIBS} install: @if [ ! -f sslscan ] ; then \ echo "\n=========\n| ERROR |\n========="; \ echo "Before installing you need to build sslscan with either \`make\` or \`make static\`\n"; \ exit 1; \ fi ifeq ($(OS), Darwin) install -d $(DESTDIR)$(BINDIR)/; install sslscan $(DESTDIR)$(BINDIR)/sslscan; install -d $(DESTDIR)$(MAN1DIR)/; install sslscan.1 $(DESTDIR)$(MAN1DIR)/sslscan.1; else install -D sslscan $(DESTDIR)$(BINDIR)/sslscan; install -D sslscan.1 $(DESTDIR)$(MAN1DIR)/sslscan.1; endif uninstall: rm -f $(DESTDIR)$(BINDIR)/sslscan rm -f $(DESTDIR)$(MAN1DIR)/sslscan.1 .openssl.is.fresh: opensslpull true opensslpull: if [ -d openssl -a -d openssl/.git ]; then \ cd ./openssl && git checkout `git ls-remote https://github.com/openssl/openssl | grep -Eo '(openssl-3\.0\.[0-9]+)' | sort --version-sort | tail -n 1` && git pull | grep -q "Already up-to-date." && [ -e ../.openssl.is.fresh ] || touch ../.openssl.is.fresh ; \ else \ git clone --depth 1 -b `git ls-remote https://github.com/openssl/openssl | grep -Eo '(openssl-3\.0\.[0-9]+)' | sort -V | tail -n 1` https://github.com/openssl/openssl ./openssl && cd ./openssl && touch ../.openssl.is.fresh ; \ fi # Need to build OpenSSL differently on OSX ifeq ($(OS), Darwin) ifeq ($(ARCH), arm64) OSSL_TARGET=darwin64-arm64-cc else OSSL_TARGET=darwin64-x86_64-cc endif openssl/Makefile: .openssl.is.fresh cd ./openssl; ./Configure -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIC enable-weak-ssl-ciphers zlib $(OSSL_TARGET) # Any other *NIX platform else openssl/Makefile: .openssl.is.fresh cd ./openssl; ./config -v -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIC no-shared enable-weak-ssl-ciphers zlib endif openssl/libcrypto.a: openssl/Makefile $(MAKE) -j $(NUM_PROCS) -C openssl depend $(MAKE) -j $(NUM_PROCS) -C openssl build_libs # $(MAKE) -j $(NUM_PROCS) -C openssl test # Disabled because this takes 45+ minutes for OpenSSL v1.1.1. static: openssl/libcrypto.a $(MAKE) -j $(NUM_PROCS) sslscan STATIC_BUILD=TRUE docker: docker build -t sslscan:sslscan . test: static ./docker_test.sh clean: if [ -d openssl ]; then ( rm -rf openssl ); fi; rm -f sslscan rm -f .openssl.is.fresh sslscan-2.1.2/Makefile.mingw000066400000000000000000000072561452476416400157710ustar00rootroot00000000000000# # To build a 64-bit executable: make -f Makefile.mingw # To build a 32-bit executable: make -f Makefile.mingw BUILD_32BIT=1 # # Enable to echo commands for debugging. #SHELL = sh -xv # If we're in Linux, lets see if we can find the path to Mingw automatically... ARCHITECTURE= CC_PREFIX= OPENSSL_TARGET= ifneq ($(BUILD_32BIT),) DEFINES=-DBUILD_32BIT=1 endif ifeq ($(shell uname), Linux) MINGW32=$(shell which i686-w64-mingw32-gcc) ifneq ($(MINGW32),) CC=$(MINGW32) ARCHITECTURE=32-bit CC_PREFIX=i686-w64-mingw32- OPENSSL_TARGET=mingw endif MINGW64=$(shell which x86_64-w64-mingw32-gcc) ifneq ($(MINGW64),) ifeq ($(BUILD_32BIT),) CC=$(MINGW64) ARCHITECTURE=64-bit CC_PREFIX=x86_64-w64-mingw32- OPENSSL_TARGET=mingw64 endif endif endif ifndef CC $(error "Failed to determine the compiler!") endif .PHONY: clean # Enable security options like stack protectors and variable formatting checks. # Sadly, we can't use -pie, because MinGW produces a broken executable when # enabled. SECURITY_OPTIONS=-fstack-protector-all -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security # Turn on linker optimizations, and DEP support (--nxcompat) LINK_OPTIONS=-Wl,-O1 -Wl,--discard-all -Wl,--no-undefined -Wl,--dynamicbase -Wl,--nxcompat -static CFLAGS += -Iopenssl_mingw/include -D__USE_GNU -DOPENSSL_NO_SSL2 -Wno-deprecated-declarations LDFLAGS += -lws2_32 -lgdi32 -lcrypt32 # Set the version string for the program. VERSION = "$(shell grep -E -o -m 1 '[0-9]+\.[0-9]+\.[0-9]+(\-[a-z]+[0-9]+)?' Changelog) Windows $(ARCHITECTURE) (Mingw)" all: sslscan .openssl_mingw.is.fresh: opensslpull true zlibpull: # If the zlib dir already exists, issue a pull, otherwise clone it from GitHub. Either way, check out the latest tag. if [ -d zlib_mingw -a -d zlib_mingw/.git ]; then \ cd ./zlib_mingw && git pull && git checkout tags/`git describe --abbrev=0 --tags` ; \ else \ git clone -b master --depth 1 https://github.com/madler/zlib ./zlib_mingw && cd ./zlib_mingw && git checkout tags/`git describe --abbrev=0` ; \ fi opensslpull: if [ -d openssl_mingw -a -d openssl_mingw/.git ]; then \ cd ./openssl_mingw && git checkout `git ls-remote https://github.com/openssl/openssl | grep -Eo '(openssl-3\.0\.[0-9]+)' | sort --version-sort | tail -n 1` && git pull | grep -q "Already up-to-date." && [ -e ../.openssl_mingw.is.fresh ] || touch ../.openssl_mingw.is.fresh ; \ else \ git clone --depth 1 -b `git ls-remote https://github.com/openssl/openssl | grep -Eo '(openssl-3\.0\.[0-9]+)' | sort --version-sort | tail -n 1` https://github.com/openssl/openssl ./openssl_mingw && cd ./openssl_mingw && touch ../.openssl_mingw.is.fresh ; \ fi zlib_mingw/libz.a: zlibpull cd ./zlib_mingw; make -f win32/Makefile.gcc PREFIX=$(CC_PREFIX) openssl_mingw/Makefile: .openssl_mingw.is.fresh zlib_mingw/libz.a cd ./openssl_mingw; ./Configure --cross-compile-prefix=$(CC_PREFIX) --with-zlib-include=`pwd`/../zlib_mingw --with-zlib-lib=`pwd`/../zlib_mingw -fstack-protector-all -D_FORTIFY_SOURCE=2 $(OPENSSL_TARGET) no-shared enable-weak-ssl-ciphers enable-ssl2 zlib openssl_mingw/libcrypto.a: openssl_mingw/Makefile $(MAKE) -C openssl_mingw depend CC=$(CC) $(MAKE) -j 10 -C openssl_mingw all CC=$(CC) sslscan: openssl_mingw/libcrypto.a sslscan.c $(CC) $(CFLAGS) -DVERSION=\"$(VERSION)\" $(DEFINES) $(SECURITY_OPTIONS) $(LINK_OPTIONS) -o sslscan.exe sslscan.c openssl_mingw/libssl.a openssl_mingw/libcrypto.a zlib_mingw/libz.a $(LDFLAGS) $(CC_PREFIX)strip sslscan.exe clean: rm -f *.o sslscan.exe .openssl_mingw.is.fresh if [ -f openssl_mingw/Makefile ]; then $(MAKE) -C openssl_mingw clean; fi if [ -f zlib_mingw/win32/Makefile.gcc ]; then $(MAKE) -C zlib_mingw -f win32/Makefile.gcc clean; fi sslscan-2.1.2/Makefile.vs000066400000000000000000000010041452476416400152610ustar00rootroot00000000000000LFLAGS=/nologo /dynamicbase /highentropyva /nxcompat /opt:ref /subsystem:console /ltcg CFLAGS=/nologo /GL /GS /Gs0 /Gw /MT /Ox -DVERSION="\"1.9.8 Windows 64-bit (VS)\"" all: sslscan.exe sslscan.obj: sslscan.c cl.exe $(CFLAGS) /I $(OPENSSL_PATH)/include /c sslscan.c sslscan.exe: sslscan.obj link.exe $(LFLAGS) /out:sslscan.exe sslscan.obj $(OPENSSL_PATH)/out32/libeay32.lib $(OPENSSL_PATH)/out32/ssleay32.lib advapi32.lib gdi32.lib user32.lib ws2_32.lib clean: del sslscan.obj sslscan.exe rebuild: clean all sslscan-2.1.2/README.md000066400000000000000000000163621452476416400144660ustar00rootroot00000000000000# sslscan2 sslscan version 2 has now been released. This includes a major rewrite of the backend scanning code, which means that it is no longer reliant on the version of OpenSSL for many checks. This means that it is possible to support legacy protocols (SSLv2 and SSLv3), as well as supporting TLSv1.3 - regardless of the version of OpenSSL that it has been compiled against. This has been made possible largely by the work of [jtesta](https://github.com/jtesta), who has been responsible for most of the backend rewrite. Other key changes include: * Enumeration of server key exchange groups. * Enumeration of server signature algorithms. * SSLv2 and SSLv3 protocol support is scanned, but individual ciphers are not. * A test suite is included using Docker, to verify that sslscan is functionality correctly. * Removed the `--http` option, as it was broken and had very little use in the first place. ## XML Output Changes A potentially breaking change has been made to the XML output in version **2.0.0-beta4**. Previously, multiple `` elements could be returned (one by default, and a second one if `--show-certificate` was used). The key changes are: * A new parent `` element that will contain the `` elements. * `` elements have a new `type` attribute, which can either be: * `short` for the default output. * `full` for when `--show-certificate` is used. * There will potentially be more than one certificate of each type returned on servers that have multiple certificates with different signature algorithms (see discussion in issue [#208](https://github.com/rbsec/sslscan/issues/208)). * The `` element in a `` no longer contains the "Signature Algorithm:" prefix, or the spacing and newline. If you are using the XML output, then you may need to make changes to your parser. # README [![ci](https://github.com/rbsec/sslscan/actions/workflows/ci.yml/badge.svg)](https://github.com/rbsec/sslscan/actions/workflows/ci.yml) This is a fork of ioerror's version of sslscan (the original readme of which is included below). Key changes are as follows: * Highlight SSLv2 and SSLv3 ciphers in output. * Highlight CBC ciphers on SSLv3 (POODLE). * Highlight 3DES and RC4 ciphers in output. * Highlight PFS+GCM ciphers as good in output. * Highlight NULL (0 bit), weak (<40 bit) and medium (40 < n <= 56) ciphers in output. * Highlight anonymous (ADH and AECDH) ciphers in output (purple). * Hide certificate information by default (display with `--show-certificate`). * Hide rejected ciphers by default (display with `--failed`). * Added TLSv1.1, TLSv1.2 and TLSv1.3 support. * Supports IPv6 (can be forced with `--ipv6`). * Check for TLS compression (CRIME, disable with `--no-compression`). * Disable cipher suite checking `--no-ciphersuites`. * Disable coloured output `--no-colour`. * Removed undocumented -p output option. * Added check for OpenSSL HeartBleed (CVE-2014-0160, disable with `--no-heartbleed`). * Flag certificates signed with MD5 or SHA-1, or with short (<2048 bit) RSA keys. * Support scanning RDP servers with `--rdp` (credit skettler). * Added option to specify socket timeout. * Added option for static compilation (credit dmke). * Added `--sleep` option to pause between requests. * Disable output for anything than specified checks `--no-preferred`. * Determine the list of CAs acceptable for client certificates `--show-client-cas`. * Experimental build support on OS X (credit MikeSchroll). * Flag some self-signed SSL certificates. * Experimental Windows support (credit jtesta). * Display EC curve names and DHE key lengths with OpenSSL >= 1.0.2 `--no-cipher-details`. * Flag weak DHE keys with OpenSSL >= 1.0.2 `--cipher-details`. * Flag expired certificates. * Flag TLSv1.0 and TLSv1.1 protocols in output as weak. * Experimental OS X support (static building only). * Support for scanning PostgreSQL servers (credit nuxi). * Check for TLS Fallback SCSV support. * Added StartTLS support for LDAP `--starttls-ldap`. * Added SNI support `--sni-name` (credit Ken). * Support STARTTLS for MySQL (credit bk2017). * Check for supported key exchange groups. * Check for supported server signature algorithms. * Display IANA/RFC cipher names `--iana-names` ### Building on Linux It is possible to ignore the OpenSSL system installation and ship your own version. Although this results in a more resource-heavy `sslscan` binary (file size, memory consumption, etc.), this allows some additional checks such as TLS compression. To compile your own OpenSSL version, you'll probably need to install the OpenSSL build dependencies. The commands below can be used to do this on Debian. If you don't have them already, you will need to enable the `deb-src` repos in your apt config. sslscan was primarily developed on Debian, so if you are compiling on other distributions your mileage may vary. apt-get install build-essential git zlib1g-dev apt-get build-dep openssl Then run make static This will clone the [OpenSSL repository](https://github.com/openssl/openssl), and configure/compile/test OpenSSL prior to compiling `sslscan`. **Please note:** Out of the box, OpenSSL cannot compiled with `clang` without further customization (which is not done by the provided `Makefile`). For more information on this, see [Modifying Build Settings](http://wiki.openssl.org/index.php/Compilation_and_Installation#Modifying_Build_Settings) in the OpenSSL wiki. You can verify whether you have a statically linked OpenSSL version, by checking whether the version listed by `sslscan --version` has the `-static` suffix. ### Building with Docker Ensure that you local Docker installation is functional, and the build the container with: make docker Or manually with: docker build -t sslscan:sslscan . You can then run sslscan with: docker run --rm -ti sslscan:sslscan --help ### Building on Windows Thanks to a patch by jtesta, sslscan can now be compiled on Windows. This can either be done natively or by cross-compiling from Linux. See INSTALL for instructions. Note that sslscan was originally written for Linux, and has not been extensively tested on Windows. As such, the Windows version should be considered experimental. Pre-build cross-compiled Windows binaries are available on the [GitHub Releases Page](https://github.com/rbsec/sslscan/releases). ### Building on OS X There is experimental support for statically building on OS X, however this should be considered unsupported. You may need to install any dependencies required to compile OpenSSL from source on OS X. Once you have, just run: make static # Original (ioerror) README This is a fork of sslscan.c to better support STARTTLS. The original home page of sslscan is: http://www.titania.co.uk sslscan was originally written by: Ian Ventura-Whiting The current home page of this fork (until upstream merges a finished patch) is: http://www.github.com/ioerror/sslscan Most of the pre-TLS protocol setup was inspired by the OpenSSL s_client.c program. The goal of this fork is to eventually merge with the original project after the STARTTLS setup is polished. Some of the OpenSSL setup code was borrowed from The Tor Project's Tor program. Thus it is likely proper to comply with the BSD license by saying: Copyright (c) 2007-2010, The Tor Project, Inc. sslscan-2.1.2/TODO000066400000000000000000000015541452476416400136740ustar00rootroot00000000000000Fix session resumption test We have a false positive for session resumption IDs are assigned but not accepted for resumption Fix the certificate formatting (prefix it with whitespace) Add support for SOCKS5 proxy (or audit for 'usewithtor') It seems to work fine with 'usewithtor' It still seems prudent to add proper proxy support Fix XMPP scans that do not support StartTLS: "" Add HTML report generation Add diff between reported and actually supported ciphers Make a Debian package We should explicitly check for things that may be NULL; the original author was not very careful. Perhaps write a GUI for people who are console adverse? Compare with http://www.thesprawl.org/memdump/?entry=7 Finally, we should send a diff from 1.8.2 to the upstream developer sslscan-2.1.2/docker_test.sh000077500000000000000000000527071452476416400160570ustar00rootroot00000000000000#!/bin/bash # # Copyright (C) 2019-2020 Joe Testa # # This script (adapted from the ssh-audit project) will set up a docker image with # multiple SSL/TLS servers. They are each executed one at a time, and sslscan is run # against them. The output of sslscan is compared against the expected output. If # they match, the test passes; otherwise the test fails. # # # For debugging purposes, here is a cheat sheet for manually running the docker image: # # docker run -p 4443:443 --security-opt seccomp:unconfined -it sslscan-test:3 /bin/bash # # # Running this script with no arguments causes it to build the docker image (if it # doesn't yet exist), then run all tests. # # Running the script with a test number argument (i.e.: './docker_test.sh 2') will # run the docker image for test #2 only (in the background) and do nothing else. This # allows the test itself to be debugged. # # This is the docker tag for the image. If this tag doesn't exist, then we assume the # image is out of date, and generate a new one with this tag. IMAGE_VERSION=3 # This is the name of our docker image. IMAGE_NAME=sslscan-test # Terminal colors. CLR="\033[0m" RED="\033[0;31m" GREEN="\033[0;32m" REDB="\033[1;31m" # Red + bold YELLOWB="\033[1;33m" # Yellow + bold GREENB="\033[1;32m" # Green + bold # Set to 0 if any test fails. all_passed=1 # Number of processors on this system (used to compile parallel builds). NUM_PROCS=`/usr/bin/nproc --all 2> /dev/null` if [[ $NUM_PROCS == '' ]]; then NUM_PROCS=4 fi # Returns 0 if current docker image exists. function check_if_docker_image_exists { images=`docker image ls | grep -E "$IMAGE_NAME[[:space:]]+$IMAGE_VERSION"` } # Compile all version of GnuTLS. function compile_gnutls_all { compile_gnutls '3.6.11.1' } # Compile all versions of OpenSSL. function compile_openssl_all { compile_openssl '1.0.0' compile_openssl '1.0.2' compile_openssl '1.1.1' } # Compile a specific version of OpenSSL. function compile_openssl { version=$1 git_tag= compile_args= precompile_command= output_dir= compile_num_procs=$NUM_PROCS if [[ $version == '1.0.0' ]]; then git_tag="OpenSSL_1_0_0-stable" compile_args="enable-weak-ssl-ciphers enable-ssl2 zlib no-shared" precompile_command="make depend" output_dir="openssl_v1.0.0_dir" compile_num_procs=1 # Compilation randomly fails when done in parallel. elif [[ $version == '1.0.2' ]]; then git_tag="OpenSSL_1_0_2-stable" compile_args="enable-weak-ssl-ciphers enable-ssl2 zlib" precompile_command="make depend" output_dir="openssl_v1.0.2_dir" elif [[ $version == '1.1.1' ]]; then git_tag="OpenSSL_1_1_1-stable" compile_args="enable-weak-ssl-ciphers no-shared zlib" output_dir="openssl_v1.1.1_dir" else echo -e "${REDB}Error: OpenSSL v${version} is unknown!${CLR}" exit 1 fi # Download OpenSSL from github. echo -e "\n${YELLOWB}Downloading OpenSSL v${version}...${CLR}\n" git clone --depth 1 -b $git_tag https://github.com/openssl/openssl/ $output_dir # Configure and compile it. echo -e "\n\n${YELLOWB}Compiling OpenSSL v${version} with \"-j ${compile_num_procs}\"...${CLR}" pushd $output_dir ./config $compile_args if [[ $precompile_command != '' ]]; then $precompile_command; fi make -j $compile_num_procs # Ensure that the 'openssl' command-line tool was built. if [[ ! -f "apps/openssl" ]]; then echo -e "${REDB}Error: compilation failed! apps/openssl not found.${CLR}\n\nStrangely, sometimes OpenSSL v1.0.0 fails for no reason; simply running this script again and changing nothing fixes the problem.\n\n" exit 1 fi # Copy the 'openssl' app to the top-level docker building dir as, e.g. 'openssl_prog_v1.0.0'. Then we can delete the source code directory and move on. cp "apps/openssl" "../openssl_prog_v${version}" popd # Delete the source code directory now that we built the 'openssl' tool and moved it out. rm -rf $output_dir echo -e "\n\n${YELLOWB}Compilation of v${version} finished.${CLR}\n\n" } # Compile a specific version of GnuTLS. function compile_gnutls { gnutls_version=$1 gnutls_url= nettle_url= gnutls_expected_sha256= nettle_expected_sha256= gnutls_filename= nettle_filename= gnutls_source_dir= nettle_source_dir= nettle_version= compile_num_procs=$NUM_PROCS compile_nettle=0 if [[ $gnutls_version == '3.6.11.1' ]]; then gnutls_url=https://www.gnupg.org/ftp/gcrypt/gnutls/v3.6/gnutls-3.6.11.1.tar.xz gnutls_expected_sha256=fbba12f3db9a55dbf027e14111755817ec44b57eabec3e8089aac8ac6f533cf8 gnutls_filename=gnutls-3.6.11.1.tar.xz gnutls_source_dir=gnutls-3.6.11.1 nettle_version=3.5.1 nettle_url=https://ftp.gnu.org/gnu/nettle/nettle-3.5.1.tar.gz nettle_expected_sha256=75cca1998761b02e16f2db56da52992aef622bf55a3b45ec538bc2eedadc9419 nettle_filename=nettle-3.5.1.tar.gz nettle_source_dir=nettle-3.5.1 compile_nettle=1 else echo -e "${REDB}Error: GnuTLS v${gnutls_version} is unknown!${CLR}" exit 1 fi # Download GnuTLS. echo -e "\n${YELLOWB}Downloading GnuTLS v${gnutls_version}...${CLR}\n" wget $gnutls_url # Download nettle. echo -e "\n${YELLOWB}Downloading nettle library v${nettle_version}...${CLR}\n" wget $nettle_url # Check the SHA256 hashes. gnutls_actual_sha256=`sha256sum ${gnutls_filename} | cut -f1 -d" "` nettle_actual_sha256=`sha256sum ${nettle_filename} | cut -f1 -d" "` if [[ ($gnutls_actual_sha256 != $gnutls_expected_sha256) || ($nettle_actual_sha256 != $nettle_expected_sha256) ]]; then echo -e "${REDB}GnuTLS/nettle actual hashes differ from expected hashes! ${CLR}\n" echo -e "\tGnuTLS expected hash: ${gnutls_expected_sha256}\n" echo -e "\tGnuTLS actual hash: ${gnutls_actual_sha256}\n" echo -e "\tnettle expected hash: ${nettle_expected_sha256}\n" echo -e "\tnettle actual hash: ${nettle_actual_sha256}\n\n" exit 1 else echo -e "${GREEN}Hashes verified.${CLR}\n" fi tar xJf $gnutls_filename if [[ $compile_nettle == 1 ]]; then tar xzf $nettle_filename mv $nettle_source_dir nettle # Configure and compile nettle. echo -e "\n\n${YELLOWB}Compiling nettle v${nettle_version} with \"-j ${compile_num_procs}\"...${CLR}" pushd nettle ./configure && make -j $compile_num_procs if [[ ! -f libnettle.so || ! -f libhogweed.so ]]; then echo -e "${REDB}Error: compilation failed! libnettle.so and/or libhogweed.so not found.${CLR}" exit 1 fi popd fi # Configure and compile GnuTLS. echo -e "\n\n${YELLOWB}Compiling GnuTLS v${gnutls_version} with \"-j ${compile_num_procs}\"...${CLR}" pushd $gnutls_source_dir nettle_source_dir_abs=`readlink -m ../nettle` nettle_parent_dir=`readlink -m ..` NETTLE_CFLAGS=-I${nettle_parent_dir} NETTLE_LIBS="-L${nettle_source_dir_abs} -lnettle" HOGWEED_CFLAGS=-I${nettle_parent_dir} HOGWEED_LIBS="-L${nettle_source_dir_abs} -lhogweed" ./configure --with-included-libtasn1 --with-included-unistring --without-p11-kit --disable-guile make CFLAGS=-I${nettle_parent_dir} LDFLAGS="-L${nettle_source_dir_abs} -lhogweed -lnettle" -j $compile_num_procs # Ensure that the gnutls-serv and gnutls-cli tools were built if [[ (! -f "src/.libs/gnutls-cli") || (! -f "src/.libs/gnutls-serv") ]]; then echo -e "${REDB}Error: compilation failed! gnutls-cli and/or gnutls-serv not found.${CLR}\n" exit 1 fi # Copy the gnutls-cli and gnutls-serv apps to the top-level docker building dir as, e.g. 'gnutls-cli-v3.6.11.1'. Then we can delete the source code directory and move on. cp "lib/.libs/libgnutls.so" "../libgnutls.so.30" cp "src/.libs/gnutls-cli" "../gnutls-cli-v${gnutls_version}" cp "src/.libs/gnutls-serv" "../gnutls-serv-v${gnutls_version}" cp "${nettle_source_dir_abs}/libhogweed.so" "../libhogweed.so.5" cp "${nettle_source_dir_abs}/libnettle.so" "../libnettle.so.7" popd # Delete the source code directory now that we built the tools and moved them out. rm -rf ${gnutls_source_dir} echo -e "\n\n${YELLOWB}Compilation of GnuTLS v${gnutls_version} finished.${CLR}\n\n" } # Creates a new docker image. function create_docker_image { # Create a new temporary directory. TMP_DIR=`mktemp -d /tmp/sslscan-docker-XXXXXXXXXX` # Copy the Dockerfile and all files in the test/docker/ dir to our new temp directory. find docker_test -maxdepth 1 -type f | xargs cp -t $TMP_DIR # Make the temp directory our working directory for the duration of the build # process. pushd $TMP_DIR > /dev/null # Compile the versions of OpenSSL. compile_openssl_all # Compile the versions of GnuTLS. compile_gnutls_all # Now build the docker image! echo -e "${YELLOWB}Creating docker image...$IMAGE_NAME:$IMAGE_VERSION ${CLR}" docker build --tag $IMAGE_NAME:$IMAGE_VERSION . echo -e "${YELLOWB}Docker image creation complete.${CLR}" popd > /dev/null rm -rf $TMP_DIR } # Runs all tests with the debug flag disabled. function run_tests { run_test_1 "0" run_test_2 "0" run_test_3 "0" run_test_4 "0" run_test_5 "0" run_test_6 "0" run_test_7 "0" run_test_8 "0" run_test_9 "0" run_test_10 "0" run_test_11 "0" run_test_12 "0" run_test_13 "0" run_test_14 "0" run_test_15 "0" run_test_16 "0" run_test_17 "0" run_test_18 "0" } # Mostly default v1.0.2 (SSLv3, TLSv1.0, TLSv1.1, TLSv1.2) function run_test_1 { run_test $1 '1' "/openssl_v1.0.2/openssl s_server -accept 443 -dhparam /etc/ssl/dhparams_2048.pem -key /etc/ssl/key_2048.pem -cert /etc/ssl/cert_2048.crt" "" } # SSLv2 with 1024-bit certificate & DH parameters. function run_test_2 { run_test $1 '2' "/openssl_v1.0.2/openssl s_server -ssl2 -accept 443 -dhparam /etc/ssl/dhparams_1024.pem -key /etc/ssl/key_1024.pem -cert /etc/ssl/cert_1024.crt" "" } # SSLv3 with 1024-bit certificate & DH parameters. function run_test_3 { run_test $1 '3' "/openssl_v1.0.2/openssl s_server -ssl3 -accept 443 -dhparam /etc/ssl/dhparams_1024.pem -key /etc/ssl/key_1024.pem -cert /etc/ssl/cert_1024.crt" "" } # Mostly default v1.1.1. function run_test_4 { run_test $1 '4' "/openssl_v1.1.1/openssl s_server -accept 443 -dhparam /etc/ssl/dhparams_3072.pem -key /etc/ssl/key_3072.pem -cert /etc/ssl/cert_3072.crt" "" } # All ciphers with SSLv2 through TLSv1.2 with 1024-bit certificate & DH parameters. function run_test_5 { run_test $1 '5' "/openssl_v1.0.2/openssl s_server -cipher ALL -accept 443 -dhparam /etc/ssl/dhparams_1024.pem -key /etc/ssl/key_1024.pem -cert /etc/ssl/cert_1024.crt" "" } # TLSv1.3 with all ciphers. function run_test_6 { run_test $1 '6' "/openssl_v1.1.1/openssl s_server -tls1_3 -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 -accept 443 -dhparam /etc/ssl/dhparams_3072.pem -key /etc/ssl/key_3072.pem -cert /etc/ssl/cert_3072.crt" "" } # Default v1.0.0. function run_test_7 { run_test $1 '7' "/openssl_v1.0.0/openssl s_server -accept 443 -key /etc/ssl/key_3072.pem -cert /etc/ssl/cert_3072.crt" "" } # v1.0.0 with 'ALL:eNULL' ciphers. function run_test_8 { run_test $1 '8' "/openssl_v1.0.0/openssl s_server -accept 443 -cipher ALL:eNULL -key /etc/ssl/key_3072.pem -cert /etc/ssl/cert_3072.crt" "" } # Runs nginx with client certificate checking (signed by the CA in docker_test/ca_cert.pem). sslscan will connect and make an HTTP request (--http). The HTTP response code should be 200 to signify that the certificate was accepted. Otherwise, nginx returns HTTP code 400 if no client certificates were presented. function run_test_9 { #run_test $1 '9' "/usr/sbin/nginx -c /etc/nginx/nginx_test9.conf" "--no-fallback --no-renegotiation --no-compression --no-heartbleed --certs=docker_test/cert_3072.crt --pk=docker_test/key_3072.pem --http" echo "Test #9 skipped." } # Runs nginx with client certificate checking, just as above. Except this time, we connect with no certificate. The HTTP response code should be "400 Bad Request". function run_test_10 { #run_test $1 '10' "/usr/sbin/nginx -c /etc/nginx/nginx_test9.conf" "--no-fallback --no-renegotiation --no-compression --no-heartbleed --http" echo "Test #10 skipped." } # Makes an OCSP request to www.amazon.com. The horrible Perl command that comes after it will filter out the timestamps and other variable data from the response, otherwise the diff would fail. function run_test_11 { run_test_internet '11' "./sslscan --ocsp --no-ciphersuites --no-fallback --no-renegotiation --no-compression --no-heartbleed --no-check-certificate --no-groups --no-sigs www.amazon.com | perl -pe 'BEGIN{undef $/;} s/Connected to .+?$/Connected to\033[0m/smg; s/Responder Id: .+?$/Responder Id:/smg; s/Produced At: .+?$/Produced At:/smg; s/Hash Algorithm: .+?$/Hash Algorithm:/smg; s/Issuer Name Hash: .+?$/Issuer Name Hash:/smg; s/Issuer Key Hash: .+?$/Issuer Key Hash:/smg; s/Serial Number: .+?$/Serial Number:/smg; s/This Update: .+?$/This Update:/smg; s/Next Update: .+?$/Next Update:/smg; s/Response Single Extensions:.+?\n\n/\n\n/smg;'" } # 512-bit DH, 512-bit RSA key with MD5 signature. function run_test_12 { run_test $1 '12' "/openssl_v1.0.0/openssl s_server -accept 443 -dhparam /etc/ssl/dhparams_512.pem -key /etc/ssl/key_512.pem -cert /etc/ssl/cert_512.crt" "" } # Default GnuTLS. function run_test_13 { run_test $1 '13' "/gnutls-3.6.11.1/gnutls-serv -p 443 --x509certfile=/etc/ssl/cert_3072.crt --x509keyfile=/etc/ssl/key_3072.pem" "" } # GnuTLS with only TLSv1.2 and TLSv1.3, and secp521r1 and ffdhe8192 groups. function run_test_14 { run_test $1 '14' "/gnutls-3.6.11.1/gnutls-serv -p 443 --priority=NORMAL:-VERS-TLS1.1:-VERS-TLS1.0:-GROUP-X25519:-GROUP-SECP256R1:-GROUP-SECP384R1:-GROUP-FFDHE2048:-GROUP-FFDHE3072:-GROUP-FFDHE4096:-GROUP-FFDHE6144 --x509certfile=/etc/ssl/cert_3072.crt --x509keyfile=/etc/ssl/key_3072.pem" "" } # GnuTLS with an ECDSA certificate (secp256r1 / NIST P-256). function run_test_15 { run_test $1 '15' "/gnutls-3.6.11.1/gnutls-serv -p 443 --x509certfile=/etc/ssl/cert_ecdsa_prime256v1.crt --x509keyfile=/etc/ssl/key_ecdsa_prime256v1.pem" "" } # OpenSSL v1.0.2, TLSv1.2 with sect163k1 curve only. function run_test_16 { run_test $1 '16' "/openssl_v1.0.2/openssl s_server -accept 443 -tls1_2 -named_curve sect163k1 -cert /etc/ssl/cert_1024.crt -key /etc/ssl/key_1024.pem" "" } # OpenSSL v1.1.1, TLSv1.2 with brainpoolP512r1 curve only. function run_test_17 { run_test $1 '17' "/openssl_v1.1.1/openssl s_server -accept 443 -tls1_2 -named_curve brainpoolP512r1 -cert /etc/ssl/cert_1024.crt -key /etc/ssl/key_1024.pem" "" } # TLSv1.2 with ECDSA-SHA1 signature only. function run_test_18 { run_test $1 '18' "/gnutls-3.6.11.1/gnutls-serv -p 443 --x509certfile=/etc/ssl/cert_ecdsa_prime256v1.crt --x509keyfile=/etc/ssl/key_ecdsa_prime256v1.pem --priority=NONE:-VERS-TLS1.0:-VERS-TLS1.1:+VERS-TLS1.2:-VERS-TLS1.3:+MAC-ALL:+GROUP-ALL:+SIGN-ECDSA-SHA1:+COMP-NULL:+CTYPE-SRV-ALL:+KX-ALL:+CHACHA20-POLY1305:+CAMELLIA-128-GCM:+AES-128-GCM" "" } # Run a test. Set the first argument to '1' to enable test debugging. # Second argument is the test number to run. Third argument is the executable and # its args to be run inside the container.. function run_test { debug=$1 test_number=$2 server_exec=$3 sslscan_additional_args=$4 test_result_stdout="${TEST_RESULT_DIR}/test_${test_number}.txt" expected_result_stdout="docker_test/expected_output/test_${test_number}.txt" # Run the container in the background. Route port 4443 on the outside to port 443 on the inside. cid=`docker run -d -p 4443:443 -t ${IMAGE_NAME}:${IMAGE_VERSION} ${server_exec}` if [[ $? != 0 ]]; then echo -e "${REDB}Failed to run docker image! (exit code: $?)${CLR}" exit 1 fi # If debugging is enabled, just run the container. Don't do any output comparison. if [[ $debug == 1 ]]; then echo -e "\nExecuted in container: ${server_exec}\n\nTerminate container with: docker container stop -t 0 ${cid}\n\nHint: run sslscan against localhost on port 4443, not 443.\n" return fi # Wait 250ms to ensure that the services in the container are fully initialized. sleep 0.25 # Run sslscan and cut out the first two lines. Those contain the version number # and local version of OpenSSL, which can change over time (and when they do, this # would break the test if they were left in). ./sslscan $sslscan_additional_args 127.0.0.1:4443 | tail -n +3 > $test_result_stdout if [[ $? != 0 ]]; then echo -e "${REDB}Failed to run sslscan! (exit code: $?)${CLR}" docker container stop -t 0 $cid > /dev/null exit 1 fi # Stop the container now that we captured the sslscan output. docker container stop -t 0 $cid > /dev/null if [[ $? != 0 ]]; then echo -e "${REDB}Failed to stop docker container ${cid}! (exit code: $?)${CLR}" exit 1 fi # If the expected output file doesn't exist, give the user all the info we have so they can fix this. if [[ ! -f ${expected_result_stdout} ]]; then test_result_stdout_actual=`cat ${test_result_stdout}` echo -e "\n${REDB}Error:${CLR} expected output file for test #${test_number} not found (${expected_result_stdout}). Actual test result is below. Manually verify that this output is correct; if so, then copy it to the expected test file path with:\n\n $ cp ${test_result_stdout} ${expected_result_stdout}\n\n------\n${test_result_stdout_actual}\n" all_passed=0 return fi # Compare the actual output to the expected output. Any discrepency results in test failure. diff=`diff -u ${expected_result_stdout} ${test_result_stdout}` if [[ $? != 0 ]]; then echo -e "Test #${test_number} ${REDB}FAILED${CLR}.\n\n${diff}\n" all_passed=0 return fi echo -e "Test #${test_number} ${GREEN}passed${CLR}." } # Instead of spinning up a docker instance, this will run a test using a host on the # public Internet. function run_test_internet { test_number=$1 command=$2 test_result_stdout="${TEST_RESULT_DIR}/test_${test_number}.txt" expected_result_stdout="docker_test/expected_output/test_${test_number}.txt" `/bin/bash -c "${command} | tail -n +3 > ${test_result_stdout}"` if [[ $? != 0 ]]; then echo -e "${REDB}Failed to run sslscan! (exit code: $?)${CLR}" docker container stop -t 0 $cid > /dev/null exit 1 fi # If the expected output file doesn't exist, give the user all the info we have so they can fix this. if [[ ! -f ${expected_result_stdout} ]]; then test_result_stdout_actual=`cat ${test_result_stdout}` echo -e "\n${REDB}Error:${CLR} expected output file for test #${test_number} not found (${expected_result_stdout}). Actual test result is below. Manually verify that this output is correct; if so, then copy it to the expected test file path with:\n\n $ cp ${test_result_stdout} ${expected_result_stdout}\n\n------\n${test_result_stdout_actual}\n" exit 1 fi # Compare the actual output to the expected output. Any discrepency results in test failure. diff=`diff -u ${expected_result_stdout} ${test_result_stdout}` if [[ $? != 0 ]]; then echo -e "Test #${test_number} ${REDB}FAILED${CLR}.\n\n${diff}\n" exit 1 fi echo -e "Test #${test_number} ${GREEN}passed${CLR}." } # First check if docker is functional. docker version > /dev/null if [[ $? != 0 ]]; then echo -e "${REDB}Error: 'docker version' command failed (error code: $?). Is docker installed and functioning?${CLR}" exit 1 fi is_debian=0 is_arch=0 # If dpkg exists, assume this is a Debian-based system. dpkg --version > /dev/null 2>&1 if [[ $? == 0 ]]; then is_debian=1 fi # If pacman exists, assume this is an Arch system. pacman --version > /dev/null 2>&1 if [[ ($is_debian == 0) && ($? == 0) ]]; then is_arch=1 fi # Ensure that the libgmp-dev, m4, and wget packages are installed. Use dpkg on Debian, or pacman on Arch. if [[ $is_debian == 1 ]]; then dpkg -l libgmp-dev m4 perl wget > /dev/null 2>&1 if [[ $? != 0 ]]; then echo -e "${REDB}Error: libgmp-dev, m4, perl and/or wget packages not installed. Fix with: apt install libgmp-dev m4 perl wget${CLR}" exit 1 fi elif [[ $is_arch == 1 ]]; then pacman -Qi gmp m4 perl wget > /dev/null 2>&1 if [[ $? != 0 ]]; then echo -e "${REDB}Error: gmp, m4, perl and/or wget packages not installed. Fix with: pacman -S gmp m4 perl wget${CLR}" exit 1 fi fi # Make sure sslscan has been built. if [[ ! -f sslscan ]]; then echo -e "${REDB}Error: sslscan executable not found. Build it first!${CLR}" exit 1 fi # If the user specified a test number to debug... debug_test_number=0 if [[ $# == 1 ]]; then debug_test_number=$1 debug_test_number=$((debug_test_number + 0)) # Effectively, convert this to a number. fi # Check if the docker image is the most up-to-date version. If not, create it. check_if_docker_image_exists if [[ $? == 0 ]]; then echo -e "\n${GREEN}Docker image $IMAGE_NAME:$IMAGE_VERSION already exists.${CLR}" else echo -e "\nCreating docker image $IMAGE_NAME:$IMAGE_VERSION..." create_docker_image echo -e "\n${GREEN}Done creating docker image!${CLR}" fi # Create a temporary directory to write test results to. TEST_RESULT_DIR=`mktemp -d /tmp/sslscan_test-results_XXXXXXXXXX` # If the user wants to run a specific test with debugging enabled, do that then exit. if [[ $debug_test_number > 0 ]]; then eval "run_test_${debug_test_number} 1" exit 0 fi # Now run all the tests. echo -e "\nRunning all tests..." run_tests if [[ $all_passed == 1 ]]; then echo -e "\n${GREENB}ALL TESTS PASS!${CLR}\n" rm -rf $TEST_RESULT_DIR exit 0 else echo -e "\n\n${YELLOWB}!! SOME TESTS FAILED !!${CLR}\n\n" exit 1 fi sslscan-2.1.2/docker_test/000077500000000000000000000000001452476416400155055ustar00rootroot00000000000000sslscan-2.1.2/docker_test/Dockerfile000066400000000000000000000017621452476416400175050ustar00rootroot00000000000000FROM ubuntu:22.04 # Copy OpenSSL's 'openssl' tools. COPY openssl_prog_v1.0.0 /openssl_v1.0.0/openssl COPY openssl_prog_v1.0.2 /openssl_v1.0.2/openssl COPY openssl_prog_v1.1.1 /openssl_v1.1.1/openssl # Copy GnuTLS client & server tools, along with their required libraries. COPY gnutls-cli-v3.6.11.1 /gnutls-3.6.11.1/gnutls-cli COPY gnutls-serv-v3.6.11.1 /gnutls-3.6.11.1/gnutls-serv COPY libhogweed.so.5 /usr/lib/ COPY libnettle.so.7 /usr/lib/ COPY libgnutls.so.30 /usr/lib/x86_64-linux-gnu/ # Copy certificates, keys, and DH parameters. COPY *.pem /etc/ssl/ COPY *.crt /etc/ssl/ # Copy nginx site configurations & modules. COPY nginx_site_client_cert_required /etc/nginx/sites-available/ COPY nginx_test9.conf /etc/nginx/ # Install nginx for some tests. # Install strace for potential debugging, and rsyslog to enable system log gathering. RUN apt update 2> /dev/null RUN apt install -y nginx strace rsyslog ca-certificates 2> /dev/null RUN apt clean 2> /dev/null RUN update-ca-certificates EXPOSE 443 sslscan-2.1.2/docker_test/ca_cert.pem000066400000000000000000000035571452476416400176220ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIFUTCCAzmgAwIBAgIJAI+xjVeRdKcWMA0GCSqGSIb3DQEBCwUAMD8xCzAJBgNV BAYTAlhYMR4wHAYDVQQIDBVOb3doZXJlIGluIHBhcnRpY3VsYXIxEDAOBgNVBAcM B05vd2hlcmUwHhcNMTkxMjAzMDIxNjUzWhcNMjkxMjAzMDIxNjUzWjA/MQswCQYD VQQGEwJYWDEeMBwGA1UECAwVTm93aGVyZSBpbiBwYXJ0aWN1bGFyMRAwDgYDVQQH DAdOb3doZXJlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAze8SR6JK HTftNJrZdnvzE5LlpU6hCVGr1aIhx1nWae7crLRRB7xAc9T+YIMUhMazKwbMJBIx 7I6rYeU+FWJBkcc5AREk0C1sM6vlM001kpcYs3amib1DTJkORdQTJlh5+bPlnupa YJQIqAVKqnEYUJuOblpeUqz2LteVLlV1hycznrvkmywU72AtzaOTx1hrgH7FjpVz 2M2KJ3zDFO8NfDtqx67fbM8Z/QL+/67tfSFwRKdPU4u38IlushoYbQ/8Y81Hw1tQ 2px08q2awgtFljHl2cDLsDB8bAsQ+AiU9/3trbTid1U48Q8Uk0BBJ+TXio5qDg+n bPw0gcXlq+Rj8CBADPzWaBZdAtH1kVlSwJ2PZ5xwi0LKNsJN2wbfJIc6WjA/pL5p VjS+Yx5X8rhGqWAJDrbLoVoTg/bEy8RPPorxBspFe8jPRoSIWsmDZn+SL0SbgnxV eZG0tVn6nbWepSUOq23Gc9E6sfMsMR3WxBBIchoWCkPB8Y/X0YeT0V3kGql2fVsT 6mMTTDvcc4RORikH+wg0EOmzn+WA0I5BzR2zYANfga+cPuowO+U6qf85wzeO6eDp x49GAyTCGMYlhZd/hWEXD+Q2bZRy2j8osTRe270MKyYiMuP0eB7VZx7pr1zb8fTE BAh4JI6xUqCG8isoTyEKDdLrX4ilW+ZN2tkCAwEAAaNQME4wHQYDVR0OBBYEFDTe OueTIjWF4f771PS5kGNY28BLMB8GA1UdIwQYMBaAFDTeOueTIjWF4f771PS5kGNY 28BLMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIBALnZCFWzH3n0GFpO fYxALeoyrwYia4HrGGQ9JOwQJEHH1sUL3TwvGVoLtSB8962loGakvhtwvtr6XDyk wqsAF9J1j7PKzXvlVt3MAGDupDMTgOvX9D7GY/MYhteB2ExckmDXGyq/Ustm877S XaEkwiwCs2Jrm9T6ksZIcFd0OwpzfY+sEBjmKKTKo6n0xOmUEvlIsJ8AHZg0cOsj LD0hdcdwQ6gtvX+LrjrCWk1OzjHlGWLpDuPhDlhYFidBoRH65SWjUzqH6jmaUjEi pwO3wmPfaXAkSqVw1O+Pkc0BThpSbPCwnn5J6VuAJQN65pLD1vRh0UfpLI8TeOQe dDDIoiRjRCrBfSmrzZ5uj18fC/MB/6x5jfyPzMMlJCSmpWcuz65imP8VVn8V8M9b vGM+hgP66xEO4UwBGbKiIWh8Hb0Jqo+vV6AObdpncOmWxnFU891NbyLjgkRfmTMq dH3q71sarOmvv2aHcZTWwj46mzPoJHViS0lT3XYURTKar16RgMihUmKcMyPdVj75 JDZyvJwpis3zSPTERmYjeuqY3Lb/hXIWHMg3v6+xWrHunj7aFuugCtyl2qm6uHGh 5uBjZfocr+ZrT4YItUZGsSw4zfkJMIWVuHuX30Q2Gtrkt25IlYCKHZGpb49KyWub wS03DVRaHGOd/8zksngsXzReZeor -----END CERTIFICATE----- sslscan-2.1.2/docker_test/ca_key.pem000066400000000000000000000063101452476416400174430ustar00rootroot00000000000000-----BEGIN PRIVATE KEY----- MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQDN7xJHokodN+00 mtl2e/MTkuWlTqEJUavVoiHHWdZp7tystFEHvEBz1P5ggxSExrMrBswkEjHsjqth 5T4VYkGRxzkBESTQLWwzq+UzTTWSlxizdqaJvUNMmQ5F1BMmWHn5s+We6lpglAio BUqqcRhQm45uWl5SrPYu15UuVXWHJzOeu+SbLBTvYC3No5PHWGuAfsWOlXPYzYon fMMU7w18O2rHrt9szxn9Av7/ru19IXBEp09Ti7fwiW6yGhhtD/xjzUfDW1DanHTy rZrCC0WWMeXZwMuwMHxsCxD4CJT3/e2ttOJ3VTjxDxSTQEEn5NeKjmoOD6ds/DSB xeWr5GPwIEAM/NZoFl0C0fWRWVLAnY9nnHCLQso2wk3bBt8khzpaMD+kvmlWNL5j HlfyuEapYAkOtsuhWhOD9sTLxE8+ivEGykV7yM9GhIhayYNmf5IvRJuCfFV5kbS1 WfqdtZ6lJQ6rbcZz0Tqx8ywxHdbEEEhyGhYKQ8Hxj9fRh5PRXeQaqXZ9WxPqYxNM O9xzhE5GKQf7CDQQ6bOf5YDQjkHNHbNgA1+Br5w+6jA75Tqp/znDN47p4OnHj0YD JMIYxiWFl3+FYRcP5DZtlHLaPyixNF7bvQwrJiIy4/R4HtVnHumvXNvx9MQECHgk jrFSoIbyKyhPIQoN0utfiKVb5k3a2QIDAQABAoICAGMM1HwEASXgmoUs3d/xak9F 3pMOKMK0t7O/kgOyoEC/lQC0kizoTQ/pqJh/M8VRVSgi0tmersibLq+ddakPY35c lnx+5HgFAQAxc8KjJltltYnMTfn+QHp9O7I2eSd+cty5vH4dNm8xhKBcOzeTwiAz UeSeLrQRYS/SnXx1ulvRbTCyKxi/sSoZ1q4MOa4uRza8wwT7uYbUBdlMVwCgopnY clmtMOXDDzr0z/XnC2+eP8Olva/vif91+vpLNuhuQfU27Yd3SoJ7snxvJ/qhNU0y nt2Hr/EEwTOudvD2H8DQMBvW3v6KzSKVIE5bH3uyxEFuknBE80CmZhLtPrTY23/s 97/ncS+tY3mxr8hOBRyiz7o2zDvPcbSq56jt2JkUUS4mwk2uVzpO9uKhrDY9CkkS Iq5UjV0gtjQ8092Mp83Bazy0q7fTKdwgvsoorbdKMZP4GZ0EPIGJC9r8IH9UD7Cl 1YVGj1qBXUFznbJmFtNGofvc/8PzZ6TMNscEVOcjy8vrqmhKGcdXMoMl1LxDl/4g mN26n9uKfatCeRN9qyxOsts3+QEqJq+rKn2odQlCNfpezxNh8uauAx8ZxQ4HXirW O+CZS5JAlNWK5qp27pGq7JNKy5xyaU8PkC5G/A8Fi35iF1o0j2ICSWkCY3cTd73W /TvzsGNsbrJLTIFfo1ghAoIBAQDqOp7LfXLZct17TdpBSwq+2IzSN/H6ozKcyXSf Nnx56Avy1OZkU3ELMN+/zZp9X91dhR+PpXJfcbufiuJIUq0L34ow8X+cnw66hUur ig9rzs7o1Ak6PZcrVINOjZ5Sn6gzuDMZgH5PzFNjXxZto1KjDLCnf5adoYEUfjJZ r85ZN9/NlUW/PhZzuyRUW0ouRDsjjnLQouomCrFbva2tvpPggCcRlizHg6ReyX1S LfozmQbfvI4e60cbRj5MuouJbbvMicecRT5R00HhTfHTj5MMqf5DRToS2ir/QYw6 kZQWHdFih+eDQcZFiPILUxq89OSBJy2UtrfgaFxGiPBdgm5lAoIBAQDhEy5NBB0X udTc9BJlL/ROp84/ER/OTd4eG57FVXhv/kuC+v2gv/M+PHc7RVSZCh+sEvqs2Dzd qRms57zQGJ2zbSzhgcCzghpNx+mNXe5UScAUM4sDONOGeeQc15HkAMCz4/umcInc IcM1zsbxa+AG8YGv9JHuknYBZ2bbaUlsoltQ57sa2h7Wht3ql3IRYSu2hwsWiGlb MZlozaEXpqH4+LvBfs0gCXNmqMOV72MnEFWFVooSzISi5KakPysH5TNypJpE6FWn 1ccUMTFFkNRFgn64qUXHyaKQlaMl0UPb3XVcyxB4Wamde8yXoo4trdFRGY1kRLl9 31zFeZDoT8llAoIBAQDGV61wE2LVz/bNGzfeYnVO9oEI4mb+HoQVUGJ5D+KIOH8l ujL+ccof99sAyFIyKKODNd9r/GXFfMGscCb9p0Tx8PFMULQHJImMWKOjNt2oJRAB CMxnjRAdmQs30aRnwtrkMO7UgYJ0gEl8tGCBpvOrLmvI6rnX8ZMkj1iDqePKmQ3j QKw3LZRFnAs/g65lT1Hk4hNHqS0t2ZAmZ5BSuDbwvJRYyBpTOJ5Pxb9hf52HY+X2 P+z5MbKc3faTcsQGM+37XhCxu9Dx6Tq4VxCYXdPfvXOZ810h6azPSeo9DlmgAM/1 56+b7m6/IyAThuP1bkqxM0Pd0nwSg0zgTcV86Z4hAoIBAELgYSSPMVnIZMBWYVTh n9TzNWw12V6Ccpo9mLqHv+Z/B87eZxgpkMwQSVk6K33hrTGC3isXgVZXlYJzxP2M Iueaa/iBhlGQOeKcoP/ZRiSTWVhnTEnjy64sb6RGRVobAycweailzcCz434Md75q UEGf5unyYJ4jtJ6MK9rL+P4na7ypbkX3Q6x4nF3FLCaP2d49WAUU+UEYhr3GQ7R0 VbJVrew7khWP2VNKl/roC20jBFY/NX2KeWqxR/aLsmyBJP1OfWw2IKVi9ulACKTj +L7CnIaf/VT0y7HsVHK7ME+XCPVOfRFVivl5PHxd16Mo/4X6crG1XexRvw4KJg1x D6UCggEAT+eKtfA0EkA4zQKAC15KZSTxrpYK0phQX6dBTgwXlwoczInlX7HjtQb9 7G9OzRFZvenzXsBfT+av1ilSjEPo6l/bL664qJY4hzG+5Tq1NC0YA+2Ihb9/wQP/ yXp/tnn27XZChm/wxdGG+s7wpWaZ9LQj/80pbMbH/DoMGlaFyHF+8RPXbDF6ycJF kAV9E0PKeVBGaQbvEx1NW093F1Lf2yPhPeEA89qjmOigyZQ7r4tIhJxYgzUo3gqD b8PbWwbrGPGD5AUu6V4Fv2E86mIgoRlcZFayHGDvGSqM5CZ7VSLLc9pc33WPV55T IvfsnBvVJ9M2TPyXcd9tejBOzLjOkQ== -----END PRIVATE KEY----- sslscan-2.1.2/docker_test/cert_1024.crt000066400000000000000000000024521452476416400176250ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIDpDCCAYwCCQCaM8BbiyPRSTANBgkqhkiG9w0BAQsFADA/MQswCQYDVQQGEwJY WDEeMBwGA1UECAwVTm93aGVyZSBpbiBwYXJ0aWN1bGFyMRAwDgYDVQQHDAdOb3do ZXJlMB4XDTE5MTIwMzAzNTY1MloXDTI5MTIwMzAzNTY1MlowbTELMAkGA1UEBhMC VVMxCzAJBgNVBAgMAk5ZMRIwEAYDVQQHDAlSb2NoZXN0ZXIxGTAXBgNVBAoMEEJh bWJvb3psZWQsIEluYy4xIjAgBgNVBAMMGWhvd2Z1Y2tlZGlzbXlkYXRhYmFzZS5j b20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOak+uYE1LeCoKAIH2Uq8fhm lf0W8fPDc/iQ1vI3jn7zKruAFSl/0lgVA7SuqbSFJ5slJBQOSGsV87qidl2wzI3f aU+VU8WYEgswE+BrElNVQ5r5NbGDJW4+Bp+2sxAyvRa+Fu/7deG3mGo9MQp78YTD Fcko9KbYXUCACSTCVBHNAgMBAAEwDQYJKoZIhvcNAQELBQADggIBAEh3v+b8P6/g 3OkAzkNpLJ2yQK1AJ35yd9KtmnTWzAYfWqkowWOZPVQv41VG0LEy8DF/DuBlXLyp H1HfY7hpJYMmZfs1Mdcr1D7pir1nobG7CFJSiS4/R1Irqb4KQhFaYPEvdy6vEh5s T+DrF6/rWlE1QnoiAoDxgUn7gYv5LThux/aX2L9ne6YY8mxBZm6AXCjsXGSFZdFY vAFeQTAVs6/lJ5AXrV9IIO5L9MGozeKVKTwz5MqNlQjr2XkGeCJ/+L40NL91/mTK xuSIZXP3gCyfL+szN7qQ8NWmrqdFoUkzVyV+SUbXfpuVLf+yC7dZGZx8AktqQERr esKgd54fIJTpZGRtx/y9UW9OAHugAoAd/6Sd1Pk3B2YH4cJPFQTUkod4OKotWs0f R4DA+aAf0tqFwKRTGDsny/6+nnGenn75zRunmae0R51vS4vbHgEoMVsGLu/QbSdC +f9DYXpeH96u/0lKl5ueW/Acoa20ngJFS6IzJiWMTJPxWJYq+gOnSMS2OEakoUKU UYjZ1VFYJrnXB+cKBksY38c6ryskUP1dfaWICwX9DH2MnD1RuuaKcdmhu+k45ujC LefUCIQ+2K4jMe/Irvk9yAbKfSBZ7xfRfgNPTdr0jjLfSZHhI5QDUOUsP8SEt1yV CQx1WMxnRCNtwJVsAhisGWFTA0sDImOX -----END CERTIFICATE----- sslscan-2.1.2/docker_test/cert_2048.crt000066400000000000000000000027411452476416400176350ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIEKTCCAhECCQCaM8BbiyPRSDANBgkqhkiG9w0BAQsFADA/MQswCQYDVQQGEwJY WDEeMBwGA1UECAwVTm93aGVyZSBpbiBwYXJ0aWN1bGFyMRAwDgYDVQQHDAdOb3do ZXJlMB4XDTE5MTIwMzAzMDEyM1oXDTI5MTIwMzAzMDEyM1owbjELMAkGA1UEBhMC VVMxCzAJBgNVBAgMAk5ZMRIwEAYDVQQHDAlSb2NoZXN0ZXIxGTAXBgNVBAoMEEJh bWJvb3psZWQsIEluYy4xIzAhBgNVBAMMGndoeXRoZWZ1Y2t3YXNpYnJlYWNoZWQu Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAywGmJp/AoA4TCs6z bXuiBOkho35IeVvpsy7RqM3y3KxkEFnk/LM6U/ayL+j2vo4/15WPM0PaAGRRbvnQ EuI1xvhn/0/T4xP+TBe91pTMo/nKrK/ycvBLBqLPZQK9SJbHk6mwfgpQs5S/+VHl U9jl7+eQWcR+o3NXtv4XFlQyqx1dcokAJrL4wr2vGPkigUNU2iI6FwRB4f7Wo1rB NzI49uE97IWuh+VBMPYMp+Zn2Om4ptCyjdvSI7DEYc6jyKlPzH2UOgd0RkcwivaS pxfXJEBOC8PtOxyLg/KPjUTwUh0nHSpeOIbT3HKnOErEbbiHQmlYbbcOyinv3hIl Rj+PyQIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQCYTQPx8JIdeNfov2cSsM/8ByDo M6DDhW+kAgGdhKdGglDXtrtX4ffPYvG1EjQg7TIZJoXWcwng4XWGFI7lGqyAOQn9 KjDqfFj00udNJq8B57JJK3vq71rppcggt5mJnzTrrMlTZ4z8ZMFLnj6drCEsjZLM 3oRRcBvtfC4j9xT4ZICt8R3eXw18Ne43PT1wRhFpQAud0Y9zPO/0veyAlf/D0suR 8Ix8XXRr3PU+c5XZeY2uT50FcHNKLgcSmck+25CPnwSdQtdhhfcXGpBKzczjHHTU yqIBVf9xwM4sCtg50aWrdYTYgFivMqPy4ieLe/NlhrlmjSJPFR/hw7605mTiu4zG 9Dlr310eCjL8jiASWpfj27u6QYaxFL5yg1mMfl/mvDr9dLV4LnffdkeE8hk+PVkz IvHKeLhAu39t1JAs841NwW0WhdxOQkSB+VqDmixy9lmJhM0c8I45S9qERvnKrd9S kMiVxO0d4Aza1eEt1Kep2tfK2CkAzQD30Tl/v4njPZXR7lU5p4g6pr4EukxBwMrs t2Hs1Czb9x59HV7FDB0Z8DgrNkysi40lRMMNzNoQ2HaoaLKuotwXZFCs5O5HRnze iMDS3Jy0gDs53TanmxXC2gE/ODeYOqzkOjvGgPruZOMEZ7bKkLkC/lcUxIYy4xoE PgE/onpOVIay+K/3dQ== -----END CERTIFICATE----- sslscan-2.1.2/docker_test/cert_3072.crt000066400000000000000000000031671452476416400176360ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIEmTCCAoECCQCaM8BbiyPRSjANBgkqhkiG9w0BAQsFADA/MQswCQYDVQQGEwJY WDEeMBwGA1UECAwVTm93aGVyZSBpbiBwYXJ0aWN1bGFyMRAwDgYDVQQHDAdOb3do ZXJlMB4XDTE5MTIwMzA0MDc0M1oXDTI5MTIwMzA0MDc0M1owXjELMAkGA1UEBhMC VVMxCzAJBgNVBAgMAk5ZMRIwEAYDVQQHDAlSb2NoZXN0ZXIxGTAXBgNVBAoMEEJh bWJvb3psZWQsIEluYy4xEzARBgNVBAMMCmxtZ3RmeS5jb20wggGiMA0GCSqGSIb3 DQEBAQUAA4IBjwAwggGKAoIBgQDEDVOhDYctVgOYpKM9KUKmixtQxgDfQGVFczN0 l7U5UGD+rASuFRGUUC8YX2WOBcWcxnqhMrXriwlexyM1dL8BupY72sF4xtTEPzn8 9Gjh6aYFWKh7kD8DjFsC8+3WyfCCNu1k1OzFmiF5SjHbXr81MnbhzdIYQE6UBIEe 1PpUEk9qbHVoAuVKVLiOq0sCWTHPoz9dQ95ERHoMphdSLfvDRcJlFGTVTa54zad+ TPjtr8bGh4Baa9Y9VbUG75Vslv0eyH/ai3KEdkBVf39+wpnAd/2pxKu60uTkzSLH 01QWeryplW5ktNlrv+sLDpieaU6/WYBknyw0m23XDKEwYt5uR9UcoREKqTfstGlL OWhO73n64+7+r7f3VcwpM6YwerCG9kGkCg683tuzijw3UkXyE+74wEaxlSzw/571 ZMlTb3O85FZ3tn/wrXNqSKEkP0VdwLfw4Y7zyH/slXFhwzJVRlbfNkrEhOUlaXwn Xw6pClProrhx4s5bVKNEh4cZf1MCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAikFI 8LMptJKl9L5WmXW3OFS/stc0dxBQ/0/qzPiDWrhINrFkIYeNZ2fi+Cv6mLXil+C1 72Mu9YsTJ6L6VjHUnIXAhwQC4gjnhjPoZIQ3sdaQl0I5vwPr5xS6wDLoWtUSjcem x8x+axPEsqw/EIGv55NsY7YezpqFU48rkRrGbJL9jOVbKcIwzbg5ZxqRZ2kmSUD9 Ze56RqXhwZPbdMmcrIk2632RoAh9HXgndL9QCIvypDnK50KpP/b2C/1Amaux//Rs ro8C55J/x2FWl0iDwHc4gAtsZvn8aznfGnavj4JHq8+3cZBZQ3zfv6ojFvWCBniT YGb57CJA+s1MW2urF6ldExgsb/adQN7oXW6I0Y9A+zFOdd3epoa+GJZu2FI7kVs3 VViioCRPDCCxgDJ8CnhBvr5ALd+dWDGOpU7+POWqmtscF56tnPgiCK9J8TsT2GkN S5h/NbTbxEZvFAJS5x4GnwQBW0o0tmnybLzkRUeUucDg3k/jsMsnQIft2kPtcxD8 vEZWKl/jwfX6EMLIXgAHIDK2HiG9301GlksvDTFaZhMNRcH9RYhTwYYsdLjvs5Bj aY+evRF2E6MQnaLQ7m1Hg8YZZY5O3Z/n6fPUESd3zMSsXtmcyRZ4KP5LSwTy6HuE +qEu3vdeFaOd+Ii8k8sD/4SuKf7RcXC3OG5Ne0M= -----END CERTIFICATE----- sslscan-2.1.2/docker_test/cert_512.crt000066400000000000000000000022601452476416400175430ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIDSjCCATICCQC6PCarUG/VGDANBgkqhkiG9w0BAQQFADA/MQswCQYDVQQGEwJY WDEeMBwGA1UECAwVTm93aGVyZSBpbiBwYXJ0aWN1bGFyMRAwDgYDVQQHDAdOb3do ZXJlMB4XDTE5MTIxMzAzNTYyMloXDTI5MTIxMzAzNTYyMlowVzELMAkGA1UEBhMC WFgxHjAcBgNVBAgMFU5vd2hlcmUgaW4gcGFydGljdWxhcjEQMA4GA1UEBwwHTm93 aGVyZTEWMBQGA1UEAwwNZ2VvY2l0aWVzLmNvbTBcMA0GCSqGSIb3DQEBAQUAA0sA MEgCQQDL3c8fl0i1RqSy1ctDSAWVbOpOy8b4ruQspvuZ9M28LGCrYq2pSL3NBz3p CYpNaP0C4KnDvN/N+8DkvIT1NJPVAgMBAAEwDQYJKoZIhvcNAQEEBQADggIBADgl k3V0s2HTPreUrn37fNwj9jYlATJGiQEy8tOoU42j6hK1nhVDq947JCtRXN3ykQkp bGWcK8TioA+IgPopW8as7rPPzbG330LYUqTub4v3r7b8NqMQBJeRp5EbDj7cvppW L8Op/pKNJBdFCL+qp4vw+k31ZALcDLfU2evGLD5cq7S/FmzQs7es0c13RICPK3nI X4AC19isu52zzMXXECPL51nbWbVH7MRQt/UPzfgyDfe+UIAUpR/cvGqree/fWL2D UQrIOD/k789XzrynRfjlJjxeSWlIyrSYD+zedjxUyn+L6YfcEwUfaqvfYn1YOeKZ BXNNTxWWZQtdlXif1L/Tk0xHrXlpMNJOmXUnKu9Wb/7ovTfjxiXHnwrhmOHZAn6O e1Oev5tnMmVWEtp0c1uowX4BTKtl5v/a827cTSJDVm5Va+cfIGL0MkjFcPz4zq04 Ke/22SM4XdEiUvSiiYj/NrTI4txLid0d+gRZZIzoTnybUobBZUFWYvIFqyi990OF Mnjercyzb5uEpCiq2xZVwAKSUNMzFqzv+zerN3otOwi3lIY1evNkRdGngmmItEUD wvNgfpQApqAUH81zFKpnCmOIMZ3XDed+xO7JCJKr1zZ6+qyEhtrew8RL2hMHIok0 jQQ3dyi39Ekmfr+CyKvPBQ+F4qtMHgv7VFd73RBf -----END CERTIFICATE----- sslscan-2.1.2/docker_test/cert_ecdsa_prime256v1.crt000066400000000000000000000023001452476416400222060ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIDVjCCAT4CCQDe1MM22vqmNTANBgkqhkiG9w0BAQsFADA/MQswCQYDVQQGEwJY WDEeMBwGA1UECAwVTm93aGVyZSBpbiBwYXJ0aWN1bGFyMRAwDgYDVQQHDAdOb3do ZXJlMB4XDTE5MTIyMjE5MDE1NloXDTI5MTIyMjE5MDE1NlowZjELMAkGA1UEBhMC WFgxHjAcBgNVBAgMFU5vd2hlcmUgaW4gcGFydGljdWxhcjEQMA4GA1UEBwwHTm93 aGVyZTElMCMGA1UEAwwcaXRzcGVhbnV0YnV0dGVyamVsbHl0aW1lLmNvbTBZMBMG ByqGSM49AgEGCCqGSM49AwEHA0IABEJG/H34ca87RR7tz4meDGqz8sV+nSSl2+VB JFW3M3W85C84Tlx5WG5Z16+GtpsK0hBT84wjkUo0KpPfY7/dCFYwDQYJKoZIhvcN AQELBQADggIBAEATuWgTLHRq3+EDfJj8l5kGhvg8jjAGc/9J1i8oEwJl1Gy8Dv02 jFu67camK09vprZ25EHzyVHUn+1PtZUi1kl/dpnBfFYADHZTOyokhIZ/QWLd1yr4 Oc7ZHcVwODt+S/npfZsga2R66oI+wUQbkF7+/xpFU/DcjevMQkE3Ql5cMaFa5NZf Z7adpYct7RPTW1aqPVckZbB3FfN85YpTyRVOt3u93/qG73dzIVjVg6YsjZYgtvxD QhIQotKyAL6lIzA51KtIY0WhE2QmBB4YnIHlK1VkvvTaWk5tcBuY8Se2mBHfAyL5 TESNfxBi884xBoHAJXkV6tZszhEJFgJi7zZS+fpP3kxst+CQBvhSa7gh6hWcqZyL JGCUTjSUxfZEo97cKqOt8kYMls1eBYuIOUQdmcFbY8ML3O90KpLxosT9cUwsceZc nBnF1qJwtG0o1RsnAYOLVCuZaimqor7rBGgBwBjkauR58PgQQBvMLtwj59edkkW+ fAQ/xcI7ofETEKzoxHc1ea6LTE4ELWP58tds5URx0/aGYyMVazKZyhPDk2rh7/r3 uo7rhOrCJBO89u7wRcbSnzxtWxYI3V8+5a/70Eh7ztIUJwOd+XehexJJvqZdeA7p LBMjnUSNaR1BA4oNXP3vaFUgRFDf8dosmVAstzVDHQlE6l08bFZ0ovpj -----END CERTIFICATE----- sslscan-2.1.2/docker_test/dhparams_1024.pem000066400000000000000000000003651452476416400204610ustar00rootroot00000000000000-----BEGIN DH PARAMETERS----- MIGHAoGBAOA34y/7fH82VEhOGbr50PFlSTZcVG5+YtJmVsWH+r6Y72UAIyhBbF2D ll4gK+uYmXam6Uk8Nwf1U4QiLf7H6ZWlk3ynTa0XUWAGDf8Fce/Y9bWaJV+M7Klr c+WGk/Rt8CySRfB58fzsoGuDEW85tq5rqlkJcIKBr2bgSTtE8kIrAgEC -----END DH PARAMETERS----- sslscan-2.1.2/docker_test/dhparams_2048.pem000066400000000000000000000006501452476416400204650ustar00rootroot00000000000000-----BEGIN DH PARAMETERS----- MIIBCAKCAQEAhmyrz3SekFJY9nkmUt7tKXi/fNfxw3/UZA9+g0SOsvYxMI+vw8XJ ILm+8HJR5+kvcz6vkxgbxV9IACEdRzf33zBHcRXzA7OifsAy8CN217d8HNHqurGk ueCLTn2w1SfMy2Do3NB50AOru32xPBQL9hqLLhqEs8IKdAVuNL/OKmuLCovaAck4 YYCT0Phe6VSmOmMP46dFJYuAIoup6J/TsDLqGIG/G8bZPaAn1XtgjJ23Ptoielu1 z7CcvO2Bxv5gDGUnd/oW+rWU1gJ2Aav62564Fy6tNSVnNWzWy3WGuqMjkzJsEy8L 3sklLhryd4vf1E2vvFRaupMUY9g0oVWB4wIBAg== -----END DH PARAMETERS----- sslscan-2.1.2/docker_test/dhparams_3072.pem000066400000000000000000000011231452476416400204570ustar00rootroot00000000000000-----BEGIN DH PARAMETERS----- MIIBiAKCAYEAjoI7ICm70zsvw1DgmheGKxrpFz31cR2F+b4P5HwFPJ77EZDDNZQ2 rmfJ6B1F4fFZZcGeEzuRvnujzy3grie33zRDvPLAFSzoTWjarh/bEiMcDFz/X2AY 7TAlC1snEmdcrnar8H7Twg2pWCbUKrwF/wsBsqjzXtokGqhseUTDgTUjP4JW94li 3SnqBPLGypFPGmwt5rq6IUARilOXHhwDfodV2JHvbdRvbIUivShYT9YpzLwA512s sz4clyLNjFDpVdX9HtcQoJL7etStC8Jo7qJvpjkQUGxUrbZR7QM12YfHiT7+dOIi PyLPGrEm11FWLntxyX+RuR8v5wVaXIiRziwRiz/xy4YM5giYXPQFSWNcSp7YlZO2 8LyTreyWKp9hHPFN0B2PX1G5XU8bEsIeS/gUVorjd/k6/KsQGHhFpUTMAv43CgYI UVXqw8DPGQKHejfmA5sX3rKTXZlxQjKofxsZUuymuH+Bn9tQKCLzFVWPMScM0Abb xNG5W9qEvHGDAgEC -----END DH PARAMETERS----- sslscan-2.1.2/docker_test/dhparams_512.pem000066400000000000000000000002341452476416400203750ustar00rootroot00000000000000-----BEGIN DH PARAMETERS----- MEYCQQDGepU1BSbkViIkFsK+7q68p2ISObhxXRf9uZAqi1jfEhuFrE9IXrhs1CFe QFW4cLx60bJttVU6acun8aaySWSjAgEC -----END DH PARAMETERS----- sslscan-2.1.2/docker_test/expected_output/000077500000000000000000000000001452476416400207265ustar00rootroot00000000000000sslscan-2.1.2/docker_test/expected_output/test_1.txt000066400000000000000000000154421452476416400226740ustar00rootroot00000000000000 Connected to 127.0.0.1 Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 SSL/TLS Protocols: SSLv2 disabled SSLv3 enabled TLSv1.0 enabled TLSv1.1 enabled TLSv1.2 enabled TLSv1.3 disabled TLS Fallback SCSV: Server supports TLS Fallback SCSV TLS renegotiation: Secure session renegotiation supported TLS Compression: Compression enabled (CRIME) Heartbleed: TLSv1.2 not vulnerable to heartbleed TLSv1.1 not vulnerable to heartbleed TLSv1.0 not vulnerable to heartbleed Supported Server Cipher(s): Preferred TLSv1.2 256 bits ECDHE-RSA-AES256-GCM-SHA384  Curve P-256 DHE 256 Accepted TLSv1.2 256 bits DHE-RSA-AES256-GCM-SHA384  DHE 2048 bits Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-GCM-SHA256  Curve P-256 DHE 256 Accepted TLSv1.2 128 bits DHE-RSA-AES128-GCM-SHA256  DHE 2048 bits Accepted TLSv1.2 256 bits ECDHE-RSA-AES256-SHA384 Curve P-256 DHE 256 Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA256 DHE 2048 bits Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-SHA256 Curve P-256 DHE 256 Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA256 DHE 2048 bits Accepted TLSv1.2 256 bits ECDHE-RSA-AES256-SHA Curve P-256 DHE 256 Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA DHE 2048 bits Accepted TLSv1.2 256 bits DHE-RSA-CAMELLIA256-SHA DHE 2048 bits Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-SHA Curve P-256 DHE 256 Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA DHE 2048 bits Accepted TLSv1.2 128 bits DHE-RSA-CAMELLIA128-SHA DHE 2048 bits Accepted TLSv1.2 112 bits ECDHE-RSA-DES-CBC3-SHA  Curve P-256 DHE 256 Accepted TLSv1.2 112 bits DHE-RSA-DES-CBC3-SHA  DHE 2048 bits Accepted TLSv1.2 256 bits AES256-GCM-SHA384 Accepted TLSv1.2 128 bits AES128-GCM-SHA256 Accepted TLSv1.2 256 bits AES256-SHA256 Accepted TLSv1.2 128 bits AES128-SHA256 Accepted TLSv1.2 256 bits AES256-SHA Accepted TLSv1.2 256 bits CAMELLIA256-SHA Accepted TLSv1.2 128 bits AES128-SHA Accepted TLSv1.2 128 bits CAMELLIA128-SHA Accepted TLSv1.2 112 bits DES-CBC3-SHA  Accepted TLSv1.2 128 bits TLS_RSA_WITH_RC4_128_MD5  Accepted TLSv1.2 128 bits TLS_RSA_WITH_RC4_128_SHA  Accepted TLSv1.2 128 bits TLS_RSA_WITH_IDEA_CBC_SHA Accepted TLSv1.2 128 bits TLS_RSA_WITH_SEED_CBC_SHA Accepted TLSv1.2 128 bits TLS_DHE_RSA_WITH_SEED_CBC_SHA Accepted TLSv1.2 128 bits TLS_ECDHE_RSA_WITH_RC4_128_SHA Preferred TLSv1.1 256 bits ECDHE-RSA-AES256-SHA Curve P-256 DHE 256 Accepted TLSv1.1 256 bits DHE-RSA-AES256-SHA DHE 2048 bits Accepted TLSv1.1 256 bits DHE-RSA-CAMELLIA256-SHA DHE 2048 bits Accepted TLSv1.1 128 bits ECDHE-RSA-AES128-SHA Curve P-256 DHE 256 Accepted TLSv1.1 128 bits DHE-RSA-AES128-SHA DHE 2048 bits Accepted TLSv1.1 128 bits DHE-RSA-CAMELLIA128-SHA DHE 2048 bits Accepted TLSv1.1 112 bits ECDHE-RSA-DES-CBC3-SHA  Curve P-256 DHE 256 Accepted TLSv1.1 112 bits DHE-RSA-DES-CBC3-SHA  DHE 2048 bits Accepted TLSv1.1 256 bits AES256-SHA Accepted TLSv1.1 256 bits CAMELLIA256-SHA Accepted TLSv1.1 128 bits AES128-SHA Accepted TLSv1.1 128 bits CAMELLIA128-SHA Accepted TLSv1.1 112 bits DES-CBC3-SHA  Accepted TLSv1.1 128 bits TLS_RSA_WITH_RC4_128_MD5  Accepted TLSv1.1 128 bits TLS_RSA_WITH_RC4_128_SHA  Accepted TLSv1.1 128 bits TLS_RSA_WITH_IDEA_CBC_SHA Accepted TLSv1.1 128 bits TLS_RSA_WITH_SEED_CBC_SHA Accepted TLSv1.1 128 bits TLS_DHE_RSA_WITH_SEED_CBC_SHA Accepted TLSv1.1 128 bits TLS_ECDHE_RSA_WITH_RC4_128_SHA Preferred TLSv1.0 256 bits ECDHE-RSA-AES256-SHA Curve P-256 DHE 256 Accepted TLSv1.0 256 bits DHE-RSA-AES256-SHA DHE 2048 bits Accepted TLSv1.0 256 bits DHE-RSA-CAMELLIA256-SHA DHE 2048 bits Accepted TLSv1.0 128 bits ECDHE-RSA-AES128-SHA Curve P-256 DHE 256 Accepted TLSv1.0 128 bits DHE-RSA-AES128-SHA DHE 2048 bits Accepted TLSv1.0 128 bits DHE-RSA-CAMELLIA128-SHA DHE 2048 bits Accepted TLSv1.0 112 bits ECDHE-RSA-DES-CBC3-SHA  Curve P-256 DHE 256 Accepted TLSv1.0 112 bits DHE-RSA-DES-CBC3-SHA  DHE 2048 bits Accepted TLSv1.0 256 bits AES256-SHA Accepted TLSv1.0 256 bits CAMELLIA256-SHA Accepted TLSv1.0 128 bits AES128-SHA Accepted TLSv1.0 128 bits CAMELLIA128-SHA Accepted TLSv1.0 112 bits DES-CBC3-SHA  Accepted TLSv1.0 128 bits TLS_RSA_WITH_RC4_128_MD5  Accepted TLSv1.0 128 bits TLS_RSA_WITH_RC4_128_SHA  Accepted TLSv1.0 128 bits TLS_RSA_WITH_IDEA_CBC_SHA Accepted TLSv1.0 128 bits TLS_RSA_WITH_SEED_CBC_SHA Accepted TLSv1.0 128 bits TLS_DHE_RSA_WITH_SEED_CBC_SHA Accepted TLSv1.0 128 bits TLS_ECDHE_RSA_WITH_RC4_128_SHA Server Key Exchange Group(s): TLSv1.2 128 bits secp256r1 (NIST P-256) SSL Certificate: Signature Algorithm: sha256WithRSAEncryption RSA Key Strength: 2048 Subject: whythefuckwasibreached.com Issuer: /C=XX/ST=Nowhere in particular/L=Nowhere Not valid before: Dec 3 03:01:23 2019 GMT Not valid after: Dec 3 03:01:23 2029 GMT sslscan-2.1.2/docker_test/expected_output/test_10.txt000066400000000000000000000014211452476416400227440ustar00rootroot00000000000000 Connected to 127.0.0.1 Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 SSL/TLS Protocols: SSLv2 disabled SSLv3 disabled TLSv1.0 disabled TLSv1.1 disabled TLSv1.2 enabled TLSv1.3 disabled Supported Server Cipher(s): Preferred 400 Bad Request TLSv1.2 256 bits ECDHE-RSA-CHACHA20-POLY1305  Curve 25519 DHE 253 SSL Certificate: Signature Algorithm: sha256WithRSAEncryption RSA Key Strength: 3072 Subject: lmgtfy.com Issuer: /C=XX/ST=Nowhere in particular/L=Nowhere Not valid before: Dec 3 04:07:43 2019 GMT Not valid after: Dec 3 04:07:43 2029 GMT sslscan-2.1.2/docker_test/expected_output/test_11.txt000066400000000000000000000012251452476416400227470ustar00rootroot00000000000000 Connected to Testing SSL server www.amazon.com on port 443 using SNI name www.amazon.com SSL/TLS Protocols: SSLv2 disabled SSLv3 disabled TLSv1.0 enabled TLSv1.1 enabled TLSv1.2 enabled TLSv1.3 enabled OCSP Stapling Request: OCSP Response Status: successful (0x0) Response Type: Basic OCSP Response Version: 1 (0x0) Responder Id: Produced At: Responses: Certificate ID: Hash Algorithm: Issuer Name Hash: Issuer Key Hash: Serial Number: Cert Status: good This Update: Next Update: sslscan-2.1.2/docker_test/expected_output/test_12.txt000066400000000000000000000055701452476416400227570ustar00rootroot00000000000000 Connected to 127.0.0.1 Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 SSL/TLS Protocols: SSLv2 enabled SSLv3 enabled TLSv1.0 enabled TLSv1.1 disabled TLSv1.2 disabled TLSv1.3 disabled TLS Fallback SCSV: Server does not support TLS Fallback SCSV TLS renegotiation: Secure session renegotiation supported TLS Compression: Compression enabled (CRIME) Heartbleed: TLSv1.0 not vulnerable to heartbleed Supported Server Cipher(s): Preferred TLSv1.0 256 bits ECDHE-RSA-AES256-SHA Curve P-256 DHE 256 Accepted TLSv1.0 256 bits DHE-RSA-AES256-SHA DHE 512 bits Accepted TLSv1.0 256 bits DHE-RSA-CAMELLIA256-SHA DHE 512 bits Accepted TLSv1.0 128 bits ECDHE-RSA-AES128-SHA Curve P-256 DHE 256 Accepted TLSv1.0 128 bits DHE-RSA-AES128-SHA DHE 512 bits Accepted TLSv1.0 128 bits DHE-RSA-CAMELLIA128-SHA DHE 512 bits Accepted TLSv1.0 112 bits ECDHE-RSA-DES-CBC3-SHA  Curve P-256 DHE 256 Accepted TLSv1.0 112 bits DHE-RSA-DES-CBC3-SHA  DHE 512 bits Accepted TLSv1.0 256 bits AES256-SHA Accepted TLSv1.0 256 bits CAMELLIA256-SHA Accepted TLSv1.0 128 bits AES128-SHA Accepted TLSv1.0 128 bits CAMELLIA128-SHA Accepted TLSv1.0 112 bits DES-CBC3-SHA  Accepted TLSv1.0 128 bits TLS_RSA_WITH_RC4_128_MD5  Accepted TLSv1.0 128 bits TLS_RSA_WITH_RC4_128_SHA  Accepted TLSv1.0 128 bits TLS_RSA_WITH_IDEA_CBC_SHA Accepted TLSv1.0 56 bits TLS_RSA_WITH_DES_CBC_SHA  Accepted TLSv1.0 56 bits TLS_DHE_RSA_WITH_DES_CBC_SHA  Accepted TLSv1.0 128 bits TLS_RSA_WITH_SEED_CBC_SHA Accepted TLSv1.0 128 bits TLS_DHE_RSA_WITH_SEED_CBC_SHA Accepted TLSv1.0 128 bits TLS_ECDHE_RSA_WITH_RC4_128_SHA Server Key Exchange Group(s): TLSv1.0 128 bits secp256r1 (NIST P-256) SSL Certificate: Signature Algorithm: md5WithRSAEncryption RSA Key Strength: 512 Subject: geocities.com Issuer: /C=XX/ST=Nowhere in particular/L=Nowhere Not valid before: Dec 13 03:56:22 2019 GMT Not valid after: Dec 13 03:56:22 2029 GMT sslscan-2.1.2/docker_test/expected_output/test_13.txt000066400000000000000000000114031452476416400227500ustar00rootroot00000000000000 Connected to 127.0.0.1 Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 SSL/TLS Protocols: SSLv2 disabled SSLv3 disabled TLSv1.0 enabled TLSv1.1 enabled TLSv1.2 enabled TLSv1.3 enabled TLS Fallback SCSV: Server supports TLS Fallback SCSV TLS renegotiation: Secure session renegotiation supported TLS Compression: Compression disabled Heartbleed: TLSv1.3 not vulnerable to heartbleed TLSv1.2 not vulnerable to heartbleed TLSv1.1 not vulnerable to heartbleed TLSv1.0 not vulnerable to heartbleed Supported Server Cipher(s): Preferred TLSv1.3 128 bits TLS_AES_128_GCM_SHA256  Curve 25519 DHE 253 Accepted TLSv1.3 256 bits TLS_AES_256_GCM_SHA384  Curve 25519 DHE 253 Accepted TLSv1.3 256 bits TLS_CHACHA20_POLY1305_SHA256  Curve 25519 DHE 253 Accepted TLSv1.3 128 bits TLS_AES_128_CCM_SHA256 Curve 25519 DHE 253 Preferred TLSv1.2 256 bits ECDHE-RSA-AES256-GCM-SHA384  Curve 25519 DHE 253 Accepted TLSv1.2 256 bits DHE-RSA-AES256-GCM-SHA384  DHE 2048 bits Accepted TLSv1.2 256 bits ECDHE-RSA-CHACHA20-POLY1305  Curve 25519 DHE 253 Accepted TLSv1.2 256 bits DHE-RSA-CHACHA20-POLY1305  DHE 2048 bits Accepted TLSv1.2 256 bits DHE-RSA-AES256-CCM DHE 2048 bits Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-GCM-SHA256  Curve 25519 DHE 253 Accepted TLSv1.2 128 bits DHE-RSA-AES128-GCM-SHA256  DHE 2048 bits Accepted TLSv1.2 128 bits DHE-RSA-AES128-CCM DHE 2048 bits Accepted TLSv1.2 256 bits ECDHE-RSA-AES256-SHA Curve 25519 DHE 253 Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA DHE 2048 bits Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-SHA Curve 25519 DHE 253 Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA DHE 2048 bits Accepted TLSv1.2 256 bits AES256-GCM-SHA384 Accepted TLSv1.2 256 bits AES256-CCM Accepted TLSv1.2 128 bits AES128-GCM-SHA256 Accepted TLSv1.2 128 bits AES128-CCM Accepted TLSv1.2 256 bits AES256-SHA Accepted TLSv1.2 128 bits AES128-SHA Preferred TLSv1.1 256 bits ECDHE-RSA-AES256-SHA Curve 25519 DHE 253 Accepted TLSv1.1 256 bits DHE-RSA-AES256-SHA DHE 2048 bits Accepted TLSv1.1 128 bits ECDHE-RSA-AES128-SHA Curve 25519 DHE 253 Accepted TLSv1.1 128 bits DHE-RSA-AES128-SHA DHE 2048 bits Accepted TLSv1.1 256 bits AES256-SHA Accepted TLSv1.1 128 bits AES128-SHA Preferred TLSv1.0 256 bits ECDHE-RSA-AES256-SHA Curve 25519 DHE 253 Accepted TLSv1.0 256 bits DHE-RSA-AES256-SHA DHE 2048 bits Accepted TLSv1.0 128 bits ECDHE-RSA-AES128-SHA Curve 25519 DHE 253 Accepted TLSv1.0 128 bits DHE-RSA-AES128-SHA DHE 2048 bits Accepted TLSv1.0 256 bits AES256-SHA Accepted TLSv1.0 128 bits AES128-SHA Server Key Exchange Group(s): TLSv1.3 128 bits secp256r1 (NIST P-256) TLSv1.3 192 bits secp384r1 (NIST P-384) TLSv1.3 260 bits secp521r1 (NIST P-521) TLSv1.3 128 bits x25519 TLSv1.3 112 bits ffdhe2048 TLSv1.3 128 bits ffdhe3072 TLSv1.3 150 bits ffdhe4096 TLSv1.3 175 bits ffdhe6144 TLSv1.3 192 bits ffdhe8192 TLSv1.2 128 bits secp256r1 (NIST P-256) TLSv1.2 192 bits secp384r1 (NIST P-384) TLSv1.2 260 bits secp521r1 (NIST P-521) TLSv1.2 128 bits x25519 SSL Certificate: Signature Algorithm: sha256WithRSAEncryption RSA Key Strength: 3072 Subject: lmgtfy.com Issuer: /C=XX/ST=Nowhere in particular/L=Nowhere Not valid before: Dec 3 04:07:43 2019 GMT Not valid after: Dec 3 04:07:43 2029 GMT sslscan-2.1.2/docker_test/expected_output/test_14.txt000066400000000000000000000060371452476416400227600ustar00rootroot00000000000000 Connected to 127.0.0.1 Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 SSL/TLS Protocols: SSLv2 disabled SSLv3 disabled TLSv1.0 disabled TLSv1.1 disabled TLSv1.2 enabled TLSv1.3 enabled TLS Fallback SCSV: Server supports TLS Fallback SCSV TLS renegotiation: Session renegotiation not supported TLS Compression: Compression disabled Heartbleed: TLSv1.3 not vulnerable to heartbleed TLSv1.2 not vulnerable to heartbleed Supported Server Cipher(s): Preferred TLSv1.3 128 bits TLS_AES_128_GCM_SHA256  Curve P-521 DHE 521 Accepted TLSv1.3 256 bits TLS_AES_256_GCM_SHA384  Curve P-521 DHE 521 Accepted TLSv1.3 256 bits TLS_CHACHA20_POLY1305_SHA256  Curve P-521 DHE 521 Accepted TLSv1.3 128 bits TLS_AES_128_CCM_SHA256 Curve P-521 DHE 521 Preferred TLSv1.2 256 bits ECDHE-RSA-AES256-GCM-SHA384  Curve P-521 DHE 521 Accepted TLSv1.2 256 bits DHE-RSA-AES256-GCM-SHA384  DHE 8192 bits Accepted TLSv1.2 256 bits ECDHE-RSA-CHACHA20-POLY1305  Curve P-521 DHE 521 Accepted TLSv1.2 256 bits DHE-RSA-CHACHA20-POLY1305  DHE 8192 bits Accepted TLSv1.2 256 bits DHE-RSA-AES256-CCM DHE 8192 bits Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-GCM-SHA256  Curve P-521 DHE 521 Accepted TLSv1.2 128 bits DHE-RSA-AES128-GCM-SHA256  DHE 8192 bits Accepted TLSv1.2 128 bits DHE-RSA-AES128-CCM DHE 8192 bits Accepted TLSv1.2 256 bits ECDHE-RSA-AES256-SHA Curve P-521 DHE 521 Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA DHE 8192 bits Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-SHA Curve P-521 DHE 521 Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA DHE 8192 bits Accepted TLSv1.2 256 bits AES256-GCM-SHA384 Accepted TLSv1.2 256 bits AES256-CCM Accepted TLSv1.2 128 bits AES128-GCM-SHA256 Accepted TLSv1.2 128 bits AES128-CCM Accepted TLSv1.2 256 bits AES256-SHA Accepted TLSv1.2 128 bits AES128-SHA Server Key Exchange Group(s): TLSv1.3 260 bits secp521r1 (NIST P-521) TLSv1.3 192 bits ffdhe8192 TLSv1.2 260 bits secp521r1 (NIST P-521) SSL Certificate: Signature Algorithm: sha256WithRSAEncryption RSA Key Strength: 3072 Subject: lmgtfy.com Issuer: /C=XX/ST=Nowhere in particular/L=Nowhere Not valid before: Dec 3 04:07:43 2019 GMT Not valid after: Dec 3 04:07:43 2029 GMT sslscan-2.1.2/docker_test/expected_output/test_15.txt000066400000000000000000000065401452476416400227600ustar00rootroot00000000000000 Connected to 127.0.0.1 Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 SSL/TLS Protocols: SSLv2 disabled SSLv3 disabled TLSv1.0 enabled TLSv1.1 enabled TLSv1.2 enabled TLSv1.3 enabled TLS Fallback SCSV: Server supports TLS Fallback SCSV TLS renegotiation: Secure session renegotiation supported TLS Compression: Compression disabled Heartbleed: TLSv1.3 not vulnerable to heartbleed TLSv1.2 not vulnerable to heartbleed TLSv1.1 not vulnerable to heartbleed TLSv1.0 not vulnerable to heartbleed Supported Server Cipher(s): Preferred TLSv1.3 128 bits TLS_AES_128_GCM_SHA256  Curve 25519 DHE 253 Accepted TLSv1.3 256 bits TLS_AES_256_GCM_SHA384  Curve 25519 DHE 253 Accepted TLSv1.3 256 bits TLS_CHACHA20_POLY1305_SHA256  Curve 25519 DHE 253 Accepted TLSv1.3 128 bits TLS_AES_128_CCM_SHA256 Curve 25519 DHE 253 Preferred TLSv1.2 256 bits ECDHE-ECDSA-AES256-GCM-SHA384 Curve 25519 DHE 253 Accepted TLSv1.2 256 bits ECDHE-ECDSA-CHACHA20-POLY1305 Curve 25519 DHE 253 Accepted TLSv1.2 256 bits ECDHE-ECDSA-AES256-CCM Curve 25519 DHE 253 Accepted TLSv1.2 128 bits ECDHE-ECDSA-AES128-GCM-SHA256 Curve 25519 DHE 253 Accepted TLSv1.2 128 bits ECDHE-ECDSA-AES128-CCM Curve 25519 DHE 253 Accepted TLSv1.2 256 bits ECDHE-ECDSA-AES256-SHA Curve 25519 DHE 253 Accepted TLSv1.2 128 bits ECDHE-ECDSA-AES128-SHA Curve 25519 DHE 253 Preferred TLSv1.1 256 bits ECDHE-ECDSA-AES256-SHA Curve 25519 DHE 253 Accepted TLSv1.1 128 bits ECDHE-ECDSA-AES128-SHA Curve 25519 DHE 253 Preferred TLSv1.0 256 bits ECDHE-ECDSA-AES256-SHA Curve 25519 DHE 253 Accepted TLSv1.0 128 bits ECDHE-ECDSA-AES128-SHA Curve 25519 DHE 253 Server Key Exchange Group(s): TLSv1.3 128 bits secp256r1 (NIST P-256) TLSv1.3 192 bits secp384r1 (NIST P-384) TLSv1.3 260 bits secp521r1 (NIST P-521) TLSv1.3 128 bits x25519 TLSv1.3 112 bits ffdhe2048 TLSv1.3 128 bits ffdhe3072 TLSv1.3 150 bits ffdhe4096 TLSv1.3 175 bits ffdhe6144 TLSv1.3 192 bits ffdhe8192 TLSv1.2 128 bits secp256r1 (NIST P-256) TLSv1.2 192 bits secp384r1 (NIST P-384) TLSv1.2 260 bits secp521r1 (NIST P-521) TLSv1.2 128 bits x25519 SSL Certificate: Signature Algorithm: sha256WithRSAEncryption ECC Curve Name: prime256v1 ECC Key Strength: 128 Subject: itspeanutbutterjellytime.com Issuer: /C=XX/ST=Nowhere in particular/L=Nowhere Not valid before: Dec 22 19:01:56 2019 GMT Not valid after: Dec 22 19:01:56 2029 GMT sslscan-2.1.2/docker_test/expected_output/test_16.txt000066400000000000000000000053731452476416400227640ustar00rootroot00000000000000 Connected to 127.0.0.1 Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 SSL/TLS Protocols: SSLv2 disabled SSLv3 disabled TLSv1.0 disabled TLSv1.1 disabled TLSv1.2 enabled TLSv1.3 disabled TLS Fallback SCSV: Server supports TLS Fallback SCSV TLS renegotiation: Session renegotiation not supported TLS Compression: Compression disabled Heartbleed: TLSv1.2 not vulnerable to heartbleed Supported Server Cipher(s): Preferred TLSv1.2 256 bits DHE-RSA-AES256-GCM-SHA384  DHE 2048 bits Accepted TLSv1.2 128 bits DHE-RSA-AES128-GCM-SHA256  DHE 2048 bits Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA256 DHE 2048 bits Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA256 DHE 2048 bits Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA DHE 2048 bits Accepted TLSv1.2 256 bits DHE-RSA-CAMELLIA256-SHA DHE 2048 bits Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA DHE 2048 bits Accepted TLSv1.2 128 bits DHE-RSA-CAMELLIA128-SHA DHE 2048 bits Accepted TLSv1.2 112 bits DHE-RSA-DES-CBC3-SHA  DHE 2048 bits Accepted TLSv1.2 256 bits AES256-GCM-SHA384 Accepted TLSv1.2 128 bits AES128-GCM-SHA256 Accepted TLSv1.2 256 bits AES256-SHA256 Accepted TLSv1.2 128 bits AES128-SHA256 Accepted TLSv1.2 256 bits AES256-SHA Accepted TLSv1.2 256 bits CAMELLIA256-SHA Accepted TLSv1.2 128 bits AES128-SHA Accepted TLSv1.2 128 bits CAMELLIA128-SHA Accepted TLSv1.2 112 bits DES-CBC3-SHA  Accepted TLSv1.2 128 bits TLS_RSA_WITH_RC4_128_MD5  Accepted TLSv1.2 128 bits TLS_RSA_WITH_RC4_128_SHA  Accepted TLSv1.2 128 bits TLS_RSA_WITH_IDEA_CBC_SHA Accepted TLSv1.2 128 bits TLS_RSA_WITH_SEED_CBC_SHA Accepted TLSv1.2 128 bits TLS_DHE_RSA_WITH_SEED_CBC_SHA Server Key Exchange Group(s): TLSv1.2 81 bits sect163k1 SSL Certificate: Signature Algorithm: sha256WithRSAEncryption RSA Key Strength: 1024 Subject: howfuckedismydatabase.com Issuer: /C=XX/ST=Nowhere in particular/L=Nowhere Not valid before: Dec 3 03:56:52 2019 GMT Not valid after: Dec 3 03:56:52 2029 GMT sslscan-2.1.2/docker_test/expected_output/test_17.txt000066400000000000000000000041351452476416400227600ustar00rootroot00000000000000 Connected to 127.0.0.1 Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 SSL/TLS Protocols: SSLv2 disabled SSLv3 disabled TLSv1.0 disabled TLSv1.1 disabled TLSv1.2 enabled TLSv1.3 disabled TLS Fallback SCSV: Server supports TLS Fallback SCSV TLS renegotiation: Session renegotiation not supported TLS Compression: Compression disabled Heartbleed: TLSv1.2 not vulnerable to heartbleed Supported Server Cipher(s): Preferred TLSv1.2 256 bits DHE-RSA-AES256-GCM-SHA384  DHE 1024 bits Accepted TLSv1.2 256 bits DHE-RSA-CHACHA20-POLY1305  DHE 1024 bits Accepted TLSv1.2 128 bits DHE-RSA-AES128-GCM-SHA256  DHE 1024 bits Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA256 DHE 1024 bits Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA256 DHE 1024 bits Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA DHE 1024 bits Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA DHE 1024 bits Accepted TLSv1.2 256 bits AES256-GCM-SHA384 Accepted TLSv1.2 128 bits AES128-GCM-SHA256 Accepted TLSv1.2 256 bits AES256-SHA256 Accepted TLSv1.2 128 bits AES128-SHA256 Accepted TLSv1.2 256 bits AES256-SHA Accepted TLSv1.2 128 bits AES128-SHA Server Key Exchange Group(s): TLSv1.2 256 bits brainpoolP512r1 SSL Certificate: Signature Algorithm: sha256WithRSAEncryption RSA Key Strength: 1024 Subject: howfuckedismydatabase.com Issuer: /C=XX/ST=Nowhere in particular/L=Nowhere Not valid before: Dec 3 03:56:52 2019 GMT Not valid after: Dec 3 03:56:52 2029 GMT sslscan-2.1.2/docker_test/expected_output/test_18.txt000066400000000000000000000030331452476416400227550ustar00rootroot00000000000000 Connected to 127.0.0.1 Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 SSL/TLS Protocols: SSLv2 disabled SSLv3 disabled TLSv1.0 disabled TLSv1.1 disabled TLSv1.2 enabled TLSv1.3 disabled TLS Fallback SCSV: Server supports TLS Fallback SCSV TLS renegotiation: Session renegotiation not supported TLS Compression: Compression disabled Heartbleed: TLSv1.2 not vulnerable to heartbleed Supported Server Cipher(s): Preferred TLSv1.2 256 bits ECDHE-ECDSA-CHACHA20-POLY1305 Curve 25519 DHE 253 Accepted TLSv1.2 128 bits ECDHE-ECDSA-AES128-GCM-SHA256 Curve 25519 DHE 253 Accepted TLSv1.2 128 bits TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 Server Key Exchange Group(s): TLSv1.2 128 bits secp256r1 (NIST P-256) TLSv1.2 192 bits secp384r1 (NIST P-384) TLSv1.2 260 bits secp521r1 (NIST P-521) TLSv1.2 128 bits x25519 SSL Certificate: Signature Algorithm: sha256WithRSAEncryption ECC Curve Name: prime256v1 ECC Key Strength: 128 Subject: itspeanutbutterjellytime.com Issuer: /C=XX/ST=Nowhere in particular/L=Nowhere Not valid before: Dec 22 19:01:56 2019 GMT Not valid after: Dec 22 19:01:56 2029 GMT sslscan-2.1.2/docker_test/expected_output/test_2.txt000066400000000000000000000014541452476416400226730ustar00rootroot00000000000000 Connected to 127.0.0.1 Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 SSL/TLS Protocols: SSLv2 enabled SSLv3 disabled TLSv1.0 disabled TLSv1.1 disabled TLSv1.2 disabled TLSv1.3 disabled TLS Fallback SCSV: Connection failed - unable to determine TLS Fallback SCSV support TLS renegotiation: Session renegotiation not supported TLS Compression: Compression disabled Heartbleed: Supported Server Cipher(s): Unable to parse certificate Unable to parse certificate Unable to parse certificate Unable to parse certificate Certificate information cannot be retrieved. sslscan-2.1.2/docker_test/expected_output/test_3.txt000066400000000000000000000014541452476416400226740ustar00rootroot00000000000000 Connected to 127.0.0.1 Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 SSL/TLS Protocols: SSLv2 disabled SSLv3 enabled TLSv1.0 disabled TLSv1.1 disabled TLSv1.2 disabled TLSv1.3 disabled TLS Fallback SCSV: Connection failed - unable to determine TLS Fallback SCSV support TLS renegotiation: Session renegotiation not supported TLS Compression: Compression disabled Heartbleed: Supported Server Cipher(s): Unable to parse certificate Unable to parse certificate Unable to parse certificate Unable to parse certificate Certificate information cannot be retrieved. sslscan-2.1.2/docker_test/expected_output/test_4.txt000066400000000000000000000113351452476416400226740ustar00rootroot00000000000000 Connected to 127.0.0.1 Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 SSL/TLS Protocols: SSLv2 disabled SSLv3 disabled TLSv1.0 enabled TLSv1.1 enabled TLSv1.2 enabled TLSv1.3 enabled TLS Fallback SCSV: Server supports TLS Fallback SCSV TLS renegotiation: Secure session renegotiation supported TLS Compression: Compression disabled Heartbleed: TLSv1.3 not vulnerable to heartbleed TLSv1.2 not vulnerable to heartbleed TLSv1.1 not vulnerable to heartbleed TLSv1.0 not vulnerable to heartbleed Supported Server Cipher(s): Preferred TLSv1.3 128 bits TLS_AES_128_GCM_SHA256  Curve 25519 DHE 253 Accepted TLSv1.3 256 bits TLS_AES_256_GCM_SHA384  Curve 25519 DHE 253 Accepted TLSv1.3 256 bits TLS_CHACHA20_POLY1305_SHA256  Curve 25519 DHE 253 Preferred TLSv1.2 256 bits ECDHE-RSA-AES256-GCM-SHA384  Curve 25519 DHE 253 Accepted TLSv1.2 256 bits DHE-RSA-AES256-GCM-SHA384  DHE 3072 bits Accepted TLSv1.2 256 bits ECDHE-RSA-CHACHA20-POLY1305  Curve 25519 DHE 253 Accepted TLSv1.2 256 bits DHE-RSA-CHACHA20-POLY1305  DHE 3072 bits Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-GCM-SHA256  Curve 25519 DHE 253 Accepted TLSv1.2 128 bits DHE-RSA-AES128-GCM-SHA256  DHE 3072 bits Accepted TLSv1.2 256 bits ECDHE-RSA-AES256-SHA384 Curve 25519 DHE 253 Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA256 DHE 3072 bits Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-SHA256 Curve 25519 DHE 253 Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA256 DHE 3072 bits Accepted TLSv1.2 256 bits ECDHE-RSA-AES256-SHA Curve 25519 DHE 253 Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA DHE 3072 bits Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-SHA Curve 25519 DHE 253 Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA DHE 3072 bits Accepted TLSv1.2 256 bits AES256-GCM-SHA384 Accepted TLSv1.2 128 bits AES128-GCM-SHA256 Accepted TLSv1.2 256 bits AES256-SHA256 Accepted TLSv1.2 128 bits AES128-SHA256 Accepted TLSv1.2 256 bits AES256-SHA Accepted TLSv1.2 128 bits AES128-SHA Preferred TLSv1.1 256 bits ECDHE-RSA-AES256-SHA Curve 25519 DHE 253 Accepted TLSv1.1 256 bits DHE-RSA-AES256-SHA DHE 3072 bits Accepted TLSv1.1 128 bits ECDHE-RSA-AES128-SHA Curve 25519 DHE 253 Accepted TLSv1.1 128 bits DHE-RSA-AES128-SHA DHE 3072 bits Accepted TLSv1.1 256 bits AES256-SHA Accepted TLSv1.1 128 bits AES128-SHA Preferred TLSv1.0 256 bits ECDHE-RSA-AES256-SHA Curve 25519 DHE 253 Accepted TLSv1.0 256 bits DHE-RSA-AES256-SHA DHE 3072 bits Accepted TLSv1.0 128 bits ECDHE-RSA-AES128-SHA Curve 25519 DHE 253 Accepted TLSv1.0 128 bits DHE-RSA-AES128-SHA DHE 3072 bits Accepted TLSv1.0 256 bits AES256-SHA Accepted TLSv1.0 128 bits AES128-SHA Server Key Exchange Group(s): TLSv1.3 128 bits secp256r1 (NIST P-256) TLSv1.3 192 bits secp384r1 (NIST P-384) TLSv1.3 260 bits secp521r1 (NIST P-521) TLSv1.3 128 bits x25519 TLSv1.3 224 bits x448 TLSv1.2 128 bits secp256r1 (NIST P-256) TLSv1.2 192 bits secp384r1 (NIST P-384) TLSv1.2 260 bits secp521r1 (NIST P-521) TLSv1.2 128 bits x25519 TLSv1.2 224 bits x448 SSL Certificate: Signature Algorithm: sha256WithRSAEncryption RSA Key Strength: 3072 Subject: lmgtfy.com Issuer: /C=XX/ST=Nowhere in particular/L=Nowhere Not valid before: Dec 3 04:07:43 2019 GMT Not valid after: Dec 3 04:07:43 2029 GMT sslscan-2.1.2/docker_test/expected_output/test_5.txt000066400000000000000000000300341452476416400226720ustar00rootroot00000000000000 Connected to 127.0.0.1 Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 SSL/TLS Protocols: SSLv2 disabled SSLv3 enabled TLSv1.0 enabled TLSv1.1 enabled TLSv1.2 enabled TLSv1.3 disabled TLS Fallback SCSV: Server supports TLS Fallback SCSV TLS renegotiation: Secure session renegotiation supported TLS Compression: Compression enabled (CRIME) Heartbleed: TLSv1.2 not vulnerable to heartbleed TLSv1.1 not vulnerable to heartbleed TLSv1.0 not vulnerable to heartbleed Supported Server Cipher(s): Preferred TLSv1.2 256 bits ECDHE-RSA-AES256-GCM-SHA384  Curve P-256 DHE 256 Accepted TLSv1.2 256 bits DHE-RSA-AES256-GCM-SHA384  DHE 1024 bits Accepted TLSv1.2 256 bits ADH-AES256-GCM-SHA384  DHE 1024 bits Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-GCM-SHA256  Curve P-256 DHE 256 Accepted TLSv1.2 128 bits DHE-RSA-AES128-GCM-SHA256  DHE 1024 bits Accepted TLSv1.2 128 bits ADH-AES128-GCM-SHA256  DHE 1024 bits Accepted TLSv1.2 256 bits ECDHE-RSA-AES256-SHA384 Curve P-256 DHE 256 Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA256 DHE 1024 bits Accepted TLSv1.2 256 bits ADH-AES256-SHA256  DHE 1024 bits Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-SHA256 Curve P-256 DHE 256 Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA256 DHE 1024 bits Accepted TLSv1.2 128 bits ADH-AES128-SHA256  DHE 1024 bits Accepted TLSv1.2 256 bits ECDHE-RSA-AES256-SHA Curve P-256 DHE 256 Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA DHE 1024 bits Accepted TLSv1.2 256 bits DHE-RSA-CAMELLIA256-SHA DHE 1024 bits Accepted TLSv1.2 256 bits AECDH-AES256-SHA  Curve P-256 DHE 256 Accepted TLSv1.2 256 bits ADH-AES256-SHA  DHE 1024 bits Accepted TLSv1.2 256 bits ADH-CAMELLIA256-SHA  DHE 1024 bits Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-SHA Curve P-256 DHE 256 Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA DHE 1024 bits Accepted TLSv1.2 128 bits DHE-RSA-CAMELLIA128-SHA DHE 1024 bits Accepted TLSv1.2 128 bits AECDH-AES128-SHA  Curve P-256 DHE 256 Accepted TLSv1.2 128 bits ADH-AES128-SHA  DHE 1024 bits Accepted TLSv1.2 128 bits ADH-CAMELLIA128-SHA  DHE 1024 bits Accepted TLSv1.2 112 bits ECDHE-RSA-DES-CBC3-SHA  Curve P-256 DHE 256 Accepted TLSv1.2 112 bits DHE-RSA-DES-CBC3-SHA  DHE 1024 bits Accepted TLSv1.2 112 bits AECDH-DES-CBC3-SHA  Curve P-256 DHE 256 Accepted TLSv1.2 112 bits ADH-DES-CBC3-SHA  DHE 1024 bits Accepted TLSv1.2 256 bits AES256-GCM-SHA384 Accepted TLSv1.2 128 bits AES128-GCM-SHA256 Accepted TLSv1.2 256 bits AES256-SHA256 Accepted TLSv1.2 128 bits AES128-SHA256 Accepted TLSv1.2 256 bits AES256-SHA Accepted TLSv1.2 256 bits CAMELLIA256-SHA Accepted TLSv1.2 128 bits AES128-SHA Accepted TLSv1.2 128 bits CAMELLIA128-SHA Accepted TLSv1.2 112 bits DES-CBC3-SHA  Accepted TLSv1.2 40 bits TLS_RSA_EXPORT_WITH_RC4_40_MD5 Accepted TLSv1.2 128 bits TLS_RSA_WITH_RC4_128_MD5  Accepted TLSv1.2 128 bits TLS_RSA_WITH_RC4_128_SHA  Accepted TLSv1.2 40 bits TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 Accepted TLSv1.2 128 bits TLS_RSA_WITH_IDEA_CBC_SHA Accepted TLSv1.2 40 bits TLS_RSA_EXPORT_WITH_DES40_CBC_SHA Accepted TLSv1.2 56 bits TLS_RSA_WITH_DES_CBC_SHA  Accepted TLSv1.2 56 bits TLS_DHE_RSA_WITH_DES_CBC_SHA  Accepted TLSv1.2 128 bits TLS_DH_anon_WITH_RC4_128_MD5  Accepted TLSv1.2 56 bits TLS_DH_anon_WITH_DES_CBC_SHA  Accepted TLSv1.2 128 bits TLS_RSA_WITH_SEED_CBC_SHA Accepted TLSv1.2 128 bits TLS_DHE_RSA_WITH_SEED_CBC_SHA Accepted TLSv1.2 128 bits TLS_DH_anon_WITH_SEED_CBC_SHA Accepted TLSv1.2 128 bits TLS_ECDHE_RSA_WITH_RC4_128_SHA Accepted TLSv1.2 128 bits TLS_ECDH_anon_WITH_RC4_128_SHA Preferred TLSv1.1 256 bits ECDHE-RSA-AES256-SHA Curve P-256 DHE 256 Accepted TLSv1.1 256 bits DHE-RSA-AES256-SHA DHE 1024 bits Accepted TLSv1.1 256 bits DHE-RSA-CAMELLIA256-SHA DHE 1024 bits Accepted TLSv1.1 256 bits AECDH-AES256-SHA  Curve P-256 DHE 256 Accepted TLSv1.1 256 bits ADH-AES256-SHA  DHE 1024 bits Accepted TLSv1.1 256 bits ADH-CAMELLIA256-SHA  DHE 1024 bits Accepted TLSv1.1 128 bits ECDHE-RSA-AES128-SHA Curve P-256 DHE 256 Accepted TLSv1.1 128 bits DHE-RSA-AES128-SHA DHE 1024 bits Accepted TLSv1.1 128 bits DHE-RSA-CAMELLIA128-SHA DHE 1024 bits Accepted TLSv1.1 128 bits AECDH-AES128-SHA  Curve P-256 DHE 256 Accepted TLSv1.1 128 bits ADH-AES128-SHA  DHE 1024 bits Accepted TLSv1.1 128 bits ADH-CAMELLIA128-SHA  DHE 1024 bits Accepted TLSv1.1 112 bits ECDHE-RSA-DES-CBC3-SHA  Curve P-256 DHE 256 Accepted TLSv1.1 112 bits DHE-RSA-DES-CBC3-SHA  DHE 1024 bits Accepted TLSv1.1 112 bits AECDH-DES-CBC3-SHA  Curve P-256 DHE 256 Accepted TLSv1.1 112 bits ADH-DES-CBC3-SHA  DHE 1024 bits Accepted TLSv1.1 256 bits AES256-SHA Accepted TLSv1.1 256 bits CAMELLIA256-SHA Accepted TLSv1.1 128 bits AES128-SHA Accepted TLSv1.1 128 bits CAMELLIA128-SHA Accepted TLSv1.1 112 bits DES-CBC3-SHA  Accepted TLSv1.1 40 bits TLS_RSA_EXPORT_WITH_RC4_40_MD5 Accepted TLSv1.1 128 bits TLS_RSA_WITH_RC4_128_MD5  Accepted TLSv1.1 128 bits TLS_RSA_WITH_RC4_128_SHA  Accepted TLSv1.1 40 bits TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 Accepted TLSv1.1 128 bits TLS_RSA_WITH_IDEA_CBC_SHA Accepted TLSv1.1 40 bits TLS_RSA_EXPORT_WITH_DES40_CBC_SHA Accepted TLSv1.1 56 bits TLS_RSA_WITH_DES_CBC_SHA  Accepted TLSv1.1 56 bits TLS_DHE_RSA_WITH_DES_CBC_SHA  Accepted TLSv1.1 128 bits TLS_DH_anon_WITH_RC4_128_MD5  Accepted TLSv1.1 56 bits TLS_DH_anon_WITH_DES_CBC_SHA  Accepted TLSv1.1 128 bits TLS_RSA_WITH_SEED_CBC_SHA Accepted TLSv1.1 128 bits TLS_DHE_RSA_WITH_SEED_CBC_SHA Accepted TLSv1.1 128 bits TLS_DH_anon_WITH_SEED_CBC_SHA Accepted TLSv1.1 128 bits TLS_ECDHE_RSA_WITH_RC4_128_SHA Accepted TLSv1.1 128 bits TLS_ECDH_anon_WITH_RC4_128_SHA Preferred TLSv1.0 256 bits ECDHE-RSA-AES256-SHA Curve P-256 DHE 256 Accepted TLSv1.0 256 bits DHE-RSA-AES256-SHA DHE 1024 bits Accepted TLSv1.0 256 bits DHE-RSA-CAMELLIA256-SHA DHE 1024 bits Accepted TLSv1.0 256 bits AECDH-AES256-SHA  Curve P-256 DHE 256 Accepted TLSv1.0 256 bits ADH-AES256-SHA  DHE 1024 bits Accepted TLSv1.0 256 bits ADH-CAMELLIA256-SHA  DHE 1024 bits Accepted TLSv1.0 128 bits ECDHE-RSA-AES128-SHA Curve P-256 DHE 256 Accepted TLSv1.0 128 bits DHE-RSA-AES128-SHA DHE 1024 bits Accepted TLSv1.0 128 bits DHE-RSA-CAMELLIA128-SHA DHE 1024 bits Accepted TLSv1.0 128 bits AECDH-AES128-SHA  Curve P-256 DHE 256 Accepted TLSv1.0 128 bits ADH-AES128-SHA  DHE 1024 bits Accepted TLSv1.0 128 bits ADH-CAMELLIA128-SHA  DHE 1024 bits Accepted TLSv1.0 112 bits ECDHE-RSA-DES-CBC3-SHA  Curve P-256 DHE 256 Accepted TLSv1.0 112 bits DHE-RSA-DES-CBC3-SHA  DHE 1024 bits Accepted TLSv1.0 112 bits AECDH-DES-CBC3-SHA  Curve P-256 DHE 256 Accepted TLSv1.0 112 bits ADH-DES-CBC3-SHA  DHE 1024 bits Accepted TLSv1.0 256 bits AES256-SHA Accepted TLSv1.0 256 bits CAMELLIA256-SHA Accepted TLSv1.0 128 bits AES128-SHA Accepted TLSv1.0 128 bits CAMELLIA128-SHA Accepted TLSv1.0 112 bits DES-CBC3-SHA  Accepted TLSv1.0 40 bits TLS_RSA_EXPORT_WITH_RC4_40_MD5 Accepted TLSv1.0 128 bits TLS_RSA_WITH_RC4_128_MD5  Accepted TLSv1.0 128 bits TLS_RSA_WITH_RC4_128_SHA  Accepted TLSv1.0 40 bits TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 Accepted TLSv1.0 128 bits TLS_RSA_WITH_IDEA_CBC_SHA Accepted TLSv1.0 40 bits TLS_RSA_EXPORT_WITH_DES40_CBC_SHA Accepted TLSv1.0 56 bits TLS_RSA_WITH_DES_CBC_SHA  Accepted TLSv1.0 56 bits TLS_DHE_RSA_WITH_DES_CBC_SHA  Accepted TLSv1.0 128 bits TLS_DH_anon_WITH_RC4_128_MD5  Accepted TLSv1.0 56 bits TLS_DH_anon_WITH_DES_CBC_SHA  Accepted TLSv1.0 128 bits TLS_RSA_WITH_SEED_CBC_SHA Accepted TLSv1.0 128 bits TLS_DHE_RSA_WITH_SEED_CBC_SHA Accepted TLSv1.0 128 bits TLS_DH_anon_WITH_SEED_CBC_SHA Accepted TLSv1.0 128 bits TLS_ECDHE_RSA_WITH_RC4_128_SHA Accepted TLSv1.0 128 bits TLS_ECDH_anon_WITH_RC4_128_SHA Server Key Exchange Group(s): TLSv1.2 128 bits secp256r1 (NIST P-256) SSL Certificate: Signature Algorithm: sha256WithRSAEncryption RSA Key Strength: 1024 Subject: howfuckedismydatabase.com Issuer: /C=XX/ST=Nowhere in particular/L=Nowhere Not valid before: Dec 3 03:56:52 2019 GMT Not valid after: Dec 3 03:56:52 2029 GMT sslscan-2.1.2/docker_test/expected_output/test_6.txt000066400000000000000000000034261452476416400227000ustar00rootroot00000000000000 Connected to 127.0.0.1 Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 SSL/TLS Protocols: SSLv2 disabled SSLv3 disabled TLSv1.0 disabled TLSv1.1 disabled TLSv1.2 disabled TLSv1.3 enabled TLS Fallback SCSV: Server supports TLS Fallback SCSV TLS renegotiation: Session renegotiation not supported TLS Compression: Compression disabled Heartbleed: TLSv1.3 not vulnerable to heartbleed Supported Server Cipher(s): Preferred TLSv1.3 128 bits TLS_AES_128_GCM_SHA256  Curve 25519 DHE 253 Accepted TLSv1.3 256 bits TLS_AES_256_GCM_SHA384  Curve 25519 DHE 253 Accepted TLSv1.3 256 bits TLS_CHACHA20_POLY1305_SHA256  Curve 25519 DHE 253 Accepted TLSv1.3 128 bits TLS_AES_128_CCM_SHA256 Curve 25519 DHE 253 Accepted TLSv1.3 128 bits TLS_AES_128_CCM_8_SHA256 Curve 25519 DHE 253 Server Key Exchange Group(s): TLSv1.3 128 bits secp256r1 (NIST P-256) TLSv1.3 192 bits secp384r1 (NIST P-384) TLSv1.3 260 bits secp521r1 (NIST P-521) TLSv1.3 128 bits x25519 TLSv1.3 224 bits x448 SSL Certificate: Signature Algorithm: sha256WithRSAEncryption RSA Key Strength: 3072 Subject: lmgtfy.com Issuer: /C=XX/ST=Nowhere in particular/L=Nowhere Not valid before: Dec 3 04:07:43 2019 GMT Not valid after: Dec 3 04:07:43 2029 GMT sslscan-2.1.2/docker_test/expected_output/test_7.txt000066400000000000000000000055711452476416400227040ustar00rootroot00000000000000 Connected to 127.0.0.1 Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 SSL/TLS Protocols: SSLv2 enabled SSLv3 enabled TLSv1.0 enabled TLSv1.1 disabled TLSv1.2 disabled TLSv1.3 disabled TLS Fallback SCSV: Server does not support TLS Fallback SCSV TLS renegotiation: Secure session renegotiation supported TLS Compression: Compression enabled (CRIME) Heartbleed: TLSv1.0 not vulnerable to heartbleed Supported Server Cipher(s): Preferred TLSv1.0 256 bits ECDHE-RSA-AES256-SHA Curve P-256 DHE 256 Accepted TLSv1.0 256 bits DHE-RSA-AES256-SHA DHE 512 bits Accepted TLSv1.0 256 bits DHE-RSA-CAMELLIA256-SHA DHE 512 bits Accepted TLSv1.0 128 bits ECDHE-RSA-AES128-SHA Curve P-256 DHE 256 Accepted TLSv1.0 128 bits DHE-RSA-AES128-SHA DHE 512 bits Accepted TLSv1.0 128 bits DHE-RSA-CAMELLIA128-SHA DHE 512 bits Accepted TLSv1.0 112 bits ECDHE-RSA-DES-CBC3-SHA  Curve P-256 DHE 256 Accepted TLSv1.0 112 bits DHE-RSA-DES-CBC3-SHA  DHE 512 bits Accepted TLSv1.0 256 bits AES256-SHA Accepted TLSv1.0 256 bits CAMELLIA256-SHA Accepted TLSv1.0 128 bits AES128-SHA Accepted TLSv1.0 128 bits CAMELLIA128-SHA Accepted TLSv1.0 112 bits DES-CBC3-SHA  Accepted TLSv1.0 128 bits TLS_RSA_WITH_RC4_128_MD5  Accepted TLSv1.0 128 bits TLS_RSA_WITH_RC4_128_SHA  Accepted TLSv1.0 128 bits TLS_RSA_WITH_IDEA_CBC_SHA Accepted TLSv1.0 56 bits TLS_RSA_WITH_DES_CBC_SHA  Accepted TLSv1.0 56 bits TLS_DHE_RSA_WITH_DES_CBC_SHA  Accepted TLSv1.0 128 bits TLS_RSA_WITH_SEED_CBC_SHA Accepted TLSv1.0 128 bits TLS_DHE_RSA_WITH_SEED_CBC_SHA Accepted TLSv1.0 128 bits TLS_ECDHE_RSA_WITH_RC4_128_SHA Server Key Exchange Group(s): TLSv1.0 128 bits secp256r1 (NIST P-256) SSL Certificate: Signature Algorithm: sha256WithRSAEncryption RSA Key Strength: 3072 Subject: lmgtfy.com Issuer: /C=XX/ST=Nowhere in particular/L=Nowhere Not valid before: Dec 3 04:07:43 2019 GMT Not valid after: Dec 3 04:07:43 2029 GMT sslscan-2.1.2/docker_test/expected_output/test_8.txt000066400000000000000000000117171452476416400227040ustar00rootroot00000000000000 Connected to 127.0.0.1 Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 SSL/TLS Protocols: SSLv2 enabled SSLv3 enabled TLSv1.0 enabled TLSv1.1 disabled TLSv1.2 disabled TLSv1.3 disabled TLS Fallback SCSV: Server does not support TLS Fallback SCSV TLS renegotiation: Secure session renegotiation supported TLS Compression: Compression enabled (CRIME) Heartbleed: TLSv1.0 not vulnerable to heartbleed Supported Server Cipher(s): Preferred TLSv1.0 256 bits ECDHE-RSA-AES256-SHA Curve P-256 DHE 256 Accepted TLSv1.0 256 bits DHE-RSA-AES256-SHA DHE 512 bits Accepted TLSv1.0 256 bits DHE-RSA-CAMELLIA256-SHA DHE 512 bits Accepted TLSv1.0 256 bits AECDH-AES256-SHA  Curve P-256 DHE 256 Accepted TLSv1.0 256 bits ADH-AES256-SHA  DHE 512 bits Accepted TLSv1.0 256 bits ADH-CAMELLIA256-SHA  DHE 512 bits Accepted TLSv1.0 128 bits ECDHE-RSA-AES128-SHA Curve P-256 DHE 256 Accepted TLSv1.0 128 bits DHE-RSA-AES128-SHA DHE 512 bits Accepted TLSv1.0 128 bits DHE-RSA-CAMELLIA128-SHA DHE 512 bits Accepted TLSv1.0 128 bits AECDH-AES128-SHA  Curve P-256 DHE 256 Accepted TLSv1.0 128 bits ADH-AES128-SHA  DHE 512 bits Accepted TLSv1.0 128 bits ADH-CAMELLIA128-SHA  DHE 512 bits Accepted TLSv1.0 112 bits ECDHE-RSA-DES-CBC3-SHA  Curve P-256 DHE 256 Accepted TLSv1.0 112 bits DHE-RSA-DES-CBC3-SHA  DHE 512 bits Accepted TLSv1.0 112 bits AECDH-DES-CBC3-SHA  Curve P-256 DHE 256 Accepted TLSv1.0 112 bits ADH-DES-CBC3-SHA  DHE 512 bits Accepted TLSv1.0 256 bits AES256-SHA Accepted TLSv1.0 256 bits CAMELLIA256-SHA Accepted TLSv1.0 128 bits AES128-SHA Accepted TLSv1.0 128 bits CAMELLIA128-SHA Accepted TLSv1.0 112 bits DES-CBC3-SHA  Accepted TLSv1.0 0 bits ECDHE-RSA-NULL-SHA  Curve P-256 DHE 256 Accepted TLSv1.0 0 bits AECDH-NULL-SHA  Curve P-256 DHE 256 Accepted TLSv1.0 0 bits NULL-SHA  Accepted TLSv1.0 0 bits NULL-MD5  Accepted TLSv1.0 40 bits TLS_RSA_EXPORT_WITH_RC4_40_MD5 Accepted TLSv1.0 128 bits TLS_RSA_WITH_RC4_128_MD5  Accepted TLSv1.0 128 bits TLS_RSA_WITH_RC4_128_SHA  Accepted TLSv1.0 40 bits TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 Accepted TLSv1.0 128 bits TLS_RSA_WITH_IDEA_CBC_SHA Accepted TLSv1.0 40 bits TLS_RSA_EXPORT_WITH_DES40_CBC_SHA Accepted TLSv1.0 56 bits TLS_RSA_WITH_DES_CBC_SHA  Accepted TLSv1.0 40 bits TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA Accepted TLSv1.0 56 bits TLS_DHE_RSA_WITH_DES_CBC_SHA  Accepted TLSv1.0 40 bits TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 Accepted TLSv1.0 128 bits TLS_DH_anon_WITH_RC4_128_MD5  Accepted TLSv1.0 40 bits TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA Accepted TLSv1.0 56 bits TLS_DH_anon_WITH_DES_CBC_SHA  Accepted TLSv1.0 128 bits TLS_RSA_WITH_SEED_CBC_SHA Accepted TLSv1.0 128 bits TLS_DHE_RSA_WITH_SEED_CBC_SHA Accepted TLSv1.0 128 bits TLS_DH_anon_WITH_SEED_CBC_SHA Accepted TLSv1.0 128 bits TLS_ECDHE_RSA_WITH_RC4_128_SHA Accepted TLSv1.0 128 bits TLS_ECDH_anon_WITH_RC4_128_SHA Server Key Exchange Group(s): TLSv1.0 128 bits secp256r1 (NIST P-256) SSL Certificate: Signature Algorithm: sha256WithRSAEncryption RSA Key Strength: 3072 Subject: lmgtfy.com Issuer: /C=XX/ST=Nowhere in particular/L=Nowhere Not valid before: Dec 3 04:07:43 2019 GMT Not valid after: Dec 3 04:07:43 2029 GMT sslscan-2.1.2/docker_test/expected_output/test_9.txt000066400000000000000000000014211452476416400226740ustar00rootroot00000000000000 Connected to 127.0.0.1 Testing SSL server 127.0.0.1 on port 4443 using SNI name 127.0.0.1 SSL/TLS Protocols: SSLv2 disabled SSLv3 disabled TLSv1.0 disabled TLSv1.1 disabled TLSv1.2 enabled TLSv1.3 disabled Supported Server Cipher(s): Preferred 200 OK TLSv1.2 256 bits ECDHE-RSA-CHACHA20-POLY1305  Curve 25519 DHE 253 SSL Certificate: Signature Algorithm: sha256WithRSAEncryption RSA Key Strength: 3072 Subject: lmgtfy.com Issuer: /C=XX/ST=Nowhere in particular/L=Nowhere Not valid before: Dec 3 04:07:43 2019 GMT Not valid after: Dec 3 04:07:43 2029 GMT sslscan-2.1.2/docker_test/key_1024.pem000066400000000000000000000015731452476416400174540ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIICXgIBAAKBgQDmpPrmBNS3gqCgCB9lKvH4ZpX9FvHzw3P4kNbyN45+8yq7gBUp f9JYFQO0rqm0hSebJSQUDkhrFfO6onZdsMyN32lPlVPFmBILMBPgaxJTVUOa+TWx gyVuPgaftrMQMr0Wvhbv+3Xht5hqPTEKe/GEwxXJKPSm2F1AgAkkwlQRzQIDAQAB AoGBAJgeR7xdg05lQTtLICnBYUXLozEBaSK0zlAqdxnZuonQJ2by2wI746dkdMU+ TX9aMv0ISftQUEMQf2egryCr8rx+yq8bI7LVF8H210x+8BT0H+gmd0iIcFNJNL0l WSSIAmRVTbSK0IwsvEDwR+Egcnd8wA/9s/s9d2GmbChjisIBAkEA/QY1YLKkG+IT Ad7GaOKv/UFQNLu7yLDtfjJcJ+dpjCWPv1B/orh6dwFJ4F+7MYruu0BAXhnvw70s uyPH9W290QJBAOlbZEZtl5n5iL+czI0Ibkyn9VlZ44kgVQHs9Y5hFG0Hv1VH66EP hU7ZeUUfSmiPqnTcVEKQFZjl09FSoVzTJz0CQQDROzsUlWTjsdUp7MCBp0ME1+et U7j7QmOBwb83OEOtorn16GlDc+3BTw16P2+ajlrP+VfA+Q2t/VdqATKvH2qhAkBk zLJ67Zn/y9czFbMR9KNYf3CuwPJVaF7v7wB/GRYuppsSZne04bRuw+frYMHOeshh pE7NVdnOavBdSfkj1J3tAkEAjQ/+3cGCBiv9lnDdlszKW/Zq4Uu19znfQSbSbI8L JezLQJbSlVDPG3W3NSNkLizrOg1H6AG2pnnVq2q++Lt5tQ== -----END RSA PRIVATE KEY----- sslscan-2.1.2/docker_test/key_2048.pem000066400000000000000000000032171452476416400174600ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEpQIBAAKCAQEAywGmJp/AoA4TCs6zbXuiBOkho35IeVvpsy7RqM3y3KxkEFnk /LM6U/ayL+j2vo4/15WPM0PaAGRRbvnQEuI1xvhn/0/T4xP+TBe91pTMo/nKrK/y cvBLBqLPZQK9SJbHk6mwfgpQs5S/+VHlU9jl7+eQWcR+o3NXtv4XFlQyqx1dcokA JrL4wr2vGPkigUNU2iI6FwRB4f7Wo1rBNzI49uE97IWuh+VBMPYMp+Zn2Om4ptCy jdvSI7DEYc6jyKlPzH2UOgd0RkcwivaSpxfXJEBOC8PtOxyLg/KPjUTwUh0nHSpe OIbT3HKnOErEbbiHQmlYbbcOyinv3hIlRj+PyQIDAQABAoIBAGiA09BkQpviQuk4 WOOOVmxiut9YHeTjbN3Bx0o3osL4t5Y3QIrZlLgucbH6IjMcNT88jXgdgLbc7ZLM ZNGjw31G2Pp0VKY735e6TQ6OkP4Ek9HrzUpf6q9i1pKwI1Kf0+Nu4h0wIDUh6OVm xEAyksO6F/QuE+b+dHQOP0JOW7r7uxTMB/tbs1U+idcIRVrPTlO9Ixuaolmd/flz jmcwwTtwBe+mA53IywCOV6ZxO3lMKzDkSvViRam37fmSh9JJyPEa6KpPTR5ps3w8 7eG0u9nsEf1wYVA2u575iH4+uM6250bRuw3icZxTU2FPuMOtzJPnxY+A6q13bteW h0zdzbUCgYEA6ryUy+BSOIFzX4e6dB2gwmn2PUEF1rO9dOG8H0YktOGHnHFDXECy FYHf6njWEzwztd9ZiE8YQYjAjn829Gr4e45H6rEPAMzSpOJ/ZoLd6PG8d5L6A7AD RtMS8KzG2fAMwvd0HJ0N4SwuwhFmq6/TLHB9vstwo0myyYqH2qWIOAcCgYEA3WVC 2VnrcuMZngYpXP+gWQDhkIxI7yqUhTB+OZGxHMMjfJ72JHKOI3StnQWSqhxmFtWF x+XtnihcaWG+G7Po6TmW75oazoitqXjiixJOXGrN3jcmFj97nIh3NlhG2mskP9Ut 5iDE2w2nDRk1eI+13c7j12/bJy7kdi70gr0l5a8CgYEA03V6nYbAysJiyqYco0ml bj3CYz/WIKnefBJ2Q74Ohxu77IRj6BEn3BQZQMIGJ2HOO4KuxwppkW+99yBGwzwy CCwOQS+rkk7xWzPnDNPLUHOkEhvHOdcvvHec0k7y+5UyCdidMsGQpU4F+TFvyi4k EB5uSJhAKfjUJJa095Sy97UCgYEAlOLpPtP6w+s3qg7IuFLsWY5/Ir9EuRowgRVo fXyd2BLfBYq9SyuCrRNlQeiihiXM/eQgMJtO3gKUiwYBXA30PwvMlltTVbuS1hqG dzIbYoks4xjBU0rj7RPU38Yj9/T/jrHlSRKWcB3RTry6OdajXoQosxP1FHezikrv ghCDsN8CgYEA4JuCSuOxmP5/4MTl9oLUDHDbUBGPZICR+2Y0I76kRISQbHT+oidz /ceQpOP20fBQquVhMrHmKthyN13TvBSn5SaNIa5SVIIGhVZJQPU1/Udfox1gx7iF TcFx7dbMIh7byuVRy8iIyaVYr9ZtSX+6mYWFUXVrzF9LTGyDVta6YQA= -----END RSA PRIVATE KEY----- sslscan-2.1.2/docker_test/key_3072.pem000066400000000000000000000046271452476416400174640ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIG4gIBAAKCAYEAxA1ToQ2HLVYDmKSjPSlCposbUMYA30BlRXMzdJe1OVBg/qwE rhURlFAvGF9ljgXFnMZ6oTK164sJXscjNXS/AbqWO9rBeMbUxD85/PRo4emmBVio e5A/A4xbAvPt1snwgjbtZNTsxZoheUox216/NTJ24c3SGEBOlASBHtT6VBJPamx1 aALlSlS4jqtLAlkxz6M/XUPeRER6DKYXUi37w0XCZRRk1U2ueM2nfkz47a/GxoeA WmvWPVW1Bu+VbJb9Hsh/2otyhHZAVX9/fsKZwHf9qcSrutLk5M0ix9NUFnq8qZVu ZLTZa7/rCw6YnmlOv1mAZJ8sNJtt1wyhMGLebkfVHKERCqk37LRpSzloTu95+uPu /q+391XMKTOmMHqwhvZBpAoOvN7bs4o8N1JF8hPu+MBGsZUs8P+e9WTJU29zvORW d7Z/8K1zakihJD9FXcC38OGO88h/7JVxYcMyVUZW3zZKxITlJWl8J18OqQpT66K4 ceLOW1SjRIeHGX9TAgMBAAECggF/D1D7N5nW9bPClCpIln6itmAnwie16bseLk7R tkoj3lZpPXwy4WbD+NJK25yYUoAg8B6RdgaAL+as1Lq6BXMZeQkas5Jjiwv9k1dd MGXny751OfWzM/QQ+DX+5jwoWJ9uKr4fzcDUvptMAi3Jt1mvlnha0UlDIKHlgarY a5A3/llv2uCeS4HuZ+A2iu7W7VgKjC40xRSISM0Qu+w95i2xfY/1n+/38LIg708h xrw8tlUFMn1jiazjD+eiPOh6xAEHojAGu1actfW+jg8NySpTGWAUPfTxXV9J6r/c BdCldXP5lQHfWKBIAKUK9MZyrFFQnZZMdPDXyyKsfbO04gVW5BsEK9Br5dnGbFGu e+Ve4jOCAC9//wLqgLDL2t3CCnnPU1bGFnqLqzwtEKrEP3XeK1CFLYCwOZ2tUH9h IbQRZKbEMlsXR4XvplmwjNqRb/uHSIVmPJ1DVXbFZy/2j7i59+Kl+JqINHEPvGc1 tfLOFvOHYRWRONkylj3O+qH6lyECgcEA+CErcMNYkM7Y2uRRB2UhQQ96NDoflQmg uObO0XTnhMbRFrRRrgEr0POOo4oCqDSVQk/vJjmB1ugo/IKxGphnAOmi1xDpSXqo UWnUR34nrqL76ZdV1R3FZX0b4iO9X1R/P9sNl4S0+XCDyAMlcaXroPoUIo9mzxbX vIAk6lMiJijfzLt7RssVCfgCfHZ9srBMG5oaEfTbFImc9fwjNoJdLTDopEQzA1X5 AjVa8VhIGyE+uoLkPsy9jBNF9asEEdc/AoHBAMpFSKUdTIXuYOOGltr1qFAMofUU +ztagHg1/UdV3EOhkYZOfpa4clu++x0MNp+bRySxEK6IOpEtSaKHaJlHnvR4+4e7 xQp/jBoWCrxWtqXHe3ufyglsq/1ID7HIEGfBs9IAVPx9PkY9IOC8cXX3q9uRB7xM MCtl/H8QMf01f4p3vEgx+XXb2+MKsjOqOVDpAqfqrcUmTiK9ixC7BJWwWSBAvN4e 2jS4UEOoBiczX6qhKo+tUEddfnAJGnxp2cZG7QKBwHwU8klIltCLb+w+grrE+tUz LTRS4JpCH0p3uXMLF//RAJxu/e2bDlNGiM0FZgDBkuZ/XKNr3J8gp+ZmYLRhBBlz vIf6H/8rxGI6HvrFfoiZXopYsIaLhbwTzU7P+pJiiePf4jMkHPAkMPJjiGUFyQhO JqWFuq7SyH2uQ0ee3RPiGtCh7KrhQZsjl/KvunoSKW0gKetS2/+wNXrZZK6MkJXZ wGzs4enII2bUUa8hK6XNgTX54LP65MrYlIKey8E0NwKBwHBb3kfCJ8D6Mx4QpHoL Hi0hZ1ISDqDg3B5qt0BKJKn49TKrJcyptvTZ+Pogz7MHeZSbO04IZKhChPXgzCzh SR46mlbC6mizg2r2NY57iMg8MI7yqzNjB4MR5Y33OY25Xx9Xid4b4Fz6FephI5HJ O9EjFi32EIf7BjC7GVmzvx529sMP56gdsl7DkUv70gzs8sm+Jjsu1RadPcPUb26L YGb3LzMf5kyE2ilLC+f4tLq+/jqDpuWNvO+VTv4veoaW3QKBwQDQlmXDJ+4SdYnD QkHis9G5AnyXkUHhBFTWLyhsJMrt3CZyVp8L7xXgEJTsSVoyvURimeBmua4LEqci 5PPo1fOfyEqUIrHIJVR26ATeMsxC3icV6kna7cD0K1BILtAGTJeO7sWceFhl2QJb E4wio0Vljyt+foytCL/KV3bIj/OYGk8bUp1OMzEIXot4kx3l2SOf+cYE5UDca9Ey Z/6IvSvAP/JSqo2pk4azaqxSuZIMQnZB2YlFxllCZ6ce/Z6YcSs= -----END RSA PRIVATE KEY----- sslscan-2.1.2/docker_test/key_512.pem000066400000000000000000000007611452476416400173730ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIBPQIBAAJBAMvdzx+XSLVGpLLVy0NIBZVs6k7Lxviu5Cym+5n0zbwsYKtiralI vc0HPekJik1o/QLgqcO83837wOS8hPU0k9UCAwEAAQJBAJP8Vj7TXZchSar7oMod PNhkMI20RKH+qmlzaU4vsyx1Kqcv2uTkAPMugNZZtRP7bOYU9inbH8LUIrHJIpZP /H0CIQDliBIQF6c7uaVbjCZ4iki9wnGZ5JA8hFZDoREgJCsHxwIhAONgFmVUzsUw Z/hjjodDMMX9KgZ0pYHSfbKoNRuJzZ+DAiEAp9ooC2igvUZ3rEkDYScPJuXpGXdS G09TnkVNNsn8RcUCIQCQ2ERMFwOFgHmrNRi1uCrY5Zag+Cv7ELE8X4U9XsLbqwIh ALM7UlYJ1ZKAFlK2cnqUCiLoD7Ah9eVfg+rOTUVMOa3v -----END RSA PRIVATE KEY----- sslscan-2.1.2/docker_test/key_ecdsa_prime256v1.pem000066400000000000000000000003431452476416400220370ustar00rootroot00000000000000-----BEGIN EC PRIVATE KEY----- MHcCAQEEIP5zy1nQDeAkFKDZ1F/ur26G7SBeu1HbCgbNLwFVUzrroAoGCCqGSM49 AwEHoUQDQgAEQkb8ffhxrztFHu3PiZ4MarPyxX6dJKXb5UEkVbczdbzkLzhOXHlY blnXr4a2mwrSEFPzjCORSjQqk99jv90IVg== -----END EC PRIVATE KEY----- sslscan-2.1.2/docker_test/key_notes.txt000066400000000000000000000014061452476416400202470ustar00rootroot00000000000000There is one Certificate Authority in this directory: ca_cert.pem / ca_key.pem. This CA directly signed these certificates (with their corresponding keys): * cert_512.crt / key_512.pem * cert_1024.crt / key_3072.pem * cert_2048.crt / key_2048.pem * cert_3072.crt / key_3072.pem The 512, 1024, 2048, and 3072 refer to the RSA key size. --- To generate new keys, and sign them by the CA: 1.) Generate the key. * For RSA keys: openssl genrsa -out key.pem 1024 * For ECDSA keys: openssl ecparam -name prime256v1 -genkey -noout -out key.pem 2.) Make CSR: openssl req -new -key key.pem -out new.csr 3.) Sign with CA: openssl x509 -req -days 3653 -in new.csr -CA path/to/ca_cert.pem -CAkey path/to/ca_key.pem -CAcreateserial -out new.crt [-md5|-sha1|-sha256] sslscan-2.1.2/docker_test/nginx_site_client_cert_required000066400000000000000000000012071452476416400240520ustar00rootroot00000000000000server { listen 443 ssl default_server; listen [::]:443 ssl default_server; gzip off; root /var/www/html; index index.html index.nginx-debian.html; server_name _; location / { try_files $uri $uri/ =404; } # Only TLSv1.2 with one cipher is specified, so the test that runs against this # finishes quicker (all that's needed is the HTTP response of one successful # TLS connection). ssl_protocols TLSv1.2; ssl_ciphers ECDHE-RSA-CHACHA20-POLY1305; ssl_prefer_server_ciphers on; ssl_certificate /etc/ssl/cert_3072.crt; ssl_certificate_key /etc/ssl/key_3072.pem; ssl_client_certificate /etc/ssl/ca_cert.pem; ssl_verify_client on; } sslscan-2.1.2/docker_test/nginx_test9.conf000066400000000000000000000006571452476416400206370ustar00rootroot00000000000000user www-data; worker_processes auto; pid /run/nginx.pid; daemon off; events { worker_connections 768; } http { sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; include /etc/nginx/mime.types; default_type application/octet-stream; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; include /etc/nginx/sites-available/nginx_site_client_cert_required; } sslscan-2.1.2/missing_ciphersuites.h000066400000000000000000001046551452476416400176230ustar00rootroot00000000000000#ifndef _MISSING_CIPHERSUITES_H #define _MISSING_CIPHERSUITES_H /* At run-time, the findMissingCiphers() function will enumerate all the ciphers that OpenSSL knows of, and compares them each to the missing_ciphersuites list. Afterwards, the 'check_tls_versions' field will have the set of TLS versions that OpenSSL does not have an implementation for (i.e.: if the TLS_RSA_WITH_IDEA_CBC_SHA cipher is set to V1_2, then OpenSSL has an implementation for it for TLS v1.0 and v1.1, but not for v1.2). */ #define V1_0 (1) #define V1_1 (1 << 1) #define V1_2 (1 << 2) #define VALL (V1_0 | V1_1 | V1_2) struct missing_ciphersuite { unsigned short id; /* TLS protocol ID. */ char protocol_name[48]; /* IANA name, as defined in the RFCs. */ int bits; /* Bit strength of the cipher. -1 if unknown. */ unsigned int check_tls_versions; /* OR'ed list of V1_? defines. Refers to TLS version that OpenSSL does not have a ciphersuite implementation for. Hence, it should be tested under this version of TLS. */ unsigned int accepted_tls_versions; /* OR'ed list of V1_? defines. Set at run-time if this ciphersuite was accepted by the server by the specified TLS version. */ }; /* Auto-generated by ./iana_tls_ciphersuite_parser.py on December 10, 2019. */ struct missing_ciphersuite missing_ciphersuites[] = { {0x0000, "TLS_NULL_WITH_NULL_NULL", -1, VALL, 0}, {0x0001, "TLS_RSA_WITH_NULL_MD5", -1, VALL, 0}, {0x0002, "TLS_RSA_WITH_NULL_SHA", -1, VALL, 0}, {0x0003, "TLS_RSA_EXPORT_WITH_RC4_40_MD5", 40, VALL, 0}, {0x0004, "TLS_RSA_WITH_RC4_128_MD5", 128, VALL, 0}, {0x0005, "TLS_RSA_WITH_RC4_128_SHA", 128, VALL, 0}, {0x0006, "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5", 40, VALL, 0}, {0x0007, "TLS_RSA_WITH_IDEA_CBC_SHA", 128, VALL, 0}, {0x0008, "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA", 40, VALL, 0}, {0x0009, "TLS_RSA_WITH_DES_CBC_SHA", 56, VALL, 0}, {0x000A, "TLS_RSA_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, {0x000B, "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA", 40, VALL, 0}, {0x000C, "TLS_DH_DSS_WITH_DES_CBC_SHA", 56, VALL, 0}, {0x000D, "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, {0x000E, "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA", 40, VALL, 0}, {0x000F, "TLS_DH_RSA_WITH_DES_CBC_SHA", 56, VALL, 0}, {0x0010, "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, {0x0011, "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", 40, VALL, 0}, {0x0012, "TLS_DHE_DSS_WITH_DES_CBC_SHA", 56, VALL, 0}, {0x0013, "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, {0x0014, "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", 40, VALL, 0}, {0x0015, "TLS_DHE_RSA_WITH_DES_CBC_SHA", 56, VALL, 0}, {0x0016, "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, {0x0017, "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5", 40, VALL, 0}, {0x0018, "TLS_DH_anon_WITH_RC4_128_MD5", 128, VALL, 0}, {0x0019, "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA", 40, VALL, 0}, {0x001A, "TLS_DH_anon_WITH_DES_CBC_SHA", 56, VALL, 0}, {0x001B, "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, {0x001E, "TLS_KRB5_WITH_DES_CBC_SHA", 56, VALL, 0}, {0x001F, "TLS_KRB5_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, {0x0020, "TLS_KRB5_WITH_RC4_128_SHA", 128, VALL, 0}, {0x0021, "TLS_KRB5_WITH_IDEA_CBC_SHA", 128, VALL, 0}, {0x0022, "TLS_KRB5_WITH_DES_CBC_MD5", 56, VALL, 0}, {0x0023, "TLS_KRB5_WITH_3DES_EDE_CBC_MD5", 112, VALL, 0}, {0x0024, "TLS_KRB5_WITH_RC4_128_MD5", 128, VALL, 0}, {0x0025, "TLS_KRB5_WITH_IDEA_CBC_MD5", 128, VALL, 0}, {0x0026, "TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA", 56, VALL, 0}, {0x0027, "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA", 40, VALL, 0}, {0x0028, "TLS_KRB5_EXPORT_WITH_RC4_40_SHA", 40, VALL, 0}, {0x0029, "TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5", 56, VALL, 0}, {0x002A, "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5", 40, VALL, 0}, {0x002B, "TLS_KRB5_EXPORT_WITH_RC4_40_MD5", 40, VALL, 0}, {0x002C, "TLS_PSK_WITH_NULL_SHA", -1, VALL, 0}, {0x002D, "TLS_DHE_PSK_WITH_NULL_SHA", -1, VALL, 0}, {0x002E, "TLS_RSA_PSK_WITH_NULL_SHA", -1, VALL, 0}, {0x002F, "TLS_RSA_WITH_AES_128_CBC_SHA", 128, VALL, 0}, {0x0030, "TLS_DH_DSS_WITH_AES_128_CBC_SHA", 128, VALL, 0}, {0x0031, "TLS_DH_RSA_WITH_AES_128_CBC_SHA", 128, VALL, 0}, {0x0032, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", 128, VALL, 0}, {0x0033, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", 128, VALL, 0}, {0x0034, "TLS_DH_anon_WITH_AES_128_CBC_SHA", 128, VALL, 0}, {0x0035, "TLS_RSA_WITH_AES_256_CBC_SHA", 256, VALL, 0}, {0x0036, "TLS_DH_DSS_WITH_AES_256_CBC_SHA", 256, VALL, 0}, {0x0037, "TLS_DH_RSA_WITH_AES_256_CBC_SHA", 256, VALL, 0}, {0x0038, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA", 256, VALL, 0}, {0x0039, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA", 256, VALL, 0}, {0x003A, "TLS_DH_anon_WITH_AES_256_CBC_SHA", 256, VALL, 0}, {0x003B, "TLS_RSA_WITH_NULL_SHA256", -1, VALL, 0}, {0x003C, "TLS_RSA_WITH_AES_128_CBC_SHA256", 128, VALL, 0}, {0x003D, "TLS_RSA_WITH_AES_256_CBC_SHA256", 256, VALL, 0}, {0x003E, "TLS_DH_DSS_WITH_AES_128_CBC_SHA256", 128, VALL, 0}, {0x003F, "TLS_DH_RSA_WITH_AES_128_CBC_SHA256", 128, VALL, 0}, {0x0040, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256", 128, VALL, 0}, {0x0041, "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA", 128, VALL, 0}, {0x0042, "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA", 128, VALL, 0}, {0x0043, "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA", 128, VALL, 0}, {0x0044, "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA", 128, VALL, 0}, {0x0045, "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA", 128, VALL, 0}, {0x0046, "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA", 128, VALL, 0}, {0x0067, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256", 128, VALL, 0}, {0x0068, "TLS_DH_DSS_WITH_AES_256_CBC_SHA256", 256, VALL, 0}, {0x0069, "TLS_DH_RSA_WITH_AES_256_CBC_SHA256", 256, VALL, 0}, {0x006A, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256", 256, VALL, 0}, {0x006B, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256", 256, VALL, 0}, {0x006C, "TLS_DH_anon_WITH_AES_128_CBC_SHA256", 128, VALL, 0}, {0x006D, "TLS_DH_anon_WITH_AES_256_CBC_SHA256", 256, VALL, 0}, {0x0084, "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA", 256, VALL, 0}, {0x0085, "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA", 256, VALL, 0}, {0x0086, "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA", 256, VALL, 0}, {0x0087, "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA", 256, VALL, 0}, {0x0088, "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA", 256, VALL, 0}, {0x0089, "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA", 256, VALL, 0}, {0x008A, "TLS_PSK_WITH_RC4_128_SHA", 128, VALL, 0}, {0x008B, "TLS_PSK_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, {0x008C, "TLS_PSK_WITH_AES_128_CBC_SHA", 128, VALL, 0}, {0x008D, "TLS_PSK_WITH_AES_256_CBC_SHA", 256, VALL, 0}, {0x008E, "TLS_DHE_PSK_WITH_RC4_128_SHA", 128, VALL, 0}, {0x008F, "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, {0x0090, "TLS_DHE_PSK_WITH_AES_128_CBC_SHA", 128, VALL, 0}, {0x0091, "TLS_DHE_PSK_WITH_AES_256_CBC_SHA", 256, VALL, 0}, {0x0092, "TLS_RSA_PSK_WITH_RC4_128_SHA", 128, VALL, 0}, {0x0093, "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, {0x0094, "TLS_RSA_PSK_WITH_AES_128_CBC_SHA", 128, VALL, 0}, {0x0095, "TLS_RSA_PSK_WITH_AES_256_CBC_SHA", 256, VALL, 0}, {0x0096, "TLS_RSA_WITH_SEED_CBC_SHA", 128, VALL, 0}, {0x0097, "TLS_DH_DSS_WITH_SEED_CBC_SHA", 128, VALL, 0}, {0x0098, "TLS_DH_RSA_WITH_SEED_CBC_SHA", 128, VALL, 0}, {0x0099, "TLS_DHE_DSS_WITH_SEED_CBC_SHA", 128, VALL, 0}, {0x009A, "TLS_DHE_RSA_WITH_SEED_CBC_SHA", 128, VALL, 0}, {0x009B, "TLS_DH_anon_WITH_SEED_CBC_SHA", 128, VALL, 0}, {0x009C, "TLS_RSA_WITH_AES_128_GCM_SHA256", 128, VALL, 0}, {0x009D, "TLS_RSA_WITH_AES_256_GCM_SHA384", 256, VALL, 0}, {0x009E, "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", 128, VALL, 0}, {0x009F, "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", 256, VALL, 0}, {0x00A0, "TLS_DH_RSA_WITH_AES_128_GCM_SHA256", 128, VALL, 0}, {0x00A1, "TLS_DH_RSA_WITH_AES_256_GCM_SHA384", 256, VALL, 0}, {0x00A2, "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", 128, VALL, 0}, {0x00A3, "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", 256, VALL, 0}, {0x00A4, "TLS_DH_DSS_WITH_AES_128_GCM_SHA256", 128, VALL, 0}, {0x00A5, "TLS_DH_DSS_WITH_AES_256_GCM_SHA384", 256, VALL, 0}, {0x00A6, "TLS_DH_anon_WITH_AES_128_GCM_SHA256", 128, VALL, 0}, {0x00A7, "TLS_DH_anon_WITH_AES_256_GCM_SHA384", 256, VALL, 0}, {0x00A8, "TLS_PSK_WITH_AES_128_GCM_SHA256", 128, VALL, 0}, {0x00A9, "TLS_PSK_WITH_AES_256_GCM_SHA384", 256, VALL, 0}, {0x00AA, "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256", 128, VALL, 0}, {0x00AB, "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384", 256, VALL, 0}, {0x00AC, "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256", 128, VALL, 0}, {0x00AD, "TLS_RSA_PSK_WITH_AES_256_GCM_SHA384", 256, VALL, 0}, {0x00AE, "TLS_PSK_WITH_AES_128_CBC_SHA256", 128, VALL, 0}, {0x00AF, "TLS_PSK_WITH_AES_256_CBC_SHA384", 256, VALL, 0}, {0x00B0, "TLS_PSK_WITH_NULL_SHA256", -1, VALL, 0}, {0x00B1, "TLS_PSK_WITH_NULL_SHA384", -1, VALL, 0}, {0x00B2, "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256", 128, VALL, 0}, {0x00B3, "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384", 256, VALL, 0}, {0x00B4, "TLS_DHE_PSK_WITH_NULL_SHA256", -1, VALL, 0}, {0x00B5, "TLS_DHE_PSK_WITH_NULL_SHA384", -1, VALL, 0}, {0x00B6, "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256", 128, VALL, 0}, {0x00B7, "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384", 256, VALL, 0}, {0x00B8, "TLS_RSA_PSK_WITH_NULL_SHA256", -1, VALL, 0}, {0x00B9, "TLS_RSA_PSK_WITH_NULL_SHA384", -1, VALL, 0}, {0x00BA, "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256", 128, VALL, 0}, {0x00BB, "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256", 128, VALL, 0}, {0x00BC, "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256", 128, VALL, 0}, {0x00BD, "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256", 128, VALL, 0}, {0x00BE, "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256", 128, VALL, 0}, {0x00BF, "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256", 128, VALL, 0}, {0x00C0, "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256", 256, VALL, 0}, {0x00C1, "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256", 256, VALL, 0}, {0x00C2, "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256", 256, VALL, 0}, {0x00C3, "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256", 256, VALL, 0}, {0x00C4, "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256", 256, VALL, 0}, {0x00C5, "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256", 256, VALL, 0}, {0x00C6, "TLS_SM4_GCM_SM3", 128, VALL, 0}, {0x00C7, "TLS_SM4_CCM_SM3", 128, VALL, 0}, {0x1301, "TLS_AES_128_GCM_SHA256", 128, VALL, 0}, {0x1302, "TLS_AES_256_GCM_SHA384", 256, VALL, 0}, {0x1303, "TLS_CHACHA20_POLY1305_SHA256", 256, VALL, 0}, {0x1304, "TLS_AES_128_CCM_SHA256", 128, VALL, 0}, {0x1305, "TLS_AES_128_CCM_8_SHA256", 128, VALL, 0}, {0xC001, "TLS_ECDH_ECDSA_WITH_NULL_SHA", -1, VALL, 0}, {0xC002, "TLS_ECDH_ECDSA_WITH_RC4_128_SHA", 128, VALL, 0}, {0xC003, "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, {0xC004, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA", 128, VALL, 0}, {0xC005, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA", 256, VALL, 0}, {0xC006, "TLS_ECDHE_ECDSA_WITH_NULL_SHA", -1, VALL, 0}, {0xC007, "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", 128, VALL, 0}, {0xC008, "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, {0xC009, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", 128, VALL, 0}, {0xC00A, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", 256, VALL, 0}, {0xC00B, "TLS_ECDH_RSA_WITH_NULL_SHA", -1, VALL, 0}, {0xC00C, "TLS_ECDH_RSA_WITH_RC4_128_SHA", 128, VALL, 0}, {0xC00D, "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, {0xC00E, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA", 128, VALL, 0}, {0xC00F, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA", 256, VALL, 0}, {0xC010, "TLS_ECDHE_RSA_WITH_NULL_SHA", -1, VALL, 0}, {0xC011, "TLS_ECDHE_RSA_WITH_RC4_128_SHA", 128, VALL, 0}, {0xC012, "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, {0xC013, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", 128, VALL, 0}, {0xC014, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", 256, VALL, 0}, {0xC015, "TLS_ECDH_anon_WITH_NULL_SHA", -1, VALL, 0}, {0xC016, "TLS_ECDH_anon_WITH_RC4_128_SHA", 128, VALL, 0}, {0xC017, "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, {0xC018, "TLS_ECDH_anon_WITH_AES_128_CBC_SHA", 128, VALL, 0}, {0xC019, "TLS_ECDH_anon_WITH_AES_256_CBC_SHA", 256, VALL, 0}, {0xC01A, "TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, {0xC01B, "TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, {0xC01C, "TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, {0xC01D, "TLS_SRP_SHA_WITH_AES_128_CBC_SHA", 128, VALL, 0}, {0xC01E, "TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA", 128, VALL, 0}, {0xC01F, "TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA", 128, VALL, 0}, {0xC020, "TLS_SRP_SHA_WITH_AES_256_CBC_SHA", 256, VALL, 0}, {0xC021, "TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA", 256, VALL, 0}, {0xC022, "TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA", 256, VALL, 0}, {0xC023, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", 128, VALL, 0}, {0xC024, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", 256, VALL, 0}, {0xC025, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256", 128, VALL, 0}, {0xC026, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384", 256, VALL, 0}, {0xC027, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", 128, VALL, 0}, {0xC028, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", 256, VALL, 0}, {0xC029, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256", 128, VALL, 0}, {0xC02A, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384", 256, VALL, 0}, {0xC02B, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 128, VALL, 0}, {0xC02C, "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 256, VALL, 0}, {0xC02D, "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", 128, VALL, 0}, {0xC02E, "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", 256, VALL, 0}, {0xC02F, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 128, VALL, 0}, {0xC030, "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 256, VALL, 0}, {0xC031, "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", 128, VALL, 0}, {0xC032, "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", 256, VALL, 0}, {0xC033, "TLS_ECDHE_PSK_WITH_RC4_128_SHA", 128, VALL, 0}, {0xC034, "TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA", 112, VALL, 0}, {0xC035, "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA", 128, VALL, 0}, {0xC036, "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA", 256, VALL, 0}, {0xC037, "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256", 128, VALL, 0}, {0xC038, "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384", 256, VALL, 0}, {0xC039, "TLS_ECDHE_PSK_WITH_NULL_SHA", -1, VALL, 0}, {0xC03A, "TLS_ECDHE_PSK_WITH_NULL_SHA256", -1, VALL, 0}, {0xC03B, "TLS_ECDHE_PSK_WITH_NULL_SHA384", -1, VALL, 0}, {0xC03C, "TLS_RSA_WITH_ARIA_128_CBC_SHA256", 128, VALL, 0}, {0xC03D, "TLS_RSA_WITH_ARIA_256_CBC_SHA384", 256, VALL, 0}, {0xC03E, "TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256", 128, VALL, 0}, {0xC03F, "TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384", 256, VALL, 0}, {0xC040, "TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256", 128, VALL, 0}, {0xC041, "TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384", 256, VALL, 0}, {0xC042, "TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256", 128, VALL, 0}, {0xC043, "TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384", 256, VALL, 0}, {0xC044, "TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256", 128, VALL, 0}, {0xC045, "TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384", 256, VALL, 0}, {0xC046, "TLS_DH_anon_WITH_ARIA_128_CBC_SHA256", 128, VALL, 0}, {0xC047, "TLS_DH_anon_WITH_ARIA_256_CBC_SHA384", 256, VALL, 0}, {0xC048, "TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256", 128, VALL, 0}, {0xC049, "TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384", 256, VALL, 0}, {0xC04A, "TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256", 128, VALL, 0}, {0xC04B, "TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384", 256, VALL, 0}, {0xC04C, "TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256", 128, VALL, 0}, {0xC04D, "TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384", 256, VALL, 0}, {0xC04E, "TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256", 128, VALL, 0}, {0xC04F, "TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384", 256, VALL, 0}, {0xC050, "TLS_RSA_WITH_ARIA_128_GCM_SHA256", 128, VALL, 0}, {0xC051, "TLS_RSA_WITH_ARIA_256_GCM_SHA384", 256, VALL, 0}, {0xC052, "TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256", 128, VALL, 0}, {0xC053, "TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384", 256, VALL, 0}, {0xC054, "TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256", 128, VALL, 0}, {0xC055, "TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384", 256, VALL, 0}, {0xC056, "TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256", 128, VALL, 0}, {0xC057, "TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384", 256, VALL, 0}, {0xC058, "TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256", 128, VALL, 0}, {0xC059, "TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384", 256, VALL, 0}, {0xC05A, "TLS_DH_anon_WITH_ARIA_128_GCM_SHA256", 128, VALL, 0}, {0xC05B, "TLS_DH_anon_WITH_ARIA_256_GCM_SHA384", 256, VALL, 0}, {0xC05C, "TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256", 128, VALL, 0}, {0xC05D, "TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384", 256, VALL, 0}, {0xC05E, "TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256", 128, VALL, 0}, {0xC05F, "TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384", 256, VALL, 0}, {0xC060, "TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256", 128, VALL, 0}, {0xC061, "TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384", 256, VALL, 0}, {0xC062, "TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256", 128, VALL, 0}, {0xC063, "TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384", 256, VALL, 0}, {0xC064, "TLS_PSK_WITH_ARIA_128_CBC_SHA256", 128, VALL, 0}, {0xC065, "TLS_PSK_WITH_ARIA_256_CBC_SHA384", 256, VALL, 0}, {0xC066, "TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256", 128, VALL, 0}, {0xC067, "TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384", 256, VALL, 0}, {0xC068, "TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256", 128, VALL, 0}, {0xC069, "TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384", 256, VALL, 0}, {0xC06A, "TLS_PSK_WITH_ARIA_128_GCM_SHA256", 128, VALL, 0}, {0xC06B, "TLS_PSK_WITH_ARIA_256_GCM_SHA384", 256, VALL, 0}, {0xC06C, "TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256", 128, VALL, 0}, {0xC06D, "TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384", 256, VALL, 0}, {0xC06E, "TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256", 128, VALL, 0}, {0xC06F, "TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384", 256, VALL, 0}, {0xC070, "TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256", 128, VALL, 0}, {0xC071, "TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384", 256, VALL, 0}, {0xC072, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256", 128, VALL, 0}, {0xC073, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384", 256, VALL, 0}, {0xC074, "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256", 128, VALL, 0}, {0xC075, "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384", 256, VALL, 0}, {0xC076, "TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256", 128, VALL, 0}, {0xC077, "TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384", 256, VALL, 0}, {0xC078, "TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256", 128, VALL, 0}, {0xC079, "TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384", 256, VALL, 0}, {0xC07A, "TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256", 128, VALL, 0}, {0xC07B, "TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384", 256, VALL, 0}, {0xC07C, "TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256", 128, VALL, 0}, {0xC07D, "TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384", 256, VALL, 0}, {0xC07E, "TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256", 128, VALL, 0}, {0xC07F, "TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384", 256, VALL, 0}, {0xC080, "TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256", 128, VALL, 0}, {0xC081, "TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384", 256, VALL, 0}, {0xC082, "TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256", 128, VALL, 0}, {0xC083, "TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384", 256, VALL, 0}, {0xC084, "TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256", 128, VALL, 0}, {0xC085, "TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384", 256, VALL, 0}, {0xC086, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256", 128, VALL, 0}, {0xC087, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384", 256, VALL, 0}, {0xC088, "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256", 128, VALL, 0}, {0xC089, "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384", 256, VALL, 0}, {0xC08A, "TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256", 128, VALL, 0}, {0xC08B, "TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384", 256, VALL, 0}, {0xC08C, "TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256", 128, VALL, 0}, {0xC08D, "TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384", 256, VALL, 0}, {0xC08E, "TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256", 128, VALL, 0}, {0xC08F, "TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384", 256, VALL, 0}, {0xC090, "TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256", 128, VALL, 0}, {0xC091, "TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384", 256, VALL, 0}, {0xC092, "TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256", 128, VALL, 0}, {0xC093, "TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384", 256, VALL, 0}, {0xC094, "TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256", 128, VALL, 0}, {0xC095, "TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384", 256, VALL, 0}, {0xC096, "TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256", 128, VALL, 0}, {0xC097, "TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384", 256, VALL, 0}, {0xC098, "TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256", 128, VALL, 0}, {0xC099, "TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384", 256, VALL, 0}, {0xC09A, "TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256", 128, VALL, 0}, {0xC09B, "TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384", 256, VALL, 0}, {0xC09C, "TLS_RSA_WITH_AES_128_CCM", 128, VALL, 0}, {0xC09D, "TLS_RSA_WITH_AES_256_CCM", 256, VALL, 0}, {0xC09E, "TLS_DHE_RSA_WITH_AES_128_CCM", 128, VALL, 0}, {0xC09F, "TLS_DHE_RSA_WITH_AES_256_CCM", 256, VALL, 0}, {0xC0A0, "TLS_RSA_WITH_AES_128_CCM_8", 128, VALL, 0}, {0xC0A1, "TLS_RSA_WITH_AES_256_CCM_8", 256, VALL, 0}, {0xC0A2, "TLS_DHE_RSA_WITH_AES_128_CCM_8", 128, VALL, 0}, {0xC0A3, "TLS_DHE_RSA_WITH_AES_256_CCM_8", 256, VALL, 0}, {0xC0A4, "TLS_PSK_WITH_AES_128_CCM", 128, VALL, 0}, {0xC0A5, "TLS_PSK_WITH_AES_256_CCM", 256, VALL, 0}, {0xC0A6, "TLS_DHE_PSK_WITH_AES_128_CCM", 128, VALL, 0}, {0xC0A7, "TLS_DHE_PSK_WITH_AES_256_CCM", 256, VALL, 0}, {0xC0A8, "TLS_PSK_WITH_AES_128_CCM_8", 128, VALL, 0}, {0xC0A9, "TLS_PSK_WITH_AES_256_CCM_8", 256, VALL, 0}, {0xC0AA, "TLS_PSK_DHE_WITH_AES_128_CCM_8", 128, VALL, 0}, {0xC0AB, "TLS_PSK_DHE_WITH_AES_256_CCM_8", 256, VALL, 0}, {0xC0AC, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM", 128, VALL, 0}, {0xC0AD, "TLS_ECDHE_ECDSA_WITH_AES_256_CCM", 256, VALL, 0}, {0xC0AE, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8", 128, VALL, 0}, {0xC0AF, "TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8", 256, VALL, 0}, {0xC0B0, "TLS_ECCPWD_WITH_AES_128_GCM_SHA256", 128, VALL, 0}, {0xC0B1, "TLS_ECCPWD_WITH_AES_256_GCM_SHA384", 256, VALL, 0}, {0xC0B2, "TLS_ECCPWD_WITH_AES_128_CCM_SHA256", 128, VALL, 0}, {0xC0B3, "TLS_ECCPWD_WITH_AES_256_CCM_SHA384", 256, VALL, 0}, {0xC0B4, "TLS_SHA256_SHA256", -1, VALL, 0}, {0xC0B5, "TLS_SHA384_SHA384", -1, VALL, 0}, {0xC100, "TLS_GOSTR341112_256_WITH_KUZNYECHIK_CTR_OMAC", 256, VALL, 0}, {0xC101, "TLS_GOSTR341112_256_WITH_MAGMA_CTR_OMAC", 256, VALL, 0}, {0xC102, "TLS_GOSTR341112_256_WITH_28147_CNT_IMIT", 256, VALL, 0}, {0xCCA8, "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", 256, VALL, 0}, {0xCCA9, "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", 256, VALL, 0}, {0xCCAA, "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256", 256, VALL, 0}, {0xCCAB, "TLS_PSK_WITH_CHACHA20_POLY1305_SHA256", 256, VALL, 0}, {0xCCAC, "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256", 256, VALL, 0}, {0xCCAD, "TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256", 256, VALL, 0}, {0xCCAE, "TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256", 256, VALL, 0}, {0xD001, "TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256", 128, VALL, 0}, {0xD002, "TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384", 256, VALL, 0}, {0xD003, "TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256", 128, VALL, 0}, {0xD005, "TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256", 128, VALL, 0}, /* The ciphers below are reserved for private use (see RFC8446). */ {0xFF00, "PRIVATE_CIPHER_0", -1, VALL, 0}, {0xFF01, "PRIVATE_CIPHER_1", -1, VALL, 0}, {0xFF02, "PRIVATE_CIPHER_2", -1, VALL, 0}, {0xFF03, "PRIVATE_CIPHER_3", -1, VALL, 0}, {0xFF04, "PRIVATE_CIPHER_4", -1, VALL, 0}, {0xFF05, "PRIVATE_CIPHER_5", -1, VALL, 0}, {0xFF06, "PRIVATE_CIPHER_6", -1, VALL, 0}, {0xFF07, "PRIVATE_CIPHER_7", -1, VALL, 0}, {0xFF08, "PRIVATE_CIPHER_8", -1, VALL, 0}, {0xFF09, "PRIVATE_CIPHER_9", -1, VALL, 0}, {0xFF0A, "PRIVATE_CIPHER_10", -1, VALL, 0}, {0xFF0B, "PRIVATE_CIPHER_11", -1, VALL, 0}, {0xFF0C, "PRIVATE_CIPHER_12", -1, VALL, 0}, {0xFF0D, "PRIVATE_CIPHER_13", -1, VALL, 0}, {0xFF0E, "PRIVATE_CIPHER_14", -1, VALL, 0}, {0xFF0F, "PRIVATE_CIPHER_15", -1, VALL, 0}, {0xFF10, "PRIVATE_CIPHER_16", -1, VALL, 0}, {0xFF11, "PRIVATE_CIPHER_17", -1, VALL, 0}, {0xFF12, "PRIVATE_CIPHER_18", -1, VALL, 0}, {0xFF13, "PRIVATE_CIPHER_19", -1, VALL, 0}, {0xFF14, "PRIVATE_CIPHER_20", -1, VALL, 0}, {0xFF15, "PRIVATE_CIPHER_21", -1, VALL, 0}, {0xFF16, "PRIVATE_CIPHER_22", -1, VALL, 0}, {0xFF17, "PRIVATE_CIPHER_23", -1, VALL, 0}, {0xFF18, "PRIVATE_CIPHER_24", -1, VALL, 0}, {0xFF19, "PRIVATE_CIPHER_25", -1, VALL, 0}, {0xFF1A, "PRIVATE_CIPHER_26", -1, VALL, 0}, {0xFF1B, "PRIVATE_CIPHER_27", -1, VALL, 0}, {0xFF1C, "PRIVATE_CIPHER_28", -1, VALL, 0}, {0xFF1D, "PRIVATE_CIPHER_29", -1, VALL, 0}, {0xFF1E, "PRIVATE_CIPHER_30", -1, VALL, 0}, {0xFF1F, "PRIVATE_CIPHER_31", -1, VALL, 0}, {0xFF20, "PRIVATE_CIPHER_32", -1, VALL, 0}, {0xFF21, "PRIVATE_CIPHER_33", -1, VALL, 0}, {0xFF22, "PRIVATE_CIPHER_34", -1, VALL, 0}, {0xFF23, "PRIVATE_CIPHER_35", -1, VALL, 0}, {0xFF24, "PRIVATE_CIPHER_36", -1, VALL, 0}, {0xFF25, "PRIVATE_CIPHER_37", -1, VALL, 0}, {0xFF26, "PRIVATE_CIPHER_38", -1, VALL, 0}, {0xFF27, "PRIVATE_CIPHER_39", -1, VALL, 0}, {0xFF28, "PRIVATE_CIPHER_40", -1, VALL, 0}, {0xFF29, "PRIVATE_CIPHER_41", -1, VALL, 0}, {0xFF2A, "PRIVATE_CIPHER_42", -1, VALL, 0}, {0xFF2B, "PRIVATE_CIPHER_43", -1, VALL, 0}, {0xFF2C, "PRIVATE_CIPHER_44", -1, VALL, 0}, {0xFF2D, "PRIVATE_CIPHER_45", -1, VALL, 0}, {0xFF2E, "PRIVATE_CIPHER_46", -1, VALL, 0}, {0xFF2F, "PRIVATE_CIPHER_47", -1, VALL, 0}, {0xFF30, "PRIVATE_CIPHER_48", -1, VALL, 0}, {0xFF31, "PRIVATE_CIPHER_49", -1, VALL, 0}, {0xFF32, "PRIVATE_CIPHER_50", -1, VALL, 0}, {0xFF33, "PRIVATE_CIPHER_51", -1, VALL, 0}, {0xFF34, "PRIVATE_CIPHER_52", -1, VALL, 0}, {0xFF35, "PRIVATE_CIPHER_53", -1, VALL, 0}, {0xFF36, "PRIVATE_CIPHER_54", -1, VALL, 0}, {0xFF37, "PRIVATE_CIPHER_55", -1, VALL, 0}, {0xFF38, "PRIVATE_CIPHER_56", -1, VALL, 0}, {0xFF39, "PRIVATE_CIPHER_57", -1, VALL, 0}, {0xFF3A, "PRIVATE_CIPHER_58", -1, VALL, 0}, {0xFF3B, "PRIVATE_CIPHER_59", -1, VALL, 0}, {0xFF3C, "PRIVATE_CIPHER_60", -1, VALL, 0}, {0xFF3D, "PRIVATE_CIPHER_61", -1, VALL, 0}, {0xFF3E, "PRIVATE_CIPHER_62", -1, VALL, 0}, {0xFF3F, "PRIVATE_CIPHER_63", -1, VALL, 0}, {0xFF40, "PRIVATE_CIPHER_64", -1, VALL, 0}, {0xFF41, "PRIVATE_CIPHER_65", -1, VALL, 0}, {0xFF42, "PRIVATE_CIPHER_66", -1, VALL, 0}, {0xFF43, "PRIVATE_CIPHER_67", -1, VALL, 0}, {0xFF44, "PRIVATE_CIPHER_68", -1, VALL, 0}, {0xFF45, "PRIVATE_CIPHER_69", -1, VALL, 0}, {0xFF46, "PRIVATE_CIPHER_70", -1, VALL, 0}, {0xFF47, "PRIVATE_CIPHER_71", -1, VALL, 0}, {0xFF48, "PRIVATE_CIPHER_72", -1, VALL, 0}, {0xFF49, "PRIVATE_CIPHER_73", -1, VALL, 0}, {0xFF4A, "PRIVATE_CIPHER_74", -1, VALL, 0}, {0xFF4B, "PRIVATE_CIPHER_75", -1, VALL, 0}, {0xFF4C, "PRIVATE_CIPHER_76", -1, VALL, 0}, {0xFF4D, "PRIVATE_CIPHER_77", -1, VALL, 0}, {0xFF4E, "PRIVATE_CIPHER_78", -1, VALL, 0}, {0xFF4F, "PRIVATE_CIPHER_79", -1, VALL, 0}, {0xFF50, "PRIVATE_CIPHER_80", -1, VALL, 0}, {0xFF51, "PRIVATE_CIPHER_81", -1, VALL, 0}, {0xFF52, "PRIVATE_CIPHER_82", -1, VALL, 0}, {0xFF53, "PRIVATE_CIPHER_83", -1, VALL, 0}, {0xFF54, "PRIVATE_CIPHER_84", -1, VALL, 0}, {0xFF55, "PRIVATE_CIPHER_85", -1, VALL, 0}, {0xFF56, "PRIVATE_CIPHER_86", -1, VALL, 0}, {0xFF57, "PRIVATE_CIPHER_87", -1, VALL, 0}, {0xFF58, "PRIVATE_CIPHER_88", -1, VALL, 0}, {0xFF59, "PRIVATE_CIPHER_89", -1, VALL, 0}, {0xFF5A, "PRIVATE_CIPHER_90", -1, VALL, 0}, {0xFF5B, "PRIVATE_CIPHER_91", -1, VALL, 0}, {0xFF5C, "PRIVATE_CIPHER_92", -1, VALL, 0}, {0xFF5D, "PRIVATE_CIPHER_93", -1, VALL, 0}, {0xFF5E, "PRIVATE_CIPHER_94", -1, VALL, 0}, {0xFF5F, "PRIVATE_CIPHER_95", -1, VALL, 0}, {0xFF60, "PRIVATE_CIPHER_96", -1, VALL, 0}, {0xFF61, "PRIVATE_CIPHER_97", -1, VALL, 0}, {0xFF62, "PRIVATE_CIPHER_98", -1, VALL, 0}, {0xFF63, "PRIVATE_CIPHER_99", -1, VALL, 0}, {0xFF64, "PRIVATE_CIPHER_100", -1, VALL, 0}, {0xFF65, "PRIVATE_CIPHER_101", -1, VALL, 0}, {0xFF66, "PRIVATE_CIPHER_102", -1, VALL, 0}, {0xFF67, "PRIVATE_CIPHER_103", -1, VALL, 0}, {0xFF68, "PRIVATE_CIPHER_104", -1, VALL, 0}, {0xFF69, "PRIVATE_CIPHER_105", -1, VALL, 0}, {0xFF6A, "PRIVATE_CIPHER_106", -1, VALL, 0}, {0xFF6B, "PRIVATE_CIPHER_107", -1, VALL, 0}, {0xFF6C, "PRIVATE_CIPHER_108", -1, VALL, 0}, {0xFF6D, "PRIVATE_CIPHER_109", -1, VALL, 0}, {0xFF6E, "PRIVATE_CIPHER_110", -1, VALL, 0}, {0xFF6F, "PRIVATE_CIPHER_111", -1, VALL, 0}, {0xFF70, "PRIVATE_CIPHER_112", -1, VALL, 0}, {0xFF71, "PRIVATE_CIPHER_113", -1, VALL, 0}, {0xFF72, "PRIVATE_CIPHER_114", -1, VALL, 0}, {0xFF73, "PRIVATE_CIPHER_115", -1, VALL, 0}, {0xFF74, "PRIVATE_CIPHER_116", -1, VALL, 0}, {0xFF75, "PRIVATE_CIPHER_117", -1, VALL, 0}, {0xFF76, "PRIVATE_CIPHER_118", -1, VALL, 0}, {0xFF77, "PRIVATE_CIPHER_119", -1, VALL, 0}, {0xFF78, "PRIVATE_CIPHER_120", -1, VALL, 0}, {0xFF79, "PRIVATE_CIPHER_121", -1, VALL, 0}, {0xFF7A, "PRIVATE_CIPHER_122", -1, VALL, 0}, {0xFF7B, "PRIVATE_CIPHER_123", -1, VALL, 0}, {0xFF7C, "PRIVATE_CIPHER_124", -1, VALL, 0}, {0xFF7D, "PRIVATE_CIPHER_125", -1, VALL, 0}, {0xFF7E, "PRIVATE_CIPHER_126", -1, VALL, 0}, {0xFF7F, "PRIVATE_CIPHER_127", -1, VALL, 0}, {0xFF80, "PRIVATE_CIPHER_128", -1, VALL, 0}, {0xFF81, "PRIVATE_CIPHER_129", -1, VALL, 0}, {0xFF82, "PRIVATE_CIPHER_130", -1, VALL, 0}, {0xFF83, "PRIVATE_CIPHER_131", -1, VALL, 0}, {0xFF84, "PRIVATE_CIPHER_132", -1, VALL, 0}, {0xFF85, "PRIVATE_CIPHER_133", -1, VALL, 0}, {0xFF86, "PRIVATE_CIPHER_134", -1, VALL, 0}, {0xFF87, "PRIVATE_CIPHER_135", -1, VALL, 0}, {0xFF88, "PRIVATE_CIPHER_136", -1, VALL, 0}, {0xFF89, "PRIVATE_CIPHER_137", -1, VALL, 0}, {0xFF8A, "PRIVATE_CIPHER_138", -1, VALL, 0}, {0xFF8B, "PRIVATE_CIPHER_139", -1, VALL, 0}, {0xFF8C, "PRIVATE_CIPHER_140", -1, VALL, 0}, {0xFF8D, "PRIVATE_CIPHER_141", -1, VALL, 0}, {0xFF8E, "PRIVATE_CIPHER_142", -1, VALL, 0}, {0xFF8F, "PRIVATE_CIPHER_143", -1, VALL, 0}, {0xFF90, "PRIVATE_CIPHER_144", -1, VALL, 0}, {0xFF91, "PRIVATE_CIPHER_145", -1, VALL, 0}, {0xFF92, "PRIVATE_CIPHER_146", -1, VALL, 0}, {0xFF93, "PRIVATE_CIPHER_147", -1, VALL, 0}, {0xFF94, "PRIVATE_CIPHER_148", -1, VALL, 0}, {0xFF95, "PRIVATE_CIPHER_149", -1, VALL, 0}, {0xFF96, "PRIVATE_CIPHER_150", -1, VALL, 0}, {0xFF97, "PRIVATE_CIPHER_151", -1, VALL, 0}, {0xFF98, "PRIVATE_CIPHER_152", -1, VALL, 0}, {0xFF99, "PRIVATE_CIPHER_153", -1, VALL, 0}, {0xFF9A, "PRIVATE_CIPHER_154", -1, VALL, 0}, {0xFF9B, "PRIVATE_CIPHER_155", -1, VALL, 0}, {0xFF9C, "PRIVATE_CIPHER_156", -1, VALL, 0}, {0xFF9D, "PRIVATE_CIPHER_157", -1, VALL, 0}, {0xFF9E, "PRIVATE_CIPHER_158", -1, VALL, 0}, {0xFF9F, "PRIVATE_CIPHER_159", -1, VALL, 0}, {0xFFA0, "PRIVATE_CIPHER_160", -1, VALL, 0}, {0xFFA1, "PRIVATE_CIPHER_161", -1, VALL, 0}, {0xFFA2, "PRIVATE_CIPHER_162", -1, VALL, 0}, {0xFFA3, "PRIVATE_CIPHER_163", -1, VALL, 0}, {0xFFA4, "PRIVATE_CIPHER_164", -1, VALL, 0}, {0xFFA5, "PRIVATE_CIPHER_165", -1, VALL, 0}, {0xFFA6, "PRIVATE_CIPHER_166", -1, VALL, 0}, {0xFFA7, "PRIVATE_CIPHER_167", -1, VALL, 0}, {0xFFA8, "PRIVATE_CIPHER_168", -1, VALL, 0}, {0xFFA9, "PRIVATE_CIPHER_169", -1, VALL, 0}, {0xFFAA, "PRIVATE_CIPHER_170", -1, VALL, 0}, {0xFFAB, "PRIVATE_CIPHER_171", -1, VALL, 0}, {0xFFAC, "PRIVATE_CIPHER_172", -1, VALL, 0}, {0xFFAD, "PRIVATE_CIPHER_173", -1, VALL, 0}, {0xFFAE, "PRIVATE_CIPHER_174", -1, VALL, 0}, {0xFFAF, "PRIVATE_CIPHER_175", -1, VALL, 0}, {0xFFB0, "PRIVATE_CIPHER_176", -1, VALL, 0}, {0xFFB1, "PRIVATE_CIPHER_177", -1, VALL, 0}, {0xFFB2, "PRIVATE_CIPHER_178", -1, VALL, 0}, {0xFFB3, "PRIVATE_CIPHER_179", -1, VALL, 0}, {0xFFB4, "PRIVATE_CIPHER_180", -1, VALL, 0}, {0xFFB5, "PRIVATE_CIPHER_181", -1, VALL, 0}, {0xFFB6, "PRIVATE_CIPHER_182", -1, VALL, 0}, {0xFFB7, "PRIVATE_CIPHER_183", -1, VALL, 0}, {0xFFB8, "PRIVATE_CIPHER_184", -1, VALL, 0}, {0xFFB9, "PRIVATE_CIPHER_185", -1, VALL, 0}, {0xFFBA, "PRIVATE_CIPHER_186", -1, VALL, 0}, {0xFFBB, "PRIVATE_CIPHER_187", -1, VALL, 0}, {0xFFBC, "PRIVATE_CIPHER_188", -1, VALL, 0}, {0xFFBD, "PRIVATE_CIPHER_189", -1, VALL, 0}, {0xFFBE, "PRIVATE_CIPHER_190", -1, VALL, 0}, {0xFFBF, "PRIVATE_CIPHER_191", -1, VALL, 0}, {0xFFC0, "PRIVATE_CIPHER_192", -1, VALL, 0}, {0xFFC1, "PRIVATE_CIPHER_193", -1, VALL, 0}, {0xFFC2, "PRIVATE_CIPHER_194", -1, VALL, 0}, {0xFFC3, "PRIVATE_CIPHER_195", -1, VALL, 0}, {0xFFC4, "PRIVATE_CIPHER_196", -1, VALL, 0}, {0xFFC5, "PRIVATE_CIPHER_197", -1, VALL, 0}, {0xFFC6, "PRIVATE_CIPHER_198", -1, VALL, 0}, {0xFFC7, "PRIVATE_CIPHER_199", -1, VALL, 0}, {0xFFC8, "PRIVATE_CIPHER_200", -1, VALL, 0}, {0xFFC9, "PRIVATE_CIPHER_201", -1, VALL, 0}, {0xFFCA, "PRIVATE_CIPHER_202", -1, VALL, 0}, {0xFFCB, "PRIVATE_CIPHER_203", -1, VALL, 0}, {0xFFCC, "PRIVATE_CIPHER_204", -1, VALL, 0}, {0xFFCD, "PRIVATE_CIPHER_205", -1, VALL, 0}, {0xFFCE, "PRIVATE_CIPHER_206", -1, VALL, 0}, {0xFFCF, "PRIVATE_CIPHER_207", -1, VALL, 0}, {0xFFD0, "PRIVATE_CIPHER_208", -1, VALL, 0}, {0xFFD1, "PRIVATE_CIPHER_209", -1, VALL, 0}, {0xFFD2, "PRIVATE_CIPHER_210", -1, VALL, 0}, {0xFFD3, "PRIVATE_CIPHER_211", -1, VALL, 0}, {0xFFD4, "PRIVATE_CIPHER_212", -1, VALL, 0}, {0xFFD5, "PRIVATE_CIPHER_213", -1, VALL, 0}, {0xFFD6, "PRIVATE_CIPHER_214", -1, VALL, 0}, {0xFFD7, "PRIVATE_CIPHER_215", -1, VALL, 0}, {0xFFD8, "PRIVATE_CIPHER_216", -1, VALL, 0}, {0xFFD9, "PRIVATE_CIPHER_217", -1, VALL, 0}, {0xFFDA, "PRIVATE_CIPHER_218", -1, VALL, 0}, {0xFFDB, "PRIVATE_CIPHER_219", -1, VALL, 0}, {0xFFDC, "PRIVATE_CIPHER_220", -1, VALL, 0}, {0xFFDD, "PRIVATE_CIPHER_221", -1, VALL, 0}, {0xFFDE, "PRIVATE_CIPHER_222", -1, VALL, 0}, {0xFFDF, "PRIVATE_CIPHER_223", -1, VALL, 0}, {0xFFE0, "PRIVATE_CIPHER_224", -1, VALL, 0}, {0xFFE1, "PRIVATE_CIPHER_225", -1, VALL, 0}, {0xFFE2, "PRIVATE_CIPHER_226", -1, VALL, 0}, {0xFFE3, "PRIVATE_CIPHER_227", -1, VALL, 0}, {0xFFE4, "PRIVATE_CIPHER_228", -1, VALL, 0}, {0xFFE5, "PRIVATE_CIPHER_229", -1, VALL, 0}, {0xFFE6, "PRIVATE_CIPHER_230", -1, VALL, 0}, {0xFFE7, "PRIVATE_CIPHER_231", -1, VALL, 0}, {0xFFE8, "PRIVATE_CIPHER_232", -1, VALL, 0}, {0xFFE9, "PRIVATE_CIPHER_233", -1, VALL, 0}, {0xFFEA, "PRIVATE_CIPHER_234", -1, VALL, 0}, {0xFFEB, "PRIVATE_CIPHER_235", -1, VALL, 0}, {0xFFEC, "PRIVATE_CIPHER_236", -1, VALL, 0}, {0xFFED, "PRIVATE_CIPHER_237", -1, VALL, 0}, {0xFFEE, "PRIVATE_CIPHER_238", -1, VALL, 0}, {0xFFEF, "PRIVATE_CIPHER_239", -1, VALL, 0}, {0xFFF0, "PRIVATE_CIPHER_240", -1, VALL, 0}, {0xFFF1, "PRIVATE_CIPHER_241", -1, VALL, 0}, {0xFFF2, "PRIVATE_CIPHER_242", -1, VALL, 0}, {0xFFF3, "PRIVATE_CIPHER_243", -1, VALL, 0}, {0xFFF4, "PRIVATE_CIPHER_244", -1, VALL, 0}, {0xFFF5, "PRIVATE_CIPHER_245", -1, VALL, 0}, {0xFFF6, "PRIVATE_CIPHER_246", -1, VALL, 0}, {0xFFF7, "PRIVATE_CIPHER_247", -1, VALL, 0}, {0xFFF8, "PRIVATE_CIPHER_248", -1, VALL, 0}, {0xFFF9, "PRIVATE_CIPHER_249", -1, VALL, 0}, {0xFFFA, "PRIVATE_CIPHER_250", -1, VALL, 0}, {0xFFFB, "PRIVATE_CIPHER_251", -1, VALL, 0}, {0xFFFC, "PRIVATE_CIPHER_252", -1, VALL, 0}, {0xFFFD, "PRIVATE_CIPHER_253", -1, VALL, 0}, {0xFFFE, "PRIVATE_CIPHER_254", -1, VALL, 0}, {0xFFFF, "PRIVATE_CIPHER_255", -1, VALL, 0}, }; #endif sslscan-2.1.2/sslscan.1000066400000000000000000000123411452476416400147300ustar00rootroot00000000000000.TH SSLSCAN 1 "March 19, 2020" .SH NAME sslscan \- Fast SSL/TLS scanner .SH SYNOPSIS .B sslscan .RI [ options ] " [host:port | host]" .SH DESCRIPTION .PP \fBsslscan\fP queries SSL/TLS services (such as HTTPS) and reports the protocol versions, cipher suites, key exchanges, signature algorithms, and certificates in use. This helps the user understand which parameters are weak from a security standpoint. Terminal output is thus colour-coded as follows: Red Background NULL cipher (no encryption) .br Red Broken cipher (<= 40 bit), broken protocol (SSLv2 or SSLv3) or broken certificate signing algorithm (MD5) .br Yellow Weak cipher (<= 56 bit or RC4) or weak certificate signing algorithm (SHA-1) .br Purple Anonymous cipher (ADH or AECDH) \fBsslscan\fP can also output results into an XML file for easy consumption by external programs. .SH OPTIONS .TP .B \-\-help .br Show summary of options .TP .B \-\-targets= A file containing a list of hosts to check. Hosts can be supplied with ports (i.e. host:port). One target per line .TP .B \-\-sni\-name= Use a different hostname for SNI .br .TP .B \-\-ipv4, \-4 .br Force IPv4 DNS resolution. Default is to try IPv4, and if that fails then fall back to IPv6. .TP .B \-\-ipv6, \-6 .br Force IPv6 DNS resolution. Default is to try IPv4, and if that fails then fall back to IPv6. .TP .B \-\-show\-certificate Display certificate information. .TP .B \-\-no\-check\-certificate Don't flag certificates signed with weak algorithms (MD5 and SHA-1) or short (<2048 bit) RSA keys .TP .B \-\-show\-client\-cas Show a list of CAs that the server allows for client authentication. Will be blank for IIS/Schannel servers. .TP .B \-\-show\-ciphers Show a complete list of ciphers supported by sslscan .TP .B \-\-show\-cipher-ids Print the hexadecimal cipher IDs .TP .B \-\-iana\-names Use IANA/RFC cipher names rather than OpenSSL ones .TP .B \-\-show\-times Show the time taken for each handshake in milliseconds. Note that only a single request is made with each cipher, and that the size of the ClientHello is not constant, so this should not be used for proper benchmarking or performance testing. You might want to also use \-\-no\-cipher\-details to make the output a bit clearer. .TP .B \-\-ssl2 .br Only check if SSLv2 is enabled .TP .B \-\-ssl3 .br Only check if SSLv3 is enabled .TP .B \-\-tls10 .br Only check TLS 1.0 ciphers .TP .B \-\-tls11 .br Only check TLS 1.1 ciphers .TP .B \-\-tls12 .br Only check TLS 1.2 ciphers .TP .B \-\-tls13 .br Only check TLS 1.3 ciphers .TP .B \-\-tlsall .br Only check TLS ciphers (versions 1.0, 1.1, 1.2, and 1.3) .TP .B \-\-ocsp .br Display OCSP status .TP .B \-\-pk= A file containing the private key or a PKCS#12 file containing a private key/certificate pair (as produced by MSIE and Netscape) .TP .B \-\-pkpass= The password for the private key or PKCS#12 file .TP .B \-\-certs= A file containing PEM/ASN1 formatted client certificates .TP .B \-\-no\-ciphersuites Do not scan for supported ciphersuites. .TP .B \-\-no\-fallback Do not check for TLS Fallback Signaling Cipher Suite Value (fallback) .TP .B \-\-no\-renegotiation Do not check for secure TLS renegotiation .TP .B \-\-no\-compression Do not check for TLS compression (CRIME) .TP .B \-\-no\-heartbleed Do not check for OpenSSL Heartbleed (CVE-2014-0160) .TP .B \-\-no\-groups Do not enumerate key exchange groups .TP .B \-\-show\-sigs Enumerate signature algorithms .TP .B \-\-starttls\-ftp STARTTLS setup for FTP .TP .B \-\-starttls\-imap STARTTLS setup for IMAP .TP .B \-\-starttls\-irc STARTTLS setup for IRC .TP .B \-\-starttls\-ldap STARTTLS setup for LDAP .TP .B \-\-starttls\-pop3 STARTTLS setup for POP3 .TP .B \-\-starttls\-smtp STARTTLS setup for SMTP .TP .B \-\-starttls\-mysql STARTTLS setup for MySQL .TP .B \-\-starttls\-xmpp STARTTLS setup for XMPP .TP .B \-\-starttls\-psql STARTTLS setup for PostgreSQL .TP .B \-\-xmpp-server Perform a server-to-server XMPP connection. Try this if --starttls-xmpp is failing. .TP .B \-\-rdp .br Send RDP preamble before starting scan. .TP .B \-\-bugs .br Enables workarounds for SSL bugs .TP .B \-\-timeout= .br Set socket timeout. Useful for hosts that fail to respond to ciphers they don't understand. Default is 3s. .TP .B \-\-connect\-timeout= .br Set initial connection timeout. Useful for hosts that are slow to respond to the initial connect(). Default is 75s. .TP .B \-\-sleep= .br Pause between connections. Useful on STARTTLS SMTP services, or anything else that's performing rate limiting. Default is disabled. .TP .B \-\-xml= .br Output results to an XML file. - can be used to mean stdout. .br .TP .B \-\-version Show version of program .TP .B \-\-verbose Display verbose output .TP .B \-\-no\-cipher\-details .br Hide NIST EC curve name and EDH/RSA key length. .TP .B \-\-no-colour .br Disable coloured output. .SH EXAMPLES .LP Scan a local HTTPS server .RS .nf sslscan localhost sslscan 127.0.0.1 sslscan 127.0.0.1:443 sslscan [::1] sslscan [::1]:443 .SH AUTHOR sslscan was originally written by Ian Ventura-Whiting . .br sslscan was extended by Jacob Appelbaum . .br sslscan was extended by rbsec . .br This manual page was originally written by Marvin Stark . sslscan-2.1.2/sslscan.c000066400000000000000000007275601452476416400150320ustar00rootroot00000000000000/*************************************************************************** * sslscan - A SSL cipher scanning tool * * Copyright 2007-2009 by Ian Ventura-Whiting (Fizz) * * fizz@titania.co.uk * * Copyright 2010 by Michael Boman (michael@michaelboman.org) * * Copyleft 2010 by Jacob Appelbaum * * Copyleft 2013 by rbsec * * Copyleft 2014 by Julian Kornberger * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #define _GNU_SOURCE // Includes... #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #define VC_EXTRALEAN #define _WIN32_WINNT 0x0501 #include #include #include #include #include #ifdef _MSC_VER // For access(). #include // Flag for access() call. #define R_OK 4 // access() happens to be deprecated, so use the secure version instead. #define access _access_s // There is no snprintf(), but _snprintf() instead. #define snprintf _snprintf // Calling close() on a socket descriptor instead of closesocket() causes // a crash! #define close closesocket // Visual Studio doesn't have ssize_t... typedef int ssize_t; #else void *memmem(const void *haystack_start, size_t haystack_len, const void *needle, size_t needle_len); /* Taken from https://sourceforge.net/p/mingw/bugs/_discuss/thread/ec0291f1/93ae/attachment/patchset-wrapped.diff:*/ #define timersub(a, b, result) \ do { \ (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ if ((result)->tv_usec < 0) { \ --(result)->tv_sec; \ (result)->tv_usec += 1000000L; \ } \ } while (0) #ifdef BUILD_32BIT #include "win32bit-compat.h" #endif #endif #ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING #define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 #endif #else #include #include #include #include #endif #include #include #include #include #include #include #include #include #include #include #ifdef __linux__ #include #endif #ifndef OPENSSL_NO_COMP #include #endif // If we're not compiling with Visual Studio, include unistd.h. VS // doesn't have this header. #ifndef _MSC_VER #include #endif #if defined(__FreeBSD__) || defined(__OpenBSD__) #include #endif /* Format specifier for printing a size_t. */ #ifdef _WIN32 #define SIZE_T_FMT PRIu64 #else #define SIZE_T_FMT "zu" #endif #include "sslscan.h" #if OPENSSL_VERSION_NUMBER < 0x1010100fL #error "OpenSSL v1.1.1 or later is required!" #endif /* Borrowed from tortls.c to dance with OpenSSL on many platforms, with * many versions and releases of OpenSSL. */ /** Does the run-time openssl version look like we need * SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION? */ static int use_unsafe_renegotiation_op = 0; /** Does the run-time openssl version look like we need * SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION? */ static int use_unsafe_renegotiation_flag = 0; /** Does output xml to stdout? */ static int xml_to_stdout = 0; #if OPENSSL_VERSION_NUMBER < 0x1000100L unsigned long SSL_CIPHER_get_id(const SSL_CIPHER* cipher) { return cipher->id; } #endif const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); const SSL_METHOD *TLSv1_3_client_method(void) { return TLS_client_method(); } const SSL_METHOD *TLSv1_3_method(void) { return TLS_method(); } /* Callback set through SSL_set_security_callback() and SSL_CTX_set_security_callback(). Allows all weak algorithms. */ static int security_callback_allow_all(const SSL *s, const SSL_CTX *ctx, int op, int bits, int nid, void *other, void *ex) { return 1; } /* Creates an SSL_CTX using SSL_CTX_new(), sets the security level to 0, and sets the permissive security callback on it. Free with FREE_CTX(). */ SSL_CTX *new_CTX(const SSL_METHOD *method) { SSL_CTX *ret = SSL_CTX_new(method); SSL_CTX_set_security_level(ret, 0); SSL_CTX_set_security_callback(ret, security_callback_allow_all); return ret; } /* Creates an SSL object using SSL_new(), sets the security level to 0, and sets the permissive security callback on it. Free with FREE_SSL(). */ SSL *new_SSL(SSL_CTX *ctx) { SSL *ret = SSL_new(ctx); SSL_set_security_level(ret, 0); SSL_set_security_callback(ret, security_callback_allow_all); return ret; } // Adds Ciphers to the Cipher List structure int populateCipherList(struct sslCheckOptions *options, const SSL_METHOD *sslMethod) { int returnCode = true; struct sslCipher *sslCipherPointer; int tempInt; int loop; // STACK_OF is a sign that you should be using C++ :) STACK_OF(SSL_CIPHER) *cipherList; SSL *ssl = NULL; options->ctx = new_CTX(sslMethod); if (options->ctx == NULL) { printf_error("Could not create CTX object."); return false; } SSL_CTX_set_cipher_list(options->ctx, CIPHERSUITE_LIST_ALL); ssl = new_SSL(options->ctx); if (ssl == NULL) { printf_error("Could not create SSL object."); FREE_CTX(options->ctx); return false; } cipherList = SSL_get_ciphers(ssl); // Create Cipher Struct Entries... for (loop = 0; loop < sk_SSL_CIPHER_num(cipherList); loop++) { if (options->ciphers == 0) { options->ciphers = malloc(sizeof(struct sslCipher)); sslCipherPointer = options->ciphers; } else { sslCipherPointer = options->ciphers; while (sslCipherPointer->next != 0) sslCipherPointer = sslCipherPointer->next; sslCipherPointer->next = malloc(sizeof(struct sslCipher)); sslCipherPointer = sslCipherPointer->next; } // Init memset(sslCipherPointer, 0, sizeof(struct sslCipher)); // Add cipher information... sslCipherPointer->sslMethod = sslMethod; sslCipherPointer->name = SSL_CIPHER_get_name(sk_SSL_CIPHER_value(cipherList, loop)); sslCipherPointer->version = SSL_CIPHER_get_version(sk_SSL_CIPHER_value(cipherList, loop)); SSL_CIPHER_description(sk_SSL_CIPHER_value(cipherList, loop), sslCipherPointer->description, sizeof(sslCipherPointer->description) - 1); sslCipherPointer->bits = SSL_CIPHER_get_bits(sk_SSL_CIPHER_value(cipherList, loop), &tempInt); } FREE_SSL(ssl); FREE_CTX(options->ctx); return returnCode; } // File Exists int fileExists(char *fileName) { return access(fileName, R_OK) == 0; } // Read a line from the input... void readLine(FILE *input, char *lineFromFile, int maxSize) { // Variables... int stripPointer; // Read line from file... fgets(lineFromFile, maxSize, input); // Clear the end-of-line stuff... stripPointer = strlen(lineFromFile) -1; while (stripPointer >= 0 && ((lineFromFile[stripPointer] == '\r') || (lineFromFile[stripPointer] == '\n') || (lineFromFile[stripPointer] == ' '))) { lineFromFile[stripPointer] = 0; stripPointer--; } } int readOrLogAndClose(int fd, void* buffer, size_t len, const struct sslCheckOptions *options) { ssize_t n; if (len < 2) return 1; n = recv(fd, buffer, len - 1, 0); if (n < 0 && errno != 11) { printf_error("Error reading from %s:%d: %s", options->host, options->port, strerror(errno)); close(fd); return 0; } else if (n == 0) { printf_error("Unexpected EOF reading from %s:%d", options->host, options->port); close(fd); return 0; } else { ((unsigned char *)buffer)[n] = 0; } return 1; } // Write a null-terminated string to a socket ssize_t sendString(int sockfd, const char str[]) { return send(sockfd, str, strlen(str), 0); } char *sock_strerror(int err) { #ifdef _WIN32 static char msg[255]; msg[0] = '\0'; if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), msg, sizeof(msg), NULL) == 0 || msg[0] == '\0') { sprintf(msg, "Error code %d", err); } return msg; #else return strerror(err); #endif } int tcpConnectSocket(int socket, struct sslCheckOptions *options, char *error, int errlen) { int status = -1, flags, errn = 0, len; fd_set rset, wset, eset; struct timeval tval; #ifdef _WIN32 #define INPROGRESS WSAEWOULDBLOCK #define sock_errno WSAGetLastError() flags = 1; if ((status = ioctlsocket(socket, FIONBIO, (u_long *)&flags)) != 0) { snprintf(error, errlen, "ioctlsocket: %s", sock_strerror(sock_errno)); return status; } #else #define INPROGRESS EINPROGRESS #define sock_errno errno if ((flags = fcntl(socket, F_GETFL, 0)) < 0) { snprintf(error, errlen, "fcntl getfl: %s", sock_strerror(sock_errno)); return status; } if (fcntl(socket, F_SETFL, flags | O_NONBLOCK) < 0) { snprintf(error, errlen, "fcntl setfl: %s", sock_strerror(sock_errno)); return status; } #endif // Connect if (options->h_addrtype == AF_INET) { status = connect(socket, (struct sockaddr *)&options->serverAddress, sizeof(options->serverAddress)); } else // IPv6 { status = connect(socket, (struct sockaddr *)&options->serverAddress6, sizeof(options->serverAddress6)); } if (status < 0 && sock_errno != INPROGRESS) { snprintf(error, errlen, "connect: %s", sock_strerror(sock_errno)); return status; } // connect() completed immediately if (status == 0) return status; FD_ZERO(&rset); FD_SET(socket, &rset); wset = eset = rset; tval.tv_sec = options->connect_timeout; tval.tv_usec = 0; if ((status = select(socket + 1, &rset, &wset, &eset, &tval)) == 0) { snprintf(error, errlen, "connect: Timed out"); return -1; } else if (status < 0) { snprintf(error, errlen, "connect: select: %s", sock_strerror(sock_errno)); return status; } if (FD_ISSET(socket, &rset) || FD_ISSET(socket, &wset) || FD_ISSET(socket, &eset)) { len = sizeof(errn); if (getsockopt(socket, SOL_SOCKET, SO_ERROR, (void *)&errn, (socklen_t *)&len) < 0) { snprintf(error, errlen, "connect: getsockopt: %s", sock_strerror(errn)); return -1; } } if (errn) { snprintf(error, errlen, "connect: %s", sock_strerror(errn)); return -1; } #ifdef _WIN32 flags = 0; if ((status = ioctlsocket(socket, FIONBIO, (u_long *)&flags)) != NO_ERROR) { snprintf(error, errlen, "ioctlsocket: %s", sock_strerror(sock_errno)); return -1; } #else if (fcntl(socket, F_SETFL, flags) < 0) { snprintf(error, errlen, "fcntl setfl: %s", sock_strerror(sock_errno)); return -1; } #endif return status; } // Create a TCP socket int tcpConnect(struct sslCheckOptions *options) { //Sleep if required if (options->sleep > 0) { SLEEPMS(options->sleep); } // Variables... int socketDescriptor; int tlsStarted = 0; char buffer[BUFFERSIZE], errmsg[BUFFERSIZE]; int status; // Create Socket if (options->h_addrtype == AF_INET) { socketDescriptor = socket(AF_INET, SOCK_STREAM, 0); } else // IPv6 { socketDescriptor = socket(AF_INET6, SOCK_STREAM, 0); } if(socketDescriptor < 0) { printf_error("Could not open a socket."); return 0; } // Set socket timeout #ifdef _WIN32 // Windows isn't looking for a timeval struct like in UNIX; it wants a timeout in a DWORD represented in milliseconds... DWORD timeout = (options->timeout.tv_sec * 1000) + (options->timeout.tv_usec / 1000); setsockopt(socketDescriptor, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)); setsockopt(socketDescriptor, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)); #else setsockopt(socketDescriptor, SOL_SOCKET, SO_RCVTIMEO, (char *)&options->timeout, sizeof(struct timeval)); setsockopt(socketDescriptor, SOL_SOCKET, SO_SNDTIMEO, (char *)&options->timeout, sizeof(struct timeval)); #endif status = tcpConnectSocket(socketDescriptor, options, errmsg, BUFFERSIZE); if(status < 0) { printf_error("Could not open a connection to host %s (%s) on port %d (%s).", options->host, options->addrstr, options->port, errmsg); close(socketDescriptor); return 0; } // If STARTTLS is required... if (options->starttls_smtp == true && tlsStarted == false) { tlsStarted = 1; if (!readOrLogAndClose(socketDescriptor, buffer, BUFFERSIZE, options)) return 0; if (strncmp(buffer, "220", 3) != 0) { close(socketDescriptor); printf_error("The host %s on port %d did not appear to be an SMTP service.", options->host, options->port); return 0; } sendString(socketDescriptor, "EHLO example.org\r\n"); if (!readOrLogAndClose(socketDescriptor, buffer, BUFFERSIZE, options)) return 0; if (strncmp(buffer, "250", 3) != 0) { close(socketDescriptor); printf_error("The SMTP service on %s port %d did not respond with status 250 to our HELO.", options->host, options->port); return 0; } sendString(socketDescriptor, "STARTTLS\r\n"); if (!readOrLogAndClose(socketDescriptor, buffer, BUFFERSIZE, options)) return 0; if (strncmp(buffer, "220", 3) != 0) { close(socketDescriptor); printf_error("The SMTP service on %s port %d did not appear to support STARTTLS.", options->host, options->port); return 0; } } if (options->starttls_mysql == true && tlsStarted == false) { tlsStarted = 1; // Taken from https://github.com/tetlowgm/sslscan/blob/master/sslscan.c const char mysqlssl[] = { 0x20, 0x00, 0x00, 0x01, 0x85, 0xae, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x01, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; if (!readOrLogAndClose(socketDescriptor, buffer, BUFFERSIZE, options)) return 0; send(socketDescriptor, mysqlssl, sizeof(mysqlssl), 0); } // We could use an XML parser but frankly it seems like a security disaster if (options->starttls_xmpp == true && tlsStarted == false) { /* This is so ghetto, you cannot release it! */ char xmpp_setup[1024]; // options->host is 512 bytes long /* XXX: TODO - options->host isn't always the host you want to test eg: talk.google.com actually expects gmail.com, not talk.google.com jabber.ccc.de expects jabber.ccc.de It may be useful to provide a commandline switch to provide the expected hostname. */ // Server to server handshake if (options->xmpp_server) { if (snprintf(xmpp_setup, sizeof(xmpp_setup), "\r\n" "\r\n", options->host) >= sizeof(xmpp_setup)) { printf("(internal error: xmpp_setup buffer too small)\n"); abort(); } } // Client to server handshake (default) else { if (snprintf(xmpp_setup, sizeof(xmpp_setup), "\r\n" "\r\n", options->host) >= sizeof(xmpp_setup)) { printf("(internal error: xmpp_setup buffer too small)\n"); abort(); } } tlsStarted = 1; sendString(socketDescriptor, xmpp_setup); if (!readOrLogAndClose(socketDescriptor, buffer, BUFFERSIZE, options)) return 0; printf_verbose("Server reported: %s\nAttempting to STARTTLS\n", buffer); sendString(socketDescriptor, "\r\n"); if (!readOrLogAndClose(socketDescriptor, buffer, BUFFERSIZE, options)) return 0; /* We're looking for something like: verbose) printf("Server reported: %s\n", buffer); if (strstr(buffer, "starttls_pop3 == true && tlsStarted == false) { tlsStarted = 1; if (!readOrLogAndClose(socketDescriptor, buffer, BUFFERSIZE, options)) return 0; printf_verbose("Server reported: %s\n", buffer); sendString(socketDescriptor, "STLS\r\n"); if (!readOrLogAndClose(socketDescriptor, buffer, BUFFERSIZE, options)) return 0; // We probably want to confirm that we see something like: // '+OK Begin SSL/TLS negotiation now.' // Or // '+OK Begin TLS negotiation, mate' if (strstr(buffer, "+OK Begin")) { printf_verbose("It appears that the POP3 server is ready for TLS.\n"); } printf_verbose("Server reported: %s\n", buffer); } // Setup an IMAP STARTTLS socket if (options->starttls_imap == true && tlsStarted == false) { tlsStarted = 1; memset(buffer, 0, BUFFERSIZE); // Fetch the IMAP banner if (!readOrLogAndClose(socketDescriptor, buffer, BUFFERSIZE, options)) return 0; printf_verbose("Server banner: %s\n", buffer); // Attempt to STARTTLS sendString(socketDescriptor, ". STARTTLS\r\n"); if (!readOrLogAndClose(socketDescriptor, buffer, BUFFERSIZE, options)) return 0; if (strstr(buffer, ". OK") || strstr(buffer, " . OK")){ printf_verbose("STARTLS IMAP setup complete.\nServer reported: %s\n", buffer); } else{ printf_verbose("STARTLS IMAP setup not complete.\nServer reported: %s\n", buffer); } } if (options->starttls_irc == true && tlsStarted == false) { tlsStarted = 1; if (!readOrLogAndClose(socketDescriptor, buffer, BUFFERSIZE, options)) return 0; printf_verbose("Server reported: %s\n", buffer); // Attempt to STARTTLS sendString(socketDescriptor, "STARTTLS\r\n"); if (!readOrLogAndClose(socketDescriptor, buffer, BUFFERSIZE, options)) return 0; if (strstr(buffer, " 670 ") || strstr(buffer, ":STARTTLS successful")) { printf_verbose("STARTLS IRC setup complete.\nServer reported %s\n", buffer); } else { printf_verbose("STARTLS IRC setup not complete.\nServer reported %s\n", buffer); } } // Setup a LDAP STARTTLS socket if (options->starttls_ldap == true && tlsStarted == false) { tlsStarted = 1; memset(buffer, 0, BUFFERSIZE); char starttls[] = {'0', 0x1d, 0x02, 0x01, 0x01, 'w', 0x18, 0x80, 0x16, '1', '.', '3', '.', '6', '.', '1', '.', '4', '.', '1', '.', '1', '4', '6', '6', '.', '2', '0', '0', '3', '7'}; char ok[] = "1.3.6.1.4.1.1466.20037"; char unsupported[] = "unsupported extended operation"; // Send TLS send(socketDescriptor, starttls, sizeof(starttls), 0); if (!readOrLogAndClose(socketDescriptor, buffer, BUFFERSIZE, options)) return 0; if (memmem(buffer, BUFFERSIZE, ok, strlen(ok))) { printf_verbose("STARTLS LDAP setup complete.\n"); } else if (strstr(buffer, unsupported)) { printf_error("STARTLS LDAP connection to %s:%d failed with '%s'.", options->host, options->port, unsupported); return 0; } else { printf_error("STARTLS LDAP connection to %s:%d failed with unknown error.", options->host, options->port); return 0; } } // Setup a FTP STARTTLS socket if (options->starttls_ftp == true && tlsStarted == false) { tlsStarted = 1; // Fetch the server banner if (!readOrLogAndClose(socketDescriptor, buffer, BUFFERSIZE, options)) return 0; printf_verbose("Server banner: %s\n", buffer); // Send TLS request sendString(socketDescriptor, "AUTH TLS\r\n"); if (!readOrLogAndClose(socketDescriptor, buffer, BUFFERSIZE, options)) return 0; if (strstr(buffer, "234 AUTH TLS successful")) { printf_verbose("STARTLS FTP setup complete.\n"); } else { printf_verbose("STARTLS FTP setup possibly not complete.\n"); } printf_verbose("Server reported: %s\n", buffer); } if (options->starttls_psql == true && tlsStarted == false) { unsigned char buffer; tlsStarted = 1; // Send SSLRequest packet send(socketDescriptor, "\x00\x00\x00\x08\x04\xd2\x16\x2f", 8, 0); // Read reply byte if (1 != recv(socketDescriptor, &buffer, 1, 0)) { printf_error("Unexpected EOF reading from %s:%d", options->host, options->port); return 0; } if (buffer != 'S') { printf_error("Server at %s:%d rejected TLS startup", options->host, options->port); return 0; } } // Setup an RDP socket with preamble // Borrowed from https://labs.portcullis.co.uk/tools/ssl-cipher-suite-enum/ if (options->rdp == true && tlsStarted == false) { unsigned char buffer[32768]; size_t readlen; tlsStarted = 1; // Send RDP preamble send(socketDescriptor, "\x03\x00\x00\x13\x0e\xe0\x00\x00\x00\x00\x00\x01\x00\x08\x00\x03\x00\x00\x00", 19, 0); // Read reply header if (4 != recv(socketDescriptor, buffer, 4, 0)) { printf_error("Unexpected EOF reading from %s:%d", options->host, options->port); return 0; } // Calculate remaining bytes (and check for overflows) readlen = ((buffer[2] & 0x7f) << 8) + buffer[3] - 4; if (readlen > sizeof(buffer)) { printf_error("Unexpected data from %s:%d", options->host, options->port); return 0; } // Read reply data if (readlen != recv(socketDescriptor, buffer, readlen, 0)) { printf_error("Unexpected EOF reading from %s:%d", options->host, options->port); return 0; } } // Return return socketDescriptor; } // Private Key Password Callback... static int password_callback(char *buf, int size, int rwflag, void *userdata) { strncpy(buf, (char *)userdata, size); // I don't know the semantics of these arguments, but it looks like this // could go badly wrong if userdata is too long. buf[strlen(userdata)] = 0; return strlen(userdata); } // Load client certificates/private keys... int loadCerts(struct sslCheckOptions *options) { // Variables... int status = 1; PKCS12 *pk12 = NULL; FILE *pk12File = NULL; X509 *cert = NULL; EVP_PKEY *pkey = NULL; STACK_OF(X509) *ca = NULL; // Configure PKey password... if (options->privateKeyPassword != 0) { SSL_CTX_set_default_passwd_cb_userdata(options->ctx, (void *)options->privateKeyPassword); SSL_CTX_set_default_passwd_cb(options->ctx, password_callback); } // Separate Certs and PKey Files... if ((options->clientCertsFile != 0) && (options->privateKeyFile != 0)) { // Load Cert... if (!SSL_CTX_use_certificate_file(options->ctx, options->clientCertsFile, SSL_FILETYPE_PEM)) { if (!SSL_CTX_use_certificate_file(options->ctx, options->clientCertsFile, SSL_FILETYPE_ASN1)) { if (!SSL_CTX_use_certificate_chain_file(options->ctx, options->clientCertsFile)) { printf("%s Could not configure certificate(s).%s\n", COL_RED, RESET); status = 0; } } } // Load PKey... if (status != 0) { if (!SSL_CTX_use_PrivateKey_file(options->ctx, options->privateKeyFile, SSL_FILETYPE_PEM)) { if (!SSL_CTX_use_PrivateKey_file(options->ctx, options->privateKeyFile, SSL_FILETYPE_ASN1)) { // Why would the more specific functions succeed if the generic functions failed? // -- I'm guessing that the original author was hopeful? - io if (!SSL_CTX_use_RSAPrivateKey_file(options->ctx, options->privateKeyFile, SSL_FILETYPE_PEM)) { if (!SSL_CTX_use_RSAPrivateKey_file(options->ctx, options->privateKeyFile, SSL_FILETYPE_ASN1)) { printf("%s Could not configure private key.%s\n", COL_RED, RESET); status = 0; } } } } } } // PKCS Cert and PKey File... else if (options->privateKeyFile != 0) { pk12File = fopen(options->privateKeyFile, "rb"); if (pk12File != NULL) { pk12 = d2i_PKCS12_fp(pk12File, NULL); if (!pk12) { status = 0; printf("%s Could not read PKCS#12 file.%s\n", COL_RED, RESET); } else { if (!PKCS12_parse(pk12, options->privateKeyPassword, &pkey, &cert, &ca)) { status = 0; printf("%s Error parsing PKCS#12. Are you sure that password was correct?%s\n", COL_RED, RESET); } else { if (!SSL_CTX_use_certificate(options->ctx, cert)) { status = 0; printf("%s Could not configure certificate.%s\n", COL_RED, RESET); } if (!SSL_CTX_use_PrivateKey(options->ctx, pkey)) { status = 0; printf("%s Could not configure private key.%s\n", COL_RED, RESET); } } PKCS12_free(pk12); } fclose(pk12File); } else { printf("%s Could not open PKCS#12 file.%s\n", COL_RED, RESET); status = 0; } } // Check Cert/Key... if (status != 0) { if (!SSL_CTX_check_private_key(options->ctx)) { printf("%s Private key does not match certificate.%s\n", COL_RED, RESET); return false; } else return true; } else return false; } // Test renegotiation int outputRenegotiation( struct sslCheckOptions *options, struct renegotiationOutput *outputData) { printf_xml(" \n", outputData->supported, outputData->secure); if (outputData->secure) { printf("%sSecure%s session renegotiation supported\n\n", COL_GREEN, RESET); } else if (outputData->supported) { printf("%sInsecure%s session renegotiation supported\n\n", COL_RED, RESET); } else { printf("Session renegotiation %snot supported%s\n\n", COL_GREEN, RESET); } return true; } struct renegotiationOutput * newRenegotiationOutput( void ) { struct renegotiationOutput *myRenOut; myRenOut = calloc(1,sizeof(struct renegotiationOutput)); return( myRenOut ); } int freeRenegotiationOutput( struct renegotiationOutput *myRenOut ) { if ( myRenOut != NULL) { free(myRenOut); } return true; } void tls_reneg_init(struct sslCheckOptions *options) { /* Borrowed from tortls.c to dance with OpenSSL on many platforms, with * many versions and release of OpenSSL. */ SSL_library_init(); SSL_load_error_strings(); long version = SSLeay(); if (version >= 0x009080c0L && version < 0x009080d0L) { printf_verbose("OpenSSL %s looks like version 0.9.8l; I will try SSL3_FLAGS to enable renegotiation.\n", SSLeay_version(SSLEAY_VERSION)); use_unsafe_renegotiation_flag = 1; use_unsafe_renegotiation_op = 1; } else if (version >= 0x009080d0L) { printf_verbose("OpenSSL %s looks like version 0.9.8m or later; " "I will try SSL_OP to enable renegotiation\n", SSLeay_version(SSLEAY_VERSION)); use_unsafe_renegotiation_op = 1; } else if (version < 0x009080c0L) { printf_verbose("OpenSSL %s [%lx] looks like it's older than " "0.9.8l, but some vendors have backported 0.9.8l's " "renegotiation code to earlier versions, and some have " "backported the code from 0.9.8m or 0.9.8n. I'll set both " "SSL3_FLAGS and SSL_OP just to be safe.\n", SSLeay_version(SSLEAY_VERSION), version); use_unsafe_renegotiation_flag = 1; use_unsafe_renegotiation_op = 1; } else { printf_verbose("OpenSSL %s has version %lx\n", SSLeay_version(SSLEAY_VERSION), version); } #ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION SSL_CTX_set_options(options->ctx, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); #endif } // Check if the server supports compression int testCompression(struct sslCheckOptions *options, const SSL_METHOD *sslMethod) { // Variables... int status = true; int socketDescriptor = 0; SSL *ssl = NULL; BIO *cipherConnectionBio; SSL_SESSION *session; // Connect to host socketDescriptor = tcpConnect(options); if (socketDescriptor != 0) { // Setup Context Object... options->ctx = new_CTX(sslMethod); tls_reneg_init(options); if (options->ctx != NULL) { if (SSL_CTX_set_cipher_list(options->ctx, CIPHERSUITE_LIST_ALL) != 0) { // Load Certs if required... if ((options->clientCertsFile != 0) || (options->privateKeyFile != 0)) status = loadCerts(options); if (status == true) { // Create SSL object... ssl = new_SSL(options->ctx); #if ( OPENSSL_VERSION_NUMBER > 0x009080cfL ) // Make sure we can connect to insecure servers // OpenSSL is going to change the default at a later date SSL_set_options(ssl, SSL_OP_LEGACY_SERVER_CONNECT); #endif #ifdef SSL_OP_NO_COMPRESSION // Make sure to clear the no compression flag SSL_clear_options(ssl, SSL_OP_NO_COMPRESSION); #endif if (ssl != NULL) { // Connect socket and BIO cipherConnectionBio = BIO_new_socket(socketDescriptor, BIO_NOCLOSE); // Connect SSL and BIO SSL_set_bio(ssl, cipherConnectionBio, cipherConnectionBio); #if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT) // This enables TLS SNI SSL_set_tlsext_host_name(ssl, options->sniname); #endif // Connect SSL over socket SSL_connect(ssl); session = SSL_get_session(ssl); #ifndef OPENSSL_NO_COMP // Make sure zlib is actually present if (sk_SSL_COMP_num(SSL_COMP_get_compression_methods()) != 0) { printf_xml(" \n", SSL_SESSION_get_compress_id(session)); if (SSL_SESSION_get_compress_id(session) == 0) { printf("Compression %sdisabled%s\n\n", COL_GREEN, RESET); } else { printf("Compression %senabled%s (CRIME)\n\n", COL_RED, RESET); } } else #endif { printf("%sOpenSSL version does not support compression%s\n", COL_RED, RESET); printf("%sRebuild with zlib1g-dev package for zlib support%s\n\n", COL_RED, RESET); } // Disconnect SSL over socket SSL_shutdown(ssl); // Free SSL object FREE_SSL(ssl); } else { status = false; printf_error("Could not create SSL object."); } } } else { status = false; printf_error("Could not set cipher."); } // Free CTX Object FREE_CTX(options->ctx); } // Error Creating Context Object else { status = false; printf_error("Could not create CTX object."); } // Disconnect from host close(socketDescriptor); } else { // Could not connect printf_error("Could not connect."); exit(1); } return status; } #ifdef SSL_MODE_SEND_FALLBACK_SCSV // Check for TLS_FALLBACK_SCSV int testFallback(struct sslCheckOptions *options, const SSL_METHOD *sslMethod) { // Variables... int status = true; int downgraded = true; int connStatus = false; int socketDescriptor = 0; int sslversion; SSL *ssl = NULL; BIO *cipherConnectionBio; const SSL_METHOD *secondMethod; // Function gets called a second time with downgraded protocol if (!sslMethod) { sslMethod = SSLv23_method(); downgraded = false; } // Connect to host socketDescriptor = tcpConnect(options); if (socketDescriptor != 0) { // Setup Context Object... options->ctx = new_CTX(sslMethod); tls_reneg_init(options); if (options->ctx != NULL) { if (downgraded) { SSL_CTX_set_mode(options->ctx, SSL_MODE_SEND_FALLBACK_SCSV); } if (SSL_CTX_set_cipher_list(options->ctx, CIPHERSUITE_LIST_ALL) != 0) { // Load Certs if required... if ((options->clientCertsFile != 0) || (options->privateKeyFile != 0)) status = loadCerts(options); if (status == true) { // Create SSL object... ssl = new_SSL(options->ctx); #if ( OPENSSL_VERSION_NUMBER > 0x009080cfL ) // Make sure we can connect to insecure servers // OpenSSL is going to change the default at a later date SSL_set_options(ssl, SSL_OP_LEGACY_SERVER_CONNECT); #endif #ifdef SSL_OP_NO_COMPRESSION // Make sure to clear the no compression flag SSL_clear_options(ssl, SSL_OP_NO_COMPRESSION); #endif if (ssl != NULL) { // Connect socket and BIO cipherConnectionBio = BIO_new_socket(socketDescriptor, BIO_NOCLOSE); // Connect SSL and BIO SSL_set_bio(ssl, cipherConnectionBio, cipherConnectionBio); #if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT) // This enables TLS SNI SSL_set_tlsext_host_name(ssl, options->sniname); #endif // Connect SSL over socket connStatus = SSL_connect(ssl); if (connStatus > 0) { if (!downgraded) { sslversion = SSL_version(ssl); if (sslversion == TLS1_3_VERSION) { secondMethod = TLSv1_2_client_method(); } else if (sslversion == TLS1_2_VERSION) { secondMethod = TLSv1_1_client_method(); } else if (sslversion == TLS1_VERSION) { secondMethod = TLSv1_client_method(); } else if (sslversion == TLS1_VERSION) { printf("Server only supports TLSv1.0"); status = false; } else { printf("Server doesn't support TLS - skipping TLS Fallback SCSV check\n\n"); status = false; } } else { printf("Server %sdoes not%s support TLS Fallback SCSV\n\n", COL_RED, RESET); printf_xml(" \n"); } } else { if (downgraded) { if (SSL_get_error(ssl, connStatus == 1)) { ERR_get_error(); if (SSL_get_error(ssl, connStatus == 6)) { printf("Server %ssupports%s TLS Fallback SCSV\n\n", COL_GREEN, RESET); printf_xml(" \n"); status = false; } } } else { printf("%sConnection failed%s - unable to determine TLS Fallback SCSV support\n\n", COL_YELLOW, RESET); status = false; } } // Disconnect SSL over socket SSL_shutdown(ssl); // Free SSL object FREE_SSL(ssl); } else { status = false; printf_error("Could not create SSL object."); } } } else { status = false; printf_error("Could not set cipher."); } // Free CTX Object FREE_CTX(options->ctx); } // Error Creating Context Object else { status = false; printf_error("Could not create CTX object."); } // Disconnect from host close(socketDescriptor); } else { // Could not connect printf_error("Could not connect."); exit(1); } // Call function again with downgraded protocol if (status && !downgraded) { testFallback(options, secondMethod); } return status; } #endif // Check if the server supports renegotiation int testRenegotiation(struct sslCheckOptions *options, const SSL_METHOD *sslMethod) { // Variables... int cipherStatus; int status = true; //int secure = false; int socketDescriptor = 0; int res; SSL *ssl = NULL; BIO *cipherConnectionBio; struct renegotiationOutput *renOut = newRenegotiationOutput(); // Connect to host socketDescriptor = tcpConnect(options); if (socketDescriptor != 0) { // Setup Context Object... options->ctx = new_CTX(sslMethod); tls_reneg_init(options); if (options->ctx != NULL) { if (SSL_CTX_set_cipher_list(options->ctx, CIPHERSUITE_LIST_ALL) != 0) { // Load Certs if required... if ((options->clientCertsFile != 0) || (options->privateKeyFile != 0)) status = loadCerts(options); if (status == true) { // Create SSL object... ssl = new_SSL(options->ctx); #if ( OPENSSL_VERSION_NUMBER > 0x009080cfL ) // Make sure we can connect to insecure servers // OpenSSL is going to change the default at a later date SSL_set_options(ssl, SSL_OP_LEGACY_SERVER_CONNECT); #endif if (ssl != NULL) { // Connect socket and BIO cipherConnectionBio = BIO_new_socket(socketDescriptor, BIO_NOCLOSE); // Connect SSL and BIO SSL_set_bio(ssl, cipherConnectionBio, cipherConnectionBio); #if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT) // This enables TLS SNI // Based on http://does-not-exist.org/mail-archives/mutt-dev/msg13045.html // TLS Virtual-hosting requires that the server present the correct // certificate; to do this, the ServerNameIndication TLS extension is used. // If TLS is negotiated, and OpenSSL is recent enough that it might have // support, and support was enabled when OpenSSL was built, mutt supports // sending the hostname we think we're connecting to, so a server can send // back the correct certificate. // NB: finding a server which uses this for IMAP is problematic, so this is // untested. Please report success or failure! However, this code change // has worked fine in other projects to which the contributor has added it, // or HTTP usage. SSL_set_tlsext_host_name(ssl, options->sniname); #endif // Connect SSL over socket cipherStatus = SSL_connect(ssl); /* Yes, we know what we are doing here. No, we do not treat a renegotiation * as authenticating any earlier-received data. */ /* if (use_unsafe_renegotiation_flag) { printf_verbose("use_unsafe_renegotiation_flag\n"); SSL_CTX_set_options(ssl,SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION); SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION?? } */ if (use_unsafe_renegotiation_op) { printf_verbose("use_unsafe_renegotiation_op\n"); SSL_set_options(ssl, SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION); } if (cipherStatus == 1) { #if ( OPENSSL_VERSION_NUMBER > 0x009080cfL ) // SSL_get_secure_renegotiation_support() appeared first in OpenSSL 0.9.8m printf_verbose("Attempting secure_renegotiation_support()\n"); renOut->secure = SSL_get_secure_renegotiation_support(ssl); if( renOut->secure ) { // If it supports secure renegotiations, // it should have renegotiation support in general renOut->supported = true; status = true; } else { #endif // We can't assume that just because the secure renegotiation // support failed the server doesn't support insecure renegotiations // assume ssl is connected and error free up to here //setBlocking(ssl); // this is unnecessary if it is already blocking printf_verbose("Attempting SSL_renegotiate(ssl)\n"); SSL_renegotiate(ssl); // Ask to renegotiate the connection // This hangs when an 'encrypted alert' is sent by the server printf_verbose("Attempting SSL_do_handshake(ssl)\n"); SSL_do_handshake(ssl); // Send renegotiation request to server //TODO :: XXX hanging here if (SSL_get_state(ssl) == TLS_ST_OK) { res = SSL_do_handshake(ssl); // Send renegotiation request to server if( res != 1 ) { printf_error("SSL_do_handshake() call failed"); } if (SSL_get_state(ssl) == TLS_ST_OK) { /* our renegotiation is complete */ renOut->supported = true; status = true; } else { renOut->supported = false; status = false; printf_error("Failed to complete renegotiation"); } } else { status = false; renOut->secure = false; } #if ( OPENSSL_VERSION_NUMBER > 0x009080cfL ) } #endif // Disconnect SSL over socket SSL_shutdown(ssl); } // Free SSL object FREE_SSL(ssl); } else { status = false; renOut->supported = false; printf_error("Could not create SSL object."); } } } else { status = false; renOut->supported = false; printf_error("Could not set cipher."); } // Free CTX Object FREE_CTX(options->ctx); } // Error Creating Context Object else { status = false; renOut->supported = false; printf_error("Could not create CTX object."); } // Disconnect from host close(socketDescriptor); } else { // Could not connect printf_error("Could not connect."); renOut->supported = false; freeRenegotiationOutput( renOut ); exit(1); } outputRenegotiation(options, renOut); freeRenegotiationOutput( renOut ); return status; } const char* printableSslMethod(const SSL_METHOD *sslMethod) { if (sslMethod == TLSv1_client_method()) return "TLSv1.0"; #if OPENSSL_VERSION_NUMBER >= 0x10001000L if (sslMethod == TLSv1_1_client_method()) return "TLSv1.1"; if (sslMethod == TLSv1_2_client_method()) return "TLSv1.2"; #endif if (sslMethod == TLSv1_3_client_method()) return "TLSv1.3"; return "unknown SSL_METHOD"; } // Test for Heartbleed int testHeartbleed(struct sslCheckOptions *options, const SSL_METHOD *sslMethod) { // Variables... int status = true; int socketDescriptor = 0; // Connect to host socketDescriptor = tcpConnect(options); if (socketDescriptor != 0) { // Credit to Jared Stafford (jspenguin@jspenguin.org) char hello[] = {0x16,0x03,0x01,0x00,0xdc,0x01,0x00,0x00,0xd8,0x03,0x00,0x53,0x43,0x5b,0x90,0x9d,0x9b,0x72,0x0b,0xbc,0x0c,0xbc,0x2b,0x92,0xa8,0x48,0x97,0xcf,0xbd,0x39,0x04,0xcc,0x16,0x0a,0x85,0x03,0x90,0x9f,0x77,0x04,0x33,0xd4,0xde,0x00,0x00,0x66,0xc0,0x14,0xc0,0x0a,0xc0,0x22,0xc0,0x21,0x00,0x39,0x00,0x38,0x00,0x88,0x00,0x87,0xc0,0x0f,0xc0,0x05,0x00,0x35,0x00,0x84,0xc0,0x12,0xc0,0x08,0xc0,0x1c,0xc0,0x1b,0x00,0x16,0x00,0x13,0xc0,0x0d,0xc0,0x03,0x00,0x0a,0xc0,0x13,0xc0,0x09,0xc0,0x1f,0xc0,0x1e,0x00,0x33,0x00,0x32,0x00,0x9a,0x00,0x99,0x00,0x45,0x00,0x44,0xc0,0x0e,0xc0,0x04,0x00,0x2f,0x00,0x96,0x00,0x41,0xc0,0x11,0xc0,0x07,0xc0,0x0c,0xc0,0x02,0x00,0x05,0x00,0x04,0x00,0x15,0x00,0x12,0x00,0x09,0x00,0x14,0x00,0x11,0x00,0x08,0x00,0x06,0x00,0x03,0x00,0xff,0x01,0x00,0x00,0x49,0x00,0x0b,0x00,0x04,0x03,0x00,0x01,0x02,0x00,0x0a,0x00,0x34,0x00,0x32,0x00,0x0e,0x00,0x0d,0x00,0x19,0x00,0x0b,0x00,0x0c,0x00,0x18,0x00,0x09,0x00,0x0a,0x00,0x16,0x00,0x17,0x00,0x08,0x00,0x06,0x00,0x07,0x00,0x14,0x00,0x15,0x00,0x04,0x00,0x05,0x00,0x12,0x00,0x13,0x00,0x01,0x00,0x02,0x00,0x03,0x00,0x0f,0x00,0x10,0x00,0x11,0x00,0x23,0x00,0x00,0x00,0x0f,0x00,0x01,0x01}; if (sslMethod == TLSv1_client_method()) { hello[10] = 0x01; } #if OPENSSL_VERSION_NUMBER >= 0x10001000L else if (sslMethod == TLSv1_1_client_method()) { hello[10] = 0x02; } else if (sslMethod == TLSv1_2_client_method()) { hello[10] = 0x03; } #endif else if (sslMethod == TLSv1_3_client_method()) { hello[10] = 0x03; } if (send(socketDescriptor, hello, sizeof(hello), 0) <= 0) { printf_error("send() failed: %s", strerror(errno)); exit(1); } // Send the heartbeat char hb[8] = {0x18,0x03,0x00,0x00,0x03,0x01,0x40,0x00}; if (sslMethod == TLSv1_client_method()) { hb[2] = 0x01; } #if OPENSSL_VERSION_NUMBER >= 0x10001000L else if (sslMethod == TLSv1_1_client_method()) { hb[2] = 0x02; } else if (sslMethod == TLSv1_2_client_method()) { hb[2] = 0x03; } #endif else if (sslMethod == TLSv1_3_client_method()) { hb[2] = 0x03; } if (send(socketDescriptor, hb, sizeof(hb), 0) <= 0) { printf_error("send() failed: %s", strerror(errno)); exit(1); } char hbbuf[65536]; while(1) { memset(hbbuf, 0, sizeof(hbbuf)); // Read 5 byte header int readResult = recv(socketDescriptor, hbbuf, 5, 0); if (readResult <= 0) { break; } char typ = hbbuf[0]; // Combine 2 bytes to get payload length uint16_t ln = hbbuf[4] | hbbuf[3] << 8; // Debugging /* uint16_t ver = hbbuf[2] | hbbuf[1] << 8; printf("%hhX %hhX %hhX %hhX %hhX - %d %d %d\n", hbbuf[0], hbbuf[1], hbbuf[2], hbbuf[3], hbbuf[4], typ, ver, ln); */ memset(hbbuf, 0, sizeof(hbbuf)); // Read rest of record readResult = recv(socketDescriptor, hbbuf, ln, 0); if (readResult <= 0) { break; } // Server returned error if (typ == 21) { break; } // Successful response else if (typ == 24 && ln > 3) { printf("%svulnerable%s to heartbleed\n", COL_RED, RESET); printf_xml(" \n", printableSslMethod(sslMethod)); close(socketDescriptor); return status; } } printf("%snot vulnerable%s to heartbleed\n", COL_GREEN, RESET); printf_xml(" \n", printableSslMethod(sslMethod)); // Disconnect from host close(socketDescriptor); } else { // Could not connect printf_error("Could not connect."); printf("dying"); exit(1); } return status; } int ssl_print_tmp_key(struct sslCheckOptions *options, SSL *s) { #if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER) EVP_PKEY *key; if (!SSL_get_server_tmp_key(s, &key)) return 1; switch (EVP_PKEY_id(key)) { case EVP_PKEY_RSA: if (EVP_PKEY_bits(key) <= 768) { printf(" RSA %s%d%s bits", COL_RED, EVP_PKEY_bits(key), RESET); } else if (EVP_PKEY_bits(key) <= 1024) { printf(" RSA %s%d%s bits", COL_YELLOW, EVP_PKEY_bits(key), RESET); } else { printf(" RSA %d bits", EVP_PKEY_bits(key)); } break; case EVP_PKEY_DH: if (EVP_PKEY_bits(key) <= 768) { printf(" DHE %s%d%s bits", COL_RED, EVP_PKEY_bits(key), RESET); } else if (EVP_PKEY_bits(key) <= 1024) { printf(" DHE %s%d%s bits", COL_YELLOW, EVP_PKEY_bits(key), RESET); } else { printf(" DHE %d bits", EVP_PKEY_bits(key)); } printf_xml(" dhebits=\"%d\"", EVP_PKEY_bits(key)); break; case EVP_PKEY_EC: { EC_KEY *ec = EVP_PKEY_get1_EC_KEY(key); int nid; const char *cname; nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)); EC_KEY_free(ec); cname = EC_curve_nid2nist(nid); if (!cname) cname = OBJ_nid2sn(nid); printf(" Curve %s DHE %d", cname, EVP_PKEY_bits(key)); printf_xml(" curve=\"%s\" ecdhebits=\"%d\"", cname, EVP_PKEY_bits(key)); } break; case EVP_PKEY_X25519: printf(" Curve %s25519%s DHE %d", COL_GREEN, RESET, EVP_PKEY_bits(key)); printf_xml(" curve=\"25519\" ecdhebits=\"%d\"", EVP_PKEY_bits(key)); break; case EVP_PKEY_X448: printf(" Curve %s448%s DHE %d", COL_GREEN, RESET, EVP_PKEY_bits(key)); printf_xml(" curve=\"448\" ecdhebits=\"%d\"", EVP_PKEY_bits(key)); break; default: printf(" %sUnknown ID (%d)%s", COL_YELLOW, EVP_PKEY_id(key), RESET); } EVP_PKEY_free(key); return 1; #endif return 0; } int setCipherSuite(struct sslCheckOptions *options, const SSL_METHOD *sslMethod, const char *str) { if(strlen(str)>0) { if(sslMethod==TLSv1_3_client_method()) { return(SSL_CTX_set_ciphersuites(options->ctx,str)); } else { return(SSL_CTX_set_cipher_list(options->ctx,str)); } } return 0; } char *cipherRemove(char *str, const char *sub) { char *p, *q, *r; if ((q = r = strstr(str, sub)) != NULL) { size_t len = strlen(sub)+1; if(q != str) { q--; r--; } while ((r = strstr(p = r + len, sub)) != NULL) { while (p < r) *q++ = *p++; } while ((*q++ = *p++) != '\0') continue; } return str; } /* Outputs an accepted cipher to the console and XML file. */ void outputCipher(struct sslCheckOptions *options, SSL *ssl, const char *cleanSslMethod, uint32_t cipherid, const char *ciphername, int cipherbits, int cipher_accepted, unsigned int milliseconds_elapsed) { char hexCipherId[8] = {0}; char *strength; unsigned int tempInt = 0; printf_xml(" cipherstring, CIPHERSUITE_LIST_ALL) && strcmp(options->cipherstring, TLSV13_CIPHERSUITES)) { printf_xml("accepted\""); printf("Accepted "); } else { printf_xml("preferred\""); printf("%sPreferred%s ", COL_GREEN, RESET); } printf_xml(" sslversion=\"%s\"", cleanSslMethod); if (strcmp(cleanSslMethod, "TLSv1.3") == 0) { printf("%sTLSv1.3%s ", COL_GREEN, RESET); } else if (strcmp(cleanSslMethod, "TLSv1.1") == 0) { printf("%sTLSv1.1%s ", COL_YELLOW, RESET); } else if (strcmp(cleanSslMethod, "TLSv1.0") == 0) { printf("%sTLSv1.0%s ", COL_YELLOW, RESET); } else printf("%s ", cleanSslMethod); if (cipherbits < 10) tempInt = 2; else if (cipherbits < 100) tempInt = 1; if (cipherbits == -1) { /* When missing ciphers are tested, and we don't have a reasonable guess. */ printf("%s??%s bits ", COL_YELLOW, RESET); } else if (cipherbits == 0) { printf("%s%d%s bits ", COL_RED_BG, cipherbits, RESET); } else if (cipherbits >= 112) { printf("%s%d%s bits ", COL_GREEN, cipherbits, RESET); } else if (cipherbits > 56) { printf("%s%d%s bits ", COL_YELLOW, cipherbits, RESET); } else printf("%s%d%s bits ", COL_RED, cipherbits, RESET); while (tempInt != 0) { tempInt--; printf(" "); } snprintf(hexCipherId, sizeof(hexCipherId) - 1, "0x%04X", cipherid); if (options->showCipherIds == true) printf("%8s ", hexCipherId); printf_xml(" bits=\"%d\" cipher=\"%s\" id=\"%s\"", cipherbits, ciphername, hexCipherId); if (strstr(ciphername, "NULL")) { if (options->ianaNames) { printf("%s%-45s%s", COL_RED_BG, ciphername, RESET); } else { printf("%s%-29s%s", COL_RED_BG, ciphername, RESET); } strength = "null"; } else if (strstr(ciphername, "ADH") || strstr(ciphername, "AECDH") || strstr(ciphername, "_anon_")) { if (options->ianaNames) { printf("%s%-45s%s", COL_PURPLE, ciphername, RESET); } else { printf("%s%-29s%s", COL_PURPLE, ciphername, RESET); } strength = "anonymous"; } else if (strstr(ciphername, "EXP")) { if (options->ianaNames) { printf("%s%-45s%s", COL_RED, ciphername, RESET); } else { printf("%s%-29s%s", COL_RED, ciphername, RESET); } strength = "weak"; } else if (strstr(ciphername, "RC4") || strstr(ciphername, "DES")) { if (options->ianaNames) { printf("%s%-45s%s", COL_YELLOW, ciphername, RESET); } else { printf("%s%-29s%s", COL_YELLOW, ciphername, RESET); } strength = "medium"; } else if (strstr(ciphername, "_SM4_")) { /* Developed by Chinese government */ if (options->ianaNames) { printf("%s%-45s%s", COL_YELLOW, ciphername, RESET); } else { printf("%s%-29s%s", COL_YELLOW, ciphername, RESET); } strength = "medium"; } else if (strstr(ciphername, "_GOSTR341112_")) { /* Developed by Russian government */ if (options->ianaNames) { printf("%s%-45s%s", COL_YELLOW, ciphername, RESET); } else { printf("%s%-29s%s", COL_YELLOW, ciphername, RESET); } strength = "medium"; } else if ((strstr(ciphername, "CHACHA20") || (strstr(ciphername, "GCM"))) && (strstr(ciphername, "DHE") || (strcmp(cleanSslMethod, "TLSv1.3") == 0))) { if (options->ianaNames) { printf("%s%-45s%s", COL_GREEN, ciphername, RESET); } else { printf("%s%-29s%s", COL_GREEN, ciphername, RESET); } strength = "strong"; } else { if (options->ianaNames) { printf("%-45s", ciphername); } else { printf("%-29s", ciphername); } strength = "acceptable"; } printf_xml(" strength=\"%s\"", strength); if ((options->cipher_details == true) && (ssl != NULL)) ssl_print_tmp_key(options, ssl); // Timing if (options->showTimes) { printf(" %s%ums%s", COL_GREY, milliseconds_elapsed, RESET); printf_xml(" time=\"%u\"", milliseconds_elapsed); } printf("\n"); } printf_xml(" />\n"); } // Test a cipher... int testCipher(struct sslCheckOptions *options, const SSL_METHOD *sslMethod) { // Variables... int cipherStatus = 0; int status = true; int socketDescriptor = 0; SSL *ssl = NULL; BIO *cipherConnectionBio = NULL; int cipherbits = -1; uint32_t cipherid = 0; const SSL_CIPHER *sslCipherPointer = NULL; const char *cleanSslMethod = printableSslMethod(sslMethod); const char *ciphername = NULL; struct timeval tval_start = {0}; unsigned int milliseconds_elapsed = 0; if (options->showTimes) { gettimeofday(&tval_start, NULL); } // Connect to host socketDescriptor = tcpConnect(options); if (socketDescriptor != 0) { if (setCipherSuite(options, sslMethod, options->cipherstring)) { // Create SSL object... ssl = new_SSL(options->ctx); if (ssl != NULL) { // Connect socket and BIO cipherConnectionBio = BIO_new_socket(socketDescriptor, BIO_NOCLOSE); // Connect SSL and BIO SSL_set_bio(ssl, cipherConnectionBio, cipherConnectionBio); // This enables TLS SNI SSL_set_tlsext_host_name (ssl, options->sniname); // Against some servers, this is required for a successful SSL_connect(), below. SSL_set_options(ssl, SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION); // Connect SSL over socket cipherStatus = SSL_connect(ssl); printf_verbose("SSL_connect() returned: %d\n", cipherStatus); sslCipherPointer = SSL_get_current_cipher(ssl); if (sslCipherPointer == NULL) { printf_verbose("SSL_get_current_cipher() returned NULL; this indicates that the server did not choose a cipher from our list (%s)\n", options->cipherstring); SSL_shutdown(ssl); FREE_SSL(ssl); CLOSE(socketDescriptor); return false; } cipherbits = SSL_CIPHER_get_bits(sslCipherPointer, NULL); cipherid = SSL_CIPHER_get_id(sslCipherPointer); cipherid = cipherid & 0x00ffffff; // remove first byte which is the version (0x03 for TLSv1/SSLv3) if (options->ianaNames) { ciphername = SSL_CIPHER_standard_name(sslCipherPointer); } else { ciphername = SSL_CIPHER_get_name(sslCipherPointer); } // Timing if (options->showTimes) { struct timeval tval_end = {0}, tval_elapsed = {0}; gettimeofday(&tval_end, NULL); timersub(&tval_end, &tval_start, &tval_elapsed); milliseconds_elapsed = tval_elapsed.tv_sec * 1000 + (int)tval_elapsed.tv_usec / 1000; } outputCipher(options, ssl, cleanSslMethod, cipherid, ciphername, cipherbits, 1, milliseconds_elapsed); // Disconnect SSL over socket const char *usedcipher = SSL_get_cipher_name(ssl); if(sslMethod == TLSv1_3_client_method()) cipherRemove(options->cipherstring, usedcipher); // Remove cipher from TLSv1.3 list else { // Using strcat rather than strncat to avoid a warning from GCC strcat(options->cipherstring, ":!"); strncat(options->cipherstring, usedcipher, strlen(usedcipher)); } SSL_shutdown(ssl); // Free SSL object FREE_SSL(ssl); } else { status = false; printf_error("Could not create SSL object."); } } else { status = false; } // Disconnect from host CLOSE(socketDescriptor); } // Could not connect else status = false; return status; } int checkCertificateProtocol(struct sslCheckOptions *options, const SSL_METHOD *sslMethod) { int status = true; // Setup Context Object... options->ctx = new_CTX(sslMethod); if (options->ctx != NULL) { // SSL implementation bugs/workaround if (options->sslbugs) SSL_CTX_set_options(options->ctx, SSL_OP_ALL | 0); else SSL_CTX_set_options(options->ctx, 0); // Load Certs if required... if ((options->clientCertsFile != 0) || (options->privateKeyFile != 0)) status = loadCerts(options); // Check the certificate status = checkCertificate(options, sslMethod); } // Error Creating Context Object else { printf_error("Could not create CTX object."); status = false; } return status; } // Report certificate weaknesses (key length and signing algorithm) int checkCertificate(struct sslCheckOptions *options, const SSL_METHOD *sslMethod) { int status = true; int socketDescriptor = 0; int keyBits; SSL *ssl = NULL; BIO *cipherConnectionBio = NULL; BIO *stdoutBIO = NULL; BIO *fileBIO = NULL; X509 *x509Cert = NULL; EVP_PKEY *publicKey = NULL; char certAlgorithm[80]; X509_EXTENSION *extension = NULL; const X509_ALGOR *palg = NULL; const ASN1_OBJECT *paobj = NULL; // Connect to host socketDescriptor = tcpConnect(options); if (socketDescriptor != 0) { // Setup Context Object... options->ctx = new_CTX(sslMethod); if (options->ctx != NULL) { if (SSL_CTX_set_cipher_list(options->ctx, CIPHERSUITE_LIST_ALL) != 0) { // Load Certs if required... if ((options->clientCertsFile != 0) || (options->privateKeyFile != 0)) status = loadCerts(options); if (status == true) { // Create SSL object... ssl = new_SSL(options->ctx); if (ssl != NULL) { // Connect socket and BIO cipherConnectionBio = BIO_new_socket(socketDescriptor, BIO_NOCLOSE); // Connect SSL and BIO SSL_set_bio(ssl, cipherConnectionBio, cipherConnectionBio); #if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT) // Based on http://does-not-exist.org/mail-archives/mutt-dev/msg13045.html // TLS Virtual-hosting requires that the server present the correct // certificate; to do this, the ServerNameIndication TLS extension is used. // If TLS is negotiated, and OpenSSL is recent enough that it might have // support, and support was enabled when OpenSSL was built, mutt supports // sending the hostname we think we're connecting to, so a server can send // back the correct certificate. // NB: finding a server which uses this for IMAP is problematic, so this is // untested. Please report success or failure! However, this code change // has worked fine in other projects to which the contributor has added it, // or HTTP usage. SSL_set_tlsext_host_name (ssl, options->sniname); #endif // Against some servers, this is required for a successful SSL_connect(), below. SSL_set_options(ssl, SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION); // Connect SSL over socket SSL_connect(ssl); // Setup BIO's if (!xml_to_stdout) { stdoutBIO = BIO_new(BIO_s_file()); BIO_set_fp(stdoutBIO, stdout, BIO_NOCLOSE); } if (options->xmlOutput) { fileBIO = BIO_new(BIO_s_file()); BIO_set_fp(fileBIO, options->xmlOutput, BIO_NOCLOSE); } // Get Certificate... x509Cert = SSL_get_peer_certificate(ssl); if (x509Cert != NULL) { printf("\n %sSSL Certificate:%s\n", COL_BLUE, RESET); printf_xml(" \n"); // Cert Serial No. - Code adapted from OpenSSL's crypto/asn1/t_x509.c if (!(X509_FLAG_COMPAT & X509_FLAG_NO_SERIAL)) { BIO *bp; bp = BIO_new_fp(stdout, BIO_NOCLOSE); if (options->xmlOutput) if(NULL != bp) BIO_free(bp); // We don't free the xml_bp because it will be used in the future } // Signature Algo... if (!(X509_FLAG_COMPAT & X509_FLAG_NO_SIGNAME)) { printf("Signature Algorithm: "); X509_get0_signature(NULL, &palg, x509Cert); X509_ALGOR_get0(&paobj, NULL, NULL, palg); OBJ_obj2txt(certAlgorithm, sizeof(certAlgorithm), paobj, 0); strtok(certAlgorithm, "\n"); if (strstr(certAlgorithm, "md5") || strstr(certAlgorithm, "sha1")) { printf("%s%s%s\n", COL_RED, certAlgorithm, RESET); } else if (strstr(certAlgorithm, "sha512") || strstr(certAlgorithm, "sha256")) { printf("%s%s%s\n", COL_GREEN, certAlgorithm, RESET); } else { printf("%s\n", certAlgorithm); } if (options->xmlOutput) { printf_xml(" %s\n", certAlgorithm); } } // Public Key... if (!(X509_FLAG_COMPAT & X509_FLAG_NO_PUBKEY)) { publicKey = X509_get_pubkey(x509Cert); if (publicKey == NULL) { printf("Public Key: Could not load\n"); printf_xml(" \n"); } else { keyBits=EVP_PKEY_bits(publicKey); switch (EVP_PKEY_id(publicKey)) { case EVP_PKEY_RSA: if (EVP_PKEY_get1_RSA(publicKey)!=NULL) { if (keyBits < 2048 ) { printf("RSA Key Strength: %s%d%s\n", COL_RED, keyBits, RESET); } else if (keyBits >= 3072 ) { printf("RSA Key Strength: %s%d%s\n", COL_GREEN, keyBits, RESET); } else { printf("RSA Key Strength: %d\n", keyBits); } printf_xml(" \n", keyBits); } else { printf(" RSA Public Key: NULL\n"); } printf("\n"); break; case EVP_PKEY_DSA: if (EVP_PKEY_get1_DSA(publicKey)!=NULL) { // TODO - display key strength printf_xml(" \n"); /* DSA_print(stdoutBIO, publicKey->pkey.dsa, 6); */ } else { printf(" DSA Public Key: NULL\n"); } break; case EVP_PKEY_EC: { EC_KEY *ec_key = EVP_PKEY_get1_EC_KEY(publicKey); if (ec_key != NULL) { // We divide by two to get the symmetric key strength equivalent; this // ensures consistency with the Server Key Exchange Group section. int keyBits = EVP_PKEY_bits(publicKey) / 2; const char *ec_group_name = OBJ_nid2sn(EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key))); char *color = ""; if (keyBits < 112) color = COL_RED; else if (keyBits < 128) color = COL_YELLOW; printf("ECC Curve Name: %s\n", ec_group_name); printf("ECC Key Strength: %s%d%s\n\n", color, keyBits, RESET); printf_xml(" \n", ec_group_name, keyBits); EC_KEY_free(ec_key); ec_key = NULL; } else printf(" EC Public Key: NULL\n"); } break; default: printf(" Public Key: Unknown\n"); printf_xml(" \n"); break; } EVP_PKEY_free(publicKey); } } // SSL Certificate Issuer... if (!(X509_FLAG_COMPAT & X509_FLAG_NO_ISSUER)) { int cnindex; X509_NAME *subj; X509_NAME_ENTRY *e; ASN1_STRING *d; const char *subject; const char *issuer; // Get SSL cert CN cnindex = -1; subj = X509_get_subject_name(x509Cert); cnindex = X509_NAME_get_index_by_NID(subj, NID_commonName, cnindex); // SSL cert doesn't have a CN, so just print whole thing if (cnindex == -1) { subject = (char *) X509_NAME_oneline(X509_get_subject_name(x509Cert), NULL, 0); printf("Subject: %s\n", subject); printf_xml(" \n", subject); } else { e = X509_NAME_get_entry(subj, cnindex); d = X509_NAME_ENTRY_get_data(e); subject = (char *) ASN1_STRING_data(d); printf("Subject: %s\n", subject); printf_xml(" \n", subject); } // Get certificate altnames if supported if (!(X509_FLAG_COMPAT & X509_FLAG_NO_EXTENSIONS)) { if (sk_X509_EXTENSION_num(X509_get0_extensions(x509Cert)) > 0) { cnindex = X509_get_ext_by_NID (x509Cert, NID_subject_alt_name, -1); if (cnindex != -1) { extension = X509v3_get_ext(X509_get0_extensions(x509Cert),cnindex); printf("Altnames: "); if (!X509V3_EXT_print(stdoutBIO, extension, X509_FLAG_COMPAT, 0)) { ASN1_STRING_print(stdoutBIO, X509_EXTENSION_get_data(extension)); } if (options->xmlOutput) { printf_xml(" \n"); printf("\n"); } } } // Get SSL cert issuer cnindex = -1; subj = X509_get_issuer_name(x509Cert); cnindex = X509_NAME_get_index_by_NID(subj, NID_commonName, cnindex); // Issuer cert doesn't have a CN, so just print whole thing if (cnindex == -1) { char *issuer = X509_NAME_oneline(X509_get_issuer_name(x509Cert), NULL, 0); char *color = ""; int self_signed = 0; if ((subject != NULL) && (strcmp(subject, issuer) == 0)) { color = COL_RED; self_signed = 1; } printf("%sIssuer: %s%s", color, issuer, RESET); printf_xml(" \n", issuer); if (self_signed) { printf_xml(" true\n"); } else { printf_xml(" false\n"); } } else { e = X509_NAME_get_entry(subj, cnindex); d = X509_NAME_ENTRY_get_data(e); issuer = (char *) ASN1_STRING_data(d); // If issuer is same as hostname we scanned or is *, flag as self-signed if ( strcmp(issuer, options->host) == 0 || strcmp(issuer, subject) == 0 || strcmp(issuer, "*") == 0 ) { printf("Issuer: %s%s%s\n", COL_RED, issuer, RESET); printf_xml(" \n", issuer); printf_xml(" true\n"); } else { printf("Issuer: %s\n", issuer); printf_xml(" \n", issuer); printf_xml(" false\n"); } } } // Check for certificate expiration time_t *ptime; int timediff; ptime = NULL; printf("\nNot valid before: "); timediff = X509_cmp_time(X509_get_notBefore(x509Cert), ptime); // Certificate isn't valid yet if (timediff > 0) { printf("%s", COL_RED); } else { printf("%s", COL_GREEN); } ASN1_TIME_print(stdoutBIO, X509_get_notBefore(x509Cert)); printf("%s", RESET); if (options->xmlOutput) { printf_xml(" "); ASN1_TIME_print(fileBIO, X509_get_notBefore(x509Cert)); printf_xml("\n"); if (timediff > 0) { printf_xml(" true\n"); } else { printf_xml(" false\n"); } } printf("\nNot valid after: "); timediff = X509_cmp_time(X509_get_notAfter(x509Cert), ptime); // Certificate has expired if (timediff < 0) { printf("%s", COL_RED); } else { printf("%s", COL_GREEN); } ASN1_TIME_print(stdoutBIO, X509_get_notAfter(x509Cert)); printf("%s", RESET); if (options->xmlOutput) { printf_xml(" "); ASN1_TIME_print(fileBIO, X509_get_notAfter(x509Cert)); printf_xml("\n"); if (timediff < 0) { printf_xml(" true\n"); } else { printf_xml(" false\n"); } } printf("\n"); // Free X509 Certificate... X509_free(x509Cert); // This is abusing status a bit, but means that we'll only get the cert once status = false; printf_xml(" \n"); } else { printf(" Unable to parse certificate\n"); } // Free BIO BIO_free(stdoutBIO); if (options->xmlOutput) BIO_free(fileBIO); // Disconnect SSL over socket SSL_shutdown(ssl); // Free SSL object FREE_SSL(ssl); } else { status = false; printf_error("Could not create SSL object."); } } } else { status = false; printf_error("Could not set cipher."); } // Free CTX Object FREE_CTX(options->ctx); } // Error Creating Context Object else { status = false; printf_error("Could not create CTX object."); } // Disconnect from host close(socketDescriptor); } // Could not connect else status = false; return status; } // Request a stapled OCSP request from the server. int ocspRequest(struct sslCheckOptions *options) { int cipherStatus = 0; int status = true; int socketDescriptor = 0; SSL *ssl = NULL; BIO *cipherConnectionBio = NULL; BIO *stdoutBIO = NULL; BIO *fileBIO = NULL; const SSL_METHOD *sslMethod = NULL; // Connect to host socketDescriptor = tcpConnect(options); if (socketDescriptor != 0) { // Setup Context Object... if( options->sslVersion == ssl_v2 || options->sslVersion == ssl_v3) { printf_verbose("sslMethod = SSLv23_method()"); sslMethod = SSLv23_method(); } #if OPENSSL_VERSION_NUMBER >= 0x10001000L else if( options->sslVersion == tls_v11) { printf_verbose("sslMethod = TLSv1_1_method()"); sslMethod = TLSv1_1_method(); } else if( options->sslVersion == tls_v12) { printf_verbose("sslMethod = TLSv1_2_method()"); sslMethod = TLSv1_2_method(); } #endif else if( options->sslVersion == tls_v13) { printf_verbose("sslMethod = TLSv1_3_method()"); sslMethod = TLSv1_3_method(); } else { printf_verbose("sslMethod = TLS_method()\n"); sslMethod = TLS_method(); } options->ctx = new_CTX(sslMethod); if (options->ctx != NULL) { if (SSL_CTX_set_cipher_list(options->ctx, CIPHERSUITE_LIST_ALL) != 0) { // Load Certs if required... if ((options->clientCertsFile != 0) || (options->privateKeyFile != 0)) status = loadCerts(options); if (status == true) { // Create SSL object... ssl = new_SSL(options->ctx); if (ssl != NULL) { // Connect socket and BIO cipherConnectionBio = BIO_new_socket(socketDescriptor, BIO_NOCLOSE); // Connect SSL and BIO SSL_set_bio(ssl, cipherConnectionBio, cipherConnectionBio); #if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT) // Based on http://does-not-exist.org/mail-archives/mutt-dev/msg13045.html // TLS Virtual-hosting requires that the server present the correct // certificate; to do this, the ServerNameIndication TLS extension is used. // If TLS is negotiated, and OpenSSL is recent enough that it might have // support, and support was enabled when OpenSSL was built, mutt supports // sending the hostname we think we're connecting to, so a server can send // back the correct certificate. // NB: finding a server which uses this for IMAP is problematic, so this is // untested. Please report success or failure! However, this code change // has worked fine in other projects to which the contributor has added it, // or HTTP usage. SSL_set_tlsext_host_name (ssl, options->sniname); #endif SSL_set_tlsext_status_type(ssl, TLSEXT_STATUSTYPE_ocsp); SSL_CTX_set_tlsext_status_cb(options->ctx, ocsp_resp_cb); // Connect SSL over socket cipherStatus = SSL_connect(ssl); if (cipherStatus == 1) { // Setup BIO's if (!xml_to_stdout) { stdoutBIO = BIO_new(BIO_s_file()); BIO_set_fp(stdoutBIO, stdout, BIO_NOCLOSE); } if (options->xmlOutput) { fileBIO = BIO_new(BIO_s_file()); BIO_set_fp(fileBIO, options->xmlOutput, BIO_NOCLOSE); } // Free BIO BIO_free(stdoutBIO); if (options->xmlOutput) BIO_free(fileBIO); // Disconnect SSL over socket SSL_shutdown(ssl); } else { printf("\n%sFailed to connect to get OCSP status.%s\n", COL_RED, RESET); printf("Most likely cause is server not supporting %s, try manually specifying version\n", printableSslMethod(sslMethod)); } // Free SSL object FREE_SSL(ssl); } else { status = false; printf_error("Could not create SSL object."); } } } else { status = false; printf_error("Could not set cipher."); } // Free CTX Object FREE_CTX(options->ctx); } // Error Creating Context Object else { status = false; printf_error("Could not create CTX object."); } // Disconnect from host close(socketDescriptor); } // Could not connect else status = false; return status; } static int ocsp_resp_cb(SSL *s, void *unused) { const unsigned char *p = NULL; int len = 0; OCSP_RESPONSE *o = NULL; BIO *bp = BIO_new_fp(stdout, BIO_NOCLOSE); int i = 0; long l = 0; OCSP_CERTID *cid = NULL; OCSP_BASICRESP *br = NULL; OCSP_RESPID *rid = NULL; OCSP_RESPDATA *rd = NULL; OCSP_CERTSTATUS *cst = NULL; OCSP_REVOKEDINFO *rev = NULL; OCSP_SINGLERESP *single = NULL; OCSP_RESPBYTES *rb = NULL; len = SSL_get_tlsext_status_ocsp_resp(s, &p); if (p == NULL) { BIO_puts(bp, "No OCSP response received.\n\n"); goto err; } o = d2i_OCSP_RESPONSE(NULL, &p, len); if (o == NULL) { BIO_puts(bp, "OCSP response parse error\n"); BIO_dump_indent(bp, (char *)p, len, 4); goto err; } rb = o->responseBytes; l = ASN1_ENUMERATED_get(o->responseStatus); if (BIO_printf(bp, "OCSP Response Status: %s (0x%lx)\n", OCSP_response_status_str(l), l) <= 0) goto err; if (rb == NULL) return 1; if (BIO_puts(bp, "Response Type: ") <= 0) goto err; if (i2a_ASN1_OBJECT(bp, rb->responseType) <= 0) goto err; if (OBJ_obj2nid(rb->responseType) != NID_id_pkix_OCSP_basic) { BIO_puts(bp, " (unknown response type)\n"); return 1; } if ((br = OCSP_response_get1_basic(o)) == NULL) goto err; rd = &br->tbsResponseData; l = ASN1_INTEGER_get(rd->version); if (BIO_printf(bp, "\nVersion: %lu (0x%lx)\n", l + 1, l) <= 0) goto err; if (BIO_puts(bp, "Responder Id: ") <= 0) goto err; rid = &rd->responderId; switch (rid->type) { case V_OCSP_RESPID_NAME: X509_NAME_print_ex(bp, rid->value.byName, 0, XN_FLAG_ONELINE); break; case V_OCSP_RESPID_KEY: i2a_ASN1_STRING(bp, rid->value.byKey, 0); break; } if (BIO_printf(bp, "\nProduced At: ") <= 0) goto err; if (!ASN1_GENERALIZEDTIME_print(bp, rd->producedAt)) goto err; if (BIO_printf(bp, "\nResponses:\n") <= 0) goto err; for (i = 0; i < sk_OCSP_SINGLERESP_num(rd->responses); i++) { if (!sk_OCSP_SINGLERESP_value(rd->responses, i)) continue; single = sk_OCSP_SINGLERESP_value(rd->responses, i); cid = single->certId; if (ocsp_certid_print(bp, cid, 4) <= 0) goto err; cst = single->certStatus; if (BIO_puts(bp, " Cert Status: ") <= 0) goto err; if (cst->type == V_OCSP_CERTSTATUS_GOOD) { if (BIO_printf(bp, "%s%s%s", COL_GREEN, OCSP_cert_status_str(cst->type), RESET) <= 0) goto err; } else if (cst->type == V_OCSP_CERTSTATUS_REVOKED) { if (BIO_printf(bp, "%s%s%s", COL_RED, OCSP_cert_status_str(cst->type), RESET) <= 0) goto err; rev = cst->value.revoked; if (BIO_printf(bp, "\n Revocation Time: ") <= 0) goto err; if (!ASN1_GENERALIZEDTIME_print(bp, rev->revocationTime)) goto err; if (rev->revocationReason) { l = ASN1_ENUMERATED_get(rev->revocationReason); if (BIO_printf(bp, "\n Revocation Reason: %s (0x%lx)", OCSP_crl_reason_str(l), l) <= 0) goto err; } } else { if (BIO_printf(bp, "%s%s%s", COL_YELLOW, OCSP_cert_status_str(cst->type), RESET) <= 0) goto err; } if (BIO_printf(bp, "\n This Update: ") <= 0) goto err; if (!ASN1_GENERALIZEDTIME_print(bp, single->thisUpdate)) goto err; if (single->nextUpdate) { if (BIO_printf(bp, "\n Next Update: ") <= 0) goto err; if (!ASN1_GENERALIZEDTIME_print(bp, single->nextUpdate)) goto err; } if (BIO_write(bp, "\n", 1) <= 0) goto err; if (!X509V3_extensions_print(bp, "Response Single Extensions", single->singleExtensions, 0, 4)) goto err; if (BIO_write(bp, "\n", 1) <= 0) goto err; } /* if (!X509V3_extensions_print(bp, "Response Extensions", rd->responseExtensions, 0, 4)) goto err; if (X509_signature_print(bp, &br->signatureAlgorithm, br->signature) <= 0) goto err; for (i = 0; i < sk_X509_num(br->certs); i++) { X509_print(bp, sk_X509_value(br->certs, i)); PEM_write_bio_X509(bp, sk_X509_value(br->certs, i)); } */ err: if (o != NULL) { OCSP_RESPONSE_free(o); o = NULL; } BIO_free(bp); return 1; } int ocsp_certid_print(BIO *bp, OCSP_CERTID *a, int indent) { BIO_printf(bp, "%*sCertificate ID:\n", indent, ""); indent += 2; BIO_printf(bp, "%*sHash Algorithm: ", indent, ""); i2a_ASN1_OBJECT(bp, a->hashAlgorithm.algorithm); BIO_printf(bp, "\n%*sIssuer Name Hash: ", indent, ""); i2a_ASN1_STRING(bp, &a->issuerNameHash, 0); BIO_printf(bp, "\n%*sIssuer Key Hash: ", indent, ""); i2a_ASN1_STRING(bp, &a->issuerKeyHash, 0); BIO_printf(bp, "\n%*sSerial Number: ", indent, ""); i2a_ASN1_INTEGER(bp, &a->serialNumber); BIO_printf(bp, "\n"); return 1; } // Print out the full certificate int showCertificate(struct sslCheckOptions *options) { // Variables... int cipherStatus = 0; int status = true; int socketDescriptor = 0; SSL *ssl = NULL; BIO *cipherConnectionBio = NULL; BIO *stdoutBIO = NULL; BIO *fileBIO = NULL; X509 *x509Cert = NULL; EVP_PKEY *publicKey = NULL; const SSL_METHOD *sslMethod = NULL; ASN1_OBJECT *asn1Object = NULL; X509_EXTENSION *extension = NULL; char buffer[1024]; long tempLong = 0; int tempInt = 0; int tempInt2 = 0; long verifyError = 0; // Connect to host socketDescriptor = tcpConnect(options); if (socketDescriptor != 0) { // Setup Context Object... if( options->sslVersion == ssl_v2 || options->sslVersion == ssl_v3) { printf_verbose("sslMethod = SSLv23_method()"); sslMethod = SSLv23_method(); } #if OPENSSL_VERSION_NUMBER >= 0x10001000L else if( options->sslVersion == tls_v11) { printf_verbose("sslMethod = TLSv1_1_method()"); sslMethod = TLSv1_1_method(); } else if( options->sslVersion == tls_v12) { printf_verbose("sslMethod = TLSv1_2_method()"); sslMethod = TLSv1_2_method(); } else if( options->sslVersion == tls_v13) { printf_verbose("sslMethod = TLSv1_3_method()"); sslMethod = TLSv1_3_method(); } #endif else { printf_verbose("sslMethod = TLS_method()\n"); sslMethod = TLS_method(); } options->ctx = new_CTX(sslMethod); if (options->ctx != NULL) { if (SSL_CTX_set_cipher_list(options->ctx, CIPHERSUITE_LIST_ALL) != 0) { // Load Certs if required... if ((options->clientCertsFile != 0) || (options->privateKeyFile != 0)) status = loadCerts(options); if (status == true) { // Create SSL object... ssl = new_SSL(options->ctx); if (ssl != NULL) { // Connect socket and BIO cipherConnectionBio = BIO_new_socket(socketDescriptor, BIO_NOCLOSE); // Connect SSL and BIO SSL_set_bio(ssl, cipherConnectionBio, cipherConnectionBio); #if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT) // Based on http://does-not-exist.org/mail-archives/mutt-dev/msg13045.html // TLS Virtual-hosting requires that the server present the correct // certificate; to do this, the ServerNameIndication TLS extension is used. // If TLS is negotiated, and OpenSSL is recent enough that it might have // support, and support was enabled when OpenSSL was built, mutt supports // sending the hostname we think we're connecting to, so a server can send // back the correct certificate. // NB: finding a server which uses this for IMAP is problematic, so this is // untested. Please report success or failure! However, this code change // has worked fine in other projects to which the contributor has added it, // or HTTP usage. SSL_set_tlsext_host_name (ssl, options->sniname); #endif // Connect SSL over socket cipherStatus = SSL_connect(ssl); if (cipherStatus == 1) { // Setup BIO's if (!xml_to_stdout) { stdoutBIO = BIO_new(BIO_s_file()); BIO_set_fp(stdoutBIO, stdout, BIO_NOCLOSE); } if (options->xmlOutput) { fileBIO = BIO_new(BIO_s_file()); BIO_set_fp(fileBIO, options->xmlOutput, BIO_NOCLOSE); } // Get Certificate... printf("\n %sSSL Certificate:%s\n", COL_BLUE, RESET); printf_xml(" \n"); x509Cert = SSL_get_peer_certificate(ssl); if (x509Cert != NULL) { // Print a base64 blob version of the cert printf(" Certificate blob:\n"); PEM_write_bio_X509(stdoutBIO,x509Cert); if (options->xmlOutput) { printf_xml(" \n"); PEM_write_bio_X509(fileBIO,x509Cert); printf_xml(" \n"); } //SSL_set_verify(ssl, SSL_VERIFY_NONE|SSL_VERIFY_CLIENT_ONCE, NULL); //X509_print_ex(bp, x509Cert, 0, 0); // Cert Version if (!(X509_FLAG_COMPAT & X509_FLAG_NO_VERSION)) { tempLong = X509_get_version(x509Cert); printf(" Version: %lu\n", tempLong); printf_xml(" %lu\n", tempLong); } // Cert Serial No. - Code adapted from OpenSSL's crypto/asn1/t_x509.c if (!(X509_FLAG_COMPAT & X509_FLAG_NO_SERIAL)) { ASN1_INTEGER *bs; BIO *bp; BIO *xml_bp; bp = BIO_new_fp(stdout, BIO_NOCLOSE); if (options->xmlOutput) xml_bp = BIO_new_fp(options->xmlOutput, BIO_NOCLOSE); long l; int i; const char *neg; bs=X509_get_serialNumber(x509Cert); if (BIO_write(bp," Serial Number:",18) <= 0) return(1); if (bs->length <= 4) { l=ASN1_INTEGER_get(bs); if (l < 0) { l= -l; neg="-"; } else neg=""; if (BIO_printf(bp," %s%lu (%s0x%lx)\n",neg,l,neg,l) <= 0) return(1); if (options->xmlOutput) if (BIO_printf(xml_bp," %s%lu (%s0x%lx)\n",neg,l,neg,l) <= 0) return(1); } else { neg=(bs->type == V_ASN1_NEG_INTEGER)?" (Negative)":""; if (BIO_printf(bp,"%1s%s","",neg) <= 0) return(1); if (options->xmlOutput) if (BIO_printf(xml_bp," ") <= 0) return(1); for (i=0; ilength; i++) { if (BIO_printf(bp,"%02x%c",bs->data[i], ((i+1 == bs->length)?'\n':':')) <= 0) return(1); if (options->xmlOutput) { if (i+1 == bs->length) { if (BIO_printf(xml_bp,"%02x",bs->data[i]) <= 0) return(1); } else { if (BIO_printf(xml_bp,"%02x%c",bs->data[i], ':') <= 0) return(1); } } } if (options->xmlOutput) if (BIO_printf(xml_bp,"\n") <= 0) return(1); } if(NULL != bp) BIO_free(bp); // We don't free the xml_bp because it will be used in the future } // Signature Algo... if (!(X509_FLAG_COMPAT & X509_FLAG_NO_SIGNAME)) { X509_signature_print(stdoutBIO, X509_get0_tbs_sigalg(x509Cert), NULL); /* printf(" Signature Algorithm: "); i2a_ASN1_OBJECT(stdoutBIO, X509_get0_tbs_sigalg(x509Cert)); printf("\n"); */ if (options->xmlOutput) { printf_xml(" "); X509_signature_print(fileBIO, X509_get0_tbs_sigalg(x509Cert), NULL); printf_xml("\n"); } } // SSL Certificate Issuer... if (!(X509_FLAG_COMPAT & X509_FLAG_NO_ISSUER)) { X509_NAME_oneline(X509_get_issuer_name(x509Cert), buffer, sizeof(buffer) - 1); printf(" Issuer: %s\n", buffer); printf_xml(" \n", buffer); } // Validity... if (!(X509_FLAG_COMPAT & X509_FLAG_NO_VALIDITY)) { printf(" Not valid before: "); ASN1_TIME_print(stdoutBIO, X509_get_notBefore(x509Cert)); if (options->xmlOutput) { printf_xml(" "); ASN1_TIME_print(fileBIO, X509_get_notBefore(x509Cert)); printf_xml("\n"); } printf("\n Not valid after: "); ASN1_TIME_print(stdoutBIO, X509_get_notAfter(x509Cert)); printf("\n"); if (options->xmlOutput) { printf_xml(" "); ASN1_TIME_print(fileBIO, X509_get_notAfter(x509Cert)); printf_xml("\n"); } } // SSL Certificate Subject... if (!(X509_FLAG_COMPAT & X509_FLAG_NO_SUBJECT)) { X509_NAME_oneline(X509_get_subject_name(x509Cert), buffer, sizeof(buffer) - 1); printf(" Subject: %s\n", buffer); printf_xml(" \n", buffer); } // Public Key Algo... if (!(X509_FLAG_COMPAT & X509_FLAG_NO_PUBKEY)) { printf(" Public Key Algorithm: "); ASN1_OBJECT *xpoid = NULL; i2a_ASN1_OBJECT(stdoutBIO, xpoid); printf("\n"); if (options->xmlOutput) { printf_xml(" "); i2a_ASN1_OBJECT(fileBIO, xpoid); printf_xml("\n"); } // Public Key... publicKey = X509_get_pubkey(x509Cert); if (publicKey == NULL) { printf(" Public Key: Could not load\n"); printf_xml(" \n"); } else { switch (EVP_PKEY_id(publicKey)) { case EVP_PKEY_RSA: if (EVP_PKEY_get1_RSA(publicKey)!=NULL) { printf(" RSA Public Key: (%d bit)\n", EVP_PKEY_bits(publicKey)); printf_xml(" \n", EVP_PKEY_bits(publicKey)); RSA_print(stdoutBIO, EVP_PKEY_get1_RSA(publicKey), 6); if (options->xmlOutput) { RSA_print(fileBIO, EVP_PKEY_get1_RSA(publicKey), 4); printf_xml(" \n"); } } else { printf(" RSA Public Key: NULL\n"); } break; case EVP_PKEY_DSA: if (EVP_PKEY_get1_DSA(publicKey)!=NULL) { printf(" DSA Public Key:\n"); printf_xml(" \n"); DSA_print(stdoutBIO, EVP_PKEY_get1_DSA(publicKey), 6); if (options->xmlOutput) { DSA_print(fileBIO, EVP_PKEY_get1_DSA(publicKey), 4); printf_xml(" \n"); } } else { printf(" DSA Public Key: NULL\n"); } break; case EVP_PKEY_EC: if (EVP_PKEY_get1_EC_KEY(publicKey)!=NULL) { printf(" EC Public Key:\n"); printf_xml(" \n"); EC_KEY_print(stdoutBIO, EVP_PKEY_get1_EC_KEY(publicKey), 6); if (options->xmlOutput) { EC_KEY_print(fileBIO, EVP_PKEY_get1_EC_KEY(publicKey), 4); printf_xml(" \n"); } } else { printf(" EC Public Key: NULL\n"); } break; default: printf(" Public Key: Unknown\n"); printf_xml(" \n"); break; } EVP_PKEY_free(publicKey); } } // X509 v3... if (!(X509_FLAG_COMPAT & X509_FLAG_NO_EXTENSIONS)) { if (sk_X509_EXTENSION_num(X509_get0_extensions(x509Cert)) > 0) { printf(" X509v3 Extensions:\n"); printf_xml(" \n"); for (tempInt = 0; tempInt < sk_X509_EXTENSION_num(X509_get0_extensions(x509Cert)); tempInt++) { // Get Extension... extension = sk_X509_EXTENSION_value(X509_get0_extensions(x509Cert), tempInt); // Print Extension name... printf(" "); asn1Object = X509_EXTENSION_get_object(extension); i2a_ASN1_OBJECT(stdoutBIO, asn1Object); tempInt2 = X509_EXTENSION_get_critical(extension); BIO_printf(stdoutBIO, ": %s\n", tempInt2 ? "critical" : ""); if (options->xmlOutput) { printf_xml(" xmlOutput) { if (!X509V3_EXT_print(fileBIO, extension, X509_FLAG_COMPAT, 0)) ASN1_STRING_print(stdoutBIO, X509_EXTENSION_get_data(extension)); printf_xml("]]>\n"); } printf("\n"); } printf_xml(" \n"); } } // Verify Certificate... printf(" Verify Certificate:\n"); verifyError = SSL_get_verify_result(ssl); if (verifyError == X509_V_OK) { printf(" Certificate passed verification\n"); } else { printf(" %s\n", X509_verify_cert_error_string(verifyError)); } // Free X509 Certificate... X509_free(x509Cert); } else { printf(" Unable to parse certificate\n"); } printf_xml(" \n"); // Free BIO BIO_free(stdoutBIO); if (options->xmlOutput) BIO_free(fileBIO); // Disconnect SSL over socket SSL_shutdown(ssl); } // Free SSL object FREE_SSL(ssl); } else { status = false; printf_error("Could not create SSL object."); } } } else { status = false; printf_error("Could not set cipher."); } // Free CTX Object FREE_CTX(options->ctx); } // Error Creating Context Object else { status = false; printf_error("Could not create CTX object."); } // Disconnect from host close(socketDescriptor); } // Could not connect else status = false; return status; } // Print out the list of trusted CAs int showTrustedCAs(struct sslCheckOptions *options) { // Variables... int cipherStatus = 0; int status = true; int socketDescriptor = 0; SSL *ssl = NULL; BIO *cipherConnectionBio = NULL; BIO *stdoutBIO = NULL; BIO *fileBIO = NULL; const SSL_METHOD *sslMethod = NULL; char buffer[1024]; int tempInt = 0; STACK_OF(X509_NAME) *sk2; X509_NAME *xn; // Connect to host socketDescriptor = tcpConnect(options); if (socketDescriptor != 0) { // Setup Context Object... if( options->sslVersion == ssl_v2 || options->sslVersion == ssl_v3) { printf_verbose("sslMethod = SSLv23_method()"); sslMethod = SSLv23_method(); } #if OPENSSL_VERSION_NUMBER >= 0x10001000L else if( options->sslVersion == tls_v11) { printf_verbose("sslMethod = TLSv1_1_method()"); sslMethod = TLSv1_1_method(); } else if( options->sslVersion == tls_v12) { printf_verbose("sslMethod = TLSv1_2_method()"); sslMethod = TLSv1_2_method(); } else if( options->sslVersion == tls_v13) { printf_verbose("sslMethod = TLSv1_3_method()"); sslMethod = TLSv1_3_method(); } #endif else { printf_verbose("sslMethod = TLS_method()\n"); sslMethod = TLS_method(); } options->ctx = new_CTX(sslMethod); if (options->ctx != NULL) { if (SSL_CTX_set_cipher_list(options->ctx, CIPHERSUITE_LIST_ALL) != 0) { // Load Certs if required... if ((options->clientCertsFile != 0) || (options->privateKeyFile != 0)) status = loadCerts(options); if (status == true) { // Create SSL object... ssl = new_SSL(options->ctx); if (ssl != NULL) { // Connect socket and BIO cipherConnectionBio = BIO_new_socket(socketDescriptor, BIO_NOCLOSE); // Connect SSL and BIO SSL_set_bio(ssl, cipherConnectionBio, cipherConnectionBio); #if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT) // Based on http://does-not-exist.org/mail-archives/mutt-dev/msg13045.html // TLS Virtual-hosting requires that the server present the correct // certificate; to do this, the ServerNameIndication TLS extension is used. // If TLS is negotiated, and OpenSSL is recent enough that it might have // support, and support was enabled when OpenSSL was built, mutt supports // sending the hostname we think we're connecting to, so a server can send // back the correct certificate. // NB: finding a server which uses this for IMAP is problematic, so this is // untested. Please report success or failure! However, this code change // has worked fine in other projects to which the contributor has added it, // or HTTP usage. SSL_set_tlsext_host_name (ssl, options->sniname); #endif // Connect SSL over socket cipherStatus = SSL_connect(ssl); if (cipherStatus >= 0) { // Setup BIO's if (!xml_to_stdout) { stdoutBIO = BIO_new(BIO_s_file()); BIO_set_fp(stdoutBIO, stdout, BIO_NOCLOSE); } if (options->xmlOutput) { fileBIO = BIO_new(BIO_s_file()); BIO_set_fp(fileBIO, options->xmlOutput, BIO_NOCLOSE); } printf("\n %sAcceptable client certificate CA names:%s\n", COL_BLUE, RESET); sk2=SSL_get_client_CA_list(ssl); if ((sk2 != NULL) && (sk_X509_NAME_num(sk2) > 0)) { for (tempInt=0; tempIntxmlOutput) { printf_xml(" \n"); BIO_printf(fileBIO, "%s", buffer); BIO_printf(fileBIO, "\n"); printf_xml(" \n"); } printf("%s", buffer); printf("\n"); } } else { printf("%sNone defined (any)%s\n", COL_YELLOW, RESET); } // Free BIO BIO_free(stdoutBIO); if (options->xmlOutput) BIO_free(fileBIO); // Disconnect SSL over socket SSL_shutdown(ssl); } // Free SSL object FREE_SSL(ssl); } else { status = false; printf_error("Could not create SSL object."); } } } else { status = false; printf_error("Could not set cipher."); } // Free CTX Object FREE_CTX(options->ctx); } // Error Creating Context Object else { status = false; printf_error("Could not create CTX object."); } // Disconnect from host close(socketDescriptor); } // Could not connect else status = false; return status; } int testConnection(struct sslCheckOptions *options) { // Variables... int socketDescriptor = 0; struct addrinfo *ai; struct addrinfo *addrinfoResult = NULL; struct addrinfo hints; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_socktype = SOCK_STREAM; hints.ai_family = AF_UNSPEC; // Resolve Host Name if (options->ipv4 && options->ipv6) { // If both IPv4 and IPv6 are enabled, we restrict nothing in the // results (i.e.: we'll accept either type of address). } else if (options->ipv4) // Only IPv4 is acceptable... { hints.ai_family = AF_INET; } else if (options->ipv6) // Only IPv6 is acceptable... { hints.ai_family = AF_INET6; printf("Trying %sIPv6%s lookup\n\n", COL_GREEN, RESET); } // Perform the actual lookup. if (getaddrinfo(options->host, NULL, &hints, &addrinfoResult) != 0) { printf_error("Could not resolve hostname %s.", options->host); return false; } // Configure Server Address and Port for (ai = addrinfoResult; ai != NULL; ai = ai->ai_next) { if (ai->ai_family == AF_INET6) { options->serverAddress6.sin6_family = ai->ai_family; memcpy((char *) &options->serverAddress6, ai->ai_addr, ai->ai_addrlen); options->serverAddress6.sin6_port = htons(options->port); inet_ntop(ai->ai_family, &options->serverAddress6.sin6_addr, options->addrstr, sizeof(options->addrstr)); } else { options->serverAddress.sin_family = ai->ai_family; memcpy((char *) &options->serverAddress, ai->ai_addr, ai->ai_addrlen); options->serverAddress.sin_port = htons(options->port); inet_ntop(ai->ai_family, &options->serverAddress.sin_addr, options->addrstr, sizeof(options->addrstr)); } options->h_addrtype = ai->ai_family; socketDescriptor = tcpConnect(options); if (socketDescriptor != 0) { close(socketDescriptor); freeaddrinfo(addrinfoResult); addrinfoResult = NULL; printf("%sConnected to %s%s\n\n", COL_GREEN, options->addrstr, RESET); return true; } } freeaddrinfo(addrinfoResult); addrinfoResult = NULL; return false; } int testProtocolCiphers(struct sslCheckOptions *options, const SSL_METHOD *sslMethod) { int status; status = true; if (sslMethod == TLSv1_3_client_method()) strncpy(options->cipherstring, TLSV13_CIPHERSUITES, sizeof(options->cipherstring)); else strncpy(options->cipherstring, CIPHERSUITE_LIST_ALL, sizeof(options->cipherstring)); // Loop until the server won't accept any more ciphers while (status == true) { // Setup Context Object... options->ctx = new_CTX(sslMethod); if (options->ctx != NULL) { // SSL implementation bugs/workaround if (options->sslbugs) SSL_CTX_set_options(options->ctx, SSL_OP_ALL | 0); else SSL_CTX_set_options(options->ctx, 0); // minimal protocol version if (sslMethod == TLSv1_3_client_method()) SSL_CTX_set_min_proto_version(options->ctx, TLS1_3_VERSION); // Load Certs if required... if ((options->clientCertsFile != 0) || (options->privateKeyFile != 0)) status = loadCerts(options); // Test the cipher if (status == true) status = testCipher(options, sslMethod); // Free CTX Object FREE_CTX(options->ctx); } // Error Creating Context Object else { printf_error("Could not create CTX object."); return false; } } /* Test the missing ciphersuites. */ if (sslMethod != TLSv1_3_client_method()) { int tls_version = TLSv1_0; if (sslMethod == TLSv1_1_client_method()) tls_version = TLSv1_1; else if (sslMethod == TLSv1_2_client_method()) tls_version = TLSv1_2; testMissingCiphers(options, tls_version); } return true; } // Test a single host and port for ciphers... int testHost(struct sslCheckOptions *options) { // Variables... struct sslCipher *sslCipherPointer = NULL; int status = true; // XML Output... printf_xml(" \n", options->host, options->sniname, options->port); // Verbose warning about STARTTLS and SSLv3 if (options->sslVersion == ssl_v3 || options->sslVersion == ssl_all) { printf_verbose("Some servers will fail to response to SSLv3 ciphers over STARTTLS\nIf your scan hangs, try using the --tlsall option\n\n"); } printf("Testing SSL server %s%s%s on port %s%d%s using SNI name %s%s%s\n\n", COL_GREEN, options->host, RESET, COL_GREEN, options->port, RESET, COL_GREEN, options->sniname, RESET); printf(" %sSSL/TLS Protocols:%s\n", COL_BLUE, RESET); // Check if SSLv2 is enabled. if ((options->sslVersion == ssl_all) || (options->sslVersion == ssl_v2)) { if (runSSLv2Test(options)) { printf("SSLv2 %senabled%s\n", COL_RED, RESET); printf_xml(" \n"); } else { printf("SSLv2 %sdisabled%s\n", COL_GREEN, RESET); printf_xml(" \n"); } } // Check if SSLv3 is enabled. if ((options->sslVersion == ssl_all) || (options->sslVersion == ssl_v3)) { if (runSSLv3Test(options)) { printf("SSLv3 %senabled%s\n", COL_RED, RESET); printf_xml(" \n"); } else { printf("SSLv3 %sdisabled%s\n", COL_GREEN, RESET); printf_xml(" \n"); } } /* Test if TLSv1.0 through TLSv1.3 is supported. This allows us to skip unnecessary tests later. Print status of each protocol when verbose flag is set. */ if ((options->sslVersion == ssl_all) || (options->sslVersion == tls_all) || (options->sslVersion == tls_v10)) { if ((options->tls10_supported = checkIfTLSVersionIsSupported(options, TLSv1_0))) { printf("TLSv1.0 %senabled%s\n", COL_YELLOW, RESET); printf_xml(" \n"); } else { printf("TLSv1.0 %sdisabled%s\n", COL_GREEN, RESET); printf_xml(" \n"); } } if ((options->sslVersion == ssl_all) || (options->sslVersion == tls_all) || (options->sslVersion == tls_v11)) { if ((options->tls11_supported = checkIfTLSVersionIsSupported(options, TLSv1_1))) { printf("TLSv1.1 %senabled%s\n", COL_YELLOW, RESET); printf_xml(" \n"); } else { printf("TLSv1.1 %sdisabled%s\n", COL_GREEN, RESET); printf_xml(" \n"); } } if ((options->sslVersion == ssl_all) || (options->sslVersion == tls_all) || (options->sslVersion == tls_v12)) { if ((options->tls12_supported = checkIfTLSVersionIsSupported(options, TLSv1_2))) { printf("TLSv1.2 enabled\n"); printf_xml(" \n"); } else { printf("TLSv1.2 disabled\n"); printf_xml(" \n"); } } if ((options->sslVersion == ssl_all) || (options->sslVersion == tls_all) || (options->sslVersion == tls_v13)) { if ((options->tls13_supported = checkIfTLSVersionIsSupported(options, TLSv1_3))) { printf("TLSv1.3 %senabled%s\n", COL_GREEN, RESET); printf_xml(" \n"); } else { printf("TLSv1.3 %sdisabled%s\n", COL_YELLOW, RESET); printf_xml(" \n"); } } printf("\n"); if (options->showClientCiphers == true) { // Build a list of ciphers... switch (options->sslVersion) { case ssl_all: populateCipherList(options, TLSv1_3_client_method()); #if OPENSSL_VERSION_NUMBER >= 0x10001000L populateCipherList(options, TLSv1_2_client_method()); populateCipherList(options, TLSv1_1_client_method()); #endif populateCipherList(options, TLSv1_client_method()); break; case tls_all: populateCipherList(options, TLSv1_3_client_method()); #if OPENSSL_VERSION_NUMBER >= 0x10001000L populateCipherList(options, TLSv1_2_client_method()); populateCipherList(options, TLSv1_1_client_method()); #endif populateCipherList(options, TLSv1_client_method()); break; case tls_v13: populateCipherList(options, TLSv1_3_client_method()); break; #if OPENSSL_VERSION_NUMBER >= 0x10001000L case tls_v12: populateCipherList(options, TLSv1_2_client_method()); break; case tls_v11: populateCipherList(options, TLSv1_1_client_method()); break; #endif case tls_v10: populateCipherList(options, TLSv1_client_method()); break; } printf("\n %sOpenSSL-Supported Client Cipher(s):%s\n", COL_BLUE, RESET); sslCipherPointer = options->ciphers; while ((sslCipherPointer != 0) && (status == true)) { printf(" %s\n",sslCipherPointer->name); printf_xml(" \n", sslCipherPointer->name); sslCipherPointer = sslCipherPointer->next; } printf("\n %sDirectly-Supported Client Cipher(s):%s\n", COL_BLUE, RESET); for (int i = 0; i < (sizeof(missing_ciphersuites) / sizeof(struct missing_ciphersuite)); i++) { printf(" %s\n", missing_ciphersuites[i].protocol_name); printf_xml(" \n", missing_ciphersuites[i].protocol_name); } printf("\n"); } if (status == true && options->fallback ) { printf(" %sTLS Fallback SCSV:%s\n", COL_BLUE, RESET); #ifdef SSL_MODE_SEND_FALLBACK_SCSV testFallback(options, NULL); #else printf("%sOpenSSL version does not support SCSV fallback%s\n\n", COL_RED, RESET); #endif } if (status == true && options->reneg ) { printf(" %sTLS renegotiation:%s\n", COL_BLUE, RESET); testRenegotiation(options, TLSv1_client_method()); } if (status == true && options->compression ) { printf(" %sTLS Compression:%s\n", COL_BLUE, RESET); testCompression(options, TLSv1_client_method()); } if (status == true && options->heartbleed ) { printf(" %sHeartbleed:%s\n", COL_BLUE, RESET); #if OPENSSL_VERSION_NUMBER >= 0x10001000L if ((options->sslVersion == ssl_all || options->sslVersion == tls_all || options->sslVersion == tls_v13) && options->tls13_supported) { printf("TLSv1.3 "); status = testHeartbleed(options, TLSv1_3_client_method()); } if ((options->sslVersion == ssl_all || options->sslVersion == tls_all || options->sslVersion == tls_v12) && options->tls12_supported) { printf("TLSv1.2 "); status = testHeartbleed(options, TLSv1_2_client_method()); } if ((options->sslVersion == ssl_all || options->sslVersion == tls_all || options->sslVersion == tls_v11) && options->tls11_supported) { printf("TLSv1.1 "); status = testHeartbleed(options, TLSv1_1_client_method()); } #endif if ((options->sslVersion == ssl_all || options->sslVersion == tls_all || options->sslVersion == tls_v10) && options->tls10_supported) { printf("TLSv1.0 "); status = testHeartbleed(options, TLSv1_client_method()); } if( options->sslVersion == ssl_v2 || options->sslVersion == ssl_v3) { printf("%sAll TLS protocols disabled, cannot check for heartbleed.\n%s", COL_RED, RESET); } printf("\n"); } // Print OCSP response if (status == true && options->ocspStatus == true) { printf(" %sOCSP Stapling Request:%s\n", COL_BLUE, RESET); #if OPENSSL_VERSION_NUMBER > 0x00908000L && !defined(OPENSSL_NO_TLSEXT) status = ocspRequest(options); #endif } if (options->ciphersuites) { // Test supported ciphers... printf(" %sSupported Server Cipher(s):%s\n", COL_BLUE, RESET); switch (options->sslVersion) { case ssl_all: case tls_all: if ((status != false) && options->tls13_supported) status = testProtocolCiphers(options, TLSv1_3_client_method()); if ((status != false) && options->tls12_supported) status = testProtocolCiphers(options, TLSv1_2_client_method()); if ((status != false) && options->tls11_supported) status = testProtocolCiphers(options, TLSv1_1_client_method()); if ((status != false) && options->tls10_supported) status = testProtocolCiphers(options, TLSv1_client_method()); break; case tls_v10: if ((status != false) && options->tls10_supported) status = testProtocolCiphers(options, TLSv1_client_method()); break; case tls_v11: if ((status != false) && options->tls11_supported) status = testProtocolCiphers(options, TLSv1_1_client_method()); break; case tls_v12: if ((status != false) && options->tls12_supported) status = testProtocolCiphers(options, TLSv1_2_client_method()); break; case tls_v13: if ((status != false) && options->tls13_supported) status = testProtocolCiphers(options, TLSv1_3_client_method()); break; } } // Enumerate key exchange groups. if (options->groups) testSupportedGroups(options); // Enumerate signature algorithms. if (options->signature_algorithms) testSignatureAlgorithms(options); // Certificate checks if (status == true && (options->showCertificate == true || options->checkCertificate == true)) { printf_xml(" \n"); // Full certificate details (--show-certificates) if (status == true && options->showCertificate == true) { status = showCertificate(options); } // Default certificate details if (status == true && options->checkCertificate == true) { if (status != false) status = checkCertificateProtocol(options, TLSv1_3_client_method()); if (status != false) status = checkCertificateProtocol(options, TLSv1_2_client_method()); if (status != false) status = checkCertificateProtocol(options, TLSv1_1_client_method()); if (status != false) status = checkCertificateProtocol(options, TLSv1_client_method()); if (status != false) printf("Certificate information cannot be retrieved.\n\n"); } printf_xml(" \n"); } // Print client auth trusted CAs if (options->showTrustedCAs == true) { status = showTrustedCAs(options); } // XML Output... printf_xml(" \n"); // Return status... return status; } int main(int argc, char *argv[]) { // Variables... struct sslCheckOptions sslOptions; struct sslCipher *sslCipherPointer; int argLoop; int tempInt; int maxSize; int xmlArg; int mode = mode_help; int msec; FILE *targetsFile; char line[1024]; #ifdef _WIN32 WORD wVersionRequested; WSADATA wsaData; int err; HANDLE hConsole; DWORD consoleMode; unsigned int enable_colors; #endif // Init... memset(&sslOptions, 0, sizeof(struct sslCheckOptions)); sslOptions.port = 0; xmlArg = 0; strncpy(sslOptions.host, "127.0.0.1", 10); sslOptions.showCertificate = false; sslOptions.showTrustedCAs = false; sslOptions.checkCertificate = true; sslOptions.showClientCiphers = false; sslOptions.showCipherIds = false; sslOptions.showTimes = false; sslOptions.ciphersuites = true; sslOptions.reneg = true; sslOptions.fallback = true; sslOptions.compression = true; sslOptions.heartbleed = true; sslOptions.groups = true; sslOptions.signature_algorithms = false; sslOptions.starttls_ftp = false; sslOptions.starttls_imap = false; sslOptions.starttls_irc = false; sslOptions.starttls_ldap = false; sslOptions.starttls_pop3 = false; sslOptions.starttls_smtp = false; sslOptions.starttls_mysql = false; sslOptions.starttls_xmpp = false; sslOptions.starttls_psql = false; sslOptions.xmpp_server = false; sslOptions.verbose = false; sslOptions.cipher_details = true; sslOptions.ipv4 = true; sslOptions.ipv6 = true; sslOptions.ocspStatus = false; // Default socket timeout 3s sslOptions.timeout.tv_sec = 3; sslOptions.timeout.tv_usec = 0; // Default connect timeout 75s sslOptions.connect_timeout = 75; sslOptions.sleep = 0; sslOptions.sslVersion = ssl_all; struct sslCheckOptions *options = &sslOptions; #ifdef _WIN32 /* Attempt to enable console colors. This succeeds in Windows 10. For other * OSes, color is disabled. */ enable_colors = 1; hConsole = GetStdHandle(STD_OUTPUT_HANDLE); /* Cygwin's terminal is re-directed, so GetConsoleMode() fails on it. So we'll try to get a direct handle in that case. */ if (!GetConsoleMode(hConsole, &consoleMode)) { hConsole = CreateFile("CONIN$", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); /* Also, Cygwin appears to do full buffering of output, so the program seems to hang until its fully complete, then the output gets dumped all at once. To be more responsive, we'll force line buffering at 80 bytes (the default terminal width). */ setvbuf(stdout, NULL, _IOLBF, 80); /* If we still can't get console information, then disable colors. */ if (!GetConsoleMode(hConsole, &consoleMode)) enable_colors = 0; } /* Some terminals already have colors enabled, and somehow don't like being set. */ if (enable_colors && ((consoleMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) == 0)) { if (!SetConsoleMode(hConsole, consoleMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)) enable_colors = 0; } if (!enable_colors) { RESET = ""; COL_RED = ""; COL_YELLOW = ""; COL_BLUE = ""; COL_GREEN = ""; COL_PURPLE = ""; COL_GREY = ""; COL_RED_BG = ""; } /* Initialize networking library. */ wVersionRequested = MAKEWORD(2, 2); err = WSAStartup(wVersionRequested, &wsaData); if (err != 0) { printf_error("WSAStartup failed: %d", err); return -1; } #endif SSL_library_init(); // Get program parameters for (argLoop = 1; argLoop < argc; argLoop++) { // Help if ((strcmp("--help", argv[argLoop]) == 0) || (strcmp("-h", argv[argLoop]) == 0)) mode = mode_help; // targets else if ((strncmp("--targets=", argv[argLoop], 10) == 0) && (strlen(argv[argLoop]) > 10)) { mode = mode_multiple; options->targets = argLoop; } // Show certificate else if (strcmp("--show-certificate", argv[argLoop]) == 0) options->showCertificate = true; // Don't check certificate strength else if (strcmp("--no-check-certificate", argv[argLoop]) == 0) options->checkCertificate = false; // Show supported client ciphers else if (strcmp("--show-ciphers", argv[argLoop]) == 0) options->showClientCiphers = true; // Show ciphers ids else if (strcmp("--show-cipher-ids", argv[argLoop]) == 0) { options->showCipherIds = true; } // Show handshake times else if (strcmp("--show-times", argv[argLoop]) == 0) { options->showTimes = true; } // Show client auth trusted CAs else if (strcmp("--show-client-cas", argv[argLoop]) == 0) options->showTrustedCAs = true; // Version else if (strcmp("--version", argv[argLoop]) == 0) mode = mode_version; // XML Output else if (strncmp("--xml=", argv[argLoop], 6) == 0) xmlArg = argLoop; // Verbose else if (strcmp("--verbose", argv[argLoop]) == 0) options->verbose = true; #if OPENSSL_VERSION_NUMBER >= 0x10002000L // Cipher details (curve names and EDH key lengths) else if (strcmp("--no-cipher-details", argv[argLoop]) == 0) options->cipher_details = false; #endif // Disable coloured output else if ((strcmp("--no-colour", argv[argLoop]) == 0) || (strcmp("--no-color", argv[argLoop]) == 0)) { RESET = ""; COL_RED = ""; COL_YELLOW = ""; COL_BLUE = ""; COL_GREEN = ""; COL_PURPLE = ""; COL_RED_BG = ""; COL_GREY = ""; } // Client Certificates else if (strncmp("--certs=", argv[argLoop], 8) == 0) options->clientCertsFile = argv[argLoop] +8; // Private Key File else if (strncmp("--pk=", argv[argLoop], 5) == 0) options->privateKeyFile = argv[argLoop] +5; // Private Key Password else if (strncmp("--pkpass=", argv[argLoop], 9) == 0) options->privateKeyPassword = argv[argLoop] +9; // Should we check for supported cipher suites else if (strcmp("--no-ciphersuites", argv[argLoop]) == 0) options->ciphersuites = false; // Should we check for TLS Falback SCSV? else if (strcmp("--no-fallback", argv[argLoop]) == 0) options->fallback = false; // Should we check for TLS renegotiation? else if (strcmp("--no-renegotiation", argv[argLoop]) == 0) options->reneg = false; // Should we check for TLS Compression else if (strcmp("--no-compression", argv[argLoop]) == 0) options->compression = false; // Should we check for Heartbleed (CVE-2014-0160) else if (strcmp("--no-heartbleed", argv[argLoop]) == 0) options->heartbleed = false; // Should we check for key exchange groups? else if (strcmp("--no-groups", argv[argLoop]) == 0) options->groups = false; // Should we check for signature algorithms? else if (strcmp("--show-sigs", argv[argLoop]) == 0) options->signature_algorithms = true; // Show IANA/RFC cipher names in output else if (strcmp("--iana-names", argv[argLoop]) == 0) options->ianaNames = true; // StartTLS... FTP else if (strcmp("--starttls-ftp", argv[argLoop]) == 0) options->starttls_ftp = true; // StartTLS... IMAP else if (strcmp("--starttls-imap", argv[argLoop]) == 0) options->starttls_imap = true; else if (strcmp("--starttls-irc", argv[argLoop]) == 0) options->starttls_irc = true; // StartTLS... LDAP else if (strcmp("--starttls-ldap", argv[argLoop]) == 0) options->starttls_ldap = true; // StartTLS... POP3 else if (strcmp("--starttls-pop3", argv[argLoop]) == 0) options->starttls_pop3 = true; // StartTLS... SMTP else if (strcmp("--starttls-smtp", argv[argLoop]) == 0) options->starttls_smtp = true; // StartTLS... MYSQL else if (strcmp("--starttls-mysql", argv[argLoop]) == 0) options->starttls_mysql = true; // StartTLS... XMPP else if (strcmp("--starttls-xmpp", argv[argLoop]) == 0) options->starttls_xmpp = true; // StartTLS... PostgreSQL else if (strcmp("--starttls-psql", argv[argLoop]) == 0) options->starttls_psql = true; // SSL v2 only... else if (strcmp("--ssl2", argv[argLoop]) == 0) options->sslVersion = ssl_v2; // SSL v3 only... else if (strcmp("--ssl3", argv[argLoop]) == 0) options->sslVersion = ssl_v3; // TLS v1 only... else if (strcmp("--tls10", argv[argLoop]) == 0) options->sslVersion = tls_v10; #if OPENSSL_VERSION_NUMBER >= 0x10001000L // TLS v11 only... else if (strcmp("--tls11", argv[argLoop]) == 0) options->sslVersion = tls_v11; // TLS v12 only... else if (strcmp("--tls12", argv[argLoop]) == 0) options->sslVersion = tls_v12; // TLS v13 only... else if (strcmp("--tls13", argv[argLoop]) == 0) options->sslVersion = tls_v13; #endif // TLS (all versions)... else if (strcmp("--tlsall", argv[argLoop]) == 0) options->sslVersion = tls_all; // Use a server-to-server XMPP handshake else if (strcmp("--xmpp-server", argv[argLoop]) == 0) options->xmpp_server = true; // SSL Bugs... else if (strcmp("--bugs", argv[argLoop]) == 0) options->sslbugs = 1; // Socket Timeout (both send and receive) else if (strncmp("--timeout=", argv[argLoop], 10) == 0) options->timeout.tv_sec = atoi(argv[argLoop] + 10); // Connect Timeout else if (strncmp("--connect-timeout=", argv[argLoop], 18) == 0) options->connect_timeout = atoi(argv[argLoop] + 18); // Sleep between requests (ms) else if (strncmp("--sleep=", argv[argLoop], 8) == 0) { msec = atoi(argv[argLoop] + 8); if (msec >= 0) { options->sleep = msec; } } // RDP Preamble... else if (strcmp("--rdp", argv[argLoop]) == 0) options->rdp = 1; // IPv4 only else if ((strcmp("--ipv4", argv[argLoop]) == 0) || (strcmp("-4", argv[argLoop]) == 0)) options->ipv6 = false; // IPv6 only else if ((strcmp("--ipv6", argv[argLoop]) == 0) || (strcmp("-6", argv[argLoop]) == 0)) options->ipv4 = false; // Check OCSP response else if (strcmp("--ocsp", argv[argLoop]) == 0) options->ocspStatus = true; // SNI name else if (strncmp("--sni-name=", argv[argLoop], 11) == 0) { strncpy(options->sniname, argv[argLoop]+11, strlen(argv[argLoop])-11); options->sni_set = 1; } // Host (maybe port too)... else if (argLoop + 1 == argc) { mode = mode_single; // Get host... // IPv6 [] address parsing by DinoTools/phibos tempInt = 0; char *hostString = argv[argLoop]; maxSize = strlen(hostString); if (strncmp((char*)hostString, "https://", 8) == 0) { // Strip https:// from the start of the hostname memmove(hostString, hostString + 8, (maxSize - 8)); memset(hostString + (maxSize - 8), 0, 8); maxSize = strlen(hostString); } int squareBrackets = false; if (hostString[0] == '[') { squareBrackets = true; // skip the square bracket hostString++; } while ((hostString[tempInt] != 0) && ((squareBrackets == true && hostString[tempInt] != ']') || (squareBrackets == false && hostString[tempInt] != ':' && hostString[tempInt] != '/'))) { tempInt++; } if (squareBrackets == true && hostString[tempInt] == ']') { hostString[tempInt] = 0; if (tempInt < maxSize && (hostString[tempInt + 1] == ':' || hostString[tempInt + 1] == '/')) { tempInt++; hostString[tempInt] = 0; } } else { hostString[tempInt] = 0; } strncpy(options->host, hostString, sizeof(options->host) -1); // No SNI name passed on command line if (!options->sni_set) { strncpy(options->sniname, options->host, sizeof(options->host) -1); } // Get port (if it exists)... tempInt++; if (tempInt < maxSize) { errno = 0; options->port = strtol((hostString + tempInt), NULL, 10); if (options->port < 1 || options->port > 65535) { printf_error("Invalid target specified."); exit(1); } } else if (options->port == 0) { if (options->starttls_ftp) options->port = 21; else if (options->starttls_imap) options->port = 143; else if (options->starttls_irc) options->port = 6667; else if (options->starttls_ldap) options->port = 389; else if (options->starttls_pop3) options->port = 110; else if (options->starttls_smtp) options->port = 25; else if (options->starttls_mysql) options->port = 3306; else if (options->starttls_xmpp) options->port = 5222; else if (options->starttls_psql) options->port = 5432; else if (options->rdp) options->port = 3389; else options->port = 443; } } // Not too sure what the user is doing... else mode = mode_help; } // Open XML file output... if ((xmlArg > 0) && (mode != mode_help)) { if (strcmp(argv[xmlArg] + 6, "-") == 0) { options->xmlOutput = stdout; xml_to_stdout = 1; } else { options->xmlOutput = fopen(argv[xmlArg] + 6, "w"); if (options->xmlOutput == NULL) { printf_error("Could not open XML output file %s.", argv[xmlArg] + 6); exit(0); } } // Output file header... fprintf(options->xmlOutput, "\n\n", VERSION); } // Build the list of ciphers missing from OpenSSL. findMissingCiphers(); switch (mode) { case mode_version: printf("%s\t\t%s\n\t\t%s\n%s", COL_BLUE, VERSION, SSLeay_version(SSLEAY_VERSION), RESET); #if OPENSSL_VERSION_NUMBER < 0x10001000L printf("\t\t%sOpenSSL version does not support TLSv1.1%s\n", COL_RED, RESET); printf("\t\t%sTLSv1.1 ciphers will not be detected%s\n", COL_RED, RESET); printf("\t\t%sOpenSSL version does not support TLSv1.2%s\n", COL_RED, RESET); printf("\t\t%sTLSv1.2 ciphers will not be detected%s\n", COL_RED, RESET); #endif break; case mode_help: // Program version banner... printf("%s%s%s\n", COL_BLUE, program_banner, RESET); printf("%s\t\t%s\n\t\t%s\n%s\n\n", COL_BLUE, VERSION, SSLeay_version(SSLEAY_VERSION), RESET); printf("%sCommand:%s\n", COL_BLUE, RESET); printf(" %s%s [options] [host:port | host]%s\n\n", COL_GREEN, argv[0], RESET); printf("%sOptions:%s\n", COL_BLUE, RESET); printf(" %s--targets=%s A file containing a list of hosts to check.\n", COL_GREEN, RESET); printf(" Hosts can be supplied with ports (host:port)\n"); printf(" %s--sni-name=%s Hostname for SNI\n", COL_GREEN, RESET); printf(" %s--ipv4, -4%s Only use IPv4\n", COL_GREEN, RESET); printf(" %s--ipv6, -6%s Only use IPv6\n", COL_GREEN, RESET); printf("\n"); printf(" %s--show-certificate%s Show full certificate information\n", COL_GREEN, RESET); printf(" %s--show-client-cas%s Show trusted CAs for TLS client auth\n", COL_GREEN, RESET); printf(" %s--no-check-certificate%s Don't warn about weak certificate algorithm or keys\n", COL_GREEN, RESET); printf(" %s--ocsp%s Request OCSP response from server\n", COL_GREEN, RESET); printf(" %s--pk=%s A file containing the private key or a PKCS#12 file\n", COL_GREEN, RESET); printf(" containing a private key/certificate pair\n"); printf(" %s--pkpass=%s The password for the private key or PKCS#12 file\n", COL_GREEN, RESET); printf(" %s--certs=%s A file containing PEM/ASN1 formatted client certificates\n", COL_GREEN, RESET); printf("\n"); printf(" %s--ssl2%s Only check if SSLv2 is enabled\n", COL_GREEN, RESET); printf(" %s--ssl3%s Only check if SSLv3 is enabled\n", COL_GREEN, RESET); printf(" %s--tls10%s Only check TLSv1.0 ciphers\n", COL_GREEN, RESET); #if OPENSSL_VERSION_NUMBER >= 0x10001000L printf(" %s--tls11%s Only check TLSv1.1 ciphers\n", COL_GREEN, RESET); printf(" %s--tls12%s Only check TLSv1.2 ciphers\n", COL_GREEN, RESET); printf(" %s--tls13%s Only check TLSv1.3 ciphers\n", COL_GREEN, RESET); #endif printf(" %s--tlsall%s Only check TLS ciphers (all versions)\n", COL_GREEN, RESET); printf(" %s--show-ciphers%s Show supported client ciphers\n", COL_GREEN, RESET); printf(" %s--show-cipher-ids%s Show cipher ids\n", COL_GREEN, RESET); printf(" %s--iana-names%s Use IANA/RFC cipher names rather than OpenSSL ones\n", COL_GREEN, RESET); printf(" %s--show-times%s Show handhake times in milliseconds\n", COL_GREEN, RESET); printf("\n"); #if OPENSSL_VERSION_NUMBER >= 0x10002000L printf(" %s--no-cipher-details%s Disable EC curve names and EDH/RSA key lengths output\n", COL_GREEN, RESET); #endif printf(" %s--no-ciphersuites%s Do not check for supported ciphersuites\n", COL_GREEN, RESET); printf(" %s--no-compression%s Do not check for TLS compression (CRIME)\n", COL_GREEN, RESET); #ifdef SSL_MODE_SEND_FALLBACK_SCSV printf(" %s--no-fallback%s Do not check for TLS Fallback SCSV\n", COL_GREEN, RESET); #endif printf(" %s--no-groups%s Do not enumerate key exchange groups\n", COL_GREEN, RESET); printf(" %s--no-heartbleed%s Do not check for OpenSSL Heartbleed (CVE-2014-0160)\n", COL_GREEN, RESET); printf(" %s--no-renegotiation%s Do not check for TLS renegotiation\n", COL_GREEN, RESET); printf(" %s--show-sigs%s Enumerate signature algorithms\n", COL_GREEN, RESET); printf("\n"); printf(" %s--starttls-ftp%s STARTTLS setup for FTP\n", COL_GREEN, RESET); printf(" %s--starttls-imap%s STARTTLS setup for IMAP\n", COL_GREEN, RESET); printf(" %s--starttls-irc%s STARTTLS setup for IRC\n", COL_GREEN, RESET); printf(" %s--starttls-ldap%s STARTTLS setup for LDAP\n", COL_GREEN, RESET); printf(" %s--starttls-mysql%s STARTTLS setup for MYSQL\n", COL_GREEN, RESET); printf(" %s--starttls-pop3%s STARTTLS setup for POP3\n", COL_GREEN, RESET); printf(" %s--starttls-psql%s STARTTLS setup for PostgreSQL\n", COL_GREEN, RESET); printf(" %s--starttls-smtp%s STARTTLS setup for SMTP\n", COL_GREEN, RESET); printf(" %s--starttls-xmpp%s STARTTLS setup for XMPP\n", COL_GREEN, RESET); printf(" %s--xmpp-server%s Use a server-to-server XMPP handshake\n", COL_GREEN, RESET); printf(" %s--rdp%s Send RDP preamble before starting scan\n", COL_GREEN, RESET); printf("\n"); printf(" %s--bugs%s Enable SSL implementation bug work-arounds\n", COL_GREEN, RESET); printf(" %s--no-colour%s Disable coloured output\n", COL_GREEN, RESET); printf(" %s--sleep=%s Pause between connection request. Default is disabled\n", COL_GREEN, RESET); printf(" %s--timeout=%s Set socket timeout. Default is 3s\n", COL_GREEN, RESET); printf(" %s--connect-timeout=%s Set connect timeout. Default is 75s\n", COL_GREEN, RESET); printf(" %s--verbose%s Display verbose output\n", COL_GREEN, RESET); printf(" %s--version%s Display the program version\n", COL_GREEN, RESET); printf(" %s--xml=%s Output results to an XML file. Use - for STDOUT.\n", COL_GREEN, RESET); printf(" %s--help%s Display the help text you are now reading\n\n", COL_GREEN, RESET); printf("%sExample:%s\n", COL_BLUE, RESET); printf(" %s%s 127.0.0.1%s\n", COL_GREEN, argv[0], RESET); printf(" %s%s [::1]%s\n\n", COL_GREEN, argv[0], RESET); break; // Check a single host/port ciphers... case mode_single: case mode_multiple: printf("Version: %s%s%s\n%s\n%s\n", COL_GREEN, VERSION, RESET, SSLeay_version(SSLEAY_VERSION), RESET); #if OPENSSL_VERSION_NUMBER < 0x10001000L printf("\t\t%sOpenSSL version does not support TLSv1.1%s\n", COL_RED, RESET); printf("\t\t%sTLSv1.1 ciphers will not be detected%s\n", COL_RED, RESET); printf("\t\t%sOpenSSL version does not support TLSv1.2%s\n", COL_RED, RESET); printf("\t\t%sTLSv1.2 ciphers will not be detected%s\n", COL_RED, RESET); #endif //SSLeay_add_all_algorithms(); ERR_load_crypto_strings(); // Do the testing... if (mode == mode_single) { if (testConnection(options)) { testHost(options); } } else { if (fileExists(argv[options->targets] + 10) == true) { // Open targets file... targetsFile = fopen(argv[options->targets] + 10, "r"); if (targetsFile == NULL) { printf_error("Could not open targets file %s.", argv[options->targets] + 10); } else { readLine(targetsFile, line, sizeof(line)); while (feof(targetsFile) == 0) { if (strlen(line) != 0) { // Strip https:// from the start of the hostname if (strncmp(line, "https://", 8) == 0) { memmove(line, line + 8, (strlen(line) - 8)); memset(line + (strlen(line) - 8), 0, 8); } // Get host... tempInt = 0; while ((line[tempInt] != 0) && (line[tempInt] != ':')) tempInt++; line[tempInt] = 0; strncpy(options->host, line, sizeof(options->host) -1); if (!options->sni_set) { strncpy(options->sniname, options->host, sizeof(options->host) -1); } // Get port (if it exists)... tempInt++; if (strlen(line + tempInt) > 0) { int port; port = atoi(line + tempInt); // Invalid port if (port == 0) { printf_error("Invalid port specified."); exit(1); } else { options->port = port; } } // Otherwise assume 443 else { options->port = 443; } // Test the host... if (testConnection(options)) { testHost(options); } printf("\n\n"); } readLine(targetsFile, line, sizeof(line)); } } } else printf_error("Targets file %s does not exist.", argv[options->targets] + 10); } // Free Structures while (options->ciphers != 0) { sslCipherPointer = options->ciphers->next; free(options->ciphers); options->ciphers = sslCipherPointer; } break; } // Close XML file, if required... if ((xmlArg > 0) && (mode != mode_help)) { fprintf(options->xmlOutput, "\n"); fclose(options->xmlOutput); } return 0; } int runSSLv2Test(struct sslCheckOptions *options) { int ret = false, s = -1; char sslv2_client_hello[] = { 0x80, 0x34, /* Length: 52 */ 0x01, /* Handshake Message Type: Client Hello */ 0x00, 0x02, /* Version: SSL 2.0 */ 0x00, 0x1b, /* Cipher Spec Length: 27 */ 0x00, 0x00, /* Session ID Length: 0 */ 0x00, 0x10, /* Challenge Length: 16 */ 0x05, 0x00, 0x80, /* SSL2_IDEA_128_CBC_WITH_MD5 */ 0x03, 0x00, 0x80, /* SSL2_RC2_128_CBC_WITH_MD5 */ 0x01, 0x00, 0x80, /* SSL2_RC4_128_WITH_MD5 */ 0x07, 0x00, 0xc0, /* SSL2_DES_192_EDE3_CBC_WITH_MD5 */ 0x08, 0x00, 0x80, /* SSL2_RC4_64_WITH_MD5 */ 0x06, 0x00, 0x40, /* SSL2_DES_64_CBC_WITH_MD5 */ 0x04, 0x00, 0x80, /* SSL2_RC2_128_CBC_EXPORT40_WITH_MD5 */ 0x02, 0x00, 0x80, /* SSL2_RC4_128_EXPORT40_WITH_MD5 */ 0x00, 0x00, 0x00, /* TLS_NULL_WITH_NULL_NULL */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f /* Challenge */ }; char response[8] = {0}; /* Create a socket to the target. */ s = tcpConnect(options); /* If a connection could not be made, return false. */ if (s == 0) return false; /* Send the SSLv2 Client Hello packet. */ if (send(s, sslv2_client_hello, sizeof(sslv2_client_hello), 0) <= 0) { printf_error("send() failed: %s", strerror(errno)); exit(1); } /* Read a small amount of the response. */ if (recv(s, response, sizeof(response), 0) != sizeof(response)) goto done; /* Returns false. */ /* If the Handshake Message Type is Server Hello (0x04) and the Version is SSL 2.0 * (0x00, 0x02), we confirm that this is SSL v2. */ if ((response[2] == 0x04) && (response[5] == 0x00) && (response[6] == 0x02)) ret = true; done: close(s); return ret; } int runSSLv3Test(struct sslCheckOptions *options) { int ret = false, s = -1; uint32_t timestamp = 0; unsigned char timestamp_bytes[4] = {0}; char sslv3_client_hello_1[] = { 0x16, /* Content Type: Handshake (22) */ 0x03, 0x00, /* Version SSL 3.0 */ 0x00, 0xe8, /* Length: 232 */ 0x01, /* Handshake Type: Client Hello */ 0x00, 0x00, 0xe4, /* Length: 228 */ 0x03, 0x00, /* Version: SSL 3.0 */ }; char sslv3_client_hello_2[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, /* Random bytes */ 0x00, /* Session ID Length */ 0x00, 0xbc, /* Cipher Suites Length: 188 */ 0xc0, 0x14, /* TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA */ 0xc0, 0x0a, /* TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA */ 0x00, 0x39, /* TLS_DHE_RSA_WITH_AES_256_CBC_SHA */ 0x00, 0x38, /* TLS_DHE_DSS_WITH_AES_256_CBC_SHA */ 0x00, 0x37, /* TLS_DH_RSA_WITH_AES_256_CBC_SHA */ 0x00, 0x36, /* TLS_DH_DSS_WITH_AES_256_CBC_SHA */ 0x00, 0x88, /* TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA */ 0x00, 0x87, /* TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA */ 0x00, 0x86, /* TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA */ 0x00, 0x85, /* TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA */ 0xc0, 0x19, /* TLS_ECDH_anon_WITH_AES_256_CBC_SHA */ 0x00, 0x3a, /* TLS_DH_anon_WITH_AES_256_CBC_SHA */ 0x00, 0x89, /* TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA */ 0xc0, 0x0f, /* TLS_ECDH_RSA_WITH_AES_256_CBC_SHA */ 0xc0, 0x05, /* TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA */ 0x00, 0x35, /* TLS_RSA_WITH_AES_256_CBC_SHA */ 0x00, 0x84, /* TLS_RSA_WITH_CAMELLIA_256_CBC_SHA */ 0x00, 0x95, /* TLS_RSA_PSK_WITH_AES_256_CBC_SHA */ 0xc0, 0x13, /* TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA */ 0xc0, 0x09, /* TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA */ 0x00, 0x33, /* TLS_DHE_RSA_WITH_AES_128_CBC_SHA */ 0x00, 0x32, /* TLS_DHE_DSS_WITH_AES_128_CBC_SHA */ 0x00, 0x31, /* TLS_DH_RSA_WITH_AES_128_CBC_SHA */ 0x00, 0x30, /* TLS_DH_DSS_WITH_AES_128_CBC_SHA */ 0x00, 0x9a, /* TLS_DHE_RSA_WITH_SEED_CBC_SHA */ 0x00, 0x99, /* TLS_DHE_DSS_WITH_SEED_CBC_SHA */ 0x00, 0x98, /* TLS_DH_RSA_WITH_SEED_CBC_SHA */ 0x00, 0x97, /* TLS_DH_DSS_WITH_SEED_CBC_SHA */ 0x00, 0x45, /* TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA */ 0x00, 0x44, /* TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA */ 0x00, 0x43, /* TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA */ 0x00, 0x42, /* TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA */ 0xc0, 0x18, /* TLS_ECDH_anon_WITH_AES_128_CBC_SHA */ 0x00, 0x34, /* TLS_DH_anon_WITH_AES_128_CBC_SHA */ 0x00, 0x9b, /* TLS_DH_anon_WITH_SEED_CBC_SHA */ 0x00, 0x46, /* TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA */ 0xc0, 0x0e, /* TLS_ECDH_RSA_WITH_AES_128_CBC_SHA */ 0xc0, 0x04, /* TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA */ 0x00, 0x2f, /* TLS_RSA_WITH_AES_128_CBC_SHA */ 0x00, 0x96, /* TLS_RSA_WITH_SEED_CBC_SHA */ 0x00, 0x41, /* TLS_RSA_WITH_CAMELLIA_128_CBC_SHA */ 0x00, 0x07, /* TLS_RSA_WITH_IDEA_CBC_SHA */ 0x00, 0x94, /* TLS_RSA_PSK_WITH_AES_128_CBC_SHA */ 0xc0, 0x11, /* TLS_ECDHE_RSA_WITH_RC4_128_SHA */ 0xc0, 0x07, /* TLS_ECDHE_ECDSA_WITH_RC4_128_SHA */ 0x00, 0x66, /* TLS_DHE_DSS_WITH_RC4_128_SHA */ 0xc0, 0x16, /* TLS_ECDH_anon_WITH_RC4_128_SHA */ 0x00, 0x18, /* TLS_DH_anon_WITH_RC4_128_MD5 */ 0xc0, 0x0c, /* TLS_ECDH_RSA_WITH_RC4_128_SHA */ 0xc0, 0x02, /* TLS_ECDH_ECDSA_WITH_RC4_128_SHA */ 0x00, 0x05, /* TLS_RSA_WITH_RC4_128_SHA */ 0x00, 0x04, /* TLS_RSA_WITH_RC4_128_MD5 */ 0x00, 0x92, /* TLS_RSA_PSK_WITH_RC4_128_SHA */ 0xc0, 0x12, /* TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA */ 0xc0, 0x08, /* TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA */ 0x00, 0x16, /* TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA */ 0x00, 0x13, /* TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA */ 0x00, 0x10, /* TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA */ 0x00, 0x0d, /* TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA */ 0xc0, 0x17, /* TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA */ 0x00, 0x1b, /* TLS_DH_anon_WITH_3DES_EDE_CBC_SHA */ 0xc0, 0x0d, /* TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA */ 0xc0, 0x03, /* TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA */ 0x00, 0x0a, /* TLS_RSA_WITH_3DES_EDE_CBC_SHA */ 0x00, 0x93, /* TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA */ 0x00, 0x63, /* TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA */ 0x00, 0x15, /* TLS_DHE_RSA_WITH_DES_CBC_SHA */ 0x00, 0x12, /* TLS_DHE_DSS_WITH_DES_CBC_SHA */ 0x00, 0x0f, /* TLS_DH_RSA_WITH_DES_CBC_SHA */ 0x00, 0x0c, /* TLS_DH_DSS_WITH_DES_CBC_SHA */ 0x00, 0x1a, /* TLS_DH_anon_WITH_DES_CBC_SHA */ 0x00, 0x62, /* TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA */ 0x00, 0x09, /* TLS_RSA_WITH_DES_CBC_SHA */ 0x00, 0x61, /* TLS_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5 */ 0x00, 0x65, /* TLS_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA */ 0x00, 0x64, /* TLS_RSA_EXPORT1024_WITH_RC4_56_SHA */ 0x00, 0x60, /* TLS_RSA_EXPORT1024_WITH_RC4_56_MD5 */ 0x00, 0x14, /* TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA */ 0x00, 0x11, /* TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA */ 0x00, 0x0e, /* TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA */ 0x00, 0x0b, /* TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA */ 0x00, 0x19, /* TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA */ 0x00, 0x08, /* TLS_RSA_EXPORT_WITH_DES40_CBC_SHA */ 0x00, 0x06, /* TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 */ 0x00, 0x17, /* TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 */ 0x00, 0x03, /* TLS_RSA_EXPORT_WITH_RC4_40_MD5 */ 0xc0, 0x10, /* TLS_ECDHE_RSA_WITH_NULL_SHA */ 0xc0, 0x06, /* TLS_ECDHE_ECDSA_WITH_NULL_SHA */ 0xc0, 0x15, /* TLS_ECDH_anon_WITH_NULL_SHA */ 0xc0, 0x0b, /* TLS_ECDH_RSA_WITH_NULL_SHA */ 0xc0, 0x01, /* TLS_ECDH_ECDSA_WITH_NULL_SHA */ 0x00, 0x02, /* TLS_RSA_WITH_NULL_SHA */ 0x00, 0x01, /* TLS_RSA_WITH_NULL_MD5 */ 0x00, 0xff, /* TLS_EMPTY_RENEGOTIATION_INFO_SCSV */ 0x02, /* Compression Methods Length: 2 */ 0x01, 0x00, /* DEFLATE, none */ }; char response[16] = {0}; /* Create a socket to the target. */ s = tcpConnect(options); /* If a connection could not be made, return false. */ if (s == 0) return false; /* Send the SSLv3 Client Hello packet. */ if (send(s, sslv3_client_hello_1, sizeof(sslv3_client_hello_1), 0) <= 0) { printf_error("send() failed: %s", strerror(errno)); exit(1); } timestamp = htonl(time(NULL)); /* Current time stamp. */ timestamp_bytes[0] = timestamp & 0xff; timestamp_bytes[1] = (timestamp >> 8) & 0xff; timestamp_bytes[2] = (timestamp >> 16) & 0xff; timestamp_bytes[3] = (timestamp >> 24) & 0xff; if (send(s, timestamp_bytes, sizeof(timestamp_bytes), 0) <= 0) { printf_error("send() failed: %s", strerror(errno)); exit(1); } if (send(s, sslv3_client_hello_2, sizeof(sslv3_client_hello_2), 0) <= 0) { printf_error("send() failed: %s", strerror(errno)); exit(1); } /* Read a small amount of the response. */ if (recv(s, response, sizeof(response), 0) != sizeof(response)) goto done; /* Returns false. */ /* Examine response. */ if ((response[0] == 0x16) && /* Content Type is Handshake (22) */ (response[1] == 0x03) && (response[2] == 0x00) && /* Version is SSL 3.0 */ (response[5] == 0x02) && /* Handshake Type is Server Hello (2) */ (response[9] == 0x03) && (response[10] == 0x00)) /* Version is SSL 3.0 (again) */ ret = true; done: close(s); return ret; } /* Compares the list of supported ciphersuites by OpenSSL with the complete list of ciphersuites from IANA. Marks the matches so they are not re-tested again later. */ void findMissingCiphers() { STACK_OF(SSL_CIPHER) *cipherList = NULL; const SSL_CIPHER *cipher = NULL; unsigned int tls_version = 0; uint32_t id = 0; const SSL_METHOD *sslMethods[] = { TLSv1_client_method(), TLSv1_1_client_method(), TLSv1_2_client_method() }; unsigned int tls_versions[] = { V1_0, V1_1, V1_2 }; /* For each TLS version (not including v1.3)... */ for (int m = 0; m < (sizeof(sslMethods) / sizeof(const SSL_METHOD *)); m++) { tls_version = tls_versions[m]; SSL_CTX *ctx = new_CTX(sslMethods[m]); SSL_CTX_set_cipher_list(ctx, CIPHERSUITE_LIST_ALL); cipherList = SSL_CTX_get_ciphers(ctx); /* Loop through all OpenSSL ciphers... */ for (int i = 0; i < sk_SSL_CIPHER_num(cipherList); i++) { cipher = sk_SSL_CIPHER_value(cipherList, i); id = SSL_CIPHER_get_protocol_id(cipher); /* Using the cipher ID, find the match in the IANA list. */ for (int j = 0; j < (sizeof(missing_ciphersuites) / sizeof(struct missing_ciphersuite)); j++) { if ((missing_ciphersuites[j].id == id) && (missing_ciphersuites[j].check_tls_versions & tls_version)) { /* Turn off the flag for this version of TLS. */ missing_ciphersuites[j].check_tls_versions &= ~tls_version; } } } FREE_CTX(ctx); } } /* Creates a new byte string of size BS_DEFAULT_NEW_SIZE. Caller must eventually free it with bs_free(). The caller MUST initialize the pointer to NULL, otherwise the heap will be corrupted. */ void bs_new(bs **b) { bs_new_size(b, BS_DEFAULT_NEW_SIZE); } /* Creates a new byte string with the specified initial size (or BS_DEFAULT_NEW_SIZE if 0). Caller must eventually free it with bs_free(). The caller MUST initialize the pointer to NULL, otherwise the heap will be corrupted. */ void bs_new_size(bs **b, size_t new_size) { if (b == NULL) { fprintf(stderr, "Error: bs_new*() given NULL pointer!\n"); exit(-1); } /* If this byte string was already initialized, silently free it, then continue on. */ if (*b != NULL) bs_free(b); if (new_size == 0) new_size = BS_DEFAULT_NEW_SIZE; *b = calloc(1, sizeof(bs)); if (*b == NULL) { fprintf(stderr, "bs_new_size(): failed to allocate new buffer.\n"); exit(-1); } (*b)->buf = calloc(new_size, sizeof(unsigned char)); if ((*b)->buf == NULL) { fprintf(stderr, "bs_new_size(): failed to allocate new buffer.\n"); exit(-1); } (*b)->size = new_size; (*b)->len = 0; } /* De-allocates a byte string. May be safely called multiple times. Furthermore, bs_free(NULL) does nothing. */ void bs_free(bs **b) { if ((b == NULL) || (*b == NULL)) return; free((*b)->buf); (*b)->buf = NULL; (*b)->size = 0; (*b)->len = 0; free(*b); *b = NULL; } /* Appends an array of bytes to this byte string. The byte string is automatically re-sized if necessary. */ #define OVERFLOW_MESSAGE "Cannot lengthen buffer without overflowing length!\n" void bs_append_bytes(bs *b, unsigned char *bytes, size_t bytes_len) { size_t new_len = 0, b_len = 0, b_size = 0; if ((b == NULL) || (bytes == NULL) || (bytes_len == 0)) return; b_len = b->len; b_size = b->size; new_len = b_len + bytes_len; /* Ensure that the new length does not cause an integer overflow. */ if ((new_len < b_len) || (new_len < bytes_len)) { fprintf(stderr, OVERFLOW_MESSAGE); exit(-1); } /* If the buffer needs re-sizing... */ if (new_len > b_size) { /* Double the size of the buffer until it is larger than what we need right now. */ while (new_len > b_size) { /* Ensure we don't overflow the length. */ if ((b_len * 2) < b_len) { fprintf(stderr, OVERFLOW_MESSAGE); exit(-1); } b_size = b_size * 2; } /* Extend the buffer's size. */ b->buf = realloc(b->buf, b_size); if (b->buf == NULL) { fprintf(stderr, "Failed to resize buffer.\n"); exit(-1); } b->size = b_size; /* Zero out the extended buffer region; leave the existing bytes intact. */ memset(b->buf + b_len, 0, b_size - b_len); } /* Copy the new bytes into the buffer right after the existing bytes. */ memcpy(b->buf + b_len, bytes, bytes_len); /* Update the number of used bytes in the buffer. */ b->len = new_len; } /* Appends a uint32_t to the byte string. */ void bs_append_uint32_t(bs *b, uint32_t u) { bs_append_bytes(b, (unsigned char *)&u, sizeof(uint32_t)); } /* Converts an unsigned short to network-order, then appends it to the byte string. */ void bs_append_ushort(bs *b, unsigned short us) { uint16_t u16 = htons(us); bs_append_bytes(b, (unsigned char *)&u16, sizeof(uint16_t)); } /* Appends one byte string (src) to another (dst). */ void bs_append_bs(bs *dst, bs *src) { if (src == NULL) return; bs_append_bytes(dst, src->buf, src->len); } /* Returns the number of bytes in this byte string. */ size_t bs_get_len(bs *b) { if (b == NULL) return 0; return b->len; } /* Returns the number of bytes allocated in the underlying byte string. */ size_t bs_get_size(bs *b) { if (b == NULL) return 0; return b->size; } /* Gets the bytes of this byte string. The caller must _never_ free it directly themselves. */ unsigned char *bs_get_bytes(bs *b) { if (b == NULL) return NULL; return b->buf; } /* Gets a single byte from the offset position. Performs safety checks that the read will not overflow. Returns 0 if out of bounds. */ unsigned char bs_get_byte(bs *b, size_t offset) { if ((b == NULL) || (offset >= b->len)) return 0; return b->buf[offset]; } /* Gets a single byte from the offset position. Performs safety checks that the read will not overflow. */ void bs_set_byte(bs *b, size_t offset, unsigned char byte) { if ((b == NULL) || (offset >= b->len)) return; b->buf[offset] = byte; } /* Sets a length field in a TLS packet at the specified offset. */ void bs_set_ushort(bs *b, size_t offset, unsigned short length) { uint16_t u = htons(length); bs_set_byte(b, offset, (unsigned char)u); bs_set_byte(b, offset + 1, (unsigned char)(u >> 8)); } /* Reads the specified number of bytes from socket s into byte string b. Returns 0 on success, or errno on error. */ int bs_read_socket(bs *b, int s, size_t num_bytes) { int ret = -1, n = 0; unsigned int i = 0; size_t old_len = 0, bytes_read = 0; if (b == NULL) return -1; /* Append num_bytes to the byte string to ensure that the underlying buffer is resized appropriately. Then reset the length. */ old_len = b->len; for (; i < (num_bytes / sizeof(uint32_t)) + 1; i++) bs_append_uint32_t(b, 0); b->len = old_len; /* Read in num_bytes from the socket and store it in the underlying buffer. */ bytes_read = 0; while (bytes_read < num_bytes) { n = recv(s, b->buf + b->len + bytes_read, num_bytes - bytes_read, 0); if (n <= 0) { if ((errno != 0) && (errno != ECONNRESET)) ret = errno; b->len += bytes_read; goto err; } bytes_read += n; } b->len += bytes_read; ret = 0; err: return ret; } /* Internal function. Use bs_append_x25519_pubkey() and bs_append_x448_pubkey() instead. */ void __bs_append_xstar_pubkey(bs *b, unsigned int gen_x25519) { unsigned char public_key[64] = {0}; /* X25519 requires 32 bytes minimum, and X448 requires 56 bytes minimum. */ size_t public_key_len = sizeof(public_key); EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *pctx = NULL; /* Create an X25519 or X448 key depending on which is requested. */ if (gen_x25519) pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_X25519, NULL); else pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_X448, NULL); /* Create the private and public keys, and append the raw public key to the byte string. */ EVP_PKEY_keygen_init(pctx); EVP_PKEY_keygen(pctx, &pkey); EVP_PKEY_get_raw_public_key(pkey, public_key, &public_key_len); bs_append_bytes(b, public_key, public_key_len); EVP_PKEY_free(pkey); pkey = NULL; EVP_PKEY_CTX_free(pctx); pctx = NULL; } /* Generates a random x25519 public key and appends it to the byte string. */ void bs_append_x25519_pubkey(bs *b) { __bs_append_xstar_pubkey(b, 1); } /* Generates a random x448 public key and appends it to the byte string. */ void bs_append_x448_pubkey(bs *b) { __bs_append_xstar_pubkey(b, 0); } /* Returns true if the ServerHello response contains TLSv1.3 in its supported_versions extension. */ unsigned int checkSupportedVersionsExtensionForTLS13(bs *server_hello) { unsigned int handshake_record_len = bs_get_byte(server_hello, 3) << 8 | bs_get_byte(server_hello, 4); /* The Server Hello *record* passed into this function can have multiple handshake protocols inside. We need to find the Server Hello *handshake protocol*, specifically, since that contains the extensions we need to parse. */ unsigned int handshake_record_ptr = 5; while (handshake_record_ptr < handshake_record_len) { unsigned int handshake_protocol_type = bs_get_byte(server_hello, handshake_record_ptr); unsigned int handshake_protocol_len = bs_get_byte(server_hello, handshake_record_ptr + 1) << 16 | bs_get_byte(server_hello, handshake_record_ptr + 2) << 8 | bs_get_byte(server_hello, handshake_record_ptr + 3); /* We found the Server Hello handshake protocol entry... */ if (handshake_protocol_type == 2) { /* The session ID field is variable, so we need to find its length first so we can skip over it and get to the extensions section. */ unsigned int session_id_len = (unsigned int)bs_get_byte(server_hello, handshake_record_ptr + 5 + 32 + 1); /* Get the length of all the extensions. */ unsigned int extensions_len_offset = handshake_record_ptr + 5 + 32 + 1 + session_id_len + 4; unsigned int extensions_len = bs_get_byte(server_hello, extensions_len_offset) << 8 | bs_get_byte(server_hello, extensions_len_offset + 1); /* Loop through each extension. */ unsigned int extensions_base_offset = extensions_len_offset + 2; unsigned int extensions_offset = 0; while (extensions_offset < extensions_len) { /* Get the extension type and length. */ unsigned int extension_type = bs_get_byte(server_hello, extensions_base_offset + extensions_offset) << 8 | bs_get_byte(server_hello, extensions_base_offset + extensions_offset + 1); unsigned int extension_len = bs_get_byte(server_hello, extensions_base_offset + extensions_offset + 2) << 8 | bs_get_byte(server_hello, extensions_base_offset + extensions_offset + 3); /* The supported_version extension is type 43. */ if (extension_type == 43) { /* The length of this extension should be divisible by 2, since the TLS versions are each 2 bytes. */ if ((extension_len % 2) != 0) { fprintf(stderr, "Error in %s: extension length for supported_versions is not even!: %u\n", __func__, extension_len); return 0; } /* Loop through all the TLS versions in the supported_versions extension. Each version uses two bytes. */ for (int i = 0; i < extension_len; i += 2) { unsigned int tls_high_byte = (unsigned int)bs_get_byte(server_hello, extensions_base_offset + extensions_offset + 4 + i); unsigned int tls_low_byte = (unsigned int)bs_get_byte(server_hello, extensions_base_offset + extensions_offset + 5 + i); /* If we find TLS version 0x0304 in the supported_versions extension, then the server supports TLSv1.3! */ if ((tls_high_byte == 3) && (tls_low_byte == 4)) return 1; } } extensions_offset += (4 + extension_len); } /* We already found the Server Hello protocol handshake and looked through all the extensions. If we reached here, then there's no point in continuing. */ return 0; } handshake_record_ptr += (4 + handshake_protocol_len); } return 0; } /* Returns true if a specific TLS version is supported by the server. */ unsigned int checkIfTLSVersionIsSupported(struct sslCheckOptions *options, unsigned int tls_version) { bs *tls_extensions = NULL, *ciphersuite_list = NULL, *client_hello = NULL, *server_hello = NULL; int ret = false, s = -1; tls_extensions = makeTLSExtensions(options, 1); if (tls_version == TLSv1_3) { /* Extension: supported_groups */ bs_append_bytes(tls_extensions, (unsigned char []) { 0x00, 0x0a, // Extension: supported_groups (10) 0x00, 0x16, // Extension Length (22) 0x00, 0x14, // Supported Groups List Length (20) 0x00, 0x17, // secp256r1 0x00, 0x19, // secp521r1 0x00, 0x18, // secp384r1 0x00, 0x1d, // X25519 0x00, 0x1e, // X448 0x01, 0x00, // FFDHE2048 0x01, 0x01, // FFDHE3072 0x01, 0x02, // FFDHE4096 0x01, 0x03, // FFDHE6144 0x01, 0x04, // FFDHE8192 }, 26); /* Add key share for X25519. */ tlsExtensionAddDefaultKeyShare(tls_extensions); /* Explicitly mark that this is a TLSv1.3 Client Hello. */ tlsExtensionAddTLSv1_3(tls_extensions); /* Update the length of the extensions. */ tlsExtensionUpdateLength(tls_extensions); } else { /* Extension: supported_groups */ bs_append_bytes(tls_extensions, (unsigned char []) { 0x00, 0x0a, // Extension: supported_groups (10) 0x00, 0x1c, // Extension Length (28) 0x00, 0x1a, // Supported Groups List Length (26) 0x00, 0x17, // secp256r1 0x00, 0x19, // secp521r1 0x00, 0x1c, // brainpoolP512r1 0x00, 0x1b, // brainpoolP384r1 0x00, 0x18, // secp384r1 0x00, 0x1a, // brainpoolP256r1 0x00, 0x16, // secp256k1 0x00, 0x0e, // sect571r1 0x00, 0x0d, // sect571k1 0x00, 0x0b, // sect409k1 0x00, 0x0c, // sect409r1 0x00, 0x09, // sect283k1 0x00, 0x0a, // sect283r1 }, 32); /* Update the length of the extensions. */ tlsExtensionUpdateLength(tls_extensions); } ciphersuite_list = makeCiphersuiteListAll(tls_version); client_hello = makeClientHello(options, tls_version, ciphersuite_list, tls_extensions); bs_free(&ciphersuite_list); bs_free(&tls_extensions); /* Now connect to the target server. */ s = tcpConnect(options); if (s == 0) goto done; /* Send the Client Hello message. */ if (send(s, bs_get_bytes(client_hello), bs_get_len(client_hello), 0) <= 0) { printf_error("send() failed while sending Client Hello: %d (%s)", errno, strerror(errno)); goto done; /* Returns false. */ } bs_free(&client_hello); server_hello = getServerHello(s); /* If we don't receive a proper Server Hello message, then this TLS version is not supported. */ if (server_hello == NULL) goto done; unsigned int expected_tls_version_low = tls_version + 1; if (tls_version == TLSv1_3) expected_tls_version_low = 3; /* Get the server's TLS version and compare it with what we sent. */ unsigned int server_tls_version_high = bs_get_byte(server_hello, 9); unsigned int server_tls_version_low = bs_get_byte(server_hello, 10); if ((server_tls_version_high != 3) || (server_tls_version_low != expected_tls_version_low)) goto done; /* TLSv1.3's ServerHello will be tagged as TLSv1.2 in the header, but will include v1.3 in the supported_versions extension. Some servers (like Windows Server 2019), when only supporting v1.2, will still respond with a ServerHello to our v1.3 Client Hello. So to eliminate false positives, we need to check the supported_versions extension and ensure v1.3 is listed there. */ if ((tls_version == TLSv1_3) && (!checkSupportedVersionsExtensionForTLS13(server_hello))) goto done; /* A valid Server Hello was returned, so this TLS version is supported. */ ret = true; done: CLOSE(s); bs_free(&ciphersuite_list); bs_free(&tls_extensions); bs_free(&client_hello); bs_free(&server_hello); return ret; } /* Given a TLSv1_? constant, return its printable string representation. */ char *getPrintableTLSName(unsigned int tls_version) { switch (tls_version) { case TLSv1_0: return "TLSv1.0"; case TLSv1_1: return "TLSv1.1"; case TLSv1_2: return "TLSv1.2"; case TLSv1_3: return "TLSv1.3"; default: return "Unknown"; } } /* Returns a byte string of all TLSv1.3 cipher suites. The caller must eventually call bs_free() on it. */ bs *makeCiphersuiteListTLS13All() { bs *ciphersuite_list = NULL; bs_new_size(&ciphersuite_list, 16); bs_append_bytes(ciphersuite_list, (unsigned char []) { 0x13, 0x01, // TLS_AES_128_GCM_SHA256 0x13, 0x02, // TLS_AES_256_GCM_SHA384 0x13, 0x03, // TLS_CHACHA20_POLY1305_SHA256 0x13, 0x04, // TLS_AES_128_CCM_SHA256 0x13, 0x05, // TLS_AES_128_CCM_8_SHA256 }, 10); return ciphersuite_list; } /* Returns a byte string with a list of all ciphersuites registered by IANA. */ bs *makeCiphersuiteListAll(unsigned int tls_version) { bs *ciphersuite_list = NULL; /* If its TLSv1.3, return the smaller v1.3-specific list. */ if (tls_version == TLSv1_3) return makeCiphersuiteListTLS13All(); bs_new_size(&ciphersuite_list, 1024); for (int i = 0; i < (sizeof(missing_ciphersuites) / sizeof(struct missing_ciphersuite)); i++) { if (!strstr(missing_ciphersuites[i].protocol_name, "PRIVATE_CIPHER_")) bs_append_ushort(ciphersuite_list, missing_ciphersuites[i].id); } /* Append TLS_EMPTY_RENEGOTIATION_INFO_SCSV (0x00ff), otherwise some servers will reject the connection outright. */ bs_append_ushort(ciphersuite_list, 255); return ciphersuite_list; } /* Returns a byte string with a list of all missing ciphersuites for a given TLS version (TLSv1_? constant) .*/ bs *makeCiphersuiteListMissing(unsigned int tls_version) { bs *ciphersuite_list = NULL; bs_new_size(&ciphersuite_list, 1024); if (tls_version == TLSv1_0) tls_version = V1_0; else if (tls_version == TLSv1_1) tls_version = V1_1; else if (tls_version == TLSv1_2) tls_version = V1_2; for (int i = 0; i < (sizeof(missing_ciphersuites) / sizeof(struct missing_ciphersuite)); i++) { /* Append only those that OpenSSL does not cover, and those that were not already accepted through a previous run. */ if ((missing_ciphersuites[i].check_tls_versions & tls_version) && ((missing_ciphersuites[i].accepted_tls_versions & tls_version) == 0)) { bs_append_ushort(ciphersuite_list, missing_ciphersuites[i].id); } } return ciphersuite_list; } /* Marks a ciphersuite as found so that it is not re-tested again. */ void markFoundCiphersuite(unsigned short server_cipher_id, unsigned int tls_version) { if (tls_version == TLSv1_0) tls_version = V1_0; else if (tls_version == TLSv1_1) tls_version = V1_1; else if (tls_version == TLSv1_2) tls_version = V1_2; for (int i = 0; i < (sizeof(missing_ciphersuites) / sizeof(struct missing_ciphersuite)); i++) { if (missing_ciphersuites[i].id == server_cipher_id) { missing_ciphersuites[i].accepted_tls_versions |= tls_version; break; } } } /* Resolves an IANA cipher ID to its IANA name. Sets the cipher_bits argument to the cipher strength (or to -1 if unknown). Returns "UNKNOWN_CIPHER if cipher ID is not found. */ char *resolveCipherID(unsigned short cipher_id, int *cipher_bits) { for (int i = 0; i < (sizeof(missing_ciphersuites) / sizeof(struct missing_ciphersuite)); i++) { if (missing_ciphersuites[i].id == cipher_id) { *cipher_bits = missing_ciphersuites[i].bits; return missing_ciphersuites[i].protocol_name; } } *cipher_bits = -1; return "UNKNOWN_CIPHER"; } /* Creates a basic set of TLS extensions, including SNI, ec_point_formats, Session Ticket TLS, and signature_algorithms. */ bs *makeTLSExtensions(struct sslCheckOptions *options, unsigned int include_signature_algorithms) { bs *tls_extensions = NULL; bs_new_size(&tls_extensions, 64); /* Add the length of the extensions (to be filled in later). */ bs_append_ushort(tls_extensions, 0); /* Extension: server name */ uint16_t sni_length = strlen(options->sniname); uint16_t sni_list_length = sni_length + 3; uint16_t extension_length = sni_list_length + 2; bs_append_ushort(tls_extensions, 0x0000); /* Extension: server_name */ bs_append_ushort(tls_extensions, extension_length); bs_append_ushort(tls_extensions, sni_list_length); bs_append_bytes(tls_extensions, (unsigned char []) { 0x00 /* Server Name Type: host_name */ }, 1); bs_append_ushort(tls_extensions, sni_length); /* The length of the hostname. */ bs_append_bytes(tls_extensions, (unsigned char *)options->sniname, sni_length); /* The hostname itself. */ /* Extension: ec_point_formats */ bs_append_bytes(tls_extensions, (unsigned char []) { 0x00, 0x0b, // Extension: ec_point_formats (11) 0x00, 0x04, // Extension Length (4) 0x03, // EC Point Formats Length (3) 0x00, // Uncompressed 0x01, // ansiX962_compressed_prime 0x02, // ansiX962_compressed_char2 }, 8); /* Extension: SessionTicket TLS */ bs_append_bytes(tls_extensions, (unsigned char []) { 0x00, 0x23, // Extension: SessionTicket TLS (35) 0x00, 0x00, // Extension Length (0) }, 4); if (include_signature_algorithms) { /* Extension: signature_algorithms */ bs_append_bytes(tls_extensions, (unsigned char []) { 0x00, 0x0d, // Extension: signature_algorithms (13) 0x00, 0x30, // Extension Length (48) 0x00, 0x2e, // Signature Hash Algorithms Length (46) 0x08, 0x04, // rsa_pss_rsae_sha256 0x08, 0x05, // rsa_pss_rsae_sha384 0x08, 0x06, // rsa_pss_rsae_sha512 0x08, 0x07, // ed25519 0x08, 0x08, // ed448 0x08, 0x09, // rsa_pss_pss_sha256 0x08, 0x0a, // rsa_pss_pss_sha384 0x08, 0x0b, // rsa_pss_pss_sha512 0x06, 0x01, // rsa_pkcs1_sha512 0x06, 0x02, // SHA512 DSA 0x06, 0x03, // ecdsa_secp521r1_sha512 0x05, 0x01, // rsa_pkcs1_sha384 0x05, 0x02, // SHA384 DSA 0x05, 0x03, // ecdsa_secp384r1_sha384 0x04, 0x01, // rsa_pkcs1_sha256" 0x04, 0x02, // SHA256 DSA 0x04, 0x03, // ecdsa_secp256r1_sha256 0x03, 0x01, // SHA224 ECDSA 0x03, 0x02, // SHA224 DSA 0x03, 0x03, // SHA224 ECDSA 0x02, 0x01, // rsa_pkcs1_sha1 0x02, 0x02, // SHA1 DSA 0x02, 0x03, // ecdsa_sha1 }, 52); } /* Set the extension length. */ tlsExtensionUpdateLength(tls_extensions); return tls_extensions; } /* Adds the TLS supported_versions extension, set to TLSv1.3 only. */ void tlsExtensionAddTLSv1_3(bs *tls_extensions) { bs_append_bytes(tls_extensions, (unsigned char []) { 0x00, 0x2b, // supported_versions (43) 0x00, 0x03, // Length 0x02, // Supported Versions Length 0x03, 0x04, // Supported Version: TLS v1.3 }, 7); tlsExtensionUpdateLength(tls_extensions); } /* Adds default key_share extension. */ void tlsExtensionAddDefaultKeyShare(bs *tls_extensions) { bs_append_bytes(tls_extensions, (unsigned char []) { 0x00, 0x33, // key_share (51) 0x00, 0x26, // Length (38) 0x00, 0x24, // Key Share List Length (36) 0x00, 0x1d, // Group ID (X25519) 0x00, 0x20, // Key Exchange Length (32) }, 10); /* Append a random X25519 public key. */ bs_append_x25519_pubkey(tls_extensions); /* Update the length of the extensions. */ tlsExtensionUpdateLength(tls_extensions); } /* Retrieves a TLS Handshake record, or returns NULL on error. */ bs *getTLSHandshakeRecord(int s) { bs *tls_record = NULL; bs_new_size(&tls_record, 512); /* Read in the first 5 bytes to get the length of the rest of the record. */ int err = bs_read_socket(tls_record, s, 5); if (err != 0) goto err; /* Ensure that the Content Type is Handshake (22). */ if (bs_get_byte(tls_record, 0) != 0x16) goto err; /* Get the length of the record. */ unsigned short packet_len = (bs_get_byte(tls_record, 3) << 8) | bs_get_byte(tls_record, 4); /* Read in the rest of the record. */ err = bs_read_socket(tls_record, s, packet_len); if (err != 0) goto err; return tls_record; err: bs_free(&tls_record); return NULL; } /* Update the length of the TLS extensions. */ void tlsExtensionUpdateLength(bs *tls_extensions) { bs_set_ushort(tls_extensions, 0, bs_get_len(tls_extensions) - 2); } /* From socket s, reads a ServerHello from the network. Returns a byte string on success (which the caller must bs_free()), or NULL on failure. */ bs *getServerHello(int s) { bs *server_hello = getTLSHandshakeRecord(s); if (server_hello == NULL) goto err; /* Ensure that the Handshake Type is Server Hello (2). */ if (bs_get_byte(server_hello, 5) != 0x02) goto err; return server_hello; err: bs_free(&server_hello); return NULL; } /* Returns a byte string (which the caller must later bs_free()) containing a TLS Client Hello message. The 'tls_version' must be one of the TLSv1_? constants. The specified ciphersuite list and TLS extensions will be included. */ bs *makeClientHello(struct sslCheckOptions *options, unsigned int tls_version, bs *ciphersuite_list, bs *tls_extensions) { bs *client_hello = NULL; unsigned int tls_record_version_low_byte = 1, tls_handshake_version_low_byte = 1; time_t time_now = time(NULL); /* For TLSv1.0, 1.1, and 1.2, the TLS Record version and Handshake version are the same (and what they should be). For TLSv1.3, the TLS Record claims to be TLSv1.0 and the Handshake claims to be TLSv1.2; this is for compatibility of buggy middleware that most implementations follow. */ if (tls_version < TLSv1_3) { tls_record_version_low_byte += tls_version; tls_handshake_version_low_byte += tls_version; } else { tls_record_version_low_byte = 1; tls_handshake_version_low_byte = 3; } /* Allocate byte string for the Client Hello and TLS extensions. */ bs_new_size(&client_hello, 1024); /* Build the TLSv1 Record with the ClientHello message. */ bs_append_bytes(client_hello, (unsigned char []) { 0x16, // Content Type: Handshake (22) 0x03, (unsigned char)tls_record_version_low_byte, // Version: TLS 1.x 0x00, 0x00, // Length (to be filled in later) 0x01, // Handshake Type: Client Hello 0x00, 0x00, 0x00, // Length (to be filled in later) 0x03, (unsigned char)tls_handshake_version_low_byte, // Version: TLS 1.x }, 11); /* "Random" 32 bytes. */ uint32_t rand = htonl(time_now); bs_append_uint32_t(client_hello, rand); /* The first 4 bytes is the timestamp. */ for (int i = 1; i < 8; i++) { rand = rand + (time_now ^ (uint32_t)((~(i + 0) << 24) | (~(i + 1) << 16) | (~(i + 2) << 8) | (~(i + 3) << 0))); bs_append_uint32_t(client_hello, rand); } /* Session ID Length: 32 */ bs_append_bytes(client_hello, (unsigned char []) { 32 }, 1); /* A "random" 32-byte session ID. */ for (int i = 0; i < 8; i++) { rand += (time_now ^ (uint32_t)((~(i + 0) << 24) | (~(i + 1) << 16) | (~(i + 2) << 8) | (~(i + 3) << 0))); bs_append_uint32_t(client_hello, rand); } /* Add the length (in bytes) of the ciphersuites list to the Client Hello. */ bs_append_ushort(client_hello, bs_get_len(ciphersuite_list)); /* Add the ciphersuite list. */ bs_append_bs(client_hello, ciphersuite_list); /* Add the compression options. */ bs_append_bytes(client_hello, (unsigned char []) { 0x01, // Compression Methods Length (1) 0x00 // Compression Method: null (0) }, 2); /* Add the extensions to the Client Hello. */ bs_append_bs(client_hello, tls_extensions); /* Set the length of the Client Hello. */ bs_set_byte(client_hello, 6, 0); bs_set_ushort(client_hello, 7, bs_get_len(client_hello) - 9); /* Set the length of the Record Layer. */ bs_set_ushort(client_hello, 3, bs_get_len(client_hello) - 5); return client_hello; } /* Checks all ciphersuites that OpenSSL does not support. When version is 0, TLSv1.0 is tested. When set to 1, TLSv1.1 is tested. When set to 2, TLSv1.2 is tested. */ int testMissingCiphers(struct sslCheckOptions *options, unsigned int tls_version) { int ret = false, s = -1, valid_cipher_id = false; unsigned int tls_version_low_byte = 1; char *tls_printable_name = getPrintableTLSName(tls_version); bs *client_hello = NULL, *server_hello = NULL, *ciphersuite_list = NULL, *tls_extensions = NULL; tls_version_low_byte += tls_version; /* Continue until a Server Hello isn't received. */ while (1) { int cipher_bits = -1; char *cipher_name = NULL; struct timeval tval_start = {0}, tval_end = {0}, tval_elapsed = {0}; gettimeofday(&tval_start, NULL); tls_extensions = makeTLSExtensions(options, 1); /* Extension: supported_groups */ bs_append_bytes(tls_extensions, (unsigned char []) { 0x00, 0x0a, // Extension: supported_groups (10) 0x00, 0x1c, // Extension Length (28) 0x00, 0x1a, // Supported Groups List Length (26) 0x00, 0x17, // secp256r1 0x00, 0x19, // secp521r1 0x00, 0x1c, // brainpoolP512r1 0x00, 0x1b, // brainpoolP384r1 0x00, 0x18, // secp384r1 0x00, 0x1a, // brainpoolP256r1 0x00, 0x16, // secp256k1 0x00, 0x0e, // sect571r1 0x00, 0x0d, // sect571k1 0x00, 0x0b, // sect409k1 0x00, 0x0c, // sect409r1 0x00, 0x09, // sect283k1 0x00, 0x0a, // sect283r1 }, 32); tlsExtensionUpdateLength(tls_extensions); /* Construct the list of all ciphersuites not implemented by OpenSSL. */ ciphersuite_list = makeCiphersuiteListMissing(tls_version); client_hello = makeClientHello(options, tls_version, ciphersuite_list, tls_extensions); bs_free(&tls_extensions); /* Now connect to the target server. */ s = tcpConnect(options); if (s == 0) goto done; /* Send the Client Hello message. */ if (send(s, bs_get_bytes(client_hello), bs_get_len(client_hello), 0) <= 0) { printf_error("send() failed while sending Client Hello: %d (%s)", errno, strerror(errno)); goto done; /* Returns false. */ } bs_free(&client_hello); server_hello = getServerHello(s); /* If we don't receive a proper Server Hello message, or its too short, abort. We need to reach at least the session ID field (offset 44). */ if ((server_hello == NULL) || (bs_get_len(server_hello) < 44)) goto done; /* Close the socket, since we're done reading. */ CLOSE(s); /* Check that the TLS version returned is what we sent earlier. */ if ((bs_get_byte(server_hello, 1) != 0x03) || (bs_get_byte(server_hello, 2) != (unsigned char)tls_version_low_byte)) goto done; /* At this point, the test is considered a success, even if the server rejects our Client Hello. */ ret = true; /* Get the length of the session ID. We must jump over this to reach the ciphersuite selected by the server. */ unsigned int session_id_len = bs_get_byte(server_hello, 43); /* Its impossible for one byte to overflow an unsigned int (on any modern hardware), but still... */ if ((session_id_len + 43 + 2 + 1) < session_id_len) { fprintf(stderr, "Error: potential integer overflow averted (%d).\n", session_id_len); exit(-1); } /* Check that the session ID length wouldn't put us past our buffer boundary. */ if ((session_id_len + 43 + 2 + 1) > bs_get_len(server_hello)) { fprintf(stderr, "Error: size of server_hello (%"SIZE_T_FMT") is not large enough to reach cipher suite (%u).\n", sizeof(server_hello), session_id_len + 43 + 2); exit(-1); } /* Extract the cipher ID. */ unsigned char cipher_id_byte1 = bs_get_byte(server_hello, session_id_len + 43 + 1); unsigned char cipher_id_byte2 = bs_get_byte(server_hello, session_id_len + 43 + 2); unsigned short cipher_id = (cipher_id_byte1 << 8) | cipher_id_byte2; bs_free(&server_hello); /* Check that the server returned a cipher ID that we requested. Some servers * will return a cipher ID that we didn't request when our ciphersuite list * doesn't match anything (this likely violates the spec, but real servers in the * wild do this sometimes, so we have to handle it). When this happens, we * conclude that the server does not accept any of the ciphers, so we're done. */ valid_cipher_id = false; for (int i = 0; i < (bs_get_len(ciphersuite_list) / 2) && (valid_cipher_id == false); i++) { if ((bs_get_byte(ciphersuite_list, i * 2) == cipher_id_byte1) && (bs_get_byte(ciphersuite_list, (i * 2) + 1) == cipher_id_byte2)) valid_cipher_id = true; } if (valid_cipher_id == false) goto done; bs_free(&ciphersuite_list); /* Mark this cipher ID as supported by the server, so when we loop again, the next ciphersuite list doesn't include it. */ markFoundCiphersuite(cipher_id, tls_version); /* Get the IANA name and cipher bit strength (maybe -1 when unknown). */ cipher_name = resolveCipherID(cipher_id, &cipher_bits); /* Get the number of milliseconds that have elapsed. */ gettimeofday(&tval_end, NULL); timersub(&tval_end, &tval_start, &tval_elapsed); unsigned int milliseconds_elapsed = tval_elapsed.tv_sec * 1000 + (int)tval_elapsed.tv_usec / 1000; /* Output the cipher information. */ outputCipher(options, NULL, tls_printable_name, cipher_id, cipher_name, cipher_bits, 1, milliseconds_elapsed); } done: CLOSE(s); bs_free(&ciphersuite_list); bs_free(&tls_extensions); bs_free(&client_hello); bs_free(&server_hello); return ret; } /* Enumerates all the group key exchanges supported by the server. Tests the highest supported protocol between TLSv1.0 and v1.2, along with TLSv1.3 (if enabled). */ int testSupportedGroups(struct sslCheckOptions *options) { int ret = true, s = -1; unsigned int printed_header = 0; int test_versions[2] = {-1, -1}; bs *client_hello = NULL, *ciphersuite_list = NULL, *tls_extensions = NULL, *tls_record = NULL, *key_exchange = NULL; struct group_key_exchange { uint16_t group_id; char *group_name; unsigned int group_bit_strength; /* The bit strength equivalent of this group. */ char *color; int nid; /* NID for group, or -1 for X25519/X448. */ unsigned int nid_type; /* One of the NID_TYPE_* flags. */ uint16_t key_exchange_len; }; /* Auto-generated by ./tools/iana_tls_supported_groups_parser.py on December 24, 2019. */ #define COL_PLAIN "" #define NID_TYPE_UNUSED 0 #define NID_TYPE_ECDHE 1 /* For ECDHE curves (sec*, P-256/384-521) */ #define NID_TYPE_DHE 2 /* For ffdhe* */ #define NID_TYPE_X25519 3 #define NID_TYPE_X448 4 /* Bit strength of DHE 2048 and 3072-bit moduli is taken directly from NIST SP 800-57 pt.1, rev4., pg. 53; DHE 4096, 6144, and 8192 are estimated using that document. */ struct group_key_exchange group_key_exchanges[] = { {0x0001, "sect163k1", 81, COL_RED, NID_sect163k1, NID_TYPE_ECDHE, 0}, {0x0002, "sect163r1", 81, COL_RED, NID_sect163r1, NID_TYPE_ECDHE, 0}, {0x0003, "sect163r2", 81, COL_RED, NID_sect163r2, NID_TYPE_ECDHE, 0}, {0x0004, "sect193r1", 96, COL_RED, NID_sect193r1, NID_TYPE_ECDHE, 0}, {0x0005, "sect193r2", 96, COL_RED, NID_sect193r2, NID_TYPE_ECDHE, 0}, {0x0006, "sect233k1", 116, COL_PLAIN, NID_sect233k1, NID_TYPE_ECDHE, 0}, {0x0007, "sect233r1", 116, COL_PLAIN, NID_sect233r1, NID_TYPE_ECDHE, 0}, {0x0008, "sect239k1", 119, COL_PLAIN, NID_sect239k1, NID_TYPE_ECDHE, 0}, {0x0009, "sect283k1", 141, COL_PLAIN, NID_sect283k1, NID_TYPE_ECDHE, 0}, {0x000a, "sect283r1", 141, COL_PLAIN, NID_sect283r1, NID_TYPE_ECDHE, 0}, {0x000b, "sect409k1", 204, COL_PLAIN, NID_sect409k1, NID_TYPE_ECDHE, 0}, {0x000c, "sect409r1", 204, COL_PLAIN, NID_sect409r1, NID_TYPE_ECDHE, 0}, {0x000d, "sect571k1", 285, COL_PLAIN, NID_sect571k1, NID_TYPE_ECDHE, 0}, {0x000e, "sect571r1", 285, COL_PLAIN, NID_sect571r1, NID_TYPE_ECDHE, 0}, {0x000f, "secp160k1", 80, COL_RED, NID_secp160k1, NID_TYPE_ECDHE, 0}, {0x0010, "secp160r1", 80, COL_RED, NID_secp160r1, NID_TYPE_ECDHE, 0}, {0x0011, "secp160r2", 80, COL_RED, NID_secp160r2, NID_TYPE_ECDHE, 0}, {0x0012, "secp192k1", 96, COL_RED, NID_secp192k1, NID_TYPE_ECDHE, 0}, {0x0013, "secp192r1", 96, COL_RED, NID_X9_62_prime192v1, NID_TYPE_ECDHE, 0}, {0x0014, "secp224k1", 112, COL_PLAIN, NID_secp224k1, NID_TYPE_ECDHE, 0}, {0x0015, "secp224r1", 112, COL_PLAIN, NID_secp224r1, NID_TYPE_ECDHE, 0}, {0x0016, "secp256k1", 128, COL_GREEN, NID_secp256k1, NID_TYPE_ECDHE, 0}, {0x0017, "secp256r1 (NIST P-256)", 128, COL_PLAIN, NID_X9_62_prime256v1, NID_TYPE_ECDHE, 0}, {0x0018, "secp384r1 (NIST P-384)", 192, COL_PLAIN, NID_secp384r1, NID_TYPE_ECDHE, 0}, {0x0019, "secp521r1 (NIST P-521)", 260, COL_PLAIN, NID_secp521r1, NID_TYPE_ECDHE, 0}, {0x001a, "brainpoolP256r1", 128, COL_PLAIN, NID_brainpoolP256r1, NID_TYPE_ECDHE, 0}, {0x001b, "brainpoolP384r1", 192, COL_PLAIN, NID_brainpoolP384r1, NID_TYPE_ECDHE, 0}, {0x001c, "brainpoolP512r1", 256, COL_PLAIN, NID_brainpoolP512r1, NID_TYPE_ECDHE, 0}, {0x001d, "x25519", 128, COL_GREEN, -1, NID_TYPE_X25519, 32}, {0x001e, "x448", 224, COL_GREEN, -1, NID_TYPE_X448, 56}, {0x0100, "ffdhe2048", 112, COL_PLAIN, NID_ffdhe2048, NID_TYPE_DHE, 256}, {0x0101, "ffdhe3072", 128, COL_PLAIN, NID_ffdhe3072, NID_TYPE_DHE, 384}, {0x0102, "ffdhe4096", 150, COL_PLAIN, NID_ffdhe4096, NID_TYPE_DHE, 512}, {0x0103, "ffdhe6144", 175, COL_PLAIN, NID_ffdhe6144, NID_TYPE_DHE, 768}, {0x0104, "ffdhe8192", 192, COL_PLAIN, NID_ffdhe8192, NID_TYPE_DHE, 1024}, }; /* If TLSv1.3 is supported, test it first. */ unsigned int index = 0; if (options->tls13_supported) { test_versions[index] = TLSv1_3; index++; } /* For TLSv1.2 and below, test the highest protocol version supported. */ if (options->tls12_supported) test_versions[index] = TLSv1_2; else if (options->tls11_supported) test_versions[index] = TLSv1_1; else if (options->tls10_supported) test_versions[index] = TLSv1_0; /* Loop through the one or two TLS versions to test. */ for (index = 0; index < (sizeof(test_versions) / sizeof(int)); index++) { int tls_version = test_versions[index]; /* If there's only one version to test... */ if (tls_version == -1) break; if (tls_version == TLSv1_3) ciphersuite_list = makeCiphersuiteListAll(tls_version); else { /* For some reason, with TLSv1.2 (and maybe below), passing all ciphersuites causes false negatives. So we use a string of bytes sniffed from an OpenSSL client connection. */ bs_new(&ciphersuite_list); bs_append_bytes(ciphersuite_list, (unsigned char []) { 0xc0, 0x30, 0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14, 0xc0, 0x0a, 0x00, 0xa5, 0x00, 0xa3, 0x00, 0xa1, 0x00, 0x9f, 0x00, 0x6b, 0x00, 0x6a, 0x00, 0x69, 0x00, 0x68, 0x00, 0x39, 0x00, 0x38, 0x00, 0x37, 0x00, 0x36, 0x00, 0x88, 0x00, 0x87, 0x00, 0x86, 0x00, 0x85, 0xc0, 0x32, 0xc0, 0x2e, 0xc0, 0x2a, 0xc0, 0x26, 0xc0, 0x0f, 0xc0, 0x05, 0x00, 0x9d, 0x00, 0x3d, 0x00, 0x35, 0x00, 0x84, 0xc0, 0x2f, 0xc0, 0x2b, 0xc0, 0x27, 0xc0, 0x23, 0xc0, 0x13, 0xc0, 0x09, 0x00, 0xa4, 0x00, 0xa2, 0x00, 0xa0, 0x00, 0x9e, 0x00, 0x67, 0x00, 0x40, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x33, 0x00, 0x32, 0x00, 0x31, 0x00, 0x30, 0x00, 0x9a, 0x00, 0x99, 0x00, 0x98, 0x00, 0x97, 0x00, 0x45, 0x00, 0x44, 0x00, 0x43, 0x00, 0x42, 0xc0, 0x31, 0xc0, 0x2d, 0xc0, 0x29, 0xc0, 0x25, 0xc0, 0x0e, 0xc0, 0x04, 0x00, 0x9c, 0x00, 0x3c, 0x00, 0x2f, 0x00, 0x96, 0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 0xc0, 0x0c, 0xc0, 0x02, 0x00, 0x05, 0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 0x00, 0x13, 0x00, 0x10, 0x00, 0x0d, 0xc0, 0x0d, 0xc0, 0x03, 0x00, 0x0a, 0x00, 0xff }, 170); } /* For each key exchange group... */ for (int i = 0; i < (sizeof(group_key_exchanges) / sizeof(struct group_key_exchange)); i++) { uint16_t group_id = group_key_exchanges[i].group_id; char *group_name = group_key_exchanges[i].group_name; char *color = group_key_exchanges[i].color; unsigned int group_bit_strength = group_key_exchanges[i].group_bit_strength; int nid = group_key_exchanges[i].nid; unsigned nid_type = group_key_exchanges[i].nid_type; uint16_t key_exchange_len = group_key_exchanges[i].key_exchange_len; /* This will hold the key exchange data that we send to the server. */ bs_new_size(&key_exchange, key_exchange_len); /* Generate the right type of key exchange data. */ if (nid_type == NID_TYPE_X25519) bs_append_x25519_pubkey(key_exchange); else if (nid_type == NID_TYPE_X448) bs_append_x448_pubkey(key_exchange); else if (nid_type == NID_TYPE_ECDHE) { /* Generate the ECDHE key. */ EC_KEY *key = EC_KEY_new_by_curve_name(nid); if ((key == NULL) || (EC_KEY_generate_key(key) != 1)) { EC_KEY_free(key); key = NULL; fprintf(stderr, "Failed to generate ECDHE key for nid %d\n", nid); continue; } /* Allocate a *new* byte array and put the key into it. */ unsigned char *kex_buf = NULL; key_exchange_len = EC_KEY_key2buf(key, POINT_CONVERSION_UNCOMPRESSED, &kex_buf, NULL); if (kex_buf == NULL) { EC_KEY_free(key); key = NULL; fprintf(stderr, "Failed to obtain ECDHE public key bytes.\n"); continue; } bs_append_bytes(key_exchange, kex_buf, key_exchange_len); OPENSSL_free(kex_buf); kex_buf = NULL; EC_KEY_free(key); key = NULL; } else if (nid_type == NID_TYPE_DHE) { /* The value (Y) for FFDHE group must be 1 < Y < p - 1 (see RFC7919). Furthermore, GnuTLS checks that Y ^ q mod p == 1 (see GnuTLS v3.6.11.1, lib/nettle/pk.c:291). The easiest way to do this seems to be to actually generate real DH public keys. */ DH *dh = DH_new_by_nid(nid); if (!DH_generate_key(dh)) { bs_free(&key_exchange); fprintf(stderr, "Failed to generate DH key for nid %d\n", nid); continue; } /* Make array to read in DH public key. */ unsigned int bytes_len = key_exchange_len; unsigned char *bytes = calloc(bytes_len, sizeof(unsigned char)); if (bytes == NULL) { fprintf(stderr, "Failed to allocate buffer for key.\n"); exit(-1); } /* Export the public key to our array. */ const BIGNUM *pub_key = NULL; DH_get0_key(dh, &pub_key, NULL); if (!BN_bn2binpad(pub_key, bytes, bytes_len)) { bs_free(&key_exchange); fprintf(stderr, "Failed to get DH key for nid %d\n", nid); continue; } /* Add the bytes to our byte string. */ bs_append_bytes(key_exchange, bytes, bytes_len); FREE(bytes); bytes_len = 0; } else { /* Use the provided value, since it must be a specific format. */ fprintf(stderr, "Error: unknown NID_TYPE in struct: %d\n", nid_type); exit(-1); } /* Make generic TLS extensions (with SNI, accepted EC point formats, etc). */ tls_extensions = makeTLSExtensions(options, 1); /* Add the supported_versions extension to signify we are using TLS v1.3. */ if (tls_version == TLSv1_3) tlsExtensionAddTLSv1_3(tls_extensions); /* Add the supported_groups extension. Only add the one group we are testing for. */ bs_append_bytes(tls_extensions, (unsigned char []) { 0x00, 0x0a, // Extension Type: supported_groups (10) 0x00, 0x04, // Extension Length (4) 0x00, 0x02, // Supported Groups List Length (2) }, 6); bs_append_ushort(tls_extensions, group_id); /* Only add the key_share extension if we're using TLS v1.3. */ if (tls_version == TLSv1_3) { /* Add the key_share extension for the current group type. */ bs_append_bytes(tls_extensions, (unsigned char []) { 0x00, 0x33 }, 2); // Extension Type: key_share (51) bs_append_ushort(tls_extensions, bs_get_len(key_exchange) + 6); // Extension Length bs_append_ushort(tls_extensions, bs_get_len(key_exchange) + 4); // Client Key Share Length bs_append_ushort(tls_extensions, group_id); // Group ID. bs_append_ushort(tls_extensions, bs_get_len(key_exchange)); // Key Exchange Length bs_append_bs(tls_extensions, key_exchange); // Key Exchange } bs_free(&key_exchange); /* Update the TLS extensions length since we manually added to it. */ tlsExtensionUpdateLength(tls_extensions); /* Create the Client Hello buffer using the ciphersuite list and TLS extensions. */ client_hello = makeClientHello(options, tls_version, ciphersuite_list, tls_extensions); /* Free the TLS extensions since we're done with them. Note: we don't free the ciphersuite_list because we'll need them on the next loop. */ bs_free(&tls_extensions); CLOSE(s); /* In case the last loop left the socket open. */ /* Now connect to the target server. */ s = tcpConnect(options); if (s == 0) { ret = false; goto done; } /* Send the Client Hello message. */ if (send(s, bs_get_bytes(client_hello), bs_get_len(client_hello), 0) <= 0) { printf_error("send() failed while sending Client Hello: %d (%s)", errno, strerror(errno)); ret = false; goto done; } bs_free(&client_hello); tls_record = getServerHello(s); /* This group is definitely not supported. */ if (tls_record == NULL) { CLOSE(s); continue; } /* For TLSv1.2 and below, we need to examine the Server Key Exchange record. */ if (tls_version < TLSv1_3) { unsigned int handshake_type = 0; unsigned int handshake_type_offset = 5; uint32_t handshake_len = 0; /* Loop through all the handshake protocols inside this TLS record. Some implementations only include one (such as OpenSSL), and others include several (such as Windows Server 2022). */ while (tls_record != NULL) { handshake_type = bs_get_byte(tls_record, handshake_type_offset); /* Handshake type 12 is a Server Key Exchange. This may have the group information we need, so we can stop searching. */ if (handshake_type == 12) { break; /* Handshake type 14 is a Server Hello Done. If we reach this before finding a Server Key Exchange, we know the server does not support this group. */ } else if (handshake_type == 14) { bs_free(&tls_record); CLOSE(s); continue; } /* The handshake length is strangely only three bytes... */ handshake_len = bs_get_byte(tls_record, handshake_type_offset + 1) << 16; handshake_len |= bs_get_byte(tls_record, handshake_type_offset + 2) << 8; handshake_len |= bs_get_byte(tls_record, handshake_type_offset + 3) << 0; /* If we processed all handshake messages in this TLS record, read the next record. */ if (tls_record->len < handshake_len + handshake_type_offset) { bs_free(&tls_record); tls_record = getTLSHandshakeRecord(s); handshake_type_offset = 5; } else handshake_type_offset += (handshake_len + 4); } /* Error, so skip this group. */ if (tls_record == NULL) { bs_free(&tls_record); CLOSE(s); continue; } /* If this Server Key Exchange does not have a named_curve (3) field, skip this group. */ if (bs_get_byte(tls_record, handshake_type_offset + 4) != 3) { bs_free(&tls_record); CLOSE(s); continue; } /* Check that the named_curve result is the group we requested. */ uint16_t server_group_id = bs_get_byte(tls_record, handshake_type_offset + 5) << 8 | bs_get_byte(tls_record, handshake_type_offset + 6); if (server_group_id != group_id) { bs_free(&tls_record); CLOSE(s); continue; } } bs_free(&tls_record); CLOSE(s); if (!printed_header) { printf("\n %sServer Key Exchange Group(s):%s\n", COL_BLUE, RESET); printed_header = 1; } char *bits_color = RESET; if (group_bit_strength < 112) bits_color = COL_RED; else bits_color = COL_GREEN; char *printable_TLS_name = getPrintableTLSName(tls_version); printf("%s %s%d%s bits %s%s%s\n", printable_TLS_name, bits_color, group_bit_strength, RESET, color, group_name, RESET); printf_xml(" \n", printable_TLS_name, group_bit_strength, group_name, group_id); } } done: CLOSE(s); bs_free(&ciphersuite_list); bs_free(&tls_extensions); bs_free(&client_hello); bs_free(&tls_record); return ret; } /* Enumerates all the signature algorithms supported by the server. */ int testSignatureAlgorithms(struct sslCheckOptions *options) { struct signature_algorithm { uint16_t sig_id; char *sig_name; char *color; }; #define COL_PLAIN "" #define BOGUS_SIG_ALG_ID 0xfdff /* Last un-assigned ID. */ struct signature_algorithm signature_algorithms[] = { {BOGUS_SIG_ALG_ID, "bogus", COL_RED}, /* Tests if the server is accepting all. */ {0x0001, "rsa_pkcs1_nohash", COL_RED}, {0x0002, "dsa_nohash", COL_RED}, {0x0003, "ecdsa_nohash", COL_RED}, {0x0101, "rsa_pkcs1_md5", COL_RED}, {0x0102, "dsa_md5", COL_RED}, {0x0103, "ecdsa_md5", COL_RED}, {0x0201, "rsa_pkcs1_sha1", COL_RED}, {0x0202, "dsa_sha1", COL_RED}, {0x0203, "ecdsa_sha1", COL_RED}, {0x0301, "rsa_pkcs1_sha224", COL_YELLOW}, {0x0302, "dsa_sha224", COL_RED}, {0x0303, "ecdsa_sha224", COL_YELLOW}, {0x0401, "rsa_pkcs1_sha256", COL_PLAIN}, {0x0402, "dsa_sha256", COL_RED}, {0x0403, "ecdsa_secp256r1_sha256", COL_PLAIN}, {0x0501, "rsa_pkcs1_sha384", COL_PLAIN}, {0x0502, "dsa_sha384", COL_RED}, {0x0503, "ecdsa_secp384r1_sha384", COL_PLAIN}, {0x0601, "rsa_pkcs1_sha512", COL_PLAIN}, {0x0602, "dsa_sha512", COL_RED}, {0x0603, "ecdsa_secp521r1_sha512", COL_PLAIN}, {0x0804, "rsa_pss_rsae_sha256", COL_PLAIN}, {0x0805, "rsa_pss_rsae_sha384", COL_PLAIN}, {0x0806, "rsa_pss_rsae_sha512", COL_PLAIN}, {0x0807, "ed25519", COL_GREEN}, {0x0808, "ed448", COL_GREEN}, {0x0809, "rsa_pss_pss_sha256", COL_PLAIN}, {0x080a, "rsa_pss_pss_sha384", COL_PLAIN}, {0x080b, "rsa_pss_pss_sha512", COL_PLAIN}, }; unsigned int printed_header = 0; int ret = true, s = -1; int test_versions[2] = {-1, -1}; bs *client_hello = NULL, *ciphersuite_list = NULL, *tls_extensions = NULL, *server_hello = NULL; /* If TLSv1.3 is supported, test it first. */ unsigned int index = 0; if (options->tls13_supported) { test_versions[index] = TLSv1_3; index++; } /* For TLSv1.2 and below, test the highest protocol version supported. */ if (options->tls12_supported) test_versions[index] = TLSv1_2; else if (options->tls11_supported) test_versions[index] = TLSv1_1; else if (options->tls10_supported) test_versions[index] = TLSv1_0; /* Loop through the one or two TLS versions to test. */ for (index = 0; index < (sizeof(test_versions) / sizeof(int)); index++) { int tls_version = test_versions[index]; /* If there's only one version to test... */ if (tls_version == -1) break; if (tls_version == TLSv1_3) { /* Get all TLSv1.3 ciphersuites. */ ciphersuite_list = makeCiphersuiteListTLS13All(); } else ciphersuite_list = makeCiphersuiteListAll(tls_version); /* For each signature algorithm... */ for (int i = 0; i < (sizeof(signature_algorithms) / sizeof(struct signature_algorithm)); i++) { uint16_t sig_id = signature_algorithms[i].sig_id; char *sig_name = signature_algorithms[i].sig_name; char *color = signature_algorithms[i].color; /* Make generic TLS extensions (with SNI, accepted EC point formats, etc). */ tls_extensions = makeTLSExtensions(options, 0); if (tls_version == TLSv1_3) { /* Extension: supported_groups */ bs_append_bytes(tls_extensions, (unsigned char []) { 0x00, 0x0a, // Extension: supported_groups (10) 0x00, 0x16, // Extension Length (22) 0x00, 0x14, // Supported Groups List Length (20) 0x00, 0x17, // secp256r1 0x00, 0x19, // secp521r1 0x00, 0x18, // secp384r1 0x00, 0x1d, // X25519 0x00, 0x1e, // X448 0x01, 0x00, // FFDHE2048 0x01, 0x01, // FFDHE3072 0x01, 0x02, // FFDHE4096 0x01, 0x03, // FFDHE6144 0x01, 0x04, // FFDHE8192 }, 26); /* Add key shares for X25519. */ tlsExtensionAddDefaultKeyShare(tls_extensions); /* Add the supported_versions extension to signify we are using TLS v1.3. */ tlsExtensionAddTLSv1_3(tls_extensions); } /* Add the signature_algorithms extension. Only add the one group we are testing for. */ bs_append_bytes(tls_extensions, (unsigned char []) { 0x00, 0x0d, // Extension Type: signature_algorithms (13) 0x00, 0x04, // Extension Length (4) 0x00, 0x02, // Signature Hash Algorithms List Length (2) }, 6); bs_append_ushort(tls_extensions, sig_id); /* Update the TLS extensions length since we manually added to it. */ tlsExtensionUpdateLength(tls_extensions); /* Create the Client Hello buffer using the ciphersuite list and TLS extensions. */ client_hello = makeClientHello(options, tls_version, ciphersuite_list, tls_extensions); /* Free the TLS extensions since we're done with them. Note: we don't free the ciphersuite_list because we'll need them on the next loop. */ bs_free(&tls_extensions); /* Now connect to the target server. */ s = tcpConnect(options); if (s == 0) { ret = false; goto done; } /* Send the Client Hello message. */ if (send(s, bs_get_bytes(client_hello), bs_get_len(client_hello), 0) <= 0) { printf_error("send() failed while sending Client Hello: %d (%s)", errno, strerror(errno)); ret = false; goto done; } bs_free(&client_hello); server_hello = getServerHello(s); CLOSE(s); /* This signature algorithm is not supported. */ if (server_hello == NULL) continue; bs_free(&server_hello); if (!printed_header) { printf("\n %sServer Signature Algorithm(s):%s\n", COL_BLUE, RESET); printed_header = 1; } /* If the server accepted our bogus signature ID, then we can conclude that it will accept all of them (and not test any further). Some servers in the wild do this for some reason... */ if (sig_id == BOGUS_SIG_ALG_ID) { printf("%s%s Server accepts all signature algorithms.%s\n", getPrintableTLSName(tls_version), COL_RED, RESET); printf_xml(" \n", getPrintableTLSName(tls_version)); break; } else { printf("%s %s%s%s\n", getPrintableTLSName(tls_version), color, sig_name, RESET); printf_xml(" \n", getPrintableTLSName(tls_version), sig_name, sig_id); } } } done: CLOSE(s); bs_free(&ciphersuite_list); bs_free(&tls_extensions); bs_free(&client_hello); bs_free(&server_hello); return ret; } /* MinGW doesn't have a memmem() implementation. */ #ifdef _WIN32 /* Implementation taken from: https://sourceforge.net/p/mingw/msys2-runtime/ci/f21dc72d306bd98e55a08461a9530c4b0ce1dffe/tree/newlib/libc/string/memmem.c#l80 */ /* Copyright (C) 2008 Eric Blake * Permission to use, copy, modify, and distribute this software * is freely granted, provided that this notice is preserved.*/ void *memmem(const void *haystack_start, size_t haystack_len, const void *needle, size_t needle_len) { const unsigned char *haystack = (const unsigned char *) haystack_start; //const unsigned char *needle = (const unsigned char *) needle_start; if (needle_len == 0) return (void *)haystack; while (needle_len <= haystack_len) { if (!memcmp (haystack, needle, needle_len)) return (void *) haystack; haystack++; haystack_len--; } return NULL; } #endif /* vim :set ts=4 sw=4 sts=4 et : */ sslscan-2.1.2/sslscan.h000066400000000000000000000327301452476416400150230ustar00rootroot00000000000000/*************************************************************************** * sslscan - A SSL cipher scanning tool * * Copyright 2007-2009 by Ian Ventura-Whiting (Fizz) * * fizz@titania.co.uk * * Copyright 2010 by Michael Boman (michael@michaelboman.org) * * Copyleft 2010 by Jacob Appelbaum * * Copyleft 2013 by rbsec * * Copyleft 2014 by Julian Kornberger * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef HAVE_SSLSCAN_H_ #define HAVE_SSLSCAN_H_ #include "missing_ciphersuites.h" // Defines... #define false 0 #define true 1 #define mode_help 0 #define mode_version 1 #define mode_single 2 #define mode_multiple 3 #define BUFFERSIZE 1024 // For options.sslVersion field. #define ssl_all 0 #define ssl_v2 1 #define ssl_v3 2 #define tls_all 3 #define tls_v10 4 #define tls_v11 5 #define tls_v12 6 #define tls_v13 7 // For functions that take a tls_version argument. #define TLSv1_0 0 #define TLSv1_1 1 #define TLSv1_2 2 #define TLSv1_3 3 /* We must maintain our own list of TLSv1.3-specific ciphersuites here, because SSL_CTX_get_ciphers() will *always* return TLSv1.2 ciphersuites, even when SSL_CTX_set_min_proto_version() and SSL_CTX_set_max_proto_version() are used. This is confirmed by an OpenSSL developer here: https://github.com/openssl/openssl/issues/7196#issuecomment-420575202 */ #define TLSV13_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" /* Cipherlist for TLSv1.2 and below that corresponds to all available ciphersuites. */ #define CIPHERSUITE_LIST_ALL "ALL:COMPLEMENTOFALL" // Macros for various outputs #define printf(format, ...) if (!xml_to_stdout) fprintf(stdout, format, ##__VA_ARGS__) #define printf_xml(format, ...) if (options->xmlOutput) fprintf(options->xmlOutput, format, ##__VA_ARGS__) #define printf_verbose(format, ...) if (options->verbose) printf(format, ##__VA_ARGS__) #define printf_error(format, ...) \ if (!xml_to_stdout) fprintf(stderr, "%sERROR: " format "%s\n", COL_RED, ##__VA_ARGS__, RESET); \ printf_xml(" \n", ##__VA_ARGS__) /* Calls close() on a file descriptor, then sets it to zero to prevent accidental re-use. */ #define CLOSE(fd) { if ((fd) != -1) { close((fd)); (fd) = -1; } } /* Calls free() on a pointer, then explicitly sets it to NULL to avoid use-after-free. */ #define FREE(ptr) { free((ptr)); (ptr) = NULL; } /* Frees an SSL pointer, and explicitly sets it to NULL to avoid use-after-free. */ #define FREE_SSL(ssl) { if ((ssl) != NULL) { SSL_free((ssl)); (ssl) = NULL; } } /* Frees a SSL_CTX pointer, and explicitly sets it to NULL to avoid use-after-free. */ #define FREE_CTX(ctx) { if ((ctx) != NULL) { SSL_CTX_free((ctx)); (ctx) = NULL; } } // Colour Console Output... // Always better to do "const char RESET[] = " because it saves relocation records. // Default colours were hard to read on Windows, so use lighter ones #ifdef _WIN32 char *RESET = ""; // DEFAULT char *COL_RED = ""; char *COL_YELLOW = ""; char *COL_BLUE = ""; char *COL_GREEN = ""; char *COL_PURPLE = ""; char *COL_GREY = ""; char *COL_RED_BG = ""; #else char *RESET = ""; // DEFAULT char *COL_RED = ""; char *COL_YELLOW = ""; char *COL_BLUE = ""; char *COL_GREEN = ""; char *COL_PURPLE = ""; char *COL_GREY = ""; char *COL_RED_BG = ""; #endif #ifdef _WIN32 #define SLEEPMS(ms) Sleep(ms); #else #define SLEEPMS(ms) do { \ struct timeval wait = { 0, ms*1000 }; \ select(0, NULL, NULL, NULL, &wait); \ } while(0) #endif const char *program_banner = " _\n" " ___ ___| |___ ___ __ _ _ __\n" " / __/ __| / __|/ __/ _` | '_ \\\n" " \\__ \\__ \\ \\__ \\ (_| (_| | | | |\n" " |___/___/_|___/\\___\\__,_|_| |_|\n\n"; struct sslCipher { // Cipher Properties... const char *name; const char *version; int bits; char description[512]; const SSL_METHOD *sslMethod; struct sslCipher *next; }; struct sslCheckOptions { // Program Options... char host[512]; char sniname[512]; int sni_set; char addrstr[INET6_ADDRSTRLEN]; int port; int showCertificate; int checkCertificate; int showTrustedCAs; int showClientCiphers; int showCipherIds; int showTimes; int ciphersuites; int reneg; int fallback; int compression; int heartbleed; int groups; int signature_algorithms; int starttls_ftp; int starttls_imap; int starttls_irc; int starttls_ldap; int starttls_pop3; int starttls_smtp; int starttls_mysql; int starttls_xmpp; int starttls_psql; int xmpp_server; int sslVersion; int targets; int sslbugs; int rdp; int verbose; int cipher_details; int ipv4; int ipv6; int ocspStatus; int ianaNames; char cipherstring[65536]; // File Handles... FILE *xmlOutput; // TCP Connection Variables... short h_addrtype; struct sockaddr_in serverAddress; struct sockaddr_in6 serverAddress6; struct timeval timeout; int connect_timeout; unsigned int sleep; // SSL Variables... SSL_CTX *ctx; struct sslCipher *ciphers; char *clientCertsFile; char *privateKeyFile; char *privateKeyPassword; // TLS versions supported by the server. unsigned int tls10_supported; unsigned int tls11_supported; unsigned int tls12_supported; unsigned int tls13_supported; }; // store renegotiation test data struct renegotiationOutput { int supported; int secure; }; /* For OCSP processing. Taken from crypto/ocsp/ocsp_local.h in OpenSSL, which does not seem to be normally exposed externally. */ struct ocsp_response_st { ASN1_ENUMERATED *responseStatus; OCSP_RESPBYTES *responseBytes; }; struct ocsp_resp_bytes_st { ASN1_OBJECT *responseType; ASN1_OCTET_STRING *response; }; struct ocsp_responder_id_st { int type; union { X509_NAME *byName; ASN1_OCTET_STRING *byKey; } value; }; typedef struct ocsp_responder_id_st OCSP_RESPID; struct ocsp_response_data_st { ASN1_INTEGER *version; OCSP_RESPID responderId; ASN1_GENERALIZEDTIME *producedAt; STACK_OF(OCSP_SINGLERESP) *responses; STACK_OF(X509_EXTENSION) *responseExtensions; }; typedef struct ocsp_response_data_st OCSP_RESPDATA; struct ocsp_basic_response_st { OCSP_RESPDATA tbsResponseData; X509_ALGOR signatureAlgorithm; ASN1_BIT_STRING *signature; STACK_OF(X509) *certs; }; struct ocsp_single_response_st { OCSP_CERTID *certId; OCSP_CERTSTATUS *certStatus; ASN1_GENERALIZEDTIME *thisUpdate; ASN1_GENERALIZEDTIME *nextUpdate; STACK_OF(X509_EXTENSION) *singleExtensions; }; struct ocsp_cert_status_st { int type; union { ASN1_NULL *good; OCSP_REVOKEDINFO *revoked; ASN1_NULL *unknown; } value; }; struct ocsp_revoked_info_st { ASN1_GENERALIZEDTIME *revocationTime; ASN1_ENUMERATED *revocationReason; }; struct ocsp_cert_id_st { X509_ALGOR hashAlgorithm; ASN1_OCTET_STRING issuerNameHash; ASN1_OCTET_STRING issuerKeyHash; ASN1_INTEGER serialNumber; }; #define BS_DEFAULT_NEW_SIZE 256 /* The starting size of the buffer when bs_new() is used. */ struct _bs { unsigned char *buf; size_t size; /* The size of the allocated buffer. */ size_t len; /* The number of bytes currently in the buffer. */ }; typedef struct _bs bs; /* Stands for 'byte string'. */ /* We redefine these so that we can run correctly even if the vendor gives us * a version of OpenSSL that does not match its header files. (Apple: I am * looking at you.) */ #ifndef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION # define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0x00040000L #endif #ifndef SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION # define SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0x0010 #endif // Utilities void bs_new(bs **); void bs_new_size(bs **, size_t); void bs_free(bs **); void bs_append_bytes(bs *, unsigned char *, size_t); void bs_append_uint32_t(bs *, uint32_t); void bs_append_ushort(bs *, unsigned short); void bs_append_bs(bs *, bs *); size_t bs_get_len(bs *); size_t bs_get_size(bs *); unsigned char *bs_get_bytes(bs *); unsigned char bs_get_byte(bs *, size_t); void bs_set_byte(bs *, size_t, unsigned char); void bs_set_ushort(bs *b, size_t offset, unsigned short length); int bs_read_socket(bs *b, int s, size_t num_bytes); unsigned int checkIfTLSVersionIsSupported(struct sslCheckOptions *options, unsigned int tls_version); SSL_CTX *CTX_new(const SSL_METHOD *method); int fileExists(char *); void findMissingCiphers(); char *getPrintableTLSName(unsigned int tls_version); bs *getServerHello(int s); bs *makeCiphersuiteListAll(unsigned int tls_version); bs *makeCiphersuiteListTLS13All(); bs *makeCiphersuiteListMissing(unsigned int tls_version); bs *makeClientHello(struct sslCheckOptions *options, unsigned int version, bs *ciphersuite_list, bs *tls_extensions); bs *makeTLSExtensions(struct sslCheckOptions *options, unsigned int include_signature_algorithms); void markFoundCiphersuite(unsigned short server_cipher_id, unsigned int tls_version); int ocsp_certid_print(BIO *bp, OCSP_CERTID *a, int indent); static int ocsp_resp_cb(SSL *s, void *arg); void readLine(FILE *, char *, int); int readOrLogAndClose(int, void *, size_t, const struct sslCheckOptions *); char *resolveCipherID(unsigned short cipher_id, int *cipher_bits); static int password_callback(char *, int, int, void *); const char *printableSslMethod(const SSL_METHOD *); ssize_t sendString(int, const char[]); int ssl_print_tmp_key(struct sslCheckOptions *, SSL *s); void tlsExtensionAddDefaultKeyShare(bs *tls_extensions); void tlsExtensionAddTLSv1_3(bs *tls_extensions); void tlsExtensionUpdateLength(bs *tls_extensions); int tcpConnect(struct sslCheckOptions *); // Tests void tls_reneg_init(struct sslCheckOptions *); int outputRenegotiation(struct sslCheckOptions *, struct renegotiationOutput *); struct renegotiationOutput *newRenegotiationOutput(void); int freeRenegotiationOutput(struct renegotiationOutput *); int testCompression(struct sslCheckOptions *, const SSL_METHOD *); int testRenegotiation(struct sslCheckOptions *, const SSL_METHOD *); #ifdef SSL_MODE_SEND_FALLBACK_SCSV int testfallback(struct sslCheckOptions *, const SSL_METHOD *); #endif int testHeartbleed(struct sslCheckOptions *, const SSL_METHOD *); int testSupportedGroups(struct sslCheckOptions *options); int testSignatureAlgorithms(struct sslCheckOptions *options); int testCipher(struct sslCheckOptions *, const SSL_METHOD *); int testMissingCiphers(struct sslCheckOptions *options, unsigned int version); int testProtocolCiphers(struct sslCheckOptions *, const SSL_METHOD *); int testConnection(struct sslCheckOptions *); int testHost(struct sslCheckOptions *); int loadCerts(struct sslCheckOptions *); int checkCertificateProtocols(struct sslCheckOptions *, const SSL_METHOD *); int checkCertificate(struct sslCheckOptions *, const SSL_METHOD *); int showCertificate(struct sslCheckOptions *); int runSSLv2Test(struct sslCheckOptions *options); int runSSLv3Test(struct sslCheckOptions *options); #endif /* vim :set ts=4 sw=4 sts=4 et : */ sslscan-2.1.2/tags000066400000000000000000000633701452476416400140710ustar00rootroot00000000000000!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/ !_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/ !_TAG_OUTPUT_FILESEP slash /slash or backslash/ !_TAG_OUTPUT_MODE u-ctags /u-ctags or e-ctags/ !_TAG_PROGRAM_AUTHOR Universal Ctags Team // !_TAG_PROGRAM_NAME Universal Ctags /Derived from Exuberant Ctags/ !_TAG_PROGRAM_URL https://ctags.io/ /official site/ !_TAG_PROGRAM_VERSION 0.0.0 /a3c87ab5/ BOGUS_SIG_ALG_ID sslscan.c /^#define BOGUS_SIG_ALG_ID /;" d file: BS_DEFAULT_NEW_SIZE sslscan.h /^#define BS_DEFAULT_NEW_SIZE /;" d BUFFERSIZE sslscan.h /^#define BUFFERSIZE /;" d CIPHERSUITE_LIST_ALL sslscan.h /^#define CIPHERSUITE_LIST_ALL /;" d CLOSE sslscan.h /^#define CLOSE(/;" d COL_BLUE sslscan.h /^char *COL_BLUE = "";$/;" v typeref:typename:char * COL_BLUE sslscan.h /^char *COL_BLUE = "";$/;" v typeref:typename:char * COL_GREEN sslscan.h /^char *COL_GREEN = "";$/;" v typeref:typename:char * COL_GREEN sslscan.h /^char *COL_GREEN = "";$/;" v typeref:typename:char * COL_GREY sslscan.h /^char *COL_GREY = "";$/;" v typeref:typename:char * COL_PLAIN sslscan.c /^#define COL_PLAIN /;" d file: COL_PURPLE sslscan.h /^char *COL_PURPLE = "";$/;" v typeref:typename:char * COL_PURPLE sslscan.h /^char *COL_PURPLE = "";$/;" v typeref:typename:char * COL_RED sslscan.h /^char *COL_RED = "";$/;" v typeref:typename:char * COL_RED sslscan.h /^char *COL_RED = "";$/;" v typeref:typename:char * COL_RED_BG sslscan.h /^char *COL_RED_BG = "";$/;" v typeref:typename:char * COL_YELLOW sslscan.h /^char *COL_YELLOW = "";$/;" v typeref:typename:char * COL_YELLOW sslscan.h /^char *COL_YELLOW = "";$/;" v typeref:typename:char * ENABLE_VIRTUAL_TERMINAL_PROCESSING sslscan.c /^ #define ENABLE_VIRTUAL_TERMINAL_PROCESSING /;" d file: FREE sslscan.h /^#define FREE(/;" d FREE_CTX sslscan.h /^#define FREE_CTX(/;" d FREE_SSL sslscan.h /^#define FREE_SSL(/;" d HAVE_SSLSCAN_H_ sslscan.h /^#define HAVE_SSLSCAN_H_$/;" d NID_TYPE_DHE sslscan.c /^#define NID_TYPE_DHE /;" d file: NID_TYPE_ECDHE sslscan.c /^#define NID_TYPE_ECDHE /;" d file: NID_TYPE_NA sslscan.c /^#define NID_TYPE_NA /;" d file: OCSP_RESPDATA sslscan.h /^typedef struct ocsp_response_data_st OCSP_RESPDATA;$/;" t typeref:struct:ocsp_response_data_st OCSP_RESPID sslscan.h /^typedef struct ocsp_responder_id_st OCSP_RESPID;$/;" t typeref:struct:ocsp_responder_id_st OVERFLOW_MESSAGE sslscan.c /^#define OVERFLOW_MESSAGE /;" d file: RESET sslscan.h /^char *RESET = ""; \/\/ DEFAULT$/;" v typeref:typename:char * R_OK sslscan.c /^ #define R_OK /;" d file: SIZE_T_FMT sslscan.c /^ #define SIZE_T_FMT /;" d file: SLEEPMS sslscan.h /^ #define SLEEPMS(/;" d SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION sslscan.h /^# define SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION /;" d SSL_CIPHER_get_id sslscan.c /^unsigned long SSL_CIPHER_get_id(const SSL_CIPHER* cipher) { return cipher->id; }$/;" f typeref:typename:unsigned long SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION sslscan.h /^# define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION /;" d TLSV13_CIPHERSUITES sslscan.h /^#define TLSV13_CIPHERSUITES /;" d TLSv1_0 sslscan.h /^#define TLSv1_0 /;" d TLSv1_1 sslscan.h /^#define TLSv1_1 /;" d TLSv1_2 sslscan.h /^#define TLSv1_2 /;" d TLSv1_3 sslscan.h /^#define TLSv1_3 /;" d TLSv1_3_client_method sslscan.c /^const SSL_METHOD *TLSv1_3_client_method(void)$/;" f typeref:typename:const SSL_METHOD * TLSv1_3_method sslscan.c /^const SSL_METHOD *TLSv1_3_method(void)$/;" f typeref:typename:const SSL_METHOD * VC_EXTRALEAN sslscan.c /^ #define VC_EXTRALEAN$/;" d file: WIN32_LEAN_AND_MEAN sslscan.c /^ #define WIN32_LEAN_AND_MEAN$/;" d file: _GNU_SOURCE sslscan.c /^#define _GNU_SOURCE$/;" d file: _WIN32_WINNT sslscan.c /^ #define _WIN32_WINNT /;" d file: __anonf49f55d2010a sslscan.h /^ union {$/;" u struct:ocsp_responder_id_st __anonf49f55d2020a sslscan.h /^ union {$/;" u struct:ocsp_cert_status_st _bs sslscan.h /^struct _bs {$/;" s access sslscan.c /^ #define access /;" d file: addrstr sslscan.h /^ char addrstr[INET6_ADDRSTRLEN];$/;" m struct:sslCheckOptions typeref:typename:char[] bits sslscan.h /^ int bits;$/;" m struct:sslCipher typeref:typename:int bs sslscan.h /^typedef struct _bs bs; \/* Stands for 'byte string'. *\/$/;" t typeref:struct:_bs bs_append_bs sslscan.c /^void bs_append_bs(bs *dst, bs *src) {$/;" f typeref:typename:void bs_append_bytes sslscan.c /^void bs_append_bytes(bs *b, unsigned char *bytes, size_t bytes_len) {$/;" f typeref:typename:void bs_append_uint32_t sslscan.c /^void bs_append_uint32_t(bs *b, uint32_t u) {$/;" f typeref:typename:void bs_append_ushort sslscan.c /^void bs_append_ushort(bs *b, unsigned short us) {$/;" f typeref:typename:void bs_free sslscan.c /^void bs_free(bs **b) {$/;" f typeref:typename:void bs_get_byte sslscan.c /^unsigned char bs_get_byte(bs *b, size_t offset) {$/;" f typeref:typename:unsigned char bs_get_bytes sslscan.c /^unsigned char *bs_get_bytes(bs *b) {$/;" f typeref:typename:unsigned char * bs_get_len sslscan.c /^size_t bs_get_len(bs *b) {$/;" f typeref:typename:size_t bs_get_size sslscan.c /^size_t bs_get_size(bs *b) {$/;" f typeref:typename:size_t bs_new sslscan.c /^void bs_new(bs **b) {$/;" f typeref:typename:void bs_new_size sslscan.c /^void bs_new_size(bs **b, size_t new_size) {$/;" f typeref:typename:void bs_read_socket sslscan.c /^int bs_read_socket(bs *b, int s, size_t num_bytes) {$/;" f typeref:typename:int bs_set_byte sslscan.c /^void bs_set_byte(bs *b, size_t offset, unsigned char byte) {$/;" f typeref:typename:void bs_set_ushort sslscan.c /^void bs_set_ushort(bs *b, size_t offset, unsigned short length) {$/;" f typeref:typename:void buf sslscan.h /^ unsigned char *buf;$/;" m struct:_bs typeref:typename:unsigned char * byKey sslscan.h /^ ASN1_OCTET_STRING *byKey;$/;" m union:ocsp_responder_id_st::__anonf49f55d2010a typeref:typename:ASN1_OCTET_STRING * byName sslscan.h /^ X509_NAME *byName;$/;" m union:ocsp_responder_id_st::__anonf49f55d2010a typeref:typename:X509_NAME * certId sslscan.h /^ OCSP_CERTID *certId;$/;" m struct:ocsp_single_response_st typeref:typename:OCSP_CERTID * certStatus sslscan.h /^ OCSP_CERTSTATUS *certStatus;$/;" m struct:ocsp_single_response_st typeref:typename:OCSP_CERTSTATUS * checkCertificate sslscan.c /^int checkCertificate(struct sslCheckOptions *options, const SSL_METHOD *sslMethod)$/;" f typeref:typename:int checkCertificate sslscan.h /^ int checkCertificate;$/;" m struct:sslCheckOptions typeref:typename:int checkCertificateProtocol sslscan.c /^int checkCertificateProtocol(struct sslCheckOptions *options, const SSL_METHOD *sslMethod)$/;" f typeref:typename:int checkIfTLSVersionIsSupported sslscan.c /^unsigned int checkIfTLSVersionIsSupported(struct sslCheckOptions *options, unsigned int tls_vers/;" f typeref:typename:unsigned int cipherRemove sslscan.c /^char *cipherRemove(char *str, const char *sub) {$/;" f typeref:typename:char * cipher_details sslscan.h /^ int cipher_details;$/;" m struct:sslCheckOptions typeref:typename:int ciphers sslscan.h /^ struct sslCipher *ciphers;$/;" m struct:sslCheckOptions typeref:struct:sslCipher * cipherstring sslscan.h /^ char cipherstring[65536];$/;" m struct:sslCheckOptions typeref:typename:char[65536] ciphersuites sslscan.h /^ int ciphersuites;$/;" m struct:sslCheckOptions typeref:typename:int clientCertsFile sslscan.h /^ char *clientCertsFile;$/;" m struct:sslCheckOptions typeref:typename:char * close sslscan.c /^ #define close /;" d file: color sslscan.c /^ char *color;$/;" m struct:testSignatureAlgorithms::signature_algorithm typeref:typename:char * file: color sslscan.c /^ char *color;$/;" m struct:testSupportedGroups::group_key_exchange typeref:typename:char * file: compression sslscan.h /^ int compression;$/;" m struct:sslCheckOptions typeref:typename:int ctx sslscan.h /^ SSL_CTX *ctx;$/;" m struct:sslCheckOptions typeref:typename:SSL_CTX * description sslscan.h /^ char description[512];$/;" m struct:sslCipher typeref:typename:char[512] fallback sslscan.h /^ int fallback;$/;" m struct:sslCheckOptions typeref:typename:int false sslscan.h /^#define false /;" d fileExists sslscan.c /^int fileExists(char *fileName)$/;" f typeref:typename:int findMissingCiphers sslscan.c /^void findMissingCiphers() {$/;" f typeref:typename:void freeRenegotiationOutput sslscan.c /^int freeRenegotiationOutput( struct renegotiationOutput *myRenOut )$/;" f typeref:typename:int getPrintableTLSName sslscan.c /^char *getPrintableTLSName(unsigned int tls_version) {$/;" f typeref:typename:char * getServerHello sslscan.c /^bs *getServerHello(int s) {$/;" f typeref:typename:bs * getTLSHandshakeRecord sslscan.c /^bs *getTLSHandshakeRecord(int s) {$/;" f typeref:typename:bs * good sslscan.h /^ ASN1_NULL *good;$/;" m union:ocsp_cert_status_st::__anonf49f55d2020a typeref:typename:ASN1_NULL * group_bit_strength sslscan.c /^ unsigned int group_bit_strength; \/* The bit strength equivalent of this group. *\/$/;" m struct:testSupportedGroups::group_key_exchange typeref:typename:unsigned int file: group_id sslscan.c /^ uint16_t group_id;$/;" m struct:testSupportedGroups::group_key_exchange typeref:typename:uint16_t file: group_key_exchange sslscan.c /^ struct group_key_exchange {$/;" s function:testSupportedGroups file: group_name sslscan.c /^ char *group_name;$/;" m struct:testSupportedGroups::group_key_exchange typeref:typename:char * file: groups sslscan.h /^ int groups;$/;" m struct:sslCheckOptions typeref:typename:int h_addrtype sslscan.h /^ short h_addrtype;$/;" m struct:sslCheckOptions typeref:typename:short hashAlgorithm sslscan.h /^ X509_ALGOR hashAlgorithm;$/;" m struct:ocsp_cert_id_st typeref:typename:X509_ALGOR heartbleed sslscan.h /^ int heartbleed;$/;" m struct:sslCheckOptions typeref:typename:int host sslscan.h /^ char host[512];$/;" m struct:sslCheckOptions typeref:typename:char[512] http sslscan.h /^ int http;$/;" m struct:sslCheckOptions typeref:typename:int ipv4 sslscan.h /^ int ipv4;$/;" m struct:sslCheckOptions typeref:typename:int ipv6 sslscan.h /^ int ipv6;$/;" m struct:sslCheckOptions typeref:typename:int issuerKeyHash sslscan.h /^ ASN1_OCTET_STRING issuerKeyHash;$/;" m struct:ocsp_cert_id_st typeref:typename:ASN1_OCTET_STRING issuerNameHash sslscan.h /^ ASN1_OCTET_STRING issuerNameHash;$/;" m struct:ocsp_cert_id_st typeref:typename:ASN1_OCTET_STRING key_exchange_len sslscan.c /^ uint16_t key_exchange_len;$/;" m struct:testSupportedGroups::group_key_exchange typeref:typename:uint16_t file: len sslscan.h /^ size_t len; \/* The number of bytes currently in the buffer. *\/$/;" m struct:_bs typeref:typename:size_t loadCerts sslscan.c /^int loadCerts(struct sslCheckOptions *options)$/;" f typeref:typename:int main sslscan.c /^int main(int argc, char *argv[])$/;" f typeref:typename:int makeCiphersuiteListAll sslscan.c /^bs *makeCiphersuiteListAll(unsigned int tls_version) {$/;" f typeref:typename:bs * makeCiphersuiteListMissing sslscan.c /^bs *makeCiphersuiteListMissing(unsigned int tls_version) {$/;" f typeref:typename:bs * makeCiphersuiteListTLS13All sslscan.c /^bs *makeCiphersuiteListTLS13All() {$/;" f typeref:typename:bs * makeClientHello sslscan.c /^bs *makeClientHello(struct sslCheckOptions *options, unsigned int tls_version, bs *ciphersuite_l/;" f typeref:typename:bs * makeTLSExtensions sslscan.c /^bs *makeTLSExtensions(struct sslCheckOptions *options, unsigned int include_signature_algorithms/;" f typeref:typename:bs * markFoundCiphersuite sslscan.c /^void markFoundCiphersuite(unsigned short server_cipher_id, unsigned int tls_version) {$/;" f typeref:typename:void memmem sslscan.c /^void *memmem(const void *haystack_start, size_t haystack_len, const void *needle, size_t needle_/;" f typeref:typename:void * mode_help sslscan.h /^#define mode_help /;" d mode_multiple sslscan.h /^#define mode_multiple /;" d mode_single sslscan.h /^#define mode_single /;" d mode_version sslscan.h /^#define mode_version /;" d name sslscan.h /^ const char *name;$/;" m struct:sslCipher typeref:typename:const char * newRenegotiationOutput sslscan.c /^struct renegotiationOutput * newRenegotiationOutput( void )$/;" f typeref:struct:renegotiationOutput * new_CTX sslscan.c /^SSL_CTX *new_CTX(const SSL_METHOD *method) {$/;" f typeref:typename:SSL_CTX * new_SSL sslscan.c /^SSL *new_SSL(SSL_CTX *ctx) {$/;" f typeref:typename:SSL * next sslscan.h /^ struct sslCipher *next;$/;" m struct:sslCipher typeref:struct:sslCipher * nextUpdate sslscan.h /^ ASN1_GENERALIZEDTIME *nextUpdate;$/;" m struct:ocsp_single_response_st typeref:typename:ASN1_GENERALIZEDTIME * nid sslscan.c /^ int nid; \/* NID for group, or -1 for X25519\/X448. *\/$/;" m struct:testSupportedGroups::group_key_exchange typeref:typename:int file: nid_type sslscan.c /^ unsigned int nid_type; \/* One of the NID_TYPE_* flags. *\/$/;" m struct:testSupportedGroups::group_key_exchange typeref:typename:unsigned int file: ocspRequest sslscan.c /^int ocspRequest(struct sslCheckOptions *options)$/;" f typeref:typename:int ocspStatus sslscan.h /^ int ocspStatus;$/;" m struct:sslCheckOptions typeref:typename:int ocsp_basic_response_st sslscan.h /^struct ocsp_basic_response_st {$/;" s ocsp_cert_id_st sslscan.h /^struct ocsp_cert_id_st {$/;" s ocsp_cert_status_st sslscan.h /^struct ocsp_cert_status_st {$/;" s ocsp_certid_print sslscan.c /^int ocsp_certid_print(BIO *bp, OCSP_CERTID *a, int indent)$/;" f typeref:typename:int ocsp_resp_bytes_st sslscan.h /^struct ocsp_resp_bytes_st {$/;" s ocsp_resp_cb sslscan.c /^static int ocsp_resp_cb(SSL *s, void *unused) {$/;" f typeref:typename:int file: ocsp_responder_id_st sslscan.h /^struct ocsp_responder_id_st {$/;" s ocsp_response_data_st sslscan.h /^struct ocsp_response_data_st {$/;" s ocsp_response_st sslscan.h /^struct ocsp_response_st {$/;" s ocsp_revoked_info_st sslscan.h /^struct ocsp_revoked_info_st {$/;" s ocsp_single_response_st sslscan.h /^struct ocsp_single_response_st {$/;" s outputCipher sslscan.c /^void outputCipher(struct sslCheckOptions *options, SSL *ssl, const char *cleanSslMethod, uint32_/;" f typeref:typename:void outputRenegotiation sslscan.c /^int outputRenegotiation( struct sslCheckOptions *options, struct renegotiationOutput *outputData/;" f typeref:typename:int password_callback sslscan.c /^static int password_callback(char *buf, int size, int rwflag, void *userdata)$/;" f typeref:typename:int file: populateCipherList sslscan.c /^int populateCipherList(struct sslCheckOptions *options, const SSL_METHOD *sslMethod)$/;" f typeref:typename:int port sslscan.h /^ int port;$/;" m struct:sslCheckOptions typeref:typename:int printableSslMethod sslscan.c /^const char* printableSslMethod(const SSL_METHOD *sslMethod)$/;" f typeref:typename:const char * printf sslscan.h /^#define printf(/;" d printf_error sslscan.h /^#define printf_error(/;" d printf_verbose sslscan.h /^#define printf_verbose(/;" d printf_xml sslscan.h /^#define printf_xml(/;" d privateKeyFile sslscan.h /^ char *privateKeyFile;$/;" m struct:sslCheckOptions typeref:typename:char * privateKeyPassword sslscan.h /^ char *privateKeyPassword;$/;" m struct:sslCheckOptions typeref:typename:char * producedAt sslscan.h /^ ASN1_GENERALIZEDTIME *producedAt;$/;" m struct:ocsp_response_data_st typeref:typename:ASN1_GENERALIZEDTIME * program_banner sslscan.h /^const char *program_banner = " _\\n"$/;" v typeref:typename:const char * rdp sslscan.h /^ int rdp;$/;" m struct:sslCheckOptions typeref:typename:int readLine sslscan.c /^void readLine(FILE *input, char *lineFromFile, int maxSize)$/;" f typeref:typename:void readOrLogAndClose sslscan.c /^int readOrLogAndClose(int fd, void* buffer, size_t len, const struct sslCheckOptions *options)$/;" f typeref:typename:int reneg sslscan.h /^ int reneg;$/;" m struct:sslCheckOptions typeref:typename:int renegotiationOutput sslscan.h /^struct renegotiationOutput$/;" s resolveCipherID sslscan.c /^char *resolveCipherID(unsigned short cipher_id, int *cipher_bits) {$/;" f typeref:typename:char * responderId sslscan.h /^ OCSP_RESPID responderId;$/;" m struct:ocsp_response_data_st typeref:typename:OCSP_RESPID response sslscan.h /^ ASN1_OCTET_STRING *response;$/;" m struct:ocsp_resp_bytes_st typeref:typename:ASN1_OCTET_STRING * responseBytes sslscan.h /^ OCSP_RESPBYTES *responseBytes;$/;" m struct:ocsp_response_st typeref:typename:OCSP_RESPBYTES * responseStatus sslscan.h /^ ASN1_ENUMERATED *responseStatus;$/;" m struct:ocsp_response_st typeref:typename:ASN1_ENUMERATED * responseType sslscan.h /^ ASN1_OBJECT *responseType;$/;" m struct:ocsp_resp_bytes_st typeref:typename:ASN1_OBJECT * revocationReason sslscan.h /^ ASN1_ENUMERATED *revocationReason;$/;" m struct:ocsp_revoked_info_st typeref:typename:ASN1_ENUMERATED * revocationTime sslscan.h /^ ASN1_GENERALIZEDTIME *revocationTime;$/;" m struct:ocsp_revoked_info_st typeref:typename:ASN1_GENERALIZEDTIME * revoked sslscan.h /^ OCSP_REVOKEDINFO *revoked;$/;" m union:ocsp_cert_status_st::__anonf49f55d2020a typeref:typename:OCSP_REVOKEDINFO * runSSLv2Test sslscan.c /^int runSSLv2Test(struct sslCheckOptions *options) {$/;" f typeref:typename:int runSSLv3Test sslscan.c /^int runSSLv3Test(struct sslCheckOptions *options) {$/;" f typeref:typename:int secure sslscan.h /^ int secure;$/;" m struct:renegotiationOutput typeref:typename:int security_callback_allow_all sslscan.c /^static int security_callback_allow_all(const SSL *s, const SSL_CTX *ctx, int op, int bits, int n/;" f typeref:typename:int file: sendString sslscan.c /^ssize_t sendString(int sockfd, const char str[])$/;" f typeref:typename:ssize_t serialNumber sslscan.h /^ ASN1_INTEGER serialNumber;$/;" m struct:ocsp_cert_id_st typeref:typename:ASN1_INTEGER serverAddress sslscan.h /^ struct sockaddr_in serverAddress;$/;" m struct:sslCheckOptions typeref:struct:sockaddr_in serverAddress6 sslscan.h /^ struct sockaddr_in6 serverAddress6;$/;" m struct:sslCheckOptions typeref:struct:sockaddr_in6 setCipherSuite sslscan.c /^int setCipherSuite(struct sslCheckOptions *options, const SSL_METHOD *sslMethod, const char *str/;" f typeref:typename:int showCertificate sslscan.c /^int showCertificate(struct sslCheckOptions *options)$/;" f typeref:typename:int showCertificate sslscan.h /^ int showCertificate;$/;" m struct:sslCheckOptions typeref:typename:int showCipherIds sslscan.h /^ int showCipherIds;$/;" m struct:sslCheckOptions typeref:typename:int showClientCiphers sslscan.h /^ int showClientCiphers;$/;" m struct:sslCheckOptions typeref:typename:int showTimes sslscan.h /^ int showTimes;$/;" m struct:sslCheckOptions typeref:typename:int showTrustedCAs sslscan.c /^int showTrustedCAs(struct sslCheckOptions *options)$/;" f typeref:typename:int showTrustedCAs sslscan.h /^ int showTrustedCAs;$/;" m struct:sslCheckOptions typeref:typename:int sig_id sslscan.c /^ uint16_t sig_id;$/;" m struct:testSignatureAlgorithms::signature_algorithm typeref:typename:uint16_t file: sig_name sslscan.c /^ char *sig_name;$/;" m struct:testSignatureAlgorithms::signature_algorithm typeref:typename:char * file: signature sslscan.h /^ ASN1_BIT_STRING *signature;$/;" m struct:ocsp_basic_response_st typeref:typename:ASN1_BIT_STRING * signatureAlgorithm sslscan.h /^ X509_ALGOR signatureAlgorithm;$/;" m struct:ocsp_basic_response_st typeref:typename:X509_ALGOR signature_algorithm sslscan.c /^ struct signature_algorithm {$/;" s function:testSignatureAlgorithms file: signature_algorithms sslscan.h /^ int signature_algorithms;$/;" m struct:sslCheckOptions typeref:typename:int size sslscan.h /^ size_t size; \/* The size of the allocated buffer. *\/$/;" m struct:_bs typeref:typename:size_t sleep sslscan.h /^ unsigned int sleep;$/;" m struct:sslCheckOptions typeref:typename:unsigned int sniname sslscan.h /^ char sniname[512];$/;" m struct:sslCheckOptions typeref:typename:char[512] snprintf sslscan.c /^ #define snprintf /;" d file: ssize_t sslscan.c /^ typedef int ssize_t;$/;" t typeref:typename:int file: sslCheckOptions sslscan.h /^struct sslCheckOptions$/;" s sslCipher sslscan.h /^struct sslCipher$/;" s sslMethod sslscan.h /^ const SSL_METHOD *sslMethod;$/;" m struct:sslCipher typeref:typename:const SSL_METHOD * sslVersion sslscan.h /^ int sslVersion;$/;" m struct:sslCheckOptions typeref:typename:int ssl_all sslscan.h /^#define ssl_all /;" d ssl_print_tmp_key sslscan.c /^int ssl_print_tmp_key(struct sslCheckOptions *options, SSL *s)$/;" f typeref:typename:int ssl_v2 sslscan.h /^#define ssl_v2 /;" d ssl_v3 sslscan.h /^#define ssl_v3 /;" d sslbugs sslscan.h /^ int sslbugs;$/;" m struct:sslCheckOptions typeref:typename:int starttls_ftp sslscan.h /^ int starttls_ftp;$/;" m struct:sslCheckOptions typeref:typename:int starttls_imap sslscan.h /^ int starttls_imap;$/;" m struct:sslCheckOptions typeref:typename:int starttls_irc sslscan.h /^ int starttls_irc;$/;" m struct:sslCheckOptions typeref:typename:int starttls_ldap sslscan.h /^ int starttls_ldap;$/;" m struct:sslCheckOptions typeref:typename:int starttls_mysql sslscan.h /^ int starttls_mysql;$/;" m struct:sslCheckOptions typeref:typename:int starttls_pop3 sslscan.h /^ int starttls_pop3;$/;" m struct:sslCheckOptions typeref:typename:int starttls_psql sslscan.h /^ int starttls_psql;$/;" m struct:sslCheckOptions typeref:typename:int starttls_smtp sslscan.h /^ int starttls_smtp;$/;" m struct:sslCheckOptions typeref:typename:int starttls_xmpp sslscan.h /^ int starttls_xmpp;$/;" m struct:sslCheckOptions typeref:typename:int supported sslscan.h /^ int supported;$/;" m struct:renegotiationOutput typeref:typename:int targets sslscan.h /^ int targets;$/;" m struct:sslCheckOptions typeref:typename:int tbsResponseData sslscan.h /^ OCSP_RESPDATA tbsResponseData;$/;" m struct:ocsp_basic_response_st typeref:typename:OCSP_RESPDATA tcpConnect sslscan.c /^int tcpConnect(struct sslCheckOptions *options)$/;" f typeref:typename:int testCipher sslscan.c /^int testCipher(struct sslCheckOptions *options, const SSL_METHOD *sslMethod)$/;" f typeref:typename:int testCompression sslscan.c /^int testCompression(struct sslCheckOptions *options, const SSL_METHOD *sslMethod)$/;" f typeref:typename:int testConnection sslscan.c /^int testConnection(struct sslCheckOptions *options)$/;" f typeref:typename:int testFallback sslscan.c /^int testFallback(struct sslCheckOptions *options, const SSL_METHOD *sslMethod)$/;" f typeref:typename:int testHeartbleed sslscan.c /^int testHeartbleed(struct sslCheckOptions *options, const SSL_METHOD *sslMethod)$/;" f typeref:typename:int testHost sslscan.c /^int testHost(struct sslCheckOptions *options)$/;" f typeref:typename:int testMissingCiphers sslscan.c /^int testMissingCiphers(struct sslCheckOptions *options, unsigned int tls_version) {$/;" f typeref:typename:int testProtocolCiphers sslscan.c /^int testProtocolCiphers(struct sslCheckOptions *options, const SSL_METHOD *sslMethod)$/;" f typeref:typename:int testRenegotiation sslscan.c /^int testRenegotiation(struct sslCheckOptions *options, const SSL_METHOD *sslMethod)$/;" f typeref:typename:int testSignatureAlgorithms sslscan.c /^int testSignatureAlgorithms(struct sslCheckOptions *options) {$/;" f typeref:typename:int testSupportedGroups sslscan.c /^int testSupportedGroups(struct sslCheckOptions *options) {$/;" f typeref:typename:int thisUpdate sslscan.h /^ ASN1_GENERALIZEDTIME *thisUpdate;$/;" m struct:ocsp_single_response_st typeref:typename:ASN1_GENERALIZEDTIME * timeout sslscan.h /^ struct timeval timeout;$/;" m struct:sslCheckOptions typeref:struct:timeval timersub sslscan.c /^ #define timersub(/;" d file: tls10_supported sslscan.h /^ unsigned int tls10_supported;$/;" m struct:sslCheckOptions typeref:typename:unsigned int tls11_supported sslscan.h /^ unsigned int tls11_supported;$/;" m struct:sslCheckOptions typeref:typename:unsigned int tls12_supported sslscan.h /^ unsigned int tls12_supported;$/;" m struct:sslCheckOptions typeref:typename:unsigned int tls13_supported sslscan.h /^ unsigned int tls13_supported;$/;" m struct:sslCheckOptions typeref:typename:unsigned int tlsExtensionAddDefaultKeyShare sslscan.c /^void tlsExtensionAddDefaultKeyShare(bs *tls_extensions) {$/;" f typeref:typename:void tlsExtensionAddTLSv1_3 sslscan.c /^void tlsExtensionAddTLSv1_3(bs *tls_extensions) {$/;" f typeref:typename:void tlsExtensionUpdateLength sslscan.c /^void tlsExtensionUpdateLength(bs *tls_extensions) {$/;" f typeref:typename:void tls_all sslscan.h /^#define tls_all /;" d tls_reneg_init sslscan.c /^void tls_reneg_init(struct sslCheckOptions *options)$/;" f typeref:typename:void tls_v10 sslscan.h /^#define tls_v10 /;" d tls_v11 sslscan.h /^#define tls_v11 /;" d tls_v12 sslscan.h /^#define tls_v12 /;" d tls_v13 sslscan.h /^#define tls_v13 /;" d true sslscan.h /^#define true /;" d type sslscan.h /^ int type;$/;" m struct:ocsp_cert_status_st typeref:typename:int type sslscan.h /^ int type;$/;" m struct:ocsp_responder_id_st typeref:typename:int unknown sslscan.h /^ ASN1_NULL *unknown;$/;" m union:ocsp_cert_status_st::__anonf49f55d2020a typeref:typename:ASN1_NULL * use_unsafe_renegotiation_flag sslscan.c /^static int use_unsafe_renegotiation_flag = 0;$/;" v typeref:typename:int file: use_unsafe_renegotiation_op sslscan.c /^static int use_unsafe_renegotiation_op = 0;$/;" v typeref:typename:int file: value sslscan.h /^ } value;$/;" m struct:ocsp_cert_status_st typeref:union:ocsp_cert_status_st::__anonf49f55d2020a value sslscan.h /^ } value;$/;" m struct:ocsp_responder_id_st typeref:union:ocsp_responder_id_st::__anonf49f55d2010a verbose sslscan.h /^ int verbose;$/;" m struct:sslCheckOptions typeref:typename:int version sslscan.h /^ ASN1_INTEGER *version;$/;" m struct:ocsp_response_data_st typeref:typename:ASN1_INTEGER * version sslscan.h /^ const char *version;$/;" m struct:sslCipher typeref:typename:const char * xmlOutput sslscan.h /^ FILE *xmlOutput;$/;" m struct:sslCheckOptions typeref:typename:FILE * xml_to_stdout sslscan.c /^static int xml_to_stdout = 0;$/;" v typeref:typename:int file: xmpp_server sslscan.h /^ int xmpp_server;$/;" m struct:sslCheckOptions typeref:typename:int sslscan-2.1.2/tools/000077500000000000000000000000001452476416400143375ustar00rootroot00000000000000sslscan-2.1.2/tools/iana_tls_ciphersuite_parser.py000077500000000000000000000063511452476416400224730ustar00rootroot00000000000000#!/usr/bin/python3 # # Copyright (C) 2019 Joe Testa # # This tool will parse the list of TLS ciphersuites from IANA # (https://www.iana.org/assignments/tls-parameters/tls-parameters.xml) into a C-struct # for use in missing_ciphersuites.h. # import csv, sys from datetime import date # We must be given a path to a CSV file with the ciphersuites. It can be obtained from # . if len(sys.argv) != 2: print("\nUsage: %s tls_ciphers.csv\n\nHint: copy the TLS table in CSV format from .\n" % sys.argv[0]) exit(0) csv_file = sys.argv[1] print("/* Auto-generated by %s on %s. */" % (sys.argv[0], date.today().strftime("%B %d, %Y"))) print("struct missing_ciphersuite missing_ciphersuites[] = {") with open(csv_file, 'r') as f: reader = csv.reader(f) for row in reader: id = row[0] cipher_name = row[1] # Skip the header. if '0x' not in id: continue # Skip reserved or unassigned ranges. Also skip SCSV ciphers. if ('Reserved' in cipher_name) or ('Unassigned' in cipher_name) or ('TLS_FALLBACK_SCSV' in cipher_name) or ('TLS_EMPTY_RENEGOTIATION_INFO_SCSV' in cipher_name): continue # Convert '0xC0,0x87' to '0xC087' parsed_id = id[0:4] + id[7:9] if len(parsed_id) != 6: print("Error: parsed ID is not length 6: %s" % parsed_id) exit -1 # Make an educated guess of the cipher's bit strength based on its name. bits = -1 if 'AES_128' in cipher_name: bits = 128 elif 'AES_256' in cipher_name: bits = 256 elif 'CHACHA20' in cipher_name: bits = 256 elif 'CAMELLIA_128' in cipher_name: bits = 128 elif 'CAMELLIA_256' in cipher_name: bits = 256 elif 'ARIA_128' in cipher_name: bits = 128 elif 'ARIA_256' in cipher_name: bits = 256 elif '3DES' in cipher_name: bits = 112 elif 'DES40' in cipher_name: bits = 40 elif '_DES_' in cipher_name: bits = 56 elif 'RC4_128' in cipher_name: bits = 128 elif 'RC4_40' in cipher_name: bits = 40 elif 'IDEA' in cipher_name: bits = 128 elif '_RC2_' in cipher_name: bits = 40 elif 'GOSTR341112_256' in cipher_name: bits = 256 elif '_SM4_' in cipher_name: # See http://www.gmbz.org.cn/upload/2018-04-04/1522788048733065051.pdf bits = 128 print(' {%s, "%s", %d, VALL, 0},' % (parsed_id, cipher_name, bits)) # These ciphers are reserved for private use. Kind of like the 10.0.0.0/8 IPv4 # addresses. print("\n /* The ciphers below are reserved for private use (see RFC8446). */") for i in range(0, 256): low_byte = hex(i)[2:].upper() if len(low_byte) == 1: low_byte = '0' + low_byte parsed_id = '0xFF' + low_byte cipher_name = 'PRIVATE_CIPHER_%d' % i bits = -1 print(' {%s, "%s", %d, VALL, 0},' % (parsed_id, cipher_name, bits)) print("};") exit 0 sslscan-2.1.2/tools/iana_tls_supported_groups_parser.py000077500000000000000000000111501452476416400235640ustar00rootroot00000000000000#!/usr/bin/python3 # # Copyright (C) 2019 Joe Testa # # This tool will parse the list of TLS supported groups from IANA # (https://www.iana.org/assignments/tls-parameters/tls-parameters-8.csv) into a C-struct # for use in testSupportedGroups(). # import csv, sys from datetime import date # We must be given a path to a CSV file with the groups. It can be obtained from # . if len(sys.argv) != 2: print("\nUsage: %s tls_ciphers.csv\n\nHint: copy the TLS table in CSV format from .\n" % sys.argv[0]) exit(0) csv_file = sys.argv[1] print() print(" /* Auto-generated by %s on %s. */" % (sys.argv[0], date.today().strftime("%B %d, %Y"))) print('#define COL_PLAIN ""') print('#define NID_TYPE_NA 0 /* Not Applicable (i.e.: X25519/X448) */') print('#define NID_TYPE_ECDHE 1 /* For ECDHE curves (sec*, P-256/384-521) */') print('#define NID_TYPE_DHE 2 /* For ffdhe* */') print(" /* Bit strength of DHE 2048 and 3072-bit moduli is taken directly from NIST SP 800-57 pt.1, rev4., pg. 53; DHE 4096, 6144, and 8192 are estimated using that document. */") print(" struct group_key_exchange group_key_exchanges[] = {") with open(csv_file, 'r') as f: reader = csv.reader(f) for row in reader: id = row[0] group_name = row[1] reference = row[4] # Skip the header. try: int(id) except ValueError as e: continue id = int(id) # Skip reserved or unassigned IDs. if group_name in ('Reserved', 'Unassigned'): continue # The Reference field looks like "[RFC1234]", "[draft-blah-blah]", or "[RFC-ietf-tls-blah-02]". Skip all rows that aren't of the "[RFC1234]" variety. reference = reference[1:] rt_bracket_pos = reference.find(']') if rt_bracket_pos == -1: print("Warning: can't parse reference: %s" % reference) else: reference = reference[3:rt_bracket_pos] try: int(reference) except ValueError as e: continue bits = 0 nid = "NID_x" nid_type = "NID_TYPE_x" key_exchange_len = 0 color = "COL_PLAIN" if group_name.startswith('sec'): bits = int(group_name[4:-2]) / 2 nid = "NID_%s" % group_name nid_type = "NID_TYPE_ECDHE" if group_name == "secp192r1": nid = "NID_X9_62_prime192v1" elif group_name == "secp256r1": nid = "NID_X9_62_prime256v1" group_name += ' (NIST P-256)' elif group_name == "secp256k1": color = "COL_GREEN" # This is the very well-tested Bitcoin curve. elif group_name == "secp384r1": group_name += ' (NIST P-384)' elif group_name == "secp521r1": group_name += ' (NIST P-521)' elif group_name.startswith('brainpoolP'): bits = int(group_name[10:-2]) / 2 nid = "NID_%s" % group_name nid_type = "NID_TYPE_ECDHE" elif group_name in ('x25519', 'x448'): color = "COL_GREEN" nid = "-1" nid_type = "NID_TYPE_NA" if group_name == 'x25519': bits = 128 key_exchange_len = 32 elif group_name == 'x448': bits = 224 key_exchange_len = 56 elif group_name.startswith('ffdhe'): # Bit strength of DHE 2048 and 3072-bit moduli is taken directly from NIST SP 800-57 pt.1, rev4., pg. 53; DHE 4096, 6144, and 8192 are estimated using that document. if group_name == 'ffdhe2048': bits = 112 key_exchange_len = 256 elif group_name == 'ffdhe3072': bits = 128 key_exchange_len = 384 elif group_name == 'ffdhe4096': bits = 150 key_exchange_len = 512 elif group_name == 'ffdhe6144': bits = 175 key_exchange_len = 768 elif group_name == 'ffdhe8192': bits = 192 key_exchange_len = 1024 nid = "NID_%s" % group_name nid_type = "NID_TYPE_DHE" elif group_name.startswith('arbitrary_'): # Skip these two. continue if bits < 112: color = "COL_RED" print(' {0x%04x, "%s", %d, %s, %s, %s, %d},' % (id, group_name, bits, color, nid, nid_type, key_exchange_len)) print(" };") print() exit(0) sslscan-2.1.2/win32bit-compat.h000066400000000000000000000124421452476416400162750ustar00rootroot00000000000000/* The file below was copied from glibc v2.26 (resolv/inet_ntop.c). */ /* This is needed for legacy 32-bit Windows builds only. */ #include typedef unsigned char u_char; #define __set_errno(X) #define libc_hidden_def(X) #define internal_function #define NS_IN6ADDRSZ 16 #define NS_INT16SZ 2 /* * Copyright (c) 1996-1999 by Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. */ #include #include /*#include #include #include #include */ #include #include #include #ifdef SPRINTF_CHAR # define SPRINTF(x) strlen(sprintf/**/x) #else # define SPRINTF(x) ((size_t)sprintf x) #endif /* * WARNING: Don't even consider trying to compile this on a system where * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. */ static const char *inet_ntop4 (const u_char *src, char *dst, socklen_t size) internal_function; static const char *inet_ntop6 (const u_char *src, char *dst, socklen_t size) internal_function; /* char * * inet_ntop(af, src, dst, size) * convert a network format address to presentation format. * return: * pointer to presentation format address (`dst'), or NULL (see errno). * author: * Paul Vixie, 1996. */ const char * inet_ntop (int af, const void *src, char *dst, socklen_t size) { switch (af) { case AF_INET: return (inet_ntop4(src, dst, size)); case AF_INET6: return (inet_ntop6(src, dst, size)); default: __set_errno (EAFNOSUPPORT); return (NULL); } /* NOTREACHED */ } libc_hidden_def (inet_ntop) /* const char * * inet_ntop4(src, dst, size) * format an IPv4 address * return: * `dst' (as a const) * notes: * (1) uses no statics * (2) takes a u_char* not an in_addr as input * author: * Paul Vixie, 1996. */ static const char * internal_function inet_ntop4 (const u_char *src, char *dst, socklen_t size) { static const char fmt[] = "%u.%u.%u.%u"; char tmp[sizeof "255.255.255.255"]; if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) >= size) { __set_errno (ENOSPC); return (NULL); } return strcpy(dst, tmp); } /* const char * * inet_ntop6(src, dst, size) * convert IPv6 binary address into presentation (printable) format * author: * Paul Vixie, 1996. */ static const char * internal_function inet_ntop6 (const u_char *src, char *dst, socklen_t size) { /* * Note that int32_t and int16_t need only be "at least" large enough * to contain a value of the specified size. On some systems, like * Crays, there is no such thing as an integer variable with 16 bits. * Keep this in mind if you think this function should have been coded * to use pointer overlays. All the world's not a VAX. */ char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp; struct { int base, len; } best, cur; u_int words[NS_IN6ADDRSZ / NS_INT16SZ]; int i; /* * Preprocess: * Copy the input (bytewise) array into a wordwise array. * Find the longest run of 0x00's in src[] for :: shorthanding. */ memset(words, '\0', sizeof words); for (i = 0; i < NS_IN6ADDRSZ; i += 2) words[i / 2] = (src[i] << 8) | src[i + 1]; best.base = -1; cur.base = -1; best.len = 0; cur.len = 0; for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { if (words[i] == 0) { if (cur.base == -1) cur.base = i, cur.len = 1; else cur.len++; } else { if (cur.base != -1) { if (best.base == -1 || cur.len > best.len) best = cur; cur.base = -1; } } } if (cur.base != -1) { if (best.base == -1 || cur.len > best.len) best = cur; } if (best.base != -1 && best.len < 2) best.base = -1; /* * Format the result. */ tp = tmp; for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { /* Are we inside the best run of 0x00's? */ if (best.base != -1 && i >= best.base && i < (best.base + best.len)) { if (i == best.base) *tp++ = ':'; continue; } /* Are we following an initial run of 0x00s or any real hex? */ if (i != 0) *tp++ = ':'; /* Is this address an encapsulated IPv4? */ if (i == 6 && best.base == 0 && (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp))) return (NULL); tp += strlen(tp); break; } tp += SPRINTF((tp, "%x", words[i])); } /* Was it a trailing run of 0x00's? */ if (best.base != -1 && (best.base + best.len) == (NS_IN6ADDRSZ / NS_INT16SZ)) *tp++ = ':'; *tp++ = '\0'; /* * Check for overflow, copy, and we're done. */ if ((socklen_t)(tp - tmp) > size) { __set_errno (ENOSPC); return (NULL); } return strcpy(dst, tmp); }