Merge branch 'drwetter:3.1dev' into 3.1dev

This commit is contained in:
Jauder Ho 2021-07-31 14:28:57 -07:00 committed by GitHub
commit 91970a2214
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 203 additions and 65 deletions

View File

@ -7,7 +7,7 @@ assignees: ''
--- ---
_Feel free to remove this line but please stick to the template. We would like to reproduce the bug and therefore need concise information. _ _Feel free to remove this line but please stick to the template. We would like to reproduce the bug and therefore need concise information. Depending on the completeness of your information provided we might close your issue otherwise. _
**Please check this repo whether this is a known issue** **Please check this repo whether this is a known issue**

View File

@ -1,9 +1,9 @@
### Contributions / participation ### Contributions / participation
is always welcome! is always welcome, here @ gihub or via e-mail.
Note please the following: Note please the following
* Please read at least the [coding convention](https://github.com/drwetter/testssl.sh/Coding_Convention.md). * Please read at least the [coding convention](https://github.com/drwetter/testssl.sh/Coding_Convention.md).
* One PR per feature or bug fix or improvement. Please do not mix issues. * One PR per feature or bug fix or improvement. Please do not mix issues.
@ -13,5 +13,9 @@ Note please the following:
* If it's a new feature please consider writing a unit test for it. You can use e.g. `t/20_baseline_ipv4_http.t` as a template. The general documentation for [Test::More](https://perldoc.perl.org/Test/More.html) is a good start. * If it's a new feature please consider writing a unit test for it. You can use e.g. `t/20_baseline_ipv4_http.t` as a template. The general documentation for [Test::More](https://perldoc.perl.org/Test/More.html) is a good start.
* If it's a new feature it would need to be documented in the appropriate section in `help()` and in `~/doc/testssl.1.md` * If it's a new feature it would need to be documented in the appropriate section in `help()` and in `~/doc/testssl.1.md`
For questions just open an issue. For questions just open an issue or feel free to send me an e-mail.
#### Patches via e-mail
Of course it is fine when you want to send in patches to use e-mail. For the address please grep for SWCONTACT in testssl.sh .
Let me know how you like them to be attributed.

View File

@ -1,4 +1,4 @@
FROM alpine:3.12 FROM alpine:3.13
RUN apk update && \ RUN apk update && \
apk upgrade && \ apk upgrade && \

View File

@ -351,6 +351,8 @@ HAS_ZLIB=false
HAS_UDS=false HAS_UDS=false
HAS_UDS2=false HAS_UDS2=false
HAS_DIG=false HAS_DIG=false
HAS_DIG_R=true
DIG_R="-r"
HAS_HOST=false HAS_HOST=false
HAS_DRILL=false HAS_DRILL=false
HAS_NSLOOKUP=false HAS_NSLOOKUP=false
@ -634,7 +636,9 @@ pr_bold() { tm_bold "$1"; [[ "$COLOR" -ne 0 ]] && html_out "<span style=\"
prln_bold() { pr_bold "$1" ; outln; } prln_bold() { pr_bold "$1" ; outln; }
NO_ITALICS=false NO_ITALICS=false
if [[ $SYSTEM == OpenBSD ]]; then if [[ $TERM == screen ]]; then
NO_ITALICS=true
elif [[ $SYSTEM == OpenBSD ]]; then
NO_ITALICS=true NO_ITALICS=true
elif [[ $SYSTEM == FreeBSD ]]; then elif [[ $SYSTEM == FreeBSD ]]; then
if [[ ${SYSTEMREV%\.*} -le 9 ]]; then if [[ ${SYSTEMREV%\.*} -le 9 ]]; then
@ -1555,6 +1559,14 @@ prepare_logging() {
################### END all file output functions ######################### ################### END all file output functions #########################
# prints a string of n spaces (n < 80)
print_n_spaces() {
local -i n="$1"
local spaces=" "
out "${spaces:0:n}"
}
# prints out multiple lines in $1, left aligned by spaces in $2 # prints out multiple lines in $1, left aligned by spaces in $2
out_row_aligned() { out_row_aligned() {
local first=true local first=true
@ -1638,14 +1650,12 @@ out_row_aligned_max_width_by_entry() {
print_fixed_width() { print_fixed_width() {
local text="$1" local text="$1"
local -i i len width="$2" local -i len width="$2"
local print_function="$3" local print_function="$3"
len=${#text} len=${#text}
$print_function "$text" $print_function "$text"
for (( i=len; i <= width; i++ )); do print_n_spaces "$((width-len+1))"
out " "
done
} }
# saves $TMPFILE or file supplied in $2 under name "$TEMPDIR/$NODEIP.$1". # saves $TMPFILE or file supplied in $2 under name "$TEMPDIR/$NODEIP.$1".
@ -3570,9 +3580,7 @@ neat_list(){
fi fi
fi fi
len=${#kx} len=${#kx}
for (( i=len; i<10; i++ )); do print_n_spaces "$((10-len))"
out " "
done
out "$(printf -- " %-12s%-8s " "$enc" "$strength")" out "$(printf -- " %-12s%-8s " "$enc" "$strength")"
if [[ "$COLOR" -le 2 ]]; then if [[ "$COLOR" -le 2 ]]; then
if [[ "$DISPLAY_CIPHERNAMES" == rfc ]]; then if [[ "$DISPLAY_CIPHERNAMES" == rfc ]]; then
@ -4984,13 +4992,9 @@ run_client_simulation() {
pr_cipher_quality "$cipher" pr_cipher_quality "$cipher"
fi fi
if [[ "$DISPLAY_CIPHERNAMES" =~ openssl ]]; then if [[ "$DISPLAY_CIPHERNAMES" =~ openssl ]]; then
for (( j=${#cipher}; j < 34; j++ )); do print_n_spaces "$((34-${#cipher}))"
out " "
done
else else
for (( j=${#cipher}; j < 50; j++ )); do print_n_spaces "$((50-${#cipher}))"
out " "
done
fi fi
if [[ -n "$what_dh" ]]; then if [[ -n "$what_dh" ]]; then
[[ -n "$curve" ]] && curve="($curve)" [[ -n "$curve" ]] && curve="($curve)"
@ -19562,6 +19566,7 @@ HAS_IDN: $HAS_IDN
HAS_IDN2: $HAS_IDN2 HAS_IDN2: $HAS_IDN2
HAS_AVAHIRESOLVE: $HAS_AVAHIRESOLVE HAS_AVAHIRESOLVE: $HAS_AVAHIRESOLVE
HAS_DIG_NOIDNOUT: $HAS_DIG_NOIDNOUT HAS_DIG_NOIDNOUT: $HAS_DIG_NOIDNOUT
HAS_DIG_R: $HAS_DIG_R
HAS_XXD: $HAS_XXD HAS_XXD: $HAS_XXD
PATH: $PATH PATH: $PATH
@ -20024,12 +20029,18 @@ check_resolver_bins() {
type -p idn &>/dev/null && HAS_IDN=true type -p idn &>/dev/null && HAS_IDN=true
type -p idn2 &>/dev/null && HAS_IDN2=true type -p idn2 &>/dev/null && HAS_IDN2=true
# Old dig versions don't have an option to ignore $HOME/.digrc
if dig -r 2>&1 | grep -qiE 'invalid|usage'; then
HAS_DIG_R=false
DIG_R=""
fi
OPENSSL_CONF="" # see https://github.com/drwetter/testssl.sh/issues/134 OPENSSL_CONF="" # see https://github.com/drwetter/testssl.sh/issues/134
if ! "$HAS_DIG" && ! "$HAS_HOST" && ! "$HAS_DRILL" && ! "$HAS_NSLOOKUP"; then if ! "$HAS_DIG" && ! "$HAS_HOST" && ! "$HAS_DRILL" && ! "$HAS_NSLOOKUP"; then
fatal "Neither \"dig\", \"host\", \"drill\" or \"nslookup\" is present" $ERR_DNSBIN fatal "Neither \"dig\", \"host\", \"drill\" or \"nslookup\" is present" $ERR_DNSBIN
fi fi
if "$HAS_DIG"; then if "$HAS_DIG"; then
if dig +noidnout -t a 2>&1 | grep -Eq 'Invalid option: \+noidnout|IDN support not enabled'; then if dig $DIG_R +noidnout -t a 2>&1 | grep -Eq 'Invalid option: \+noidnout|IDN support not enabled'; then
: :
else else
HAS_DIG_NOIDNOUT=true HAS_DIG_NOIDNOUT=true
@ -20063,13 +20074,13 @@ get_a_record() {
if "$HAS_AVAHIRESOLVE"; then if "$HAS_AVAHIRESOLVE"; then
ip4=$(filter_ip4_address $(avahi-resolve -4 -n "$1" 2>/dev/null | awk '{ print $2 }')) ip4=$(filter_ip4_address $(avahi-resolve -4 -n "$1" 2>/dev/null | awk '{ print $2 }'))
elif "$HAS_DIG"; then elif "$HAS_DIG"; then
ip4=$(filter_ip4_address $(dig @224.0.0.251 -p 5353 +short -t a +notcp "$1" 2>/dev/null | sed '/^;;/d')) ip4=$(filter_ip4_address $(dig $DIG_R @224.0.0.251 -p 5353 +short -t a +notcp "$1" 2>/dev/null | sed '/^;;/d'))
else else
fatal "Local hostname given but no 'avahi-resolve' or 'dig' available." $ERR_DNSBIN fatal "Local hostname given but no 'avahi-resolve' or 'dig' available." $ERR_DNSBIN
fi fi
fi fi
if [[ -z "$ip4" ]] && "$HAS_DIG"; then if [[ -z "$ip4" ]] && "$HAS_DIG"; then
ip4=$(filter_ip4_address $(dig +short +timeout=2 +tries=2 $noidnout -t a "$1" 2>/dev/null | awk '/^[0-9]/ { print $1 }')) ip4=$(filter_ip4_address $(dig $DIG_R +short +timeout=2 +tries=2 $noidnout -t a "$1" 2>/dev/null | awk '/^[0-9]/ { print $1 }'))
fi fi
if [[ -z "$ip4" ]] && "$HAS_HOST"; then if [[ -z "$ip4" ]] && "$HAS_HOST"; then
ip4=$(filter_ip4_address $(host -t a "$1" 2>/dev/null | awk '/address/ { print $NF }')) ip4=$(filter_ip4_address $(host -t a "$1" 2>/dev/null | awk '/address/ { print $NF }'))
@ -20107,12 +20118,12 @@ get_aaaa_record() {
if "$HAS_AVAHIRESOLVE"; then if "$HAS_AVAHIRESOLVE"; then
ip6=$(filter_ip6_address $(avahi-resolve -6 -n "$1" 2>/dev/null | awk '{ print $2 }')) ip6=$(filter_ip6_address $(avahi-resolve -6 -n "$1" 2>/dev/null | awk '{ print $2 }'))
elif "$HAS_DIG"; then elif "$HAS_DIG"; then
ip6=$(filter_ip6_address $(dig @ff02::fb -p 5353 -t aaaa +short +notcp "$NODE")) ip6=$(filter_ip6_address $(dig $DIG_R @ff02::fb -p 5353 -t aaaa +short +notcp "$NODE"))
else else
fatal "Local hostname given but no 'avahi-resolve' or 'dig' available." $ERR_DNSBIN fatal "Local hostname given but no 'avahi-resolve' or 'dig' available." $ERR_DNSBIN
fi fi
elif "$HAS_DIG"; then elif "$HAS_DIG"; then
ip6=$(filter_ip6_address $(dig +short +timeout=2 +tries=2 $noidnout -t aaaa "$1" 2>/dev/null | awk '/^[0-9]/ { print $1 }')) ip6=$(filter_ip6_address $(dig $DIG_R +short +timeout=2 +tries=2 $noidnout -t aaaa "$1" 2>/dev/null | awk '/^[0-9]/ { print $1 }'))
elif "$HAS_HOST"; then elif "$HAS_HOST"; then
ip6=$(filter_ip6_address $(host -t aaaa "$1" | awk '/address/ { print $NF }')) ip6=$(filter_ip6_address $(host -t aaaa "$1" | awk '/address/ { print $NF }'))
elif "$HAS_DRILL"; then elif "$HAS_DRILL"; then
@ -20148,7 +20159,7 @@ get_caa_rr_record() {
# caa_property then has key/value pairs, see https://tools.ietf.org/html/rfc6844#section-3 # caa_property then has key/value pairs, see https://tools.ietf.org/html/rfc6844#section-3
OPENSSL_CONF="" OPENSSL_CONF=""
if "$HAS_DIG"; then if "$HAS_DIG"; then
raw_caa="$(dig +short +timeout=3 +tries=3 $noidnout type257 "$1" 2>/dev/null | awk '{ print $1" "$2" "$3 }')" raw_caa="$(dig $DIG_R +short +timeout=3 +tries=3 $noidnout type257 "$1" 2>/dev/null | awk '{ print $1" "$2" "$3 }')"
# empty if no CAA record # empty if no CAA record
elif "$HAS_DRILL"; then elif "$HAS_DRILL"; then
raw_caa="$(drill $1 type257 | awk '/'"^${1}"'.*CAA/ { print $5,$6,$7 }')" raw_caa="$(drill $1 type257 | awk '/'"^${1}"'.*CAA/ { print $5,$6,$7 }')"
@ -20219,7 +20230,7 @@ get_mx_record() {
if "$HAS_HOST"; then if "$HAS_HOST"; then
mx="$(host -t MX "$1" 2>/dev/null | awk '/is handled by/ { print $(NF-1), $NF }')" mx="$(host -t MX "$1" 2>/dev/null | awk '/is handled by/ { print $(NF-1), $NF }')"
elif "$HAS_DIG"; then elif "$HAS_DIG"; then
mx="$(dig +short $noidnout -t MX "$1" 2>/dev/null | awk '/^[0-9]/ { print $1" "$2 }')" mx="$(dig $DIG_R +short $noidnout -t MX "$1" 2>/dev/null | awk '/^[0-9]/ { print $1" "$2 }')"
elif "$HAS_DRILL"; then elif "$HAS_DRILL"; then
mx="$(drill mx $1 | awk '/IN[ \t]MX[ \t]+/ { print $(NF-1), $NF }')" mx="$(drill mx $1 | awk '/IN[ \t]MX[ \t]+/ { print $(NF-1), $NF }')"
elif "$HAS_NSLOOKUP"; then elif "$HAS_NSLOOKUP"; then
@ -20246,7 +20257,7 @@ get_txt_record() {
if "$HAS_HOST"; then if "$HAS_HOST"; then
record="$(host -t TXT "$1" 2>/dev/null | awk -F\" '/descriptive text/ { print $(NF-1) }')" record="$(host -t TXT "$1" 2>/dev/null | awk -F\" '/descriptive text/ { print $(NF-1) }')"
elif "$HAS_DIG"; then elif "$HAS_DIG"; then
record="$(dig +short $noidnout -t TXT "$1" 2>/dev/null)" record="$(dig $DIG_R +short $noidnout -t TXT "$1" 2>/dev/null)"
elif "$HAS_DRILL"; then elif "$HAS_DRILL"; then
record="$(drill txt $1 | awk -F\" '/^[a-z0-9].*TXT/ { print $(NF-1) }')" record="$(drill txt $1 | awk -F\" '/^[a-z0-9].*TXT/ { print $(NF-1) }')"
elif "$HAS_NSLOOKUP"; then elif "$HAS_NSLOOKUP"; then
@ -20346,11 +20357,11 @@ determine_rdns() {
if "$HAS_AVAHIRESOLVE"; then if "$HAS_AVAHIRESOLVE"; then
rDNS=$(avahi-resolve -a $nodeip 2>/dev/null | awk '{ print $2 }') rDNS=$(avahi-resolve -a $nodeip 2>/dev/null | awk '{ print $2 }')
elif "$HAS_DIG"; then elif "$HAS_DIG"; then
rDNS=$(dig -x $nodeip @224.0.0.251 -p 5353 +notcp +noall +answer +short | awk '{ print $1 }') rDNS=$(dig $DIG_R -x $nodeip @224.0.0.251 -p 5353 +notcp +noall +answer +short | awk '{ print $1 }')
fi fi
elif "$HAS_DIG"; then elif "$HAS_DIG"; then
# 1+2 should suffice. It's a compromise for if e.g. network is down but we have a docker/localhost server # 1+2 should suffice. It's a compromise for if e.g. network is down but we have a docker/localhost server
rDNS=$(dig -x $nodeip +timeout=1 +tries=2 +noall +answer +short | awk '{ print $1 }') # +short returns also CNAME, e.g. openssl.org rDNS=$(dig $DIG_R -x $nodeip +timeout=1 +tries=2 +noall +answer +short | awk '{ print $1 }') # +short returns also CNAME, e.g. openssl.org
elif "$HAS_HOST"; then elif "$HAS_HOST"; 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 "$HAS_DRILL"; then elif "$HAS_DRILL"; then
@ -21353,7 +21364,7 @@ nmap_to_plain_file() {
local target_fname="" local target_fname=""
local oneline="" local oneline=""
local ip hostdontcare round_brackets ports_specs starttls local ip hostdontcare round_brackets ports_specs starttls
local tmp port host_spec protocol dontcare dontcare1 local tmp port host_spec protocol ssl_hint dontcare dontcare1
#FIXME: IPv6 is missing here #FIXME: IPv6 is missing here
# Ok, since we are here we are sure to have an nmap file. To avoid questions we make sure it's the right format too # Ok, since we are here we are sure to have an nmap file. To avoid questions we make sure it's the right format too
@ -21368,17 +21379,12 @@ nmap_to_plain_file() {
else else
fatal "Nmap file $FNAME is not in grep(p)able format (-oG filename.g(n)map)" $ERR_FNAMEPARSE fatal "Nmap file $FNAME is not in grep(p)able format (-oG filename.g(n)map)" $ERR_FNAMEPARSE
fi fi
# strip extension and create output file *.txt in same folder # create ${FNAME%.*}.txt in $TEMPDIR
target_fname="${FNAME%.*}.txt" target_fname="${FNAME%.*}.txt"
> "${target_fname}" target_fname="${target_fname##*\/}" # strip path (Unix)
if [[ $? -ne 0 ]]; then target_fname="${target_fname##*\\}" # strip path (Dos)
# try to just create ${FNAME%.*}.txt in the same dir as the gnmap file failed. target_fname="$TEMPDIR/$target_fname"
# backup is using one in $TEMPDIR > "${target_fname}" || fatal "Cannot create \"${target_fname}\"" $ERR_FCREATE
target_fname="${target_fname##*\/}" # strip path (Unix)
target_fname="${target_fname##*\\}" # strip path (Dos)
target_fname="$TEMPDIR/$target_fname"
> "${target_fname}" || fatal "Cannot create \"${target_fname}\"" $ERR_FCREATE
fi
# Line x: "Host: AAA.BBB.CCC.DDD (<FQDN>) Status: Up" # Line x: "Host: AAA.BBB.CCC.DDD (<FQDN>) Status: Up"
# Line x+1: "Host: AAA.BBB.CCC.DDD (<FQDN>) Ports: 443/open/tcp//https///" # Line x+1: "Host: AAA.BBB.CCC.DDD (<FQDN>) Ports: 443/open/tcp//https///"
@ -21399,11 +21405,15 @@ nmap_to_plain_file() {
while read -r oneline; do while read -r oneline; do
# 25/open/tcp//smtp//<banner>/, # 25/open/tcp//smtp//<banner>/,
[[ "$oneline" =~ '/open/tcp/' ]] || continue # no open tcp for this port on this IP --> move on [[ "$oneline" =~ '/open/tcp/' ]] || continue # no open tcp for this port on this IP --> move on
IFS=/ read -r port dontcare protocol dontcare1 <<< "$oneline" IFS=/ read -r port dontcare protocol ssl_hint dontcare1 <<< "$oneline"
starttls="$(ports2starttls $port)" if [[ "$ssl_hint" =~ ^(ssl|https) ]] || [[ "$dontcare1" =~ ^(ssl|https) ]]; then
[[ $? -eq 1 ]] && continue # nmap got a port but we don't know how to speak to echo "${host_spec}:${port}" >>"$target_fname"
[[ "$DEBUG" -ge 1 ]] && echo "${starttls}$host_spec:$port" else
echo "${starttls}${host_spec}:${port}" >>"$target_fname" starttls="$(ports2starttls $port)"
[[ $? -eq 1 ]] && continue # nmap got a port but we don't know how to speak to
[[ "$DEBUG" -ge 1 ]] && echo "${starttls}$host_spec:$port"
echo "${starttls}${host_spec}:${port}" >>"$target_fname"
fi
done < <(tr ',' '\n' <<< "$ports_specs") done < <(tr ',' '\n' <<< "$ports_specs")
done < "$FNAME" done < "$FNAME"
[[ "$DEBUG" -ge 1 ]] && echo [[ "$DEBUG" -ge 1 ]] && echo

View File

@ -1,43 +1,167 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -e # Utility which converts grepable nmap outout to testssl's file input
# It is just borrowed from testssl.sh
# License see testssl.sh
# utility which converts grepable nmap outout to testssl's file input
echo A | sed -E 's/A//' >/dev/null 2>&1 && \
declare -r HAS_SED_E=true || \
declare -r HAS_SED_E=false
usage() { usage() {
cat << EOF cat << EOF
usage: usage:
"$0 filename<.gmap>": looks for filename/filename.gmap and converts into basename \$(filename)-testssl.txt" "$0 <filename>": looks for <filename> (nmap gmap format) and converts into basename \$(filename)-testssl.txt"
"$0 filename<.gmap>" "scan option": same as before, only adds testssl.sh scan option in front of IPs"
EOF EOF
exit 0 exit 0
} }
[ -z "$1" ] && usage fatal () {
FNAME="$1" echo "$1" >&2
OPT2ADD="${2:-}" exit $2
}
if ! grep -q gmap <<< "$FNAME"; then is_ipv4addr() {
FNAME="$FNAME.gmap" local octet="(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])"
fi local ipv4address="$octet\\.$octet\\.$octet\\.$octet"
[ ! -e $FNAME ] && echo "$FNAME not readable" && exit 2
[[ -z "$1" ]] && return 1
TARGET_FNAME=${FNAME%.*}-testssl.txt # Check that $1 contains an IPv4 address and nothing else
[[ "$1" =~ $ipv4address ]] && [[ "$1" == $BASH_REMATCH ]] && \
return 0 || \
return 1
}
# test whether there's more than one "open" per line filter_ip4_address() {
while read -r oneline; do local a
if [ $(echo "${oneline}" | tr ',' '\n' | grep -wc 'open') -gt 1 ]; then
# not supported currently for a in "$@"; do
echo "$FNAME contains at least on one line more than 1x\"open\"" if ! is_ipv4addr "$a"; then
exit 3 continue
fi
if "$HAS_SED_E"; then
sed -E 's/[^[:digit:].]//g' <<< "$a" | sed -e '/^$/d'
else
sed -r 's/[^[:digit:].]//g' <<< "$a" | sed -e '/^$/d'
fi
done
}
# arg1: a host name. Returned will be 0-n IPv4 addresses
# watch out: $1 can also be a cname! --> all checked
get_a_record() {
local ip4=""
local noidnout=""
ip4=$(filter_ip4_address $(dig -r +short +timeout=2 +tries=2 -t a "$1" 2>/dev/null | awk '/^[0-9]/ { print $1 }'))
if [[ -z "$ip4" ]]; then
ip4=$(filter_ip4_address $(host -t a "$1" 2>/dev/null | awk '/address/ { print $NF }'))
fi fi
done < "$FNAME" if [[ -z "$ip4" ]]; then
ip4=$(filter_ip4_address $(drill a "$1" | awk '/ANSWER SECTION/,/AUTHORITY SECTION/ { print $NF }' | awk '/^[0-9]/'))
fi
echo "$ip4"
}
ports2starttls() {
local tcp_port=$1
local ret=0
# https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers
case $tcp_port in
21) echo "-t ftp " ;;
23) echo "-t telnet " ;;
119|433) echo "-t nntp " ;; # to come
25|587) echo "-t smtp " ;;
110) echo "-t pop3 " ;;
143) echo "-t imap " ;;
389) echo "-t ldap ";;
3306) echo "-t mysql " ;;
5222) echo "-t xmpp " ;; # domain of jabber server maybe needed
5432) echo "-t postgres " ;;
563) ;; # NNTPS
636) ;; # LDAP
1443|8443|443|981) ;; # HTTPS
465) ;; # HTTPS | SMTP
631) ;; # CUPS
853) ;; # DNS over TLS
995|993) ;; # POP3|IMAP
3389) ;; # RDP
*) ret=1 ;; # we don't know this ports so we rather do not scan it
esac
return $ret
}
nmap_to_plain_file () {
local fname="$1"
local target_fname=""
local oneline=""
local ip hostdontcare round_brackets ports_specs starttls
local tmp port host_spec protocol ssl_hint dontcare dontcare1
# Ok, since we are here we are sure to have an nmap file. To avoid questions we make sure it's the right format too
if [[ "$(head -1 "$fname")" =~ ( -oG )(.*) ]] || [[ "$(head -1 "$fname")" =~ ( -oA )(.*) ]] ; then
# yes, greppable
if [[ $(grep -c Status "$fname") -ge 1 ]]; then
[[ $(grep -c '\/open\/' "$fname") -eq 0 ]] && \
fatal "Nmap file $fname should contain at least one open port" 250
else
fatal "strange, nmap grepable misses \"Status\"" 251
fi
else
fatal "Nmap file $fname is not in grep(p)able format (-oG filename.g(n)map)" 250
fi
target_fname="${fname%.*}"-testssl.txt
[[ -e $target_fname ]] && fatal "$target_fname already exists" 3
> "${target_fname}" || fatal "Cannot create \"${target_fname}\"" 252
# Line x: "Host: AAA.BBB.CCC.DDD (<FQDN>) Status: Up"
# Line x+1: "Host: AAA.BBB.CCC.DDD (<FQDN>) Ports: 443/open/tcp//https///"
# (or): Host: AAA.BBB.CCC.DDD (<FQDN>) Ports: 22/open/tcp//ssh//<banner>/, 25/open/tcp//smtp//<banner>/, 443/open/tcp//ssl|http//<banner>
while read -r hostdontcare ip round_brackets tmp ports_specs; do
[[ "$ports_specs" =~ "Status: " ]] && continue # we don't need this
[[ "$ports_specs" =~ '/open/tcp/' ]] || continue # no open tcp at all for this IP --> move
host_spec="$ip"
fqdn="${round_brackets/\(/}"
fqdn="${fqdn/\)/}"
if [[ -n "$fqdn" ]]; then
tmp="$(get_a_record "$fqdn")"
if [[ "$tmp" == "$ip" ]]; then
host_spec="$fqdn"
fi
fi
while read -r oneline; do
# 25/open/tcp//smtp//<banner>/,
[[ "$oneline" =~ '/open/tcp/' ]] || continue # no open tcp for this port on this IP --> move on
IFS=/ read -r port dontcare protocol ssl_hint dontcare1 <<< "$oneline"
if [[ "$ssl_hint" =~ ^(ssl|https) ]] || [[ "$dontcare1" =~ ^(ssl|https) ]]; then
echo "${host_spec}:${port}" >>"$target_fname"
else
starttls="$(ports2starttls $port)"
[[ $? -eq 1 ]] && continue # nmap got a port but we don't know how to speak to
echo "${starttls}${host_spec}:${port}" >>"$target_fname"
fi
done < <(tr ',' '\n' <<< "$ports_specs")
done < "$fname"
[[ -s "$target_fname" ]] || fatal "Couldn't find any open port in $fname" 253
echo "$target_fname written successfully"
return 0
}
[[ -z "$1" ]] && usage
FNAME="$1"
[[ ! -e $FNAME ]] && echo "$FNAME not readable" && exit 2
nmap_to_plain_file "$FNAME"
awk '/\<open\>/ { print "'"${OPT2ADD}"' " $2":"$5 }' "$FNAME" | sed 's/\/open.*$//g' >"$TARGET_FNAME"
exit $? exit $?
# vim:ts=5:sw=5:expandtab # vim:ts=5:sw=5:expandtab