This is an automated email from the git hooks/post-receive script.

dom pushed a commit to branch master
in repository libnet-sslglue-perl.

commit b1cb840a574c8d8bc3e7894adf196e1dc9ab6c3c
Author: Dominic Hargreaves <d...@earth.li>
Date:   Sun Feb 9 15:01:25 2014 +0000

    Imported Upstream version 1.052
---
 Changes                   |  14 ++
 MANIFEST                  |  23 ++--
 META.yml                  |   4 +-
 Makefile.PL               |  21 +--
 TODO                      |   1 -
 examples/ftps-direct.pl   |  12 ++
 examples/ftps-starttls.pl |  21 +++
 examples/ftps-tests.pl    | 124 +++++++++++++++++
 lib/Net/SSLGlue.pm        |   8 +-
 lib/Net/SSLGlue/FTP.pm    | 334 ++++++++++++++++++++++++++++++++++++++++++++++
 lib/Net/SSLGlue/Socket.pm | 204 ++++++++++++++++++++++++++++
 t/external/02_smtp.t      |  28 +---
 t/external/03_lwp.t       | 104 +++++++++------
 t/external/04_pop3.t      |  29 +---
 t/external/05_ftp.t       | 169 +++++++++++++++++++++++
 15 files changed, 981 insertions(+), 115 deletions(-)

diff --git a/Changes b/Changes
index 7741a5c..e853530 100644
--- a/Changes
+++ b/Changes
@@ -1,3 +1,17 @@
+1.052 2014/01/16
+- FTPS: reuse same SSL session for control and data channnel to work
+  with default configuration of proftpd. 
+
+1.051 2014/01/10
+- fixes to Net::FTP SSL support
+- examples/ftps-tests.pl has lots of tests for FTP against live server
+
+1.05 2014/01/09
+- added support for SSL+IPv6 in Net::FTP
+- new package Net::SSLGlue::Socket for a socket which combines plain,ssl,ipv6
+- fixed some tests - some checks for bad certificates do not work anymore
+  because these certs were fixed
+
 1.04 2013/08/01
 replace Net::Cmd::getline via Net::SSLGlue::POP3 because it assumed, that it
 just needs to wait for read events on the sockets - which is not the case for
diff --git a/MANIFEST b/MANIFEST
index dde4968..2c2acbf 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -1,20 +1,25 @@
+Changes
+COPYRIGHT
+examples/ftps-direct.pl
+examples/ftps-starttls.pl
+examples/ftps-tests.pl
+examples/lwp.pl
+examples/lwp_post.pl
+examples/send-ssl-mail.pl
+examples/send-starttls-mail.pl
 lib/Net/SSLGlue.pm
+lib/Net/SSLGlue/FTP.pm
 lib/Net/SSLGlue/LDAP.pm
 lib/Net/SSLGlue/LWP.pm
-lib/Net/SSLGlue/SMTP.pm
 lib/Net/SSLGlue/POP3.pm
+lib/Net/SSLGlue/SMTP.pm
+lib/Net/SSLGlue/Socket.pm
 Makefile.PL
 MANIFEST                       This list of files
+README
 t/01_load.t
 t/external/02_smtp.t
 t/external/03_lwp.t
 t/external/04_pop3.t
-TODO
-COPYRIGHT
-examples/lwp.pl
-examples/lwp_post.pl
-examples/send-ssl-mail.pl
-examples/send-starttls-mail.pl
-Changes
-README
+t/external/05_ftp.t
 META.yml                                 Module meta-data (added by MakeMaker)
diff --git a/META.yml b/META.yml
index 38dff5f..8007d08 100644
--- a/META.yml
+++ b/META.yml
@@ -1,6 +1,6 @@
 --- #YAML:1.0
 name:               Net-SSLGlue
-version:            1.04
+version:            1.052
 abstract:           ~
 author:  []
 license:            unknown
@@ -11,6 +11,8 @@ build_requires:
     ExtUtils::MakeMaker:  0
 requires:
     IO::Socket::SSL:  1.19
+resources:
+    repository:  https://github.com/noxxi/p5-net-sslglue
 no_index:
     directory:
         - t
