aboutsummaryrefslogtreecommitdiffstats
path: root/tests/tls-verify-peer/t
blob: 8326521bdd2b5204a8677eb3b404a99ed5c320d7 (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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
X509_SHA256="$(doveconf -c "$HOME_remote/.dovecot/config" -hx ssl_cert \
    | openssl x509 -noout -fingerprint -sha256 \
    | sed -rn "/^.*=\\s*/ {s///p;q}" | tr -d : | tr "[A-Z]" "[a-z]")"
PKEY_SHA256="$(doveconf -c "$HOME_remote/.dovecot/config" -hx ssl_cert \
    | openssl x509 -pubkey | openssl pkey -pubin -outform DER \
    | openssl dgst -sha256 | sed -rn "/^.*=\\s*/ {s///p;q}")"

unverified_peer() {
    ! interimap --debug || error

    # make sure we aborted the handshake immediately after connecting
    grep -Fx "remote: Peer certificate fingerprint: sha256\$$X509_SHA256" <"$STDERR" || error
    grep -Fx "remote: ERROR: Can't initiate TLS/SSL handshake" <"$STDERR" || error
    sed -nr "s/remote: \[[0-9]+\] (preverify=[0-9]+)$/\1/p" <"$STDERR" >"$TMPDIR/preverify"
    [ -s "$TMPDIR/preverify" ] || error
    ! grep -Fvx "preverify=0" <"$TMPDIR/preverify" || error

    # make sure we didn't send any credentials or started speaking IMAP
    ! grep -E "^remote: C: .* (AUTHENTICATE|LOGIN) " <"$STDERR" || error
    grep -Fx "remote: IMAP traffic (bytes): recv 0 sent 0" <"$STDERR" || error
}
verified_peer() {
    local i u
    for ((i = 0; i < 4; i++)); do
        u="$(shuf -n1 -e "local" "remote")"
        sample_message | deliver -u "$u"
    done
    interimap --debug || error

    grep -Fx "remote: Peer certificate fingerprint: sha256\$$X509_SHA256" <"$STDERR" || error
    sed -nr "s/remote: \[[0-9]+\] (preverify=[0-9]+)$/\1/p" <"$STDERR" >"$TMPDIR/preverify"
    [ -s "$TMPDIR/preverify" ] || error
    ! grep -Fvx "preverify=1" <"$TMPDIR/preverify" || error

    grep "^remote: SSL protocol: TLSv" <"$STDERR" || error
    grep "^remote: SSL cipher: " <"$STDERR" || error

    check_mailbox_status "INBOX"
}

# backup config
install -m0600 -- "$XDG_CONFIG_HOME/interimap/config" "$XDG_CONFIG_HOME/interimap/config~"
with_remote_config() {
    install -m0600 -- "$XDG_CONFIG_HOME/interimap/config~" "$XDG_CONFIG_HOME/interimap/config"
    cat >>"$XDG_CONFIG_HOME/interimap/config"
}

step_start "peer verification enabled by default"
# assume our fake root CA is not among OpenSSL's default trusted CAs
unverified_peer
grep -Fx "remote: Using default locations for trusted CA certificates" <"$STDERR" || error
step_done

step_start "peer verification result honored when pinned pubkey matches"
with_remote_config <<-EOF
	SSL_fingerprint = sha256\$$PKEY_SHA256
EOF
unverified_peer
grep -Fx "remote: Using default locations for trusted CA certificates" <"$STDERR" || error
grep -Fx "remote: Peer certificate matches pinned SPKI digest sha256\$$PKEY_SHA256" <"$STDERR" || error
step_done


capath=$(mktemp --tmpdir="$TMPDIR" --directory capath.XXXXXX)
cp -T -- ~/.dovecot/conf.d/ca.crt "$capath/ca-certificates.crt"

step_start "SSL_CAfile/\$SSL_CERT_FILE"

# verify that an error is raised when CAfile can't be loaded
# (it's not the case for $SSL_CERT_FILE, cf. SSL_CTX_load_verify_locations(3ssl))
with_remote_config <<<"SSL_CAfile = /nonexistent"
! interimap --debug || error
grep -Fx "remote: ERROR: SSL_CTX_load_verify_locations()" <"$STDERR" || error
grep -Fx "remote: IMAP traffic (bytes): recv 0 sent 0" <"$STDERR" || error

if [ -f "/etc/ssl/certs/ca-certificates.crt" ]; then
    # assume our fake root CA is not there
    with_remote_config <<<"SSL_CAfile = /etc/ssl/certs/ca-certificates.crt"
    unverified_peer
fi

# default host (localhost) is the CN (and also subjectAltName)
with_remote_config <<<"SSL_CAfile = $capath/ca-certificates.crt"
verified_peer

with_remote_config </dev/null
SSL_CERT_FILE=~/.dovecot/conf.d/ca.crt verified_peer
grep -Fx "remote: Using default locations for trusted CA certificates" <"$STDERR" || error

# hostnames and IPs included in the subjectAltName should work as well
for host in "ip6-localhost" "127.0.0.1" "::1"; do
    with_remote_config <<-EOF
		host = $host
		SSL_CAfile = $capath/ca-certificates.crt
	EOF
    verified_peer
done

# but not for other hostnames or IPs
for host in "ip6-loopback" "127.0.1.1"; do
    with_remote_config <<-EOF
		host = $host
		SSL_CAfile = $capath/ca-certificates.crt
	EOF
    unverified_peer
done

step_done


step_start "SSL_CApath/\$SSL_CERT_DIR"

if [ -d "/etc/ssl/certs" ]; then
    # assume our fake root CA is not there
    with_remote_config <<<"SSL_CApath = /etc/ssl/certs"
    unverified_peer
fi

c_rehash "$capath"

# default host (localhost) is the CN (and also subjectAltName)
with_remote_config <<<"SSL_CApath = $capath"
verified_peer

with_remote_config </dev/null
SSL_CERT_DIR="$capath" verified_peer
grep -Fx "remote: Using default locations for trusted CA certificates" <"$STDERR" || error

# hostnames and IPs included in the subjectAltName should work as well
for host in "ip6-localhost" "127.0.0.1" "::1"; do
    with_remote_config <<-EOF
		host = $host
		SSL_CApath = $capath
	EOF
    verified_peer
done

# but not for other IPs or hostnames
for host in "ip6-loopback" "127.0.1.1"; do
    with_remote_config <<-EOF
		host = $host
		SSL_CApath = $capath
	EOF
    unverified_peer
done

step_done

# vim: set filetype=sh :