blob: ee4cd888ea570439d64097747ccaa118a3bad358 (
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
150
|
X509_SHA256="$(doveconf -c "$HOME_remote/.dovecot/config" -hx ssl_cert \
| openssl x509 -in /dev/stdin -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 -in /dev/stdin -pubkey \
| openssl pkey -in /dev/stdin -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=bash :
|