Skip to content

Commit 5eee672

Browse files
committed
Outsourcing of certificate date properties determination
determine_dates_certificate() is now determining the important dates of a certificate passed via argument. It works of course for host and any other certificates. Returning multiple parameters is being done via CSV and passed to a read statement which seemed the best choice for bash. ToDo: * $expok is not set properly for intermediate certificates * check if expired at least in the UI (JSON+CSV: echo the dates so far) * for multiple host certificates the naming scheme (jsonID + intermediate certnumnber kind of sucks: "id" : "intermediate_cert_fingerprintSHA256 <cert#1> 1", "id" : "intermediate_cert_notAfter <cert#2> 1", The whole thing is kind of hackish as the code has been historically grown. At some certian point we may want to reconsider how we determine properties of certificates in certificate_info()
1 parent b625df8 commit 5eee672

1 file changed

Lines changed: 74 additions & 45 deletions

File tree

testssl.sh

Lines changed: 74 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -3567,7 +3567,7 @@ run_cipher_match(){
35673567
hexc="${TLS_CIPHER_HEXCODE[i]}"
35683568
if [[ ${#hexc} -eq 9 ]]; then
35693569
hexcode[nr_ciphers]="${hexc:2:2},${hexc:7:2}"
3570-
if [[ "${hexc:2:2}" == "00" ]]; then
3570+
if [[ "${hexc:2:2}" == 00 ]]; then
35713571
normalized_hexcode[nr_ciphers]="x${hexc:7:2}"
35723572
else
35733573
normalized_hexcode[nr_ciphers]="x${hexc:2:2}${hexc:7:2}"
@@ -8321,18 +8321,73 @@ certificate_transparency() {
83218321
# and $OPENSSL x509 -noout -in $HOSTCERT -fingerprint -sha256/-sha1
83228322
#
83238323
determine_cert_fingerprint_serial() {
8324-
local cert="$1"
8324+
local cert_file="$1"
83258325
local ossl_command="$2"
83268326
local result=""
83278327

8328-
result="$($OPENSSL x509 -noout -in $1 $2 2>>$ERRFILE)"
8328+
if [[ -r "$cert_file" ]]; then
8329+
result="$($OPENSSL x509 -noout -in $cert_file $ossl_command 2>>$ERRFILE)"
8330+
else
8331+
# not really a file but the variable which holds the certificate
8332+
result="$($OPENSSL x509 -noout $ossl_command 2>>$ERRFILE <<< "$cert_file")"
8333+
fi
83298334
# remove strings in text output, colon only appear in fingerprints
83308335
result="${result//Fingerprint=}"
83318336
result="${result//serial=}"
83328337
result="${result//:/}"
83338338
safe_echo "$result"
83348339
}
83358340

8341+
# Returns startdate, enddate, diffseconds, days2expire as CSVs as strings
8342+
# arg1: human readable text string for certificate (openssl x509 -text -noout)
8343+
#
8344+
determine_dates_certificate () {
8345+
local cert_txt="$1"
8346+
local startdate enddate yearnow y m d yearstart clockstart yearend clockend
8347+
local diffseconds=0 days2expire=0
8348+
8349+
startdate="${cert_txt#*Validity*Not Before: }"
8350+
# FreeBSD + OSX can't swallow the leading blank:
8351+
startdate="${startdate%%GMT*}GMT"
8352+
enddate="${cert_txt#*Validity*Not Before: *Not After : }"
8353+
enddate="${enddate%%GMT*}GMT"
8354+
debugme echo "$enddate - $startdate"
8355+
# Now we have a normalized enddate and startdate like "Feb 27 10:03:20 2017 GMT" -- also for OpenBSD
8356+
if "$HAS_OPENBSDDATE"; then
8357+
# Best we want to do under old versions of OpenBSD, first just remove the GMT and keep start/endate for later output
8358+
startdate="$(parse_date "$startdate" "+%s")"
8359+
enddate="$(parse_date "$enddate" "+%s")"
8360+
# Now we extract a date block and a time block which we need for later output
8361+
startdate="$(parse_date "$startdate" +"%F %H:%M" "%b %d %T %Y %Z")"
8362+
enddate="$(parse_date "$enddate" +"%F %H:%M" "%b %d %T %Y %Z")"
8363+
read yearstart clockstart <<< "$startdate"
8364+
read yearend clockend <<< "$enddate"
8365+
debugme echo "$yearstart, $clockstart"
8366+
debugme echo "$yearend, $clockend"
8367+
y=$(( ${yearend:0:4} - ${yearstart:0:4} ))
8368+
m=$(( ${yearend:5:1} - ${yearstart:5:1} + ${yearend:6:1} - ${yearstart:6:1} ))
8369+
d=$(( ${yearend:8:2} - ${yearstart:8:2} ))
8370+
# We take the year, month, days here as old OpenBSD's date is too difficult for real conversion
8371+
# see comment in parse_date(). In diffseconds then we have the estimated absolute validity period
8372+
diffseconds=$(( d + ((m*30)) + ((y*365)) ))
8373+
diffseconds=$((diffseconds * 3600 * 24))
8374+
# Now we estimate the days left plus length of month/year:
8375+
yearnow="$(date -juz GMT "+%Y-%m-%d %H:%M")"
8376+
y=$(( ${yearend:0:4} - ${yearnow:0:4} ))
8377+
m=$(( ${yearend:5:1} - ${yearnow:5:1} + ${yearend:6:1} - ${yearnow:6:1} ))
8378+
d=$(( ${yearend:8:2} - ${yearnow:8:2} ))
8379+
days2expire=$(( d + ((m*30)) + ((y*365)) ))
8380+
else
8381+
startdate="$(parse_date "$startdate" +"%F %H:%M" "%b %d %T %Y %Z")"
8382+
enddate="$(parse_date "$enddate" +"%F %H:%M" "%b %d %T %Y %Z")"
8383+
days2expire=$(( $(parse_date "$enddate" "+%s" $'%F %H:%M') - $(LC_ALL=C date "+%s") )) # first in seconds
8384+
days2expire=$((days2expire / 3600 / 24 ))
8385+
diffseconds=$(( $(parse_date "$enddate" "+%s" $'%F %H:%M') - $(parse_date "$startdate" "+%s" $'%F %H:%M') ))
8386+
fi
8387+
safe_echo "$startdate, $enddate, $diffseconds, $days2expire, $yearstart"
8388+
}
8389+
8390+
83368391

83378392
certificate_info() {
83388393
local proto
@@ -8378,7 +8433,7 @@ certificate_info() {
83788433
local provides_stapling=false
83798434
local caa_node="" all_caa="" caa_property_name="" caa_property_value=""
83808435
local response=""
8381-
local yearstart yearend clockstart clockend y m d
8436+
local yearstart
83828437
local gt_398=false gt_398warn=false
83838438
local gt_825=false gt_825warn=false
83848439
local badocsp=1
@@ -8735,7 +8790,7 @@ certificate_info() {
87358790
CERT_FINGERPRINT_SHA2="$cert_fingerprint_sha2" ||
87368791
CERT_FINGERPRINT_SHA2="$cert_fingerprint_sha2 $CERT_FINGERPRINT_SHA2"
87378792
[[ -z $RSA_CERT_FINGERPRINT_SHA2 ]] && \
8738-
( [[ $cert_key_algo = *RSA* ]] || [[ $cert_key_algo = *rsa* ]] ) &&
8793+
( [[ $cert_key_algo =~ RSA ]] || [[ $cert_key_algo =~ rsa ]] ) &&
87398794
RSA_CERT_FINGERPRINT_SHA2="$cert_fingerprint_sha2"
87408795

87418796
out "$indent"; pr_bold " Common Name (CN) "
@@ -8812,7 +8867,7 @@ certificate_info() {
88128867
out "$indent"; pr_bold " Issuer "
88138868
jsonID="cert_caIssuers"
88148869
#FIXME: oid would be better maybe (see above)
8815-
issuer="$($OPENSSL x509 -in $HOSTCERT -noout -issuer -nameopt multiline,-align,sname,-esc_msb,utf8,-space_eq 2>>$ERRFILE)"
8870+
issuer="$($OPENSSL x509 -in $HOSTCERT -noout -issuer -nameopt multiline,-align,sname,-esc_msb,utf8,-space_eq 2>>$ERRFILE)"
88168871
issuer_CN="$(awk -F'=' '/CN=/ { print $2 }' <<< "$issuer")"
88178872
issuer_O="$(awk -F'=' '/O=/ { print $2 }' <<< "$issuer")"
88188873
issuer_C="$(awk -F'=' '/ C=/ { print $2 }' <<< "$issuer")"
@@ -9019,9 +9074,19 @@ certificate_info() {
90199074
cert="${intermediates%%-----END CERTIFICATE-----*}"
90209075
intermediates="${intermediates#${cert}-----END CERTIFICATE-----}"
90219076
cert="-----BEGIN CERTIFICATE-----${cert}-----END CERTIFICATE-----"
9077+
90229078
# we count as humans in the file output here. This needs later to be adjusted in the code
9023-
fileout "intermediate_cert $((certificates_provided + 1 ))" "INFO" "$cert"
9079+
fileout "intermediate_cert${json_postfix} $((certificates_provided + 1 ))" "INFO" "$cert"
9080+
9081+
fileout "intermediate_cert_fingerprintSHA256${json_postfix} $((certificates_provided + 1 ))" "INFO" "$(determine_cert_fingerprint_serial "$cert" "-fingerprint -sha256")"
9082+
90249083
intermediate_certs_txt[certificates_provided]="$($OPENSSL x509 -text -noout 2>/dev/null <<< "$cert")"
9084+
9085+
# We don't need every value here. For the sake of consistency we add the rest
9086+
IFS=',' read -r startdate enddate diffseconds days2expire yearstart < <(determine_dates_certificate "${intermediate_certs_txt[certificates_provided]}")
9087+
fileout "intermediate_cert_notBefore${json_postfix} $((certificates_provided + 1))" "INFO" "$startdate"
9088+
expok="OK" #FIXME!
9089+
fileout "intermediate_cert_notAfter${json_postfix} $((certificates_provided + 1))" "$expok" "$enddate"
90259090
certificates_provided+=1
90269091
done
90279092

@@ -9054,44 +9119,8 @@ certificate_info() {
90549119
# For now we leave this here. We may want to change that later or add infos to other sections (FS & vulnerability)
90559120

90569121
out "$indent"; pr_bold " Certificate Validity (UTC) "
9057-
# FreeBSD + OSX can't swallow the leading blank:
9058-
startdate="${cert_txt#*Validity*Not Before: }"
9059-
startdate="${startdate%%GMT*}GMT"
9060-
enddate="${cert_txt#*Validity*Not Before: *Not After : }"
9061-
enddate="${enddate%%GMT*}GMT"
9062-
debugme echo "$enddate - $startdate"
9063-
# Now we have a normalized enddate and startdate like "Feb 27 10:03:20 2017 GMT" -- also for OpenBSD
9064-
if "$HAS_OPENBSDDATE"; then
9065-
# Best we want to do under old versions of OpenBSD, first just remove the GMT and keep start/endate for later output
9066-
startdate="$(parse_date "$startdate" "+%s")"
9067-
enddate="$(parse_date "$enddate" "+%s")"
9068-
# Now we extract a date block and a time block which we need for later output
9069-
startdate="$(parse_date "$startdate" +"%F %H:%M" "%b %d %T %Y %Z")"
9070-
enddate="$(parse_date "$enddate" +"%F %H:%M" "%b %d %T %Y %Z")"
9071-
read yearstart clockstart <<< "$startdate"
9072-
read yearend clockend <<< "$enddate"
9073-
debugme echo "$yearstart, $clockstart"
9074-
debugme echo "$yearend, $clockend"
9075-
y=$(( ${yearend:0:4} - ${yearstart:0:4} ))
9076-
m=$(( ${yearend:5:1} - ${yearstart:5:1} + ${yearend:6:1} - ${yearstart:6:1} ))
9077-
d=$(( ${yearend:8:2} - ${yearstart:8:2} ))
9078-
# We take the year, month, days here as old OpenBSD's date is too difficult for real conversion
9079-
# see comment in parse_date(). In diffseconds then we have the estimated absolute validity period
9080-
diffseconds=$(( d + ((m*30)) + ((y*365)) ))
9081-
diffseconds=$((diffseconds * 3600 * 24))
9082-
# Now we estimate the days left plus length of month/year:
9083-
yearnow="$(date -juz GMT "+%Y-%m-%d %H:%M")"
9084-
y=$(( ${yearend:0:4} - ${yearnow:0:4} ))
9085-
m=$(( ${yearend:5:1} - ${yearnow:5:1} + ${yearend:6:1} - ${yearnow:6:1} ))
9086-
d=$(( ${yearend:8:2} - ${yearnow:8:2} ))
9087-
days2expire=$(( d + ((m*30)) + ((y*365)) ))
9088-
else
9089-
startdate="$(parse_date "$startdate" +"%F %H:%M" "%b %d %T %Y %Z")"
9090-
enddate="$(parse_date "$enddate" +"%F %H:%M" "%b %d %T %Y %Z")"
9091-
days2expire=$(( $(parse_date "$enddate" "+%s" $'%F %H:%M') - $(LC_ALL=C date "+%s") )) # first in seconds
9092-
days2expire=$((days2expire / 3600 / 24 ))
9093-
diffseconds=$(( $(parse_date "$enddate" "+%s" $'%F %H:%M') - $(parse_date "$startdate" "+%s" $'%F %H:%M') ))
9094-
fi
9122+
IFS=',' read -r startdate enddate diffseconds days2expire yearstart < <(determine_dates_certificate "$cert_txt")
9123+
90959124
# We adjust the thresholds by %50 for LE certificates, relaxing warnings for those certificates.
90969125
# . instead of \' because it does not break syntax highlighting in vim
90979126
if [[ "$issuer_CN" =~ ^Let.s\ Encrypt\ Authority ]] ; then

0 commit comments

Comments
 (0)