From 17b263c49df682fc45f0e50cceb01db4366ad9a7 Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Thu, 10 Dec 2020 14:28:29 +0100 Subject: libinterimap: show the matching pinned SPKI in --debug mode. --- tests/tls-pin-fingerprint/t | 9 ++++++--- tests/tls-rsa+ecdsa/t | 7 ++++++- tests/tls-verify-peer/t | 2 +- 3 files changed, 13 insertions(+), 5 deletions(-) (limited to 'tests') diff --git a/tests/tls-pin-fingerprint/t b/tests/tls-pin-fingerprint/t index d3830e2..6716833 100644 --- a/tests/tls-pin-fingerprint/t +++ b/tests/tls-pin-fingerprint/t @@ -28,7 +28,8 @@ check_mailbox_status "INBOX" with_remote_config <<-EOF SSL_fingerprint = $INVALID_FPR $PKEY_SHA256 EOF -interimap || error +interimap --debug || error +grep -Fx "remote: Peer certificate matches pinned SPKI digest sha256\$$PKEY_SHA256" <"$STDERR" || error # and now an invalid one @@ -60,13 +61,15 @@ grep -Fx "remote: ERROR: Can't initiate TLS/SSL handshake" <"$STDERR" || error with_remote_config <<-EOF SSL_fingerprint = sha256\$$PKEY_SHA256 $INVALID_FPR EOF -interimap || error +interimap --debug || error +grep -Fx "remote: Peer certificate matches pinned SPKI digest sha256\$$PKEY_SHA256" <"$STDERR" || error # invalid + valid with_remote_config <<-EOF SSL_fingerprint = $INVALID_FPR sha256\$$PKEY_SHA256 EOF -interimap || error +interimap --debug || error +grep -Fx "remote: Peer certificate matches pinned SPKI digest sha256\$$PKEY_SHA256" <"$STDERR" || error # vim: set filetype=sh : diff --git a/tests/tls-rsa+ecdsa/t b/tests/tls-rsa+ecdsa/t index 29352e9..2adf930 100644 --- a/tests/tls-rsa+ecdsa/t +++ b/tests/tls-rsa+ecdsa/t @@ -32,6 +32,9 @@ interimap --debug || error grep -Fx -e "remote: Peer certificate fingerprint: sha256\$$X509_SHA256" \ -e "remote: Peer certificate fingerprint: sha256\$$X509_ALT_SHA256" \ <"$STDERR" || error +grep -Fx -e "remote: Peer certificate matches pinned SPKI digest sha256\$$PKEY_SHA256" \ + -e "remote: Peer certificate matches pinned SPKI digest sha256\$$PKEY_ALT_SHA256" \ + <"$STDERR" || error # force RSA (XXX do we really have to force TLSv1.2 here?) cat >>"$XDG_CONFIG_HOME/interimap/config" <<-EOF @@ -40,10 +43,12 @@ cat >>"$XDG_CONFIG_HOME/interimap/config" <<-EOF EOF interimap --debug || error grep -Fx "remote: Peer certificate fingerprint: sha256\$$X509_SHA256" <"$STDERR" || error +grep -Fx "remote: Peer certificate matches pinned SPKI digest sha256\$$PKEY_SHA256" <"$STDERR" || error # force ECDSA -sed -i "s/^SSL_cipherlist\\s*=.*/SSL_cipherlist = EECDH+AESGCM+aECDSA/" "$XDG_CONFIG_HOME/interimap/config" +sed -i "s/^SSL_cipherlist\\s*=.*/SSL_cipherlist = EECDH+AESGCM+aECDSA/" -- "$XDG_CONFIG_HOME/interimap/config" interimap --debug || error grep -Fx "remote: Peer certificate fingerprint: sha256\$$X509_ALT_SHA256" <"$STDERR" || error +grep -Fx "remote: Peer certificate matches pinned SPKI digest sha256\$$PKEY_ALT_SHA256" <"$STDERR" || error # vim: set filetype=sh : diff --git a/tests/tls-verify-peer/t b/tests/tls-verify-peer/t index 9e4d9fa..35c7c8d 100644 --- a/tests/tls-verify-peer/t +++ b/tests/tls-verify-peer/t @@ -46,7 +46,7 @@ with_remote_config <<-EOF SSL_fingerprint = sha256\$$PKEY_SHA256 EOF unverified_peer -! grep -Fx "remote: WARNING: Fingerprint doesn't match! MiTM in action?" <"$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) -- cgit v1.2.3 From 26e5c04abfb81bdcbd4d89d9f9329b8433920b26 Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Thu, 10 Dec 2020 14:34:48 +0100 Subject: test suite: always generate new certificates on `make test`. In addition, sign test certificates with the same root CA. Hence running `make test` now requires OpenSSL 1.1.1 or later. --- tests/certs/.gitignore | 4 ++++ tests/certs/generate | 38 ++++++++++++++++++++++++++++++++ tests/run | 1 + tests/snippets/dovecot/dovecot.ecdsa.crt | 11 --------- tests/snippets/dovecot/dovecot.ecdsa.key | 5 ----- tests/snippets/dovecot/dovecot.rsa.crt | 19 ---------------- tests/snippets/dovecot/dovecot.rsa.key | 28 ----------------------- tests/tls-verify-peer/t | 10 ++++----- 8 files changed, 48 insertions(+), 68 deletions(-) create mode 100644 tests/certs/.gitignore create mode 100755 tests/certs/generate delete mode 100644 tests/snippets/dovecot/dovecot.ecdsa.crt delete mode 100644 tests/snippets/dovecot/dovecot.ecdsa.key delete mode 100644 tests/snippets/dovecot/dovecot.rsa.crt delete mode 100644 tests/snippets/dovecot/dovecot.rsa.key (limited to 'tests') diff --git a/tests/certs/.gitignore b/tests/certs/.gitignore new file mode 100644 index 0000000..8b2d0ad --- /dev/null +++ b/tests/certs/.gitignore @@ -0,0 +1,4 @@ +!/generate +/*.key +/*.crt +/*.pem diff --git a/tests/certs/generate b/tests/certs/generate new file mode 100755 index 0000000..19463d5 --- /dev/null +++ b/tests/certs/generate @@ -0,0 +1,38 @@ +#!/bin/sh + +set -ue +PATH="/usr/bin:/bin" +export PATH + +BASEDIR="$(dirname -- "$0")" +OU="InterIMAP test suite" +cd "$BASEDIR" + +cadir="$(mktemp --tmpdir --directory)" +trap 'rm -rf -- "$cadir"' EXIT INT TERM + +# generate CA (we intentionally throw away the private key and serial +# file to avoid reuse) +openssl genpkey -algorithm RSA -out "$cadir/ca.key" +openssl req -new -x509 -rand /dev/urandom -subj "/OU=$OU/CN=Fake Root CA" -key "$cadir/ca.key" -out ./ca.crt + +SERIAL=1 +new() { + local key="$1" cn="$2" + openssl req -new -rand /dev/urandom -key "$key" \ + -subj "/OU=$OU/CN=$cn" \ + -out "$cadir/new.csr" + cat >"$cadir/new-ext.cnf" <<-EOF + basicConstraints = critical, CA:FALSE + keyUsage = critical, digitalSignature, keyEncipherment + extendedKeyUsage = critical, serverAuth + EOF + openssl x509 -req -in "$cadir/new.csr" -CA ./ca.crt -CAkey "$cadir/ca.key" \ + -CAserial "$cadir/ca.srl" -CAcreateserial -extfile "$cadir/new-ext.cnf" +} + +openssl genpkey -algorithm RSA -out ./dovecot.rsa.key +new ./dovecot.rsa.key "localhost" >./dovecot.rsa.crt + +openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -pkeyopt ec_param_enc:named_curve -out ./dovecot.ecdsa.key +new ./dovecot.ecdsa.key "localhost" >./dovecot.ecdsa.crt diff --git a/tests/run b/tests/run index 8164524..0305812 100755 --- a/tests/run +++ b/tests/run @@ -102,6 +102,7 @@ prepare() { cat >>"$home/.dovecot/config" <"$TESTDIR/$u.conf" fi cp -aT -- "$BASEDIR/snippets/dovecot" "$home/.dovecot/conf.d" + cp -at "$home/.dovecot/conf.d" -- "$BASEDIR/certs/ca.crt" "$BASEDIR/certs"/dovecot.* proto="$(env -i "${ENVIRON[@]}" doveconf -c "$home/.dovecot/config" -h protocols)" if [ -n "$proto" ]; then diff --git a/tests/snippets/dovecot/dovecot.ecdsa.crt b/tests/snippets/dovecot/dovecot.ecdsa.crt deleted file mode 100644 index b928d4d..0000000 --- a/tests/snippets/dovecot/dovecot.ecdsa.crt +++ /dev/null @@ -1,11 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIBkjCCATmgAwIBAgIUWyEAqMhQ0uRLtagXgm68bUypQa4wCgYIKoZIzj0EAwIw -HzEdMBsGA1UEAwwUSW50ZXJJTUFQIHRlc3Qgc3VpdGUwHhcNMjAxMjA5MTQwOTUy -WhcNMzAxMjA3MTQwOTUyWjAfMR0wGwYDVQQDDBRJbnRlcklNQVAgdGVzdCBzdWl0 -ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABFP7A0ivFsHK/WuCQzz+WWh2jBLO -7uqhWSMh+1cc//jmn2q910XNH3xVFNkIRo7ddg6X8twli3OvC66/YIbxiTyjUzBR -MB0GA1UdDgQWBBS/p0mJpdBjKpNrQ/t+oJMrehS7wzAfBgNVHSMEGDAWgBS/p0mJ -pdBjKpNrQ/t+oJMrehS7wzAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0cA -MEQCIFMlTb7E92tElIueK8TxbllJ3NOaMb1TMjSScM38N8oOAiAiNI4AkESnimPN -IOsdnydFYjOkDEhzpXbrBEcP3EgJuQ== ------END CERTIFICATE----- diff --git a/tests/snippets/dovecot/dovecot.ecdsa.key b/tests/snippets/dovecot/dovecot.ecdsa.key deleted file mode 100644 index dfbd4a7..0000000 --- a/tests/snippets/dovecot/dovecot.ecdsa.key +++ /dev/null @@ -1,5 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgleLchaikcJbUnkps -4ITR6FGkW2S2+S+w2ISJSsvgt0ehRANCAART+wNIrxbByv1rgkM8/llodowSzu7q -oVkjIftXHP/45p9qvddFzR98VRTZCEaO3XYOl/LcJYtzrwuuv2CG8Yk8 ------END PRIVATE KEY----- diff --git a/tests/snippets/dovecot/dovecot.rsa.crt b/tests/snippets/dovecot/dovecot.rsa.crt deleted file mode 100644 index d10204b..0000000 --- a/tests/snippets/dovecot/dovecot.rsa.crt +++ /dev/null @@ -1,19 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDHzCCAgegAwIBAgIUKSm5of13M/4NiGfhLMspFl/+YmYwDQYJKoZIhvcNAQEL -BQAwHzEdMBsGA1UEAwwUSW50ZXJJTUFQIHRlc3Qgc3VpdGUwHhcNMjAxMjA5MTM1 -NjI1WhcNMzAxMjA3MTM1NjI1WjAfMR0wGwYDVQQDDBRJbnRlcklNQVAgdGVzdCBz -dWl0ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM1DTaSl/4UtngRG -bAHmxHlNFZJxQVK9AM4tcYna1PGrY/JbmS5kKVFLSM6znHD5aBvTaOy0HLpF15wY -Vj+zbaWmgqtlKGYGSGoXcTzNYFNJNB/WNhOv25q5VHNNFePTX/zOgQS8geza7qrK -MZDiMlbuGKCQSKtZqKiEGiMWIyXtVi8BkkHXcTrvDggOTCQlk/0v8dWbGFZZA9ly -f7PIdxtfm6tacw6Fxcz4ukWx2uoEjOIyOYhgd4WYdM7L9Jnabrh9OHYknuiGZv38 -b2GUZZ0h0RtkcdP1zOxaz4ZTaewo+gLm6yTFsL3mhnNsK/xxx00/QE6C9OyU0Nip -gGmpT9ECAwEAAaNTMFEwHQYDVR0OBBYEFHlctzGj8GhUJ8GrlHb0mT7DR/mEMB8G -A1UdIwQYMBaAFHlctzGj8GhUJ8GrlHb0mT7DR/mEMA8GA1UdEwEB/wQFMAMBAf8w -DQYJKoZIhvcNAQELBQADggEBAJ/FGOVrBmYujPk2ZzJHJZE/+7+upZndrUA+27l7 -u/bHxhLnl94gfGmOaflU+Zyy/9eqLzllY40wkMT6d/SQmfv4C6d+fqk/dDPfdLdk -N3ew/q/sPvLuEyoj1QoHamWqc3dfgV6p5j4ek6kjyWtjBPcQbVOZ02Xes1GSLzVJ -Yo9kfbZxk4Y2mqiBDHCM+erNkG002D7cWErjj/fqhYlnjOxU+v9FEm0gLc3VqAkE -BRuYZbmyMJUklH00R39G2Fey34kcpaB1VCMOLsymWLkZEhfgrl2qPRwGyh+Wc8N5 -gR/w97oHDOfJ2oZRzjRUB7MIhGoY0ED42Ma44Ub4al57XbY= ------END CERTIFICATE----- diff --git a/tests/snippets/dovecot/dovecot.rsa.key b/tests/snippets/dovecot/dovecot.rsa.key deleted file mode 100644 index ed77230..0000000 --- a/tests/snippets/dovecot/dovecot.rsa.key +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDNQ02kpf+FLZ4E -RmwB5sR5TRWScUFSvQDOLXGJ2tTxq2PyW5kuZClRS0jOs5xw+Wgb02jstBy6Rdec -GFY/s22lpoKrZShmBkhqF3E8zWBTSTQf1jYTr9uauVRzTRXj01/8zoEEvIHs2u6q -yjGQ4jJW7higkEirWaiohBojFiMl7VYvAZJB13E67w4IDkwkJZP9L/HVmxhWWQPZ -cn+zyHcbX5urWnMOhcXM+LpFsdrqBIziMjmIYHeFmHTOy/SZ2m64fTh2JJ7ohmb9 -/G9hlGWdIdEbZHHT9czsWs+GU2nsKPoC5uskxbC95oZzbCv8ccdNP0BOgvTslNDY -qYBpqU/RAgMBAAECggEANzx5VGlnTYttDnF09z4GeS4JNBNOJNm/sbwA5bwBudcJ -WlrT6ewCQmIkAZvL6Yr0PSiy/5+oa2gIEXVrIFFEnGMmnsDmEi52pjYQvu/1j/QP -FtIqUznrusNMuopv7ZMgLYPUrFWeEQMJXuRyWi7EpSgFcI/jPlkuTcrezbpTUw0D -bNAQjgXiDGNzyJDVmx496CWtTJHE94wwKo2QAiFU7zCZcqM7JlNCnRenws4KGqJ1 -qyFeCJJlgORQDMpiqaJLMreF41WPs++Xsu07RzQdmFKaS/sX4Um/5uyhlApmxepR -cwx3RYvOtGArQKreNONn5j16O012DSbFXIyrUjJgAQKBgQD48iZmm2iiq4oC1u+/ -kYPXMHjUBHeMj8D3lA2mnCh4W/vcEj+ZBFgmR90KyYkK2eDuFslvfwzxZqU3sqJE -au4OsITsSrxhJHAz4pVWPlJiWUCrz/7ektxY6Jw2+Jk8lR3UvLMgJbKpLWkd5Od+ -h5xKNU5Xzu198yX703k4+v5rgQKBgQDTFEcIJK9BffQ5hqMiM7NujdbMQ4ldxUy+ -ivyHk4MX4Z/kequE1rMJ1Ap8hypPJz10NhXM2naQWa8APnFYkNygwbtwTSZaiyMY -Tav8rjYoA0CfEsPfIx2AFPtDtrhWGH5o9LZI9sjhH79ud412IDZxSGdZmAho8Xdj -ky5sQr9MUQKBgByF+jplcg65Yt3CbMPhU17TkfSQ8nWrfuufDhVZ7RUlTO1BNgI9 -SjBQqZXz03zny+rbt4bL4trB7Qo9sHPwYIhUV1aPlZf3yddYDc5M47mbClrlQQmV -gCO7uzJdN4mGeF2IpWl4iEj0CAhB0vhfZ1vlUa2j6vg0ZNS+vTP3JjGBAoGAQ+gW -IgyLRWqcE5W5DdvMMhj3radcngpHclWMgKF4X0p7Aipk28umtda9uOpTNjvNjYGI -6equkioIHu/3zyJrmFw7TRnE6QQyOjNizVvOmHjTZVnIIhVN/FLDszkpfKlMob94 -lWivn51zHLrhi8s5OKCufyhmLDzix+ol2TZwDMECgYEAwjhuZRXZeIgjKkvkG+FT -8ThPNcxSplNca+YM9fQuWAuKkCbKCtvl8m5HDWYYIDx1jkKGHvDGtUl7vV4TtCgJ -OeCQPjT5SLYs9ienMqitbzKfvCGRNsIG/1NsUrerD0Lau+V0YmbqYYk1Pptr3R8x -bLzY7IMbPzdI+aPyhNF9KSg= ------END PRIVATE KEY----- diff --git a/tests/tls-verify-peer/t b/tests/tls-verify-peer/t index 35c7c8d..9b676a6 100644 --- a/tests/tls-verify-peer/t +++ b/tests/tls-verify-peer/t @@ -28,9 +28,9 @@ verified_peer() { } # backup config -install -m0600 "$XDG_CONFIG_HOME/interimap/config" "$XDG_CONFIG_HOME/interimap/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" + install -m0600 -- "$XDG_CONFIG_HOME/interimap/config~" "$XDG_CONFIG_HOME/interimap/config" cat >>"$XDG_CONFIG_HOME/interimap/config" } @@ -53,12 +53,12 @@ capath=$(mktemp --tmpdir="$TMPDIR" --directory capath.XXXXXX) step_start "SSL_CAfile" if [ -f "/etc/ssl/certs/ca-certificates.crt" ]; then - # our self-signed test cert should not be in there + # our fake root CA should not be in there with_remote_config <<<"SSL_CAfile = /etc/ssl/certs/ca-certificates.crt" unverified_peer fi -doveconf -c "$HOME_remote/.dovecot/config" -hx ssl_cert >"$capath/ca-certificates.crt" +cp -T -- ~/.dovecot/conf.d/ca.crt "$capath/ca-certificates.crt" with_remote_config <<<"SSL_CAfile = $capath/ca-certificates.crt" verified_peer step_done @@ -66,7 +66,7 @@ step_done step_start "SSL_CApath" if [ -d "/etc/ssl/certs" ]; then - # our self-signed test cert should not be in there + # our fake root CA should not be in there with_remote_config <<<"SSL_CApath = /etc/ssl/certs" unverified_peer fi -- cgit v1.2.3 From 265f133600e9812726a52ea3067409ed3578e882 Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Thu, 10 Dec 2020 19:39:10 +0100 Subject: libinterimap: make SSL_verify check the hostname as well. More precisely, ensure that the certificate Subject Alternative Name (SAN) or Subject CommonName (CN) matches the hostname or IP literal specified by the 'host' option. Previously it was only verifying the chain of trust. This bumps the minimum Net::SSLeay version to 1.83 and OpenSSL version 1.0.2. --- tests/certs/generate | 7 ++-- tests/run | 2 +- tests/tls-verify-peer/interimap.remote | 1 - tests/tls-verify-peer/t | 61 ++++++++++++++++++++++++++++++---- 4 files changed, 60 insertions(+), 11 deletions(-) (limited to 'tests') diff --git a/tests/certs/generate b/tests/certs/generate index 19463d5..6457765 100755 --- a/tests/certs/generate +++ b/tests/certs/generate @@ -20,19 +20,22 @@ SERIAL=1 new() { local key="$1" cn="$2" openssl req -new -rand /dev/urandom -key "$key" \ - -subj "/OU=$OU/CN=$cn" \ + -subj "/OU=$OU/CN=$cn" ${3+-addext subjectAltName="$3"} \ -out "$cadir/new.csr" cat >"$cadir/new-ext.cnf" <<-EOF basicConstraints = critical, CA:FALSE keyUsage = critical, digitalSignature, keyEncipherment extendedKeyUsage = critical, serverAuth EOF + if [ -n "${3+x}" ]; then + printf "subjectAltName = %s\\n" "$3" >>"$cadir/new-ext.cnf" + fi openssl x509 -req -in "$cadir/new.csr" -CA ./ca.crt -CAkey "$cadir/ca.key" \ -CAserial "$cadir/ca.srl" -CAcreateserial -extfile "$cadir/new-ext.cnf" } openssl genpkey -algorithm RSA -out ./dovecot.rsa.key -new ./dovecot.rsa.key "localhost" >./dovecot.rsa.crt +new ./dovecot.rsa.key "localhost" "DNS:localhost,DNS:ip6-localhost,IP:127.0.0.1,IP:::1" >./dovecot.rsa.crt openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -pkeyopt ec_param_enc:named_curve -out ./dovecot.ecdsa.key new ./dovecot.ecdsa.key "localhost" >./dovecot.ecdsa.crt diff --git a/tests/run b/tests/run index 0305812..d216591 100755 --- a/tests/run +++ b/tests/run @@ -93,7 +93,7 @@ prepare() { mail_location = dbox:~/inbox:LAYOUT=index mailbox_list_index = yes ssl = no - listen = 127.0.0.1, ::1 + listen = 127.0.0.1, 127.0.1.1, ::1 namespace inbox { inbox = yes } diff --git a/tests/tls-verify-peer/interimap.remote b/tests/tls-verify-peer/interimap.remote index b02fcd0..263655f 100644 --- a/tests/tls-verify-peer/interimap.remote +++ b/tests/tls-verify-peer/interimap.remote @@ -1,2 +1 @@ -host = ::1 port = 10993 diff --git a/tests/tls-verify-peer/t b/tests/tls-verify-peer/t index 9b676a6..2461a1f 100644 --- a/tests/tls-verify-peer/t +++ b/tests/tls-verify-peer/t @@ -1,6 +1,15 @@ +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 @@ -11,12 +20,13 @@ unverified_peer() { } verified_peer() { local i u - for ((i = 0; i < 32; i++)); do + 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 @@ -39,9 +49,6 @@ unverified_peer step_done step_start "peer verification result honored when pinned pubkey matches" -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}")" with_remote_config <<-EOF SSL_fingerprint = sha256\$$PKEY_SHA256 EOF @@ -50,31 +57,71 @@ grep -Fx "remote: Peer certificate matches pinned SPKI digest sha256\$$PKEY_SHA2 step_done capath=$(mktemp --tmpdir="$TMPDIR" --directory capath.XXXXXX) +cp -T -- ~/.dovecot/conf.d/ca.crt "$capath/ca-certificates.crt" step_start "SSL_CAfile" if [ -f "/etc/ssl/certs/ca-certificates.crt" ]; then - # our fake root CA should not be in there + # assume our fake root CA is not there with_remote_config <<<"SSL_CAfile = /etc/ssl/certs/ca-certificates.crt" unverified_peer fi -cp -T -- ~/.dovecot/conf.d/ca.crt "$capath/ca-certificates.crt" +# default host (localhost) is the CN (and also subjectAltName) with_remote_config <<<"SSL_CAfile = $capath/ca-certificates.crt" verified_peer + +# 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 IPs or hostnames +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" if [ -d "/etc/ssl/certs" ]; then - # our fake root CA should not be in there + # 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 + +# 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 : -- cgit v1.2.3 From 4ed6f0982cc0553e31e7beadf441beb8573a07d4 Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Thu, 10 Dec 2020 21:52:44 +0100 Subject: libinterimap: add support for the TLS SNI (Server Name Indication) extension. This is controlled by the new 'SSL_hostname' option. The default value of that option is the value of the 'host' option when it is hostname, and the empty string (which disables SNI) when it is an IP literal. --- tests/certs/generate | 3 ++ tests/list | 3 +- tests/tls-sni/interimap.remote | 3 ++ tests/tls-sni/remote.conf | 7 +++++ tests/tls-sni/t | 66 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 tests/tls-sni/interimap.remote create mode 100644 tests/tls-sni/remote.conf create mode 100644 tests/tls-sni/t (limited to 'tests') diff --git a/tests/certs/generate b/tests/certs/generate index 6457765..de379a0 100755 --- a/tests/certs/generate +++ b/tests/certs/generate @@ -39,3 +39,6 @@ new ./dovecot.rsa.key "localhost" "DNS:localhost,DNS:ip6-localhost,IP:127.0.0.1, openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -pkeyopt ec_param_enc:named_curve -out ./dovecot.ecdsa.key new ./dovecot.ecdsa.key "localhost" >./dovecot.ecdsa.crt + +openssl genpkey -algorithm RSA -out ./dovecot.rsa2.key +new ./dovecot.rsa2.key "imap.example.net" "DNS:imap.example.net,DNS:localhost" >./dovecot.rsa2.crt diff --git a/tests/list b/tests/list index 0ad86e4..cb31a73 100644 --- a/tests/list +++ b/tests/list @@ -51,7 +51,8 @@ split-set Split large sets to avoid extra-long command lines tls SSL/TLS handshake ... tls-verify-peer tls-pin-fingerprint pubkey fingerprint pinning - tls-rsa+ecdsa pubkey fingerprint pinning for hybrid RSA+ECDSA + tls-rsa+ecdsa pubkey fingerprint pinning for dual-cert RSA+ECDSA + tls-sni TLS servername extension (SNI) tls-protocols force TLS protocol versions . Live synchronization (60s) diff --git a/tests/tls-sni/interimap.remote b/tests/tls-sni/interimap.remote new file mode 100644 index 0000000..9f0d521 --- /dev/null +++ b/tests/tls-sni/interimap.remote @@ -0,0 +1,3 @@ +type = imaps +port = 10993 +SSL_verify = no diff --git a/tests/tls-sni/remote.conf b/tests/tls-sni/remote.conf new file mode 100644 index 0000000..4ccfb44 --- /dev/null +++ b/tests/tls-sni/remote.conf @@ -0,0 +1,7 @@ +!include conf.d/imapd.conf +!include conf.d/ssl.conf + +local_name imap.example.net { + ssl_cert = >"$XDG_CONFIG_HOME/interimap/config" +for ip in "127.0.0.1" "[::1]"; do + sed -i "s/^host\\s*=.*/host = $ip/" -- "$XDG_CONFIG_HOME/interimap/config" + interimap --debug || error + ! grep "^remote: Using SNI with name " <"$STDERR" || error "Using SNI with IP $ip" + grep -Fx "remote: Peer certificate fingerprint: sha256\$$X509_SHA256" <"$STDERR" || error +done + +# verify that SNI actually works (ie we're served the right cert) +sni_ok() { + grep -Fx "remote: Using SNI with name $SERVERNAME" <"$STDERR" || error + grep -Fx "remote: Peer certificate fingerprint: sha256\$$X509_2_SHA256" <"$STDERR" || error +} +echo "SSL_hostname = $SERVERNAME" >>"$XDG_CONFIG_HOME/interimap/config" +interimap --debug || error +sni_ok + + +## make sure SSL_hostname doesn't affect certificate verification ## + +# bad CA, bad host +sed -i "s/^host\\s*=.*/host = 127.0.0.1/" -- "$XDG_CONFIG_HOME/interimap/config" +sed -i "s/^SSL_verify\\s*=.*/SSL_verify = YES/" -- "$XDG_CONFIG_HOME/interimap/config" +! interimap --debug || error +sni_ok +grep -Fx "remote: ERROR: Can't initiate TLS/SSL handshake" <"$STDERR" || error + +# good CA, bad host +echo "SSL_CAfile = $HOME/.dovecot/conf.d/ca.crt" >>"$XDG_CONFIG_HOME/interimap/config" +! interimap --debug || error +sni_ok +grep -Fx "remote: ERROR: Can't initiate TLS/SSL handshake" <"$STDERR" || error + +# bad CA, good host +sed -i "/^SSL_CAfile\\s*=/d" -- "$XDG_CONFIG_HOME/interimap/config" +sed -i "s/^host\\s*=.*/host = localhost/" -- "$XDG_CONFIG_HOME/interimap/config" +! interimap --debug || error +sni_ok +grep -Fx "remote: ERROR: Can't initiate TLS/SSL handshake" <"$STDERR" || error + +# good CA, good host +echo "SSL_CAfile = $HOME/.dovecot/conf.d/ca.crt" >>"$XDG_CONFIG_HOME/interimap/config" +interimap --debug || error +sni_ok + +# vim: set filetype=sh : -- cgit v1.2.3