summaryrefslogtreecommitdiff
path: root/openssl-connect
blob: 77ba857a6f3324b67693630003515e9c5110f1b1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#!/bin/bash
# Connects to a SSL host for a list of ciphers
# Author: Peter Wu <lekensteyn@gmail.com>

# 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: