diff --git a/Changes b/Changes index 1bfd076..548c2cc 100644 --- a/Changes +++ b/Changes @@ -1,4 +1,11 @@ Revision history for Perl extension POE::Component::SSLify. + +* 0.10 + + More tweaks of POD - finally close RT #31238 + Added SSL version support - thanks RT #31492 + Added SSL CTX option support as a side effect + Added client.pl example with ReadLine support * 0.09 diff --git a/MANIFEST b/MANIFEST index 5ebd5c8..801d991 100644 --- a/MANIFEST +++ b/MANIFEST @@ -9,3 +9,4 @@ META.yml Changes examples/server.pl +examples/client.pl diff --git a/META.yml b/META.yml index 957d74a..3af09f0 100644 --- a/META.yml +++ b/META.yml @@ -1,6 +1,6 @@ --- #YAML:1.0 name: POE-Component-SSLify -version: 0.09 +version: 0.10 abstract: Makes using SSL in the world of POE easy! license: perl generated_by: ExtUtils::MakeMaker version 6.31 diff --git a/debian/changelog b/debian/changelog index ebc7d24..ec303d1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,11 +1,20 @@ -libpoe-component-sslify-perl (0.09-1) unstable; urgency=low +libpoe-component-sslify-perl (0.10-1) unstable; urgency=low + [ Kees Cook ] * New upstream release. * debian/patches/fix-pod-docs-for-names.patch: dropped -- taken upstream. * debian/control: bumped standards version. * debian/rules: adjusted to follow cleaner stamp conventions. - -- Kees Cook Fri, 07 Dec 2007 15:07:46 -0800 + [ Martín Ferrari ] + * New upstream release (0.10), merged with 0.09 release, as it wasn't + uploaded. + * Removed quilt stuff as there aren't patches anymore. + * debian/copyright: converted to new parseable format. + * debian/rules: updated to avoid creating /usr/lib directories, instead of + deleting them afterwards. + + -- Martín Ferrari Sun, 16 Dec 2007 23:08:38 -0300 libpoe-component-sslify-perl (0.08-1) unstable; urgency=low diff --git a/debian/control b/debian/control index 0bbe813..26093dd 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,7 @@ Priority: optional Maintainer: Debian Perl Group Uploaders: Kees Cook -Build-Depends: debhelper (>= 5.0.0), quilt +Build-Depends: debhelper (>= 5.0.0) Build-Depends-Indep: perl (>= 5.8.8-7), libnet-ssleay-perl, libtest-pod-perl Standards-Version: 3.7.3 Homepage: http://search.cpan.org/dist/POE-Component-SSLify/ diff --git a/debian/copyright b/debian/copyright index 0807df8..1310273 100644 --- a/debian/copyright +++ b/debian/copyright @@ -5,16 +5,20 @@ http://search.cpan.org/dist/POE-Component-SSLify/ The upstream author is: Apocalypse -Copyright: (c) 2007 Apocalypse/Rocco Caputo -License: -This library is free software; you can redistribute it and/or modify -it under the same terms as Perl itself. +Files: * +Copyright: © 2007 Apocalypse/Rocco Caputo +License: GPL-1+ | Artistic + This library is free software; you can redistribute it and/or modify it under + the same terms as Perl itself. +Files: debian/* +Copyright: © 2007 Kees Cook + © 2007 Martín Ferrari +License: GPL-1+ | Artistic -On Debian GNU/Linux systems, the complete text of the GNU General -Public License can be found in `/usr/share/common-licenses/GPL' and -the Artistic Licence in `/usr/share/common-licenses/Artistic'. +Perl is distributed under your choice of the GNU General Public License or the +Artistic License. On Debian GNU/Linux systems, the complete text of the GNU +General Public License can be found in `/usr/share/common-licenses/GPL' and the +Artistic Licence in `/usr/share/common-licenses/Artistic'. -The Debian packaging is (C) 2007, Kees Cook and -is licensed under the same terms as the software itself (see above). diff --git a/debian/patches/series b/debian/patches/series deleted file mode 100644 index e69de29..0000000 diff --git a/debian/rules b/debian/rules index b0a3023..cdc8ac7 100755 --- a/debian/rules +++ b/debian/rules @@ -19,20 +19,20 @@ TMP =$(CURDIR)/debian/$(PACKAGE) -include /usr/share/quilt/quilt.make - build: build-stamp -build-stamp: $(QUILT_STAMPFN) +build-stamp: dh_testdir # Add commands to compile the package here - $(PERL) Makefile.PL INSTALLDIRS=vendor + $(PERL) Makefile.PL INSTALLDIRS=vendor \ + INSTALLVENDORARCH=/usr/share/perl5/ \ + VENDORARCHEXP=/usr/share/perl5/ $(MAKE) $(MAKE) test - touch build-stamp + touch $@ -clean: unpatch +clean: dh_testdir dh_testroot @@ -50,12 +50,7 @@ # Add commands to install the package into debian/$PACKAGE_NAME here $(MAKE) install DESTDIR=$(TMP) PREFIX=/usr - # As this is a architecture independent package, we are not - # supposed to install stuff to /usr/lib. MakeMaker creates - # the dirs, we delete them from the deb: - rmdir --ignore-fail-on-non-empty --parents $(TMP)/usr/lib/perl5 - - touch install-stamp + touch $@ binary-arch: # We have nothing to do here for an architecture-independent package diff --git a/examples/client.pl b/examples/client.pl new file mode 100644 index 0000000..ddceed4 --- /dev/null +++ b/examples/client.pl @@ -0,0 +1,103 @@ +#!/usr/bin/perl +use strict; use warnings; + +use POE; +use POE::Component::SSLify qw( Client_SSLify ); +use POE::Wheel::ReadWrite; +use POE::Wheel::SocketFactory; +use POE::Driver::SysRW; +use POE::Filter::Line; +use POE::Wheel::ReadLine; + +POE::Session->create( + 'inline_states' => { + '_start' => sub { + # Set the alias + $_[KERNEL]->alias_set( 'main' ); + + # Setup our ReadLine stuff + $_[HEAP]->{'RL'} = POE::Wheel::ReadLine->new( + 'InputEvent' => 'Got_ReadLine', + ); + + # Connect to the server! + $_[KERNEL]->yield( 'do_connect' ); + return 1; + }, + 'do_connect' => sub { + # Create the socketfactory wheel to listen for requests + $_[HEAP]->{'SOCKETFACTORY'} = POE::Wheel::SocketFactory->new( + 'RemotePort' => 5432, + 'RemoteAddress' => 'localhost', + 'Reuse' => 'yes', + 'SuccessEvent' => 'Got_Connection', + 'FailureEvent' => 'ConnectError', + ); + return 1; + }, + 'Got_ReadLine' => sub { + if ( defined $_[ARG0] ) { + if ( exists $_[HEAP]->{'WHEEL'} ) { + $_[HEAP]->{'WHEEL'}->put( $_[ARG0] ); + } + } else { + if ( $_[ARG1] eq 'interrupt' ) { + die 'stopped'; + } + } + }, + 'Got_Connection' => sub { + # ARG0 = Socket, ARG1 = Remote Address, ARG2 = Remote Port + my $socket = $_[ ARG0 ]; + + # SSLify it! + $socket = Client_SSLify( $socket ); + + # Hand it off to ReadWrite + my $wheel = POE::Wheel::ReadWrite->new( + 'Handle' => $socket, + 'Driver' => POE::Driver::SysRW->new(), + 'Filter' => POE::Filter::Line->new(), + 'InputEvent' => 'Got_Input', + 'ErrorEvent' => 'Got_Error', + ); + + # Store it... + $_[HEAP]->{'WHEEL'} = $wheel; + $_[HEAP]->{'RL'}->put( 'Connected to SSL server' ); + $_[HEAP]->{'RL'}->get( 'Input: ' ); + + return 1; + }, + 'ConnectError' => sub { + # ARG0 = operation, ARG1 = error number, ARG2 = error string, ARG3 = wheel ID + my ( $operation, $errnum, $errstr, $wheel_id ) = @_[ ARG0 .. ARG3 ]; + warn "SocketFactory Wheel $wheel_id generated $operation error $errnum: $errstr\n"; + delete $_[HEAP]->{'SOCKETFACTORY'}; + $_[HEAP]->{'RL'}->put( 'Unable to connect to SSL server...' ); + $_[KERNEL]->delay_set( 'do_connect', 5 ); + return 1; + }, + 'Got_Input' => sub { + # ARG0: The Line, ARG1: Wheel ID + + # Send back to the client the line! + $_[HEAP]->{'RL'}->put( 'Got Reply: ' . $_[ARG0] ); + $_[HEAP]->{'RL'}->get( 'Input: ' ); + return 1; + }, + 'Got_Error' => sub { + # ARG0 = operation, ARG1 = error number, ARG2 = error string, ARG3 = wheel ID + my ( $operation, $errnum, $errstr, $id ) = @_[ ARG0 .. ARG3 ]; + warn "Wheel $id generated $operation error $errnum: $errstr\n"; + delete $_[HEAP]->{'WHEEL'}; + $_[HEAP]->{'RL'}->put( 'Disconnected from SSL server...' ); + $_[KERNEL]->delay_set( 'do_connect', 5 ); + return 1; + }, + }, +); + +# Start POE! +POE::Kernel->run(); +exit 0; diff --git a/examples/server.pl b/examples/server.pl index 5b96402..a7fb076 100644 --- a/examples/server.pl +++ b/examples/server.pl @@ -1,3 +1,6 @@ +#!/usr/bin/perl +use strict; use warnings; + use POE; use POE::Component::SSLify qw( Server_SSLify SSLify_Options ); use POE::Wheel::ReadWrite; @@ -5,23 +8,24 @@ use POE::Driver::SysRW; use POE::Filter::Line; -# Needs to generate the SSL certs before running this! - -POE::Session->new( +POE::Session->create( 'inline_states' => { '_start' => sub { # Okay, set the SSL options - SSLify_Options( 'public-key.pem', 'public-cert.pem' ); + SSLify_Options( 'server.key', 'server.crt', 'default' ); + + # Set the alias + $_[KERNEL]->alias_set( 'main' ); # Create the socketfactory wheel to listen for requests $_[HEAP]->{'SOCKETFACTORY'} = POE::Wheel::SocketFactory->new( 'BindPort' => 5432, - 'BindAddress' => localhost, + 'BindAddress' => 'localhost', 'Reuse' => 'yes', 'SuccessEvent' => 'Got_Connection', 'FailureEvent' => 'ListenerError', ); - return; + return 1; }, 'Got_Connection' => sub { # ARG0 = Socket, ARG1 = Remote Address, ARG2 = Remote Port @@ -42,26 +46,25 @@ # Store it... $_[HEAP]->{'WHEELS'}->{ $wheel->ID } = $wheel; - return; + return 1; }, 'ListenerError' => sub { # ARG0 = operation, ARG1 = error number, ARG2 = error string, ARG3 = wheel ID my ( $operation, $errnum, $errstr, $wheel_id ) = @_[ ARG0 .. ARG3 ]; warn "SocketFactory Wheel $wheel_id generated $operation error $errnum: $errstr\n"; - return; + return 1; }, 'Got_Input' => sub { # ARG0: The Line, ARG1: Wheel ID # Send back to the client the line! $_[HEAP]->{'WHEELS'}->{ $_[ARG1] }->put( $_[ARG0] ); - return; + return 1; }, 'Got_Flush' => sub { - # Done with a wheel - delete $_[HEAP]->{'WHEELS'}->{ $_[ARG0] }; - return; + # We don't care about this event + return 1; }, 'Got_Error' => sub { # ARG0 = operation, ARG1 = error number, ARG2 = error string, ARG3 = wheel ID @@ -70,7 +73,7 @@ # Done with a wheel delete $_[HEAP]->{'WHEELS'}->{ $_[ARG0] }; - return; + return 1; }, }, ); diff --git a/lib/POE/Component/SSLify/ClientHandle.pm b/lib/POE/Component/SSLify/ClientHandle.pm index bb652f8..99157d0 100644 --- a/lib/POE/Component/SSLify/ClientHandle.pm +++ b/lib/POE/Component/SSLify/ClientHandle.pm @@ -6,9 +6,9 @@ use warnings FATAL => 'all'; # Enable warnings to catch errors # Initialize our version -# $Revision: 1223 $ +# $Revision: 1247 $ use vars qw( $VERSION ); -$VERSION = '0.03'; +$VERSION = '0.04'; # Import the SSL death routines use Net::SSLeay qw( die_now die_if_ssl_error ); @@ -19,9 +19,30 @@ # Override TIEHANDLE because we create a CTX sub TIEHANDLE { - my ( $class, $socket ) = @_; + my ( $class, $socket, $version, $options ) = @_; - my $ctx = Net::SSLeay::CTX_new() or die_now( "Failed to create SSL_CTX $!" ); + my $ctx; + if ( defined $version and ! ref $version ) { + if ( $version eq 'sslv2' ) { + $ctx = Net::SSLeay::CTX_v2_new(); + } elsif ( $version eq 'sslv3' ) { + $ctx = Net::SSLeay::CTX_v3_new(); + } elsif ( $version eq 'tlsv1' ) { + $ctx = Net::SSLeay::CTX_tlsv1_new(); + } elsif ( $version eq 'default' ) { + $ctx = Net::SSLeay::CTX_new(); + } else { + die "unknown SSL version: $version"; + } + } else { + $ctx = Net::SSLeay::CTX_new(); + } + $ctx || die_now( "Failed to create SSL_CTX $!" ); + + if ( defined $options ) { + Net::SSLeay::CTX_set_options( $ctx, $options ) and die_if_ssl_error( 'ssl ctx set options' ); + } + my $ssl = Net::SSLeay::new( $ctx ) or die_now( "Failed to create SSL $!" ); my $fileno = fileno( $socket ); @@ -58,6 +79,7 @@ 1; __END__ + =head1 NAME POE::Component::SSLify::ClientHandle - client object for POE::Component::SSLify @@ -94,7 +116,7 @@ =head1 COPYRIGHT AND LICENSE -Copyright 2006 by Apocalypse/Rocco Caputo +Copyright 2007 by Apocalypse/Rocco Caputo This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. diff --git a/lib/POE/Component/SSLify/ServerHandle.pm b/lib/POE/Component/SSLify/ServerHandle.pm index e55cafa..8306c30 100644 --- a/lib/POE/Component/SSLify/ServerHandle.pm +++ b/lib/POE/Component/SSLify/ServerHandle.pm @@ -6,7 +6,7 @@ use warnings FATAL => 'all'; # Enable warnings to catch errors # Initialize our version -# $Revision: 1223 $ +# $Revision: 1247 $ use vars qw( $VERSION ); $VERSION = '0.04'; @@ -161,6 +161,7 @@ 1; __END__ + =head1 NAME POE::Component::SSLify::ServerHandle - server object for POE::Component::SSLify diff --git a/lib/POE/Component/SSLify.pm b/lib/POE/Component/SSLify.pm index 2aeadc5..0241bd5 100644 --- a/lib/POE/Component/SSLify.pm +++ b/lib/POE/Component/SSLify.pm @@ -6,8 +6,8 @@ use warnings FATAL => 'all'; # Enable warnings to catch errors # Initialize our version -# $Revision: 1223 $ -our $VERSION = '0.09'; +# $Revision: 1248 $ +our $VERSION = '0.10'; # We need Net::SSLeay or all's a failure! BEGIN { @@ -97,8 +97,8 @@ # Okay, the main routine here! sub Client_SSLify { - # Get the socket! - my $socket = shift; + # Get the socket + version + options + my( $socket, $version, $options ) = @_; # Validation... if ( ! defined $socket ) { @@ -110,7 +110,7 @@ # Now, we create the new socket and bind it to our subclass of Net::SSLeay::Handle my $newsock = gensym(); - tie( *$newsock, 'POE::Component::SSLify::ClientHandle', $socket ) or die "Unable to tie to our subclass: $!"; + tie( *$newsock, 'POE::Component::SSLify::ClientHandle', $socket, $version, $options ) or die "Unable to tie to our subclass: $!"; # All done! return $newsock; @@ -142,13 +142,35 @@ return $newsock; } -# Sets the key + certificate sub SSLify_Options { - # Get the key + cert - my( $key, $cert ) = @_; - - $ctx = Net::SSLeay::CTX_new() or die_now( "CTX_new($ctx): $!" ); - Net::SSLeay::CTX_set_options( $ctx, &Net::SSLeay::OP_ALL ) and die_if_ssl_error( 'ssl ctx set options' ); + # Get the key + cert + version + options + my( $key, $cert, $version, $options ) = @_; + + if ( defined $version and ! ref $version ) { + if ( $version eq 'sslv2' ) { + $ctx = Net::SSLeay::CTX_v2_new(); + } elsif ( $version eq 'sslv3' ) { + $ctx = Net::SSLeay::CTX_v3_new(); + } elsif ( $version eq 'tlsv1' ) { + $ctx = Net::SSLeay::CTX_tlsv1_new(); + } elsif ( $version eq 'default' ) { + $ctx = Net::SSLeay::CTX_new(); + } else { + die "unknown SSL version: $version"; + } + } else { + $ctx = Net::SSLeay::CTX_new(); + } + if ( ! defined $ctx ) { + die_now( "Failed to create SSL_CTX $!" ); + } + + # Set the default + if ( ! defined $options ) { + $options = &Net::SSLeay::OP_ALL; + } + + Net::SSLeay::CTX_set_options( $ctx, $options ) and die_if_ssl_error( 'ssl ctx set options' ); # Following will ask password unless private key is not encrypted Net::SSLeay::CTX_use_RSAPrivateKey_file( $ctx, $key, &Net::SSLeay::FILETYPE_PEM ); @@ -183,6 +205,7 @@ 1; __END__ + =head1 NAME POE::Component::SSLify - Makes using SSL in the world of POE easy! @@ -214,19 +237,16 @@ =head2 Server-side usage # !!! Make sure you have a public key + certificate generated via Net::SSLeay's makecert.pl + # excellent howto: http://www.akadia.com/services/ssh_test_certificate.html # Import the module - use POE::Component::SSLify qw( Server_SSLify SSLify_Options SSLify_GetCTX ); + use POE::Component::SSLify qw( Server_SSLify SSLify_Options ); # Set the key + certificate file - eval { SSLify_Options( 'public-key.pem', 'public-cert.pem' ) }; + eval { SSLify_Options( 'server.key', 'server.crt' ) }; if ( $@ ) { # Unable to load key or certificate file... } - - # Ah, I want to set some options ( not required ) - # my $ctx = SSLify_GetCTX(); - # Net::SSLeay::CTX_set_options( $ctx, foo ); # Create a normal SocketFactory wheel or something my $factory = POE::Wheel::SocketFactory->new( ... ); @@ -287,6 +307,19 @@ Accepts a socket, returns a brand new socket SSLified + Optionally accepts the SSL version + CTX options + Client_SSLify( $socket, $version, $options ); + + Known versions: + * sslv2 + * sslv3 + * tlsv1 + * default + + By default we use the version: default + + By default we don't set any options + =head2 Server_SSLify Accepts a socket, returns a brand new socket SSLified @@ -296,6 +329,19 @@ =head2 SSLify_Options Accepts the location of the SSL key + certificate files and does it's job + + Optionally accepts the SSL version + CTX options + SSLify_Options( $key, $cert, $version, $options ); + + Known versions: + * sslv2 + * sslv3 + * tlsv1 + * default + + By default we use the version: default + + By default we use the options: &Net::SSLeay::OP_ALL =head2 SSLify_GetCTX