aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Net/IMAP/InterIMAP.pm
diff options
context:
space:
mode:
authorGuilhem Moulin <guilhem@fripost.org>2020-12-10 21:52:44 +0100
committerGuilhem Moulin <guilhem@fripost.org>2020-12-11 11:20:41 +0100
commit4ed6f0982cc0553e31e7beadf441beb8573a07d4 (patch)
treeb8ad71b56dc8d9a237e308877922500b46c351e7 /lib/Net/IMAP/InterIMAP.pm
parent09376bac4fe99c542223ba0ae23ad6067410b1fa (diff)
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.
Diffstat (limited to 'lib/Net/IMAP/InterIMAP.pm')
-rw-r--r--lib/Net/IMAP/InterIMAP.pm15
1 files changed, 13 insertions, 2 deletions
diff --git a/lib/Net/IMAP/InterIMAP.pm b/lib/Net/IMAP/InterIMAP.pm
index a0efcc1..e3a5d31 100644
--- a/lib/Net/IMAP/InterIMAP.pm
+++ b/lib/Net/IMAP/InterIMAP.pm
@@ -65,6 +65,7 @@ my %OPTIONS = (
SSL_protocols => qr/\A(!?$RE_SSL_PROTO(?: !?$RE_SSL_PROTO)*)\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_hostname => qr/\A(\P{Control}*)\z/,
SSL_verify => qr/\A(YES|NO)\z/i,
SSL_CApath => qr/\A(\P{Control}+)\z/,
SSL_CAfile => qr/\A(\P{Control}+)\z/,
@@ -1739,6 +1740,8 @@ sub _start_ssl($$) {
$self->_ssl_error("X509_VERIFY_PARAM_set_purpose()") unless Net::SSLeay::X509_VERIFY_PARAM_set_purpose($vpm, $purpose) == 1;
$self->_ssl_error("CTX_set_purpose()") unless Net::SSLeay::CTX_set_purpose($ctx, $purpose) == 1;
+ my $host = $self->{host} // $self->panic();
+ my ($hostip, $hostipfam) = _parse_hostip($host);
if ($self->{SSL_verify} // 1) {
# for X509_VERIFY_PARAM_set1_{ip,host}()
$self->panic("Failed requirement libssl >=1.0.2") if $openssl_version < 0x1000200f;
@@ -1751,8 +1754,6 @@ sub _start_ssl($$) {
}
# verify DNS hostname or IP literal
- my $host = $self->{host} // $self->panic();
- my ($hostip, $hostipfam) = _parse_hostip($host);
if (defined $hostipfam) {
my $addr = Socket::inet_pton($hostipfam, $hostip) // $self->panic();
$self->_ssl_error("X509_VERIFY_PARAM_set1_ip()")
@@ -1770,6 +1771,16 @@ sub _start_ssl($$) {
my $ssl = Net::SSLeay::new($ctx) or $self->fail("Can't create new SSL structure");
Net::SSLeay::set_fd($ssl, fileno $socket) or $self->fail("SSL filehandle association failed");
+
+ # always use 'SSL_hostname' when set, otherwise use 'host' (unless it's an IP) on OpenSSL >=0.9.8f
+ my $servername = $self->{SSL_hostname} // (defined $hostipfam ? "" : $host);
+ if ($servername ne "") {
+ $self->panic("Failed requirement libssl >=0.9.8f") if $openssl_version < 0x00908070;
+ $self->_ssl_error("Can't set TLS servername extension (value $servername)")
+ unless Net::SSLeay::set_tlsext_host_name($ssl, $servername) == 1;
+ $self->log("Using SNI with name $servername") if $self->{debug};
+ }
+
$self->_ssl_error("Can't initiate TLS/SSL handshake") unless Net::SSLeay::connect($ssl) == 1;
$self->panic() unless $self->{_SSL_PEER_VERIFIED}; # sanity check
$self->panic() if ($self->{SSL_verify} // 1) and Net::SSLeay::get_verify_result($ssl) != Net::SSLeay::X509_V_OK();