From 8c43ed9baa905d907a6aad77de2282a852ba69a9 Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Sun, 13 Dec 2020 17:43:52 +0100 Subject: 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). --- Changelog | 6 ++++++ doc/interimap.1.md | 14 ++++++++++---- doc/pullimap.1.md | 14 ++++++++++---- interimap.sample | 1 - lib/Net/IMAP/InterIMAP.pm | 10 +++++++--- pullimap.sample | 1 - tests/run | 3 +++ tests/tls-verify-peer/t | 27 ++++++++++++++++++++++++--- 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