Merge branch '2.9dev' of github.com:/drwetter/testssl.sh into 2.9dev
This commit is contained in:
commit
28dd530c45
259
testssl.sh
259
testssl.sh
|
@ -2997,7 +2997,7 @@ sub_cipherlists() {
|
||||||
if [[ -n "$6" ]] || listciphers "$1" "$2" $proto; then
|
if [[ -n "$6" ]] || listciphers "$1" "$2" $proto; then
|
||||||
if [[ -z "$6" ]] || ( "$FAST" && listciphers "$1" "$2" -tls1 ); then
|
if [[ -z "$6" ]] || ( "$FAST" && listciphers "$1" "$2" -tls1 ); then
|
||||||
for proto in -no_ssl2 -tls1_2 -tls1_1 -tls1 -ssl3; do
|
for proto in -no_ssl2 -tls1_2 -tls1_1 -tls1 -ssl3; do
|
||||||
if [[ "$proto" == "-tls1_2" ]]; then
|
if [[ "$proto" == -tls1_2 ]]; then
|
||||||
# If $OPENSSL doesn't support TLSv1.3 or if no TLSv1.3
|
# If $OPENSSL doesn't support TLSv1.3 or if no TLSv1.3
|
||||||
# ciphers are being tested, then a TLSv1.2 ClientHello
|
# ciphers are being tested, then a TLSv1.2 ClientHello
|
||||||
# was tested in the first iteration.
|
# was tested in the first iteration.
|
||||||
|
@ -3071,24 +3071,23 @@ sub_cipherlists() {
|
||||||
fileout "${jsonID}_$5" "MEDIUM" "not offered"
|
fileout "${jsonID}_$5" "MEDIUM" "not offered"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
|
||||||
1) if [[ $sclient_success -eq 0 ]]; then
|
1) if [[ $sclient_success -eq 0 ]]; then
|
||||||
# High is good to offer
|
# High is good to offer
|
||||||
pr_svrty_good "offered (OK)"
|
pr_svrty_good "offered (OK)"
|
||||||
fileout "${jsonID}_$5" "OK" "offered"
|
fileout "${jsonID}_$5" "OK" "offered"
|
||||||
else
|
else
|
||||||
# FIXME: the rating could be readjusted if we knew the result of STRONG before
|
# FIXME: we penalize the absence of high but don't know the result of strong encryption yet (next)
|
||||||
pr_svrty_medium "not offered"
|
pr_svrty_medium "not offered"
|
||||||
fileout "${jsonID}_$5" "MEDIUM" "not offered"
|
fileout "${jsonID}_$5" "MEDIUM" "not offered"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
0) if [[ $sclient_success -eq 0 ]]; then
|
0) if [[ $sclient_success -eq 0 ]]; then
|
||||||
# medium is not that bad
|
# medium is not that bad
|
||||||
pr_svrty_medium "offered"
|
pr_svrty_low "offered"
|
||||||
fileout "${jsonID}_$5" "MEDIUM" "offered"
|
fileout "${jsonID}_$5" "LOW" "offered"
|
||||||
else
|
else
|
||||||
out "not offered (OK)"
|
out "not offered"
|
||||||
fileout "${jsonID}_$5" "OK" "not offered"
|
fileout "${jsonID}_$5" "INFO" "not offered"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
-1) if [[ $sclient_success -eq 0 ]]; then
|
-1) if [[ $sclient_success -eq 0 ]]; then
|
||||||
|
@ -3132,6 +3131,48 @@ sub_cipherlists() {
|
||||||
return $ret
|
return $ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Generic function for a rated output, no used yet.
|
||||||
|
# arg1: rating from 2 to -4 if available or not
|
||||||
|
# arg2: no/yes: decides whether positive or negative logic will be applied and "not" will be printed
|
||||||
|
# arg3: jsonID
|
||||||
|
#
|
||||||
|
rated_output() {
|
||||||
|
local jsonID=$3
|
||||||
|
local logic=""
|
||||||
|
|
||||||
|
if [[ $2 == no ]] || [[ $2 == negative ]]; then
|
||||||
|
logic="not "
|
||||||
|
fi
|
||||||
|
case $1 in
|
||||||
|
2) pr_svrty_best "${logic}offered (OK)"
|
||||||
|
fileout "${jsonID}" "OK" "${logic}offered"
|
||||||
|
;;
|
||||||
|
1) pr_svrty_good "${logic}offered (OK)"
|
||||||
|
fileout "${jsonID}" "OK" "${logic}offered"
|
||||||
|
;;
|
||||||
|
0) out "${logic}offered"
|
||||||
|
fileout "${jsonID}" "INFO" "${logic}offered"
|
||||||
|
;;
|
||||||
|
-1) pr_svrty_low "${logic}offered"
|
||||||
|
fileout "${jsonID}" "LOW" "${logic}offered"
|
||||||
|
;;
|
||||||
|
-2) pr_svrty_medium "${logic}offered"
|
||||||
|
fileout "${jsonID}" "MEDIUM" "${logic}offered"
|
||||||
|
;;
|
||||||
|
-3) pr_svrty_high "${logic}offered (NOT ok)"
|
||||||
|
fileout "${jsonID}" "HIGH" "${logic}offered"
|
||||||
|
;;
|
||||||
|
-4) pr_svrty_critical "${logic}offered (NOT ok)"
|
||||||
|
fileout "${jsonID}" "CRITICAL" "${logic}offered"
|
||||||
|
;;
|
||||||
|
*) pr_warning "FIXME: error around $LINENO, (please report this)"
|
||||||
|
fileout "${jsonID}" "WARN" "return condition $2 when $1 unclear"
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
openssl2rfc() {
|
openssl2rfc() {
|
||||||
local rfcname=""
|
local rfcname=""
|
||||||
|
@ -5391,22 +5432,22 @@ run_cipherlists() {
|
||||||
# ~ egrep -w '64|56|RC2|RC4' etc/cipher-mapping.txt | grep -v export
|
# ~ egrep -w '64|56|RC2|RC4' etc/cipher-mapping.txt | grep -v export
|
||||||
local low_ciphers="00,15, 00,12, 00,0f, 00,0c, 00,09, 00,1e, 00,22, fe,fe, ff,e1, c0,11, c0,07, 00,66, c0,0c, c0,02, 00,05, 00,04, 00,92, 00,8a, 00,20, 00,24, c0,33, 00,8e, 00,ff"
|
local low_ciphers="00,15, 00,12, 00,0f, 00,0c, 00,09, 00,1e, 00,22, fe,fe, ff,e1, c0,11, c0,07, 00,66, c0,0c, c0,02, 00,05, 00,04, 00,92, 00,8a, 00,20, 00,24, c0,33, 00,8e, 00,ff"
|
||||||
local sslv2_low_ciphers="01,00,80, 03,00,80, 08,00,80, 06,00,40, 06,01,40, FF,80,00"
|
local sslv2_low_ciphers="01,00,80, 03,00,80, 08,00,80, 06,00,40, 06,01,40, FF,80,00"
|
||||||
# ~ egrep -w 128 etc/cipher-mapping.txt | egrep -v "Au=None|AEAD|ARIA|Camellia|AES|RC2|RC4"
|
|
||||||
local medium_ciphers="00,9a, 00,99, 00,98, 00,97, 00,96, 00,07, 00,21, 00,25, 00,ff"
|
|
||||||
local sslv2_medium_ciphers="05,00,80"
|
|
||||||
# ~ egrep -w '3DES' etc/cipher-mapping.txt
|
# ~ egrep -w '3DES' etc/cipher-mapping.txt
|
||||||
local tdes_ciphers="c0,12, c0,08, c0,1c, c0,1b, c0,1a, 00,16, 00,13, 00,10, 00,0d, c0,0d, c0,03, 00,0a, 00,93, 00,8b, 00,1f, 00,23, c0,34, 00,8f, fe,ff, ff,e0, 00,ff"
|
local tdes_ciphers="c0,12, c0,08, c0,1c, c0,1b, c0,1a, 00,16, 00,13, 00,10, 00,0d, c0,0d, c0,03, 00,0a, 00,93, 00,8b, 00,1f, 00,23, c0,34, 00,8f, fe,ff, ff,e0, 00,ff"
|
||||||
local sslv2_tdes_ciphers="07,00,c0, 07,01,c0"
|
local sslv2_tdes_ciphers="07,00,c0, 07,01,c0"
|
||||||
# ~ equivalent to 'egrep -w "GOST|128|256" etc/cipher-mapping.txt | grep -v '=None' | egrep -vw 'RC4|AEAD|IDEA|SEED|RC2'. Attention: 127 ciphers currently
|
# ~ egrep -w 128 etc/cipher-mapping.txt | egrep -v "Au=None|AEAD|RC2|RC4"
|
||||||
local high_ciphers="c0,28, c0,24, c0,14, c0,0a, c0,22, c0,21, c0,20, 00,b7, 00,b3, 00,91, c0,9b, c0,99, c0,97, 00,af, c0,95, 00,6b, 00,6a, 00,69, 00,68, 00,39, 00,38, 00,37, 00,36, c0,77, c0,73, 00,c4, 00,c3, 00,c2, 00,c1, 00,88, 00,87, 00,86, 00,85, c0,2a, c0,26, c0,0f, c0,05, c0,79, c0,75, 00,3d, 00,35, 00,c0, c0,38, c0,36, 00,84, 00,95, 00,8d, c0,3d, c0,3f, c0,41, c0,43, c0,45, c0,49, c0,4b, c0,4d, c0,4f, c0,65, c0,67, c0,69, c0,71, 00,80, 00,81, ff,00, ff,01, ff,02, ff,03, ff,85, c0,27, c0,23, c0,13, c0,09, c0,1f, c0,1e, c0,1d, 00,67, 00,40, 00,3f, 00,3e, 00,33, 00,32, 00,31, 00,30, c0,76, c0,72, 00,be, 00,bd, 00,bc, 00,bb, 00,45, 00,44, 00,43, 00,42, c0,29, c0,25, c0,0e, c0,04, c0,78, c0,74, 00,3c, 00,2f, 00,ba, c0,37, c0,35, 00,b6, 00,b2, 00,90, 00,41, c0,9a, c0,98, c0,96, 00,ae, c0,94, 00,94, 00,8c, c0,3c, c0,3e, c0,40, c0,42, c0,44, c0,48, c0,4a, c0,4c, c0,4e, c0,64, c0,66, c0,68, c0,70"
|
local medium_ciphers="00,07, 00,21, 00,25, 00,2F, 00,30, 00,31, 00,32, 00,33, 00,3C, 00,3E, 00,3F, 00,40, 00,41, 00,42, 00,43, 00,44, 00,45, 00,67, 00,8C, 00,90, 00,94, 00,96, 00,97, 00,98, 00,99, 00,9A, 00,AE, 00,B2, 00,B6, 00,BA, 00,BB, 00,BC, 00,BD, 00,BE, C0,04, C0,09, C0,0E, C0,13, C0,1D, C0,1E, C0,1F, C0,23, C0,25, C0,27, C0,29, C0,35, C0,37, C0,3C, C0,3E, C0,40, C0,42, C0,44, C0,48, C0,4A, C0,4C, C0,4E, C0,64, C0,66, C0,68, C0,70, C0,72, C0,74, C0,76, C0,78, C0,94, C0,96, C0,98, C0,9A, 00,ff"
|
||||||
# no SSLv2 here and in strong
|
# Attention we have a SSLv2 cipher here: IDEA-CBC-MD5 / SSL_CK_IDEA_128_CBC_WITH_MD5
|
||||||
# ~ equivalent to 'grep AEAD etc/cipher-mapping.txt | grep -v Au=None'
|
local sslv2_medium_ciphers="05,00,80"
|
||||||
|
# ~ egrep -w "256" etc/cipher-mapping.txt | grep -v '=None' | egrep -vw 'RC4|AEAD|IDEA|SEED|RC2|GOST'
|
||||||
|
local high_ciphers="00,35, 00,36, 00,37, 00,38, 00,39, 00,3D, 00,68, 00,69, 00,6A, 00,6B, 00,84, 00,85, 00,86, 00,87, 00,88, 00,8D, 00,91, 00,95, 00,AF, 00,B3, 00,B7, 00,C0, 00,C1, 00,C2, 00,C3, 00,C4, C0,05, C0,0A, C0,0F, C0,14, C0,20, C0,21, C0,22, C0,24, C0,26, C0,28, C0,2A, C0,36, C0,38, C0,3D, C0,3F, C0,41, C0,43, C0,45, C0,49, C0,4B, C0,4D, C0,4F, C0,65, C0,67, C0,69, C0,71, C0,73, C0,75, C0,77, C0,79, C0,95, C0,97, C0,99, C0,9B, 00,ff"
|
||||||
|
# ~ grep AEAD etc/cipher-mapping.txt | grep -v Au=None
|
||||||
local strong_ciphers="13,01, 13,02, 13,03, 13,04, 13,05, cc,14, cc,13, cc,15, c0,30, c0,2c, 00,a5, 00,a3, 00,a1, 00,9f, cc,a9, cc,a8, cc,aa, c0,af, c0,ad, c0,a3, c0,9f, 00,ad, 00,ab, cc,ae, cc,ad, cc,ac, c0,ab, c0,a7, c0,32, c0,2e, 00,9d, c0,a1, c0,9d, 00,a9, cc,ab, c0,a9, c0,a5, c0,51, c0,53, c0,55, c0,57, c0,59, c0,5d, c0,5f, c0,61, c0,63, c0,6b, c0,6d, c0,6f, c0,7b, c0,7d, c0,7f, c0,81, c0,83, c0,87, c0,89, c0,8b, c0,8d, c0,8f, c0,91, c0,93, 16,b7, 16,b8, 16,b9, 16,ba, c0,2f, c0,2b, 00,a4, 00,a2, 00,a0, 00,9e, c0,ae, c0,ac, c0,a2, c0,9e, 00,ac, 00,aa, c0,aa, c0,a6, c0,a0, c0,9c, 00,a8, c0,a8, c0,a4, c0,31, c0,2d, 00,9c, c0,50, c0,52, c0,54, c0,56, c0,58, c0,5c, c0,5e, c0,60, c0,62, c0,6a, c0,6c, c0,6e, c0,7a, c0,7c, c0,7e, c0,80, c0,82, c0,86, c0,88, c0,8a, c0,8c, c0,8e, c0,90, c0,92, 00,ff"
|
local strong_ciphers="13,01, 13,02, 13,03, 13,04, 13,05, cc,14, cc,13, cc,15, c0,30, c0,2c, 00,a5, 00,a3, 00,a1, 00,9f, cc,a9, cc,a8, cc,aa, c0,af, c0,ad, c0,a3, c0,9f, 00,ad, 00,ab, cc,ae, cc,ad, cc,ac, c0,ab, c0,a7, c0,32, c0,2e, 00,9d, c0,a1, c0,9d, 00,a9, cc,ab, c0,a9, c0,a5, c0,51, c0,53, c0,55, c0,57, c0,59, c0,5d, c0,5f, c0,61, c0,63, c0,6b, c0,6d, c0,6f, c0,7b, c0,7d, c0,7f, c0,81, c0,83, c0,87, c0,89, c0,8b, c0,8d, c0,8f, c0,91, c0,93, 16,b7, 16,b8, 16,b9, 16,ba, c0,2f, c0,2b, 00,a4, 00,a2, 00,a0, 00,9e, c0,ae, c0,ac, c0,a2, c0,9e, 00,ac, 00,aa, c0,aa, c0,a6, c0,a0, c0,9c, 00,a8, c0,a8, c0,a4, c0,31, c0,2d, 00,9c, c0,50, c0,52, c0,54, c0,56, c0,58, c0,5c, c0,5e, c0,60, c0,62, c0,6a, c0,6c, c0,6e, c0,7a, c0,7c, c0,7e, c0,80, c0,82, c0,86, c0,88, c0,8a, c0,8c, c0,8e, c0,90, c0,92, 00,ff"
|
||||||
local cwe="CWE-327"
|
local cwe="CWE-327"
|
||||||
local cwe2="CWE-310"
|
local cwe2="CWE-310"
|
||||||
local cve=""
|
local cve=""
|
||||||
|
|
||||||
# decoding the SSLv3-TLS1.2 ciphers, e.g:
|
# decoding the >= SSLv3 ciphers in the code above , e.g:
|
||||||
# echo "00,15, c0,11, fe,fe' | sed -e 's/00,/0x00,0x/g' -e 's/c0,/0xc0,0x/g' -e 's/cc,/0xcc,0x/g' -e 's/13,/0x13,0x/g' -e 's/16,/0x16,0x/g' -e 's/fe,/0xfe,0x/g' -e 's/ff,/0xff,0x/g' -e 's/, /\n/g' | \
|
# echo "00,15, c0,11, fe,fe' | sed -e 's/00,/0x00,0x/g' -e 's/c0,/0xc0,0x/g' -e 's/cc,/0xcc,0x/g' -e 's/13,/0x13,0x/g' -e 's/16,/0x16,0x/g' -e 's/fe,/0xfe,0x/g' -e 's/ff,/0xff,0x/g' -e 's/, /\n/g' | \
|
||||||
# while read ci; do grep -wi $ci etc/cipher-mapping.txt; done
|
# while read ci; do grep -wi $ci etc/cipher-mapping.txt; done
|
||||||
|
|
||||||
|
@ -5424,7 +5465,7 @@ run_cipherlists() {
|
||||||
outln
|
outln
|
||||||
pr_headlineln " Testing cipher categories "
|
pr_headlineln " Testing cipher categories "
|
||||||
outln
|
outln
|
||||||
# argv[1]: cipher list to test in OpenSSL syntax (see ciphers(1ssl) or run 'openssl ciphers -v/-V)'
|
# argv[1]: cipher list to test in OpenSSL syntax (see ciphers(1ssl) or run 'openssl ciphers -v/-V)', TLS 1.3 ciphers will be treated automatically
|
||||||
# argv[2]: string on console / HTML or "finding"
|
# argv[2]: string on console / HTML or "finding"
|
||||||
# argv[3]: rating whether ok to offer
|
# argv[3]: rating whether ok to offer
|
||||||
# argv[4]: string to be appended for fileout
|
# argv[4]: string to be appended for fileout
|
||||||
|
@ -5438,15 +5479,15 @@ run_cipherlists() {
|
||||||
ret=$((ret + $?))
|
ret=$((ret + $?))
|
||||||
sub_cipherlists 'LOW:DES:RC2:RC4:!ADH:!EXP:!NULL' "" " LOW: 64 Bit + DES, RC[2,4] (w/o export) " -2 "LOW" "$low_ciphers" "$sslv2_low_ciphers" "$cve" "$cwe"
|
sub_cipherlists 'LOW:DES:RC2:RC4:!ADH:!EXP:!NULL' "" " LOW: 64 Bit + DES, RC[2,4] (w/o export) " -2 "LOW" "$low_ciphers" "$sslv2_low_ciphers" "$cve" "$cwe"
|
||||||
ret=$((ret + $?))
|
ret=$((ret + $?))
|
||||||
sub_cipherlists 'MEDIUM:!aNULL:!AES:!CAMELLIA:!ARIA:!CHACHA20:!3DES:!RC2:!RC4' \
|
sub_cipherlists '3DES:!aNULL:!ADH' "" " Triple DES Ciphers " -1 "3DES" "$tdes_ciphers" "$sslv2_tdes_ciphers" "$cve" "$cwe2"
|
||||||
"" " Weak 128 Bit ciphers (SEED, IDEA) " -1 "128Bit" "$medium_ciphers" "$sslv2_medium_ciphers" "$cve" "$cwe2"
|
|
||||||
ret=$((ret + $?))
|
ret=$((ret + $?))
|
||||||
sub_cipherlists '3DES:!aNULL:!ADH' "" " Triple DES Ciphers (Medium) " 0 "3DES" "$tdes_ciphers" "$sslv2_tdes_ciphers" "$cve" "$cwe2"
|
sub_cipherlists 'MEDIUM:!aNULL:AES128:CAMELLIA128:ARIA128:!CHACHA20:!3DES:!RC2:!RC4:!AESCCM8:!AESCCM:!AESGCM:!ARIAGCM' \
|
||||||
|
"" " 128 Bit ciphers (SEED, IDEA, 128 Bit CBC) " 0 "128Bit" "$medium_ciphers" "$sslv2_medium_ciphers" "$cve" "$cwe2"
|
||||||
ret=$((ret + $?))
|
ret=$((ret + $?))
|
||||||
sub_cipherlists 'HIGH:!NULL:!aNULL:!DES:!3DES:!AESGCM:!CHACHA20:!AESGCM:!CamelliaGCM:!AESCCM8:!AESCCM' \
|
sub_cipherlists 'HIGH:!NULL:!aNULL:!DES:!3DES:!AESGCM:!CHACHA20:!CamelliaGCM:!AESCCM:!AESCCM8:!AES128:!CAMELLIA128:!ARIAGCM:!ARIACCM' \
|
||||||
"" " High encryption (AES+Camellia, no AEAD) " 1 "HIGH" "$high_ciphers" ""
|
"" " High encryption (AES/Aria/Camellia, !AEAD)" 1 "HIGH" "$high_ciphers" ""
|
||||||
ret=$((ret + $?))
|
ret=$((ret + $?))
|
||||||
sub_cipherlists 'AESGCM:CHACHA20:AESGCM:CamelliaGCM:AESCCM8:AESCCM' 'ALL' \
|
sub_cipherlists 'AESGCM:CHACHA20:AESGCM:CamelliaGCM:AESCCM:ARIAGCM' 'ALL' \
|
||||||
" Strong encryption (AEAD ciphers) " 2 "STRONG" "$strong_ciphers" ""
|
" Strong encryption (AEAD ciphers) " 2 "STRONG" "$strong_ciphers" ""
|
||||||
ret=$((ret + $?))
|
ret=$((ret + $?))
|
||||||
outln
|
outln
|
||||||
|
@ -7258,6 +7299,152 @@ compare_server_name_to_cert() {
|
||||||
return $subret
|
return $subret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# This function determines whether the certificate (arg3) contains "visibility
|
||||||
|
# information" (see Section 4.3.3 of
|
||||||
|
# https://www.etsi.org/deliver/etsi_ts/103500_103599/10352303/01.01.01_60/ts_10352303v010101p.pdf.
|
||||||
|
etsi_etls_visibility_info() {
|
||||||
|
local jsonID="$1"
|
||||||
|
local spaces="$2"
|
||||||
|
local cert="$3"
|
||||||
|
local cert_txt="$4"
|
||||||
|
local dercert tag
|
||||||
|
local -a fingerprint=() access_description=()
|
||||||
|
local -i i j len len1 len_name nr_visnames=0
|
||||||
|
|
||||||
|
# If "visibility information" is present, it will appear in the subjectAltName
|
||||||
|
# extension (0603551D11) as an otherName with OID 0.4.0.3523.3.1 (060604009B430301).
|
||||||
|
# OpenSSL displays all names of type otherName as "othername:<unsupported>".
|
||||||
|
# As certificates will rarely include a name encoded as an otherName, check the
|
||||||
|
# text version of the certificate for "othername:<unsupported>" before calling
|
||||||
|
# external functions to obtain the DER encoded certficate.
|
||||||
|
if [[ "$cert_txt" =~ X509v3\ Subject\ Alternative\ Name:.*othername:\<unsupported\> ]]; then
|
||||||
|
dercert="$($OPENSSL x509 -in "$cert" -outform DER 2>>$ERRFILE | hexdump -v -e '16/1 "%02X"')"
|
||||||
|
if [[ "$dercert" =~ 0603551D110101FF04[0-9A-F]*060604009B430301 ]] || \
|
||||||
|
[[ "$dercert" =~ 0603551D1104[0-9A-F]*060604009B430301 ]]; then
|
||||||
|
# Look for the beginning of the subjectAltName extension. It
|
||||||
|
# will begin with the OID (2.5.29.17 = 0603551D11). After the OID
|
||||||
|
# there may be an indication that the extension is critical (0101FF).
|
||||||
|
# Finally will be the tag indicating that the value of the extension is
|
||||||
|
# encoded as an OCTET STRING (04).
|
||||||
|
if [[ "$dercert" =~ 0603551D110101FF04 ]]; then
|
||||||
|
dercert="${dercert##*0603551D110101FF04}"
|
||||||
|
else
|
||||||
|
dercert="${dercert##*0603551D1104}"
|
||||||
|
fi
|
||||||
|
# Skip over the encoding of the length of the OCTET STRING.
|
||||||
|
if [[ "${dercert:0:1}" == 8 ]]; then
|
||||||
|
i="${dercert:1:1}"
|
||||||
|
i=2*$i+2
|
||||||
|
dercert="${dercert:i}"
|
||||||
|
else
|
||||||
|
dercert="${dercert:2}"
|
||||||
|
fi
|
||||||
|
# Next byte should be a 30 (SEQUENCE).
|
||||||
|
if [[ "${dercert:0:2}" == 30 ]]; then
|
||||||
|
# Get the length of the subjectAltName extension and then skip
|
||||||
|
# over the encoding of the length.
|
||||||
|
if [[ "${dercert:2:1}" == 8 ]]; then
|
||||||
|
case "${dercert:3:1}" in
|
||||||
|
1) len=2*0x${dercert:4:2}; dercert="${dercert:6}" ;;
|
||||||
|
2) len=2*0x${dercert:4:4}; dercert="${dercert:8}" ;;
|
||||||
|
3) len=2*0x${dercert:4:6}; dercert="${dercert:10}" ;;
|
||||||
|
*) len=0 ;;
|
||||||
|
esac
|
||||||
|
else
|
||||||
|
len=2*0x${dercert:2:2}
|
||||||
|
dercert="${dercert:4}"
|
||||||
|
fi
|
||||||
|
if [[ $len -ne 0 ]] && [[ $len -lt ${#dercert} ]]; then
|
||||||
|
# loop through all the names and extract the visibility information
|
||||||
|
for (( i=0; i < len; i=i+len_name )); do
|
||||||
|
tag="${dercert:i:2}"
|
||||||
|
i+=2
|
||||||
|
if [[ "${dercert:i:1}" == 8 ]]; then
|
||||||
|
i+=1
|
||||||
|
case "${dercert:i:1}" in
|
||||||
|
1) i+=1; len_name=2*0x${dercert:i:2}; i+=2 ;;
|
||||||
|
2) i+=1; len_name=2*0x${dercert:i:4}; i+=4 ;;
|
||||||
|
3) i+=1; len_name=2*0x${dercert:i:6}; i+=4 ;;
|
||||||
|
*) len=0 ;;
|
||||||
|
esac
|
||||||
|
else
|
||||||
|
len_name=2*0x${dercert:i:2}
|
||||||
|
i+=2
|
||||||
|
fi
|
||||||
|
[[ "$tag" == A0 ]] || continue
|
||||||
|
# This is an otherName.
|
||||||
|
[[ $len_name -gt 16 ]] || continue
|
||||||
|
[[ "${dercert:i:16}" == 060604009B430301 ]] || continue
|
||||||
|
# According to the OID, this is visibility information.
|
||||||
|
j=$i+16
|
||||||
|
# Skip over the tag (A0) and length for the otherName value.
|
||||||
|
[[ "${dercert:j:2}" == A0 ]] || continue
|
||||||
|
j+=2
|
||||||
|
if [[ "${dercert:j:1}" == 8 ]]; then
|
||||||
|
j+=1
|
||||||
|
j+=2*0x${dercert:j:1}+1
|
||||||
|
else
|
||||||
|
j+=2
|
||||||
|
fi
|
||||||
|
# The value for this otherName is encoded as a SEQUENCE (30):
|
||||||
|
# VisibilityInformation ::= SEQUENCE {
|
||||||
|
# fingerprint OCTET STRING (SIZE(10)),
|
||||||
|
# accessDescription UTF8String }
|
||||||
|
[[ "${dercert:j:2}" == 30 ]] || continue
|
||||||
|
j+=2
|
||||||
|
if [[ "${dercert:j:1}" == 8 ]]; then
|
||||||
|
j+=1
|
||||||
|
case "${dercert:j:1}" in
|
||||||
|
1) j+=1; len1=2*0x${dercert:j:2}; j+=2 ;;
|
||||||
|
2) j+=1; len1=2*0x${dercert:j:4}; j+=4 ;;
|
||||||
|
3) j+=1; len1=2*0x${dercert:j:6}; j+=6 ;;
|
||||||
|
4) len1=0 ;;
|
||||||
|
esac
|
||||||
|
else
|
||||||
|
len1=2*0x${dercert:j:2}
|
||||||
|
j+=2
|
||||||
|
fi
|
||||||
|
[[ $len1 -ne 0 ]] || continue
|
||||||
|
# Next is the 10-byte fingerprint, encoded as an OCTET STRING (04)
|
||||||
|
[[ "${dercert:j:4}" == 040A ]] || continue
|
||||||
|
j+=4
|
||||||
|
fingerprint[nr_visnames]="$(asciihex_to_binary_file "${dercert:j:20}" "/dev/stdout")"
|
||||||
|
j+=20
|
||||||
|
# Finally comes the access description, encoded as a UTF8String (0C).
|
||||||
|
[[ "${dercert:j:2}" == 0C ]] || continue
|
||||||
|
j+=2
|
||||||
|
if [[ "${dercert:j:1}" == "8" ]]; then
|
||||||
|
j+=1
|
||||||
|
case "${dercert:j:1}" in
|
||||||
|
1) j+=1; len1=2*0x${dercert:j:2}; j+=2 ;;
|
||||||
|
2) j+=1; len1=2*0x${dercert:j:4}; j+=4 ;;
|
||||||
|
3) j+=1; len1=2*0x${dercert:j:6}; j+=6 ;;
|
||||||
|
4) len1=0 ;;
|
||||||
|
esac
|
||||||
|
else
|
||||||
|
len1=2*0x${dercert:j:2}
|
||||||
|
j+=2
|
||||||
|
fi
|
||||||
|
access_description[nr_visnames]=""$(asciihex_to_binary_file "${dercert:j:len1}" "/dev/stdout")""
|
||||||
|
nr_visnames+=1
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [[ $nr_visnames -eq 0 ]]; then
|
||||||
|
outln "Not present"
|
||||||
|
fileout "$jsonID" "INFO" "Not present"
|
||||||
|
else
|
||||||
|
for (( i=0; i < nr_visnames; i++ )); do
|
||||||
|
[[ $i -ne 0 ]] && out "$spaces"
|
||||||
|
outln "$(out_row_aligned_max_width "${fingerprint[i]} / ${access_description[i]}" "$spaces" $TERM_WIDTH)"
|
||||||
|
fileout "$jsonID" "INFO" "${fingerprint[i]} / ${access_description[i]}"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
# NOTE: arg3 must contain the text output of $HOSTCERT.
|
# NOTE: arg3 must contain the text output of $HOSTCERT.
|
||||||
must_staple() {
|
must_staple() {
|
||||||
local jsonID="cert_mustStapleExtension"
|
local jsonID="cert_mustStapleExtension"
|
||||||
|
@ -7968,6 +8155,10 @@ certificate_info() {
|
||||||
# https://certs.opera.com/03/ev-oids.xml
|
# https://certs.opera.com/03/ev-oids.xml
|
||||||
# see #967
|
# see #967
|
||||||
|
|
||||||
|
out "$indent"; pr_bold " eTLS "
|
||||||
|
jsonID="cert_eTLS"
|
||||||
|
etsi_etls_visibility_info "$jsonID" "$spaces" "$HOSTCERT" "$cert_txt"
|
||||||
|
|
||||||
out "$indent"; pr_bold " Certificate Validity (UTC) "
|
out "$indent"; pr_bold " Certificate Validity (UTC) "
|
||||||
|
|
||||||
# FreeBSD + OSX can't swallow the leading blank:
|
# FreeBSD + OSX can't swallow the leading blank:
|
||||||
|
@ -16492,6 +16683,11 @@ get_a_record() {
|
||||||
echo 127.0.0.1
|
echo 127.0.0.1
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
if is_ipv4addr "$1"; then
|
||||||
|
# This saves walking through this. Also it avoids hangs e.g. if you run docker locally without reachabale DNS
|
||||||
|
echo $1
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
OPENSSL_CONF="" # see https://github.com/drwetter/testssl.sh/issues/134
|
OPENSSL_CONF="" # see https://github.com/drwetter/testssl.sh/issues/134
|
||||||
check_resolver_bins
|
check_resolver_bins
|
||||||
if [[ "$NODE" == *.local ]]; then
|
if [[ "$NODE" == *.local ]]; then
|
||||||
|
@ -16505,7 +16701,7 @@ get_a_record() {
|
||||||
fi
|
fi
|
||||||
if [[ -z "$ip4" ]]; then
|
if [[ -z "$ip4" ]]; then
|
||||||
if type -p dig &> /dev/null ; then
|
if type -p dig &> /dev/null ; then
|
||||||
ip4=$(filter_ip4_address $(dig +short -t a "$1" 2>/dev/null | awk '/^[0-9]/'))
|
ip4=$(filter_ip4_address $(dig +timeout=2 +tries=2 +short -t a "$1" 2>/dev/null | awk '/^[0-9]/'))
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
if [[ -z "$ip4" ]]; then
|
if [[ -z "$ip4" ]]; then
|
||||||
|
@ -16533,6 +16729,14 @@ get_aaaa_record() {
|
||||||
|
|
||||||
[[ "$NODNS" == none ]] && return 0 # if no DNS lookup was instructed, leave here
|
[[ "$NODNS" == none ]] && return 0 # if no DNS lookup was instructed, leave here
|
||||||
OPENSSL_CONF="" # see https://github.com/drwetter/testssl.sh/issues/134
|
OPENSSL_CONF="" # see https://github.com/drwetter/testssl.sh/issues/134
|
||||||
|
if is_ipv6addr "$1"; then
|
||||||
|
# This saves walking through this. Also it avoids hangs e.g. if you run docker locally without reachabale DNS
|
||||||
|
echo "$1"
|
||||||
|
return 0
|
||||||
|
elif is_ipv4addr "$1"; then
|
||||||
|
# we need also this here as get_aaaa_record is always called after get_a_record and we want to handle this at a low level
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
check_resolver_bins
|
check_resolver_bins
|
||||||
if [[ -z "$ip6" ]]; then
|
if [[ -z "$ip6" ]]; then
|
||||||
if [[ "$NODE" == *.local ]]; then
|
if [[ "$NODE" == *.local ]]; then
|
||||||
|
@ -16543,10 +16747,10 @@ get_aaaa_record() {
|
||||||
else
|
else
|
||||||
fatal "Local hostname given but no 'avahi-resolve' or 'dig' available." $ERR_DNSBIN
|
fatal "Local hostname given but no 'avahi-resolve' or 'dig' available." $ERR_DNSBIN
|
||||||
fi
|
fi
|
||||||
|
elif type -p dig &> /dev/null; then
|
||||||
|
ip6=$(filter_ip6_address $(dig +short +timeout=2 +tries=2 -t aaaa "$1" 2>/dev/null | awk '/^[0-9]/'))
|
||||||
elif type -p host &> /dev/null ; then
|
elif type -p host &> /dev/null ; then
|
||||||
ip6=$(filter_ip6_address $(host -t aaaa "$1" | awk '/address/ { print $NF }'))
|
ip6=$(filter_ip6_address $(host -t aaaa "$1" | awk '/address/ { print $NF }'))
|
||||||
elif type -p dig &> /dev/null; then
|
|
||||||
ip6=$(filter_ip6_address $(dig +short -t aaaa "$1" 2>/dev/null | awk '/^[0-9]/'))
|
|
||||||
elif type -p drill &> /dev/null; then
|
elif type -p drill &> /dev/null; then
|
||||||
ip6=$(filter_ip6_address $(drill aaaa "$1" | awk '/ANSWER SECTION/,/AUTHORITY SECTION/ { print $NF }' | awk '/^[0-9]/'))
|
ip6=$(filter_ip6_address $(drill aaaa "$1" | awk '/ANSWER SECTION/,/AUTHORITY SECTION/ { print $NF }' | awk '/^[0-9]/'))
|
||||||
elif type -p nslookup &>/dev/null; then
|
elif type -p nslookup &>/dev/null; then
|
||||||
|
@ -16577,7 +16781,7 @@ get_caa_rr_record() {
|
||||||
OPENSSL_CONF=""
|
OPENSSL_CONF=""
|
||||||
check_resolver_bins
|
check_resolver_bins
|
||||||
if type -p dig &> /dev/null; then
|
if type -p dig &> /dev/null; then
|
||||||
raw_caa="$(dig $1 type257 +short)"
|
raw_caa="$(dig +timeout=3 +tries=3 $1 type257 +short)"
|
||||||
# empty if no CAA record
|
# empty if no CAA record
|
||||||
elif type -p drill &> /dev/null; then
|
elif type -p drill &> /dev/null; then
|
||||||
raw_caa="$(drill $1 type257 | awk '/'"^${1}"'.*CAA/ { print $5,$6,$7 }')"
|
raw_caa="$(drill $1 type257 | awk '/'"^${1}"'.*CAA/ { print $5,$6,$7 }')"
|
||||||
|
@ -16749,7 +16953,8 @@ determine_rdns() {
|
||||||
rDNS=$(dig -x $nodeip @224.0.0.251 -p 5353 +notcp +noall +answer | awk '/PTR/ { print $NF }')
|
rDNS=$(dig -x $nodeip @224.0.0.251 -p 5353 +notcp +noall +answer | awk '/PTR/ { print $NF }')
|
||||||
fi
|
fi
|
||||||
elif type -p dig &> /dev/null; then
|
elif type -p dig &> /dev/null; then
|
||||||
rDNS=$(dig -x $nodeip +noall +answer | awk '/PTR/ { print $NF }') # +short returns also CNAME, e.g. openssl.org
|
# 1+2 should suffice. It's a compromise for if e.g. network is down but we have a docker/localhost server
|
||||||
|
rDNS=$(dig -x $nodeip +timeout=1 +tries=2 +noall +answer | awk '/PTR/ { print $NF }') # +short returns also CNAME, e.g. openssl.org
|
||||||
elif type -p host &> /dev/null; then
|
elif type -p host &> /dev/null; then
|
||||||
rDNS=$(host -t PTR $nodeip 2>/dev/null | awk '/pointer/ { print $NF }')
|
rDNS=$(host -t PTR $nodeip 2>/dev/null | awk '/pointer/ { print $NF }')
|
||||||
elif type -p drill &> /dev/null; then
|
elif type -p drill &> /dev/null; then
|
||||||
|
|
Loading…
Reference in New Issue