diff --git a/Makefile.PL b/Makefile.PL
index f260435..2ab35fc 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -1,14 +1,19 @@
 use ExtUtils::MakeMaker;
 require 5.008;
 my $xt = prompt( "Should I do external tests?\n".
-       "These tests will fail if there is no internet connection or if a 
firewall\n".
-       "blocks some traffic.\n".
-       "[y/N]", 'n' );
+    "These tests will fail if there is no internet connection or if a 
firewall\n".
+    "blocks some traffic.\n".
+    "[y/N]", 'n' );
 WriteMakefile(
-       NAME => 'Net::SSLGlue',
-       VERSION_FROM => 'lib/Net/SSLGlue.pm',
-       PREREQ_PM => {
-               'IO::Socket::SSL' => 1.19,
+    NAME => 'Net::SSLGlue',
+    VERSION_FROM => 'lib/Net/SSLGlue.pm',
+    PREREQ_PM => {
+       'IO::Socket::SSL' => 1.19,
+    },
+    $xt =~m{^y}i ? ( test => { TESTS => 't/*.t t/external/*.t' }):(),
+    META_MERGE => {
+       resources => {
+           repository => 'https://github.com/noxxi/p5-net-sslglue',
        },
-       $xt =~m{^y}i ? ( test => { TESTS => 't/*.t t/external/*.t' }):(),
+    },
 );
diff --git a/TODO b/TODO
deleted file mode 100644
index 011330a..0000000
--- a/TODO
+++ /dev/null
@@ -1 +0,0 @@
-ldap tests
diff --git a/examples/ftps-direct.pl b/examples/ftps-direct.pl
new file mode 100644
index 0000000..32c410a
--- /dev/null
+++ b/examples/ftps-direct.pl
@@ -0,0 +1,12 @@
+use strict;
+use warnings;
+use Net::SSLGlue::FTP;
+
+my $ftp = Net::FTP->new( 'ftp.example.com', 
+    SSL => 1, 
+    SSL_ca_path => '/etc/ssl/certs',
+    Passive => 1,
+    Debug => 1,
+);
+$ftp->login('foo','bar');
+print $ftp->ls;
diff --git a/examples/ftps-starttls.pl b/examples/ftps-starttls.pl
new file mode 100644
index 0000000..6d23876
--- /dev/null
+++ b/examples/ftps-starttls.pl
@@ -0,0 +1,21 @@
+use strict;
+use warnings;
+use Net::SSLGlue::FTP;
+
+my $ftp = Net::FTP->new( 'ftp.example.com', 
+    Passive => 1,
+    Debug => 1,
+);
+$ftp->starttls( SSL_ca_path => '/etc/ssl/certs' )
+    or die "tls upgrade failed";
+$ftp->login('foo','bar');
+print $ftp->ls;
+
+# change protection to clear
+$ftp->prot('C');
+$ftp->ls;
+
+# stop TLS on control channel
+$ftp->stoptls;
+$ftp->ls;
+
diff --git a/examples/ftps-tests.pl b/examples/ftps-tests.pl
new file mode 100644
index 0000000..c860fbb
--- /dev/null
+++ b/examples/ftps-tests.pl
@@ -0,0 +1,124 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+
+# This runs lots of tests with SSL against a test server
+# - plain
+# - with SSL upgrade and plain data connections
+# - with SSL upgrade and SSL data connections
+# - with SSL upgrade and downgrade after auth
+# - with direct SSL connection
+
+# setup stuff here
+# you need a server where you can write and read and create directories
+# SSL support is optional, but preferred
+# IPv6 support should be possible
+
+my $testhost = '127.0.0.1'; # where your test server is, IPv6 should be ok
+my $plain_port = 2021;      # port where server listens for plain ftp
+my $user = 'foo';           # login as user
+my $pass = 'bar';           # with pass
+my $can_auth = 1;           # does server support AUTH TLS
+my $ssl_port = 2090;        # does server support direct SSL
+my %sslargs = (
+    # should be enabled if you want to verify certificates
+    SSL_verify_mode => 1,
+    # for CAs known to the system this might be maybe ommitted
+    # otherwise set this or SSL_ca_path
+    SSL_ca_file => 'ca.pem',
+    # if the certificate has a different name then $testhost set it here
+    SSL_verifycn_name => 'server.local',
+);
+
+
+use Net::SSLGlue::FTP;
+use IO::Socket::SSL;
+use Carp 'croak';
+
+my @test = (
+    # basic FTP server stuff
+    { Passive => 0 },
+    { Passive => 1 },
+    $can_auth ? (
+       # SSL upgrade with data connections unprotected
+       { Passive => 0, _starttls => 1, _prot => 'C' },
+       { Passive => 1, _starttls => 1, _prot => 'C' },
+       # SSL upgrade with data connections protected
+       { Passive => 0, _starttls => 1 },
+       { Passive => 1, _starttls => 1 },
+       # SSL upgrade with SSL downgrade after auth
+       { Passive => 0, _starttls => 1, _stoptls => 1 },
+       { Passive => 1, _starttls => 1, _stoptls => 1 },
+    ):(),
+    # direct SSL on separate port
+    $ssl_port ? (
+       { Passive => 0, SSL => 1, Port => $ssl_port },
+       { Passive => 1, SSL => 1, Port => $ssl_port },
+    ):(),
+);
+
+my $testbase = sprintf("test-%04x%04x-",rand(2**16),rand(2**16));
+for( my $i=0;$i<@test;$i++ ) {
+
+    my %conf = %{$test[$i]};
+    my $starttls = delete $conf{_starttls};
+    my $stoptls = delete $conf{_stoptls};
+    my $prot = delete $conf{_prot};
+    my $dir = "$testbase$i";
+
+    print STDERR "------------ $dir\n";
+    my $ftp = Net::FTP->new( $testhost,
+       Port => $plain_port,
+       Debug => 1,
+       %sslargs,
+       %conf,
+    ) or die "ftp connect failed";
+
+    my $ftperr = sub {
+       my $msg = shift;
+       croak "$msg failed (@_): ".$ftp->message;
+    };
+
+    # upgrade to SSL
+    $ftp->starttls or $ftperr->('auth tls', $SSL_ERROR)
+       if $starttls;
+
+    # login
+    $ftp->login($user,$pass) or $ftperr->('login');
+
+    # downgrade from SSL
+    $ftp->stoptls or $ftperr->('ccc') if $stoptls;
+
+    # change protection level
+    $ftp->prot($prot) or $ftperr->("PROT $prot")
+       if $prot;
+
+    # create directory for test and change into it
+    $ftp->mkdir($dir) or $ftperr->('mkd');
+    $ftp->cwd($dir) or $ftperr->('cwd');
+
+    # check that dir is empty
+    my @files = $ftp->ls;
+    $ftp->ok or $ftperr->('nlst');
+    @files and die "directory should be empty";
+
+    # create a file in dir
+    $ftp->put( _s2f( my $foo = 'foo' ,'<' ), 'foo.txt' )
+       or $ftperr->('stor');
+    # append some bytes to it
+    $ftp->append( _s2f('bar'),'foo.txt' ) or $ftperr->('appe');
+    # check that it is there
+    @files = $ftp->ls;
+    "@files" eq 'foo.txt' or die "wrong ls: @files";
+
+    # retrieve file and verify content
+    $ftp->get( 'foo.txt', _s2f( $foo = '','>' ));
+    $foo eq 'foobar' or die "wrong data: 'foobar' != '$foo'";
+
+    $ftp->quit;
+}
+
+sub _s2f {
+    open( my $fh,$_[1] || '<',\$_[0] );
+    return $fh
+}
diff --git a/lib/Net/SSLGlue.pm b/lib/Net/SSLGlue.pm
index a1c38b9..8e7ce83 100644
--- a/lib/Net/SSLGlue.pm
+++ b/lib/Net/SSLGlue.pm
@@ -1,5 +1,5 @@
 package Net::SSLGlue;
-our $VERSION = '1.04';
+our $VERSION = '1.052';
 
 =head1 NAME
 
@@ -21,12 +21,18 @@ available:
 
 =item Net::POP3 - add SSL from beginning or using STLS
 
+=item Net::FTP  - add SSL and IPv6 support to Net::FTP
+
 =item Net::LDAP - add proper certificate checking
 
 =item LWP - add proper certificate checking
 
 =back
 
+There is also a Net::SSLGlue::Socket package which combines ssl and non-ssl
+and ipv6 capabilities to make it easier to enhance modules based on
+IO::Socket::INET.
+
 =head1 COPYRIGHT
 
 This module and the modules in the Net::SSLGlue Hierarchy distributed together
diff --git a/lib/Net/SSLGlue/FTP.pm b/lib/Net/SSLGlue/FTP.pm
new file mode 100644
index 0000000..70d020a
--- /dev/null
+++ b/lib/Net/SSLGlue/FTP.pm
@@ -0,0 +1,334 @@
+
+package Net::SSLGlue::FTP;
+
+use strict;
+use warnings;
+use Carp 'croak';
+use IO::Socket::SSL '$SSL_ERROR';
+use Net::SSLGlue::Socket;
+use Socket 'AF_INET';
+
+our $VERSION = 1.001;
+
+BEGIN {
+    for my $class (qw(Net::FTP Net::FTP::dataconn)) {
+       eval "require $class" or die "failed to load $class";
+       no strict 'refs';
+       my $fixed;
+       for( @{ "${class}::ISA" } ) {
+           $_ eq 'IO::Socket::INET' or next;
+           $_ = 'Net::SSLGlue::Socket';
+           $fixed = 1;
+           last;
+       }
+       die "cannot replace IO::Socket::INET with Net::SSLGlue::Socket in 
${class}::ISA"
+           if ! $fixed;
+    }
+    $Net::FTP::VERSION eq '2.77'
+       or warn "Not tested with Net::FTP version $Net::FTP::VERSION";
+}
+
+# redefine Net::FTP::new so that it understands SSL => 1 and connects directly
+# with SSL to the server
+{
+    no warnings 'redefine';
+    my $onew = Net::FTP->can('new');
+    *Net::FTP::new = sub {
+       my $class = shift;
+       my %args = @_%2 ? ( Host => shift(), @_ ): @_;
+       my %sslargs = map { $_ => delete $args{$_} }
+           grep { m{^SSL_} } keys %args;
+
+       my $self;
+       if ( $args{SSL} ) {
+           # go immediatly to SSL
+           # Net::FTP::new gives only specific args to socket class
+           $args{Port} ||= 990;
+           local %Net::SSLGlue::Socket::ARGS = ( SSL => 1, %sslargs );
+           $self = $onew->($class,%args) or return;
+           ${*$self}{net_ftp_tlstype} = 'P';
+       } else {
+           $self = $onew->($class,%args) or return;
+       }
+       ${*$self}{net_ftp_tlsargs} = \%sslargs;
+       return $self;
+    };
+}
+
+# add starttls method to upgrade connection to SSL: AUTH TLS
+sub Net::FTP::starttls {
+    my $self = shift;
+    $self->is_ssl and croak("called starttls within SSL session");
+    $self->_AUTH('TLS') == Net::FTP::CMD_OK or return;
+
+    my $host = $self->host;
+    # for name verification strip port from domain:port, ipv4:port, [ipv6]:port
+    $host =~s{(?<!:):\d+$}{};
+
+    my %args = (
+       SSL_verify_mode => 1,
+       SSL_verifycn_scheme => 'ftp',
+       SSL_verifycn_name => $host,
+       # reuse SSL session of control connection in data connections
+       SSL_session_cache => Net::SSLGlue::FTP::SingleSessionCache->new,
+       %{ ${*$self}{net_ftp_tlsargs}},
+       @_
+    );
+
+    $self->start_SSL(%args) or return;
+    ${*$self}{net_ftp_tlsargs} = \%args;
+    $self->prot('P');
+    return 1;
+}
+
+# add prot method to set protection level (PROT C|P)
+sub Net::FTP::prot {
+    my ($self,$type) = @_;
+    $type eq 'C' or $type eq 'P' or croak("type must by C or P");
+    $self->_PBSZ(0) or return;
+    $self->_PROT($type) or return;
+    ${*$self}{net_ftp_tlstype} = $type;
+    return 1;
+}
+
+# add stoptls method to downgrade connection from SSL: CCC
+sub Net::FTP::stoptls {
+    my $self = shift;
+    $self->is_ssl or croak("called stoptls outside SSL session");
+    $self->_CCC() or return;
+    $self->stop_SSL();
+    return 1;
+}
+
+# add EPSV for new style passive mode (incl. IPv6)
+sub Net::FTP::epsv {
+    my $self = shift;
+    @_ and croak 'usage: $ftp->epsv()';
+    delete ${*$self}{net_ftp_intern_port};
+
+    $self->_EPSV && $self->message =~ m{\(([\x33-\x7e])\1\1(\d+)\1\)}
+       ? ${*$self}{'net_ftp_pasv'} = [ $self->peerhost, $2 ]
+       : undef;
+}
+
+# redefine PASV so that it uses EPSV on IPv6
+# also net_ftp_pasv contains now the parsed [ip,port]
+{
+    no warnings 'redefine';
+    *Net::FTP::pasv = sub {
+       my $self = shift;
+       @_ and croak 'usage: $ftp->port()';
+       return $self->epsv if $self->sockdomain != AF_INET;
+       delete ${*$self}{net_ftp_intern_port};
+
+       if ( $self->_PASV &&
+           $self->message =~ m{(\d+,\d+,\d+,\d+),(\d+),(\d+)} ) {
+           my $port = 256 * $2 + $3;
+           ( my $ip = $1 ) =~s{,}{.}g;
+           return ${*$self}{'net_ftp_pasv'} = [ $ip,$port ];
+       }
+       return;
+    };
+}
+
+# add EPRT for new style passive mode (incl. IPv6)
+sub Net::FTP::eprt {
+    @_ == 1 || @_ == 2 or croak 'usage: $self->eprt([PORT])';
+    return _eprt('EPRT',@_);
+}
+
+# redefine PORT to use EPRT for IPv6
+{
+    no warnings 'redefine';
+    *Net::FTP::port = sub {
+       @_ == 1 || @_ == 2 or croak 'usage: $self->port([PORT])';
+       return _eprt('PORT',@_);
+    };
+}
+
+sub _eprt {
+    my ($cmd,$self,$port) = @_;
+    delete ${*$self}{net_ftp_intern_port};
+    unless ($port) {
+       my $listen = ${*$self}{net_ftp_listen} ||= Net::SSLGlue::Socket->new(
+           Listen    => 1,
+           Timeout   => $self->timeout,
+           LocalAddr => $self->sockhost,
+       );
+       ${*$self}{net_ftp_intern_port} = 1;
+       my $fam = ($listen->sockdomain == AF_INET) ? 1:2;
+       if ( $cmd eq 'EPRT' || $fam == 2 ) {
+           $port = "|$fam|".$listen->sockhost."|".$listen->sockport."|";
+           $cmd = 'EPRT';
+       } else {
+           my $p = $listen->sockport;
+           $port = join(',',split(m{\.},$listen->sockhost),$p >> 8,$p & 0xff);
+       }
+    }
+    my $ok = $cmd eq 'EPRT' ? $self->_EPRT($port) : $self->_PORT($port);
+    ${*$self}{net_ftp_port} = $port if $ok;
+    return $ok;
+}
+
+
+
+for my $cmd (qw(PBSZ PROT CCC EPRT EPSV)) {
+    no strict 'refs';
+    *{"Net::FTP::_$cmd"} = sub {
+       shift->command("$cmd @_")->response() == Net::FTP::CMD_OK
+    }
+}
+
+# redefine _dataconn to
+# - support IPv6
+# - upgrade data connection to SSL if PROT P
+{
+
+    no warnings 'redefine';
+    *Net::FTP::_dataconn = sub {
+       my $self = shift;
+       my $pkg = "Net::FTP::" . $self->type;
+       eval "require $pkg";
+       $pkg =~ s/ /_/g;
+       delete ${*$self}{net_ftp_dataconn};
+
+       my $conn;
+       if ( my $pasv = ${*$self}{net_ftp_pasv} ) {
+           $conn = $pkg->new(
+               PeerAddr  => $pasv->[0],
+               PeerPort  => $pasv->[1],
+               LocalAddr => ${*$self}{net_ftp_localaddr},
+           ) or return;
+       } elsif (my $listen =  delete ${*$self}{net_ftp_listen}) {
+           $conn = $listen->accept($pkg) or return;
+           close($listen);
+       }
+
+       if (( ${*$self}{net_ftp_tlstype} || '') eq 'P'
+           && ! $conn->start_SSL( $self->is_ssl 
+               ? ( SSL_reuse_ctx => $self )
+               : ( %{${*$self}{net_ftp_tlsargs}} )
+           ) ) {
+           croak("failed to ssl upgrade dataconn: $SSL_ERROR");
+           return;
+       }
+
+       $conn->timeout($self->timeout);
+       ${*$self}{net_ftp_dataconn} = $conn;
+       ${*$conn} = "";
+       ${*$conn}{net_ftp_cmd} = $self;
+       ${*$conn}{net_ftp_blksize} = ${*$self}{net_ftp_blksize};
+       return $conn;
+    };
+}
+
+{
+    # Session Cache with single entry
+    # used to make sure that we reuse same session for control channel and data
+    package Net::SSLGlue::FTP::SingleSessionCache;
+    sub new { my $x; return bless \$x,shift }
+    sub add_session {
+       my ($self,$key,$session) = @_;
+       Net::SSLeay::SESSION_free($$self) if $$self;
+       $$self = $session;
+    }
+    sub get_session {
+       my $self = shift;
+       return $$self
+    }
+    sub DESTROY {
+       my $self = shift;
+       Net::SSLeay::SESSION_free($$self) if $$self;
+    }
+}
+
+1;
+
+=head1 NAME
+
+Net::SSLGlue::FTP - extend Net::FTP for FTPS (SSL) and IPv6
+
+=head1 SYNOPSIS
+
+    use Net::SSLGlue::FTP;
+    # SSL right from start
+    my $ftps = Net::FTP->new( $host,
+       SSL => 1,
+       SSL_ca_path => ...
+    );
+
+    # SSL through upgrade of plain connection
+    my $ftp = Net::FTP->new( $host );
+    $ftp->starttls( SSL_ca_path => ... );
+
+    # change protection mode to unencrypted|encrypted
+    $ftp->prot('C'); # clear
+    $ftp->prot('P'); # protected
+
+=head1 DESCRIPTION
+
+L<Net::SSLGlue::FTP> extends L<Net::FTP> so one can either start directly with
+SSL or switch later to SSL using starttls method (AUTH TLS command).
+If IO::Socket::IP or IO::Socket::INET6 are installed it will also transparently
+use IPv6.
+
+By default it will take care to verify the certificate according to the rules
+for FTP implemented in L<IO::Socket::SSL>.
+
+=head1 METHODS
+
+=over 4
+
+=item new
+
+The method C<new> of L<Net::FTP> is now able to start directly with SSL when
+the argument C<<SSL => 1>> is given. One can give the usual C<SSL_*> parameter
+of L<IO::Socket::SSL> to C<Net::FTP::new>.
+
+=item starttls
+
+If the connection is not yet SSLified it will issue the "AUTH TLS" command and
+change the object, so that SSL will now be used. The usual C<SSL_*> parameter 
of
+L<IO::Socket::SSL> will be given.
+
+=item peer_certificate ...
+
+Once the SSL connection is established you can use this method to get
+information about the certificate. See the L<IO::Socket::SSL> documentation.
+
+=back
+
+All of these methods can take the C<SSL_*> parameter from L<IO::Socket::SSL> to
+change the behavior of the SSL connection. The following parameters are
+especially useful:
+
+=over 4
+
+=item SSL_ca_path, SSL_ca_file
+
+Specifies the path or a file where the CAs used for checking the certificates
+are located. This is typically L</etc/ssl/certs> on UNIX systems.
+
+=item SSL_verify_mode
+
+If set to 0, verification of the certificate will be disabled. By default
+it is set to 1 which means that the peer certificate is checked.
+
+=item SSL_verifycn_name
+
+Usually the name given as the hostname in the constructor is used to verify the
+identity of the certificate. If you want to check the certificate against
+another name you can specify it with this parameter.
+
+=back
+
+=head1 SEE ALSO
+
+IO::Socket::SSL, Net::FTP, Net::SSLGlue::Socket
+
+=head1 COPYRIGHT
+
+This module is copyright (c) 2013, Steffen Ullrich.
+All Rights Reserved.
+This module is free software. It may be used, redistributed and/or modified
+under the same terms as Perl itself.
diff --git a/lib/Net/SSLGlue/Socket.pm b/lib/Net/SSLGlue/Socket.pm
new file mode 100644
index 0000000..a8e8842
--- /dev/null
+++ b/lib/Net/SSLGlue/Socket.pm
@@ -0,0 +1,204 @@
+
+package Net::SSLGlue::Socket;
+our $VERSION = 1.001;
+
+use strict;
+use warnings;
+use Carp 'croak';
+use Symbol 'gensym';
+use IO::Socket::SSL;
+my $IPCLASS;
+BEGIN {
+    for(qw(IO::Socket::IP IO::Socket::INET6 IO::Socket::INET)) {
+       $IPCLASS = $_,last if eval "require $_";
+    }
+}
+
+# this can be overwritten (with local) to get arguments passed around
+# to strict calls of the socket class new
+our %ARGS;
+
+sub new {
+    my $class = shift;
+    my %args = @_>1 ? @_ : ( PeerAddr => shift() );
+    %args = ( %args, %ARGS );
+
+    my %sslargs;
+    for(keys %args) {
+       $sslargs{$_} = delete $args{$_} if m{^SSL_};
+    }
+
+    my $ssl = delete $args{SSL};
+    my $sock = $ssl
+       ? IO::Socket::SSL->new(%args,%sslargs)
+       : $IPCLASS->new(%args)
+       or return;
+
+    my $self = gensym();
+    *$self = *$sock;  # clone handle
+    bless $self,$class;
+    ${*$self}{sock}    = $sock;
+    ${*$self}{ssl}     = $ssl;
+    ${*$self}{sslargs} = \%sslargs;
+
+    return $self;
+}
+
+for my $sub (qw(
+    fileno sysread syswrite close connect fcntl
+    read write readline print printf getc say eof getline getlines
+    blocking autoflush timeout
+    sockhost sockport peerhost peerport sockdomain
+    truncate stat setbuf setvbuf fdopen ungetc send recv
+)) {
+    no strict 'refs';
+    *$sub = sub {
+       my $self = shift;
+       my $sock = ${*$self}{sock} or return;
+       my $sock_sub = $sock->can($sub) or croak("$sock does not support $sub");
+       unshift @_,$sock;
+       # warn "*** $sub called";
+       goto &$sock_sub;
+    };
+}
+
+sub accept {
+    my ($self,$class) = @_;
+    my $sock = ${*$self}{sock} or return;
+    my $conn = $sock->accept();
+
+    return bless $conn,$class 
+       if $class && ! $class->isa('Net::SSLGlue::Socket');
+
+    $class ||= ref($self);
+    my $wrap = gensym;
+    *$wrap = *$conn;   # clone original handle
+    bless $wrap, $class;
+    ${*$wrap}{sock}    = $conn;
+    ${*$wrap}{ssl}     = ${*$self}{ssl};
+    ${*$wrap}{sslargs} = ${*$self}{sslargs};
+    return $wrap;
+};
+
+sub start_SSL {
+    my $self = shift;
+    croak("start_SSL called on SSL socket") if ${*$self}{ssl};
+    IO::Socket::SSL->start_SSL(${*$self}{sock},%{${*$self}{sslargs}},@_)
+       or return;
+    ${*$self}{ssl} = 1;
+    return $self;
+}
+
+sub stop_SSL {
+    my $self = shift;
+    croak("stop_SSL called on plain socket") if ! ${*$self}{ssl};
+    ${*$self}{sock}->stop_SSL(@_) or return;
+    ${*$self}{ssl} = 0;
+    return $self;
+}
+
+sub can_read {
+    my ($self,$timeout) = @_;
+    return 1 if ${*$self}{ssl} && ${*$self}{sock}->pending;
+    vec( my $vec,fileno(${*$self}{sock}),1) = 1;
+    return select($vec,undef,undef,$timeout);
+}
+
+sub peer_certificate {
+    my $self = shift;
+    return ${*$self}{ssl} && ${*$self}{sock}->peer_certificate(@_);
+}
+
+sub is_ssl {
+    my $self = shift;
+    return ${*$self}{ssl} && ${*$self}{sock};
+}
+
+1;
+
+=head1 NAME
+
+Net::SSLGlue::Socket - socket which can be either SSL or plain IP (IPv4/IPv6)
+
+=head1 SYNOPSIS
+
+    use Net::SSLGlue::Socket;
+    # SSL right from start
+    my $ssl = Net::SSLGlue::Socket->new(
+       PeerHost => ...,  # IPv4|IPv6 address
+       PeerPort => ...,
+       SSL => 1,
+       SSL_ca_path => ...
+    );
+
+    # SSL through upgrade of plain connection
+    my $plain = Net::SSLGlue::Socket->new(...);
+    $plain->start_SSL( SSL_ca_path => ... );
+    ...
+    $plain->stop_SSL
+
+
+=head1 DESCRIPTION
+
+L<Net::SSLGlue::Socket> implements a socket which can be either plain or SSL.
+If IO::Socket::IP or IO::Socket::INET6 are installed it will also transparently
+handle IPv6 connections.
+
+A socket can be either start directly with SSL or it can be start plain and
+later be upgraded to SSL (because of a STARTTLS commando or similar) and also
+downgraded again.
+
+It is possible but not recommended to use the socket in non-blocking
+mode, because in this case special care must be taken with SSL (see
+documentation of L<IO::Socket::SSL>).
+
+Additionally to the usual socket methods the following methods are defined or
+extended:
+
+=head1 METHODS
+
+=over 4
+
+=item new
+
+The method C<new> of L<Net::SSLGlue::Socket> can have the argument SSL. If this
+is true the SSL upgrade will be done immediatly. If not set any SSL_* args will
+still be saved and used at a later start_SSL call.
+
+=item start_SSL
+
+This will upgrade the plain socket to SSL. See L<IO::Socket::SSL>  for
+arguments to C<start_SSL>. Any SSL_* arguments given to new will be applied
+here too.
+
+=item stop_SSL
+
+This will downgrade the socket from SSL to plain.
+
+=item peer_certificate ...
+
+Once the SSL connection is established you can use this method to get
+information about the certificate. See the L<IO::Socket::SSL> documentation.
+
+=item can_read(timeout)
+
+This will check for available data. For a plain socket this will only use
+C<select> to check the socket, but for SSL it will check if there are any
+pending data before trying a select.
+Because SSL needs to read the whole frame before decryption can be done, a
+successful return of can_read is no guarantee that data can be read
+immediatly, only that new data are either available or in the process of
+arriving.
+
+=back
+
+=head1 SEE ALSO
+
+IO::Socket::SSL
+
+=head1 COPYRIGHT
+
+This module is copyright (c) 2013, Steffen Ullrich.
+All Rights Reserved.
+This module is free software. It may be used, redistributed and/or modified
+under the same terms as Perl itself.
diff --git a/t/external/02_smtp.t b/t/external/02_smtp.t
index 4edad8d..abc16ed 100644
--- a/t/external/02_smtp.t
+++ b/t/external/02_smtp.t
@@ -38,20 +38,8 @@ IO::Socket::SSL->new(
        exit
 };
 
-# ssl to the wrong host 
-# the certificate mail.gmx.de returns is for mail.gmx.net
-diag( "connect ssl to mail.gmx.de:465" );
-IO::Socket::SSL->new( 
-       PeerAddr => 'mail.gmx.de:465',
-       SSL_ca_path => $capath,
-       SSL_verify_mode => 1,
-       SSL_verifycn_scheme => 'smtp' 
-) and do {
-       print "1..0 # mail.gmx.de:465 reachable with SSL\n";
-       exit
-};
 
-print "1..6\n";
+print "1..3\n";
 
 # first direct SSL
 my $smtp = Net::SMTP->new( 'mail.gmx.net', 
@@ -67,20 +55,6 @@ print $ok ? "ok\n" : "not ok # smtp starttls mail.gmx.net\n";
 # check that we can talk on connection
 print $smtp->quit ? "ok\n": "not ok # quit failed\n";
 
-# against wrong host should fail
-$smtp = Net::SMTP->new( 'mail.gmx.de' ); # should succeed
-$ok = $smtp->starttls( SSL_ca_path => $capath ); 
-print $ok ? "not ok # smtp starttls mail.gmx.de did not fail\n": "ok\n";
-
-# but not if we specify the right SSL_verifycn_name
-$smtp = Net::SMTP->new( 'mail.gmx.de' ); # should succeed
-$ok = $smtp->starttls( SSL_ca_path => $capath, SSL_verifycn_name => 
'mail.gmx.net' ); 
-print $ok ? "ok\n" : "not ok # smtp starttls mail.gmx.de/net\n";
-
-# or disable verification
-$smtp = Net::SMTP->new( 'mail.gmx.de' ); # should succeed
-$ok = $smtp->starttls( SSL_verify_mode => 0 );
-print $ok ? "ok\n" : "not ok # smtp starttls mail.gmx.de\n";
 
 sub diag { 
        #print STDERR "@_\n" 
diff --git a/t/external/03_lwp.t b/t/external/03_lwp.t
index cd167a2..a6f5853 100644
--- a/t/external/03_lwp.t
+++ b/t/external/03_lwp.t
@@ -3,73 +3,97 @@ use strict;
 use warnings;
 
 BEGIN {
-       eval "use LWP";
-       if ( $@ ) {
-               print "1..0 # no LWP\n";
-               exit
-       }
+    eval "use LWP";
+    if ( $@ ) {
+       print "1..0 # no LWP\n";
+       exit
+    }
 }
 
 use Net::SSLGlue::LWP;
+use IO::Socket::SSL;
 use LWP::Simple;
 
+my $goodhost = 'google.de';
+# this does not work any longer - will be skipped in test
+my $badhost = 'www.fedora.org';
+
 my $capath = '/etc/ssl/certs/'; # unix?
 -d $capath or do {
-       print "1..0 # cannot find system CA-path\n";
-       exit
+    print "1..0 # cannot find system CA-path\n";
+    exit
 };
-Net::SSLGlue::LWP->import( SSL_ca_path => $capath );
+Net::SSLGlue::LWP->import( 
+    SSL_ca_path => $capath, 
+    # LWP might define SSL_ca_file - remove it to avoid conflict
+    SSL_ca_file => undef 
+);
 
 #
 # first check everything directly with IO::Socket::SSL
 #
 
-# signin.ebay.de has a certificate, which is for signin.ebay.com
-# but where signin.ebay.de is a subjectAltName
-IO::Socket::SSL->new(
-       PeerAddr => 'signin.ebay.de:443',
-       SSL_ca_path => $capath,
-       SSL_verify_mode => 1,
-       SSL_verifycn_scheme => 'http'
+diag("connecting to $goodhost:443 with IO::Socket::INET");
+my $sock = IO::Socket::INET->new(
+    PeerAddr => "$goodhost:443",
+    Timeout => 10
 ) or do {
-       print "1..0 # ssl connect signin.ebay.de failed\n";
-       exit
-};
-
-# www.fedora.org has a certificate which has nothing in common 
-# with the hostname
-my $sock = IO::Socket::INET->new( 'www.fedora.org:443' ) or do {
-       print "1..0 # connect to www.fedora.org failed\n";
-       exit
+    print "1..0 # connect $goodhost failed: $!\n";
+    exit
 };
+diag("ssl upgrade $goodhost");
 IO::Socket::SSL->start_SSL( $sock,
+    SSL_ca_path => $capath,
+    SSL_verifycn_name => "$goodhost",
+    SSL_verify_mode => 1,
+    SSL_verifycn_scheme => 'http',
+) or do {
+    print "1..0 # ssl upgrade $goodhost failed: $SSL_ERROR\n";
+    exit
+};
+
+diag("connecting to $badhost:443 with IO::Socket::INET");
+if ( $sock = IO::Socket::INET->new( 
+    PeerAddr => "$badhost:443",
+    Timeout => 10,
+)) {
+    diag("upgrading to https - should fail because of bad certificate");
+    if ( IO::Socket::SSL->start_SSL( $sock,
        SSL_ca_path => $capath,
        SSL_verify_mode => 1,
-       SSL_verifycn_scheme => 'http'
-) and do {
-       print "1..0 # certificate for www.fedora.org unexpectly correct\n";
-       exit
-};
+    )) {
+       diag("certificate for  $badhost unexpectly correct");
+       $badhost = undef;
+    };
+} else {
+    diag("connect to $badhost failed: $!");
+    $badhost = undef;
+}
 
 #
 # and than check, that LWP uses the same checks
 #
 
-print "1..3\n";
+print "1..".( $badhost ? 3:1 )."\n";
 
-# signin.ebay.de -> should succeed
-my $content = get( 'https://signin.ebay.de' );
-print $content ? "ok\n": "not ok # lwp connect signin.ebay.de: $@\n";
+# $goodhost -> should succeed
+diag("connecting to $goodhost:443 with LWP");
+my $content = get( "https://$goodhost"; );
+print $content ? "ok\n": "not ok # lwp connect $goodhost: $@\n";
 
-# www.fedora.org -> should fail
-$content = get( 'https://www.fedora.org' );
-print $content ? "not ok # lwp ssl connect www.fedora.org should fail\n": 
"ok\n";
+if ( $badhost ) {
+    # $badhost -> should fail
+    diag("connecting to $badhost:443 with LWP");
+    $content = get( 'https://$badhost' );
+    print $content ? "not ok # lwp ssl connect $badhost should fail\n": "ok\n";
 
-# www.fedora.org -> should succeed if verify mode is 0
-{
+    # $badhost -> should succeed if verify mode is 0
+    {
        local %Net::SSLGlue::LWP::SSLopts = %Net::SSLGlue::LWP::SSLopts;
        $Net::SSLGlue::LWP::SSLopts{SSL_verify_mode} = 0;
-       $content = get( 'https://www.fedora.org' );
-       print $content ? "ok\n": "not ok # lwp ssl www.fedora.org w/o ssl 
verify\n";
+       $content = get( 'https://$badhost' );
+       print $content ? "ok\n": "not ok # lwp ssl $badhost w/o ssl verify\n";
+    }
 }
 
+sub diag { print "# @_\n" }
diff --git a/t/external/04_pop3.t b/t/external/04_pop3.t
index 4fc3b7e..917a167 100644
--- a/t/external/04_pop3.t
+++ b/t/external/04_pop3.t
@@ -38,20 +38,8 @@ IO::Socket::SSL->new(
        exit
 };
 
-# ssl to the wrong host 
-# the certificate pop.gmx.de returns is for pop.gmx.net
-diag( "connect ssl to pop.gmx.de:995" );
-IO::Socket::SSL->new( 
-       PeerAddr => 'pop.gmx.de:995',
-       SSL_ca_path => $capath,
-       SSL_verify_mode => 1,
-       SSL_verifycn_scheme => 'smtp' 
-) and do {
-       print "1..0 # pop.gmx.de:995 reachable with SSL\n";
-       exit
-};
 
-print "1..6\n";
+print "1..3\n";
 
 # first direct SSL
 my $smtp = Net::POP3->new( 'pop.gmx.net', 
@@ -67,21 +55,6 @@ print $ok ? "ok\n" : "not ok # smtp starttls pop.gmx.net\n";
 # check that we can talk on connection
 print $smtp->quit ? "ok\n": "not ok # quit failed\n";
 
-# against wrong host should fail
-$smtp = Net::POP3->new( 'pop.gmx.de' ); # should succeed
-$ok = $smtp->starttls( SSL_ca_path => $capath ); 
-print $ok ? "not ok # smtp starttls pop.gmx.de did not fail\n": "ok\n";
-
-# but not if we specify the right SSL_verifycn_name
-$smtp = Net::POP3->new( 'pop.gmx.de' ); # should succeed
-$ok = $smtp->starttls( SSL_ca_path => $capath, SSL_verifycn_name => 
'pop.gmx.net' ); 
-print $ok ? "ok\n" : "not ok # smtp starttls pop.gmx.de/net\n";
-
-# or disable verification
-$smtp = Net::POP3->new( 'pop.gmx.de' ); # should succeed
-$ok = $smtp->starttls( SSL_verify_mode => 0 );
-print $ok ? "ok\n" : "not ok # smtp starttls pop.gmx.de\n";
-
 sub diag { 
        #print STDERR "@_\n" 
 }
diff --git a/t/external/05_ftp.t b/t/external/05_ftp.t
new file mode 100644
index 0000000..7a8cbbf
--- /dev/null
+++ b/t/external/05_ftp.t
@@ -0,0 +1,169 @@
+
+use strict;
+use warnings;
+use Test::More;
+
+my $server = 'ftp.rebex.net';
+my $debug = 0;
+
+BEGIN {
+    eval "use Net::FTP";
+    if ( $@ ) {
+       print "1..0 # no Net::FTP\n";
+       exit
+    }
+}
+
+use Net::SSLGlue::FTP;
+use IO::Socket::SSL;
+use File::Temp;
+
+# first try to connect w/o ftp
+# plain
+diag( "connect inet to $server:21" );
+IO::Socket::INET->new( "$server:21" ) or do {
+    plan skip_all => "$server:21 not reachable";
+};
+
+# ssl to the right host
+diag( "connect inet to $server:990" );
+my $sock = IO::Socket::INET->new( "$server:990") or do {
+    plan skip_all => "$server:999 not reachable";
+};
+
+# now we need CAs
+my $cafh = File::Temp->new( UNLINK => 0, SUFFIX => '.crt' );
+my %sslargs = ( SSL_ca_file => $cafh->filename );
+print $cafh <DATA>;
+close($cafh);
+
+diag( "upgrade to ssl $server:990" );
+IO::Socket::SSL->start_SSL($sock,
+    %sslargs,
+    SSL_verify_mode => 1,
+    SSL_verifycn_name => $server,
+    SSL_verifycn_scheme => 'ftp'
+) or do {
+    plan skip_all => "$server:999 not upgradable to SSL: $SSL_ERROR";
+};
+
+plan tests => 9;
+
+# first direct SSL
+diag( "connect ftp over ssl to $server" );
+my $ftp = Net::FTP->new($server,
+    SSL => 1,
+    %sslargs,
+    Debug => $debug,
+    Passive => 1,
+);
+ok($ftp,"ftp ssl connect $server");
+$ftp->login("anonymous",'net-sslglue-...@test.perl')
+    or die "login to $server failed";
+diag("logged in");
+# check that we can talk on connection
+ok(~~$ftp->ls,"directory listing protected");
+$ftp->prot('C');
+ok(~~$ftp->ls,"directory listing clear");
+
+# then TLS upgrade inside plain connection
+$ftp = Net::FTP->new($server, Passive => 1, Debug => $debug);
+ok($ftp,"ftp plain connect $server");
+my $ok = $ftp->starttls(%sslargs);
+ok($ok,"ssl upgrade");
+$ftp->login("anonymous",'net-sslglue-...@test.perl')
+    or die "login to $server failed";
+diag("logged in");
+# check that we can talk on connection
+ok(~~$ftp->ls,"directory listing protected");
+$ftp->prot('C');
+ok(~~$ftp->ls,"directory listing clear");
+$ok = $ftp->stoptls;
+ok($ok,"ssl downgrade");
+ok(~~$ftp->ls,"directory listing after downgrade");
+
+
+__DATA__
+# Subject: C=IL, O=StartCom Ltd., OU=Secure Digital Certificate Signing, 
CN=StartCom Class 1 Primary Intermediate Server CA
+# Issuer:  C=IL, O=StartCom Ltd., OU=Secure Digital Certificate Signing, 
CN=StartCom Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIGNDCCBBygAwIBAgIBGDANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW
+MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg
+Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwHhcNMDcxMDI0MjA1NDE3WhcNMTcxMDI0MjA1NDE3WjCB
+jDELMAkGA1UEBhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4xKzApBgNVBAsT
+IlNlY3VyZSBEaWdpdGFsIENlcnRpZmljYXRlIFNpZ25pbmcxODA2BgNVBAMTL1N0
+YXJ0Q29tIENsYXNzIDEgUHJpbWFyeSBJbnRlcm1lZGlhdGUgU2VydmVyIENBMIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtonGrO8JUngHrJJj0PREGBiE
+gFYfka7hh/oyULTTRwbw5gdfcA4Q9x3AzhA2NIVaD5Ksg8asWFI/ujjo/OenJOJA
+pgh2wJJuniptTT9uYSAK21ne0n1jsz5G/vohURjXzTCm7QduO3CHtPn66+6CPAVv
+kvek3AowHpNz/gfK11+AnSJYUq4G2ouHI2mw5CrY6oPSvfNx23BaKA+vWjhwRRI/
+ME3NO68X5Q/LoKldSKqxYVDLNM08XMML6BDAjJvwAwNi/rJsPnIO7hxDKslIDlc5
+xDEhyBDBLIf+VJVSH1I8MRKbf+fAoKVZ1eKPPvDVqOHXcDGpxLPPr21TLwb0pwID
+AQABo4IBrTCCAakwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
+VR0OBBYEFOtCNNCYsKuf9BtrCPfMZC7vDixFMB8GA1UdIwQYMBaAFE4L7xqkQFul
+F2mHMMo0aEPQQa7yMGYGCCsGAQUFBwEBBFowWDAnBggrBgEFBQcwAYYbaHR0cDov
+L29jc3Auc3RhcnRzc2wuY29tL2NhMC0GCCsGAQUFBzAChiFodHRwOi8vd3d3LnN0
+YXJ0c3NsLmNvbS9zZnNjYS5jcnQwWwYDVR0fBFQwUjAnoCWgI4YhaHR0cDovL3d3
+dy5zdGFydHNzbC5jb20vc2ZzY2EuY3JsMCegJaAjhiFodHRwOi8vY3JsLnN0YXJ0
+c3NsLmNvbS9zZnNjYS5jcmwwgYAGA1UdIAR5MHcwdQYLKwYBBAGBtTcBAgEwZjAu
+BggrBgEFBQcCARYiaHR0cDovL3d3dy5zdGFydHNzbC5jb20vcG9saWN5LnBkZjA0
+BggrBgEFBQcCARYoaHR0cDovL3d3dy5zdGFydHNzbC5jb20vaW50ZXJtZWRpYXRl
+LnBkZjANBgkqhkiG9w0BAQUFAAOCAgEAIQlJPqWIbuALi0jaMU2P91ZXouHTYlfp
+tVbzhUV1O+VQHwSL5qBaPucAroXQ+/8gA2TLrQLhxpFy+KNN1t7ozD+hiqLjfDen
+xk+PNdb01m4Ge90h2c9W/8swIkn+iQTzheWq8ecf6HWQTd35RvdCNPdFWAwRDYSw
+xtpdPvkBnufh2lWVvnQce/xNFE+sflVHfXv0pQ1JHpXo9xLBzP92piVH0PN1Nb6X
+t1gW66pceG/sUzCv6gRNzKkC4/C2BBL2MLERPZBOVmTX3DxDX3M570uvh+v2/miI
+RHLq0gfGabDBoYvvF0nXYbFFSF87ICHpW7LM9NfpMfULFWE7epTj69m8f5SuauNi
+YpaoZHy4h/OZMn6SolK+u/hlz8nyMPyLwcKmltdfieFcNID1j0cHL7SRv7Gifl9L
+WtBbnySGBVFaaQNlQ0lxxeBvlDRr9hvYqbBMflPrj0jfyjO1SPo2ShpTpjMM0InN
+SRXNiTE8kMBy12VLUjWKRhFEuT2OKGWmPnmeXAhEKa2wNREuIU640ucQPl2Eg7PD
+wuTSxv0JS3QJ3fGz0xk+gA2iCxnwOOfFwq/iI9th4p1cbiCJSS4jarJiwUW0n6+L
+p/EiO/h94pDQehn7Skzj0n1fSoMD7SfWI55rjbRZotnvbIIp3XUZPD9MEI3vu3Un
+0q6Dp6jOW6c=
+-----END CERTIFICATE-----
+# Subject: C=IL, O=StartCom Ltd., OU=Secure Digital Certificate Signing, 
CN=StartCom Certification Authority
+# Issuer:  C=IL, O=StartCom Ltd., OU=Secure Digital Certificate Signing, 
CN=StartCom Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEW
+MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg
+Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM3WhcNMzYwOTE3MTk0NjM2WjB9
+MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi
+U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh
+cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk
+pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf
+OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C
+Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT
+Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi
+HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM
+Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w
++2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+
+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3
+Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B
+26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID
+AQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
+VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFul
+F2mHMMo0aEPQQa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCC
+ATgwLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5w
+ZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL2ludGVybWVk
+aWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENvbW1lcmNpYWwgKFN0
+YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0aGUg
+c2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0
+aWZpY2F0aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93
+d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgG
+CWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1
+dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5fPGFf59Jb2vKXfuM/gTF
+wWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWmN3PH/UvS
+Ta0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst
+0OcNOrg+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNc
+pRJvkrKTlMeIFw6Ttn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKl
+CcWw0bdT82AUuoVpaiF8H3VhFyAXe2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVF
+P0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA2MFrLH9ZXF2RsXAiV+uKa0hK
+1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBsHvUwyKMQ5bLm
+KhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE
+JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ
+8dCAWZvLMdibD4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnm
+fyWl8kgAwKQB2j8=
+-----END CERTIFICATE-----

-- 
Alioth's /usr/local/bin/git-commit-notice on 
/srv/git.debian.org/git/pkg-perl/packages/libnet-sslglue-perl.git

_______________________________________________
Pkg-perl-cvs-commits mailing list
Pkg-perl-cvs-commits@lists.alioth.debian.org
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-perl-cvs-commits

Reply via email to