Skip to content

Commit d5a64ff

Browse files
committed
Further improvements to intermediate certs
* reorder sequence of checks in certificate info so that the chain relevant points are closer together * determine_cert_fingerprint_serial() doesn't need fil input anymore, thus removed that part * cert_validityPeriod in JSON/CSV may lead to misunderstandings, thus renamed to cert_extlifeSpan * reorganized loop for the intermediate certificate checks, so that also i is used and not the variable which defines the number of certificates, i.e. certificates_provided. In addition made the counting more hiuma friendly, which starts now at 1 instead of 0
1 parent a7bcf9e commit d5a64ff

1 file changed

Lines changed: 44 additions & 55 deletions

File tree

testssl.sh

Lines changed: 44 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -8320,16 +8320,11 @@ certificate_transparency() {
83208320
# and $OPENSSL x509 -noout -in $HOSTCERT -fingerprint -sha256/-sha1
83218321
#
83228322
determine_cert_fingerprint_serial() {
8323-
local cert_file="$1"
8323+
local cert="$1"
83248324
local ossl_command="$2"
83258325
local result=""
83268326

8327-
if [[ -r "$cert_file" ]]; then
8328-
result="$($OPENSSL x509 -noout -in $cert_file $ossl_command 2>>$ERRFILE)"
8329-
else
8330-
# not really a file but the variable which holds the certificate
8331-
result="$($OPENSSL x509 -noout $ossl_command 2>>$ERRFILE <<< "$cert_file")"
8332-
fi
8327+
result="$($OPENSSL x509 -noout $ossl_command 2>>$ERRFILE <<< "$cert")"
83338328
# remove strings in text output, colon only appear in fingerprints
83348329
result="${result//Fingerprint=}"
83358330
result="${result//serial=}"
@@ -9067,14 +9062,6 @@ certificate_info() {
90679062
# https://certs.opera.com/03/ev-oids.xml
90689063
# see #967
90699064

9070-
out "$indent"; pr_bold " ETS/\"eTLS\""
9071-
out ", visibility info "
9072-
jsonID="cert_eTLS"
9073-
etsi_ets_visibility_info "${jsonID}${json_postfix}" "$spaces" "$hostcert" "$cert_txt"
9074-
# *Currently* this is even listed as a vulnerability (CWE-310, CVE-2019-919), see
9075-
# https://nvd.nist.gov/vuln/detail/CVE-2019-9191, https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-9191
9076-
# For now we leave this here. We may want to change that later or add infos to other sections (FS & vulnerability)
9077-
90789065
out "$indent"; pr_bold " Certificate Validity (UTC) "
90799066
IFS=',' read -r startdate enddate diffseconds days2expire yearstart < <(determine_dates_certificate "$cert_txt")
90809067

@@ -9119,11 +9106,11 @@ certificate_info() {
91199106
if [[ $diffseconds -ge $((secsaday*365*10)) ]]; then
91209107
out "$spaces"
91219108
prln_svrty_high ">= 10 years is way too long"
9122-
fileout "cert_validityPeriod${json_postfix}" "HIGH" "$((diffseconds / secsaday)) days"
9109+
fileout "cert_extlifeSpan${json_postfix}" "HIGH" "$((diffseconds / secsaday)) days"
91239110
elif [[ $diffseconds -ge $((secsaday*365*5)) ]]; then
91249111
out "$spaces"
91259112
prln_svrty_medium ">= 5 years is too long"
9126-
fileout "cert_validityPeriod${json_postfix}" "MEDIUM" "$((diffseconds / secsaday)) days"
9113+
fileout "cert_extlifeSpan${json_postfix}" "MEDIUM" "$((diffseconds / secsaday)) days"
91279114
elif [[ $diffseconds -ge $((secsaday*398 + 1)) ]]; then
91289115
# Also "official" certificates issued from september 1st 2020 (1598918400) aren't supposed
91299116
# to be valid longer than 398 days which is 34387200 in epoch seconds
@@ -9139,10 +9126,10 @@ certificate_info() {
91399126
out "$spaces"
91409127
if "$gt_398warn" && "$gt_398"; then
91419128
prln_svrty_medium "> 398 days issued after 2020/09/01 is too long"
9142-
fileout "cert_validityPeriod${json_postfix}" "MEDIUM" "$((diffseconds / secsaday)) > 398 days"
9129+
fileout "cert_extlifeSpan${json_postfix}" "MEDIUM" "$((diffseconds / secsaday)) > 398 days"
91439130
elif "$gt_398"; then
91449131
outln ">= 398 days certificate life time but issued before 2020/09/01"
9145-
fileout "cert_validityPeriod${json_postfix}" "INFO" "$((diffseconds / secsaday)) =< 398 days"
9132+
fileout "cert_extlifeSpan${json_postfix}" "INFO" "$((diffseconds / secsaday)) =< 398 days"
91469133
fi
91479134
elif [[ $diffseconds -ge $((secsaday*825 + 1)) ]]; then
91489135
# Also "official" certificates issued from March 1st, 2018 (1517353200) aren't supposed
@@ -9159,30 +9146,25 @@ certificate_info() {
91599146
out "$spaces"
91609147
if "$gt_825warn" && "$gt_825"; then
91619148
prln_svrty_medium "> 825 days issued after 2018/03/01 is too long"
9162-
fileout "cert_validityPeriod${json_postfix}" "MEDIUM" "$((diffseconds / secsaday)) > 825 days"
9149+
fileout "cert_extlifeSpan${json_postfix}" "MEDIUM" "$((diffseconds / secsaday)) > 825 days"
91639150
elif "$gt_825"; then
91649151
outln ">= 825 days certificate life time but issued before 2018/03/01"
9165-
fileout "cert_validityPeriod${json_postfix}" "INFO" "$((diffseconds / secsaday)) =< 825 days"
9152+
fileout "cert_extlifeSpan${json_postfix}" "INFO" "$((diffseconds / secsaday)) =< 825 days"
91669153
fi
91679154
else
9168-
# All is fine with valididy period
9155+
# All is fine with validity period
91699156
# We ignore for now certificates < 2018/03/01. On the screen we only show debug info
9170-
[[ "$DEBUG" -ge 1 ]] && outln "${spaces}DEBUG: all is fine with total certificate life time"
9171-
fileout "cert_validityPeriod${json_postfix}" "INFO" "No finding"
9157+
debugme1 outln "${spaces}DEBUG: all is fine with total certificate life time"
9158+
fileout "cert_extlifeSpan${json_postfix}" "OK" "certificate has no extended life time according to browser forum"
91729159
fi
91739160

9174-
out "$indent"; pr_bold " Certificates provided"
9175-
certificates_provided="$(grep -ac '\-\-\-\-\-BEGIN\ CERTIFICATE\-\-\-\-\-' <<< "$intermediates")"
9176-
((certificates_provided++)) # plus host certificate
9177-
out " $certificates_provided"
9178-
fileout "certs_countServer${json_postfix}" "INFO" "${certificates_provided}"
9179-
if "$certificate_list_ordering_problem"; then
9180-
prln_svrty_low " (certificate list ordering problem)"
9181-
fileout "certs_list_ordering_problem${json_postfix}" "LOW" "yes"
9182-
else
9183-
fileout "certs_list_ordering_problem${json_postfix}" "INFO" "no"
9184-
outln
9185-
fi
9161+
out "$indent"; pr_bold " ETS/\"eTLS\""
9162+
out ", visibility info "
9163+
jsonID="cert_eTLS"
9164+
etsi_ets_visibility_info "${jsonID}${json_postfix}" "$spaces" "$hostcert" "$cert_txt"
9165+
# *Currently* this is even listed as a vulnerability (CWE-310, CVE-2019-919), see
9166+
# https://nvd.nist.gov/vuln/detail/CVE-2019-9191, https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-9191
9167+
# For now we leave this here. We may want to change that later or add infos to other sections (FS & vulnerability)
91869168

91879169
if "$PHONE_OUT"; then
91889170
out "$indent"; pr_bold " In pwnedkeys.com DB "
@@ -9349,40 +9331,50 @@ certificate_info() {
93499331
fileout "${jsonID}${json_postfix}" "INFO" "$ct"
93509332
fi
93519333

9334+
out "$indent"; pr_bold " Certificates provided"
9335+
certificates_provided="$(grep -ac '\-\-\-\-\-BEGIN\ CERTIFICATE\-\-\-\-\-' <<< "$intermediates")"
9336+
((certificates_provided++)) # plus host certificate
9337+
out " $certificates_provided"
9338+
fileout "certs_countServer${json_postfix}" "INFO" "${certificates_provided}"
9339+
if "$certificate_list_ordering_problem"; then
9340+
prln_svrty_low " (certificate list ordering problem)"
9341+
fileout "certs_list_ordering_problem${json_postfix}" "LOW" "yes"
9342+
else
9343+
fileout "certs_list_ordering_problem${json_postfix}" "INFO" "no"
9344+
outln
9345+
fi
9346+
93529347
# Now we take care of the intermediate certificates. We basically (should) have them on disk
93539348
# as "intermediatecerts.pem" (which could be split into intermediatecert1.crt, intermediatecert2.crt, ..)
93549349
# However we do this in RAM which is better as it was passed to this function.
93559350
# We should keep in mind though this is somewhat redundant code. We do similar stuff elsewhere,
93569351
# e.g. in extract_certificates() and run_hpkp() but don't keep the certificates
93579352

9358-
#FIXME: the numbering scheme of certificates_provided below: we start @ 0 and always add 1. Careful with Intermediate Bad OCSP
9359-
93609353
# Store all of the text output of the intermediate certificates in an array so that they can
93619354
# be used later (e.g., to check their expiration dates).
9362-
certificates_provided=0
9363-
while true; do
9355+
for (( i=1; i < certificates_provided; i++ )); do
93649356
[[ "$intermediates" =~ \-\-\-\-\-BEGIN\ CERTIFICATE\-\-\-\-\- ]] || break
93659357
intermediates="${intermediates#*-----BEGIN CERTIFICATE-----}"
93669358
cert="${intermediates%%-----END CERTIFICATE-----*}"
93679359
intermediates="${intermediates#${cert}-----END CERTIFICATE-----}"
93689360
cert="-----BEGIN CERTIFICATE-----${cert}-----END CERTIFICATE-----"
93699361

9370-
fileout "intermediate_cert <#$((certificates_provided + 1))>${json_postfix}" "INFO" "$cert"
9371-
fileout "intermediate_cert_fingerprintSHA256 <#$((certificates_provided + 1))>${json_postfix}" "INFO" "$(determine_cert_fingerprint_serial "$cert" "-fingerprint -sha256")"
9362+
fileout "intermediate_cert <#${i}>${json_postfix}" "INFO" "$cert"
9363+
fileout "intermediate_cert_fingerprintSHA256 <#${i}>${json_postfix}" "INFO" "$(determine_cert_fingerprint_serial "$cert" "-fingerprint -sha256")"
93729364

9373-
intermediate_certs_txt[certificates_provided]="$($OPENSSL x509 -text -noout 2>/dev/null <<< "$cert")"
9365+
intermediate_certs_txt[i]="$($OPENSSL x509 -text -noout 2>/dev/null <<< "$cert")"
93749366

93759367
# We don't need every value here. For the sake of being consistent here we add the rest
9376-
IFS=',' read -r startdate enddate diffseconds days2expire yearstart < <(determine_dates_certificate "${intermediate_certs_txt[certificates_provided]}")
9377-
fileout "intermediate_cert_notBefore <#$((certificates_provided + 1))>${json_postfix}" "INFO" "$startdate"
9368+
IFS=',' read -r startdate enddate diffseconds days2expire yearstart < <(determine_dates_certificate "${intermediate_certs_txt[i]}")
9369+
fileout "intermediate_cert_notBefore <#${i}>${json_postfix}" "INFO" "$startdate"
93789370

93799371
if $first; then
93809372
out "$indent"; pr_bold " Intermediate cert validity "
93819373
first=false
93829374
else
93839375
out "$indent$spaces"
93849376
fi
9385-
out "#$((certificates_provided+1)): "
9377+
out "#${i}: "
93869378
if ! [[ "$($OPENSSL x509 -checkend 1 2>>$ERRFILE <<< "$cert")" =~ \ not\ ]]; then
93879379
cn_finding="expired!"
93889380
pr_svrty_critical "$cn_finding"
@@ -9401,13 +9393,12 @@ certificate_info() {
94019393
expok="OK"
94029394
fi
94039395
out " ($enddate). "
9404-
cn="$(awk -F= '/Subject:.*CN/ { print $NF }' <<< "${intermediate_certs_txt[certificates_provided]}")"
9405-
issuer_CN="$(awk -F= '/Issuer:.*CN/ { print $NF }' <<< "${intermediate_certs_txt[certificates_provided]}")"
9396+
cn="$(awk -F= '/Subject:.*CN/ { print $NF }' <<< "${intermediate_certs_txt[i]}")"
9397+
issuer_CN="$(awk -F= '/Issuer:.*CN/ { print $NF }' <<< "${intermediate_certs_txt[i]}")"
94069398
pr_italic "$cn"; out " <-- "; prln_italic "$issuer_CN"
9407-
fileout "intermediate_cert_notAfter <#$((certificates_provided + 1))>${json_postfix}" "$expok" "$enddate"
9408-
fileout "intermediate_cert_expiration <#$((certificates_provided + 1))>${json_postfix}" "$expok" "$cn_finding"
9409-
fileout "intermediate_cert_chain <#$((certificates_provided + 1))>${json_postfix}" "INFO" "$cn <-- $issuer_CN"
9410-
certificates_provided+=1
9399+
fileout "intermediate_cert_notAfter <#${i}>${json_postfix}" "$expok" "$enddate"
9400+
fileout "intermediate_cert_expiration <#${i}>${json_postfix}" "$expok" "$cn_finding"
9401+
fileout "intermediate_cert_chain <#${i}>${json_postfix}" "INFO" "$cn <-- $issuer_CN"
94119402
done
94129403

94139404
# Courtesy Hanno Böck (see https://github.com/hannob/badocspcert)
@@ -9419,11 +9410,9 @@ certificate_info() {
94199410
cert_ext_keyusage="$(awk '/X509v3 Extended Key Usage:/ { getline; print $0 }' <<< "${intermediate_certs_txt[i]}")"
94209411
[[ "$cert_ext_keyusage" =~ OCSP\ Signing ]] && badocsp=0 && break
94219412
done
9422-
9423-
#FIXME: We only raise the flag saying the chain is bad w/o naming the intermediate cert to blame.
94249413
if [[ $badocsp -eq 0 ]]; then
94259414
prln_svrty_medium "NOT ok"
9426-
fileout "${jsonID}${json_postfix}" "MEDIUM" "NOT ok is/are intermediate certificate(s)"
9415+
fileout "${jsonID}${json_postfix}" "MEDIUM" "NOT ok is intermediate certificate ${i}"
94279416
else
94289417
prln_svrty_good "Ok"
94299418
fileout "${jsonID}${json_postfix}" "OK" "intermediate certificate(s) is/are ok"

0 commit comments

Comments
 (0)