118 lines
3.5 KiB
Bash
Executable file
118 lines
3.5 KiB
Bash
Executable file
#!/bin/sh
|
|
|
|
# Not needed in this version of the script
|
|
set -e
|
|
|
|
PROGPATH=$( echo $0 | sed -e 's,[\\/][^\\/][^\\/]*$,,' )
|
|
REVISION="0.1"
|
|
|
|
. $PROGPATH/utils.sh
|
|
|
|
#
|
|
# Help function
|
|
#
|
|
usage() {
|
|
cat <<EOF
|
|
Usage :
|
|
$0 -h
|
|
$0 -H host -p port [-P protocol (tcp/udp)] [-S starttls-scheme (smtp)]
|
|
EOF
|
|
}
|
|
|
|
#
|
|
# Parameters management
|
|
#
|
|
CHECKED_PROTOCOL="tcp" # it's almost always TCP so we don't bother to ask
|
|
OPENSSL_OPTIONS=""
|
|
while getopts hH:p:P:S: f; do
|
|
case "$f" in
|
|
'h')
|
|
usage
|
|
exit
|
|
;;
|
|
|
|
'H')
|
|
CHECKED_HOSTNAME="$OPTARG"
|
|
;;
|
|
|
|
'p')
|
|
CHECKED_PORT="$( printf "%d" "$OPTARG" )"
|
|
;;
|
|
|
|
'P')
|
|
CHECKED_PROTOCOL="$OPTARG"
|
|
;;
|
|
|
|
'S')
|
|
OPENSSL_OPTIONS="$OPENSSL_OPTIONS -starttls $OPTARG"
|
|
;;
|
|
|
|
\?)
|
|
usage
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
if [ -z "$CHECKED_HOSTNAME" ]; then echo "ERROR empty parameter 'hostname'"; exit $STATE_UNKNOWN; fi
|
|
if [ -z "$CHECKED_PORT" ]; then echo "ERROR empty parameter 'port'"; exit $STATE_UNKNOWN; fi
|
|
|
|
|
|
|
|
# We get all TLSA record for the host
|
|
# FIXME: make a loop
|
|
# return example : "1 1 1 4A2403E87DBC4354570C5FDE24348EAED50B7791E4E2C3FC1D79B487 DDB9CC2C"
|
|
REQUEST_RECORD="_$CHECKED_PORT._$CHECKED_PROTOCOL.$CHECKED_HOSTNAME"
|
|
TLSA_RECORD="$( dig "$REQUEST_RECORD" TLSA +short | sed -n 's/^\([0-3]\)[[:space:]]\([01]\)[[:space:]]\([01]\)[[:space:]]/\1;\2;\3;/p' | sed 's/[[:space:]]//g' )"
|
|
if [ -z "$TLSA_RECORD" ]; then echo "ERROR no TLSA record at $REQUEST_RECORD"; exit $STATE_CRITICAL; fi
|
|
if [ -z "$( echo "$TLSA_RECORD" | sed -n '/^.;/p' )" ]; then echo "ERROR record malformed or too modern for this plugin"; exit $STATE_CRITICAL; fi
|
|
CPT=0
|
|
OUTPUT_STATUS=$STATE_OK
|
|
OUTPUT_DETAILS=""
|
|
MATCH_NUMBER=0
|
|
for LINE in $TLSA_RECORD; do
|
|
CERTIFICATE_USAGE="$( echo "$LINE" | cut -d ';' -f 1 )"
|
|
SELECTOR="$( echo "$LINE" | cut -d ';' -f 2 )"
|
|
MATCHING_TYPE="$( echo "$LINE" | cut -d ';' -f 3 )"
|
|
DATA="$( echo "$LINE" | cut -d ';' -f 4 )"
|
|
|
|
# PKI verification (TODO: to implement)
|
|
if [ "$CERTIFICATE_USAGE" -eq "0" ] || [ "$CERTIFICATE_USAGE" -eq "1" ]; then
|
|
OUTPUT_DETAILS="$OUTPUT_DETAILS (PKI check not implemented)"
|
|
fi
|
|
|
|
# Pointer
|
|
if [ "$CERTIFICATE_USAGE" -eq "1" ] || [ "$CERTIFICATE_USAGE" -eq "3" ]; then
|
|
# Check the certificate directly
|
|
case "$MATCHING_TYPE" in
|
|
'0')
|
|
# Entire info in base64
|
|
# TODO
|
|
;;
|
|
'1')
|
|
# SHA-256
|
|
OPENSSL_RESULT="$( openssl s_client $OPENSSL_OPTIONS -connect $CHECKED_HOSTNAME:$CHECKED_PORT -servername $CHECKED_HOSTNAME </dev/null 2>/dev/null | openssl x509 -pubkey -noout | openssl rsa -pubin -outform DER 2>/dev/null | openssl dgst -sha256 | tr a-z A-Z | sed 's/.*[[:space:]]//' )"
|
|
;;
|
|
'2')
|
|
# SHA-512
|
|
OPENSSL_RESULT="$( openssl s_client $OPENSSL_OPTIONS -connect $CHECKED_HOSTNAME:$CHECKED_PORT -servername $CHECKED_HOSTNAME </dev/null 2>/dev/null | openssl x509 -pubkey -noout | openssl rsa -pubin -outform DER 2>/dev/null | openssl dgst -sha512 | tr a-z A-Z | sed 's/.*[[:space:]]//' )"
|
|
;;
|
|
esac
|
|
if [ "$( echo "$DATA" | tr a-z A-Z )" = "$OPENSSL_RESULT" ]; then
|
|
OUTPUT_DETAILS="$OUTPUT_DETAILS $( echo $LINE | sed 's/^\(.\{8\}\).*\(.\{3\}\)$/\1...\2/' )-ok"
|
|
MATCH_NUMBER=$(( $MATCH_NUMBER + 1 ))
|
|
else
|
|
OUTPUT_DETAILS="$OUTPUT_DETAILS $( echo $LINE | sed 's/^\(.\{8\}\).*\(.\{3\}\)$/\1...\2/' )-NO"
|
|
fi
|
|
else
|
|
# Check one of the trust anchor
|
|
# TODO: to implement
|
|
OUTPUT_DETAILS="$OUTPUT_DETAILS (trust anchor check not implemented)"
|
|
fi
|
|
done
|
|
if [ "$MATCH_NUMBER" -eq 0 ]; then
|
|
echo "ERROR no match $OUTPUT_DETAILS"
|
|
exit $STATE_CRITICAL
|
|
else
|
|
echo "OK $OUTPUT_DETAILS"
|
|
exit $STATE_OK
|
|
fi
|