@@ -6468,9 +6468,8 @@ run_server_preference() {
64686468 local cipher1="" cipher2="" tls13_cipher1="" tls13_cipher2="" default_proto=""
64696469 local default_cipher=""
64706470 local limitedsense="" supported_sslv2_ciphers
6471- local -a offered_cipher offered_proto
64726471 local proto_ossl proto_txt proto_hex cipherlist i
6473- local -i ret=0 j sclient_success str_len
6472+ local -i ret=0 j sclient_success
64746473 local list_fwd="DHE-RSA-SEED-SHA:SEED-SHA:DES-CBC3-SHA:RC4-MD5:DES-CBC-SHA:RC4-SHA:AES128-SHA:AES128-SHA256:AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:ECDH-RSA-DES-CBC3-SHA:ECDH-RSA-AES128-SHA:ECDH-RSA-AES256-SHA:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:DHE-DSS-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:AES256-SHA256:ECDHE-RSA-DES-CBC3-SHA:ECDHE-RSA-AES128-SHA256:AES256-GCM-SHA384:AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-SHA256:ADH-AES256-GCM-SHA384:AECDH-AES128-SHA:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-AES128-SHA"
64756474 local list_reverse="ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-RC4-SHA:AECDH-AES128-SHA:ADH-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-GCM-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-DES-CBC3-SHA:AES256-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDH-RSA-AES256-SHA:ECDH-RSA-AES128-SHA:ECDH-RSA-DES-CBC3-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-AES128-SHA:AES256-SHA:AES128-SHA256:AES128-SHA:RC4-SHA:DES-CBC-SHA:RC4-MD5:DES-CBC3-SHA:SEED-SHA:DHE-RSA-SEED-SHA"
64766475 tls_list_fwd="c0,2c, c0,30, 00,9f, cc,a9, cc,a8, cc,aa, c0,2b, c0,2f, 00,9e, c0,24, c0,28, 00,6b, c0,23, c0,27, 00,67, c0,0a, 00,04, 00,05, 00,09, 00,0a, 00,9a, 00,96,
@@ -8335,13 +8334,15 @@ determine_cert_fingerprint_serial() {
83358334 result="${result//Fingerprint=}"
83368335 result="${result//serial=}"
83378336 result="${result//:/}"
8337+ result="${result//SHA1 /}"
8338+ result="${result//SHA256 /}"
83388339 safe_echo "$result"
83398340}
83408341
83418342# Returns startdate, enddate, diffseconds, days2expire as CSVs as strings
83428343# arg1: human readable text string for certificate (openssl x509 -text -noout)
83438344#
8344- determine_dates_certificate () {
8345+ determine_dates_certificate() {
83458346 local cert_txt="$1"
83468347 local startdate enddate yearnow y m d yearstart clockstart yearend clockend
83478348 local diffseconds=0 days2expire=0
@@ -8360,8 +8361,8 @@ determine_dates_certificate () {
83608361 # Now we extract a date block and a time block which we need for later output
83618362 startdate="$(parse_date "$startdate" +"%F %H:%M" "%b %d %T %Y %Z")"
83628363 enddate="$(parse_date "$enddate" +"%F %H:%M" "%b %d %T %Y %Z")"
8363- read yearstart clockstart <<< "$startdate"
8364- read yearend clockend <<< "$enddate"
8364+ read -r yearstart clockstart <<< "$startdate"
8365+ read -r yearend clockend <<< "$enddate"
83658366 debugme echo "$yearstart, $clockstart"
83668367 debugme echo "$yearend, $clockend"
83678368 y=$(( ${yearend:0:4} - ${yearstart:0:4} ))
@@ -8384,7 +8385,7 @@ determine_dates_certificate () {
83848385 days2expire=$((days2expire / 3600 / 24 ))
83858386 diffseconds=$(( $(parse_date "$enddate" "+%s" $'%F %H:%M') - $(parse_date "$startdate" "+%s" $'%F %H:%M') ))
83868387 fi
8387- safe_echo "$startdate, $enddate, $diffseconds, $days2expire, $yearstart"
8388+ safe_echo "$startdate,$enddate,$diffseconds,$days2expire,$yearstart"
83888389}
83898390
83908391
@@ -8436,6 +8437,7 @@ certificate_info() {
84368437 local yearstart
84378438 local gt_398=false gt_398warn=false
84388439 local gt_825=false gt_825warn=false
8440+ local first=true
84398441 local badocsp=1
84408442
84418443 if [[ $number_of_certificates -gt 1 ]]; then
@@ -8445,7 +8447,7 @@ certificate_info() {
84458447 pr_headline "Server Certificate #$certificate_number"
84468448 [[ -z "$sni_used" ]] && pr_underline " (in response to request w/o SNI)"
84478449 outln
8448- json_postfix=" <cert #${certificate_number}>"
8450+ json_postfix=" <hostCert #${certificate_number}>"
84498451 spaces=" "
84508452 else
84518453 spaces=" "
@@ -8600,7 +8602,7 @@ certificate_info() {
86008602 *GOST*|*gost*) short_keyAlgo="GOST";;
86018603 *dh*|*DH*) short_keyAlgo="DH" ;;
86028604 *) pr_fixme "don't know $cert_key_algo "
8603- let ret++ ;;
8605+ (( ret++)) ;;
86048606 esac
86058607 out "$short_keyAlgo "
86068608 # https://tools.ietf.org/html/rfc4492, https://www.keylength.com/en/compare/
@@ -8776,12 +8778,12 @@ certificate_info() {
87768778 fileout "cert_serialNumber${json_postfix}" "INFO" "$cert_serial"
87778779
87788780 cert_fingerprint_sha1="$(determine_cert_fingerprint_serial "$HOSTCERT" "-fingerprint -sha1")"
8779- outln "$cert_serial / $cert_fingerprint_sha1"
8780- fileout "cert_fingerprintSHA1${json_postfix}" "INFO" "${cert_fingerprint_sha1//SHA1 / }"
8781+ outln "$cert_serial / SHA1 $cert_fingerprint_sha1"
8782+ fileout "cert_fingerprintSHA1${json_postfix}" "INFO" "${cert_fingerprint_sha1}"
87818783
87828784 cert_fingerprint_sha2="$(determine_cert_fingerprint_serial "$HOSTCERT" "-fingerprint -sha256")"
8783- fileout "cert_fingerprintSHA256${json_postfix}" "INFO" "${cert_fingerprint_sha2//SHA256 / }"
8784- outln "$spaces$ cert_fingerprint_sha2"
8785+ fileout "cert_fingerprintSHA256${json_postfix}" "INFO" "${cert_fingerprint_sha2}"
8786+ outln "${ spaces}SHA256 ${ cert_fingerprint_sha2} "
87858787
87868788 # " " needs to be converted back to lf in JSON/CSV output. watch out leading/ending line containting "CERTIFICATE"
87878789 fileout "cert${json_postfix}" "INFO" "$(< $HOSTCERT)"
@@ -9060,56 +9062,6 @@ certificate_info() {
90609062# https://certs.opera.com/03/ev-oids.xml
90619063# see #967
90629064
9063-
9064- # There might be >1 certificate, so we split intermediatecerts.pem e.g. into
9065- # intermediatecert1.crt, intermediatecert2.cert.
9066- #FIXME: This is somewhat redundant code. We do similar stuff elsewhere, e.g. in extract_certificates()
9067- # and run_hpkp() but don't keep the result
9068-
9069- # Store all of the text output of the intermediate certificates in an array so that they can
9070- # be used later (e.g., to check their expiration dates).
9071- while true; do
9072- [[ "$intermediates" =~ \-\-\-\-\-\BEGIN\ CERTIFICATE\-\-\-\-\- ]] || break
9073- intermediates="${intermediates#*-----BEGIN CERTIFICATE-----}"
9074- cert="${intermediates%%-----END CERTIFICATE-----*}"
9075- intermediates="${intermediates#${cert}-----END CERTIFICATE-----}"
9076- cert="-----BEGIN CERTIFICATE-----${cert}-----END CERTIFICATE-----"
9077-
9078- # we count as humans in the file output here. This needs later to be adjusted in the code
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-
9083- 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"
9090- certificates_provided+=1
9091- done
9092-
9093- # courtesy Hanno Boeck (see https://github.com/hannob/badocspcert)
9094- out "$indent"; pr_bold " Bad OCSP intermediate"
9095- out " (exp.) "
9096- jsonID="cert_bad_ocsp"
9097-
9098- certificates_provided+=1
9099- for (( i=0; i < certificates_provided-1; i++ )); do
9100- cert_ext_keyusage="$(awk '/X509v3 Extended Key Usage:/ { getline; print $0 }' <<< "${intermediate_certs_txt[i]}")"
9101- [[ "$cert_ext_keyusage" =~ OCSP\ Signing ]] && badocsp=0 && break
9102- done
9103-
9104- #FIXME: We only raise the flag saying the chain is bad w/o naming the intermediate cert to blame.
9105- if [[ $badocsp -eq 0 ]]; then
9106- prln_svrty_medium "NOT ok"
9107- fileout "${jsonID}${json_postfix}" "MEDIUM" "NOT ok is/are intermediate certificate(s)"
9108- else
9109- prln_svrty_good "Ok"
9110- fileout "${jsonID}${json_postfix}" "OK" "intermediate certificate(s) is/are ok"
9111- fi
9112-
91139065 out "$indent"; pr_bold " ETS/\"eTLS\""
91149066 out ", visibility info "
91159067 jsonID="cert_eTLS"
@@ -9217,7 +9169,10 @@ certificate_info() {
92179169 fileout "cert_validityPeriod${json_postfix}" "INFO" "No finding"
92189170 fi
92199171
9220- out "$indent"; pr_bold " # of certificates provided"; out " $certificates_provided"
9172+ out "$indent"; pr_bold " Certificates provided"
9173+ certificates_provided="$(grep -ac '\-\-\-\-\-BEGIN\ CERTIFICATE\-\-\-\-\-' <<< "$intermediates")"
9174+ ((certificates_provided++)) # plus host certificate
9175+ out " $certificates_provided"
92219176 fileout "certs_countServer${json_postfix}" "INFO" "${certificates_provided}"
92229177 if "$certificate_list_ordering_problem"; then
92239178 prln_svrty_low " (certificate list ordering problem)"
@@ -9281,7 +9236,7 @@ certificate_info() {
92819236 else
92829237 if [[ $(count_lines "$ocsp_uri") -eq 1 ]]; then
92839238 out "$ocsp_uri"
9284- if [[ "$expfinding" != " expired" ]]; then
9239+ if [[ "$expfinding" != expired ]]; then
92859240 check_revocation_ocsp "$ocsp_uri" "" "cert_ocspRevoked${json_postfix}"
92869241 fi
92879242 ret=$((ret +$?))
@@ -9295,7 +9250,7 @@ certificate_info() {
92959250 out "$spaces"
92969251 fi
92979252 out "$line"
9298- if [[ "$expfinding" != " expired" ]]; then
9253+ if [[ "$expfinding" != expired ]]; then
92999254 check_revocation_ocsp "$line" "" "cert_ocspRevoked${json_postfix}"
93009255 ret=$((ret +$?))
93019256 fi
@@ -9339,7 +9294,7 @@ certificate_info() {
93399294 else
93409295 out "(response status unknown)"
93419296 fileout "${jsonID}${json_postfix}" "OK" " not sure what's going on here, '$ocsp_response'"
9342- debugme grep -a -A20 -B2 "OCSP response" <<<"$ocsp_response"
9297+ debugme grep -a -A20 -B2 "OCSP response" <<< "$ocsp_response"
93439298 ((ret++))
93449299 fi
93459300 fi
@@ -9391,6 +9346,79 @@ certificate_info() {
93919346 outln "$ct"
93929347 fileout "${jsonID}${json_postfix}" "INFO" "$ct"
93939348 fi
9349+
9350+ # Now we take care of the intermediate certificates. We basically (should) have them on disk
9351+ # as "intermediatecerts.pem" (which could be split into intermediatecert1.crt, intermediatecert2.crt, ..)
9352+ # However we do this in RAM which is better as it was passed to this function.
9353+ # We should keep in mind though this is somewhat redundant code. We do similar stuff elsewhere,
9354+ # e.g. in extract_certificates() and run_hpkp() but don't keep the certificates
9355+
9356+ #FIXME: output
9357+ # intermediate CN / (what about issuer. moving it?)
9358+ # fix the numbering schem of certificates_provided below
9359+
9360+ # Store all of the text output of the intermediate certificates in an array so that they can
9361+ # be used later (e.g., to check their expiration dates).
9362+ certificates_provided=0
9363+ while true; do
9364+ [[ "$intermediates" =~ \-\-\-\-\-BEGIN\ CERTIFICATE\-\-\-\-\- ]] || break
9365+ intermediates="${intermediates#*-----BEGIN CERTIFICATE-----}"
9366+ cert="${intermediates%%-----END CERTIFICATE-----*}"
9367+ intermediates="${intermediates#${cert}-----END CERTIFICATE-----}"
9368+ cert="-----BEGIN CERTIFICATE-----${cert}-----END CERTIFICATE-----"
9369+
9370+ # we count as humans in the file output here. This needs later to be adjusted in the code
9371+ fileout "intermediate_cert <#$((certificates_provided + 1))>${json_postfix}" "INFO" "$cert"
9372+
9373+ fileout "intermediate_cert_fingerprintSHA256 <#$((certificates_provided + 1))>${json_postfix}" "INFO" "$(determine_cert_fingerprint_serial "$cert" "-fingerprint -sha256")"
9374+
9375+ intermediate_certs_txt[certificates_provided]="$($OPENSSL x509 -text -noout 2>/dev/null <<< "$cert")"
9376+
9377+ # We don't need every value here. For the sake of being consistent here we add the rest
9378+ IFS=',' read -r startdate enddate diffseconds days2expire yearstart < <(determine_dates_certificate "${intermediate_certs_txt[certificates_provided]}")
9379+ fileout "intermediate_cert_notBefore <#$((certificates_provided + 1))>${json_postfix}" "INFO" "$startdate"
9380+
9381+ if $first; then
9382+ out "$indent"; pr_bold " Intermediate cert validity "
9383+ first=false
9384+ else
9385+ out "$indent$spaces"
9386+ fi
9387+ if ! $OPENSSL x509 -checkend $((24*3600*20)) 2>>$ERRFILE <<< "$cert" | grep -qw not; then
9388+ out "#$((certificates_provided+1)): less then "; pr_svrty_high "20 days"
9389+ outln " at $enddate"
9390+ expok="HIGH"
9391+ elif ! $OPENSSL x509 -checkend $((24*3600*40)) 2>>$ERRFILE <<< "$cert" | grep -qw not; then
9392+ out "#$((certificates_provided+1)): less then "; pr_svrty_medium "40 days"
9393+ outln " at $enddate"
9394+ expok="MEDIUM"
9395+ else
9396+ outln "#$((certificates_provided+1)): longer than 40 days ($enddate)"
9397+ fi
9398+ fileout "intermediate_cert_notAfter <#$((certificates_provided + 1))>${json_postfix}" "$expok" "$enddate"
9399+ certificates_provided+=1
9400+ done
9401+
9402+ # Courtesy Hanno Böck (see https://github.com/hannob/badocspcert)
9403+ out "$indent"; pr_bold " Intermediate Bad OCSP"
9404+ out " (exp.) "
9405+ jsonID="intermediate_cert_badOCSP"
9406+
9407+ certificates_provided+=1
9408+ for (( i=0; i < certificates_provided-1; i++ )); do
9409+ cert_ext_keyusage="$(awk '/X509v3 Extended Key Usage:/ { getline; print $0 }' <<< "${intermediate_certs_txt[i]}")"
9410+ [[ "$cert_ext_keyusage" =~ OCSP\ Signing ]] && badocsp=0 && break
9411+ done
9412+
9413+ #FIXME: We only raise the flag saying the chain is bad w/o naming the intermediate cert to blame.
9414+ if [[ $badocsp -eq 0 ]]; then
9415+ prln_svrty_medium "NOT ok"
9416+ fileout "${jsonID}${json_postfix}" "MEDIUM" "NOT ok is/are intermediate certificate(s)"
9417+ else
9418+ prln_svrty_good "Ok"
9419+ fileout "${jsonID}${json_postfix}" "OK" "intermediate certificate(s) is/are ok"
9420+ fi
9421+
93949422 outln
93959423 return $ret
93969424}
0 commit comments