352 lines
11 KiB
Bash
Executable File
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 /var/local/bin/analyze-ssl.pl.bash ] ; then
|
|
analyze=/var/local/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
|