#!/bin/sh
# Filename: sslscanner
# Location: /usr/bin/
# Author: bgstack15
# Startdate: 2018-01-28
# Title: Ssl Scanner
# Purpose: To make it easy to inspect the certificates a site is serving
# History:
#    2019-01-16 14:18 add SAN and make the editor optional
#    2020-04-19 remove trap 17 (breaks dash)
# Usage:
#    sslscanner example.com:636
#    SS_VI=1 will open the raw output in $VISUAL.
# Reference:
#    awk trick to split file based on matching line http://www.theunixschool.com/2012/06/awk-10-examples-to-split-file-into.html
# Improve:
#    accept --sni, [ file.ext | https://site:443 ]
# Documentation:
# Dependencies:
#    dep-raw: openssl, sed, awk, grep, vi
#    rec-devuan: openssl, coreutils
#    sug-devuan: vim-tiny

# FUNCTIONS
clean_sslscanner() {
   rm -rf "${ss_tmpdir:-NOTHINGTODELETE}" 1>/dev/null 2>&1
}

get_openssl_format_site() {
   # call: get_openssl_format_site connect "${site}"
   local output=""
   local thistype="${1}"
   local input="${2}"
   case "${thistype}" in
      connect)
         # output = example.com:443
         output="$( echo "${input}" | sed -r -e 's/(.{0,8}:\/\/[^\/]+)\/.*/\1/;' -e 's/.{0,8}:\/\///;' -e '/:[0-9]+/!{s/$/:443/;}' )"
         ;;
      sni)
         # output = example.com
         output="$( echo "${input}" | sed -r -e 's/.{0,8}:\/\/([^\/]+).*/\1/;' -e 's/:[0-9]*$//;' )"
         ;;
      *)
         echo "get_openssl_format_site does not support \"${thistype}\" yet. Outputting empty string..." 1>&2
         ;;
   esac
   printf "%s" "${output}"
}

# VARIABLES
site="${1}"
connectsite="$( get_openssl_format_site connect "${site}" )"
test -z "${snisite}" && snisite="$( get_openssl_format_site sni "${site}" )"
ss_tmpdir="$( mktemp -d )"
trap '__ec=$? ; clean_sslscanner ; trap "" 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 18 19 20 ; exit ${__ec} ;' 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 18 19 20
outputraw="$( TMPDIR="${ss_tmpdir}" mktemp )"
test -z "${VISUAL}" && VISUAL="$( which vi )"

# FETCH CERTS
echo "" | openssl s_client -showcerts -servername "${snisite}" -connect "${connectsite}" 1> "${outputraw}" 2>/dev/null

# SPLIT CERTS
count_cert="$( cd "${ss_tmpdir}" ; awk 'BEGIN{a=1} {b=a} /---END CERTIFICATE/{a=a+1;} {print > "cert"b} END{print b-1}' "${outputraw}" )"

# DISPLAY CERTS
x=1
while test "${x}" -le ${count_cert}
do
   thiscert="cert${x}"
   cat "${ss_tmpdir}/${thiscert}" | openssl x509 -noout -subject -issuer -dates
   cat "${ss_tmpdir}/${thiscert}" | openssl x509 -noout -text | grep -A1 'X509v3 Subject Alternative Name' | tail -n1 | tr ':,' '\n' | sed -r -e '/^ +(DNS|IP Address)/d' -e 's/^/san=/;'
   printf '\n'
   x=$(( x + 1 ))
done

test -n "${SS_VI}" && ${VISUAL} "${outputraw}"
