Merge pull request #1427 from drwetter/825_days

Check for certificates with a life time >825 days when issued after 2018/03/01
This commit is contained in:
Dirk Wetter 2020-01-08 14:31:19 +01:00 committed by GitHub
commit 256d4d32ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 85 additions and 34 deletions

View File

@ -4,9 +4,11 @@
### Features implemented in 3.0
* Full support of TLS 1.3, shows also drafts supported
* Extended protocol downgrade checks
* ROBOT check
* Better TLS extension support
* Better OpenSSL 1.1.1 and higher versions support
* Better OpenSSL 1.1.1 and higher versions support as well as LibreSSL >3
* More robustness for OpenBSD
* DNS over Proxy and other proxy improvements
* Decoding of unencrypted BIG IP cookies
* Initial client certificate support
@ -27,7 +29,7 @@
* TLS Robustness check (GREASE)
* Server preference distinguishes between TLS 1.3 and lower protocols
* Mark TLS 1.0 and TLS 1.1 as deprecated
* Does a few startup checks which make later tests easier and faster (determine_optimal_\*() )
* Does a few startup checks which make later tests easier and faster (``determine_optimal_\*()``)
* Expect-CT Header Detection
* `--phone-out` does certificate revocation checks via OCSP (LDAP+HTTP) and with CRL
* `--phone-out` checks whether the private key has been compromised via https://pwnedkeys.com/

View File

@ -64,7 +64,7 @@ $html =~ s/HTTP clock skew \+?-?[0-9]* /HTTP clock skew
$debughtml =~ s/HTTP clock skew \+?-?[0-9]* /HTTP clock skew X /;
$debughtml =~ s/ Pre-test: .*\n//g;
$debughtml =~ s/.*OK: below 5 years.*\n//g;
$debughtml =~ s/.*OK: below 825 days.*\n//g;
printf "\n%s\n", "Checking that using the --debug option doesn't affect the HTML file";
cmp_ok($debughtml, "eq", $html, "HTML file created with --debug 4 matches HTML file created without --debug");

View File

