[GTALUG] Script to show HTTP(S) and TLS details for a website
William Park
opengeometry at yahoo.ca
Sun Aug 11 23:48:54 EDT 2019
On Sat, Aug 10, 2019 at 11:46:40AM -0400, Giles Orr via talk wrote:
> If you're interested, you can find the details here:
>
> https://www.gilesorr.com/blog/tls-https-details.html
>
> Any suggestions to improve the script would be most welcome.
OK, here it goes...
> # Put most desirable/least-likely last:
> for opensslbinary in /usr/local/opt/openssl at 1.1/bin/openssl /usr/local/opt/opens
> sl/bin/openssl /usr/bin/openssl
> do
> # Every version of OpenSSL I've checked (several across multiple
> # OpenSSL versions and Apple's LibreSSL) respond to 'openssl version'
> # with '<brand> <version-no> ...' - there may or may not be stuff after
> # those two items (usually a build date, but not with Libre).
> #
> if [ -f "${opensslbinary}" ]
'-f' tests if it's a file. Maybe you should use '-x' which tests if it's
executable.
> then
> output="$("${opensslbinary}" version)"
> brand="$( echo "${output}" | awk '{ print $1 }')"
> version="$(echo "${output}" | awk '{ print $2 }')"
> if [[ "OpenSSL" == "${brand}" ]]
> then
> if [[ "${version}" == "1.1"* ]]
> then
> OPENSSL="${opensslbinary}"
> fi
> fi
You got 7 subshells here. You can reduce it to 1 subshell:
read a b rest <<< $($opensslbinary version)
case $a:$b in
OpenSSL:1.1*) OPENSSL=$opensslbinary ;;
esac
> fi
> done
Maybe you should break out of the for-loop as soon as you find something
correct. As is, OPENSSL will be the last correct one.
> function help() {
> echo "Usage:"
> echo " $(basename "${0}") [-h]|<domain-name>"
> echo ""
> echo "Show HTTP(s) and certificate details."
> echo "Do not include the 'http(s)://' leader on the domain name."
> echo ""
> echo "-h show this help and exit"
Instead of echo'ing each and every line, you can do
cat << EOF
Usage:
$(basename "${0}") [-h]|<domain-name>
Show HTTP(s) and certificate details.
Do not include the 'http(s)://' leader on the domain name.
-h show this help and exit
EOF
> function expiry_date() {
> echo "${1}" | ${OPENSSL} x509 -noout -dates | grep notAfter | awk 'BEGIN { F
> S="=" } { print $2 }'
> }
You can get rid of grep, since you're already using awk.
echo "$1" | ${OPENSSL} x509 -noout -dates | awk -F= '/notAfter/ {print $2}'
>
> function days_to_expiry() {
> expiry_date="$(echo "${1}" | ${OPENSSL} x509 -noout -dates | grep notAfter |
> awk 'BEGIN { FS="=" } { print $2 }')"
You already defined expiry_date(), so why not use it here.
expiry_date=$(expiry_date "$1")
> if [[ "$(date --version 2>/dev/null)" == *"GNU"* ]]
> then
> # Linux (or at least GNU)
> expiry_epoch_seconds=$(date --date="${expiry_date}" "+%s")
> else
> # Assuming the Mac version:
> expiry_epoch_seconds=$(date -jf '%b %e %H:%M:%S %Y %Z' "${expiry_date}"
> "+%s")
> fi
Testing for "GNU" string can be done more simply using grep.
if date --version 2>/dev/null | grep -q GNU; then
...
else
...
fi
> function tlsversions() {
> successful=""
> failed=""
> for tlsversion in ssl2 ssl3 tls1 tls1_1 tls1_2 tls1_3
> do
> success=$(echo | ${OPENSSL} s_client -connect "${1}":443 -${tlsversion}
> > /dev/null 2> /dev/null ; echo $?)
> if [ ${success} -eq 0 ]
> then
> successful="${tlsversion} ${successful}"
> else
> failed="${tlsversion} ${failed}"
> fi
Testing if a command succeeded or failed can be done in-line.
if echo | ${OPENSSL} s_client -connect "${1}":443 -${tlsversion} &>/dev/null; then
successful=...
else
failed=...
fi
Also, do you really need to send empty line to openssl? Maybe you can redirect
stdin from /dev/null as well, like
openssl ... </dev/null ...
That will reduce 3 subshells to 0.
General observation:
1. You don't need quotes in variable assignments like
var="$(...)"
var="$var1"
2. The following tests are the same. They both tests if var is empty.
[ "$var"x = x ]
[ -z "$var" ]
3. Testing if command succeeded or failed can be done in-line.
if command1 | command2 | command2; then
...
else
...
fi
4. Case statement is usually better than if statement. eg.
if [[ "$var" == glob ]]; then
...
fi
vs
case $var in
glob) ... ;;
esac
Note the missing quotes in case, too. You don't need it.
--
William Park <opengeometry at yahoo.ca>
More information about the talk
mailing list