aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Net/IMAP
diff options
context:
space:
mode:
authorGuilhem Moulin <guilhem@fripost.org>2020-12-09 15:06:37 +0100
committerGuilhem Moulin <guilhem@fripost.org>2020-12-09 15:29:54 +0100
commita1ef66a76b4a6651b7371a9fd1e35f2f99e85bfa (patch)
treefbc80ff754618b91f2fc518cff8c71175b9a0e92 /lib/Net/IMAP
parentb13c9fa6f442f555af65f869b954935dae40fcc4 (diff)
libinterimap: SSL_fingerprint now supports a space-separate list of digests to pin.
And succeeds if, and only if, the peer certificate SPKI matches one of the pinned digest values. Specifying multiple digest values can key useful in key rollover scenarios and/or when the server supports certificates of different types (for instance RSA+ECDSA).
Diffstat (limited to 'lib/Net/IMAP')
-rw-r--r--lib/Net/IMAP/InterIMAP.pm23
1 files changed, 15 insertions, 8 deletions
diff --git a/lib/Net/IMAP/InterIMAP.pm b/lib/Net/IMAP/InterIMAP.pm
index bd14625..1a71f59 100644
--- a/lib/Net/IMAP/InterIMAP.pm
+++ b/lib/Net/IMAP/InterIMAP.pm
@@ -63,7 +63,7 @@ my %OPTIONS = (
'null-stderr' => qr/\A(YES|NO)\z/i,
compress => qr/\A(YES|NO)\z/i,
SSL_protocols => qr/\A(!?$RE_SSL_PROTO(?: !?$RE_SSL_PROTO)*)\z/,
- SSL_fingerprint => qr/\A((?:[A-Za-z0-9]+\$)?\p{AHex}+)\z/,
+ SSL_fingerprint => qr/\A((?:[A-Za-z0-9]+\$)?\p{AHex}+(?: (?:[A-Za-z0-9]+\$)?\p{AHex}+)*)\z/,
SSL_cipherlist => qr/\A(\P{Control}+)\z/,
SSL_verify => qr/\A(YES|NO)\z/i,
SSL_CApath => qr/\A(\P{Control}+)\z/,
@@ -1624,15 +1624,22 @@ sub _ssl_verify($$$) {
.$algo.'$'.unpack('H*', Net::SSLeay::X509_digest($cert, $type)));
}
- if (defined (my $fpr = $self->{SSL_fingerprint})) {
- (my $algo, $fpr) = $fpr =~ /^([^\$]+)\$(.*)/ ? ($1, $2) : ('sha256', $fpr);
- my $digest = pack 'H*', ($fpr =~ tr/://rd);
+ if (defined (my $fprs = $self->{SSL_fingerprint})) {
+ my $rv = 0;
+ foreach my $fpr (split /\s+/, $fprs) {
+ (my $algo, $fpr) = $fpr =~ /^([^\$]+)\$(.*)/ ? ($1, $2) : ('sha256', $fpr);
+ my $digest = pack 'H*', ($fpr =~ tr/://rd);
- my $type = Net::SSLeay::EVP_get_digestbyname($algo)
- or $self->_ssl_error("Can't find MD value for name '$algo'");
+ my $type = Net::SSLeay::EVP_get_digestbyname($algo)
+ or $self->_ssl_error("Can't find MD value for name '$algo'");
- my $pkey = Net::SSLeay::X509_get_X509_PUBKEY($cert);
- unless (defined $pkey and Net::SSLeay::EVP_Digest($pkey, $type) eq $digest) {
+ my $pkey = Net::SSLeay::X509_get_X509_PUBKEY($cert);
+ if (defined $pkey and Net::SSLeay::EVP_Digest($pkey, $type) eq $digest) {
+ $rv = 1;
+ last;
+ }
+ }
+ unless ($rv) {
$self->warn("Fingerprint doesn't match! MiTM in action?");
$ok = 0;
}