- better compatibility with windows 2003 server

- all long options are advertised now as with dashes and not underscore
- cosmetic stuff
This commit is contained in:
Dirk 2015-04-20 10:05:01 +02:00
parent 7b6dba6369
commit 5bec0a16c9

View File

@ -315,12 +315,7 @@ fi
###### helper function definitions ###### ###### helper function definitions ######
debugme() { debugme() {
if [[ $DEBUG -ge 2 ]]; then [[ $DEBUG -ge 2 ]] && "$@"
#echo "$@"
"$@"
else
:
fi
} }
tmpfile_handle() { tmpfile_handle() {
@ -455,7 +450,7 @@ EOF
fi fi
if egrep -aq "^HTTP.1.. 301|^HTTP.1.. 302|^Location" $HEADERFILE; then if egrep -aq "^HTTP.1.. 301|^HTTP.1.. 302|^Location" $HEADERFILE; then
redir2=$(grep -a '^Location' $HEADERFILE | sed 's/Location: //' | tr -d '\r\n') redir2=$(grep -a '^Location' $HEADERFILE | sed 's/Location: //' | tr -d '\r\n')
outln " (got 30x to $redir2, may be better try this URL?)\n" outln " (got 30x to $redir2 - may be better try this URL?)\n"
fi fi
HTTP_DATE=$(awk -F': ' '/Date/ { print $2 }' $HEADERFILE) HTTP_DATE=$(awk -F': ' '/Date/ { print $2 }' $HEADERFILE)
debugme echo "$HTTP_DATE" debugme echo "$HTTP_DATE"
@ -1224,18 +1219,27 @@ cipher_pref_check() {
server_defaults() { server_defaults() {
local proto
local localtime
local extensions local sessticket_str lifetime unit keysize algo
local expire ocsp_uri crl savedir startdate enddate issuer_c issuer_o issuer sans san cn cn_nosni
outln outln
pr_blue "--> Testing server defaults (Server Hello)"; outln "\n" pr_blue "--> Testing server defaults (Server Hello)"; outln "\n"
localtime=$(date "+%s") localtime=$(date "+%s")
# throwing every cipher/protocol at the server and displaying its pick # throwing every cipher/protocol at the server and displaying its pick
$OPENSSL s_client $STARTTLS -connect $NODEIP:$PORT $SNI -tlsextdebug -status </dev/null 2>/dev/null >$TMPFILE for proto in tls1_2 tls1_1 tls1; do
ret=$? $OPENSSL s_client $STARTTLS -connect $NODEIP:$PORT $SNI -$proto -tlsextdebug -status </dev/null 2>/dev/null >$TMPFILE
$OPENSSL s_client $STARTTLS -connect $NODEIP:$PORT $SNI 2>/dev/null </dev/null | awk '/-----BEGIN/,/-----END/ { print $0 }' >$HOSTCERT ret=$?
if [ $? -ne 0 ] || [ $ret -ne 0 ]; then $OPENSSL s_client $STARTTLS -connect $NODEIP:$PORT $SNI -$proto 2>/dev/null </dev/null | awk '/-----BEGIN/,/-----END/ { print $0 }' >$HOSTCERT
openssl_error [ $? -eq 0 ] && [ $ret -eq 0 ] && break
ret=6 ret=7
done # this loop was need while testing a windows 2003 server
if [ $ret -eq 7 ]; then
pr_magenta "$OPENSSL returned an error. This shouldn't happen. "
else else
$OPENSSL s_client $STARTTLS -connect $NODEIP:$PORT -$proto 2>/dev/null </dev/null | awk '/-----BEGIN/,/-----END/ { print $0 }' >$HOSTCERT.nosni
out " TLS server extensions " out " TLS server extensions "
extensions=$(grep -aw "^TLS server extension" $TMPFILE | sed -e 's/^TLS server extension \"//' -e 's/\".*$/,/g') extensions=$(grep -aw "^TLS server extension" $TMPFILE | sed -e 's/^TLS server extension \"//' -e 's/\".*$/,/g')
if [ -z "$extensions" ]; then if [ -z "$extensions" ]; then
@ -1284,12 +1288,11 @@ server_defaults() {
outln " $($OPENSSL x509 -noout -in $HOSTCERT -fingerprint -sha256 | sed 's/Fingerprint=//' | sed 's/://g' )" outln " $($OPENSSL x509 -noout -in $HOSTCERT -fingerprint -sha256 | sed 's/Fingerprint=//' | sed 's/://g' )"
out " Common Name (CN) " out " Common Name (CN) "
CN=$($OPENSSL x509 -in $HOSTCERT -noout -subject | sed 's/subject= //' | sed -e 's/^.*CN=//' -e 's/\/emailAdd.*//') cn=$($OPENSSL x509 -in $HOSTCERT -noout -subject | sed 's/subject= //' | sed -e 's/^.*CN=//' -e 's/\/emailAdd.*//')
pr_underline "$CN" pr_underline "$cn"
CN_nosni=$($OPENSSL s_client $STARTTLS -connect $NODEIP:$PORT 2>/dev/null </dev/null | awk '/-----BEGIN/,/-----END/ { print $0 }' | \ cn_nosni=$($OPENSSL x509 -in $HOSTCERT.nosni -noout -subject | sed 's/subject= //' | sed -e 's/^.*CN=//' -e 's/\/emailAdd.*//')
$OPENSSL x509 -noout -subject | sed 's/subject= //' | sed -e 's/^.*CN=//' -e 's/\/emailAdd.*//') [[ $DEBUG -ge 2 ]] && out "\'$NODE\' | \'$cn\' | \'$cn_nosni\'"
[[ $DEBUG -ge 2 ]] && out "\'$NODE\' | \'$CN\' | \'$CN_nosni\'"
if [[ $NODE == $CN_nosni ]]; then if [[ $NODE == $CN_nosni ]]; then
if [[ $SERVICE != "HTTP" ]] ; then if [[ $SERVICE != "HTTP" ]] ; then
outln " (matches certificate directly)" outln " (matches certificate directly)"
@ -1300,21 +1303,23 @@ server_defaults() {
if [[ $SERVICE != "HTTP" ]] ; then if [[ $SERVICE != "HTTP" ]] ; then
pr_brownln " (CN doesn't match but for non-HTTP services it might be ok)" pr_brownln " (CN doesn't match but for non-HTTP services it might be ok)"
else else
out " (CN response to request w/o SNI: "; pr_underline "$CN_nosni"; outln ")" out " (CN response to request w/o SNI: "; pr_underline "$cn_nosni"; outln ")"
fi fi
fi fi
SAN=$($OPENSSL x509 -in $HOSTCERT -noout -text | grep -A3 "Subject Alternative Name" | grep "DNS:" | \ sans=$($OPENSSL x509 -in $HOSTCERT -noout -text | grep -A3 "Subject Alternative Name" | grep "DNS:" | \
sed -e 's/DNS://g' -e 's/ //g' -e 's/,/\n/g' -e 's/othername:<unsupported>//g') sed -e 's/DNS://g' -e 's/ //g' -e 's/,/\n/g' -e 's/othername:<unsupported>//g')
# ^^^ CACert # ^^^ CACert
if [ x"$SAN" != "x" ]; then out " subjectAltName (SAN) "
SAN=$(echo "$SAN" | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g') # replace line feed by " " if [ -n "$sans" ]; then
out " subjectAltName (SAN) " sans=$(echo "$sans" | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g') # replace line feed by " "
for san in $SAN; do for san in $sans; do
out "$underline$san$off " out "$underline$san$off "
done done
outln else
out "-- "
fi fi
outln
out " Issuer " out " Issuer "
issuer=$($OPENSSL x509 -in $HOSTCERT -noout -issuer | sed -e 's/^.*CN=//g' -e 's/\/.*$//g') issuer=$($OPENSSL x509 -in $HOSTCERT -noout -issuer | sed -e 's/^.*CN=//g' -e 's/\/.*$//g')
issuer_o=$($OPENSSL x509 -in $HOSTCERT -noout -issuer | sed 's/^.*O=//g' | sed 's/\/.*$//g') issuer_o=$($OPENSSL x509 -in $HOSTCERT -noout -issuer | sed 's/^.*O=//g' | sed 's/\/.*$//g')
@ -1654,8 +1659,9 @@ spdy() {
# arg for a fd doesn't work here # arg for a fd doesn't work here
fd_socket() { fd_socket() {
if ! exec 5<>/dev/tcp/$NODEIP/$PORT; then # 2>/dev/null removes an error message, but disables debugging, FIXME: subshell? if ! exec 5<>/dev/tcp/$NODEIP/$PORT; then # 2>/dev/null removes an error message, but disables debugging
pr_magentaln "Unable to open a socket to $NODEIP:$PORT" outln
pr_magenta "Unable to open a socket to $NODEIP:$PORT"
# It can last ~2 minutes but for for those rare occasions we don't do a tiemout handler here, KISS # It can last ~2 minutes but for for those rare occasions we don't do a tiemout handler here, KISS
return 6 return 6
fi fi
@ -2604,9 +2610,9 @@ $PRG <options> URI
<-S|--server_defaults> displays the servers default picks and certificate info <-S|--server_defaults> displays the servers default picks and certificate info
<-P|--preference> displays the servers picks: protocol+cipher <-P|--preference> displays the servers picks: protocol+cipher
<-y|--spdy|--npn> checks for SPDY/NPN <-y|--spdy|--npn> checks for SPDY/NPN
<-x|--single-ciphers-test> <pattern> tests matched <pattern> of cipher <-x|--single-cipher-test> <pattern> tests matched <pattern> of cipher
<-B|--heartbleed> tests only for heartbleed vulnerability <-B|--heartbleed> tests only for heartbleed vulnerability
<-I|--ccs|--ccs_injection> tests only for CCS injection vulnerability <-I|--ccs|--ccs-injection> tests only for CCS injection vulnerability
<-R|--renegotiation> tests only for renegotiation vulnerability <-R|--renegotiation> tests only for renegotiation vulnerability
<-C|--compression|--crime> tests only for CRIME vulnerability <-C|--compression|--crime> tests only for CRIME vulnerability
<-T|--breach> tests only for BREACH vulnerability <-T|--breach> tests only for BREACH vulnerability
@ -2627,6 +2633,15 @@ partly mandatory parameters:
pattern an ignore case word pattern of cipher hexcode or any other string in the name, kx or bits pattern an ignore case word pattern of cipher hexcode or any other string in the name, kx or bits
protocol is one of ftp,smtp,pop3,imap,xmpp,telnet,ldap (for the latter two you need e.g. the supplied openssl) protocol is one of ftp,smtp,pop3,imap,xmpp,telnet,ldap (for the latter two you need e.g. the supplied openssl)
tuning options:
--assuming-http if protocol check fails it assumes HTTP protocol and enforces HTTP checks
--ssl-native fallback to checks with OpenSSL where sockets are normally used
--sneaky tries to hide that testssl.sh is scanning
--warnings <batch|off|false> "batch" doesn't wait for keypress, "off|false" skips connection warning
--color 0: no escape or other codes 1: b/w escape codes 2: color (default)
--debug 1: screen output normal but debug output in itemp files. 2-6: see line ~60
For HTML output you need to pipe through "aha" (Ansi HTML Adapter: github.com/theZiz/aha) like For HTML output you need to pipe through "aha" (Ansi HTML Adapter: github.com/theZiz/aha) like
@ -2949,6 +2964,7 @@ datebanner() {
mx_allentries() { mx_allentries() {
local mxs mx local mxs mx
local mxport
if which dig &> /dev/null; then if which dig &> /dev/null; then
mxs=$(dig +short -t MX "$1") mxs=$(dig +short -t MX "$1")
@ -2964,10 +2980,13 @@ mx_allentries() {
# test first higher priority servers # test first higher priority servers
mxs=$(echo "$mxs" | sort -n | sed -e 's/^.* //' -e 's/\.$//' | tr '\n' ' ') mxs=$(echo "$mxs" | sort -n | sed -e 's/^.* //' -e 's/\.$//' | tr '\n' ' ')
mxport=${2:-25}
if [ -n "$mxs" ] && [ "$mxs" != ' ' ] ; then if [ -n "$mxs" ] && [ "$mxs" != ' ' ] ; then
pr_bold "Testing now all MX records (on port 25): "; outln "$mxs" starttls_proto="smtp"
[[ $mxport == "465" ]] && starttls_proto="" # no starttls for Port 465
pr_bold "Testing now all MX records (on port $mxport): "; outln "$mxs"
for mx in $mxs; do for mx in $mxs; do
parse_hn_port "$mx:25" smtp && lets_roll parse_hn_port "$mx:$mxport" $starttls_proto && lets_roll
done done
else else
pr_boldln " $1 has no MX records(s)" pr_boldln " $1 has no MX records(s)"
@ -3056,117 +3075,116 @@ startup() {
[[ "$#" -eq 1 ]] && set_scanning_defaults [[ "$#" -eq 1 ]] && set_scanning_defaults
while [[ $# -gt 0 ]]; do while [[ $# -gt 0 ]]; do
case $1 in case $1 in
-b|--banner|-v|--version) -b|--banner|-v|--version)
exit 0;; exit 0;;
--mx) --mx)
do_mx_allentries=true;; do_mx_allentries=true;;
-V|--local) --mx465) # doesn't work with major ISPs
initialize_engine # GOST support- do_mx_allentries=true
prettyprint_local "$2" PORT=465 ;;
exit $? ;; --mx587) # doesn't work with major ISPs
-x|--single-ciphers-test) do_mx_allentries=true
do_test_just_one=true PORT=587 ;;
single_cipher=$2 -V|--local)
shift;; initialize_engine # GOST support-
-t|--starttls) prettyprint_local "$2"
STARTTLS_PROTOCOL=$2 exit $? ;;
do_starttls=true -x|--single-ciphers-test|--single-cipher-test|--single_cipher_test|--single_ciphers_test)
shift;; do_test_just_one=true
-e|--each-cipher) single_cipher=$2
do_allciphers=true;; shift;;
-E|--cipher-per-proto) -t|--starttls)
do_cipher_per_proto=true;; STARTTLS_PROTOCOL=$2
-h|--help) do_starttls=true
help 0 shift;;
;; -e|--each-cipher)
-p|--protocols) do_allciphers=true;;
do_protocols=true -E|--cipher-per-proto|--cipher_per_proto)
do_spdy=true;; do_cipher_per_proto=true;;
-y|--spdy|--npn) -h|--help)
do_spdy=true;; help 0 ;;
-f|--ciphers) -p|--protocols)
do_run_std_cipherlists=true;; do_protocols=true
-S|--server_defaults) do_spdy=true;;
do_server_defaults=true;; -y|--spdy|--npn)
-P|--server_preference) do_spdy=true;;
do_server_preference=true;; -f|--ciphers)
-H|--header|--headers) do_run_std_cipherlists=true;;
do_header=true;; -S|--server_defaults|--server-defaults)
-B|--heartbleed) do_server_defaults=true;;
do_heartbleed=true -P|--server_preference|--server-preference)
let "VULN_COUNT++" ;; do_server_preference=true;;
-I|--ccs|--ccs_injection) -H|--header|--headers)
do_ccs_injection=true do_header=true;;
let "VULN_COUNT++" ;; -B|--heartbleed)
-R|--renegotiation) do_heartbleed=true
do_renego=true let "VULN_COUNT++" ;;
let "VULN_COUNT++" ;; -I|--ccs|--ccs_injection|--ccs-injection)
-C|--compression|--crime) do_ccs_injection=true
do_crime=true let "VULN_COUNT++" ;;
let "VULN_COUNT++" ;; -R|--renegotiation)
-T|--breach) do_renego=true
do_breach=true let "VULN_COUNT++" ;;
let "VULN_COUNT++" ;; -C|--compression|--crime)
-O|--poodle) do_crime=true
do_ssl_poodle=true let "VULN_COUNT++" ;;
let "VULN_COUNT++" ;; -T|--breach)
-F|--freak) do_breach=true
do_freak=true let "VULN_COUNT++" ;;
let "VULN_COUNT++" ;; -O|--poodle)
-A|--beast) do_ssl_poodle=true
do_beast=true let "VULN_COUNT++" ;;
let "VULN_COUNT++" ;; -F|--freak)
-4|--rc4|--appelbaum) do_freak=true
do_rc4=true;; let "VULN_COUNT++" ;;
-s|--pfs|--fs|--nsa) -A|--beast)
do_pfs=true;; do_beast=true
-q) ### following is a development feature and will disappear: let "VULN_COUNT++" ;;
# DEBUG=3 ./testssl.sh -q 03 "cc, 13, c0, 13" google.de -4|--rc4|--appelbaum)
# DEBUG=3 ./testssl.sh -q 01 yandex.ru do_rc4=true;;
TLS_LOW_BYTE="$2"; HEX_CIPHER="" -s|--pfs|--fs|--nsa)
if [ $# -eq 4 ]; then do_pfs=true;;
HEX_CIPHER="$3" -q) ### this is a development feature and will disappear:
shift # DEBUG=3 ./testssl.sh -q 03 "cc, 13, c0, 13" google.de
fi # DEBUG=3 ./testssl.sh -q 01 yandex.ru
shift TLS_LOW_BYTE="$2"; HEX_CIPHER=""
do_tls_sockets=true if [ $# -eq 4 ]; then # protocol AND ciphers specified
echo "TLS_LOW_BYTE: ${TLS_LOW_BYTE}" HEX_CIPHER="$3"
echo "HEX_CIPHER: ${HEX_CIPHER}" shift
;; fi
--assuming-http|--assuming_http|--assume_http|--assume-http) shift
ASSUMING_HTTP=0 ;; do_tls_sockets=true
--sneaky) outln "TLS_LOW_BYTE/HEX_CIPHER: ${TLS_LOW_BYTE}/${HEX_CIPHER}" ;;
SNEAKY=0 ;; --assuming-http|--assuming_http|--assume_http|--assume-http)
--warnings) ASSUMING_HTTP=0 ;;
WARNINGS="$2" --sneaky)
case $WARNINGS in SNEAKY=0 ;;
batch|off|false) ;; --warnings)
default) pr_magentaln "warnings can be either batch off false" ;; WARNINGS="$2"
esac case $WARNINGS in
shift ;; batch|off|false) ;;
--debug) default) pr_magentaln "warnings can be either batch off false" ;;
DEBUG="$2" esac
shift ;; shift ;;
--color) --debug)
COLOR=$2 DEBUG="$2"
if [ $COLOR -ne 0 ] && [ $COLOR -ne 1 ] && [ $COLOR -ne 2 ] ; then shift ;;
COLOR=2 --color)
pr_magentaln "$0: unrecognized color: $2" 1>&2 COLOR=$2
help 1 if [ $COLOR -ne 0 ] && [ $COLOR -ne 1 ] && [ $COLOR -ne 2 ] ; then
fi COLOR=2
shift ;; pr_magentaln "$0: unrecognized color: $2" 1>&2
--ssl_native|--ssl-native) help 1
SSL_NATIVE=0 fi
;; shift ;;
(--) shift --ssl_native|--ssl-native)
break SSL_NATIVE=0 ;;
;; (--) shift
(-*) pr_magentaln "$0: unrecognized option $1" 1>&2; break ;;
help 1 (-*) pr_magentaln "$0: unrecognized option $1" 1>&2;
;; help 1 ;;
(*) break (*) break ;;
;;
esac esac
shift shift
done done
@ -3252,7 +3270,7 @@ if ${do_mx_allentries} ; then
# if we have just one "do_*" set here --> query_globals: we do a standard run -- otherwise just the one specified # if we have just one "do_*" set here --> query_globals: we do a standard run -- otherwise just the one specified
[ $? -eq 1 ] && set_scanning_defaults [ $? -eq 1 ] && set_scanning_defaults
initialize_engine initialize_engine
mx_allentries "${URI}" mx_allentries "${URI}" $PORT
ret=$? ret=$?
else else
parse_hn_port "${URI}" "${STARTTLS_PROTOCOL}" parse_hn_port "${URI}" "${STARTTLS_PROTOCOL}"
@ -3262,5 +3280,6 @@ fi
exit $ret exit $ret
# $Id: testssl.sh,v 1.229 2015/04/16 18:28:28 dirkw Exp $ # $Id: testssl.sh,v 1.231 2015/04/20 08:05:00 dirkw Exp $
# vim:ts=5:sw=5 # vim:ts=5:sw=5
# ^^^ FYI: use vim and you will see everything beautifully indented with a 5 char tab