
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@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@yahoo.ca>