This commit makes some minor improvements to code that converts ASCII-HEX to binary.
First, testssl.sh currently has two functions that do the same thing: asciihex_to_binary() and hex2ascii(). This commit all calls to either of these functions with calls to hex2binary(), which is based on the current asciihex_to_binary().
This commit also changes direct use of printf to calls to hex2ascii() in generate-ccm-counter-blocks(), ccm-compute-tag(), and generate_gcm_counter().
Finally, this commit cleans up the implemention of hex2binary() a bit and introduces the option to use xxd, if that program is available. Using xxd rather than multiple calls to printf has a couple of advantages. xxd is a bit faster. However, the primary advantage is that when debugging (i.e., using bash -x), each call to hex2binary() only includes a few steps, regardless of how long the string is, whereas using printf the call to hex2binary() could take hundreds of steps.
Modify sclient_auth() to use checks similar to sclient_connect_successful() to determine whether the connection attempt was successful. Replace uses of awk and grep with Bash internals string comparisons.
This commit is a first step towards addressing #1709. It attempts to determime whether certificate-based client authentication is (1) not requested, (2) optional, or (3) required. If it is either optional or required, then it extracts the list of CA names (DNs) that the server sends in its CertificateRequest message.
The code for extracting the CA list from the CertificateRequest message seems to be working correctly. However, this commit is incomplete for a couple of reasons. First, it does not produce any new output, it just collects the information. Second, sclient_auth() needs some work.
The current sclient_auth() simply returns 0 if $OPENSSL returned 0. This may be okay if only trying to determine whether certificate-based client authentication is required. However, if it is optional, then the output will include "CertificateRequest", but $OPENSSL will return 0, since the connection was successful even though the client did not provide a certificates.
If $OPENSSL does not return 0, then sclient_auth() checks whether Master-Key is present. This works for TLS 1.2 and earlier, but not for TLS 1.3. So, sclient_auth() needs to be updated to work correctly with TLS 1.3.
The modified version of sclient_auth() will set CLIENT_AUTH and CLIENT_AUTH_CA_LIST for any version of TLS, but the remaining part of the code needs work. As I am not clear on the reason for this code, I need some help with it. Why does the code only look for "CertificateRequest" if "Master-Key" is present? Why is there a check for Session-ID in a function that is supposed to just be checking for client authentication. Why is CLIENT_AUTH set to false if SESSION-ID is absent (this is a no-op since CLIENT_AUTH would already have been false)?
See #1148 and #1805.
As noted in #1148, testssl.sh is not current designed to handle a mass testing file in which CSV, HTML, LOG, and/or JSON file names are provided in the mass testing file. If a child process receives a command line with one of the files, it assumes the same command-line option was provided to the parent so that the output of every test is being written to this one file. If this assumption is wrong, then either the file will not be created at all or it will be malformed since it will be missing header and/or footer information.
This PR partially addresses the problem by introducing new command-line arguments that are for internal use only. These command line arguments allow a child process to distinguish between a CSV, HTML, LOG, or JSON file that it is supposed to create itself versus one that is to be shared by all of the child processes.
There is one major limitation to this PR. The code for handle command-line arguments in the mass testing file is very simple and cannot handle whitespace characters, whether they are enclosed in quotes or are escaped. So, any file names included in the mass testing file cannot have whitespace characters.
... in order to be consistent with run_server_preference().
The wide formatting of other tests need some inspection and
off the top off my head are not as perfectly formatted so that
they should not run per default in wide mode.
This fixes#1779. There was a problem introduced in
3cd1273439 which counted
the size of the file name rather than the size of the
socket reply.
The helper function count_chars() is now not used anymore.
It maybe useful in the future though.
Sometimes it is needed to overwrite existing output files.
This has been requested in the past (#927). For safety reasons
it was not implemented.
However I realized that it could be useful. It requires some
responsible usage though.
Code added, help() and manpages added -- warnings added too.
While we are not sure yet how we deal with "other" colors and different
backgrounds users can have, I'll remove the light cyan here until we
settle on a standard. (other=not yellow,reds,brown,greens)
Despite the fact google doesn't support RC4 ciphers, testssl.sh called
sslv2_sockets(). Google answered with a >= TLS alert. Building a sum then
failed then in sslv2_sockets().
This fixes sslv2_sockets() and introduces count_chars() as a helper function
(tested also under old FreeBSD to make sure it works under MacOSX).
This fixes#1754 by avoiding further strings operations if the socket
reply is empty as bash 5.1 seems to have a problem with that. The fix
is done in sslv2_sockets() .
Also sslv2 is not being used in run_freak() if known not to be supported.
XMPP can be used with SNI in two contexts:
- Standard RFC 6120 STARTTLS-based connections; in that case, SNI
is most likely to be ignored, as XMPP uses another way to signal
the target domain name (via the @to attribute on the stream
header, which is already set correctly by testssl.sh). However,
setting SNI to a different value than the @to attribute may
lead to confusion.
- XEP-0368 (XMPP-over-TLS) connections which omit the STARTTLS
phase and go right for TLS (and inside that, XMPP). In that case,
SNI is obviously required to be correct. XEP-0368 specifies that
the SNI name MUST be the domain name of the service (not
necessarily the host name of the endpoint, thanks to SRV
records).
Hence, this patch forces the SNI name to be the --xmpphost value,
if --xmpphost is given. Note that it blatantly ignores whether
XMPP is used otherwise.
Travis failure was due to debug output in function which return a string.
The debug statement was removed, (stderr would have been choice \#2).
Issuer is heading now the intermediate certificate section, not
sure whethe this is redundant info.
* reorder sequence of checks in certificate info so that the chain relevant points are closer
together
* determine_cert_fingerprint_serial() doesn't need fil input anymore, thus removed that part
* cert_validityPeriod in JSON/CSV may lead to misunderstandings, thus renamed to cert_extlifeSpan
* reorganized loop for the intermediate certificate checks, so that also i is used and not the variable
which defines the number of certificates, i.e. certificates_provided. In addition made the counting
more hiuma friendly, which starts now at 1 instead of 0
* add cn and issuer_CN to the output both on screen and file
* the severity rating for intermediates are just a shot (20/40 days) and
deserve a second thought
* replace the expiry check by one test statement and make grep futile
* replace at some places "$openssl x509 -in $filename" by "$openssl x509 <<< $var"
* the thing with 25*60*60 was fie readability. When it's used >20 times it maybe is not
(and maybe costs to much time) --> replaced by $secsaday
* adjusted the loop for bad ocsp check for readability
* UI feed back for expiration date of intermediates: 20 days: HIGH, 40 days: MEDIUM
* also in JSON/CSV
* list the end date of validity
* works for >1 intermediates too
* section moved to the end of certificate_info()
* renamed <cert#${certificate_number}> --> <hostCert#${certificate_number}> to avoid coinfusion with intermediate certs
* removed blanks in return values of determine_dates_certificate
determine_dates_certificate() is now determining the important dates
of a certificate passed via argument. It works of course for host and
any other certificates.
Returning multiple parameters is being done via CSV and passed to a
read statement which seemed the best choice for bash.
ToDo:
* $expok is not set properly for intermediate certificates
* check if expired at least in the UI (JSON+CSV: echo the dates so far)
* for multiple host certificates the naming scheme (jsonID + intermediate
certnumnber kind of sucks:
"id" : "intermediate_cert_fingerprintSHA256 <cert#1> 1",
"id" : "intermediate_cert_notAfter <cert#2> 1",
The whole thing is kind of hackish as the code has been historically grown.
At some certian point we may want to reconsider how we determine properties of
certificates in certificate_info()
See #1683, #1653, #1004, #1264
* separate code for bad ocsp a bit
* output intermediate cert in json/csv
* replace sed statements from cert_fingerprint* and -serial by bash funcs
This commit adds
* a check for the elliptical curves
* and a check for TLS extensions
which will again reduces false positives.
Background:
* https://en.wikipedia.org/wiki/Comparison_of_TLS_implementations#Supported_elliptic_curves
* https://en.wikipedia.org/wiki/Comparison_of_TLS_implementations#Extensions
Also:
* Docu phrased more precise (we're not checking ciphers and
HTTP Server banner only
* As a last resort we also take 'Microsoft-HTTPAPI/2.0' as a server header on the HTTPS branch
and query the HTTP branch for Microsoft-IIS/8.x.
* $EXPERIMENTAL overrides some banner and service related checks. So that e.g. SMTP servers can also
be checked. Last but bot least ist's a vulnerability of the TLS stack.
For better debugging we'll keep the TLS extensions and offered curves in a file.
Also it adds a debug1() function which may be needed on other occasions.
Also the output is better coded as we put "check patches locally to confirm"
into a variable.
There's still room for improvement:
* More extensions (see https://raw.githubusercontent.com/cisco/joy/master/doc/using-joy-fingerprinting-00.pdf)
* We could need a separate determine_curves() function, see #1730 as otherwise
we can't use the curves in a non-default run.
Server side closed the connection but openssl retrieved
a zero exit code. In addition now we look for "closed"
and if that was returned from the server we label it
as not vulnerable.
This fixes#1725
This commit implements a detection of Winshock from 2014 (aka MS14-066, CVE-2014-6321).
It does that by analyzing
* the ciphers supported -- MS' rollup patch introduced new GCM ciphers
* AND grabbing the server banner which should match IIS 8.0 oder IIS 8.5
Admittedly this is not a strong detection. But it worked in the cases I tested
(no RDP yet). The other known method remotely testing for it against IIS is
using a patched openssl binary (see https://github.com/drwetter/testssl.sh/issues/331#issuecomment-211534954)
-- the diff "jules" (hi) provided a while back. That seems to stem from securitysift
albeit his decription was not complete and he didn't provide a PoC (I've
seen also polarssl + a little bit of python here: https://vimeo.com/112089813
The catch is securitysift's method, is not as trivial to implement and it dosses the
sass.exe process, see: http://www.securitysift.com/exploiting-ms14-066-cve-2014-6321-aka-winshock/.
* Todo: man page
This commit also removes -BB from the help. We haven't settled yet finally
where we go with short options for the cmd line for vulnerabilities. One
is for sure though: Using one letter uppercase doesn't scale. As winshock
can be executed with --WS and --winshock --BB brings that in line. For now
also -BB works (as -WS) but it isn't advertised anymore.
SERVICE global was previously set to $protocol which was
meant to set this for STARTTLS services. However it
was executes outside the corresponding if-statement.
This commit moves the statement where it belongs.
For not vulnerable hosts the low level starttls_* functions
returned an error when the STARTTLS injection was tested which
confused Travis/CI ( "Oops: STARTTLS handshake failed (code: 2)" )
* Ensured the random char generation worked under every OS supported
* Got POP3 and IMAP working
* always define SERVICE so that we can us it also for SMTP starttls injection
* fixed error in starttls_smtp_dialog where arg1 was taken as payload instead of arg2
* squashed error msg when killed socat or openssl process to avoid mess on screen
when processes already terminated
(* removed some redundant quotes at RHS if [[]] expressions)
todo:
* more tests for positives
* are tests for negatives sufficent? ("prove" is happy except one issue which
is probably not related but still need to understand)
For the record: t/25_baseline_starttls.t line 50 and 67:
"Oops: STARTTLS handshake failed (code: 2)"
This commit fixes#1699 by setting FIRST_FINDING to true in fileout_banner() if $do_json_pretty is true.
When $do_json_pretty is true, fileout_banner() calls fileout_pretty_json_banner(), which starts a new sectio in the JSON file. Setting FIRST_FINDING to true ensures that a comma is not placed before the first entry in this new section. This is the same as is done in other places when a new section is stated: fileout_section_header() and fileout_insert_warning().
* todo: parse the return strings for detection
* test ;-)
* check whether the random char thing works under every OS supported
* definition of five_random var
run_starttls_injection():
* kill background openssl process when not needed anymore
* kill background socat process when not needed anymore
* close socket
add line in help() for STARTTLS injection
Furthermore:
* for close_socket() calls always add the fd (atm not needed)
* in help() rather advertise --BB instead of -BB
It's more a PoC style and needs some work
* use $OPENSSL or $OPENSSL2
* remove exit 0
* put run_starttls_injection below run_rc4
* test with more vulnerable servers
debugme1() was defined
This is a small cleanup of find_openssl_binary(). It tries also
to find a newer openssl version which we could need for any
new features. As stated in the comment at some point we should
decide whether we stick with our old version or rather supply
a new one. (xmpp-server is also not builtin for our 1.0.2) or
maybe find a good way (code) how to use both.
Also it looks for socat and if found it populates the according
global var.
It does a minor resort of global vars in the beginning.
This PR fixes#1671.
Primarily there's now an additional case statement in the main while loop
which just calls fatal() when it detects --help -b --banner -v or --version.
The documentation was also updated to reflect that.
(Some grammar and other errors which I stumbled over were corrected too)
This fixes#1648.
Java store doesn't seem to be as complete. No downgrading of trust rating
to T but we still need to raise a red flag for some Java clients
This PR will replace #1566. It addresses that if the server side doesn't show STARTTLS
testssl.sh should exit and label it accordingly (see #1536).
For this to achieve starttls_just_send() was were changed so that a return value from of 3
signals the STARTTLS pattern wasn't found is passed back to the parent fd_socket() whcih
will then act accordingly.
Also:
* starttls_full_read() + starttls_just_send() were improved for readability and debugging.
* The caller of starttls_full_read() + starttls_just_send() had redundant indentations which were moved to the callee
* minor bugs were squashed (e.g. ``fd_socket()``'s return values =!0 always were referring to STARTTLS also when no STARTTLS was requested)
This was tested (negative + test and positive) for FTP and SMTP which worked as expected. For POP, IMAP and NNTP it should work
accordingly but I had trouble finding a server whcih DID NOT support STARTTLS.
All other protocols basically should also cause testssl.sh to bail out but haven't been tested either. However
here starttls_io() won't return 3. It returns 1 in a case of problems. It uses NR_STARTTLS_FAIL. If it's encountered 2+
times that STARTTLS fails it early exists using fatal(). So we maybe want to consider changing starttls_io() in the future
to also use return 3 in the case STARTTLS is not offered.
This commit modifies a few functions to use fewer external function calls. In most cases this involves replacing external function calls with Bash internal functions, but in one case it involves replacing multiple external function calls with one call to awk.
This commit makes a few changes to the way that some functions work.
is_ipv4addr() and is_ipv6addr() will now strictly only accept a string that is an IPv4 (or IPv6) address and nothing else.
A couple of changes were also made to match_ipv4_httpheader(). First, lines that match $excluded_header (formerly $whitelisted_header) are not processed in the while loop. This prevents the excluded header from being output in the case that $HEADERFILE includes a non-excluded header with an IPv4 address and an excluded header with a string that looks like an IPv4 address.
The list of excluded headers was also modified to exclude any line that begins "Server: " rather than just lines that begin "Server: PRTG". According to https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Server, the "Server" header describes the software used by the server, so it seems reasonable to expect that this header line will never contain an IPv4 address. Also, looking at some old test results I found cases in which Oracle software version numbers in the Server header were mistakenly matched as IPv4 addresses.
The commit updates the test for the "Visibility Information" certificate extension used in the ETSI Enterprise Transport Security protocol.
The main change is to support OpenSSL 3.0.0, which prints more information about subject alternative names that are encoded as otherName. For otherName types for the OpenSSL has no information, it prints "otherName: <OID>::<unsupported>" rather than just "otherName: <unsupported>". So, testssl.sh needs to account for the possibility that the OID for the visibility information certificate extension will be printed.
This commit also updates the reference for this extension and changes the name of the function from etsi_etls_visibility_info() to etls_ets_visibility_info() since the name of the protocol was changed from Enterprise TLS (eTLS) to Enterprise Transport Security (ETS).
This commit does not change the output to the terminal or to JSON/CSV, even though those outputs use the previous name of eTLS rather than ETS.
The ALPN GREASE test was written based on draft-ietf-tls-grease-01, which reserved all ALPN identifiers beginning with the prefix "ignore/". This commit changes the test to align with RFC 8701, which instead reserves {0x0A,0x0A}, {0x1A,0x1A}, ..., {0xFA,0xFA}.
Improved:
* readability of my old code
* readability of debugging statements
* honor $SNEAKY for SMTP greeting
* hook (arg2 to starttls_smtp_dialog() ), if we plan to add / replace SMTP greeting at some point
This is a legacy warning and seems only needed in a very few cases
whereas in other few cases we don't issue such warnings. So to be
consistent it's right to remove this message as it confuses users
unnecessarily,
It'll appear in debug mode though.
See https://github.com/drwetter/testssl.sh/issues/1119#issuecomment-656271849
As there as suggestions to check intermediate certificates for things such as expiration date, this commit saves the text versions of each of the intermediate certificates so that they are available to extract additional information.
This commit checks whether any intermediate certificates provided by the server include an extended key usage extension that asserts the OCSP Signing key purpose.
This commit replaces #1680, which checks for such certificates by comparing the server's intermediate certificates against a fixed list of known bad certificates.
* open: generation of intermediate certificate files. We do that
at several places. But for some reasons I do not understand currently
we remove those files.
* we don't name the offending certificate
run_cipherlists() checks for support for different groups of ciphers, but does not indicate which ciphers in each group are supported. So, for example, if the JSON file indicates that there is a problem with severity level "HIGH" because the "LOW" ciphers are available, there is no clear indication of which of these ciphers are supported by the server.
If run_server_preference() is run with "--color 3", then there will be a visual indication (via color) of the ciphers the server supports that are considered bad, but this information does not appear in the JSON (or CSV) output. The JSON (or CSV) output will include information about every cipher that is supported, but the severity level is always "INFO".
This commit addresses this problem by changing the fileout() calls in ciphers_by_strength() and cipher_pref_check() that output each supported cipher individually so that the "severity" argument is an indication of the quality of the cipher. With this, information about which bad ciphers are supported can easily be found in the JSON/CSV output.
When testssl.sh is called with an unknown option it prints something like:
0: unrecognized option "--option"
It should be printing the name of the program rather than "0". This commit fixes that.
This commit separates pr_cipher_quality() into two functions, one that returns the quality of a cipher as a numeric rating (get_cipher_quality()) and one that prints a cipher based on its quality (pr_cipher_quality()). This separation allows get_cipher_quality() to be used to determine how good a cipher is without having to print anything. Having this ability would be helpful in implementing the changes suggested in #1311.
Moved the sentence ~i "A grade better than T would lead to a false sense of security"
to the documentation. No reason for excuses in the output. ;-) Explanation fits
better in the doc.
See also #1657
PR #1373 changed get_cn_from_cert() to handle certificate subject names that include more than one CN attribute. It did this by converting newline characters to spaces. It seems that this resulted in a space character being added to the end of the string returned by get_cn_from_cert() even in the case that the subject name only included one CN attribute. The presence of the space character in returned value caused compare_server_name_to_cert() to determine that the CN attribute did not contain a DNS name (since DNS names cannot include spaces), and so compare_server_name_to_cert() reports that the server name does not match against the CN in the subject. This may be the reason for the problem noted in #1555.
This commit fixes the above problem and also enhances the matching of the CN in the subject name against the server's name. Currently, compare_server_name_to_cert() assumes that the subject field contains at most one CN attribute. However, as noted in #1373, some certificates include subject names with more than one CN attribute, and RFC 6125 (Section 6.2.2) indicates that the certificate subject name include more than one CN, with each specifying a different DNS name.
So, in addition to fixing the problem with the space character, this commit also enhances the CN matching to work even if the certificate includes more than one CN attribute in the subject name.
In some cases when the Trust finding is printed, there is no space between the results when SNI is used and the results without SNI (which appear in paraenthesis). This commit adds the missing space.
This commit fixes several issues related to Shellcheck issue SC2034: unused variables.
In most cases variables are declared in a function, but are referenced later. The exceptions are:
* SESS_RESUMPTION is declared and values are assigned to it, but it us never used. (Same applies for not_new_reused in sub_seession_resumption().)
* In run_cipherlists(), there is a typo in the declaration of sslv2_tdes_ciphers.
* In get_caa_rr_record(), "hash", "len", and "line" are used but not declared.
This commit adds a function for querying the TXT DNS record, so
that subsequently we'll can build on top of that a function for
checking MTA-STS, see #1073.
Also it modifies a local variable mxs in get_mx_record() which
was declared as mx but mxs was used. (That is pending an backport
to 3.0.)
This commit adds support for EdDSA (Ed25519 and Ed448). In particular:
* It modifies prepare_tls_clienthello() to include Ed25519 and Ed448 in the signature_algorithms extension of the TLS 1.2 and earlier ClientHello (RFC 8422).
* It modifies run_server_defaults() and get_server_certificate() to check whether the server offers EdDSA certificates with TLS 1.3.
* It modifies certificate_info() to handle certificates signed with EdDSA or with EdDSA public keys, even if $OPENSSL does not support pretty printing such keys and signatures.
* It modifies read_sigalg_from_file() to recognize EdDSA signatures even if $OPENSSL does not.
PR #1519 requested that testssl.sh show the signature algorithm that the server uses during the TLS handshake. In TLS 1.3, this appears in the CertificateVerify message. In TLS 1.2 it appears in the ServerKeyExchange message when the chosen cipher suite uses an ephemeral (DH or ECDH) key, except in the case of cipher suites that provide no authentication. This information is not present in TLS 1.1 and earlier, as the hash algorithm to use in these earlier versions of the protocol is hard coded into the specification.
This commit takes a first step towards being able to show the signature algorithm by extending parse_tls_serverhello() to extract the signature algorithm when it is present. Matching the output produced by OpenSSL, it output two separate lines, the "Peer signature type" (RSA, RSA-PSS, DSA, ECDSA, Ed25519, or Ed448) and the "Peer signing digest" (MD5, SHA1, SHA224, SHA256, SHA384, or SHA512). This will allow the same function to extract the signature algorithm and digest, whether the handshake was performed using "$OPENSSL s_client" or tls_sockets().
This commit fixes two issues related to $SHOW_SIGALGO.
First, cipher_pref_check() does not show the signature algorithm if any of the ciphers were found using tls_sockets(), since the call to tls_sockets() does not specify that the server's certificate should be extracted.
Second, in run_beast() the call to tls_sockets() indicates that the server's certificate should be extracted if "$SHOW_SIGALGO" is true, even if "$WIDE" is false. While this does not cause any problems, extracting the certificate is a waste of effort if "$WIDE" is false, since the signature algorithm is not shown in that case.
This commit saves more or less time for a detection of the compression.
First it assembles the GET command with all available compressions and send them all.
If the result is negative: we can just tell the finding and return. If it's
positive: We already have identified 1x compression. Then we cycle through the
remaining compressions with single GET requests.
In order to not duplicate code we introduced a helper function sub_breach_helper()
which takes care sending the request and analysis the result.
We treat now failed requests differently: When the first fails we don't
continue anymore.
This commit tries to enummerate through all possible compressions
instead of just raising the arm because of the first one detected.
As far as the performance is concerned there's room for improvements
which subsequent commits will address.
The "-sigalgs" option is used in get_server_certificate() to obtain certificates the server uses with TLS 1.3. get_server_certificate() is currently designed to use $OPENSSL, if $OPENSSL supports TLS 1.3.
LibreSSL 3.1.{0,1} has added client support for TLS 1.3, but does not support the "-sigalgs" option. So, this commit determines whether the "-sigalgs" option is supported, and if it isn't, then uses tls_sockets().
When cipher_pref_check() is called in "--ssl-native" mode and the specified protocol is not supported, the message indicating a "local problem" is not properly formatted.
PR #1619 set the grade cap to 'F' is the server has a certificate with an RSA with e=1, however, it did not change the rating in the JSON/CSV output. This commit changes the cert_keySize rating to CRITICAL for an RSA key with e=1, regardless of the size of the modulus. It also uses pr_svrty_critical() to print the exponent in this case.
This commit makes a couple of improvements to set_key_str_score().
It rates (finite-field) DH keys the same as RSA and DSA keys.
Second, in the case of a server that has more than one certificate, the current code sets $KEY_EXCH_SCORE based on the length of the public key in the last certificate that is parsed. This commit changes set_key_str_score() so that $KEY_EXCH_SCORE is set based on the weakest public key.
Note that there is still the issue that the key exchange score does not take into account any ephemeral keys used. However, that needs to be addressed by callling set_key_str_score() from run_fs() and run_logjam(), as certificate_info() cannot provide information about ephemeral keys.
This commit adds additional information to the "Server key size" line for a certificate if the subject public key is RSA, ECDSA, or DH.
For RSA it show the public exponent. For ECDSA, it shows the curve. For DH, it shows the group used, if it is a common prime.
This commit fixes#1433 by adding "@SECLEVEL=0" to the "$OPENSSL s_client" and "$OPENSSL ciphers" command lines if that option is supported. Adding this option configures OpenSSL to support some weak ciphers that it would not use in the default configuration.
There is one place in parse_tls_serverhello() that returns 8 if the server's response is not well-formed TLS. However, there is no code in testssl.sh that is prepared to handle this return value. Every function except run_protocols() only distinguishes between 0, 2, and everything else. run_protocols(), however, gets confused if tls_sockets() returns a value that it is not expecting. So, this commit changes parse_tls_serverhello() to return 1 whenever the server's response can not be parsed.
There was a empty variable in determine_optimal_proto() which prevented to save
STARTTLS_OPTIMAL_PROTO. This is fixed.
The buffers and return codes for XMPP in starttls_io() were under not every
circumstances correct. This fixes those cases and making that in general more
robust (hopefully). (There's still code commented out which I'll leave it for
now).
When openssl did not support -starttls xmpp-server there was a copy
and paste error saying that -xmpphost option was not supported.
There is code at the beginning of parse_tls_serverhello() that checks whether the server's response appears to consist of a sequence of messages of the form <protocol><content type><content>. However, at the moment the check is only performed if "$do_starttls" is false. This commit changes parse_tls_serverhello() so that the check is always performed.
XMPP client-to-server and server-to-server links historically use
different XML namespaces. Some server implementations are strict
about this and will not proceed with the connection attempt when
the client namespace (`jabber:client`) is used on a
server-to-server link.
openssl s_client also supports `xmpp-server`.
This commit addresses two compatibility issues with LibreSSL 3.1.0, which has added client support for TLS 1.3.
The first issue is that LibreSSL has named the TLS 1.3 ciphers that it supports AEAD-AES256-GCM-SHA384, AEAD-CHACHA20-POLY1305-SHA256, and AEAD-AES128-GCM-SHA256, rather than using the OpenSSL names, which are TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256, and TLS_AES_128_GCM_SHA256. (Draft versions of OpenSSL 1.1.1 names these ciphers TLS13-AES-256-GCM-SHA384, TLS13-CHACHA20-POLY1305-SHA256, TLS13-AES-128-GCM-SHA256.) There are several places where testssl.sh checks whether a cipher suite is a TLS 1.3 cipher by checking whether its OpenSSL name begins with "TLS_" (or "TLS13"). In order to work with LibreSSL 3.1.0, these checks also need to consider names that begin with "AEAD-" to be TLS 1.3 ciphers.
Second, in sub_session_resumption() there is code that adds "-no_ssl2" to the "$OPENSSL s_client" command line if that option is supported. If "-no_ssl2" is not supported, then other protocol information is added to the command line. I believe this code was written with the assumption that any version of OpenSSL that supports "-no_ssl2" does not support TLS 1.3. However, LibreSSL 3.1.0 supports both. So, this commit changes the code to add the "-no_ssl2" option only if TLS 1.3 is not supported.
This commit addresses two compatibility issues with LibreSSL.
First, with LibreSSL, "$OPENSSL s_client" does not support the "-curves" option, so the "-groups" option needs to be used instead. Note that with LibreSSL, the command line "$OPENSSL s_client -groups $curve -connect invalid." will not work, as it will complain "no port defined," but will not indicate whether the specified curve is supported. Adding a port number fixes that problem. (There does not seem to be a need to include a port number for other tests, such as whether the "-curves" option itself is supported.)
Second, including "-out -" in the command line for "$OPENSSL genpkey" causes LibreSSL to create a file with the name "-" if the algorithm is supported. This is not an issue at the moment, since LibreSSL's genpkey does not support X25519 or X448. However, both genpkey with both OpenSSL and LibreSSL uses stdout as the default output if no "-out" is specified, so the "-out -" is not necessary.
generate_key_share_extension() and prepare_tls_clienthello() currently check the $OPENSSL version number to determine whether X25519 and X448 are supported. The commit changes these functions to use $HAS_X25519 and $HAS_X448.
run_ticketbleed() and sub_session_ticket_tls() each include one call to "$OPENSSL s_client". For each of these calls the expected response is a TLS 1.2 or earlier ServerHello. However, if $OPENSSL supports TLS 1.3, then a TLS 1.3 ClientHello will be sent.
This commit fixes this problem in two ways. For the call in run_ticketbleed(), "-no_tls1_3" is added to the command line if "$OPENSSL" supports TLS 1.3. For the call in sub_session_ticket_tls(), this commit changes the function so that the same ClientHello version is sent as will sent by run_ticketbleed() via sockets.
... in cases where the protcol section has not been run before.
Also add " -\n" on the screen/html if protocol is not supported. Also for
SSLv2 which can be supported but at the same time not offer any ciphers
mention there will be an output on the screen.
In order not to provide redundant information run_allciphers() is
now not being run via default (1). Therefore run_server_preference()
runs always in wide mode.
In order to archieve that cipher_pref_check() was modified to
accept a fifth argument whether it'll run in wide mode. As
of now cipher_pref_check() is only called by run_server_preference(),
so the code referring to non-wide mode in cipher_pref_check() may also
be deleted in the future.
To provide a better view the run_fs() section is now being run after
run_server_preference().
(1) saves also 5-6 seconds
This commit fixes a couple of issues related to the use of testssl.sh with OpenSSL 3.0.0-alpha1.
First, when the command line includes an unknown option (e.g., -ssl2), OpenSSL 3.0.0-alpha responds with "Unknown option: -ssl2" rather than "Option unknown option -ssl2". This commit addresses this by making the check for "unknown option" case insensitve.
Second, the printing a DH key, OpenSSL 3.0.0-alpha1 labels the prime and the generator using "prime P:" and "generator G:" rather than just "prime:" and "generator:". This commit by changing testssl.sh to match on either string.
This commit fixes a problem with run_logjam() when run in --ssl-native mode. If $OPENSSL does not support any DH export ciphers, then no test for such cipher is performed. However, the results of "test" is still checked, leading to testssl.sh incorrectly reporting that the server supports DH EXPORT ciphers.
See #1580.
This commit brings:
* If there's no cipher for a protocol it adds a "\n - \n" (also for run_cipher_per_proto() )
* further output improvements
* Cipher order --> Cipher listing per protocol
* make some conditional statement easier to read (at least for me)
New open points:
- cipher_pref_check() doesn't save to PROTOS_OFFERED (was there before)
(just stumbled over this but how about we also use get_protocol() / parse_tls_serverhello()
- do we want run_allciphers() to be started by default?
- $WIDE per default for run_cipher_per_proto() ?
- probably better not to display text in round square brackets when there's no cipher:
Hexcode Cipher Suite Name (OpenSSL) KeyExch. Encryption Bits Cipher Suite Name (IANA/RFC)
-----------------------------------------------------------------------------------------------------------------------------
SSLv2 (listed by strength)
SSLv3 (server order)
TLSv1 (server order)
TLSv1.1 (server order)
TLSv1.2 (server order)
xc02c ECDHE-ECDSA-AES256-GCM-SHA384 ECDH 256 AESGCM 256 TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
[..]
- when a server has no preference at all it shows in wide mode:
Has server cipher order? no (NOT ok) -- only for TLS 1.3
Negotiated protocol TLSv1.3
Negotiated cipher TLS_AES_256_GCM_SHA384, 253 bit ECDH (X25519)
Cipher listing per protocol
Hexcode Cipher Suite Name (OpenSSL) KeyExch. Encryption Bits Cipher Suite Name (IANA/RFC)
-----------------------------------------------------------------------------------------------------------------------------
SSLv2
-
SSLv3
-
TLSv1 (no server order, thus listed by strength)
xc014 ECDHE-RSA-AES256-SHA ECDH 521 AES 256 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
[..]
e.g. dev.testssl.sh
This commit extends run_server_preference() to list every cipher supported by each protocol even in cases in which the server does not enforce a preference order.
For protocols where the server enforces a cipher order the list of supported ciphers is ordered by server preference (as now). For protocols where the server does not enforce a cipher order, the ciphers are listed by encryption strength (as run_cipher_per_proto() does).
In order to implement this, ciphers_by_strength() was extended to offer a non-wide mode.
by introducing framework for tests to be skipped, see also #1502.
As a first example for the development branch should serve
--disable-rating / --no-rating. The latter is for now undocumented.
Also the big case statement in parse_cmd_line() may use a general
--disable-* or --no-* clause where all --disable-* / --no-* are
being parsed/
A new function set_skip_tests() is being introduced which
sets do_<variables> according to the new array SKIP_TESTS .
Any new test do be skipped needs to be added to that array.
The changes in the --devel part come from the tries to fix
the syntax highlight in vim -- which in the end difn't work
see #1571. Bit size doesn't matter. It only matters to the
user which ciphers they are.
Additionally phrased the output better (FS + strong enc) and
do less indentation.
Renamed average_ciphers -> obsoleted_ciphers to refect what's
on the output.
STARTTLS tests should always give a bad rating because of the missing
trust 1) . That's why we don't provide more details as "T". Maybe we
decide later to provide an environment variable which still
shows this warning but divulges more details. TBC.
Documentation is missing for STARTTLS + grades.
1) There might be cases also for STARTTLS where encryption is enforced
and e.g. the certificate fingerprint is validated. As this is highly
protcol specific we won't test that.
* instead of DISABLE_GRADING we use do_grading as for run_* functions we currently don't
support global variables
* Add AEAD cipher set_grade_cap (needs to be tested though)
* remove redundant quotes
* be to be safe add double quotes at other places
* Fix typos
* Polishing output
Tasks (not complete):
* Review whether it is rated as intended
* Do we want to mofify SSL Lab's rating? (SSLv3 e.g., T for SHA1 certificate?)
* Does JSON output work?
* TLS 1.3 only server are not rated properly --> wait for SSLlabs?
* SWEET32: rating refers to TLS 1.1 atm. SSLlabs docu doesn't give a hint
(is their docu incomplete?)
* Rating for STARTTLS at all?
In all instances:
* command line (will break things)
* JSON IDs (will break things)
* in the documentation
* in the travis checks where used
* everywhere in the code: variables, functions, comments
This commit is an attempt to fix#1514. The commit is mostly based on a suggestion at https://unix.stackexchange.com/questions/57940/trap-int-term-exit-really-necessary. Even with that change, it seemed that if testssl.sh were in the middle of executing run_cipher_per_proto() when it received a signal, it would not stop until that function had completed. This seems to have something to do with subshells. Changing the while loop in run_cipher_per_proto() seems to have fixed that issue. So, I also made similar changes to the while loops in prettyprint_local().
This commit fixes#1551 by changing get_cipher() to recognize RFC names that begin with SSL_*. It also modifies run_beast() so that it does not get stuck in an infinite loop if get_cipher() doesn't return a valid cipher name.
This commit modifies run_cipherlists() to align with pr_cipher_quality().
The biggest change made by this commit is that it breaks the current list of STRONG ciphers into two lists: one for AEAD ciphers that offer forward secrecy (STRONG) and one for AEAD ciphers that do not offer forward secrecy (GOOD).
The remaining changes are just minor tweaks:
* A few ciphers that use MD5 are moved from AVERAGE and 3DES to LOW.
* '!AECDH' was added to the OpenSSL description for LOW to catch one cipher in OpenSSL 1.0.2-chacha that offers no authentication that was being included in the LOW list.
This commit also changes sub_cipherlists() to change the output when a cipherlist with a rating of 6 is not present. There was a "FIXME" associated with this output, but it didn't matter before since there were no cipherlists with a rating of 6.