add drill support

This commit is contained in:
Konstantin Shalygin 2015-11-21 16:45:07 +06:00
parent 3d869920d0
commit 07ef4537bf

View File

@ -3,7 +3,7 @@
# vim:ts=5:sw=5:expandtab # vim:ts=5:sw=5:expandtab
# we have a spaces softtab, that ensures readability with other editors too # we have a spaces softtab, that ensures readability with other editors too
[ -z "$BASH_VERSINFO" ] && printf "\n\033[1;35m Please make sure you're using \"bash\"! Bye...\033[m\n\n" >&2 && exit 245 [ -z "$BASH_VERSINFO" ] && printf "\n\033[1;35m Please make sure you're using \"bash\"! Bye...\033[m\n\n" >&2 && exit 245
[ $(kill -l | grep -c SIG) -eq 0 ] && printf "\n\033[1;35m Please make sure you're calling me without leading \"sh\"! Bye...\033[m\n\n" >&2 && exit 245 [ $(kill -l | grep -c SIG) -eq 0 ] && printf "\n\033[1;35m Please make sure you're calling me without leading \"sh\"! Bye...\033[m\n\n" >&2 && exit 245
# testssl.sh is a program for spotting weak SSL encryption, ciphers, version and some # testssl.sh is a program for spotting weak SSL encryption, ciphers, version and some
@ -25,17 +25,17 @@
# USAGE WITHOUT ANY WARRANTY, THE SOFTWARE IS PROVIDED "AS IS". USE IT AT # USAGE WITHOUT ANY WARRANTY, THE SOFTWARE IS PROVIDED "AS IS". USE IT AT
# your OWN RISK! # your OWN RISK!
# HISTORY: # HISTORY:
# Back in 2006 it all started with a few openssl commands... # Back in 2006 it all started with a few openssl commands...
# That's because openssl is a such a good swiss army knife (see e.g. # That's because openssl is a such a good swiss army knife (see e.g.
# wiki.openssl.org/index.php/Command_Line_Utilities) that it was difficult to resist # wiki.openssl.org/index.php/Command_Line_Utilities) that it was difficult to resist
# wrapping some shell commands around it, which I used for my pen tests. This is how # wrapping some shell commands around it, which I used for my pen tests. This is how
# everything started. # everything started.
# Now it has grown up, it has bash socket support for some features which basically replacing # Now it has grown up, it has bash socket support for some features which basically replacing
# more and more functions of OpenSSL and will serve as some kind of library in the future. # more and more functions of OpenSSL and will serve as some kind of library in the future.
# The socket checks in bash may sound cool and unique -- they are -- but probably you # The socket checks in bash may sound cool and unique -- they are -- but probably you
# can achieve e.g. the same result with my favorite interactive shell: zsh (zmodload zsh/net/socket # can achieve e.g. the same result with my favorite interactive shell: zsh (zmodload zsh/net/socket
# -- checkout zsh/net/tcp) too! # -- checkout zsh/net/tcp) too!
# /bin/bash though is way more often used within Linux and it's perfect # /bin/bash though is way more often used within Linux and it's perfect
# for cross platform support, see MacOS X and also under Windows the MSYS2 extension or Cygwin. # for cross platform support, see MacOS X and also under Windows the MSYS2 extension or Cygwin.
# Cross-platform is one of the three main goals of this script. Second: Ease of installation. # Cross-platform is one of the three main goals of this script. Second: Ease of installation.
@ -49,8 +49,8 @@
# internet. And those examples above 4) are 3rd parties. If these restrictions are all fine # internet. And those examples above 4) are 3rd parties. If these restrictions are all fine
# with you and you need a management compatible rating -- go ahead and use those. # with you and you need a management compatible rating -- go ahead and use those.
# But also if your fine with those restrictions: testssl.sh is meant as a tool in your hand # But also if your fine with those restrictions: testssl.sh is meant as a tool in your hand
# and it's way more flexible. # and it's way more flexible.
# #
# Oh, and did I mention testssl.sh is open source? # Oh, and did I mention testssl.sh is open source?
@ -59,7 +59,7 @@
# are disabled as they'll impact security otherwise. For security # are disabled as they'll impact security otherwise. For security
# testing though we need all broken features. testssl.sh will # testing though we need all broken features. testssl.sh will
# over time replace those checks with bash sockets -- however it's # over time replace those checks with bash sockets -- however it's
# still recommended to use the supplied binaries or cook your own, see # still recommended to use the supplied binaries or cook your own, see
# https://github.com/drwetter/testssl.sh/blob/master/bin/Readme.md . # https://github.com/drwetter/testssl.sh/blob/master/bin/Readme.md .
# Don't worry if feature X is not available you'll get a warning about # Don't worry if feature X is not available you'll get a warning about
# this missing feature! The idea is if this script can't tell something # this missing feature! The idea is if this script can't tell something
@ -86,7 +86,7 @@ MAPPING_FILE_RFC=""
which git &>/dev/null && readonly GIT_REL=$(git log --format='%h %ci' -1 2>/dev/null | awk '{ print $1" "$2" "$3 }') which git &>/dev/null && readonly GIT_REL=$(git log --format='%h %ci' -1 2>/dev/null | awk '{ print $1" "$2" "$3 }')
readonly CVS_REL=$(tail -5 "$0" | awk '/dirkw Exp/ { print $4" "$5" "$6}') readonly CVS_REL=$(tail -5 "$0" | awk '/dirkw Exp/ { print $4" "$5" "$6}')
readonly CVS_REL_SHORT=$(tail -5 "$0" | awk '/dirkw Exp/ { print $4 }') readonly CVS_REL_SHORT=$(tail -5 "$0" | awk '/dirkw Exp/ { print $4 }')
readonly SYSTEM=$(uname -s) readonly SYSTEM=$(uname -s)
date --help >/dev/null 2>&1 && \ date --help >/dev/null 2>&1 && \
readonly HAS_GNUDATE=true || \ readonly HAS_GNUDATE=true || \
readonly HAS_GNUDATE=false readonly HAS_GNUDATE=false
@ -112,14 +112,14 @@ TERM_CURRPOS=0 # custom line wrapping ne
declare -x OPENSSL declare -x OPENSSL
COLOR=${COLOR:-2} # 2: Full color, 1: b/w+positioning, 0: no ESC at all COLOR=${COLOR:-2} # 2: Full color, 1: b/w+positioning, 0: no ESC at all
SHOW_EACH_C=${SHOW_EACH_C:-0} # where individual ciphers are tested show just the positively ones tested #FIXME: upside down value SHOW_EACH_C=${SHOW_EACH_C:-0} # where individual ciphers are tested show just the positively ones tested #FIXME: upside down value
SNEAKY=${SNEAKY:-false} # is the referer and useragent we leave behind just usual? SNEAKY=${SNEAKY:-false} # is the referer and useragent we leave behind just usual?
QUIET=${QUIET:-false} # don't output the banner. By doing this yiu acknowledge usage term appearing in the banner QUIET=${QUIET:-false} # don't output the banner. By doing this yiu acknowledge usage term appearing in the banner
SSL_NATIVE=${SSL_NATIVE:-false} # we do per default bash sockets where possible "true": switch back to "openssl native" SSL_NATIVE=${SSL_NATIVE:-false} # we do per default bash sockets where possible "true": switch back to "openssl native"
ASSUMING_HTTP=${ASSUMING_HTTP:-false} # in seldom cases (WAF, old servers, grumpy SSL) service detection fails. "True" enforces HTTP checks ASSUMING_HTTP=${ASSUMING_HTTP:-false} # in seldom cases (WAF, old servers, grumpy SSL) service detection fails. "True" enforces HTTP checks
BUGS=${BUGS:-""} # -bugs option from openssl, needed for some BIG IP F5 BUGS=${BUGS:-""} # -bugs option from openssl, needed for some BIG IP F5
DEBUG=${DEBUG:-0} # 1.: the temp files won't be erased. DEBUG=${DEBUG:-0} # 1.: the temp files won't be erased.
# 2: list more what's going on (formerly: eq VERBOSE=1, VERBERR=true), lists some errors of connections # 2: list more what's going on (formerly: eq VERBOSE=1, VERBERR=true), lists some errors of connections
# 3: slight hexdumps + other info, # 3: slight hexdumps + other info,
# 4: display bytes sent via sockets, 5: display bytes received via sockets, 6: whole 9 yards # 4: display bytes sent via sockets, 5: display bytes received via sockets, 6: whole 9 yards
WIDE=${WIDE:-false} # whether to display for some options the cipher or the table with hexcode/KX,Enc,strength etc. WIDE=${WIDE:-false} # whether to display for some options the cipher or the table with hexcode/KX,Enc,strength etc.
LOGFILE=${LOGILE-""} # logfile if used LOGFILE=${LOGILE-""} # logfile if used
@ -271,7 +271,7 @@ readonly SSLv2_CLIENT_HELLO="
###### output functions ###### ###### output functions ######
# a little bit of sanitzing with bash internal search&replace -- otherwise printf will hiccup at '%' and '--' does the rest. # a little bit of sanitzing with bash internal search&replace -- otherwise printf will hiccup at '%' and '--' does the rest.
out() { /usr/bin/printf -- "${1//%/%%}"; } out() { /usr/bin/printf -- "${1//%/%%}"; }
outln() { out "$1\n"; } outln() { out "$1\n"; }
#TODO: Still no shell injection safe but if just run it from the cmd line: that's fine #TODO: Still no shell injection safe but if just run it from the cmd line: that's fine
@ -304,10 +304,10 @@ pr_greyln() { pr_grey "$1"; outln; }
pr_litegreen() { [[ "$COLOR" -eq 2 ]] && out "\033[0;32m$1" || out "$1"; pr_off; } # This is good pr_litegreen() { [[ "$COLOR" -eq 2 ]] && out "\033[0;32m$1" || out "$1"; pr_off; } # This is good
pr_litegreenln() { pr_litegreen "$1"; outln; } pr_litegreenln() { pr_litegreen "$1"; outln; }
pr_green() { [[ "$COLOR" -eq 2 ]] && out "\033[1;32m$1" || out "$1"; pr_off; } # This is the best pr_green() { [[ "$COLOR" -eq 2 ]] && out "\033[1;32m$1" || out "$1"; pr_off; } # This is the best
pr_greenln() { pr_green "$1"; outln; } pr_greenln() { pr_green "$1"; outln; }
pr_yellow() { [[ "$COLOR" -eq 2 ]] && out "\033[1;33m$1" || out "$1"; pr_off; } # academic or minor problem pr_yellow() { [[ "$COLOR" -eq 2 ]] && out "\033[1;33m$1" || out "$1"; pr_off; } # academic or minor problem
pr_yellowln() { pr_yellow "$1"; outln; } pr_yellowln() { pr_yellow "$1"; outln; }
pr_brown() { [[ "$COLOR" -eq 2 ]] && out "\033[0;33m$1" || out "$1"; pr_off; } # it is not a bad problem but you shouldn't do this pr_brown() { [[ "$COLOR" -eq 2 ]] && out "\033[0;33m$1" || out "$1"; pr_off; } # it is not a bad problem but you shouldn't do this
pr_brownln() { pr_brown "$1"; outln; } pr_brownln() { pr_brown "$1"; outln; }
@ -317,7 +317,7 @@ pr_brownln() { pr_brown "$1"; outln; }
pr_off() { [[ "$COLOR" -ne 0 ]] && out "\033[m\c"; } pr_off() { [[ "$COLOR" -ne 0 ]] && out "\033[m\c"; }
pr_bold() { [[ "$COLOR" -ne 0 ]] && out "\033[1m$1" || out "$1"; pr_off; } pr_bold() { [[ "$COLOR" -ne 0 ]] && out "\033[1m$1" || out "$1"; pr_off; }
pr_boldln() { pr_bold "$1" ; outln; } pr_boldln() { pr_bold "$1" ; outln; }
pr_italic() { [[ "$COLOR" -ne 0 ]] && out "\033[3m$1" || out "$1"; pr_off; } pr_italic() { [[ "$COLOR" -ne 0 ]] && out "\033[3m$1" || out "$1"; pr_off; }
pr_underline() { [[ "$COLOR" -ne 0 ]] && out "\033[4m$1" || out "$1"; pr_off; } pr_underline() { [[ "$COLOR" -ne 0 ]] && out "\033[4m$1" || out "$1"; pr_off; }
pr_reverse() { [[ "$COLOR" -ne 0 ]] && out "\033[7m$1" || out "$1"; pr_off; } pr_reverse() { [[ "$COLOR" -ne 0 ]] && out "\033[7m$1" || out "$1"; pr_off; }
pr_reverse_bold() { [[ "$COLOR" -ne 0 ]] && out "\033[7m\033[1m$1" || out "$1"; pr_off; } pr_reverse_bold() { [[ "$COLOR" -ne 0 ]] && out "\033[7m\033[1m$1" || out "$1"; pr_off; }
@ -475,7 +475,7 @@ is_ipv6addr() {
#check on chars allowed: #check on chars allowed:
[[ -n "$(tr -d '0-9:a-fA-F ' <<< "$1" | sed -e '/^$/d')" ]] && \ [[ -n "$(tr -d '0-9:a-fA-F ' <<< "$1" | sed -e '/^$/d')" ]] && \
return 1 return 1
return 0 return 0
} }
@ -596,7 +596,7 @@ run_http_header() {
if [[ $? -eq 0 ]]; then if [[ $? -eq 0 ]]; then
# we do the get command again as it terminated within $HEADER_MAXSLEEP. Thus it didn't hang, we do it # we do the get command again as it terminated within $HEADER_MAXSLEEP. Thus it didn't hang, we do it
# again in the foreground ito get an ccurate header time! # again in the foreground ito get an ccurate header time!
printf "$GET_REQ11" | $OPENSSL s_client $OPTIMAL_PROTO $BUGS -quiet -ign_eof -connect $NODEIP:$PORT $PROXY $SNI >$HEADERFILE 2>$ERRFILE printf "$GET_REQ11" | $OPENSSL s_client $OPTIMAL_PROTO $BUGS -quiet -ign_eof -connect $NODEIP:$PORT $PROXY $SNI >$HEADERFILE 2>$ERRFILE
NOW_TIME=$(date "+%s") NOW_TIME=$(date "+%s")
HTTP_TIME=$(awk -F': ' '/^date:/ { print $2 } /^Date:/ { print $2 }' $HEADERFILE) HTTP_TIME=$(awk -F': ' '/^date:/ { print $2 } /^Date:/ { print $2 }' $HEADERFILE)
HAD_SLEPT=0 HAD_SLEPT=0
@ -630,7 +630,7 @@ run_http_header() {
pr_bold " HTTP Status Code " pr_bold " HTTP Status Code "
[[ -z "$status_code" ]] && pr_litemagentaln "No status code" && return 3 [[ -z "$status_code" ]] && pr_litemagentaln "No status code" && return 3
out " $status_code$msg_thereafter" out " $status_code$msg_thereafter"
case $status_code in case $status_code in
301|302|307|308) out ", redirecting to \"$(grep -a '^Location' $HEADERFILE | sed 's/Location: //' | tr -d '\r\n')\"" ;; 301|302|307|308) out ", redirecting to \"$(grep -a '^Location' $HEADERFILE | sed 's/Location: //' | tr -d '\r\n')\"" ;;
200) ;; 200) ;;
@ -639,7 +639,7 @@ run_http_header() {
401) grep -aq "^WWW-Authenticate" $HEADERFILE && out " "; strip_lf "$(grep -a "^WWW-Authenticate" $HEADERFILE)" 401) grep -aq "^WWW-Authenticate" $HEADERFILE && out " "; strip_lf "$(grep -a "^WWW-Authenticate" $HEADERFILE)"
;; ;;
403) ;; 403) ;;
404) out " (Hint: supply a path which doesn't give a \"$status_code$msg_thereafter\")" ;; 404) out " (Hint: supply a path which doesn't give a \"$status_code$msg_thereafter\")" ;;
405) ;; 405) ;;
*) pr_litemagenta ". Oh, didn't expect a $status_code$msg_thereafter";; *) pr_litemagenta ". Oh, didn't expect a $status_code$msg_thereafter";;
esac esac
@ -657,7 +657,7 @@ detect_ipv4() {
local result local result
local first=true local first=true
local spaces=" " local spaces=" "
if [[ ! -s $HEADERFILE ]]; then if [[ ! -s $HEADERFILE ]]; then
run_http_header "$1" || return 3 run_http_header "$1" || return 3
fi fi
@ -665,7 +665,7 @@ detect_ipv4() {
# remove pagespeed header as it is mistakenly identified as ipv4 address https://github.com/drwetter/testssl.sh/issues/158 # remove pagespeed header as it is mistakenly identified as ipv4 address https://github.com/drwetter/testssl.sh/issues/158
# also facebook has a CSP rule for 127.0.0.1 # also facebook has a CSP rule for 127.0.0.1
if egrep -vi "pagespeed|page-speed|Content-Security-Policy" $HEADERFILE | grep -iqE "$ipv4address"; then if egrep -vi "pagespeed|page-speed|Content-Security-Policy" $HEADERFILE | grep -iqE "$ipv4address"; then
pr_bold " IPv4 address in header " pr_bold " IPv4 address in header "
while read line; do while read line; do
result="$(grep -E "$ipv4address" <<< "$line")" result="$(grep -E "$ipv4address" <<< "$line")"
result=$(strip_lf "$result") result=$(strip_lf "$result")
@ -681,7 +681,7 @@ detect_ipv4() {
fi fi
done < $HEADERFILE done < $HEADERFILE
fi fi
} }
run_http_date() { run_http_date() {
@ -914,7 +914,7 @@ run_rp_banner() {
run_http_header "$1" || return 3 run_http_header "$1" || return 3
fi fi
pr_bold " Reverse Proxy banner " pr_bold " Reverse Proxy banner "
egrep -ai '^Via:|^X-Cache|^X-Squid|^X-Varnish:|^X-Server-Name:|^X-Server-Port:|^x-forwarded' $HEADERFILE >$TMPFILE egrep -ai '^Via:|^X-Cache|^X-Squid|^X-Varnish:|^X-Server-Name:|^X-Server-Port:|^x-forwarded' $HEADERFILE >$TMPFILE
if [[ $? -ne 0 ]]; then if [[ $? -ne 0 ]]; then
outln "--" outln "--"
else else
@ -965,7 +965,7 @@ run_application_banner() {
run_cookie_flags() { # ARG1: Path, ARG2: path run_cookie_flags() { # ARG1: Path, ARG2: path
local -i nr_cookies local -i nr_cookies
local nr_httponly nr_secure local nr_httponly nr_secure
local negative_word local negative_word
if [[ ! -s $HEADERFILE ]]; then if [[ ! -s $HEADERFILE ]]; then
run_http_header "$1" || return 3 run_http_header "$1" || return 3
@ -1015,7 +1015,7 @@ run_more_flags() {
fi fi
pr_bold " Security headers " pr_bold " Security headers "
# convert spaces to | (for egrep) # convert spaces to | (for egrep)
egrep_pattern=$(echo "$good_flags2test $other_flags2test"| sed -e 's/ /|\^/g' -e 's/^/\^/g') egrep_pattern=$(echo "$good_flags2test $other_flags2test"| sed -e 's/ /|\^/g' -e 's/^/\^/g')
egrep -ai "$egrep_pattern" $HEADERFILE >$TMPFILE egrep -ai "$egrep_pattern" $HEADERFILE >$TMPFILE
if [[ $? -ne 0 ]]; then if [[ $? -ne 0 ]]; then
outln "--" outln "--"
@ -1161,7 +1161,7 @@ std_cipherlists() {
[[ $sclient_success -eq 0 ]] && \ [[ $sclient_success -eq 0 ]] && \
pr_literedln "offered (NOT ok)" || \ pr_literedln "offered (NOT ok)" || \
pr_litegreenln "not offered (OK)" ;; pr_litegreenln "not offered (OK)" ;;
3) # not totally bad 3) # not totally bad
[[ $sclient_success -eq 0 ]] && \ [[ $sclient_success -eq 0 ]] && \
pr_brownln "offered (NOT ok)" || \ pr_brownln "offered (NOT ok)" || \
outln "not offered (OK)" ;; outln "not offered (OK)" ;;
@ -1278,7 +1278,7 @@ test_just_one(){
normalize_ciphercode $hexcode normalize_ciphercode $hexcode
# is argument a number? # is argument a number?
if [[ $arg =~ $re ]]; then if [[ $arg =~ $re ]]; then
neat_list $HEXC $ciph $kx $enc | grep -qai "$arg" neat_list $HEXC $ciph $kx $enc | grep -qai "$arg"
else else
neat_list $HEXC $ciph $kx $enc | grep -qwai "$arg" neat_list $HEXC $ciph $kx $enc | grep -qwai "$arg"
fi fi
@ -1406,7 +1406,7 @@ locally_supported() {
} }
# the protocol check needs to be revamped. It sucks. # the protocol check needs to be revamped. It sucks.
# 1) we need to have a variable where the resulta are being stored so that every other test doesn't have to do this again. # 1) we need to have a variable where the resulta are being stored so that every other test doesn't have to do this again.
# 2) the code is too old and one can do that way better # 2) the code is too old and one can do that way better
# 3) HAS_SSL3/2 does already exist # 3) HAS_SSL3/2 does already exist
@ -1429,7 +1429,7 @@ run_prototest_openssl() {
# SSLv3 doesn't have SNI (openssl doesn't complain though -- yet) # SSLv3 doesn't have SNI (openssl doesn't complain though -- yet)
$OPENSSL s_client -state $1 $STARTTLS $BUGS -connect $NODEIP:$PORT $sni >$TMPFILE 2>$ERRFILE </dev/null $OPENSSL s_client -state $1 $STARTTLS $BUGS -connect $NODEIP:$PORT $sni >$TMPFILE 2>$ERRFILE </dev/null
sclient_connect_successful $? $TMPFILE sclient_connect_successful $? $TMPFILE
ret=$? ret=$?
[[ $DEBUG -eq 2 ]] && egrep "error|failure" $ERRFILE | egrep -av "unable to get local|verify error" [[ $DEBUG -eq 2 ]] && egrep "error|failure" $ERRFILE | egrep -av "unable to get local|verify error"
grep -aq "no cipher list" $TMPFILE && ret=5 # <--- important indicator for SSL2 (maybe others, too) grep -aq "no cipher list" $TMPFILE && ret=5 # <--- important indicator for SSL2 (maybe others, too)
fi fi
@ -1446,8 +1446,8 @@ run_prototest_openssl() {
# the protocol check needs to be revamped. It sucks, see above # the protocol check needs to be revamped. It sucks, see above
run_protocols() { run_protocols() {
local using_sockets=true local using_sockets=true
local supported_no_ciph1="supported but couldn't detect a cipher (may need debugging)" local supported_no_ciph1="supported but couldn't detect a cipher (may need debugging)"
local supported_no_ciph2="supported but couldn't detect a cipher" local supported_no_ciph2="supported but couldn't detect a cipher"
outln; pr_headline " Testing protocols " outln; pr_headline " Testing protocols "
@ -1475,7 +1475,7 @@ run_protocols() {
case $? in case $? in
0) pr_redln "offered (NOT ok)" ;; 0) pr_redln "offered (NOT ok)" ;;
1) pr_greenln "not offered (OK)" ;; 1) pr_greenln "not offered (OK)" ;;
5) pr_litered "$supported_no_ciph2"; 5) pr_litered "$supported_no_ciph2";
outln " (may need further attention)" ;; # protocol ok, but no cipher outln " (may need further attention)" ;; # protocol ok, but no cipher
7) ;; # no local support 7) ;; # no local support
esac esac
@ -1491,7 +1491,7 @@ run_protocols() {
0) pr_literedln "offered (NOT ok)" ;; 0) pr_literedln "offered (NOT ok)" ;;
1) pr_greenln "not offered (OK)" ;; 1) pr_greenln "not offered (OK)" ;;
2) pr_litemagentaln "#FIXME: downgraded. still missing a test case here" ;; 2) pr_litemagentaln "#FIXME: downgraded. still missing a test case here" ;;
5) pr_litered "$supported_no_ciph2"; 5) pr_litered "$supported_no_ciph2";
outln "(may need debugging)" ;; # protocol ok, but no cipher outln "(may need debugging)" ;; # protocol ok, but no cipher
7) ;; # no local support 7) ;; # no local support
esac esac
@ -1517,12 +1517,12 @@ run_protocols() {
tls_sockets "02" "$TLS_CIPHER" tls_sockets "02" "$TLS_CIPHER"
else else
run_prototest_openssl "-tls1_1" run_prototest_openssl "-tls1_1"
fi fi
case $? in case $? in
0) outln "offered" ;; # nothing wrong with it 0) outln "offered" ;; # nothing wrong with it
1) outln "not offered" ;; # neither good or bad 1) outln "not offered" ;; # neither good or bad
2) out "not offered" 2) out "not offered"
[[ $DEBUG -eq 1 ]] && out " -- downgraded" [[ $DEBUG -eq 1 ]] && out " -- downgraded"
outln ;; outln ;;
5) outln "$supported_no_ciph1" ;; # protocol ok, but no cipher 5) outln "$supported_no_ciph1" ;; # protocol ok, but no cipher
7) ;; # no local support 7) ;; # no local support
@ -1533,7 +1533,7 @@ run_protocols() {
tls_sockets "03" "$TLS12_CIPHER" tls_sockets "03" "$TLS12_CIPHER"
else else
run_prototest_openssl "-tls1_2" run_prototest_openssl "-tls1_2"
fi fi
case $? in case $? in
0) pr_greenln "offered (OK)" ;; # GCM cipher in TLS 1.2: very good! 0) pr_greenln "offered (OK)" ;; # GCM cipher in TLS 1.2: very good!
1) pr_brownln "not offered (NOT ok)" ;; # no GCM, penalty 1) pr_brownln "not offered (NOT ok)" ;; # no GCM, penalty
@ -1627,7 +1627,7 @@ read_dhbits_from_file() {
run_server_preference() { run_server_preference() {
local cipher1 cipher2 local cipher1 cipher2
local default_cipher default_proto local default_cipher default_proto
local remark4default_cipher local remark4default_cipher
local -a cipher proto local -a cipher proto
local p i local p i
local -i ret=0 local -i ret=0
@ -1635,7 +1635,7 @@ run_server_preference() {
# now reversed offline via tac, see https://github.com/thomassa/testssl.sh/commit/7a4106e839b8c3033259d66697893765fc468393 : # now reversed offline via tac, see https://github.com/thomassa/testssl.sh/commit/7a4106e839b8c3033259d66697893765fc468393 :
local list_reverse="AES256-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDH-RSA-AES256-SHA:ECDH-RSA-AES128-SHA:ECDH-RSA-DES-CBC3-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-AES128-SHA:AES256-SHA:AES128-SHA256:AES128-SHA:RC4-SHA:DES-CBC-SHA:RC4-MD5:DES-CBC3-SHA" local list_reverse="AES256-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDH-RSA-AES256-SHA:ECDH-RSA-AES128-SHA:ECDH-RSA-DES-CBC3-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-AES128-SHA:AES256-SHA:AES128-SHA256:AES128-SHA:RC4-SHA:DES-CBC-SHA:RC4-MD5:DES-CBC3-SHA"
local has_cipher_order=true local has_cipher_order=true
outln outln
pr_headlineln " Testing server preferences " pr_headlineln " Testing server preferences "
outln outln
@ -1651,7 +1651,7 @@ run_server_preference() {
# now it still could be that we hit this bug: https://github.com/drwetter/testssl.sh/issues/188 # now it still could be that we hit this bug: https://github.com/drwetter/testssl.sh/issues/188
# workaround is to connect with a protocol # workaround is to connect with a protocol
debugme out "(workaround #188) " debugme out "(workaround #188) "
determine_optimal_proto $STARTTLS_PROTOCOL determine_optimal_proto $STARTTLS_PROTOCOL
$OPENSSL s_client $STARTTLS $STARTTLS_OPTIMAL_PROTO -cipher $list_fwd $BUGS -connect $NODEIP:$PORT $PROXY $SNI </dev/null 2>$ERRFILE >$TMPFILE $OPENSSL s_client $STARTTLS $STARTTLS_OPTIMAL_PROTO -cipher $list_fwd $BUGS -connect $NODEIP:$PORT $PROXY $SNI </dev/null 2>$ERRFILE >$TMPFILE
if ! sclient_connect_successful $? $TMPFILE; then if ! sclient_connect_successful $? $TMPFILE; then
pr_litemagenta "no matching cipher in this list found (pls report this): " pr_litemagenta "no matching cipher in this list found (pls report this): "
@ -1691,7 +1691,7 @@ run_server_preference() {
*TLSv1) outln $default_proto ;; *TLSv1) outln $default_proto ;;
*SSLv2) pr_redln $default_proto ;; *SSLv2) pr_redln $default_proto ;;
*SSLv3) pr_redln $default_proto ;; *SSLv3) pr_redln $default_proto ;;
"") pr_litemagenta "default proto empty"; [[ $OSSL_VER == 1.0.2* ]] && outln " (Hint: if IIS6 give OpenSSL 1.01 a try)" ;; "") pr_litemagenta "default proto empty"; [[ $OSSL_VER == 1.0.2* ]] && outln " (Hint: if IIS6 give OpenSSL 1.01 a try)" ;;
*) pr_litemagenta "FIXME line $LINENO: $default_proto" ;; *) pr_litemagenta "FIXME line $LINENO: $default_proto" ;;
esac esac
@ -1849,7 +1849,7 @@ get_all_certs() {
pr_litemagenta "problem getting all certs" pr_litemagenta "problem getting all certs"
savedir=$(pwd); cd $TEMPDIR savedir=$(pwd); cd $TEMPDIR
# http://backreference.org/2010/05/09/ocsp-verification-with-openssl/ # http://backreference.org/2010/05/09/ocsp-verification-with-openssl/
awk -v n=-1 '/-----BEGIN CERTIFICATE-----/{ inc=1; n++ } awk -v n=-1 '/-----BEGIN CERTIFICATE-----/{ inc=1; n++ }
inc { print > ("level" n ".crt") } inc { print > ("level" n ".crt") }
/---END CERTIFICATE-----/{ inc=0 }' $TEMPDIR/allcerts.txt /---END CERTIFICATE-----/{ inc=0 }' $TEMPDIR/allcerts.txt
nrsaved=$(count_words "$(echo level?.crt 2>/dev/null)") nrsaved=$(count_words "$(echo level?.crt 2>/dev/null)")
@ -1880,7 +1880,7 @@ verify_retcode_helper() {
determine_trust() { determine_trust() {
local i=1 local i=1
local bundle_fname local bundle_fname
local -a certificate_file verify_retcode trust local -a certificate_file verify_retcode trust
local ok_was="" local ok_was=""
local notok_was="" local notok_was=""
local code local code
@ -1897,7 +1897,7 @@ determine_trust() {
for bundle_fname in $ca_bundles; do for bundle_fname in $ca_bundles; do
certificate_file[i]=$(basename $bundle_fname | sed 's/\.pem//') certificate_file[i]=$(basename $bundle_fname | sed 's/\.pem//')
if [[ ! -r $bundle_fname ]]; then if [[ ! -r $bundle_fname ]]; then
pr_litemagentaln "\"$bundle_fname\" cannot be found / not readable" pr_litemagentaln "\"$bundle_fname\" cannot be found / not readable"
return 7 return 7
fi fi
debugme printf -- " %-12s" "${certificate_file[i]}" debugme printf -- " %-12s" "${certificate_file[i]}"
@ -1917,10 +1917,10 @@ determine_trust() {
debugme out " " debugme out " "
# all stores ok # all stores ok
if ${trust[1]} && ${trust[2]} && ${trust[3]} && ${trust[4]}; then if ${trust[1]} && ${trust[2]} && ${trust[3]} && ${trust[4]}; then
pr_litegreen "Ok " pr_litegreen "Ok "
# at least one failed # at least one failed
else else
pr_litered "NOT ok" pr_litered "NOT ok"
# all failed (we assume with the same issue) # all failed (we assume with the same issue)
if ! ${trust[1]} && ! ${trust[2]} && ! ${trust[3]} && ! ${trust[4]}; then if ! ${trust[1]} && ! ${trust[2]} && ! ${trust[3]} && ! ${trust[4]}; then
verify_retcode_helper "${verify_retcode[2]}" verify_retcode_helper "${verify_retcode[2]}"
@ -1985,7 +1985,7 @@ tls_time() {
sclient_connect_successful() { sclient_connect_successful() {
[[ $1 -eq 0 ]] && return 0 [[ $1 -eq 0 ]] && return 0
[[ -n $(awk '/Master-Key: / { print $2 }' "$2") ]] && return 0 [[ -n $(awk '/Master-Key: / { print $2 }' "$2") ]] && return 0
# second check saved like # second check saved like
# fgrep 'Cipher is (NONE)' "$2" &> /dev/null && return 1 # fgrep 'Cipher is (NONE)' "$2" &> /dev/null && return 1
# what's left now is: master key empty and Session-ID not empty ==> probably client based auth with x509 certificate # what's left now is: master key empty and Session-ID not empty ==> probably client based auth with x509 certificate
return 1 return 1
@ -2045,7 +2045,7 @@ run_server_defaults() {
if [[ -z "$TLS_EXTENSIONS" ]]; then if [[ -z "$TLS_EXTENSIONS" ]]; then
outln "(none)" outln "(none)"
else else
#echo $extensions | sed 's/ /,/g' #echo $extensions | sed 's/ /,/g'
outln "$TLS_EXTENSIONS" outln "$TLS_EXTENSIONS"
fi fi
@ -2062,7 +2062,7 @@ run_server_defaults() {
out "$lifetime $unit " out "$lifetime $unit "
pr_yellowln "(PFS requires session ticket keys to be rotated <= daily)" pr_yellowln "(PFS requires session ticket keys to be rotated <= daily)"
fi fi
pr_bold " SSL Session ID support " pr_bold " SSL Session ID support "
if $NO_SSL_SESSIONID; then if $NO_SSL_SESSIONID; then
outln "no" outln "no"
@ -2194,7 +2194,7 @@ run_server_defaults() {
out " (" out " ("
pr_dquoted "$issuer_O" pr_dquoted "$issuer_O"
if [[ -n "$issuer_C" ]]; then if [[ -n "$issuer_C" ]]; then
out " from " out " from "
pr_dquoted "$issuer_C" pr_dquoted "$issuer_C"
fi fi
outln ")" outln ")"
@ -2210,14 +2210,14 @@ run_server_defaults() {
[[ 2.16.578.1.26.1.3.3 == "$policy_oid" ]] || \ [[ 2.16.578.1.26.1.3.3 == "$policy_oid" ]] || \
[[ 1.3.6.1.4.1.17326.10.14.2.1.2 == "$policy_oid" ]] || \ [[ 1.3.6.1.4.1.17326.10.14.2.1.2 == "$policy_oid" ]] || \
[[ 1.3.6.1.4.1.17326.10.8.12.1.2 == "$policy_oid" ]] || \ [[ 1.3.6.1.4.1.17326.10.8.12.1.2 == "$policy_oid" ]] || \
[[ 1.3.6.1.4.1.13177.10.1.3.10 == "$policy_oid" ]] ; then [[ 1.3.6.1.4.1.13177.10.1.3.10 == "$policy_oid" ]] ; then
out "yes " out "yes "
else else
out "no " out "no "
fi fi
debugme echo "($(newline_to_spaces "$policy_oid"))" debugme echo "($(newline_to_spaces "$policy_oid"))"
outln outln
#TODO: use browser OIDs: #TODO: use browser OIDs:
# https://mxr.mozilla.org/mozilla-central/source/security/certverifier/ExtendedValidation.cpp # https://mxr.mozilla.org/mozilla-central/source/security/certverifier/ExtendedValidation.cpp
# http://src.chromium.org/chrome/trunk/src/net/cert/ev_root_ca_metadata.cc # http://src.chromium.org/chrome/trunk/src/net/cert/ev_root_ca_metadata.cc
# https://certs.opera.com/03/ev-oids.xml # https://certs.opera.com/03/ev-oids.xml
@ -2264,7 +2264,7 @@ run_server_defaults() {
if [[ $(count_lines "$crl") -eq 1 ]]; then if [[ $(count_lines "$crl") -eq 1 ]]; then
outln "$crl" outln "$crl"
else # more than one CRL else # more than one CRL
out_row_aligned "$crl" "$spaces" out_row_aligned "$crl" "$spaces"
fi fi
else else
pr_litemagentaln "no parsable output \"$url\", pls report" pr_litemagentaln "no parsable output \"$url\", pls report"
@ -2293,7 +2293,7 @@ run_server_defaults() {
fi fi
outln outln
# if we call tls_time before tmpfile_handle it throws an error because the function tls_sockets removed $TMPFILE # if we call tls_time before tmpfile_handle it throws an error because the function tls_sockets removed $TMPFILE
# already -- and that was a different one -- means that would get overwritten anyway # already -- and that was a different one -- means that would get overwritten anyway
tmpfile_handle $FUNCNAME.txt tmpfile_handle $FUNCNAME.txt
@ -2429,7 +2429,7 @@ run_spdy() {
else else
# now comes a strange thing: "Protocols advertised by server:" is empty but connection succeeded # now comes a strange thing: "Protocols advertised by server:" is empty but connection succeeded
if echo $tmpstr | egrep -aq "spdy|http" ; then if echo $tmpstr | egrep -aq "spdy|http" ; then
out "$tmpstr" out "$tmpstr"
outln " (advertised)" outln " (advertised)"
ret=0 ret=0
else else
@ -2451,7 +2451,7 @@ starttls_line() {
debugme echo -e "\n=== sending \"$1\" ..." debugme echo -e "\n=== sending \"$1\" ..."
echo -e "$1" >&5 echo -e "$1" >&5
# we don't know how much to read and it's blocking! So we just put a cat into the # we don't know how much to read and it's blocking! So we just put a cat into the
# background and read until $STARTTLS_SLEEP and: cross our fingers # background and read until $STARTTLS_SLEEP and: cross our fingers
cat <&5 >$TMPFILE & cat <&5 >$TMPFILE &
wait_kill $! $STARTTLS_SLEEP wait_kill $! $STARTTLS_SLEEP
@ -2461,7 +2461,7 @@ starttls_line() {
if egrep -q "$2" $TMPFILE; then if egrep -q "$2" $TMPFILE; then
debugme echo "---> reply matched \"$2\"" debugme echo "---> reply matched \"$2\""
else else
# slow down for exim and friends who need a proper handshake:, see # slow down for exim and friends who need a proper handshake:, see
# https://github.com/drwetter/testssl.sh/issues/218 # https://github.com/drwetter/testssl.sh/issues/218
FAST_STARTTLS=false FAST_STARTTLS=false
debugme echo -e "\n=== sending with automated FAST_STARTTLS=false \"$1\" ..." debugme echo -e "\n=== sending with automated FAST_STARTTLS=false \"$1\" ..."
@ -2547,7 +2547,7 @@ fd_socket() {
;; ;;
smtp|smtps) # SMTP, see https://tools.ietf.org/html/rfc4217 smtp|smtps) # SMTP, see https://tools.ietf.org/html/rfc4217
$FAST_STARTTLS || starttls_just_read $FAST_STARTTLS || starttls_just_read
$FAST_STARTTLS || starttls_line "EHLO testssl.sh" "220|250" && starttls_just_send "EHLO testssl.sh" $FAST_STARTTLS || starttls_line "EHLO testssl.sh" "220|250" && starttls_just_send "EHLO testssl.sh"
starttls_line "STARTTLS" "220" starttls_line "STARTTLS" "220"
;; ;;
pop3|pop3s) # POP, see https://tools.ietf.org/html/rfc2595 pop3|pop3s) # POP, see https://tools.ietf.org/html/rfc2595
@ -2575,9 +2575,9 @@ fd_socket() {
[[ -z $XMPP_HOST ]] && XMPP_HOST="$NODE" [[ -z $XMPP_HOST ]] && XMPP_HOST="$NODE"
jabber=$(cat <<EOF jabber=$(cat <<EOF
<?xml version='1.0' ?> <?xml version='1.0' ?>
<stream:stream <stream:stream
xmlns:stream='http://etherx.jabber.org/streams' xmlns:stream='http://etherx.jabber.org/streams'
xmlns='jabber:client' xmlns='jabber:client'
to='$XMPP_HOST' to='$XMPP_HOST'
xml:lang='en' xml:lang='en'
version='1.0'> version='1.0'>
@ -2715,7 +2715,7 @@ parse_tls_serverhello() {
[[ "$DEBUG" -eq 5 ]] && echo $tls_hello_ascii # one line without any blanks [[ "$DEBUG" -eq 5 ]] && echo $tls_hello_ascii # one line without any blanks
if [[ -z "$tls_hello_ascii" ]]; then if [[ -z "$tls_hello_ascii" ]]; then
debugme echo "server hello empty, TCP connection closed" debugme echo "server hello empty, TCP connection closed"
return 1 # no server hello received return 1 # no server hello received
fi fi
@ -2733,14 +2733,14 @@ parse_tls_serverhello() {
if [[ $tls_content_type == "15" ]]; then # TLS ALERT if [[ $tls_content_type == "15" ]]; then # TLS ALERT
tls_err_level=${tls_hello_ascii:10:2} # 1: warning, 2: fatal tls_err_level=${tls_hello_ascii:10:2} # 1: warning, 2: fatal
tls_err_descr=${tls_hello_ascii:12:2} # 112/0x70: Unrecognized name, 111/0x6F: certificate_unobtainable, tls_err_descr=${tls_hello_ascii:12:2} # 112/0x70: Unrecognized name, 111/0x6F: certificate_unobtainable,
# 113/0x71: bad_certificate_status_response, #114/0x72: bad_certificate_hash_value # 113/0x71: bad_certificate_status_response, #114/0x72: bad_certificate_hash_value
if [[ $DEBUG -ge 2 ]]; then if [[ $DEBUG -ge 2 ]]; then
echo "tls_protocol (reclyr): 0x$tls_protocol" echo "tls_protocol (reclyr): 0x$tls_protocol"
echo "tls_content_type: 0x$tls_content_type" echo "tls_content_type: 0x$tls_content_type"
echo "tls_len_all: $tls_len_all" echo "tls_len_all: $tls_len_all"
echo "tls_err_descr: 0x${tls_err_descr} / = $(hex2dec ${tls_err_descr})" echo "tls_err_descr: 0x${tls_err_descr} / = $(hex2dec ${tls_err_descr})"
echo "tls_err_level: ${tls_err_level} (warning:1, fatal:2)" echo "tls_err_level: ${tls_err_level} (warning:1, fatal:2)"
fi fi
# now, here comes a strange thing... -- on the first glance # now, here comes a strange thing... -- on the first glance
# IF an apache 2.2/2.4 server e.g. has a default servername configured but we send SNI <myhostname> # IF an apache 2.2/2.4 server e.g. has a default servername configured but we send SNI <myhostname>
@ -2847,7 +2847,7 @@ socksend_tls_clienthello() {
local len_sni_listlen len_sni_ext len_extension_hex local len_sni_listlen len_sni_ext len_extension_hex
local cipher_suites len_ciph_suites len_ciph_suites_word local cipher_suites len_ciph_suites len_ciph_suites_word
local len_client_hello_word len_all_word local len_client_hello_word len_all_word
#len_servername=$(echo ${#NODE}) #len_servername=$(echo ${#NODE})
len_servername=${#NODE} len_servername=${#NODE}
hexdump_format_str="$len_servername/1 \"%02x,\"" hexdump_format_str="$len_servername/1 \"%02x,\""
@ -2937,10 +2937,10 @@ socksend_tls_clienthello() {
extension_signature_algorithms=" extension_signature_algorithms="
00, 0d, # Type: signature_algorithms , see RFC 5246 00, 0d, # Type: signature_algorithms , see RFC 5246
00, 20, # len 00, 20, # len
00,1e, 06,01, 06,02, 06,03, 05,01, 05,02, 05,03, 00,1e, 06,01, 06,02, 06,03, 05,01, 05,02, 05,03,
04,01, 04,02, 04,03, 03,01, 03,02, 03,03, 02,01, 02,02, 02,03" 04,01, 04,02, 04,03, 03,01, 03,02, 03,03, 02,01, 02,02, 02,03"
# Extension: Haertbeat 00 0f # Extension: Haertbeat 00 0f
# len 00 01 # len 00 01
# peer allowed to send requests 01 # peer allowed to send requests 01
@ -2968,7 +2968,7 @@ socksend_tls_clienthello() {
return 0 return 0
} }
# arg1: TLS version low byte # arg1: TLS version low byte
# (00: SSLv3, 01: TLS 1.0, 02: TLS 1.1, 03: TLS 1.2) # (00: SSLv3, 01: TLS 1.0, 02: TLS 1.1, 03: TLS 1.2)
tls_sockets() { tls_sockets() {
local -i ret=0 local -i ret=0
@ -3233,7 +3233,7 @@ run_ccs_injection(){
if [[ $DEBUG -ge 3 ]]; then if [[ $DEBUG -ge 3 ]]; then
outln "\n1st reply: " outln "\n1st reply: "
out "$SOCKREPLY" | "${HEXDUMPVIEW[@]}" | head -20 out "$SOCKREPLY" | "${HEXDUMPVIEW[@]}" | head -20
# ok: 15 | 0301 | 02 | 02 | 0a # ok: 15 | 0301 | 02 | 02 | 0a
# ALERT | TLS 1.0 | Length=2 | Unexpected Message (0a) # ALERT | TLS 1.0 | Length=2 | Unexpected Message (0a)
# or just timed out # or just timed out
outln outln
@ -3247,7 +3247,7 @@ run_ccs_injection(){
if [[ $DEBUG -ge 3 ]]; then if [[ $DEBUG -ge 3 ]]; then
outln "\n2nd reply: " outln "\n2nd reply: "
printf -- "$SOCKREPLY" | "${HEXDUMPVIEW[@]}" printf -- "$SOCKREPLY" | "${HEXDUMPVIEW[@]}"
# not ok: 15 | 0301 | 02 | 02 | 15 # not ok: 15 | 0301 | 02 | 02 | 15
# ALERT | TLS 1.0 | Length=2 | Decryption failed (21) # ALERT | TLS 1.0 | Length=2 | Decryption failed (21)
# ok: 0a or nothing: ==> RST # ok: 0a or nothing: ==> RST
outln outln
@ -3297,7 +3297,7 @@ run_renego() {
*) pr_litemagentaln "FIXME (bug): $sec_renego" ;; *) pr_litemagentaln "FIXME (bug): $sec_renego" ;;
esac esac
else else
pr_litemagentaln "handshake didn't succeed" pr_litemagentaln "handshake didn't succeed"
fi fi
pr_bold " Secure Client-Initiated Renegotiation " # RFC 5746 pr_bold " Secure Client-Initiated Renegotiation " # RFC 5746
@ -3320,7 +3320,7 @@ run_renego() {
else else
# We need up to two tries here, as some LiteSpeed servers don't answer on "R" and block. Thus first try in the background # We need up to two tries here, as some LiteSpeed servers don't answer on "R" and block. Thus first try in the background
# msg enables us to look deeper into it while debugging # msg enables us to look deeper into it while debugging
echo R | $OPENSSL s_client $OPTIMAL_PROTO $BUGS $legacycmd $STARTTLS -msg -connect $NODEIP:$PORT $SNI $PROXY >$TMPFILE 2>>$ERRFILE & echo R | $OPENSSL s_client $OPTIMAL_PROTO $BUGS $legacycmd $STARTTLS -msg -connect $NODEIP:$PORT $SNI $PROXY >$TMPFILE 2>>$ERRFILE &
wait_kill $! $HEADER_MAXSLEEP wait_kill $! $HEADER_MAXSLEEP
if [[ $? -eq 3 ]]; then if [[ $? -eq 3 ]]; then
pr_litegreen "likely not vulnerable (OK)"; outln " (timed out)" # it hung pr_litegreen "likely not vulnerable (OK)"; outln " (timed out)" # it hung
@ -3353,7 +3353,7 @@ run_crime() {
# means anyway "game over", w/wo CRIME # means anyway "game over", w/wo CRIME
# www.h-online.com/security/news/item/Vulnerability-in-SSL-encryption-is-barely-exploitable-1708604.html # www.h-online.com/security/news/item/Vulnerability-in-SSL-encryption-is-barely-exploitable-1708604.html
[ $VULN_COUNT -le $VULN_THRESHLD ] && outln && pr_headlineln " Testing for CRIME vulnerability " && outln [ $VULN_COUNT -le $VULN_THRESHLD ] && outln && pr_headlineln " Testing for CRIME vulnerability " && outln
pr_bold " CRIME, TLS " ; out "(CVE-2012-4929) " pr_bold " CRIME, TLS " ; out "(CVE-2012-4929) "
# first we need to test whether OpenSSL binary has zlib support # first we need to test whether OpenSSL binary has zlib support
@ -3363,11 +3363,11 @@ run_crime() {
return 7 return 7
fi fi
[[ "$OSSL_VER" == "*0.9.8*" ]] && addcmd="-no_ssl2" [[ "$OSSL_VER" == "*0.9.8*" ]] && addcmd="-no_ssl2"
$OPENSSL s_client $OPTIMAL_PROTO $BUGS $addcmd $STARTTLS -connect $NODEIP:$PORT $PROXY $SNI </dev/null &>$TMPFILE $OPENSSL s_client $OPTIMAL_PROTO $BUGS $addcmd $STARTTLS -connect $NODEIP:$PORT $PROXY $SNI </dev/null &>$TMPFILE
if grep -a Compression $TMPFILE | grep -aq NONE >/dev/null; then if grep -a Compression $TMPFILE | grep -aq NONE >/dev/null; then
pr_litegreen "not vulnerable (OK)" pr_litegreen "not vulnerable (OK)"
if [[ $SERVICE != "HTTP" ]] && ! $CLIENT_AUTH; then if [[ $SERVICE != "HTTP" ]] && ! $CLIENT_AUTH; then
out " (not using HTTP anyway)" out " (not using HTTP anyway)"
fi fi
ret=0 ret=0
@ -3573,7 +3573,7 @@ run_freak() {
local exportrsa_cipher_list="EXP1024-DES-CBC-SHA:EXP1024-RC4-SHA:EXP-EDH-RSA-DES-CBC-SHA:EXP-DH-RSA-DES-CBC-SHA:EXP-DES-CBC-SHA:EXP-RC2-CBC-MD5:EXP-RC2-CBC-MD5:EXP-RC4-MD5:EXP-RC4-MD5" local exportrsa_cipher_list="EXP1024-DES-CBC-SHA:EXP1024-RC4-SHA:EXP-EDH-RSA-DES-CBC-SHA:EXP-DH-RSA-DES-CBC-SHA:EXP-DES-CBC-SHA:EXP-RC2-CBC-MD5:EXP-RC2-CBC-MD5:EXP-RC4-MD5:EXP-RC4-MD5"
local addtl_warning="" local addtl_warning=""
[ $VULN_COUNT -le $VULN_THRESHLD ] && outln && pr_headlineln " Testing for FREAK attack " && outln [ $VULN_COUNT -le $VULN_THRESHLD ] && outln && pr_headlineln " Testing for FREAK attack " && outln
pr_bold " FREAK"; out " (CVE-2015-0204) " pr_bold " FREAK"; out " (CVE-2015-0204) "
nr_supported_ciphers=$(count_ciphers $(actually_supported_ciphers $exportrsa_cipher_list)) nr_supported_ciphers=$(count_ciphers $(actually_supported_ciphers $exportrsa_cipher_list))
@ -3615,7 +3615,7 @@ run_logjam() {
local -i nr_supported_ciphers=0 local -i nr_supported_ciphers=0
local addtl_warning="" local addtl_warning=""
[ $VULN_COUNT -le $VULN_THRESHLD ] && outln && pr_headlineln " Testing for LOGJAM vulnerability " && outln [ $VULN_COUNT -le $VULN_THRESHLD ] && outln && pr_headlineln " Testing for LOGJAM vulnerability " && outln
pr_bold " LOGJAM"; out " (CVE-2015-4000), experimental " pr_bold " LOGJAM"; out " (CVE-2015-4000), experimental "
nr_supported_ciphers=$(count_ciphers $(actually_supported_ciphers $exportdhe_cipher_list)) nr_supported_ciphers=$(count_ciphers $(actually_supported_ciphers $exportdhe_cipher_list))
@ -3639,7 +3639,7 @@ run_logjam() {
$HAS_DH_BITS && addtl_warning="$addtl_warning See below for any DH ciphers + bit size" $HAS_DH_BITS && addtl_warning="$addtl_warning See below for any DH ciphers + bit size"
fi fi
fi fi
if [[ $sclient_success -eq 0 ]]; then if [[ $sclient_success -eq 0 ]]; then
pr_red "VULNERABLE (NOT ok)"; out ", uses DHE EXPORT ciphers, common primes not checked." pr_red "VULNERABLE (NOT ok)"; out ", uses DHE EXPORT ciphers, common primes not checked."
else else
@ -3725,7 +3725,7 @@ run_beast(){
if [[ $sclient_success -eq 0 ]]; then if [[ $sclient_success -eq 0 ]]; then
[[ -n "$higher_proto_supported" ]] && \ [[ -n "$higher_proto_supported" ]] && \
pr_yellowln "available" || \ pr_yellowln "available" || \
pr_brownln "available" pr_brownln "available"
else else
outln "not a/v" outln "not a/v"
@ -3882,10 +3882,10 @@ get_install_dir() {
#INSTALL_DIR=$(cd "$(dirname "$0")" && pwd)/$(basename "$0") #INSTALL_DIR=$(cd "$(dirname "$0")" && pwd)/$(basename "$0")
INSTALL_DIR=$(dirname ${BASH_SOURCE[0]}) INSTALL_DIR=$(dirname ${BASH_SOURCE[0]})
[[ -r "$RUN_DIR/etc/mapping-rfc.txt" ]] && MAPPING_FILE_RFC="$RUN_DIR/etc/mapping-rfc.txt" [[ -r "$RUN_DIR/etc/mapping-rfc.txt" ]] && MAPPING_FILE_RFC="$RUN_DIR/etc/mapping-rfc.txt"
[[ -r "$INSTALL_DIR/etc/mapping-rfc.txt" ]] && MAPPING_FILE_RFC="$INSTALL_DIR/etc/mapping-rfc.txt" [[ -r "$INSTALL_DIR/etc/mapping-rfc.txt" ]] && MAPPING_FILE_RFC="$INSTALL_DIR/etc/mapping-rfc.txt"
# those will disapper: # those will disapper:
[[ -r "$RUN_DIR/mapping-rfc.txt" ]] && MAPPING_FILE_RFC="$RUN_DIR/mapping-rfc.txt" [[ -r "$RUN_DIR/mapping-rfc.txt" ]] && MAPPING_FILE_RFC="$RUN_DIR/mapping-rfc.txt"
[[ -r "$INSTALL_DIR/mapping-rfc.txt" ]] && MAPPING_FILE_RFC="$INSTALL_DIR/mapping-rfc.txt" [[ -r "$INSTALL_DIR/mapping-rfc.txt" ]] && MAPPING_FILE_RFC="$INSTALL_DIR/mapping-rfc.txt"
# we haven't found the mapping file yet... # we haven't found the mapping file yet...
@ -3934,7 +3934,7 @@ test_openssl_suffix() {
fi fi
return 1 return 1
} }
find_openssl_binary() { find_openssl_binary() {
# 0. check environment variable whether it's executable # 0. check environment variable whether it's executable
@ -4065,7 +4065,7 @@ $PROG_NAME <options> URI ("$PROG_NAME URI" does everything except -E)
-t, --starttls <protocol> does a default run against a STARTTLS enabled <protocol> -t, --starttls <protocol> does a default run against a STARTTLS enabled <protocol>
--xmpphost <to_domain> for STARTTLS enabled XMPP it supplies the XML stream to-'' domain -- sometimes needed --xmpphost <to_domain> for STARTTLS enabled XMPP it supplies the XML stream to-'' domain -- sometimes needed
--mx <domain/host> tests MX records from high to low priority (STARTTLS, port 25) --mx <domain/host> tests MX records from high to low priority (STARTTLS, port 25)
--ip <ip> a) tests the supplied <ip> v4 or v6 address instead of resolving host(s) in URI --ip <ip> a) tests the supplied <ip> v4 or v6 address instead of resolving host(s) in URI
b) arg "one" means: just test the first DNS returns (useful for multiple IPs) b) arg "one" means: just test the first DNS returns (useful for multiple IPs)
--file <fname> mass testing option: Reads command lines from <fname>, one line per instance. --file <fname> mass testing option: Reads command lines from <fname>, one line per instance.
Comments via # allowed, EOF signals end of <fname>. Implicitly turns on "--warnings batch" Comments via # allowed, EOF signals end of <fname>. Implicitly turns on "--warnings batch"
@ -4108,7 +4108,7 @@ maketempf() {
TEMPDIR=$(mktemp -d /tmp/ssltester.XXXXXX) || exit -6 TEMPDIR=$(mktemp -d /tmp/ssltester.XXXXXX) || exit -6
TMPFILE=$TEMPDIR/tempfile.txt || exit -6 TMPFILE=$TEMPDIR/tempfile.txt || exit -6
if [[ "$DEBUG" -eq 0 ]]; then if [[ "$DEBUG" -eq 0 ]]; then
ERRFILE="/dev/null" ERRFILE="/dev/null"
else else
ERRFILE=$TEMPDIR/errorfile.txt || exit -6 ERRFILE=$TEMPDIR/errorfile.txt || exit -6
fi fi
@ -4205,8 +4205,8 @@ mybanner() {
$PROG_NAME $VERSION from $SWURL $PROG_NAME $VERSION from $SWURL
($idtag) ($idtag)
This program is free software. Distribution and This program is free software. Distribution and
modification under GPLv2 permitted. modification under GPLv2 permitted.
USAGE w/o ANY WARRANTY. USE IT AT YOUR OWN RISK! USAGE w/o ANY WARRANTY. USE IT AT YOUR OWN RISK!
Please file bugs @ https://testssl.sh/bugs/ Please file bugs @ https://testssl.sh/bugs/
@ -4223,9 +4223,9 @@ EOF
cwd=$(/bin/pwd) || \ cwd=$(/bin/pwd) || \
cwd=$RUN_DIR cwd=$RUN_DIR
if [[ "$openssl_location" =~ $(/bin/pwd)/bin ]]; then if [[ "$openssl_location" =~ $(/bin/pwd)/bin ]]; then
echo "\$PWD/bin/$(basename "$openssl_location")" echo "\$PWD/bin/$(basename "$openssl_location")"
elif [[ "$openssl_location" =~ $cwd ]] && [[ "$cwd" != '.' ]]; then elif [[ "$openssl_location" =~ $cwd ]] && [[ "$cwd" != '.' ]]; then
echo "${openssl_location%%$cwd}" echo "${openssl_location%%$cwd}"
else else
echo "$openssl_location" echo "$openssl_location"
fi fi
@ -4235,7 +4235,7 @@ EOF
cleanup () { cleanup () {
if [[ "$DEBUG" -ge 1 ]]; then if [[ "$DEBUG" -ge 1 ]]; then
outln outln
pr_underline "DEBUG (level $DEBUG): see files in $TEMPDIR" pr_underline "DEBUG (level $DEBUG): see files in $TEMPDIR"
outln outln
else else
@ -4393,7 +4393,7 @@ filter_ip4_address() {
get_local_aaaa() { get_local_aaaa() {
local ip6="" local ip6=""
local etchosts="/etc/hosts /c/Windows/System32/drivers/etc/hosts" local etchosts="/etc/hosts /c/Windows/System32/drivers/etc/hosts"
# for security testing sometimes we have local entries. Getent is BS under Linux for localhost: No network, no resolution # for security testing sometimes we have local entries. Getent is BS under Linux for localhost: No network, no resolution
ip6=$(grep -wh "$NODE" $etchosts 2>/dev/null | grep ':' | grep -v '^#' | egrep "[[:space:]]$NODE" | awk '{ print $1 }') ip6=$(grep -wh "$NODE" $etchosts 2>/dev/null | grep ':' | grep -v '^#' | egrep "[[:space:]]$NODE" | awk '{ print $1 }')
if is_ipv6addr "$ip6"; then if is_ipv6addr "$ip6"; then
@ -4406,7 +4406,7 @@ get_local_aaaa() {
get_local_a() { get_local_a() {
local ip4="" local ip4=""
local etchosts="/etc/hosts /c/Windows/System32/drivers/etc/hosts" local etchosts="/etc/hosts /c/Windows/System32/drivers/etc/hosts"
# for security testing sometimes we have local entries. Getent is BS under Linux for localhost: No network, no resolution # for security testing sometimes we have local entries. Getent is BS under Linux for localhost: No network, no resolution
ip4=$(grep -wh "$1" $etchosts 2>/dev/null | egrep -v ':|^#' | egrep "[[:space:]]$1" | awk '{ print $1 }') ip4=$(grep -wh "$1" $etchosts 2>/dev/null | egrep -v ':|^#' | egrep "[[:space:]]$1" | awk '{ print $1 }')
if is_ipv4addr "$ip4"; then if is_ipv4addr "$ip4"; then
@ -4417,8 +4417,8 @@ get_local_a() {
} }
check_resolver_bins() { check_resolver_bins() {
if ! which dig &> /dev/null && ! which host &> /dev/null && ! which nslookup &>/dev/null; then if ! which dig &> /dev/null && ! which drill &> /dev/null && ! which host &> /dev/null && ! which nslookup &>/dev/null; then
fatal "Neither \"dig\", \"host\" or \"nslookup\" is present" "-3" fatal "Neither \"dig\", \"drill\", \"host\" or \"nslookup\" is present" "-3"
fi fi
return 0 return 0
} }
@ -4446,6 +4446,10 @@ get_a_record() {
which host &> /dev/null && \ which host &> /dev/null && \
ip4=$(filter_ip4_address $(host -t a "$1" 2>/dev/null | grep -v alias | sed 's/^.*address //')) ip4=$(filter_ip4_address $(host -t a "$1" 2>/dev/null | grep -v alias | sed 's/^.*address //'))
fi fi
if [[ -z "$ip4" ]]; then
which drill &> /dev/null && \
ip4=$(filter_ip4_address $(drill a "$1" 2>/dev/null | awk '/^\;\;\sANSWER\sSECTION\:$/,/\;\;\sAUTHORITY\sSECTION\:$/ { print $5,$6 }' | sed '/^\s$/d'))
fi
if [[ -z "$ip4" ]]; then if [[ -z "$ip4" ]]; then
if which nslookup &>/dev/null; then if which nslookup &>/dev/null; then
# filtering from Name to EOF, remove iline with 'Name', the filter out non-numbers and ".'", and empty lines # filtering from Name to EOF, remove iline with 'Name', the filter out non-numbers and ".'", and empty lines
@ -4475,8 +4479,9 @@ get_aaaa_record() {
ip6=$(filter_ip6_address $(host -t aaaa "$NODE" | grep -v alias | grep -v "no AAAA record" | sed 's/^.*address //')) ip6=$(filter_ip6_address $(host -t aaaa "$NODE" | grep -v alias | grep -v "no AAAA record" | sed 's/^.*address //'))
elif which dig &> /dev/null; then elif which dig &> /dev/null; then
ip6=$(filter_ip6_address $(dig +short -t aaaa "$NODE" 2>/dev/null)) ip6=$(filter_ip6_address $(dig +short -t aaaa "$NODE" 2>/dev/null))
elif which drill &> /dev/null; then
ip6=$(filter_ip6_address $(drill aaaa "$NODE" 2>/dev/null | awk '/^\;\;\sANSWER\sSECTION\:$/,/^\;\;\sAUTHORITY\sSECTION\:$/ { print $5,$6 }' | sed '/^\s$/d'))
elif which nslookup &>/dev/null; then elif which nslookup &>/dev/null; then
# same as above. Only we're using grep -A instead of awk
ip6=$(filter_ip6_address $(nslookup -type=aaaa "$NODE" 2>/dev/null | grep -A10 Name | grep -v Name)) ip6=$(filter_ip6_address $(nslookup -type=aaaa "$NODE" 2>/dev/null | grep -A10 Name | grep -v Name))
fi fi
fi fi
@ -4485,7 +4490,7 @@ get_aaaa_record() {
} }
# now get all IP addresses # now get all IP addresses
determine_ip_addresses() { determine_ip_addresses() {
local ip4="" local ip4=""
local ip6="" local ip6=""
@ -4501,7 +4506,7 @@ determine_ip_addresses() {
else else
LOCAL_A=true # we have the ip4 from local host entry and need to signal this to testssl LOCAL_A=true # we have the ip4 from local host entry and need to signal this to testssl
fi fi
# same now for ipv6 # same now for ipv6
ip6=$(get_local_aaaa $NODE) ip6=$(get_local_aaaa $NODE)
if [[ -z $ip6 ]]; then if [[ -z $ip6 ]]; then
check_resolver_bins check_resolver_bins
@ -4544,6 +4549,8 @@ determine_rdns() {
rDNS=$(dig -x $NODEIP +noall +answer | awk '/PTR/ { print $NF }') # +short returns also CNAME, e.g. openssl.org rDNS=$(dig -x $NODEIP +noall +answer | awk '/PTR/ { print $NF }') # +short returns also CNAME, e.g. openssl.org
elif which host &> /dev/null; then elif which host &> /dev/null; then
rDNS=$(host -t PTR $NODEIP 2>/dev/null | awk '/pointer/ { print $NF }') rDNS=$(host -t PTR $NODEIP 2>/dev/null | awk '/pointer/ { print $NF }')
elif which drill &> /dev/null; then
rDNS=$(drill -x ptr $NODEIP 2>/dev/null | awk '/^\;\;\sANSWER\sSECTION\:$/,/\;\;\sAUTHORITY\sSECTION\:$/ { print $5,$6 }' | sed '/^\s$/d')
elif which nslookup &> /dev/null; then elif which nslookup &> /dev/null; then
rDNS=$(nslookup -type=PTR $NODEIP 2>/dev/null | grep -v 'canonical name =' | grep 'name = ' | awk '{ print $NF }' | sed 's/\.$//') rDNS=$(nslookup -type=PTR $NODEIP 2>/dev/null | grep -v 'canonical name =' | grep 'name = ' | awk '{ print $NF }' | sed 's/\.$//')
fi fi
@ -4563,10 +4570,12 @@ get_mx_record() {
mxs=$(host -t MX "$1" 2>/dev/null | grep 'handled by' | sed -e 's/^.*by //g' -e 's/\.$//') mxs=$(host -t MX "$1" 2>/dev/null | grep 'handled by' | sed -e 's/^.*by //g' -e 's/\.$//')
elif which dig &> /dev/null; then elif which dig &> /dev/null; then
mxs=$(dig +short -t MX "$1" 2>/dev/null) mxs=$(dig +short -t MX "$1" 2>/dev/null)
elif which drill &> /dev/null; then
mxs=$(drill mx "$1" 2>/dev/null | awk '/^\;\;\sANSWER\sSECTION\:$/,/\;\;\sAUTHORITY\sSECTION\:$/ { print $5,$6 }' | sed '/^\s$/d')
elif which nslookup &> /dev/null; then elif which nslookup &> /dev/null; then
mxs=$(nslookup -type=MX "$1" 2>/dev/null | grep 'mail exchanger = ' | sed 's/^.*mail exchanger = //g') mxs=$(nslookup -type=MX "$1" 2>/dev/null | grep 'mail exchanger = ' | sed 's/^.*mail exchanger = //g')
else else
fatal "No dig, host or nslookup" -3 fatal "No dig, drill, host or nslookup" -3
fi fi
OPENSSL_CONF="$saved_openssl_conf" OPENSSL_CONF="$saved_openssl_conf"
echo "$mxs" echo "$mxs"
@ -4605,10 +4614,10 @@ sclient_auth() {
[[ $1 -eq 0 ]] && return 0 # no client auth (CLIENT_AUTH=false is preset globally) [[ $1 -eq 0 ]] && return 0 # no client auth (CLIENT_AUTH=false is preset globally)
if [[ -n $(awk '/Master-Key: / { print $2 }' "$2") ]]; then # connect succeeded if [[ -n $(awk '/Master-Key: / { print $2 }' "$2") ]]; then # connect succeeded
if grep -q '^<<< .*CertificateRequest' "$2"; then # CertificateRequest message in -msg if grep -q '^<<< .*CertificateRequest' "$2"; then # CertificateRequest message in -msg
CLIENT_AUTH=true CLIENT_AUTH=true
return 0 return 0
fi fi
if [[ -z $(awk '/Session-ID: / { print $2 }' "$2") ]]; then # probably no SSL session if [[ -z $(awk '/Session-ID: / { print $2 }' "$2") ]]; then # probably no SSL session
if [[ 2 -eq $(grep -c CERTIFICATE "$2") ]]; then # do another sanity check to be sure if [[ 2 -eq $(grep -c CERTIFICATE "$2") ]]; then # do another sanity check to be sure
CLIENT_AUTH=false CLIENT_AUTH=false
NO_SSL_SESSIONID=true # NO_SSL_SESSIONI is preset globally to false for all other cases NO_SSL_SESSIONID=true # NO_SSL_SESSIONI is preset globally to false for all other cases
@ -4621,7 +4630,7 @@ sclient_auth() {
} }
# this function determines OPTIMAL_PROTO. It is a workaround function as under certain circumstances # this function determines OPTIMAL_PROTO. It is a workaround function as under certain circumstances
# (e.g. IIS6.0 and openssl 1.0.2 as opposed to 1.0.1) needs a protocol otherwise s_client -connect will fail! # (e.g. IIS6.0 and openssl 1.0.2 as opposed to 1.0.1) needs a protocol otherwise s_client -connect will fail!
# Circumstances observed so far: 1.) IIS 6 2.) starttls + dovecot imap # Circumstances observed so far: 1.) IIS 6 2.) starttls + dovecot imap
# The first try in the loop is empty as we prefer not to specify always a protocol if it works w/o. # The first try in the loop is empty as we prefer not to specify always a protocol if it works w/o.
@ -4678,7 +4687,7 @@ determine_optimal_proto() {
# arg1: ftp smtp, pop3, imap, xmpp, telnet, ldap (maybe with trailing s) # arg1: ftp smtp, pop3, imap, xmpp, telnet, ldap (maybe with trailing s)
determine_service() { determine_service() {
local ua local ua
local protocol local protocol
if ! fd_socket; then # check if we can connect to $NODEIP:$PORT if ! fd_socket; then # check if we can connect to $NODEIP:$PORT
@ -4690,8 +4699,8 @@ determine_service() {
datebanner " Start" datebanner " Start"
outln outln
if [[ -z "$1" ]]; then if [[ -z "$1" ]]; then
# no STARTTLS. # no STARTTLS.
determine_optimal_proto "$1" determine_optimal_proto "$1"
$SNEAKY && \ $SNEAKY && \
ua="$UA_SNEAKY" || \ ua="$UA_SNEAKY" || \
@ -4701,7 +4710,7 @@ determine_service() {
GET_REQ10="GET $URL_PATH HTTP/1.0\r\nUser-Agent: $ua\r\nConnection: Close\r\nAccept: text/*\r\n\r\n" GET_REQ10="GET $URL_PATH HTTP/1.0\r\nUser-Agent: $ua\r\nConnection: Close\r\nAccept: text/*\r\n\r\n"
HEAD_REQ10="HEAD $URL_PATH HTTP/1.0\r\nUser-Agent: $ua\r\nAccept: text/*\r\n\r\n" HEAD_REQ10="HEAD $URL_PATH HTTP/1.0\r\nUser-Agent: $ua\r\nAccept: text/*\r\n\r\n"
runs_HTTP $OPTIMAL_PROTO runs_HTTP $OPTIMAL_PROTO
else else
# STARTTLS # STARTTLS
protocol=${1%s} # strip trailing 's' in ftp(s), smtp(s), pop3(s), etc protocol=${1%s} # strip trailing 's' in ftp(s), smtp(s), pop3(s), etc
case "$protocol" in case "$protocol" in
@ -4787,7 +4796,7 @@ draw_line() {
mx_all_ips() { mx_all_ips() {
local mxs mx local mxs mx
local mxport local mxport
local -i ret=0 local -i ret=0
STARTTLS_PROTOCOL="smtp" STARTTLS_PROTOCOL="smtp"
@ -4802,7 +4811,7 @@ mx_all_ips() {
for mx in $mxs; do for mx in $mxs; do
draw_line "-" $((TERM_DWITH * 2 / 3)) draw_line "-" $((TERM_DWITH * 2 / 3))
outln outln
parse_hn_port "$mx:$mxport" parse_hn_port "$mx:$mxport"
determine_ip_addresses || continue determine_ip_addresses || continue
if [[ $(count_words "$(echo -n "$IPADDRs")") -gt 1 ]]; then # we have more than one ipv4 address to check if [[ $(count_words "$(echo -n "$IPADDRs")") -gt 1 ]]; then # we have more than one ipv4 address to check
pr_bold "Testing all IPv4 addresses (port $PORT): "; outln "$IPADDRs" pr_bold "Testing all IPv4 addresses (port $PORT): "; outln "$IPADDRs"
@ -4845,7 +4854,7 @@ run_mass_testing() {
# This initializes boolean global do_* variables. They keep track of what to do # This initializes boolean global do_* variables. They keep track of what to do
# -- as the name insinuates # -- as the name insinuates
initialize_globals() { initialize_globals() {
do_allciphers=false do_allciphers=false
@ -4932,7 +4941,7 @@ debug_globals() {
# arg1+2 are just the options # arg1+2 are just the options
parse_opt_equal_sign() { parse_opt_equal_sign() {
if [[ "$1" == *=* ]]; then if [[ "$1" == *=* ]]; then
echo "$1" | awk -F'=' '{ print $2 }' echo "$1" | awk -F'=' '{ print $2 }'
return 1 # = means we don't need to shift args! return 1 # = means we don't need to shift args!
else else
echo $2 echo $2
@ -4948,7 +4957,7 @@ parse_cmd_line() {
while [[ $# -gt 0 ]]; do while [[ $# -gt 0 ]]; do
case $1 in case $1 in
-h|--help) -h|--help)
help 0 help 0
;; ;;
-b|--banner|-v|--version) -b|--banner|-v|--version)
find_openssl_binary find_openssl_binary
@ -4962,11 +4971,11 @@ parse_cmd_line() {
;; ;;
--mx465) # doesn't work with major ISPs --mx465) # doesn't work with major ISPs
do_mx_all_ips=true do_mx_all_ips=true
PORT=465 PORT=465
;; ;;
--mx587) # doesn't work with major ISPs --mx587) # doesn't work with major ISPs
do_mx_all_ips=true do_mx_all_ips=true
PORT=587 PORT=587
;; ;;
--ip|--ip=*) --ip|--ip=*)
CMDLINE_IP=$(parse_opt_equal_sign "$1" "$2") CMDLINE_IP=$(parse_opt_equal_sign "$1" "$2")
@ -4978,7 +4987,7 @@ parse_cmd_line() {
mybanner mybanner
openssl_age openssl_age
prettyprint_local $(parse_opt_equal_sign "$1" "$2") prettyprint_local $(parse_opt_equal_sign "$1" "$2")
exit $? exit $?
;; ;;
-x|-x=*|--single[-_]cipher|--single[-_]cipher=*) -x|-x=*|--single[-_]cipher|--single[-_]cipher=*)
do_test_just_one=true do_test_just_one=true
@ -5038,15 +5047,15 @@ parse_cmd_line() {
do_logjam=true do_logjam=true
do_beast=true do_beast=true
do_rc4=true do_rc4=true
VULN_COUNT=10 VULN_COUNT=10
;; ;;
-B|--heartbleed) -B|--heartbleed)
do_heartbleed=true do_heartbleed=true
let "VULN_COUNT++" let "VULN_COUNT++"
;; ;;
-I|--ccs|--ccs[-_]injection) -I|--ccs|--ccs[-_]injection)
do_ccs_injection=true do_ccs_injection=true
let "VULN_COUNT++" let "VULN_COUNT++"
;; ;;
-R|--renegotiation) -R|--renegotiation)
do_renego=true do_renego=true
@ -5094,16 +5103,16 @@ parse_cmd_line() {
# DEBUG=3 ./testssl.sh --devel 01 yandex.ru --> TLS 1.0 # DEBUG=3 ./testssl.sh --devel 01 yandex.ru --> TLS 1.0
# DEBUG=3 ./testssl.sh --devel 00 <host which supports SSLv3> # DEBUG=3 ./testssl.sh --devel 00 <host which supports SSLv3>
# DEBUG=3 ./testssl.sh --devel 22 <host which still supports SSLv2> # DEBUG=3 ./testssl.sh --devel 22 <host which still supports SSLv2>
TLS_LOW_BYTE="$2"; TLS_LOW_BYTE="$2";
if [[ $# -eq 4 ]]; then # protocol AND ciphers specified if [[ $# -eq 4 ]]; then # protocol AND ciphers specified
HEX_CIPHER="$3" HEX_CIPHER="$3"
shift shift
fi fi
shift shift
do_tls_sockets=true do_tls_sockets=true
outln "\nTLS_LOW_BYTE/HEX_CIPHER: ${TLS_LOW_BYTE}/${HEX_CIPHER}" outln "\nTLS_LOW_BYTE/HEX_CIPHER: ${TLS_LOW_BYTE}/${HEX_CIPHER}"
;; ;;
--wide) --wide)
WIDE=true WIDE=true
;; ;;
--assuming[_-]http|--assume[-_]http) --assuming[_-]http|--assume[-_]http)
@ -5124,27 +5133,27 @@ parse_cmd_line() {
do_mass_testing=true do_mass_testing=true
;; ;;
--warnings|--warnings=*) --warnings|--warnings=*)
WARNINGS=$(parse_opt_equal_sign "$1" "$2") WARNINGS=$(parse_opt_equal_sign "$1" "$2")
[[ $? -eq 0 ]] && shift [[ $? -eq 0 ]] && shift
case "$WARNINGS" in case "$WARNINGS" in
batch|off|false) ;; batch|off|false) ;;
*) pr_magentaln "\nwarnings can be either \"batch\", \"off\" or \"false\"" *) pr_magentaln "\nwarnings can be either \"batch\", \"off\" or \"false\""
help 1 help 1
esac esac
;; ;;
--show[-_]each) --show[-_]each)
SHOW_EACH_C=1 #FIXME: sense is vice versa SHOW_EACH_C=1 #FIXME: sense is vice versa
;; ;;
--bugs) --bugs)
BUGS="-bugs" BUGS="-bugs"
;; ;;
--debug|--debug=*) --debug|--debug=*)
DEBUG=$(parse_opt_equal_sign "$1" "$2") DEBUG=$(parse_opt_equal_sign "$1" "$2")
[[ $? -eq 0 ]] && shift [[ $? -eq 0 ]] && shift
case $DEBUG in case $DEBUG in
[0-6]) ;; [0-6]) ;;
*) pr_magentaln "\nunrecognized debug value \"$1\", must be between 0..6" 1>&2 *) pr_magentaln "\nunrecognized debug value \"$1\", must be between 0..6" 1>&2
help 1 help 1
esac esac
;; ;;
--color|--color=*) --color|--color=*)
@ -5158,14 +5167,14 @@ parse_cmd_line() {
esac esac
;; ;;
--log|--logging) --log|--logging)
do_logging=true do_logging=true
;; # DEFINITION of LOGFILE if no arg specified via ENV or automagically in parse_hn_ports() ;; # DEFINITION of LOGFILE if no arg specified via ENV or automagically in parse_hn_ports()
# following does the same but we can specify a log location additionally # following does the same but we can specify a log location additionally
--logfile=*) --logfile=*)
LOGFILE=$(parse_opt_equal_sign "$1" "$2") LOGFILE=$(parse_opt_equal_sign "$1" "$2")
[[ $? -eq 0 ]] && shift [[ $? -eq 0 ]] && shift
do_logging=true do_logging=true
;; ;;
--openssl|--openssl=*) --openssl|--openssl=*)
OPENSSL=$(parse_opt_equal_sign "$1" "$2") OPENSSL=$(parse_opt_equal_sign "$1" "$2")
[[ $? -eq 0 ]] && shift [[ $? -eq 0 ]] && shift
@ -5184,12 +5193,12 @@ parse_cmd_line() {
SSL_NATIVE=true SSL_NATIVE=true
;; ;;
(--) shift (--) shift
break break
;; ;;
(-*) pr_magentaln "\n$0: unrecognized option \"$1\"" 1>&2; (-*) pr_magentaln "\n$0: unrecognized option \"$1\"" 1>&2;
help 1 help 1
;; ;;
(*) break (*) break
;; ;;
esac esac
shift shift
@ -5286,7 +5295,7 @@ lets_roll() {
$do_cipher_per_proto && { run_cipher_per_proto; ret=$(($? + ret)); } $do_cipher_per_proto && { run_cipher_per_proto; ret=$(($? + ret)); }
outln outln
datebanner " Done" datebanner " Done"
return $ret return $ret
} }
@ -5318,14 +5327,14 @@ if $do_mx_all_ips; then
[[ $? -eq 1 ]] && set_scanning_defaults [[ $? -eq 1 ]] && set_scanning_defaults
mx_all_ips "${URI}" $PORT mx_all_ips "${URI}" $PORT
ret=$? ret=$?
else else
parse_hn_port "${URI}" # NODE, URL_PATH, PORT, IPADDR and IP46ADDR is set now parse_hn_port "${URI}" # NODE, URL_PATH, PORT, IPADDR and IP46ADDR is set now
if ! determine_ip_addresses && [[ -z "$CMDLINE_IP" ]]; then if ! determine_ip_addresses && [[ -z "$CMDLINE_IP" ]]; then
fatal "No IP address could be determined" fatal "No IP address could be determined"
fi fi
if [[ -n "$CMDLINE_IP" ]]; then if [[ -n "$CMDLINE_IP" ]]; then
[[ "$CMDLINE_IP" == "one" ]] && \ [[ "$CMDLINE_IP" == "one" ]] && \
CMDLINE_IP=$(echo -n "$IPADDRs" | awk '{ print $1 }') CMDLINE_IP=$(echo -n "$IPADDRs" | awk '{ print $1 }')
NODEIP="$CMDLINE_IP" # specific ip address for NODE was supplied NODEIP="$CMDLINE_IP" # specific ip address for NODE was supplied
lets_roll "${STARTTLS_PROTOCOL}" lets_roll "${STARTTLS_PROTOCOL}"
ret=$? ret=$?