mirror of
https://github.com/mozilla/cipherscan.git
synced 2025-05-10 17:03:40 +02:00
Merge d7a7458667
into 74dd82e8ad
This commit is contained in:
commit
f79484c45d
240
cipherscan
240
cipherscan
@ -487,17 +487,67 @@ parse_openssl_output() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flatten_or_join_array_by_char() {
|
||||||
|
# Two or less parameters (join + 0 or 1 value), then no need to join; return the string.
|
||||||
|
if (( $# <= 2 )); then
|
||||||
|
joined_array="$2"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
# Discard the join string (usually ':', could be others).
|
||||||
|
local join_by="$1"
|
||||||
|
shift
|
||||||
|
|
||||||
|
local found_many=''
|
||||||
|
local last_value=''
|
||||||
|
for each_value in "$@"; do
|
||||||
|
if [[ -z $last_value ]]; then
|
||||||
|
# This is the first one, so store it.
|
||||||
|
last_value="$each_value"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [[ $last_value != "$each_value" ]]; then
|
||||||
|
# This one is different, so we found many. Stop checking.
|
||||||
|
found_many=1
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z $found_many ]]; then
|
||||||
|
# We only found one, so emit that.
|
||||||
|
joined_array="$1"
|
||||||
|
return
|
||||||
|
else
|
||||||
|
# We found many, so join them by whatever.
|
||||||
|
join_array_by_char "$join_by" "$@"
|
||||||
|
# joined_array is now set. All done.
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
TLS_VERSIONS_TO_TEST=(
|
||||||
|
'-ssl2'
|
||||||
|
'-ssl3'
|
||||||
|
'-tls1'
|
||||||
|
'-tls1_1'
|
||||||
|
'-tls1_2'
|
||||||
|
)
|
||||||
|
|
||||||
# Connect to a target host with the selected ciphersuite
|
# Connect to a target host with the selected ciphersuite
|
||||||
test_cipher_on_target() {
|
test_cipher_on_target() {
|
||||||
local sslcommand="$*"
|
local sslcommand="$*"
|
||||||
cipher=""
|
cipher=""
|
||||||
local cmnd=""
|
local cmnd=""
|
||||||
protocols=""
|
protocols=()
|
||||||
pfs=""
|
versions=()
|
||||||
previous_cipher=""
|
previous_cipher=""
|
||||||
certificates=""
|
certificates=""
|
||||||
for tls_version in "-ssl2" "-ssl3" "-tls1" "-tls1_1" "-tls1_2"
|
declare -A sigalgs=()
|
||||||
do
|
declare -A pfses=()
|
||||||
|
declare -A tickethints=()
|
||||||
|
declare -A ocspstaples=()
|
||||||
|
declare -A trusteds=()
|
||||||
|
declare -A pubkeys=()
|
||||||
|
for tls_version in "${TLS_VERSIONS_TO_TEST[@]}"; do
|
||||||
# sslv2 client hello doesn't support SNI extension
|
# sslv2 client hello doesn't support SNI extension
|
||||||
# in SSLv3 mode OpenSSL just ignores the setting so it's ok
|
# in SSLv3 mode OpenSSL just ignores the setting so it's ok
|
||||||
# -status exception is ignored in SSLv2, go figure
|
# -status exception is ignored in SSLv2, go figure
|
||||||
@ -602,24 +652,20 @@ test_cipher_on_target() {
|
|||||||
fi
|
fi
|
||||||
# handling of TLSv1.2 only cipher suites
|
# handling of TLSv1.2 only cipher suites
|
||||||
if [[ ! -z "$previous_cipher" ]] && [[ "$previous_cipher" != "$current_cipher" ]] && [[ "$current_cipher" != "0000" ]]; then
|
if [[ ! -z "$previous_cipher" ]] && [[ "$previous_cipher" != "$current_cipher" ]] && [[ "$current_cipher" != "0000" ]]; then
|
||||||
unset protocols
|
protocols=()
|
||||||
fi
|
fi
|
||||||
previous_cipher=$current_cipher
|
previous_cipher=$current_cipher
|
||||||
|
|
||||||
# connection succeeded, add TLS version to positive results
|
# connection succeeded, add TLS version to positive results
|
||||||
if [[ -z "$protocols" ]]; then
|
protocols+=("$current_protocol")
|
||||||
protocols=$current_protocol
|
|
||||||
else
|
|
||||||
protocols="$protocols,$current_protocol"
|
|
||||||
fi
|
|
||||||
cipher=$current_cipher
|
cipher=$current_cipher
|
||||||
pfs=$current_pfs
|
[[ -z $current_pfs ]] && current_pfs="None"
|
||||||
[[ -z $pfs ]] && pfs="None"
|
pfses[$current_protocol]="$current_pfs"
|
||||||
pubkey=$current_pubkey
|
pubkeys[$current_protocol]="$current_pubkey"
|
||||||
sigalg=$current_sigalg
|
sigalgs[$current_protocol]="$current_sigalg"
|
||||||
trusted=$current_trusted
|
trusteds[$current_protocol]=$current_trusted
|
||||||
tickethint=$current_tickethint
|
tickethints[$current_protocol]=$current_tickethint
|
||||||
ocspstaple=$current_ocspstaple
|
ocspstaples[$current_protocol]=$current_ocspstaple
|
||||||
certificates="$current_certificates"
|
certificates="$current_certificates"
|
||||||
# grab the cipher and PFS key size
|
# grab the cipher and PFS key size
|
||||||
done
|
done
|
||||||
@ -629,34 +675,146 @@ test_cipher_on_target() {
|
|||||||
verbose "handshake failed, no ciphersuite was returned"
|
verbose "handshake failed, no ciphersuite was returned"
|
||||||
result='ConnectionFailure'
|
result='ConnectionFailure'
|
||||||
return 2
|
return 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Flatten the sigalgs list to a single item if every entry is the same.
|
||||||
|
if (( ${#sigalgs[*]} > 1 )); then
|
||||||
|
local sigalgs_values=()
|
||||||
|
for each_protocol in "${protocols[@]}"; do
|
||||||
|
sigalgs_values+=("${sigalgs[$each_protocol]}")
|
||||||
|
done
|
||||||
|
if [[ $OUTPUTFORMAT == 'json' ]]; then
|
||||||
|
# Don't deduplicate for JSON.
|
||||||
|
join_array_by_char ',' "${sigalgs_values[@]}"
|
||||||
|
else
|
||||||
|
flatten_or_join_array_by_char ',' "${sigalgs_values[@]}"
|
||||||
|
fi
|
||||||
|
sigalg="$joined_array"
|
||||||
|
else
|
||||||
|
# Just extract the one value that's present and use it.
|
||||||
|
sigalg="${sigalgs[@]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Flatten the pfses list to a single item if every entry is the same.
|
||||||
|
if (( ${#pfses[*]} > 1 )); then
|
||||||
|
local pfses_values=()
|
||||||
|
for each_protocol in "${protocols[@]}"; do
|
||||||
|
pfses_values+=("${pfses[$each_protocol]}")
|
||||||
|
done
|
||||||
|
if [[ $OUTPUTFORMAT == 'json' ]]; then
|
||||||
|
# Don't deduplicate for JSON.
|
||||||
|
join_array_by_char ';' "${pfses_values[@]}"
|
||||||
|
else
|
||||||
|
flatten_or_join_array_by_char ';' "${pfses_values[@]}"
|
||||||
|
fi
|
||||||
|
pfs="$joined_array"
|
||||||
|
else
|
||||||
|
# Just extract the one value that's present and use it.
|
||||||
|
pfs="${pfses[@]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Flatten the tickethints list to a single item if every entry is the same.
|
||||||
|
if (( ${#tickethints[*]} > 1 )); then
|
||||||
|
local tickethints_values=()
|
||||||
|
for each_protocol in "${protocols[@]}"; do
|
||||||
|
tickethints_values+=("${tickethints[$each_protocol]}")
|
||||||
|
done
|
||||||
|
if [[ $OUTPUTFORMAT == 'json' ]]; then
|
||||||
|
# Don't deduplicate for JSON.
|
||||||
|
join_array_by_char ',' "${tickethints_values[@]}"
|
||||||
|
else
|
||||||
|
flatten_or_join_array_by_char ',' "${tickethints_values[@]}"
|
||||||
|
fi
|
||||||
|
tickethint="$joined_array"
|
||||||
|
else
|
||||||
|
# Just extract the one value that's present and use it.
|
||||||
|
tickethint="${tickethints[@]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Flatten the ocspstaples list to a single item if every entry is the same.
|
||||||
|
if (( ${#ocspstaples[*]} > 1 )); then
|
||||||
|
local ocspstaples_values=()
|
||||||
|
for each_protocol in "${protocols[@]}"; do
|
||||||
|
ocspstaples_values+=("${ocspstaples[$each_protocol]}")
|
||||||
|
done
|
||||||
|
if [[ $OUTPUTFORMAT == 'json' ]]; then
|
||||||
|
# Don't deduplicate for JSON.
|
||||||
|
join_array_by_char ',' "${ocspstaples_values[@]}"
|
||||||
|
else
|
||||||
|
flatten_or_join_array_by_char ',' "${ocspstaples_values[@]}"
|
||||||
|
fi
|
||||||
|
ocspstaple="$joined_array"
|
||||||
|
else
|
||||||
|
# Just extract the one value that's present and use it.
|
||||||
|
ocspstaple="${ocspstaples[@]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Flatten the trusteds list to a single item if every entry is the same.
|
||||||
|
if (( ${#trusteds[*]} > 1 )); then
|
||||||
|
local trusteds_values=()
|
||||||
|
for each_protocol in "${protocols[@]}"; do
|
||||||
|
trusteds_values+=("${trusteds[$each_protocol]}")
|
||||||
|
done
|
||||||
|
if [[ $OUTPUTFORMAT == 'json' ]]; then
|
||||||
|
# Don't deduplicate for JSON.
|
||||||
|
join_array_by_char ',' "${trusteds_values[@]}"
|
||||||
|
else
|
||||||
|
flatten_or_join_array_by_char ',' "${trusteds_values[@]}"
|
||||||
|
fi
|
||||||
|
trusted="$joined_array"
|
||||||
|
else
|
||||||
|
# Just extract the one value that's present and use it.
|
||||||
|
trusted="${trusteds[@]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Flatten the pubkeys list to a single item if every entry is the same.
|
||||||
|
if (( ${#pubkeys[*]} > 1 )); then
|
||||||
|
local pubkeys_values=()
|
||||||
|
for each_protocol in "${protocols[@]}"; do
|
||||||
|
pubkeys_values+=("${pubkeys[$each_protocol]}")
|
||||||
|
done
|
||||||
|
if [[ $OUTPUTFORMAT == 'json' ]]; then
|
||||||
|
# Don't deduplicate for JSON.
|
||||||
|
join_array_by_char ',' "${pubkeys_values[@]}"
|
||||||
|
else
|
||||||
|
flatten_or_join_array_by_char ',' "${pubkeys_values[@]}"
|
||||||
|
fi
|
||||||
|
pubkey="$joined_array"
|
||||||
|
else
|
||||||
|
# Just extract the one value that's present and use it.
|
||||||
|
pubkey="${pubkeys[@]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Pre-join this, since we use it in a couple of places below.
|
||||||
|
join_array_by_char ',' "${protocols[@]}"
|
||||||
|
protocols_csv="$joined_array"
|
||||||
|
|
||||||
# if cipher contains NONE, the cipher wasn't accepted
|
# if cipher contains NONE, the cipher wasn't accepted
|
||||||
elif [[ "$cipher" == '(NONE) ' ]]; then
|
if [[ "$cipher" == '(NONE) ' ]]; then
|
||||||
result="$cipher $protocols $pubkey $sigalg $trusted $tickethint $ocspstaple $pfs $current_curves $curves_ordering"
|
result="$cipher $protocols_csv $pubkey $sigalg $trusted $tickethint $ocspstaple $pfs $current_curves $curves_ordering"
|
||||||
verbose "handshake failed, server returned ciphersuite '$result'"
|
verbose "handshake failed, server returned ciphersuite '$result'"
|
||||||
return 1
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
# the connection succeeded
|
# the connection succeeded
|
||||||
else
|
current_curves="None"
|
||||||
current_curves="None"
|
# if pfs uses ECDH, test supported curves
|
||||||
# if pfs uses ECDH, test supported curves
|
if [[ $pfs =~ ECDH ]]; then
|
||||||
if [[ $pfs =~ ECDH ]]; then
|
has_curves="True"
|
||||||
has_curves="True"
|
if [[ $TEST_CURVES == "True" ]]; then
|
||||||
if [[ $TEST_CURVES == "True" ]]; then
|
test_curves
|
||||||
test_curves
|
if [[ -n $ecc_ciphers ]]; then
|
||||||
if [[ -n $ecc_ciphers ]]; then
|
ecc_ciphers+=":"
|
||||||
ecc_ciphers+=":"
|
|
||||||
fi
|
|
||||||
ecc_ciphers+="$cipher"
|
|
||||||
else
|
|
||||||
# resolve the openssl curve to the proper IANA name
|
|
||||||
current_curves="$(get_curve_name "$(echo $pfs|cut -d ',' -f2)")"
|
|
||||||
fi
|
fi
|
||||||
|
ecc_ciphers+="$cipher"
|
||||||
|
else
|
||||||
|
# resolve the openssl curve to the proper IANA name
|
||||||
|
current_curves="$(get_curve_name "$(echo $pfs|cut -d ',' -f2)")"
|
||||||
fi
|
fi
|
||||||
result="$cipher $protocols $pubkey $sigalg $trusted $tickethint $ocspstaple $pfs $current_curves $curves_ordering"
|
|
||||||
verbose "handshake succeeded, server returned ciphersuite '$result'"
|
|
||||||
return 0
|
|
||||||
fi
|
fi
|
||||||
|
result="$cipher $protocols_csv $pubkey $sigalg $trusted $tickethint $ocspstaple $pfs $current_curves $curves_ordering"
|
||||||
|
verbose "handshake succeeded, server returned ciphersuite '$result'"
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# Calculate the average handshake time for a specific ciphersuite
|
# Calculate the average handshake time for a specific ciphersuite
|
||||||
@ -978,15 +1136,13 @@ display_results_in_json() {
|
|||||||
echo -n "\"protocols\":[\"${cipher_arr[1]//,/\",\"}\"],"
|
echo -n "\"protocols\":[\"${cipher_arr[1]//,/\",\"}\"],"
|
||||||
echo -n "\"pubkey\":[\"${cipher_arr[2]//,/\",\"}\"],"
|
echo -n "\"pubkey\":[\"${cipher_arr[2]//,/\",\"}\"],"
|
||||||
echo -n "\"sigalg\":[\"${cipher_arr[3]//,/\",\"}\"],"
|
echo -n "\"sigalg\":[\"${cipher_arr[3]//,/\",\"}\"],"
|
||||||
echo -n "\"trusted\":\"${cipher_arr[4]//,/\",\"}\","
|
echo -n "\"trusted\":[\"${cipher_arr[4]//,/\",\"}\"],"
|
||||||
if [[ -n $CAPATH ]]; then
|
if [[ -n $CAPATH ]]; then
|
||||||
echo -n "\"certificates\":[${ciphercertificates[$ctr]}],"
|
echo -n "\"certificates\":[${ciphercertificates[$ctr]}],"
|
||||||
fi
|
fi
|
||||||
echo -n "\"ticket_hint\":\"${cipher_arr[5]}\","
|
echo -n "\"ticket_hint\":[\"${cipher_arr[5]//,/\",\"}\"],"
|
||||||
echo -n "\"ocsp_stapling\":\"${cipher_arr[6]}\","
|
echo -n "\"ocsp_stapling\":[\"${cipher_arr[6]//,/\",\"}\"],"
|
||||||
pfs="${cipher_arr[7]}"
|
echo -n "\"pfs\":[\"${cipher_arr[7]//\;/\",\"}\"]"
|
||||||
[[ -z $pfs ]] && pfs="None"
|
|
||||||
echo -n "\"pfs\":\"$pfs\""
|
|
||||||
if [[ "${cipher_arr[0]}" =~ ECDH ]]; then
|
if [[ "${cipher_arr[0]}" =~ ECDH ]]; then
|
||||||
echo -n ","
|
echo -n ","
|
||||||
echo -n "\"curves\":[\"${cipher_arr[8]//,/\",\"}\"]"
|
echo -n "\"curves\":[\"${cipher_arr[8]//,/\",\"}\"]"
|
||||||
|
Loading…
Reference in New Issue
Block a user