proxy_role/overlay/Linux/usr/local/bin/proxy_test_ssl.bash

352 lines
11 KiB
Bash
Executable File

#!/bin/bash
# -*- mode: sh; fill-column: 75; tab-width: 8; coding: utf-8-unix -*-
. /usr/local/bin/usr_local_tput.bash || exit 2
PREFIX=/usr/local
ROLE=proxy
NOW=$( date -u +%y-%m-%d_%H%m )
DEBUG=1
PROXY_WLAN=wlan4
prog=$( basename $0 .bash )
# SocksPolicy Accept in /etc/tor/torrc - required and works with sslscan
ip route | grep ^default || { ERROR "not connected" ; exit 1 ; }
PATH=$PATH:/sbin
BADSSL_SITES=(
self-signed.badssl.com
expired.badssl.com
mixed.badssl.com
rc4.badssl.com
hsts.badssl.com
)
badssl=0
[ "$#" -eq 0 ] && badssl=1
# tests="$MODE"
tests=""
nodig=1
verbosity=2
outdir=/tmp
timeout=20
#[ -f /usr/local/etc/testforge/testforge.bash ] && \
# . /usr/local/etc/testforge/testforge.bash
. /usr/local/bin/proxy_ping_lib.bash || \
{ ERROR loading /usr/local/bin/proxy_ping_lib.bash ; exit 2; }
if [ -f /usr/local/etc/ssl/cacert-testforge.pem ] ; then
CAFILE=/usr/local/etc/ssl/cacert-testforge.pem
else
CERT=$( proxy_ping_update_cacert )
[ "$?" -ne 0 -o -n "$CERT" ] && CAFILE=$CERT || \
CAFILE=/usr/local/etc/ssl/cacert-testforge.pem
fi
[ -z "$MODE" ] || MODE=`proxy_ping_mode`
if [ "$MODE" = tor ] ; then
[ -z "PROXY_WLAN" ] && PROXY_WLAN=`proxy_get_if`
[ -z "PROXY_WLAN" ] && { ERROR " error getting device $?" ; exit 3 ; }
if ip route | grep ^def ; then
PROXY_WLAN_IP=$( proxy_get_wlan_ip )
[ -n "$PROXY_WLAN_IP" ] || { ERROR "no PROXY_WLAN_IP" ; exit 4 ; }
fi
fi
usage() {
echo "Usage: $0 [OPTIONS] dirs-or-files"
echo
echo " -B | --badssl - test badssl.org sites"
echo " -D | --nodig - no dig sites"
echo " -T | --tests - ping tests to run first"
echo " -o | --outdir=/tmp - output directory"
echo " -v | --verbosity=$verbosity - verbosity 0 least 5 most"
echo
echo " -V | --version - print version of this script"
echo " -h | --help - print this help"
}
SHORTOPTS="hVBDT:v:"
LONGOPTS="help,version:,badssl,nodig,tests:,verbosity:"
HOSTS=
ARGS=$(getopt --options $SHORTOPTS --longoptions $LONGOPTS -- "$@")
[ $? != 0 ] && { ERROR "error parsing getopt" ; exit 5 ; }
eval set -- "$ARGS"
while true; do
case "$1" in
# -t --tests
-o|--outdir)
shift
outdir="$1"
;;
-v|--verbosity)
shift
verbosity="$1"
;;
-B|--badssl)
badssl=1
;;
-D|--nodig)
nodig=1
;;
-T|--tests)
shift
tests="$1"
;;
-V|--version)
usage
exit 0
;;
-h|--help)
usage
exit 0
;;
'--')
shift
HOSTS="$*"
break
;;
*)
{ ERROR "unrecognized arguments $*" ; exit 6 ; }
break
;;
esac
shift
done
[ $badssl -ne 0 ] && HOSTS="${BADSSL_SITES[*]}"
[ -z "$HOSTS" ] && { ERROR "no arguments $*" ; exit 0 ; }
[ -d "$outdir" ] || mkdir -p "$outdir" || { ERROR "mkdir $outdir" ; exit 7 ; }
kill_time=$( expr $timeout + 10 )
[ -z "$tests" ] || \
for elt in $tests ; do
/usr/local/bin/proxy_ping_test.bash $elt || exit 9$?
done
if which sslscan 2>/dev/null ; then
sslscan='sslscan'
SSLSCAN_ARGS="-4 --show-client-cas --show-certificate --bugs --timeout $timeout --tlsall --show-ciphers --no-colour --verbose"
else
# no proxy support
sslscan=''
fi
# sslscan --show-client-cas - no proxy
openssl=openssl
OPENSSL_ARGS="-4 -bugs -showcerts"
if [ -e /dev/tcp ] && which testssl.bash 2>/dev/null ; then
testssl='testssl.bash'
TESTSSL_ARGS="--connect-timeout $timeout --openssl-timeout $timeout --standard --vulnerable"
#? --ssl-native
TESTSSL_ARGS="$TESTSSL_ARGS --add-ca $CAFILE --assume-http --hints --color=0 --append"
else
# no proxy support
testssl=''
fi
if [ -f /usr/local/bin/scurl.bash ] ; then
curl="/usr/local/bin/scurl.bash -- -s -S"
else
curl='curl -s -S'
fi
CURL_ARGS="-vvv --cacert $CAFILE --cert-status --connect-timeout $timeout"
if [ -f $PREFIX/bin/analyze-ssl.pl.bash ] ; then
analyze=$PREFIX/bin/analyze-ssl.pl.bash
ANALYZE_ARGS="-v --timeout $timeout --CApath $CAFILE --all-ciphers"
else
analyze=""
fi
warns=0
OUTR=$outdir/$prog-$NOW
if [ $nodig -eq 0 ] ; then
for item in $HOSTS ; do
i=0
OUTRF=$OUTR.$item
if [ $MODE = tor ] ; then
torresolve $item > $OUTRF.dig.out 2>&1
retval=$?
[ $retval -ne 0 ] && ERROR "torresolve $item $? - see $OUTRF.dig.out" && exit 1$?
elif false ; then
nslookup $item > $OUTRF.nslookup.out 2>&1
#?[ $? -eq 0 ] || WARN "nslookup $item $? - see $OUTRF.nslookup.out"
#?grep NXDOMAIN "$OUTRF.nslookup.out" && WARN "nslookup $item NXDOMAIN - see $OUTRF.nslookup.out"
else
dig $item > $OUTRF.dig.out 2>&1
[ $? -ne 0 ] && ERROR "dig $item $? - see $OUTRF.dig.out" && exit 1$?
grep 'ANSWER: 1' "$OUTRF.dig.out" || ERROR "dig $item no ANSWER - see $OUTRF.dig.out" && exit 2$?
fi
done
fi
# [ -r /etc/tor/torrc ]
# was https take precedence over socks
if [ -n "$socks_proxy" ] ; then
SOCKS_HOST=$( echo $socks_proxy|sed -e 's/.*@//' -e 's@/@@g' -e 's/:/ /g' -e 's/socks5* //' -e 's/ .*//' )
SOCKS_PORT=$( echo $socks_proxy|sed -e 's@/@@g' -e 's/:/ /g' -e 's/.* //' )
openssl='torsocks openssl'
# --interface lo --dns-interface lo
[ -n "$analyze" ] && analyze="torsocks $analyze"
[ -n "$testssl" ] && testssl="torsocks $testssl"
[ -n "$sslscan" ] && sslscan="torsocks $sslscan"
if [ $MODE = tor -o $MODE = selektor ] ; then
sudo grep -q "SocksPolicy *accept *$PROXY_WLAN_IP" /etc/tor/torrc || \
{ WARN "need SocksPolicy accept $PROXY_WLAN_IP in /etc/tor/torrc" ; }
fi
CURL_ARGS="$CURL_ARGS --proxy $socks_proxy "
if [ ${HTTPS_HOST} = 127.0.0.1 ] ; then
CURL_ARGS="$CURL_ARGS --interface"
fi
if netstat -nle4 | grep 127.0.1:53 ; then
CURL_ARGS="$CURL_ARGS --dns-interface lo"
fi
elif [ -n "$https_proxy" ] ; then
HTTPS_HOST=$( echo $https_proxy|sed -e 's@/@@g' -e 's/:/ /g' -e 's/https* //' -e 's/ .*//' )
HTTPS_PORT=$( echo $https_proxy|sed -e 's@/@@g' -e 's/:/ /g' -e 's/.* //' )
OPENSSL_ARGS="$OPENSSL_ARGS -proxy ${HTTPS_HOST}:$HTTPS_PORT"
TESTSSL_ARGS="$TESTSSL_ARGS --proxy=auto"
CURL_ARGS="$CURL_ARGS --proxy http://${HTTPS_HOST}:$HTTPS_PORT"
ANALYZE_ARGS="$ANALYZE_ARGS --starttls http_proxy:${HTTPS_HOST}:$HTTPS_PORT"
[ -n "$testssl" ] && testssl="torsocks $testssl"
[ -n "$sslscan" ] && sslscan="torsocks $sslscan"
else
: direct
fi
TENVS="DNS_VIA_PROXY=true"
errs=0
for CAFILE in /etc/ssl/certs/ca-certificates.crt /usr/local/etc/ssl/cacert-testforge.pem ; do
[ -f $CAFILE ] || { ERROR "CAfile not found $CAFILE" ; exit 8; }
for item in $HOSTS ; do
i=0
OUTRF=$OUTR.$item
if [ -n "$openssl" ] ; then
INFO "$openssl s_client -connect ${item}:443 -servername $item $OPENSSL_ARGS --CAfile $CAFILE"
echo $openssl s_client \
-connect ${item}:443 -servername $item $OPENSSL_ARGS --CAfile $CAFILE \
< /dev/null > $OUTRF.s_client.out
timeout ${kill_time}s \
$openssl s_client \
-connect ${item}:443 -servername $item $OPENSSL_ARGS --CAfile $CAFILE \
< /dev/null >> $OUTRF.s_client.out 2>&1
# :error:\|
if [ $? -eq 124 ] ; then
echo "DEBUG: timeout openssl s_client failed $? see $OUTRF.s_client.out"
elif [ $? -ne 0 ] ; then
WARN "openssl s_client failed $? see $OUTRF.s_client.out"
i=$( expr $i + 1 )
elif str='unable to get local issuer certificate' && \
grep "$str" $OUTRF.s_client.out; then
WARN "openssl s_client failed - $str see $OUTRF.s_client.out"
i=$( expr $i + 1 )
elif str='Cipher is (NONE)' && \
grep "$str" $OUTRF.s_client.out; then
WARN "openssl s_client failed - $str see $OUTRF.s_client.out"
i=$( expr $i + 1 )
elif str='SSL handshake has read 0 bytes' && \
grep "$str" $OUTRF.s_client.out; then
WARN "openssl s_client failed - $str see $OUTRF.s_client.out"
i=$( expr $i + 1 )
else
echo "DEBUG: openssl s_client -showcerts $OPENSSL_ARGS --CAfile $CAFILE $item"
timeout ${kill_time}s \
$openssl s_client -showcerts \
-connect ${item}:443 -servername $item $OPENSSL_ARGS --CAfile $CAFILE < /dev/null \
> $OUTRF.s_client.certs 2>&1
fi
fi
if [ -n "$sslscan" ] ; then
echo $sslscan $SSLSCAN_ARGS --certs $CAFILE --sni-name $item $item > $OUTRF.sslscan.out
timeout ${kill_time}s \
$sslscan $SSLSCAN_ARGS --sni-name $item $item >> $OUTRF.sslscan.out 2>&1
if [ $? -eq 124 ] ; then
echo "DEBUG: timeout sslscan failed $? see $OUTRF.sslscan.out "
elif [ $? -ne 0 ] ; then
WARN "sslscan failed $? see $OUTRF.sslscan.out "
i=$( expr $i + 1 )
elif grep 'SSL Certificate' $OUTRF.sslscan.out ; then
WARN "sslscan failed see $OUTRF.sslscan.out "
i=$( expr $i + 1 )
elif grep 'Connection failed' $OUTRF.sslscan.out ; then
# tail -1 $OUTRF.sslscan.out | grep 'Supported Server Cipher'
WARN "sslscan failed see $OUTRF.sslscan.out "
i=$( expr $i + 1 )
else
INFO "$sslscan $SSLSCAN_ARGS $item"
fi
fi
if [ -n "$testssl" -a -n "$https_proxy" ] ; then
# rDNS (140.82.114.3): lb-140-82-114-3-iad.github.com.testssl.sh: line 10330: /dev/tcp/140.82.114.3/443: No such file or directory
echo $TENVS $testssl $TESTSSL_ARGS $item > $OUTRF.testssl.out
env $TENVS $testssl $TESTSSL_ARGS $item >> $OUTRF.testssl.out 2>&1
if [ $? -ne 0 ] ; then
WARN "testssl failed $? see $OUTRF.testssl.out"
i=$( expr $i + 1 )
elif grep ': unable to\| error:\|doesn.t seem to be a TLS/SSL enabled server' $OUTRF.testssl.out; then
WARN "testssl failure see $OUTRF.testssl.out"
i=$( expr $i + 1 )
else
INFO "$testssl $TESTSSL_ARGS $item"
echo "DEBUG: $testssl $TESTSSL_ARGS --jsonfile-pretty $OUTRF.testssl.json $item"
env $TENVS $testssl $TESTSSL_ARGS --jsonfile-pretty $OUTRF.testssl.json $item > $OUTRF.testssl-json.out 2>&1
fi
fi
if [ -n "$curl" ] ; then
DBUG $TENVS $curl $CURL_ARGS -o /dev/null https://$item/
env $TENVS $curl $CURL_ARGS -o /dev/null https://$item/ > $OUTRF.curl-vvv.out 2>&1
if [ $? -eq 0 ] ; then
grep 'SSL certificate problem:' $OUTRF.curl-vvv.out && \
{ WARN "curl -vvv failed $? see $OUTRF.curl-vvv.out" ;
i=$( expr $i + 1 ) ; } || \
INFO $curl $CURL_ARGS $item
else
INFO $curl $CURL_ARGS $item
fi
fi
if [ -n "$analyze" ] ; then
timeout ${kill_time}s \
$analyze $ANALYZE_ARGS --name $item ${item}:443 \
> $OUTRF.analyze-ssl.out 2>&1
# certificate verified : ok
if [ $? -eq 124 ] ; then
echo "DEBUG: timeout $analyze $ANALYZE_ARGS $item"
elif [ $? -eq 0 ] ; then
INFO "$analyze $ANALYZE_ARGS $item"
else
WARN "$analyze failed $? see $OUTRF.analyze-ssl.out"
i=$( expr $i + 1 )
fi
fi
[ $i -eq 0 ] && continue
WARN "$i failures for $item"
errs=$(expr $errs + $i )
DBUG $OUTRF.*.out
done
done
find $OUTRF.* -type f -empty -delete
exit $errs