#!/usr/bin/env bash
#
# check X.509 cert for a domain:port with openssl, for correspondance and expiration
# + by default the port is 443
# + there is a timeout of 6 sec and is there is no connectivity the check is skipped
#
# requirements: sudo apt install openssl

# GENERAL ###########################################################

# locale env
unset LC_ALL
export LC_MESSAGES=C

# check if module was disabled
module_disable=${module_tls_disable:=0}
if (($module_disable == 1)); then
    exit 1
fi

# colors
c_txt=${c_txt:="39"}
c_txt_emphase=${c_txt_emphase:="35"}
c_txt_deco=${c_txt_deco:="97"}
c_txt_invert=${c_txt_invert:="30"}
c_bg=${c_bg_sec:="47"}
c_danger=${c_danger:="31"}
c_warning=${c_warning:="33"}
c_success=${c_success:="32"}
c_title=${c_title:="${c_bg};1;${c_txt_invert}m"}

# api website name for plain public IP4/6 check
publicip_api=${global_publicip_api:="icanhazip.com"}

# OPTIONS ###########################################################

# domains:ports input
if [[ $module_tls_domains ]]
then
    tls_domains=(${module_tls_domains[@]})
else
    tls_domains=("www.google.com" "smtp.gmail.com:465")
fi
IFS=$'\n' tls_domains=($(sort <<<"${tls_domains[*]}"))
unset IFS

# PREPARATIONS ######################################################

# print loading message
echo -e "\nWaiting for TLS checks\e[5m...\e[0m"

# parse output
output="    \e[1;4;${c_txt}mDomain\e[24m|\e[4mPort\e[24m|\e[4mValid until\e[0m"
currentTime=$(date +%s)

# check if there is internet connectivity
INTERNET_OUT=0
PUBLICIP="$(timeout 6 curl -s $publicip_api 2>/dev/null)"
if [[ ! $PUBLICIP ]]; then
    INTERNET_OUT=1
fi

# OUTPUT ############################################################

for domain in "${tls_domains[@]}"
do
    if [[ $domain == *:* ]]
    then
        port=${domain/*:/}
        domain=${domain/:*/}
    else
        port="443"
    fi
    if [[ $INTERNET_OUT == 0 ]]; then
        # fetch cert
        cert=""
        cert=$(timeout 6 openssl s_client -servername ${domain} -connect ${domain}:${port} < /dev/null 2>/dev/null)
        # fetch subject name with a 3 sec timeout
        certSubj=$(echo -e "$cert" | openssl x509 -noout -subject 2>/dev/null)
        # fetch expiration time
        certTime=$(echo -e "$cert" | openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2)
        certLineTime=$(date -d "${certTime}" +"%F")
        certTimestamp=$(date -d "${certTime}" +%s)
        port="\e[${c_txt}m${port}\e[0m"
        # check subject name with a 3 sec timeout
        if [[ $certSubj == *${domain} ]]
        then
            domain="\e[${c_txt}m${domain}\e[0m"
            # check expiration time - 3 days
            if [[ "$((${certTimestamp} - 259200 ))" -ge "${currentTime}" ]]
            then
                sign="\e[${c_success}m●\e[0m"
                result="\e[1;${c_success}m$certLineTime\e[0m"
            # check expiration time today
            elif [[ "${certTimestamp}" -ge "${currentTime}" ]]
            then
                sign="\e[1;${c_warning}m▲\e[0m"
                result="\e[1;${c_warning}m${certLineTime}\e[0m"
            else
                sign="\e[1;5;${c_danger}m▲\e[0m"
                result="\e[1;${c_danger}m$certLineTime\e[0m"
            fi
        else
            domain="\e[${c_txt}m${domain}\e[0m"
            sign="\e[1;2;${c_warning}m\U25B2\e[0m"
            result="\e[1;2;${c_warning}mtimeout or misnamed\e[0m"
        fi
    elif [[ $INTERNET_OUT == 1 ]]; then
        domain="\e[${c_txt}m${domain}\e[0m"
        sign="\e[1;2;${c_txt}m▲\e[0m"
        result="\e[1;2;${c_txt}mno internet, skipped\e[0m"
    fi
    output+="\n  ${sign} ${domain}|${port}|$result"
done

# output header and table content
echo -e "\e[1A\e[${c_title} TLS checks  \e[0m                    "
echo -e 
echo -e "$output" | column -t -s '|'