From fb94221ce0f9779a85ce66b925c87ef648d9d64e Mon Sep 17 00:00:00 2001 From: David Cooper Date: Mon, 11 Jul 2016 10:52:48 -0400 Subject: [PATCH 1/9] Reorder supported curves Reorder the supported curves sent by socksend_tls_clienthello() from strongest to weakest. --- testssl.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/testssl.sh b/testssl.sh index 76575b0..47fe1cf 100755 --- a/testssl.sh +++ b/testssl.sh @@ -5396,10 +5396,10 @@ socksend_tls_clienthello() { extensions_ecc=" 00, 0a, # Type: Supported Elliptic Curves , see RFC 4492 00, 3e, 00, 3c, # lengths - 00, 01, 00, 02, 00, 03, 00, 04, 00, 05, 00, 06, 00, 07, 00, 08, - 00, 09, 00, 0a, 00, 0b, 00, 0c, 00, 0d, 00, 0e, 00, 0f, 00, 10, - 00, 11, 00, 12, 00, 13, 00, 14, 00, 15, 00, 16, 00, 17, 00, 18, - 00, 19, 00, 1a, 00, 1b, 00, 1c, 00, 1d, 00, 1e, + 00, 0e, 00, 0d, 00, 19, 00, 1c, 00, 1e, 00, 0b, 00, 0c, 00, 1b, + 00, 18, 00, 09, 00, 0a, 00, 1a, 00, 16, 00, 17, 00, 1d, 00, 08, + 00, 06, 00, 07, 00, 14, 00, 15, 00, 04, 00, 05, 00, 12, 00, 13, + 00, 01, 00, 02, 00, 03, 00, 0f, 00, 10, 00, 11, 00, 0b, # Type: Supported Point Formats , see RFC 4492 00, 02, # len 01, 00" From 891c56f8bf328b3934264c1ab4c4a91b5cbdb9b6 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Mon, 11 Jul 2016 11:00:56 -0400 Subject: [PATCH 2/9] Determine support elliptic curves for ECDHE- ciphers This PR extends run_pfs() to display the set of elliptic curves supported by the server, if the server supports any ECDHE- ciphers. --- testssl.sh | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/testssl.sh b/testssl.sh index 76575b0..2507488 100755 --- a/testssl.sh +++ b/testssl.sh @@ -4489,13 +4489,15 @@ run_server_defaults() { run_pfs() { local -i sclient_success - local pfs_offered=false + local pfs_offered=false ecdhe_offered=false local tmpfile local dhlen - local hexcode dash pfs_cipher sslvers kx auth enc mac + local hexcode dash pfs_cipher sslvers kx auth enc mac curve local pfs_cipher_list="$ROBUST_PFS_CIPHERS" + local ecdhe_cipher_list="" + local -a curves=("sect163k1" "sect163r1" "sect163r2" "sect193r1" "sect193r2" "sect233k1" "sect233r1" "sect239k1" "sect283k1" "sect283r1" "sect409k1" "sect409r1" "sect571k1" "sect571r1" "secp160k1" "secp160r1" "secp160r2" "secp192k1" "prime192v1" "secp224k1" "secp224r1" "secp256k1" "prime256v1" "secp384r1" "secp521r1" "brainpoolP256r1" "brainpoolP384r1" "brainpoolP512r1" "X25519" "X448") local -i nr_supported_ciphers=0 - local pfs_ciphers + local pfs_ciphers curves_offered outln pr_headlineln " Testing robust (perfect) forward secrecy, (P)FS -- omitting Null Authentication/Encryption as well as 3DES and RC4 here " @@ -4539,6 +4541,7 @@ run_pfs() { if [[ "$sclient_success" -ne 0 ]] && ! "$SHOW_EACH_C"; then continue # no successful connect AND not verbose displaying each cipher fi + [[ "$sclient_success" -eq 0 ]] && [[ $pfs_cipher == "ECDHE-"* ]] && ecdhe_offered=true && ecdhe_cipher_list+=":$pfs_cipher" if "$WIDE"; then normalize_ciphercode $hexcode @@ -4575,6 +4578,21 @@ run_pfs() { fileout "pfs_ciphers" "INFO" "(Perfect) Forward Secrecy Ciphers: $pfs_ciphers" fi fi + + if $ecdhe_offered; then + # find out what elliptic curves are supported. + curves_offered="" + for curve in "${curves[@]}"; do + $OPENSSL s_client -cipher "${ecdhe_cipher_list:1}" -curves $curve $STARTTLS $BUGS -connect $NODEIP:$PORT $PROXY $SNI &>$tmpfile Date: Mon, 11 Jul 2016 18:44:28 +0200 Subject: [PATCH 3/9] polishing output for #413 --- testssl.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/testssl.sh b/testssl.sh index 949454f..14f2d02 100755 --- a/testssl.sh +++ b/testssl.sh @@ -4519,13 +4519,13 @@ run_pfs() { sclient_connect_successful $? $TMPFILE if [[ $? -ne 0 ]] || [[ $(grep -ac "BEGIN CERTIFICATE" $TMPFILE) -eq 0 ]]; then outln - pr_svrty_mediumln "No ciphers supporting Forward Secrecy offered" + pr_svrty_mediumln " No ciphers supporting Forward Secrecy offered" fileout "pfs" "MEDIUM" "(Perfect) Forward Secrecy : No ciphers supporting Forward Secrecy offered" else outln pfs_offered=true pfs_ciphers="" - pr_done_good " PFS is offered (OK)" + pr_done_good " PFS is offered (OK) " fileout "pfs" "OK" "(Perfect) Forward Secrecy : PFS is offered (OK)" if "$WIDE"; then outln ", ciphers follow (client/browser support is important here) \n" @@ -4579,7 +4579,7 @@ run_pfs() { fi fi - if $ecdhe_offered; then + if "$ecdhe_offered"; then # find out what elliptic curves are supported. curves_offered="" for curve in "${curves[@]}"; do @@ -4589,8 +4589,8 @@ run_pfs() { [[ "$sclient_success" -eq 0 ]] && curves_offered+="$curve " done if [[ -n "$curves_offered" ]]; then - pr_bold " Elliptic curves offered: "; outln "$curves_offered" - fileout "ecdhe_curves" "INFO" "Elliptic curves offered: $curves_offered" + pr_bold " Elliptic curves offered: "; outln "$curves_offered" + fileout "ecdhe_curves" "INFO" "Elliptic curves offered $curves_offered" fi fi outln @@ -8286,4 +8286,4 @@ fi exit $? -# $Id: testssl.sh,v 1.523 2016/07/11 14:20:35 dirkw Exp $ +# $Id: testssl.sh,v 1.524 2016/07/11 16:44:27 dirkw Exp $ From bda62ec715c3e9245df2d2dea0c56efa355b3214 Mon Sep 17 00:00:00 2001 From: Dirk Date: Mon, 11 Jul 2016 19:41:32 +0200 Subject: [PATCH 4/9] no glasses needed, just need to look at the right spot ;- --- testssl.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testssl.sh b/testssl.sh index 14f2d02..ea85fae 100755 --- a/testssl.sh +++ b/testssl.sh @@ -3811,7 +3811,7 @@ compare_server_name_to_cert() # Check whether any of the DNS names in the certificate match the servername dns_sans=$($OPENSSL x509 -in $cert -noout -text 2>>$ERRFILE | grep -A2 "Subject Alternative Name" | \ - tr '.' '\n' grep "DNS:" | sed -e 's/DNS://g' -e 's/ //g') + tr ',' '\n' | grep "DNS:" | sed -e 's/DNS://g' -e 's/ //g') for san in $dns_sans; do [[ "$san" == "$servername" ]] && return 0 # If $san is a wildcard name, then do a wildcard match @@ -8286,4 +8286,4 @@ fi exit $? -# $Id: testssl.sh,v 1.524 2016/07/11 16:44:27 dirkw Exp $ +# $Id: testssl.sh,v 1.525 2016/07/11 17:41:32 dirkw Exp $ From a06ac81df3494ec97da7310d3a9f0dafcd7dc7a7 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Thu, 14 Jul 2016 13:23:50 -0400 Subject: [PATCH 5/9] Speed up finding supported curves Rather than try each curve one at a time, follow model in `cipher_pref_check()`. First include all curves in ClientHello, then successively remove from the ClientHello those curves that have been offered by the server until the connection fails. This makes the number of calls to `$OPENSSL s_client` one more than the number of supported curves rather than the number of curves in NamedCurve supported by $OPENSSL. Note, however, that OpenSSL defines MAX_CURVELIST as 28 and fails if the `-curves` option includes more than 28 curves. Since OpenSSL 1.1.0 offers 29 curves from NamedCurve, this PR breaks the list of supported curves in 2. At the cost of one additional calls to `$OPENSSL s_client` it ensures that the number of curves provides to the `-curves` option is below the limit. --- testssl.sh | 66 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 55 insertions(+), 11 deletions(-) diff --git a/testssl.sh b/testssl.sh index ea85fae..622185a 100755 --- a/testssl.sh +++ b/testssl.sh @@ -4495,9 +4495,12 @@ run_pfs() { local hexcode dash pfs_cipher sslvers kx auth enc mac curve local pfs_cipher_list="$ROBUST_PFS_CIPHERS" local ecdhe_cipher_list="" - local -a curves=("sect163k1" "sect163r1" "sect163r2" "sect193r1" "sect193r2" "sect233k1" "sect233r1" "sect239k1" "sect283k1" "sect283r1" "sect409k1" "sect409r1" "sect571k1" "sect571r1" "secp160k1" "secp160r1" "secp160r2" "secp192k1" "prime192v1" "secp224k1" "secp224r1" "secp256k1" "prime256v1" "secp384r1" "secp521r1" "brainpoolP256r1" "brainpoolP384r1" "brainpoolP512r1" "X25519" "X448") - local -i nr_supported_ciphers=0 - local pfs_ciphers curves_offered + local -a curves_ossl=("sect163k1" "sect163r1" "sect163r2" "sect193r1" "sect193r2" "sect233k1" "sect233r1" "sect239k1" "sect283k1" "sect283r1" "sect409k1" "sect409r1" "sect571k1" "sect571r1" "secp160k1" "secp160r1" "secp160r2" "secp192k1" "prime192v1" "secp224k1" "secp224r1" "secp256k1" "prime256v1" "secp384r1" "secp521r1" "brainpoolP256r1" "brainpoolP384r1" "brainpoolP512r1" "X25519" "X448") + local -a curves_ossl_output=("K-163" "sect163r1" "B-163" "sect193r1" "sect193r2" "K-233" "B-233" "sect239k1" "K-283" "B-283" "K-409" "B-409" "K-571" "B-571" "secp160k1" "secp160r1" "secp160r2" "secp192k1" "P-192" "secp224k1" "P-224" "secp256k1" "P-256" "P-384" "P-521" "brainpoolP256r1" "brainpoolP384r1" "brainpoolP512r1" "X25519" "X448") + local -a supported_curves=() + local -i nr_supported_ciphers=0 nr_curves=0 i j low high + local pfs_ciphers curves_offered curves_to_test temp + local curve_found curve_used outln pr_headlineln " Testing robust (perfect) forward secrecy, (P)FS -- omitting Null Authentication/Encryption as well as 3DES and RC4 here " @@ -4582,15 +4585,56 @@ run_pfs() { if "$ecdhe_offered"; then # find out what elliptic curves are supported. curves_offered="" - for curve in "${curves[@]}"; do - $OPENSSL s_client -cipher "${ecdhe_cipher_list:1}" -curves $curve $STARTTLS $BUGS -connect $NODEIP:$PORT $PROXY $SNI &>$tmpfile $tmpfile Date: Sat, 16 Jul 2016 20:48:56 +0200 Subject: [PATCH 6/9] - output polising in curves - fix for jail #258 --- testssl.sh | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/testssl.sh b/testssl.sh index ea85fae..ee153a5 100755 --- a/testssl.sh +++ b/testssl.sh @@ -4525,13 +4525,13 @@ run_pfs() { outln pfs_offered=true pfs_ciphers="" - pr_done_good " PFS is offered (OK) " + pr_done_good " PFS is offered (OK)" fileout "pfs" "OK" "(Perfect) Forward Secrecy : PFS is offered (OK)" if "$WIDE"; then outln ", ciphers follow (client/browser support is important here) \n" neat_header else - out " " + out " " fi while read hexcode dash pfs_cipher sslvers kx auth enc mac; do tmpfile=$TMPFILE.$hexcode @@ -4589,6 +4589,7 @@ run_pfs() { [[ "$sclient_success" -eq 0 ]] && curves_offered+="$curve " done if [[ -n "$curves_offered" ]]; then + "$WIDE" && outln pr_bold " Elliptic curves offered: "; outln "$curves_offered" fileout "ecdhe_curves" "INFO" "Elliptic curves offered $curves_offered" fi @@ -6765,7 +6766,11 @@ check4openssl_oldfarts() { # FreeBSD needs to have /dev/fd mounted. This is a friendly hint, see #258 check_bsd_mount() { if [[ "$(uname)" == FreeBSD ]]; then - if ! mount | grep '/dev/fd' | grep -q fdescfs; then + if ! mount | grep -q "^devfs"; then + outln "you seem to run $PROG_NAME= in a jail. Hopefully you're did \"mount -t fdescfs fdesc /dev/fd\"" + elif mount | grep '/dev/fd' | grep -q fdescfs; then + : + else fatal "You need to mount fdescfs on FreeBSD: \"mount -t fdescfs fdesc /dev/fd\"" -3 fi fi @@ -8286,4 +8291,4 @@ fi exit $? -# $Id: testssl.sh,v 1.525 2016/07/11 17:41:32 dirkw Exp $ +# $Id: testssl.sh,v 1.526 2016/07/16 18:48:55 dirkw Exp $ From d9f8024d9a0c0999f54d5f2c3fb4c5436ba461c5 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Wed, 20 Jul 2016 10:50:38 -0400 Subject: [PATCH 7/9] Fix JSON output of Issuer name `certificate_info()` currently outputs `$issuer` to the JSON file, where is should be outputting `$issuer_CN` in order for the information in the JSON file to match the information that is displayed. This PR also fixes the problem that if an Issuer name contains a domain component attribute (DC=) then it will be mistakenly treated as a country attribute (C=). --- testssl.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/testssl.sh b/testssl.sh index a792617..e513d20 100755 --- a/testssl.sh +++ b/testssl.sh @@ -3839,7 +3839,7 @@ certificate_info() { local ocsp_response=$5 local ocsp_response_status=$6 local cert_sig_algo cert_sig_hash_algo cert_key_algo - local expire days2expire secs2warn ocsp_uri crl startdate enddate issuer_C issuer_O issuer sans san cn cn_nosni + local expire days2expire secs2warn ocsp_uri crl startdate enddate issuer_CN issuer_C issuer_O issuer sans san cn cn_nosni local cert_fingerprint_sha1 cert_fingerprint_sha2 cert_fingerprint_serial local policy_oid local spaces="" @@ -4145,7 +4145,7 @@ certificate_info() { issuer="$($OPENSSL x509 -in $HOSTCERT -noout -issuer -nameopt multiline,-align,sname,-esc_msb,utf8,-space_eq 2>>$ERRFILE)" issuer_CN="$(awk -F'=' '/CN=/ { print $2 }' <<< "$issuer")" issuer_O="$(awk -F'=' '/O=/ { print $2 }' <<< "$issuer")" - issuer_C="$(awk -F'=' '/C=/ { print $2 }' <<< "$issuer")" + issuer_C="$(awk -F'=' '/ C=/ { print $2 }' <<< "$issuer")" if [[ "$issuer_O" == "issuer=" ]] || [[ "$issuer_O" == "issuer= " ]] || [[ "$issuer_CN" == "$CN" ]]; then pr_svrty_criticalln "self-signed (NOT ok)" @@ -4157,9 +4157,9 @@ certificate_info() { if [[ -n "$issuer_C" ]]; then out " from " pr_dquoted "$issuer_C" - fileout "${json_prefix}issuer" "INFO" "Issuer: \"$issuer\" ( \"$issuer_O\" from \"$issuer_C\")" + fileout "${json_prefix}issuer" "INFO" "Issuer: \"$issuer_CN\" ( \"$issuer_O\" from \"$issuer_C\")" else - fileout "${json_prefix}issuer" "INFO" "Issuer: \"$issuer\" ( \"$issuer_O\" )" + fileout "${json_prefix}issuer" "INFO" "Issuer: \"$issuer_CN\" ( \"$issuer_O\" )" fi outln ")" fi From b0d394e93cf3d3ec849229fdd6a09edb026409f7 Mon Sep 17 00:00:00 2001 From: Dirk Wetter Date: Wed, 20 Jul 2016 17:28:09 +0200 Subject: [PATCH 8/9] merged #417 --- testssl.sh | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/testssl.sh b/testssl.sh index e513d20..013699e 100755 --- a/testssl.sh +++ b/testssl.sh @@ -3839,7 +3839,8 @@ certificate_info() { local ocsp_response=$5 local ocsp_response_status=$6 local cert_sig_algo cert_sig_hash_algo cert_key_algo - local expire days2expire secs2warn ocsp_uri crl startdate enddate issuer_CN issuer_C issuer_O issuer sans san cn cn_nosni + local expire days2expire secs2warn ocsp_uri crl startdate enddate issuer_CN issuer_C issuer_O issuer sans san cn + local cn_nosni="" local cert_fingerprint_sha1 cert_fingerprint_sha2 cert_fingerprint_serial local policy_oid local spaces="" @@ -4079,8 +4080,10 @@ certificate_info() { # no cipher suites specified here. We just want the default vhost subject $OPENSSL s_client $STARTTLS $BUGS -connect $NODEIP:$PORT $PROXY $OPTIMAL_PROTO 2>>$ERRFILE $HOSTCERT.nosni - cn_nosni="$(get_cn_from_cert "$HOSTCERT.nosni")" - [[ -z "$cn_nosni" ]] && cn_nosni="no CN field in subject" + if grep -q "\-\-\-\-\-BEGIN" "$HOSTCERT.nosni"; then + cn_nosni="$(get_cn_from_cert "$HOSTCERT.nosni")" + [[ -z "$cn_nosni" ]] && cn_nosni="no CN field in subject" + fi #FIXME: check for SSLv3/v2 and look whether it goes to a different CN (probably not polite) From 6e5c2a824e4ad705bd60a50ec97f338c5c7e6546 Mon Sep 17 00:00:00 2001 From: Dirk Wetter Date: Wed, 20 Jul 2016 17:38:55 +0200 Subject: [PATCH 9/9] merged #416 --- testssl.sh | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/testssl.sh b/testssl.sh index e513d20..86eff8a 100755 --- a/testssl.sh +++ b/testssl.sh @@ -3839,7 +3839,8 @@ certificate_info() { local ocsp_response=$5 local ocsp_response_status=$6 local cert_sig_algo cert_sig_hash_algo cert_key_algo - local expire days2expire secs2warn ocsp_uri crl startdate enddate issuer_CN issuer_C issuer_O issuer sans san cn cn_nosni + local expire days2expire secs2warn ocsp_uri crl startdate enddate issuer_CN issuer_C issuer_O issuer sans san cn + local cn_nosni="" local cert_fingerprint_sha1 cert_fingerprint_sha2 cert_fingerprint_serial local policy_oid local spaces="" @@ -4079,8 +4080,10 @@ certificate_info() { # no cipher suites specified here. We just want the default vhost subject $OPENSSL s_client $STARTTLS $BUGS -connect $NODEIP:$PORT $PROXY $OPTIMAL_PROTO 2>>$ERRFILE $HOSTCERT.nosni - cn_nosni="$(get_cn_from_cert "$HOSTCERT.nosni")" - [[ -z "$cn_nosni" ]] && cn_nosni="no CN field in subject" + if grep -q "\-\-\-\-\-BEGIN" "$HOSTCERT.nosni"; then + cn_nosni="$(get_cn_from_cert "$HOSTCERT.nosni")" + [[ -z "$cn_nosni" ]] && cn_nosni="no CN field in subject" + fi #FIXME: check for SSLv3/v2 and look whether it goes to a different CN (probably not polite) @@ -8335,4 +8338,4 @@ fi exit $? -# $Id: testssl.sh,v 1.526 2016/07/16 18:48:55 dirkw Exp $ +# $Id: testssl.sh,v 1.527 2016/07/20 15:36:50 dirkw Exp $