#!/bin/bash # Connects to a SSL host for a list of ciphers # Author: Peter Wu # Usage: $0 [host [portbase]] [openssl options] # Defaults for host and portbase are shown below: host=localhost portbase=4430 PSK=12345678 PSK=0102030405060708091011121314151617181920 # assume that openssl options always start with - if [ -n "$1" ] && [[ $1 != -* ]]; then host=$1; shift fi if [ -n "$1" ] && [[ $1 != -* ]]; then portbase=$1; shift if ! [[ $portbase -gt 0 ]] || ! [[ $portbase -le 65535 ]]; then echo "Port must be between 1 and 65535" >&2 exit 1 fi fi s_client_client_random() { awk ' # match Master-Key from SSL Session dump /Master-Key:/{key=$2} # start matching bytes when requested l > 0 { b=1;e=16; if (version == 3) { if(l==3)b=7; if(l==1)e=6; } else if (version == 2) { if(l==4)e=-1; # skip first line if(l==3)b=3; if(l==1)e=2; } for (i = b; i <= e; i++) s=s$i; # at the end, save random value in map r if (l--==1) queued[s] = 1; } # Match TLS 1.2 Random bytes (over three lines) / ClientHello/{version=3;l=3;s=""} # Match SSLv2 Challenge / CLIENT-HELLO$/{version=2;l=4;s=""} # whenever a key and random is available, print it. This allows the random # to be known before the connection is finished. key { for (rnd in queued) { has_random = 1; print "CLIENT_RANDOM", rnd, key delete queued[rnd]; } fflush(); } END { for (rnd in queued) { print "# No master key for random", rnd } # should not be possible since the first thing we sent out is a # ClientHello, but just to be sure... if (!has_random) { if (key) print "# No random found for key", key else print "# No random nor key found" } }' } # When stdin is a TTY, try all ciphers if [ -t 0 ]; then # Use only SSLv3 and TLSv1 ciphers, do not use SSLv2 openssl ciphers -V -tls1 ALL:NULL else # otherwise if not TTY, pass-through (useful for grep) cat fi | awk '# Look for something like ECDHE-RSA-AES256-SHA { for (i = 1; i <= NF; i++) { if ($i ~ /.-./) { print $i; break } } }' | while read cipher; do opts=() case $cipher in *-ECDSA-*) port=$((portbase+1)) ;; ECDH-RSA-*) port=$((portbase+2)) ;; *-DSS-*) port=$((portbase+3)) ;; PSK-*) opts+=(-psk "$PSK") port=$portbase ;; *-RSA-*|*) # assume RSA (includes name like RC4-SHA) port=$portbase ;; esac echo "# Cipher Suite $cipher" # It is expected that the other side closes the connection printf "GET / HTTP/1.0\r\n\r\n" | openssl s_client -connect "$host:$port" -ign_eof -cipher "$cipher" \ -no_comp \ "${opts[@]}" \ -msg "$@" 2>&1 | s_client_client_random done # vim: set et sw=4 ts=4: