aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuilhem Moulin <guilhem@fripost.org>2020-12-13 17:43:52 +0100
committerGuilhem Moulin <guilhem@fripost.org>2020-12-13 18:44:18 +0100
commit8c43ed9baa905d907a6aad77de2282a852ba69a9 (patch)
tree4b8ecfe08d1aafcfde68cce0fb63b1bf4ec9542d
parentba9d8af01141a6d5d5b98a0e249c311814b844a6 (diff)
libinterimap: use default locations for trusted CA certificates when neither CAfile nor CApath are set.
In particular, OpenSSL's default locations can be overridden by the SSL_CERT_FILE resp. SSL_CERT_DIR environment variables, see SSL_CTX_load_verify_locations(3ssl). This bumps the minimum OpenSSL version to 1.1.0 (when SSL_verify is used).
-rw-r--r--Changelog6
-rw-r--r--doc/interimap.1.md14
-rw-r--r--doc/pullimap.1.md14
-rw-r--r--interimap.sample1
-rw-r--r--lib/Net/IMAP/InterIMAP.pm10
-rw-r--r--pullimap.sample1
-rwxr-xr-xtests/run3
-rw-r--r--tests/tls-verify-peer/t27
8 files changed, 60 insertions, 16 deletions
diff --git a/Changelog b/Changelog
index 9a36e8a..2fbdf36 100644
--- a/Changelog
+++ b/Changelog
@@ -10,6 +10,12 @@ interimap (0.5.5) upstream;
protocol black/whitelist greatly; this only allows simple min/max
bounds, but holes are arguably not very useful here. Using the new
settings bumps the required libssl version to 1.1.0.
+ * libinterimap: use default locations for trusted CA certificates when
+ neither CAfile nor CApath are set. In particular, OpenSSL's default
+ locations can be overridden by the SSL_CERT_FILE resp. SSL_CERT_DIR
+ environment variables, see SSL_CTX_load_verify_locations(3ssl).
+ This bumps the minimum OpenSSL version to 1.1.0 (when SSL_verify is
+ used).
+ `make release`: also bump libinterimap version and pin it in 'use'
declarations.
+ Make error messages more uniform and consistent.
diff --git a/doc/interimap.1.md b/doc/interimap.1.md
index 2310cb3..63d5ab0 100644
--- a/doc/interimap.1.md
+++ b/doc/interimap.1.md
@@ -439,6 +439,14 @@ Valid options are:
measure as it pins directly its key material and ignore its chain of
trust.
+*SSL_CAfile*
+
+: File containing trusted certificates to use during server
+ certificate verification when `SSL_verify=YES`.
+
+ Trusted CA certificates are loaded from the default system locations
+ unless one (or both) of *SSL_CAfile* or *SSL_CApath* is set.
+
*SSL_CApath*
: Directory to use for server certificate verification when
@@ -446,10 +454,8 @@ Valid options are:
This directory must be in “hash format”, see [`verify`(1ssl)] for
more information.
-*SSL_CAfile*
-
-: File containing trusted certificates to use during server
- certificate verification when `SSL_verify=YES`.
+ Trusted CA certificates are loaded from the default system locations
+ unless one (or both) of *SSL_CAfile* or *SSL_CApath* is set.
*SSL_hostname*
diff --git a/doc/pullimap.1.md b/doc/pullimap.1.md
index cf6ec52..05cbcaf 100644
--- a/doc/pullimap.1.md
+++ b/doc/pullimap.1.md
@@ -258,6 +258,14 @@ Valid options are:
measure as it pins directly its key material and ignore its chain of
trust.
+*SSL_CAfile*
+
+: File containing trusted certificates to use during server
+ certificate verification when `SSL_verify=YES`.
+
+ Trusted CA certificates are loaded from the default system locations
+ unless one (or both) of *SSL_CAfile* or *SSL_CApath* is set.
+
*SSL_CApath*
: Directory to use for server certificate verification when
@@ -265,10 +273,8 @@ Valid options are:
This directory must be in “hash format”, see [`verify`(1ssl)] for
more information.
-*SSL_CAfile*
-
-: File containing trusted certificates to use during server
- certificate verification when `SSL_verify=YES`.
+ Trusted CA certificates are loaded from the default system locations
+ unless one (or both) of *SSL_CAfile* or *SSL_CApath* is set.
*SSL_hostname*
diff --git a/interimap.sample b/interimap.sample
index e54c8a0..36eeb2a 100644
--- a/interimap.sample
+++ b/interimap.sample
@@ -23,7 +23,6 @@ password = xxxxxxxxxxxxxxxx
#compress = YES
# SSL options
-#SSL_CApath = /etc/ssl/certs
#SSL_verify = YES
#SSL_protocol_min = TLSv1.2
#SSL_fingerprint = sha256$29111aea5d5be7e448bdc5c6e8a9d03bc9221c53c09b1cfbe6f953221e24dda0
diff --git a/lib/Net/IMAP/InterIMAP.pm b/lib/Net/IMAP/InterIMAP.pm
index 5bdd954..89e5cba 100644
--- a/lib/Net/IMAP/InterIMAP.pm
+++ b/lib/Net/IMAP/InterIMAP.pm
@@ -1776,10 +1776,14 @@ sub _start_ssl($$) {
$self->panic("Failed requirement libssl >=1.0.2") if $OPENSSL_VERSION < 0x1000200f;
# verify certificate chain
- my ($file, $path) = ($self->{SSL_CAfile} // '', $self->{SSL_CApath} // '');
- if ($file ne '' or $path ne '') {
+ if (defined $self->{SSL_CAfile} or defined $self->{SSL_CApath}) {
$self->_ssl_error("SSL_CTX_load_verify_locations()")
- unless Net::SSLeay::CTX_load_verify_locations($ctx, $file, $path) == 1;
+ unless Net::SSLeay::CTX_load_verify_locations($ctx,
+ $self->{SSL_CAfile} // '', $self->{SSL_CApath} // '') == 1;
+ } else {
+ $self->log("Using default locations for trusted CA certificates") if $self->{debug};
+ $self->_ssl_error("SSL_CTX_set_default_verify_paths()")
+ unless Net::SSLeay::CTX_set_default_verify_paths($ctx) == 1;
}
# verify DNS hostname or IP literal
diff --git a/pullimap.sample b/pullimap.sample
index d911851..f1a66f9 100644
--- a/pullimap.sample
+++ b/pullimap.sample
@@ -4,7 +4,6 @@ deliver-method = smtp:[127.0.0.1]:25
purge-after = 90
# SSL options
-#SSL_CApath = /etc/ssl/certs
#SSL_verify = YES
#SSL_protocol_min = TLSv1.2
diff --git a/tests/run b/tests/run
index 29384ec..329f3e3 100755
--- a/tests/run
+++ b/tests/run
@@ -209,6 +209,8 @@ _interimap_cmd() {
local script="$1" rv=0
shift
environ_set "local"
+ [ -z "${SSL_CERT_FILE+x}" ] || ENVIRON+=( SSL_CERT_FILE="$SSL_CERT_FILE" )
+ [ -z "${SSL_CERT_DIR+x}" ] || ENVIRON+=( SSL_CERT_DIR="$SSL_CERT_DIR" )
env -i "${ENVIRON[@]}" perl -I./lib -T "./$script" "$@" 2>"$STDERR" || rv=$?
cat <"$STDERR" >&2
return $rv
@@ -445,6 +447,7 @@ passed() {
# Run test in a sub-shell
declare -a ENVIRON=()
environ_set "local"
+unset SSL_CERT_FILE SSL_CERT_DIR
export TMPDIR TESTDIR STDERR "${ENVIRON[@]}" OPENSSL_CONF
export -f environ_set doveadm interimap interimap_init pullimap _interimap_cmd
export -f sqlite3 sample_message deliver ptree_abort step_start step_done passed
diff --git a/tests/tls-verify-peer/t b/tests/tls-verify-peer/t
index 8cc098a..8326521 100644
--- a/tests/tls-verify-peer/t
+++ b/tests/tls-verify-peer/t
@@ -46,7 +46,9 @@ with_remote_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"
@@ -54,13 +56,23 @@ 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"
+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"
@@ -71,6 +83,10 @@ fi
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
@@ -80,7 +96,7 @@ for host in "ip6-localhost" "127.0.0.1" "::1"; do
verified_peer
done
-# but not for other IPs or hostnames
+# but not for other hostnames or IPs
for host in "ip6-loopback" "127.0.1.1"; do
with_remote_config <<-EOF
host = $host
@@ -92,7 +108,8 @@ done
step_done
-step_start "SSL_CApath"
+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"
@@ -105,6 +122,10 @@ c_rehash "$capath"
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