@ -150,7 +150,7 @@ declare -r -a CMDLINE_ARRAY=("$@") # When performing mass testing
declare -a MASS_TESTING_CMDLINE # command line in the form of an array (see #702 and http://mywiki.wooledge.org/BashFAQ/050).
########### Some predefinitions: date, sed (we always use test and not try to determine
########### Some predefinitions: date, sed (we always use test and NOT try to determine
# capabilities by querying the OS)
#
HAS_GNUDATE=false
@ -158,13 +158,14 @@ HAS_FREEBSDDATE=false
HAS_OPENBSDDATE=false
if date -d @735275209 >/dev/null 2>&1; then
if date -r @735275209 >/dev/null 2>&1; then
# it can't do any conversion from a plain date output
# It can't do any conversion from a plain date output.
HAS_OPENBSDDATE=true
else
HAS_GNUDATE=true
fi
fi
# FreeBSD and OS X date(1) accept "-f inputformat"
# so newer OpenBSD versions >~ 6.6.
date -j -f '%s' 1234567 >/dev/null 2>&1 && \
HAS_FREEBSDDATE=true
@ -1873,18 +1874,27 @@ wait_kill(){
}
# parse_date date format input-format
if "$HAS_GNUDATE"; then # Linux and NetBSD
if "$HAS_GNUDATE"; then # Linux and NetBSD
parse_date() {
LC_ALL=C date -d "$1" "$2"
}
elif "$HAS_FREEBSDDATE"; then # FreeBSD and OS X
elif "$HAS_FREEBSDDATE"; then # FreeBSD, OS X and newer (~6.6) OpenBSD versions
parse_date() {
LC_ALL=C date -j -f "$3" "$2" "$1"
}
elif "$HAS_OPENBSDDATE"; then
# We bascially echo it as a conversion as we want it is too difficult. Approach for that would be:
# printf '%s\n' "$1" | awk '{ printf "%04d%02d%02d\n", $4, $2, (index("JanFebMarAprMayJunJulAugSepOctNovDec",$1)+2)/3}'
# 4: year, 1: month, 2: day, $3: time (e.g. "Dec 8 10:16:13 2016")
# This way we could also kind of convert args to epoch but as newer OpenBSDs "date" behave like FreeBSD
parse_date() {
# we just echo it as a conversion as we want it is not possible
echo "$1"
local tmp=""
if [[ $2 == +%s* ]]; then
echo "${1// GMT}"
else
tmp="$(printf '%s\n' "$1" | awk '{ printf "%04d-%02d-%02d %08s\n", $4, (index("JanFebMarAprMayJunJulAugSepOctNovDec",$1)+2)/3, $2, $3 }')"
echo "${tmp%:*}" # remove seconds, result now is in line with GNU date 2016-12-08 10:16
fi
}
else
parse_date() {
@ -8119,7 +8129,8 @@ certificate_info() {
local provides_stapling=false
local caa_node="" all_caa="" caa_property_name="" caa_property_value=""
local response=""
local a b c yearstart yearend
local yearstart yearend clockstart clockend y m d
local gt_825=false gt_825warn=false
if [[ $number_of_certificates -gt 1 ]]; then
[[ $certificate_number -eq 1 ]] && outln
@ -8674,37 +8685,51 @@ certificate_info() {
# For now we leave this here. We may want to change that later or add infos to other sections (PFS & vulnerability)
out "$indent"; pr_bold " Certificate Validity (UTC) "
# FreeBSD + OSX can't swallow the leading blank:
enddate="${cert_txt#*Validity*Not Before: *Not After : }"
enddate="${enddate%%GMT*}GMT"
startdate="${cert_txt#*Validity*Not Before: }"
startdate="${startdate%%GMT*}GMT"
# Now we have a normalized enddate and startdate like "Feb 27 10:03:20 2017 GMT" -- also for OpenBSD
enddate="${cert_txt#*Validity*Not Before: *Not After : }"
enddate="${enddate%%GMT*}GMT"
debugme echo "$enddate - $startdate"
# In all OS except OpenBSD it'll be reduced to "2017-02-27 11:03"
enddate="$(parse_date "$enddate" +"%F %H:%M" "%b %d %T %Y %Z")"
startdate="$(parse_date "$startdate" +"%F %H:%M" "%b %d %T %Y %Z")"
# Now we have a normalized enddate and startdate like "Feb 27 10:03:20 2017 GMT" -- also for OpenBSD
if "$HAS_OPENBSDDATE"; then
# best we are able to do under OpenBSD
days2expire=""
read a b c yearstart tz <<< "$startdate"
read a b c yearend tz <<< "$enddate"
# we only take the year here as OpenBSD's date is not for conversion
diffseconds=$((yearend - yearstart))
diffseconds=$((diffseconds * 3600 * 24 * 365))
# Best we want to do under old versions of OpenBSD, first just remove the GMT and keep start/endate for later output
startdate="$(parse_date "$startdate" "+%s")"
enddate="$(parse_date "$enddate" "+%s")"
# Now we extract a date block and a time block which we need for later output
startdate="$(parse_date "$startdate" +"%F %H:%M" "%b %d %T %Y %Z")"
enddate="$(parse_date "$enddate" +"%F %H:%M" "%b %d %T %Y %Z")"
read yearstart clockstart <<< "$startdate"
read yearend clockend <<< "$enddate"
debugme echo "$yearstart, $clockstart"
debugme echo "$yearend, $clockend"
y=$(( ${yearend:0:4} - ${yearstart:0:4} ))
m=$(( ${yearend:5:1} - ${yearstart:5:1} + ${yearend:6:1} - ${yearstart:6:1} ))
d=$(( ${yearend:8:2} - ${yearstart:8:2} ))
# We take the year, month, days here as old OpenBSD's date is too difficult for real conversion
# see comment in parse_date(). In diffseconds then we have the estimated absolute validity period
diffseconds=$(( d + ((m*30)) + ((y*365)) ))
diffseconds=$((diffseconds * 3600 * 24))
# Now we estimate the days left plus length of month/year:
yearnow="$(date -juz GMT "+%Y-%m-%d %H:%M")"
y=$(( ${yearend:0:4} - ${yearnow:0:4} ))
m=$(( ${yearend:5:1} - ${yearnow:5:1} + ${yearend:6:1} - ${yearnow:6:1} ))
d=$(( ${yearend:8:2} - ${yearnow:8:2} ))
days2expire=$(( d + ((m*30)) + ((y*365)) ))
else
startdate="$(parse_date "$startdate" +"%F %H:%M" "%b %d %T %Y %Z")"
enddate="$(parse_date "$enddate" +"%F %H:%M" "%b %d %T %Y %Z")"
days2expire=$(( $(parse_date "$enddate" "+%s" $'%F %H:%M') - $(LC_ALL=C date "+%s") )) # first in seconds
days2expire=$((days2expire / 3600 / 24 ))
# we adjust the thresholds by %50 for LE certificates, relaxing those warnings
# . instead of \' because it does not break syntax highlighting in vim
if [[ "$issuer_CN" =~ ^Let.s\ Encrypt\ Authority ]] ; then
days2warn2=$((days2warn2 / 2))
days2warn1=$((days2warn1 / 2))
fi
diffseconds=$(( $(parse_date "$enddate" "+%s" $'%F %H:%M') - $(parse_date "$startdate" "+%s" $'%F %H:%M') ))
fi
# We adjust the thresholds by %50 for LE certificates, relaxing warnings for those certificates.
# . instead of \' because it does not break syntax highlighting in vim
if [[ "$issuer_CN" =~ ^Let.s\ Encrypt\ Authority ]] ; then
days2warn2=$((days2warn2 / 2))
days2warn1=$((days2warn1 / 2))
fi
debugme echo -n "diffseconds: $diffseconds"
expire=$($OPENSSL x509 -in $HOSTCERT -checkend 1 2>>$ERRFILE)
if ! grep -qw not <<< "$expire" ; then
@ -8736,8 +8761,9 @@ certificate_info() {
fileout "cert_notBefore${json_postfix}" "INFO" "$startdate" # we assume that the certificate has no start time in the future
fileout "cert_notAfter${json_postfix}" "$expok" "$enddate" # They are in UTC
# Internal certificates or those from appliances often have too high validity periods.
# We check for ~10 years and >~ 5 years
if [[ $diffseconds -ge $((3600 * 24 * 365 * 10)) ]]; then
# certificate is valid >= 10 years
out "$spaces"
prln_svrty_high ">= 10 years is way too long"
fileout "cert_validityPeriod${json_postfix}" "HIGH" "$((diffseconds / (3600 * 24) )) days"
@ -8745,9 +8771,32 @@ certificate_info() {
out "$spaces"
prln_svrty_medium ">= 5 years is too long"
fileout "cert_validityPeriod${json_postfix}" "MEDIUM" "$((diffseconds / (3600 * 24) )) days"
elif [[ $diffseconds -ge $((3600 * 24 * 825)) ]]; then
# Also "official" certificates issued from March 1st, 2018 aren't supposed
# to be valid longer than 825 days which is 1517353200 in epoch seconds
# (GNUish: date --date='01/31/2018 00:00:00' +"%s")
gt_825=true
if "$HAS_OPENBSDDATE"; then
if [[ 20180301 -le ${yearstart//-/} ]]; then
gt_825warn=true
fi
elif [[ $(parse_date "$startdate" "+%s" $'%F %H:%M') -ge 1517353200 ]]; then
gt_825warn=true
fi
# Now, the verdict, depending on the issuing date
out "$spaces"
if "$gt_825warn" && "$gt_825"; then
prln_svrty_medium ">= 825 days issued after 2018/03/01 is too long"
fileout "cert_validityPeriod${json_postfix}" "MEDIUM" "$((diffseconds / (3600 * 24) )) >= 825 days"
elif "$gt_825"; then
outln ">= 825 days certificate life time but issued before 2018/03/01"
fileout "cert_validityPeriod${json_postfix}" "INFO" "$((diffseconds / (3600 * 24) )) < 825 days"
fi
else
[[ "$DEBUG" -ge 1 ]] && outln "${spaces}OK: below 5 years certificate life time"
fileout "cert_validityPeriod${json_postfix}" "INFO" "$((diffseconds / (3600 * 24) )) days"
# All is fine with valididy period
# We ignore for now certificates < 2018/03/01. On the screen we only show debug info
[[ "$DEBUG" -ge 1 ]] && outln "${spaces}DEBUG: all is fine with certificate life time"
fileout "cert_validityPeriod${json_postfix}" "INFO" "No finding"
fi
certificates_provided=1+$(grep -c "\-\-\-\-\-BEGIN CERTIFICATE\-\-\-\-\-" $TEMPDIR/intermediatecerts.pem)