From 50c6fd25f2958e6300ec8377ab40c3f1a23bd9fd Mon Sep 17 00:00:00 2001 From: Steffen Ullrich Date: Fri, 28 Nov 2014 11:47:16 +0100 Subject: - model SSL support for Net::NNTP after Net::SMTP, i.e. upgrade to SSL class instead of using IO::Socket::SSL in plain and SSL mode - use SNI for SSL support in SMTP, NNTP, POP3, FTP by default --- lib/Net/FTP.pm | 2 ++ lib/Net/NNTP.pm | 57 ++++++++++++++++++++++++++++++++++++++------------------- lib/Net/POP3.pm | 9 ++++----- lib/Net/SMTP.pm | 7 +++++-- 4 files changed, 49 insertions(+), 26 deletions(-) diff --git a/lib/Net/FTP.pm b/lib/Net/FTP.pm index 7141734..e95da87 100644 --- a/lib/Net/FTP.pm +++ b/lib/Net/FTP.pm @@ -103,6 +103,7 @@ sub new { %tlsargs = ( SSL_verifycn_scheme => 'ftp', SSL_verifycn_name => $hostname, + SSL_hostname => $hostname, # reuse SSL session of control connection in data connections SSL_session_cache => Net::FTP::_SSL_SingleSessionCache->new, ); @@ -1038,6 +1039,7 @@ sub _dataconn { $ftp->is_SSL ? ( SSL_reuse_ctx => $ftp, SSL_verifycn_name => ${*$ftp}{net_ftp_tlsargs}{SSL_verifycn_name}, + SSL_hostname => ${*$ftp}{net_ftp_tlsargs}{SSL_hostname}, ) :( %{${*$ftp}{net_ftp_tlsargs}} ), ):(), ) or return; diff --git a/lib/Net/NNTP.pm b/lib/Net/NNTP.pm index b63d421..09cebe1 100644 --- a/lib/Net/NNTP.pm +++ b/lib/Net/NNTP.pm @@ -47,7 +47,7 @@ my $inet6_class = eval { sub can_ssl { $ssl_class }; sub can_inet6 { $inet6_class }; -our @ISA = ('Net::Cmd', $ssl_class || $inet6_class || 'IO::Socket::INET'); +our @ISA = ('Net::Cmd', $inet6_class || 'IO::Socket::INET'); sub new { @@ -73,18 +73,11 @@ sub new { my %connect = ( Proto => 'tcp'); - if ($ssl_class) { - $connect{SSL_verifycn_scheme} = 'nntp'; + if ($arg{SSL}) { + # SSL from start + die $nossl_warn if ! $ssl_class; + $arg{Port} ||= 563; $connect{$_} = $arg{$_} for(grep { m{^SSL_} } keys %arg); - if ($arg{SSL}) { - # SSL from start - $arg{Port} ||= 563; - } else { - # upgrade later with STARTTLS - $connect{SSL_startHandshake} = 0; - } - } elsif ($arg{SSL}) { - die $nossl_warn; } foreach my $o (qw(LocalAddr Timeout)) { @@ -94,16 +87,18 @@ sub new { $connect{PeerPort} = $arg{Port} || 'nntp(119)'; foreach my $h (@{$hosts}) { $connect{PeerAddr} = $h; - $connect{SSL_verifycn_name} = $arg{SSL_verifycn_name} || $h if $ssl_class; - $obj = $type->SUPER::new(%connect) - and last; + $obj = $type->SUPER::new(%connect) or next; + ${*$obj}{'net_nntp_host'} = $h; + ${*$obj}{'net_nntp_arg'} = \%arg; + if ($arg{SSL}) { + Net::NNTP::_SSL->start_SSL($obj,%arg) or next; + } + last: } return unless defined $obj; - ${*$obj}{'net_nntp_host'} = $connect{PeerAddr}; - $obj->autoflush(1); $obj->debug(exists $arg{Debug} ? $arg{Debug} : undef); @@ -168,9 +163,11 @@ sub postok { sub starttls { my $self = shift; $ssl_class or die $nossl_warn; - $self->is_SSL and croak("NNTP connection is already in SSL mode"); $self->_STARTTLS or return; - $self->connect_SSL; + Net::NNTP::_SSL->start_SSL($self, + %{ ${*$self}{'net_nntp_arg'} }, # (ssl) args given in new + @_ # more (ssl) args + ); } @@ -750,6 +747,28 @@ sub DESTROY { defined(fileno($nntp)) && $nntp->quit; } +{ + package Net::NNTP::_SSL; + our @ISA = ( $ssl_class ? ($ssl_class):(), 'Net::NNTP' ); + sub starttls { die "NNTP connection is already in SSL mode" } + sub start_SSL { + my ($class,$nntp,%arg) = @_; + delete @arg{ grep { !m{^SSL_} } keys %arg }; + ( $arg{SSL_verifycn_name} ||= $nntp->host ) + =~s{(?SUPER::start_SSL($nntp, + SSL_verifycn_scheme => 'nntp', + %arg + ); + $@ = $ssl_class->errstr if !$ok; + return $ok; + } +} + + + 1; diff --git a/lib/Net/POP3.pm b/lib/Net/POP3.pm index ae102a3..5bebe9b 100644 --- a/lib/Net/POP3.pm +++ b/lib/Net/POP3.pm @@ -87,14 +87,11 @@ sub new { unless defined $obj; ${*$obj}{'net_pop3_arg'} = \%arg; + ${*$obj}{'net_pop3_host'} = $host; if ($arg{SSL}) { - Net::POP3::_SSL->start_SSL($obj, - SSL_verifycn_name => $host,%arg - ) or return; + Net::POP3::_SSL->start_SSL($obj,%arg) or return; } - ${*$obj}{'net_pop3_host'} = $host; - $obj->autoflush(1); $obj->debug(exists $arg{Debug} ? $arg{Debug} : undef); @@ -581,6 +578,8 @@ sub banner { delete @arg{ grep { !m{^SSL_} } keys %arg }; ( $arg{SSL_verifycn_name} ||= $pop3->host ) =~s{(?SUPER::start_SSL($pop3,%arg); $@ = $ssl_class->errstr if !$ok; diff --git a/lib/Net/SMTP.pm b/lib/Net/SMTP.pm index 5cc3922..23a0cca 100644 --- a/lib/Net/SMTP.pm +++ b/lib/Net/SMTP.pm @@ -89,8 +89,10 @@ sub new { unless defined $obj; ${*$obj}{'net_smtp_arg'} = \%arg; + ${*$obj}{'net_smtp_host'} = $host; + if ($arg{SSL}) { - Net::SMTP::_SSL->start_SSL($obj,SSL_verifycn_name => $host,%arg) + Net::SMTP::_SSL->start_SSL($obj,%arg) or return; } @@ -106,7 +108,6 @@ sub new { } ${*$obj}{'net_smtp_exact_addr'} = $arg{ExactAddresses}; - ${*$obj}{'net_smtp_host'} = $host; (${*$obj}{'net_smtp_banner'}) = $obj->message; (${*$obj}{'net_smtp_domain'}) = $obj->message =~ /\A\s*(\S+)/; @@ -614,6 +615,8 @@ sub _STARTTLS { shift->command("STARTTLS")->response() == CMD_OK } delete @arg{ grep { !m{^SSL_} } keys %arg }; ( $arg{SSL_verifycn_name} ||= $smtp->host ) =~s{(?SUPER::start_SSL($smtp,%arg); $@ = $ssl_class->errstr if !$ok; -- cgit v1.2.3-24-ge0c7