diff --git a/Build.PL b/Build.PL index 13f62d7..acdfbdf 100644 --- a/Build.PL +++ b/Build.PL @@ -24,7 +24,7 @@ 'Apocalypse ' ], 'dist_name' => 'POE-Component-SSLify', - 'dist_version' => '1.005', + 'dist_version' => '1.008', 'license' => 'perl', 'module_name' => 'POE::Component::SSLify', 'recommends' => {}, @@ -33,6 +33,7 @@ 'Exporter' => '0', 'IO::Handle' => '1.28', 'Net::SSLeay' => '1.36', + 'POE' => '0', 'Scalar::Util' => '0', 'Symbol' => '0', 'Task::Weaken' => '1.03', diff --git a/Changes b/Changes index dc0f614..2fbb31c 100644 --- a/Changes +++ b/Changes @@ -1,4 +1,23 @@ Revision history for Perl extension POE::Component::SSLify. + +1.008 + Released: 2011-05-04 21:55:27 UTC + + Bazerka@irc noticed that POE wasn't even listed as a runtime prereq, d0h! + +1.007 + Released: 2011-05-04 21:36:32 UTC + + Revert the ENGINE load logic added in 1.004 because it was causing coredumps on netbsd ( thanks BINGOS! ) + Add the constant LOAD_SSL_ENGINES sub if you need to load the ssl engines + Tweak the renegotiate tests to be more tolerant of failures, thanks RCAPUTO - RT#66741 + +1.006 + Released: 2011-04-22 00:21:51 UTC + + Fix a heinous bug where openssl will randomly+reliably close a connection ( thanks MIRE ) + Tweak the hook tests so they test the case where no data is sent over the connection + Tweak the connfail tests so they work better 1.005 Released: 2011-03-10 07:55:30 UTC diff --git a/CommitLog b/CommitLog index 5193eae..78488f4 100644 --- a/CommitLog +++ b/CommitLog @@ -2,6 +2,135 @@ 9999-99-99 99:99:99 +0000 HEAD ============================== + commit 4fa0a44b7f0a9b37ef5fcbcb07ad6e45dd50b265 + Author: Apocalypse + Date: Wed May 4 14:53:14 2011 -0700 + + actually require POE as a runtime prereq, thanks Bazerka@irc + +======================================= +2011-05-04 14:37:11 -0700 release-1.007 +======================================= + + commit 5ada288a8ab2b24c6472e5a8fb3f43958fa22445 + Author: Apocalypse + Date: Wed May 4 14:37:11 2011 -0700 + + New CPAN release of POE-Component-SSLify - v1.007 + + Released: 2011-05-04 21:36:32 UTC + + Revert the ENGINE load logic added in 1.004 because it was causing + coredumps on netbsd ( thanks BINGOS! ) + + Add the constant LOAD_SSL_ENGINES sub if you need to load the ssl + engines + + Tweak the renegotiate tests to be more tolerant of failures, thanks + RCAPUTO - RT#66741 + + commit 958b153b6d09773230336793b1a3f2f2848a55dc + Author: Apocalypse + Date: Wed May 4 14:34:15 2011 -0700 + + rename some POD for pod::coverage tests + + commit 125745d00aa051e13a18ac207a618c50913bbd57 + Author: Apocalypse + Date: Wed May 4 14:21:22 2011 -0700 + + rewrite the renegotiate tests in hope of fixing RT#66741 + + commit 393337624aef50602f4f2e9ff4ec412e1cbe7d76 + Author: Apocalypse + Date: Wed May 4 14:02:59 2011 -0700 + + fix netbsd coredumps by not loading ENGINEs, reported by BINGOS + +======================================= +2011-04-21 17:22:30 -0700 release-1.006 +======================================= + + commit 0096f51336380c31d99e87cf93a63ed650e60aff + Author: Apocalypse + Date: Thu Apr 21 17:22:30 2011 -0700 + + New CPAN release of POE-Component-SSLify - v1.006 + + Released: 2011-04-22 00:21:51 UTC + + Fix a heinous bug where openssl will randomly+reliably close a + connection ( thanks MIRE ) + + Tweak the hook tests so they test the case where no data is sent over + the connection + + Tweak the connfail tests so they work better + + commit df65edee2621f55f347db2c70d779e44d93b87d2 + Author: Apocalypse + Date: Thu Apr 21 17:16:15 2011 -0700 + + mire@irc is now MIRE, congrats + + commit 853522b575570c997d3c8ff70c530cd45cde1e40 + Author: Apocalypse + Date: Thu Apr 21 14:54:08 2011 -0700 + + tweak mires test a bit + + commit e745765e01f9c07e0b195b2c49be40bea2e916f4 + Author: Apocalypse + Date: Thu Apr 21 08:28:42 2011 -0700 + + start of work on mire's testcase + + commit 15e3d473b68e6e0ac36673bbc71b7125fd49ed2f + Author: Apocalypse + Date: Thu Apr 21 00:03:23 2011 -0700 + + add mire test to be worked into a proper AUTHOR test + + commit ad5c8c95dce50c051d8c54ade4c90b45f49103c3 + Author: Apocalypse + Date: Wed Apr 20 20:44:15 2011 -0700 + + update changelog for the fixes + + commit ed9e2b33c10572df76e790ffad68d3d7ecb820f9 + Author: Apocalypse + Date: Wed Apr 20 20:11:17 2011 -0700 + + fix random SSL failures, spotted by mire + + commit 5a9b28e587a3dace6ed71bd93691215b47cbc348 + Author: Apocalypse + Date: Wed Apr 20 20:09:00 2011 -0700 + + tweak the connfail tests and make the server test work + + commit 806d4c4df5ca108c8cfacbb19babcfebc8b05cdc + Author: Apocalypse + Date: Wed Apr 20 20:08:18 2011 -0700 + + tweak the hook tests to cover the case where there is no data sent + over the wire + +======================================= +2011-03-10 00:56:13 -0700 release-1.005 +======================================= + + commit bc1a271e1f6e597f42cf03723ef6525a21281bea + Author: Apocalypse + Date: Thu Mar 10 00:56:13 2011 -0700 + + New CPAN release of POE-Component-SSLify - v1.005 + + Released: 2011-03-10 07:55:30 UTC + + Fix the connfail tests due to an incorrect assumption regards socket + close value, thanks CPANTesters! + commit d8b4c0e354acf683f17fd63186810226e101b54e Author: Apocalypse Date: Thu Mar 10 00:54:05 2011 -0700 diff --git a/MANIFEST b/MANIFEST index 6cd300a..cc2cfc7 100644 --- a/MANIFEST +++ b/MANIFEST @@ -22,9 +22,13 @@ t/00-compile.t t/000-report-versions-tiny.t t/1_simple.t -t/2_renegotiate.t +t/2_renegotiate_client.t t/3_upgrade.t t/4_connect_hook.t t/5_connfail_client.t t/6_connfail_server.t +t/7_connect_hook_nodata.t +t/8_renegotiate_server.t +t/98_renegotiate.t +t/99_mire_test.t t/apocalypse.t diff --git a/META.json b/META.json index 59f0e34..81b245d 100644 --- a/META.json +++ b/META.json @@ -36,6 +36,7 @@ "Exporter" : 0, "IO::Handle" : "1.28", "Net::SSLeay" : "1.36", + "POE" : 0, "Scalar::Util" : 0, "Symbol" : 0, "Task::Weaken" : "1.03", @@ -58,15 +59,15 @@ "provides" : { "POE::Component::SSLify" : { "file" : "lib/POE/Component/SSLify.pm", - "version" : "1.005" + "version" : "1.008" }, "POE::Component::SSLify::ClientHandle" : { "file" : "lib/POE/Component/SSLify/ClientHandle.pm", - "version" : "1.005" + "version" : "1.008" }, "POE::Component::SSLify::ServerHandle" : { "file" : "lib/POE/Component/SSLify/ServerHandle.pm", - "version" : "1.005" + "version" : "1.008" } }, "release_status" : "stable", @@ -85,7 +86,7 @@ "web" : "http://github.com/apocalypse/perl-poe-sslify" } }, - "version" : "1.005", + "version" : "1.008", "x_BuiltWith" : { "modules" : { "Exporter" : "5.63", @@ -94,7 +95,7 @@ "IO::Handle" : "1.28", "Module::Build" : "0.3607", "Net::SSLeay" : "1.36", - "POE" : "1.299", + "POE" : "1.310", "POE::Component::Client::TCP" : "1.299", "POE::Component::Server::TCP" : "1.299", "Scalar::Util" : "1.23", @@ -162,7 +163,7 @@ { "class" : "Dist::Zilla::Plugin::ReportVersions::Tiny", "name" : "@Apocalyptic/ReportVersions::Tiny", - "version" : "1.02" + "version" : "1.03" }, { "class" : "Dist::Zilla::Plugin::Prepender", @@ -172,7 +173,7 @@ { "class" : "Dist::Zilla::Plugin::Authority", "name" : "@Apocalyptic/Authority", - "version" : "1.003" + "version" : "1.005" }, { "class" : "Dist::Zilla::Plugin::PkgVersion", @@ -197,7 +198,7 @@ { "class" : "Dist::Zilla::Plugin::MinimumPerl", "name" : "@Apocalyptic/MinimumPerl", - "version" : "1.001" + "version" : "1.003" }, { "class" : "Dist::Zilla::Plugin::Bugtracker", diff --git a/META.yml b/META.yml index 6a976ea..7c858c8 100644 --- a/META.yml +++ b/META.yml @@ -28,17 +28,18 @@ provides: POE::Component::SSLify: file: lib/POE/Component/SSLify.pm - version: 1.005 + version: 1.008 POE::Component::SSLify::ClientHandle: file: lib/POE/Component/SSLify/ClientHandle.pm - version: 1.005 + version: 1.008 POE::Component::SSLify::ServerHandle: file: lib/POE/Component/SSLify/ServerHandle.pm - version: 1.005 + version: 1.008 requires: Exporter: 0 IO::Handle: 1.28 Net::SSLeay: 1.36 + POE: 0 Scalar::Util: 0 Symbol: 0 Task::Weaken: 1.03 @@ -49,7 +50,7 @@ homepage: http://search.cpan.org/dist/POE-Component-SSLify/ license: http://dev.perl.org/licenses/ repository: git://github.com/apocalypse/perl-poe-sslify.git -version: 1.005 +version: 1.008 x_BuiltWith: modules: Exporter: 5.63 @@ -58,7 +59,7 @@ IO::Handle: 1.28 Module::Build: 0.3607 Net::SSLeay: 1.36 - POE: 1.299 + POE: 1.310 POE::Component::Client::TCP: 1.299 POE::Component::Server::TCP: 1.299 Scalar::Util: 1.23 @@ -114,7 +115,7 @@ - class: Dist::Zilla::Plugin::ReportVersions::Tiny name: '@Apocalyptic/ReportVersions::Tiny' - version: 1.02 + version: 1.03 - class: Dist::Zilla::Plugin::Prepender name: '@Apocalyptic/Prepender' @@ -122,7 +123,7 @@ - class: Dist::Zilla::Plugin::Authority name: '@Apocalyptic/Authority' - version: 1.003 + version: 1.005 - class: Dist::Zilla::Plugin::PkgVersion name: '@Apocalyptic/PkgVersion' @@ -142,7 +143,7 @@ - class: Dist::Zilla::Plugin::MinimumPerl name: '@Apocalyptic/MinimumPerl' - version: 1.001 + version: 1.003 - class: Dist::Zilla::Plugin::Bugtracker name: '@Apocalyptic/Bugtracker' diff --git a/Makefile.PL b/Makefile.PL index a7c5b1c..367db3b 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -32,12 +32,13 @@ 'Exporter' => '0', 'IO::Handle' => '1.28', 'Net::SSLeay' => '1.36', + 'POE' => '0', 'Scalar::Util' => '0', 'Symbol' => '0', 'Task::Weaken' => '1.03', 'parent' => '0' }, - 'VERSION' => '1.005', + 'VERSION' => '1.008', 'test' => { 'TESTS' => 't/*.t' } diff --git a/README b/README index b557db5..52e2299 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ POE::Component::SSLify - Makes using SSL in the world of POE easy! VERSION - This document describes v1.005 of POE::Component::SSLify - released March 10, 2011 as part of POE-Component-SSLify. + This document describes v1.008 of POE::Component::SSLify - released May 04, 2011 as part of POE-Component-SSLify. SYNOPSIS # CLIENT-side usage @@ -299,8 +299,8 @@ function against SSLify, so use them carefully! Net::SSLeay::renegotiate - This function has been tested ( it's in "t/2_renegotiate.t" ) but it - doesn't work on FreeBSD! I tracked it down to this security advisory: + This function has been tested ( it's in "t/2_renegotiate_client.t" ) but + it doesn't work on FreeBSD! I tracked it down to this security advisory: which explains it in detail. The test will skip this function if it detects that you're on a broken system. However, if you have the updated OpenSSL @@ -326,6 +326,16 @@ developer, I'm unable to fix this. However, it seems like Cygwin on MSWin32 works just fine! Please help me fix this if you can, thanks! + LOAD_SSL_ENGINES + OpenSSL supports loading ENGINEs to accelerate the crypto algorithms. + SSLify v1.004 automatically loaded the engines, but there was some + problems on certain platforms that caused coredumps. A big shout-out to + BinGOs and CPANTesters for catching this! It's now disabled in v1.007 + and you would need to explicitly enable it. + + sub POE::Component::SSLify::LOAD_SSL_ENGINES () { 1 } + use POE::Component::SSLify qw( Client::SSLify ); + EXPORT Stuffs all of the functions in @EXPORT_OK so you have to request them directly. @@ -351,35 +361,64 @@ * Search CPAN + The default CPAN search engine, useful to view POD in HTML format. + * RT: CPAN's Bug Tracker + The RT ( Request Tracker ) website is the default bug/issue tracking + system for CPAN. + - * AnnoCPAN: Annotated CPAN documentation + * AnnoCPAN + + The AnnoCPAN is a website that allows community annonations of Perl + module documentation. * CPAN Ratings + The CPAN Ratings is a website that allows community ratings and + reviews of Perl modules. + * CPAN Forum + The CPAN Forum is a web forum for discussing Perl modules. + - * CPANTS Kwalitee + * CPANTS + + The CPANTS is a website that analyzes the Kwalitee ( code metrics ) + of a distribution. - * CPAN Testers Results - - + * CPAN Testers + + The CPAN Testers is a network of smokers who run automated tests on + uploaded CPAN distributions. + + * CPAN Testers Matrix + The CPAN Testers Matrix is a website that provides a visual way to + determine what Perls/platforms PASSed for a distribution. + + + * CPAN Testers Dependencies + + The CPAN Testers Dependencies is a website that shows a chart of the + test results of all dependencies for a distribution. + + Email You can email the author of this module at "APOCAL at cpan.org" asking diff --git a/SIGNATURE b/SIGNATURE index befcaf0..fd97bfb 100644 --- a/SIGNATURE +++ b/SIGNATURE @@ -14,39 +14,43 @@ -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 -SHA1 74d0a53111acfd4b4b7f9c269175a06e77309d86 Build.PL -SHA1 0e7543ad72ae31c532a8298fae8a3c98cdc87e86 Changes -SHA1 375fe756ad481b99709cf16d1a5378a7dee530ef CommitLog +SHA1 db814b600c64a9dbf43916f952d61724c9cb5629 Build.PL +SHA1 6f3f477a7be6adda1715f4f6232d1c23f1b0c73a Changes +SHA1 6a0020176172c6097eb86b34ef42014654df64f3 CommitLog SHA1 e3edc44697d1770c65fec99f6ebdb6ea55fb3050 INSTALL SHA1 263360e99a0de4d587fedefe1a919dcf61af1d10 LICENSE -SHA1 1baae2c8b4d91da92fdf35c5542137380f00c9e4 MANIFEST +SHA1 3117aae7a178cf1a5ef1c6fbbd9af19a36462dbc MANIFEST SHA1 9dfc07c5655b958e800189837f3ddd37ca050bfe MANIFEST.SKIP -SHA1 bfa76e8e9cf9ce09d4b4fd98883f6d1b0639a4f6 META.json -SHA1 5a4ea0cc9966848930db2129a75c3cf6bea77a45 META.yml -SHA1 842e80effc5a192dd7d9ca2176d58985abb70a4c Makefile.PL -SHA1 781198b6246cacc4b4c336bbacb47320a658f024 README +SHA1 e248fce45784dc1e74a6632ae73dab4408806755 META.json +SHA1 b7979650243be1fb48f457c7f3ad7ec6ee9fd424 META.yml +SHA1 88399f5f9ea5f4cff1f2899fde9b6434fa6525fb Makefile.PL +SHA1 013286bba5f5a9bdbefd457b13cb150f53c87711 README SHA1 41a5da1356107d097f6bbf72c62ee4da83e4119f dist.ini SHA1 96decb1c51052f9b024b6d069e428b4ccc19e909 examples/client.pl SHA1 d8f9b44df461cdcf6cbd7cffd79a9d49aade3947 examples/server.pl SHA1 c4a936c75d1d566e936dfb1776c9a01ea244c618 examples/serverclient.pl -SHA1 21353f9c92b51a2a27604af460d08f6993da9a28 lib/POE/Component/SSLify.pm -SHA1 620bcbd8febf6eb4d4f066479c895b90302dedfd lib/POE/Component/SSLify/ClientHandle.pm -SHA1 444dbb2e912dc3d94494ddb316b1950612d38288 lib/POE/Component/SSLify/ServerHandle.pm +SHA1 7c470b55e86d0fc80ca4b60ba3dfb0ab1781591d lib/POE/Component/SSLify.pm +SHA1 ee5c6b2eb8109cc96d9f60c2eb993da305f959cf lib/POE/Component/SSLify/ClientHandle.pm +SHA1 9ee769ea86ff4ad984bfba8c643e74cc0bcfaaba lib/POE/Component/SSLify/ServerHandle.pm SHA1 59afa28f138a14b956443f915d60a891d5b306b8 mylib/example.crt SHA1 f2ba02d28cfb207e0a86be7cb4f3c570f257bf93 mylib/example.key SHA1 fd48b12e3df15fb55695e7d1b4ee95dc3c0cd766 t/00-compile.t -SHA1 9df6d0a549121f4e7db1cabbdb703d59aa821f85 t/000-report-versions-tiny.t +SHA1 4788d9aa069d03cc4c94ef15e11e8a0e0527561c t/000-report-versions-tiny.t SHA1 9ade9d7296a3511f42ce3010dd7d215630d51c80 t/1_simple.t -SHA1 0d6e08c744e377933f75c6d9fa25c37e3506d1a5 t/2_renegotiate.t +SHA1 949de479ef156e3845bf64adb21a9556af0420a6 t/2_renegotiate_client.t SHA1 73790060e55b0189540d898a97c485e187f05ae9 t/3_upgrade.t -SHA1 f8ba954e2a5bf546c3932eb9cc1ba9bf89a57385 t/4_connect_hook.t -SHA1 4c7ecc5d6221a593b5961f53205eb016a1eee3bd t/5_connfail_client.t -SHA1 89fa487c62b3e6aadc33bd1025bec93f2aabdc1d t/6_connfail_server.t +SHA1 3c6e64d27262d54d7b31c2d4f2e65f5d6cab87cf t/4_connect_hook.t +SHA1 520cb166745d10fa749372ce686240dafd0da543 t/5_connfail_client.t +SHA1 295f221b5001822ac23244030fb1b8be1bd838e8 t/6_connfail_server.t +SHA1 156f6b65482911b3be5c8f3ce8c07071c5308d1b t/7_connect_hook_nodata.t +SHA1 377a10c6d96cd1a23922526c44c43cd723dafcfd t/8_renegotiate_server.t +SHA1 5bb02868a0a8d995272800bc945f6db2669d291e t/98_renegotiate.t +SHA1 8f73eec992bcb37639f49945d986ff5a59a1ca36 t/99_mire_test.t SHA1 e3b390873d4de642e25fcfb4b7d16c00b096d24a t/apocalypse.t -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) -iEYEARECAAYFAk14g/0ACgkQGfr7vsGKgxzbqQCfVAAlTNCFi81uhNCljGXLGqOp -BC4AoIytDbvdcMRaIj3mHDJP7ugIZyd9 -=rNNR +iEYEARECAAYFAk3By1oACgkQGfr7vsGKgxx47ACfTzDqglDL4xb266x3RMOBG3AJ +xj0AoNyF1h2KqHOYNVVImQmGy6UIw8D5 +=qxVp -----END PGP SIGNATURE----- diff --git a/lib/POE/Component/SSLify/ClientHandle.pm b/lib/POE/Component/SSLify/ClientHandle.pm index 0149bf5..83dcb1d 100644 --- a/lib/POE/Component/SSLify/ClientHandle.pm +++ b/lib/POE/Component/SSLify/ClientHandle.pm @@ -9,7 +9,7 @@ use strict; use warnings; package POE::Component::SSLify::ClientHandle; BEGIN { - $POE::Component::SSLify::ClientHandle::VERSION = '1.005'; + $POE::Component::SSLify::ClientHandle::VERSION = '1.008'; } BEGIN { $POE::Component::SSLify::ClientHandle::AUTHORITY = 'cpan:APOCAL'; @@ -73,7 +73,7 @@ =head1 VERSION - This document describes v1.005 of POE::Component::SSLify::ClientHandle - released March 10, 2011 as part of POE-Component-SSLify. + This document describes v1.008 of POE::Component::SSLify::ClientHandle - released May 04, 2011 as part of POE-Component-SSLify. =head1 DESCRIPTION diff --git a/lib/POE/Component/SSLify/ServerHandle.pm b/lib/POE/Component/SSLify/ServerHandle.pm index c49bf3d..95572bd 100644 --- a/lib/POE/Component/SSLify/ServerHandle.pm +++ b/lib/POE/Component/SSLify/ServerHandle.pm @@ -9,7 +9,7 @@ use strict; use warnings; package POE::Component::SSLify::ServerHandle; BEGIN { - $POE::Component::SSLify::ServerHandle::VERSION = '1.005'; + $POE::Component::SSLify::ServerHandle::VERSION = '1.008'; } BEGIN { $POE::Component::SSLify::ServerHandle::AUTHORITY = 'cpan:APOCAL'; @@ -43,10 +43,23 @@ 'fileno' => $fileno, 'status' => $res, 'on_connect' => $connref, + 'ssl_started' => 0, }, $class; return $self; } + +# TODO should we make a convenience function to convert retval to string equivalents for easier debugging? +# From OpenSSL 1.0.0d +#define SSL_ERROR_NONE 0 +#define SSL_ERROR_SSL 1 +#define SSL_ERROR_WANT_READ 2 +#define SSL_ERROR_WANT_WRITE 3 +#define SSL_ERROR_WANT_X509_LOOKUP 4 +#define SSL_ERROR_SYSCALL 5 /* look at error stack/return value/errno */ +#define SSL_ERROR_ZERO_RETURN 6 +#define SSL_ERROR_WANT_CONNECT 7 +#define SSL_ERROR_WANT_ACCEPT 8 sub _check_status { my $self = shift; @@ -59,22 +72,36 @@ $self->{'status'} = Net::SSLeay::accept( $self->{'ssl'} ); } - # Only process the stuff if we actually have a callback! - return unless defined $self->{'on_connect'}; - if ( $self->{'status'} <= 0 ) { # http://www.openssl.org/docs/ssl/SSL_get_error.html my $errval = Net::SSLeay::get_error( $self->{'ssl'}, $self->{'status'} ); + # Handle the case of ERROR_WANT_READ and ERROR_WANT_WRITE # TODO should we skip ERROR_WANT_ACCEPT and ERROR_WANT_CONNECT ? # also, ERROR_WANT_ACCEPT isn't exported by Net::SSLeay, huh? - if ( $errval != ERROR_WANT_READ and $errval != ERROR_WANT_WRITE ) { + if ( $errval == ERROR_WANT_READ or $errval == ERROR_WANT_WRITE ) { + # continue reading/writing from the socket until we connect or not... + return 1; + } else { # call the hook function for error connect - $self->{'on_connect'}->( $self->{'orig_socket'}, 0, $errval ); + if ( defined $self->{'on_connect'} ) { + $self->{'on_connect'}->( $self->{'orig_socket'}, 0, $errval ); + } + + # don't try to read/write from the socket anymore! + return 0; } } elsif ( $self->{'status'} == 1 ) { + # SSL handshake is done! + $self->{'ssl_started'} = 1; + # call the hook function for successful connect - $self->{'on_connect'}->( $self->{'orig_socket'}, 1 ); + if ( defined $self->{'on_connect'} ) { + $self->{'on_connect'}->( $self->{'orig_socket'}, 1 ); + } + + # we can now read/write from the socket! + return 1; } } @@ -86,8 +113,10 @@ # Get the pointers to buffer, length, and the offset my( $buf, $len, $offset ) = \( @_ ); - # Check connection status - $self->_check_status if $self->{'status'} <= 0; + # Check the status of the SSL handshake + if ( ! $self->{'ssl_started'} ) { + return if $self->_check_status == 0; + } # If we have no offset, replace the buffer with some input if ( ! defined $$offset ) { @@ -95,6 +124,8 @@ # Are we done? if ( defined $$buf ) { + # TODO do we need the same "flush is success" logic in WRITE? + return length( $$buf ); } else { # Nah, clear the buffer too... @@ -106,6 +137,8 @@ # Now, actually read the data defined( my $read = Net::SSLeay::read( $self->{'ssl'}, $$len ) ) or return; + # TODO do we need the same "flush is success" logic in WRITE? + # Figure out the buffer and offset my $buf_len = length( $$buf ); @@ -126,8 +159,11 @@ # Get ourself + buffer + length + offset to write my( $self, $buf, $len, $offset ) = @_; - # Check connection status - $self->_check_status if $self->{'status'} <= 0; + # Check the status of the SSL handshake + if ( ! $self->{'ssl_started'} ) { + # The normal syswrite() POE uses expects 0 here. + return 0 if $self->_check_status == 0; + } # If we have nothing to offset, then start from the beginning if ( ! defined $offset ) { @@ -144,6 +180,20 @@ # The normal syswrite() POE uses expects 0 here. return 0; } else { + # We flushed some data, which means we finished the handshake! + # This is IMPORTANT, as MIRE found out! + # Otherwise openssl will zonk out and give us SSL_ERROR_SSL and things randomly break :( + # this is because we tried to connect() or accept() and the handshake was done... or something like that hah + if ( ! $self->{'ssl_started'} ) { + $self->{'ssl_started'} = 1; + $self->{'status'} = 1; + + # call the hook function for successful connect + if ( defined $self->{'on_connect'} ) { + $self->{'on_connect'}->( $self->{'orig_socket'}, 1 ); + } + } + # All done! return $wrote_len; } @@ -225,7 +275,7 @@ =head1 VERSION - This document describes v1.005 of POE::Component::SSLify::ServerHandle - released March 10, 2011 as part of POE-Component-SSLify. + This document describes v1.008 of POE::Component::SSLify::ServerHandle - released May 04, 2011 as part of POE-Component-SSLify. =head1 DESCRIPTION diff --git a/lib/POE/Component/SSLify.pm b/lib/POE/Component/SSLify.pm index 3d72fd6..5a801ab 100644 --- a/lib/POE/Component/SSLify.pm +++ b/lib/POE/Component/SSLify.pm @@ -9,13 +9,53 @@ use strict; use warnings; package POE::Component::SSLify; BEGIN { - $POE::Component::SSLify::VERSION = '1.005'; + $POE::Component::SSLify::VERSION = '1.008'; } BEGIN { $POE::Component::SSLify::AUTHORITY = 'cpan:APOCAL'; } # ABSTRACT: Makes using SSL in the world of POE easy! + +BEGIN { + # should fix netbsd smoke failures, thanks BinGOs! + # Apocal: okay cores with a 0.9.7d I've built myself from source. Doesn't if I comment out engine lines. + # BinGOs did an awesome job building various versions of openssl to try and track down the problem, it seems like + # newer versions of openssl worked fine on netbsd, but I don't want to do crazy stuff like probing openssl versions + # as it's fragile - best to let the user figure it out :) + # + # see http://www.cpantesters.org/cpan/report/1a660280-6eb1-11e0-a462-e9956c33433b + # http://www.cpantesters.org/cpan/report/49a9f2aa-6df2-11e0-a462-e9956c33433b + # http://www.cpantesters.org/cpan/report/78d9a234-6df5-11e0-a462-e9956c33433b + # and many other reports :( + # + #(gdb) bt + ##0 0xbd9d3e7e in engine_table_select () from /usr/lib/libcrypto.so.2 + ##1 0xbd9b3bed in ENGINE_get_default_RSA () from /usr/lib/libcrypto.so.2 + ##2 0xbd9b1f6d in RSA_new_method () from /usr/lib/libcrypto.so.2 + ##3 0xbd9b1cf6 in RSA_new () from /usr/lib/libcrypto.so.2 + ##4 0xbd9cf8a1 in RSAPrivateKey_asn1_meth () from /usr/lib/libcrypto.so.2 + ##5 0xbd9da64b in ASN1_item_ex_new () from /usr/lib/libcrypto.so.2 + ##6 0xbd9da567 in ASN1_item_ex_new () from /usr/lib/libcrypto.so.2 + ##7 0xbd9d88cc in ASN1_item_ex_d2i () from /usr/lib/libcrypto.so.2 + ##8 0xbd9d8437 in ASN1_item_d2i () from /usr/lib/libcrypto.so.2 + ##9 0xbd9cf8d5 in d2i_RSAPrivateKey () from /usr/lib/libcrypto.so.2 + ##10 0xbd9ad546 in d2i_PrivateKey () from /usr/lib/libcrypto.so.2 + ##11 0xbd995e63 in PEM_read_bio_PrivateKey () from /usr/lib/libcrypto.so.2 + ##12 0xbd980430 in PEM_read_bio_RSAPrivateKey () from /usr/lib/libcrypto.so.2 + ##13 0xbda2e9dc in SSL_CTX_use_RSAPrivateKey_file () from /usr/lib/libssl.so.3 + ##14 0xbda5aabe in XS_Net__SSLeay_CTX_use_RSAPrivateKey_file (cv=0x8682c80) + # at SSLeay.c:1716 + ##15 0x08115401 in Perl_pp_entersub () at pp_hot.c:2885 + ##16 0x080e0ab7 in Perl_runops_debug () at dump.c:2049 + ##17 0x08078624 in S_run_body (oldscope=1) at perl.c:2308 + ##18 0x08077ef2 in perl_run (my_perl=0x823f030) at perl.c:2233 + ##19 0x0805e321 in main (argc=3, argv=0xbfbfe6a0, env=0xbfbfe6b0) + # at perlmain.c:117 + ##20 0x0805e0c6 in ___start () + #(gdb) + if ( ! defined &LOAD_SSL_ENGINES ) { *LOAD_SSL_ENGINES = sub () { 0 } } +} # We need Net::SSLeay or all's a failure! BEGIN { @@ -35,8 +75,10 @@ # Taken from http://search.cpan.org/~flora/Net-SSLeay-1.36/lib/Net/SSLeay.pm#Low_level_API Net::SSLeay::load_error_strings(); Net::SSLeay::SSLeay_add_ssl_algorithms(); - Net::SSLeay::ENGINE_load_builtin_engines(); - Net::SSLeay::ENGINE_register_all_complete(); + if ( LOAD_SSL_ENGINES ) { + Net::SSLeay::ENGINE_load_builtin_engines(); + Net::SSLeay::ENGINE_register_all_complete(); + } Net::SSLeay::randomize(); } } @@ -58,6 +100,9 @@ # Use Scalar::Util's weaken() for the connref stuff use Scalar::Util qw( weaken ); use Task::Weaken 1.03; # to make sure it actually works! + +# load POE ( just to fool dzil AutoPrereqs :) +require POE; # The server-side CTX stuff my $ctx; @@ -282,7 +327,7 @@ =head1 VERSION - This document describes v1.005 of POE::Component::SSLify - released March 10, 2011 as part of POE-Component-SSLify. + This document describes v1.008 of POE::Component::SSLify - released May 04, 2011 as part of POE-Component-SSLify. =head1 SYNOPSIS @@ -573,8 +618,8 @@ =head3 Net::SSLeay::renegotiate -This function has been tested ( it's in C ) but it doesn't work on FreeBSD! I tracked it down to this security advisory: -L which explains it in detail. The test will skip this function +This function has been tested ( it's in C ) but it doesn't work on FreeBSD! I tracked it down to this security +advisory: L which explains it in detail. The test will skip this function if it detects that you're on a broken system. However, if you have the updated OpenSSL library that fixes this you can use it. NOTE: Calling this means the callback function you passed in L or L will not fire! If you need this @@ -594,6 +639,15 @@ This module doesn't work on MSWin32 platforms at all ( XP, Vista, 7, etc ) because of some weird underlying fd issues. Since I'm not a windows developer, I'm unable to fix this. However, it seems like Cygwin on MSWin32 works just fine! Please help me fix this if you can, thanks! +=head2 LOAD_SSL_ENGINES + +OpenSSL supports loading ENGINEs to accelerate the crypto algorithms. SSLify v1.004 automatically loaded the engines, but there was some +problems on certain platforms that caused coredumps. A big shout-out to BinGOs and CPANTesters for catching this! It's now disabled in v1.007 +and you would need to explicitly enable it. + + sub POE::Component::SSLify::LOAD_SSL_ENGINES () { 1 } + use POE::Component::SSLify qw( Client::SSLify ); + =head1 EXPORT Stuffs all of the functions in @EXPORT_OK so you have to request them directly. @@ -633,17 +687,23 @@ Search CPAN +The default CPAN search engine, useful to view POD in HTML format. + L =item * RT: CPAN's Bug Tracker +The RT ( Request Tracker ) website is the default bug/issue tracking system for CPAN. + L =item * -AnnoCPAN: Annotated CPAN documentation +AnnoCPAN + +The AnnoCPAN is a website that allows community annonations of Perl module documentation. L @@ -651,31 +711,49 @@ CPAN Ratings +The CPAN Ratings is a website that allows community ratings and reviews of Perl modules. + L =item * CPAN Forum +The CPAN Forum is a web forum for discussing Perl modules. + L =item * -CPANTS Kwalitee +CPANTS + +The CPANTS is a website that analyzes the Kwalitee ( code metrics ) of a distribution. L =item * -CPAN Testers Results - -L +CPAN Testers + +The CPAN Testers is a network of smokers who run automated tests on uploaded CPAN distributions. + +L =item * CPAN Testers Matrix +The CPAN Testers Matrix is a website that provides a visual way to determine what Perls/platforms PASSed for a distribution. + L + +=item * + +CPAN Testers Dependencies + +The CPAN Testers Dependencies is a website that shows a chart of the test results of all dependencies for a distribution. + +L =back diff --git a/t/000-report-versions-tiny.t b/t/000-report-versions-tiny.t index 6905453..ba335fc 100644 --- a/t/000-report-versions-tiny.t +++ b/t/000-report-versions-tiny.t @@ -9,6 +9,9 @@ END { $success && done_testing; } my $v = "\n"; + +# List our own version used to generate this +$v .= "Generated by Dist::Zilla::Plugin::ReportVersions::Tiny v1.03\n"; eval { # no excuses! # report our Perl details @@ -71,7 +74,7 @@ Thanks for using my code. I hope it works for you. If not, please try and include this output in the bug report. -That will help me reproduce the issue and solve you problem. +That will help me reproduce the issue and solve your problem. EOT diff --git a/t/2_renegotiate.t b/t/2_renegotiate.t deleted file mode 100644 index 8943d5d..0000000 --- a/t/2_renegotiate.t +++ /dev/null @@ -1,217 +0,0 @@ -#!/usr/bin/perl -# -# This file is part of POE-Component-SSLify -# -# This software is copyright (c) 2011 by Apocalypse. -# -# This is free software; you can redistribute it and/or modify it under -# the same terms as the Perl 5 programming language system itself. -# -use strict; use warnings; -use strict; use warnings; - -# Thanks to ASCENT for this test! -# This test adds renegotiation to the connection from client-side -# Since this is not supported on all platforms, it's marked TODO and adds custom logic -# to make sure it doesn't FAIL if it's not supported. - -my $numtests; -BEGIN { - $numtests = 23; - - eval "use Test::NoWarnings"; - if ( ! $@ ) { - # increment by one - $numtests++; - } -} - -use Test::More tests => $numtests; - -use POE 1.267; -use POE::Component::Client::TCP; -use POE::Component::Server::TCP; -use POE::Component::SSLify qw/Client_SSLify Server_SSLify SSLify_Options SSLify_GetCipher SSLify_ContextCreate SSLify_GetSocket SSLify_GetSSL/; -use Net::SSLeay qw/ERROR_WANT_READ ERROR_WANT_WRITE/; - -# TODO rewrite this to use Test::POE::Server::TCP and stuff :) - -my $port; -my $server_ping2; -my $client_ping2; - -POE::Component::Server::TCP->new -( - Alias => 'myserver', - Address => '127.0.0.1', - Port => 0, - - Started => sub - { - use Socket qw/sockaddr_in/; - $port = (sockaddr_in($_[HEAP]->{listener}->getsockname))[0]; - }, - ClientConnected => sub - { - ok(1, 'SERVER: accepted'); - }, - ClientDisconnected => sub - { - ok(1, 'SERVER: client disconnected'); - $_[KERNEL]->post(myserver => 'shutdown'); - }, - ClientPreConnect => sub - { - eval { SSLify_Options('mylib/example.key', 'mylib/example.crt', 'sslv3') }; - eval { SSLify_Options('../mylib/example.key', '../mylib/example.crt', 'sslv3') } if ($@); - ok(!$@, "SERVER: SSLify_Options $@"); - - my $socket = eval { Server_SSLify($_[ARG0]) }; - ok(!$@, "SERVER: Server_SSLify $@"); - ok(1, 'SERVER: SSLify_GetCipher: '. SSLify_GetCipher($socket)); - - # We pray that IO::Handle is sane... - ok( SSLify_GetSocket( $socket )->blocking == 0, 'SERVER: SSLified socket is non-blocking?'); - - return ($socket); - }, - ClientInput => sub - { - my ($kernel, $heap, $request) = @_[KERNEL, HEAP, ARG0]; - - ## At this point, connection MUST be encrypted. - my $cipher = SSLify_GetCipher($heap->{client}->get_output_handle); - ok($cipher ne '(NONE)', "SERVER: SSLify_GetCipher: $cipher"); - - if ($request eq 'ping') - { - ok(1, "SERVER: recv: $request"); - $heap->{client}->put("pong"); - } - elsif ($request eq 'ping2') - { - ok(1, "SERVER: recv: $request"); - $server_ping2++; - $heap->{client}->put("pong2"); - } - }, - ClientError => sub - { - # Thanks to H. Merijn Brand for spotting this FAIL in 5.12.0! - # The default PoCo::Server::TCP handler will throw a warning, which causes Test::NoWarnings to FAIL :( - my ($syscall, $errno, $error) = @_[ ARG0..ARG2 ]; - - # TODO are there other "errors" that is harmless? - $error = "Normal disconnection" unless $error; - my $msg = "Got SERVER $syscall error $errno: $error"; - unless ( $syscall eq 'read' and $errno == 0 ) { - fail( $msg ); - } else { - diag( $msg ) if $ENV{TEST_VERBOSE}; - } - }, -); - -POE::Component::Client::TCP->new -( - Alias => 'myclient', - RemoteAddress => '127.0.0.1', - RemotePort => $port, - - Connected => sub - { - ok(1, 'CLIENT: connected'); - - $_[HEAP]->{server}->put("ping"); - }, - PreConnect => sub - { - my $ctx = eval { SSLify_ContextCreate(undef, undef, 'sslv3') }; - ok(!$@, "CLIENT: SSLify_ContextCreate $@"); - my $socket = eval { Client_SSLify($_[ARG0], undef, undef, $ctx) }; - ok(!$@, "CLIENT: Client_SSLify $@"); - ok(1, 'CLIENT: SSLify_GetCipher: '. SSLify_GetCipher($socket)); - - # We pray that IO::Handle is sane... - ok( SSLify_GetSocket( $socket )->blocking == 0, 'CLIENT: SSLified socket is non-blocking?'); - - return ($socket); - }, - ServerInput => sub - { - my ($kernel, $heap, $line) = @_[KERNEL, HEAP, ARG0]; - - ## At this point, connection MUST be encrypted. - my $cipher = SSLify_GetCipher($heap->{server}->get_output_handle); - ok($cipher ne '(NONE)', "CLIENT: SSLify_GetCipher: $cipher"); - - if ($line eq 'pong') - { - ok(1, "CLIENT: recv: $line"); - - # Skip 2 Net::SSLeay::renegotiate() tests on FreeBSD because of - # http://security.freebsd.org/advisories/FreeBSD-SA-09:15.ssl.asc - TODO: { - local $TODO = "Net::SSLeay::renegotiate() does not work on all platforms"; - - ## Force SSL renegotiation - my $ssl = SSLify_GetSSL( $heap->{server}->get_output_handle ); - my $reneg_num = Net::SSLeay::num_renegotiations($ssl); - - ok(1 == Net::SSLeay::renegotiate($ssl), 'CLIENT: SSL renegotiation'); - my $handshake = Net::SSLeay::do_handshake($ssl); - my $err = Net::SSLeay::get_error($ssl, $handshake); - - ## 1 == Successful handshake, ERROR_WANT_(READ|WRITE) == non-blocking. - ok($handshake == 1 || $err == ERROR_WANT_READ || $err == ERROR_WANT_WRITE, 'CLIENT: SSL handshake'); - ok($reneg_num < Net::SSLeay::num_renegotiations($ssl), 'CLIENT: Increased number of negotiations'); - } - - $heap->{server}->put('ping2'); - } - - elsif ($line eq 'pong2') - { - ok(1, "CLIENT: recv: $line"); - $client_ping2++; - $kernel->yield('shutdown'); - } - }, - ServerError => sub - { - # Thanks to H. Merijn Brand for spotting this FAIL in 5.12.0! - # The default PoCo::Client::TCP handler will throw a warning, which causes Test::NoWarnings to FAIL :( - my ($syscall, $errno, $error) = @_[ ARG0..ARG2 ]; - - # TODO are there other "errors" that is harmless? - $error = "Normal disconnection" unless $error; - my $msg = "Got CLIENT $syscall error $errno: $error"; - unless ( $syscall eq 'read' and $errno == 0 ) { - fail( $msg ); - } else { - diag( $msg ) if $ENV{TEST_VERBOSE}; - } - }, -); - -$poe_kernel->run(); - -# Add extra pass() to make the test harness happy if renegotiate did not work -if ( ! $server_ping2 ) { - local $TODO = "Net::SSLeay::renegotiate() does not work on all platforms"; - fail( "SERVER: Failed SSL renegotiation" ); -} -if ( ! $client_ping2 ) { - local $TODO = "Net::SSLeay::renegotiate() does not work on all platforms"; - fail( "CLIENT: Failed SSL renegotiation" ); -} -if ( ! $server_ping2 or ! $client_ping2 ) { - diag( "WARNING: Your platform/SSL library does not support renegotiation of the SSL socket." ); - diag( "This test harness detected that trying to renegotiate resulted in a disconnected socket." ); - diag( "POE::Component::SSLify will work on your system, but please do not attempt a SSL renegotiate." ); - diag( "Please talk with the author to figure out if this issue can be worked around, thank you!" ); -} - -pass( 'shut down sanely' ); - -exit 0; diff --git a/t/2_renegotiate_client.t b/t/2_renegotiate_client.t new file mode 100644 index 0000000..2d0738b --- /dev/null +++ b/t/2_renegotiate_client.t @@ -0,0 +1,188 @@ +#!/usr/bin/perl +# +# This file is part of POE-Component-SSLify +# +# This software is copyright (c) 2011 by Apocalypse. +# +# This is free software; you can redistribute it and/or modify it under +# the same terms as the Perl 5 programming language system itself. +# +use strict; use warnings; +use strict; use warnings; + +# Thanks to ASCENT for this test! +# This test adds renegotiation to the connection from client-side + +# In an older version of this test, there was ok() littered everywhere +# but dngor replied in http://rt.cpan.org/Public/Bug/Display.html?id=66741 +# that it's not going to work... how do I predict which ok() will fail and "simulate" them? +# the solution was to... only run a few tests and print the diag +# because the rest of the tests just redo what we already have in 1_simple.t and stuff... + +my $numtests; +BEGIN { + $numtests = 16; + + eval "use Test::NoWarnings"; + if ( ! $@ ) { + # increment by one + $numtests++; + } +} + +use Test::More tests => $numtests; + +use POE 1.267; +use POE::Component::Client::TCP; +use POE::Component::Server::TCP; +use POE::Component::SSLify qw/Client_SSLify Server_SSLify SSLify_Options SSLify_GetCipher SSLify_ContextCreate SSLify_GetSocket SSLify_GetSSL/; +use Net::SSLeay qw/ERROR_WANT_READ ERROR_WANT_WRITE/; + +# TODO rewrite this to use Test::POE::Server::TCP and stuff :) + +my $port; +my $server_ping2; +my $client_ping2; + +POE::Component::Server::TCP->new +( + Alias => 'myserver', + Address => '127.0.0.1', + Port => 0, + + Started => sub + { + use Socket qw/sockaddr_in/; + $port = (sockaddr_in($_[HEAP]->{listener}->getsockname))[0]; + }, + ClientConnected => sub + { + ok(1, 'SERVER: accepted'); + }, + ClientDisconnected => sub + { + ok(1, 'SERVER: client disconnected'); + $_[KERNEL]->post(myserver => 'shutdown'); + }, + ClientPreConnect => sub + { + eval { SSLify_Options('mylib/example.key', 'mylib/example.crt', 'sslv3') }; + eval { SSLify_Options('../mylib/example.key', '../mylib/example.crt', 'sslv3') } if ($@); + ok(!$@, "SERVER: SSLify_Options $@"); + + my $socket = eval { Server_SSLify($_[ARG0]) }; + ok(!$@, "SERVER: Server_SSLify $@"); + ok(1, 'SERVER: SSLify_GetCipher: '. SSLify_GetCipher($socket)); + + # We pray that IO::Handle is sane... + ok( SSLify_GetSocket( $socket )->blocking == 0, 'SERVER: SSLified socket is non-blocking?'); + + return ($socket); + }, + ClientInput => sub + { + my ($kernel, $heap, $line) = @_[KERNEL, HEAP, ARG0]; + + if ($line eq 'ping') { + ok(1, "SERVER: recv: $line"); + + ## At this point, connection MUST be encrypted. + my $cipher = SSLify_GetCipher($heap->{client}->get_output_handle); + ok($cipher ne '(NONE)', "SERVER: SSLify_GetCipher: $cipher"); + + $heap->{client}->put("pong"); + } elsif ($line eq 'ping2') { + $server_ping2++; + $heap->{client}->put("pong2"); + } else { + die "Unknown line from CLIENT: $line"; + } + }, + ClientError => sub + { + # Thanks to H. Merijn Brand for spotting this FAIL in 5.12.0! + # The default PoCo::Server::TCP handler will throw a warning, which causes Test::NoWarnings to FAIL :( + my ($syscall, $errno, $error) = @_[ ARG0..ARG2 ]; + + # TODO are there other "errors" that is harmless? + $error = "Normal disconnection" unless $error; + my $msg = "Got SERVER $syscall error $errno: $error"; + unless ( $syscall eq 'read' and $errno == 0 ) { +# fail( $msg ); + } else { + diag( $msg ) if $ENV{TEST_VERBOSE}; + } + }, +); + +POE::Component::Client::TCP->new +( + Alias => 'myclient', + RemoteAddress => '127.0.0.1', + RemotePort => $port, + + Connected => sub + { + ok(1, 'CLIENT: connected'); + + $_[HEAP]->{server}->put("ping"); + }, + PreConnect => sub + { + my $ctx = eval { SSLify_ContextCreate(undef, undef, 'sslv3') }; + ok(!$@, "CLIENT: SSLify_ContextCreate $@"); + my $socket = eval { Client_SSLify($_[ARG0], undef, undef, $ctx) }; + ok(!$@, "CLIENT: Client_SSLify $@"); + ok(1, 'CLIENT: SSLify_GetCipher: '. SSLify_GetCipher($socket)); + + # We pray that IO::Handle is sane... + ok( SSLify_GetSocket( $socket )->blocking == 0, 'CLIENT: SSLified socket is non-blocking?'); + + return ($socket); + }, + ServerInput => sub + { + my ($kernel, $heap, $line) = @_[KERNEL, HEAP, ARG0]; + + if ($line eq 'pong') { + ok(1, "CLIENT: recv: $line"); + + ## At this point, connection MUST be encrypted. + my $cipher = SSLify_GetCipher($heap->{server}->get_output_handle); + ok($cipher ne '(NONE)', "CLIENT: SSLify_GetCipher: $cipher"); + + # do the actual renegotiate + Net::SSLeay::renegotiate( SSLify_GetSSL( $heap->{server}->get_output_handle ) ); + + $heap->{server}->put('ping2'); + } elsif ($line eq 'pong2') { + $client_ping2++; + $kernel->yield('shutdown'); + } else { + die "Unknown line from SERVER: $line"; + } + }, + ServerError => sub + { + # Thanks to H. Merijn Brand for spotting this FAIL in 5.12.0! + # The default PoCo::Client::TCP handler will throw a warning, which causes Test::NoWarnings to FAIL :( + my ($syscall, $errno, $error) = @_[ ARG0..ARG2 ]; + + $error = "Normal disconnection" unless $error; + my $msg = "Got CLIENT $syscall error $errno: $error"; + diag( $msg ) if $ENV{TEST_VERBOSE}; + }, +); + +$poe_kernel->run(); + +if ( ! $server_ping2 or ! $client_ping2 ) { + diag( "WARNING: Your platform/SSL library does not support renegotiation of the SSL socket." ); + diag( "This test harness detected that trying to renegotiate resulted in a disconnected socket." ); + diag( "POE::Component::SSLify will work on your system, but please do not attempt a SSL renegotiate." ); + diag( "Please talk with the author to figure out if this issue can be worked around, thank you!" ); +} + +pass( 'shut down sanely' ); + +exit 0; diff --git a/t/4_connect_hook.t b/t/4_connect_hook.t index 50fe55c..0464fcf 100644 --- a/t/4_connect_hook.t +++ b/t/4_connect_hook.t @@ -14,7 +14,7 @@ my $numtests; BEGIN { - $numtests = 17; + $numtests = 19; eval "use Test::NoWarnings"; if ( ! $@ ) { @@ -80,7 +80,12 @@ { my ($kernel, $heap, $line) = @_[KERNEL, HEAP, ARG0]; - die "Unknown line from CLIENT: $line"; + if ( $line ne 'ping' ) { + die "Unknown line from CLIENT: $line"; + } else { + ok(1, "SERVER: recv: $line"); + $_[HEAP]->{client}->put("pong"); + } }, ClientError => sub { @@ -108,21 +113,20 @@ Connected => sub { ok(1, 'CLIENT: connected'); + $_[HEAP]->{server}->put("ping"); }, PreConnect => sub { my $socket = eval { Client_SSLify($_[ARG0], sub { my( $socket, $status, $errval ) = @_; - pass( "CLIENT: Got callback hook" ); + pass( "CLIENT: Got callback hook status" ); is( $status, 1, "CLIENT: Status received from callback is OK" ); ## At this point, connection MUST be encrypted. my $cipher = SSLify_GetCipher($socket); ok($cipher ne '(NONE)', "CLIENT: SSLify_GetCipher: $cipher"); ok( SSLify_GetStatus($socket) == 1, "CLIENT: SSLify_GetStatus is done" ); - - $poe_kernel->post( 'myclient' => 'shutdown' ); }) }; ok(!$@, "CLIENT: Client_SSLify $@"); ok( SSLify_GetStatus($socket) == -1, "CLIENT: SSLify_GetStatus is pending" ); @@ -133,7 +137,12 @@ { my ($kernel, $heap, $line) = @_[KERNEL, HEAP, ARG0]; - die "Should have never got any input from the server!"; + if ( $line ne 'pong' ) { + die "Unknown line from CLIENT: $line"; + } else { + ok(1, "CLIENT: recv: $line"); + $kernel->yield('shutdown'); + } }, ServerError => sub { diff --git a/t/5_connfail_client.t b/t/5_connfail_client.t index 65d4b62..fc77155 100644 --- a/t/5_connfail_client.t +++ b/t/5_connfail_client.t @@ -48,6 +48,9 @@ ClientConnected => sub { ok(1, 'SERVER: accepted'); + + # purposefully send garbage so we screw up the ssl connect on the client-side + $_[HEAP]->{client}->put( 'garbage in, garbage out' ); }, ClientDisconnected => sub { diff --git a/t/6_connfail_server.t b/t/6_connfail_server.t index 338e8c6..200b943 100644 --- a/t/6_connfail_server.t +++ b/t/6_connfail_server.t @@ -14,20 +14,16 @@ my $numtests; BEGIN { - $numtests = 8; + $numtests = 9; -# eval "use Test::NoWarnings"; -# if ( ! $@ ) { -# # increment by one -# $numtests++; -# } + eval "use Test::NoWarnings"; + if ( ! $@ ) { + # increment by one + $numtests++; + } } -# For some reason I can't get this to replicate 5_connfail_client.t - wonder why?!#? -# I tried to use POE::Filter::Stream to see if it made a difference, nope... -#use Test::More tests => $numtests; -use Test::More; -plan skip_all => "This test hangs for some reason"; +use Test::More tests => $numtests; use POE 1.267; use POE::Component::Client::TCP; @@ -101,6 +97,9 @@ Connected => sub { ok(1, 'CLIENT: connected'); + + # purposefully send garbage so we screw up the ssl connect on the client-side + $_[HEAP]->{server}->put( 'garbage in, garbage out' ); }, ServerInput => sub { diff --git a/t/7_connect_hook_nodata.t b/t/7_connect_hook_nodata.t new file mode 100644 index 0000000..17e9340 --- /dev/null +++ b/t/7_connect_hook_nodata.t @@ -0,0 +1,159 @@ +#!/usr/bin/perl +# +# This file is part of POE-Component-SSLify +# +# This software is copyright (c) 2011 by Apocalypse. +# +# This is free software; you can redistribute it and/or modify it under +# the same terms as the Perl 5 programming language system itself. +# +use strict; use warnings; +use strict; use warnings; + +# This tests the connection OK hook on both server/client + +my $numtests; +BEGIN { + $numtests = 17; + + eval "use Test::NoWarnings"; + if ( ! $@ ) { + # increment by one + $numtests++; + } +} + +use Test::More tests => $numtests; + +use POE 1.267; +use POE::Component::Client::TCP; +use POE::Component::Server::TCP; +use POE::Component::SSLify qw/Client_SSLify Server_SSLify SSLify_Options SSLify_GetCipher SSLify_GetSocket SSLify_GetStatus/; + +# TODO rewrite this to use Test::POE::Server::TCP and stuff :) + +my $port; + +POE::Component::Server::TCP->new +( + Alias => 'myserver', + Address => '127.0.0.1', + Port => 0, + + Started => sub + { + use Socket qw/sockaddr_in/; + $port = (sockaddr_in($_[HEAP]->{listener}->getsockname))[0]; + }, + ClientConnected => sub + { + ok(1, 'SERVER: accepted'); + }, + ClientDisconnected => sub + { + ok(1, 'SERVER: client disconnected'); + $_[KERNEL]->post( 'myserver' => 'shutdown'); + }, + ClientPreConnect => sub + { + eval { SSLify_Options('mylib/example.key', 'mylib/example.crt') }; + eval { SSLify_Options('../mylib/example.key', '../mylib/example.crt') } if ($@); + ok(!$@, "SERVER: SSLify_Options $@"); + + my $socket = eval { Server_SSLify( $_[ARG0], sub { + my( $socket, $status, $errval ) = @_; + + pass( "SERVER: Got callback hook" ); + is( $status, 1, "SERVER: Status received from callback is OK" ); + + ## At this point, connection MUST be encrypted. + my $cipher = SSLify_GetCipher($socket); + ok($cipher ne '(NONE)', "SERVER: SSLify_GetCipher: $cipher"); + ok( SSLify_GetStatus($socket) == 1, "SERVER: SSLify_GetStatus is done" ); + } ) }; + ok(!$@, "SERVER: Server_SSLify $@"); + ok( SSLify_GetStatus($socket) == -1, "SERVER: SSLify_GetStatus is pending" ); + + return ($socket); + }, + ClientInput => sub + { + my ($kernel, $heap, $line) = @_[KERNEL, HEAP, ARG0]; + + die "Should have never got any input from the client!"; + }, + ClientError => sub + { + # Thanks to H. Merijn Brand for spotting this FAIL in 5.12.0! + # The default PoCo::Server::TCP handler will throw a warning, which causes Test::NoWarnings to FAIL :( + my ($syscall, $errno, $error) = @_[ ARG0..ARG2 ]; + + # TODO are there other "errors" that is harmless? + $error = "Normal disconnection" unless $error; + my $msg = "Got SERVER $syscall error $errno: $error"; + unless ( $syscall eq 'read' and $errno == 0 ) { + fail( $msg ); + } else { + diag( $msg ) if $ENV{TEST_VERBOSE}; + } + }, +); + +POE::Component::Client::TCP->new +( + Alias => 'myclient', + RemoteAddress => '127.0.0.1', + RemotePort => $port, + + Connected => sub + { + ok(1, 'CLIENT: connected'); + }, + PreConnect => sub + { + my $socket = eval { Client_SSLify($_[ARG0], sub { + my( $socket, $status, $errval ) = @_; + + pass( "CLIENT: Got callback hook" ); + is( $status, 1, "CLIENT: Status received from callback is OK" ); + + ## At this point, connection MUST be encrypted. + my $cipher = SSLify_GetCipher($socket); + ok($cipher ne '(NONE)', "CLIENT: SSLify_GetCipher: $cipher"); + ok( SSLify_GetStatus($socket) == 1, "CLIENT: SSLify_GetStatus is done" ); + + $poe_kernel->post( 'myclient' => 'shutdown' ); + }) }; + ok(!$@, "CLIENT: Client_SSLify $@"); + ok( SSLify_GetStatus($socket) == -1, "CLIENT: SSLify_GetStatus is pending" ); + + return ($socket); + }, + ServerInput => sub + { + my ($kernel, $heap, $line) = @_[KERNEL, HEAP, ARG0]; + + die "Should have never got any input from the server!"; + }, + ServerError => sub + { + # Thanks to H. Merijn Brand for spotting this FAIL in 5.12.0! + # The default PoCo::Client::TCP handler will throw a warning, which causes Test::NoWarnings to FAIL :( + my ($syscall, $errno, $error) = @_[ ARG0..ARG2 ]; + + # TODO are there other "errors" that is harmless? + $error = "Normal disconnection" unless $error; + my $msg = "Got CLIENT $syscall error $errno: $error"; + unless ( $syscall eq 'read' and $errno == 0 ) { + fail( $msg ); + } else { + diag( $msg ) if $ENV{TEST_VERBOSE}; + } + }, +); + +$poe_kernel->run(); + +pass( 'shut down sanely' ); + +exit 0; diff --git a/t/8_renegotiate_server.t b/t/8_renegotiate_server.t new file mode 100644 index 0000000..18066c5 --- /dev/null +++ b/t/8_renegotiate_server.t @@ -0,0 +1,185 @@ +#!/usr/bin/perl +# +# This file is part of POE-Component-SSLify +# +# This software is copyright (c) 2011 by Apocalypse. +# +# This is free software; you can redistribute it and/or modify it under +# the same terms as the Perl 5 programming language system itself. +# +use strict; use warnings; +use strict; use warnings; + +# Thanks to ASCENT for this test! +# This test adds renegotiation to the connection from server-side + +# In an older version of this test, there was ok() littered everywhere +# but dngor replied in http://rt.cpan.org/Public/Bug/Display.html?id=66741 +# that it's not going to work... how do I predict which ok() will fail and "simulate" them? +# the solution was to... only run a few tests and print the diag +# because the rest of the tests just redo what we already have in 1_simple.t and stuff... + +my $numtests; +BEGIN { + $numtests = 16; + + eval "use Test::NoWarnings"; + if ( ! $@ ) { + # increment by one + $numtests++; + } +} + +use Test::More tests => $numtests; + +use POE 1.267; +use POE::Component::Client::TCP; +use POE::Component::Server::TCP; +use POE::Component::SSLify qw/Client_SSLify Server_SSLify SSLify_Options SSLify_GetCipher SSLify_ContextCreate SSLify_GetSocket SSLify_GetSSL/; + +# TODO rewrite this to use Test::POE::Server::TCP and stuff :) + +my $port; +my $server_ping2; +my $client_ping2; + +POE::Component::Server::TCP->new +( + Alias => 'myserver', + Address => '127.0.0.1', + Port => 0, + + Started => sub + { + use Socket qw/sockaddr_in/; + $port = (sockaddr_in($_[HEAP]->{listener}->getsockname))[0]; + }, + ClientConnected => sub + { + ok(1, 'SERVER: accepted'); + $_[HEAP]->{client}->put("ping"); + }, + ClientDisconnected => sub + { + ok(1, 'SERVER: client disconnected'); + $_[KERNEL]->post(myserver => 'shutdown'); + }, + ClientPreConnect => sub + { + eval { SSLify_Options('mylib/example.key', 'mylib/example.crt', 'sslv3') }; + eval { SSLify_Options('../mylib/example.key', '../mylib/example.crt', 'sslv3') } if ($@); + ok(!$@, "SERVER: SSLify_Options $@"); + + my $socket = eval { Server_SSLify($_[ARG0]) }; + ok(!$@, "SERVER: Server_SSLify $@"); + ok(1, 'SERVER: SSLify_GetCipher: '. SSLify_GetCipher($socket)); + + # We pray that IO::Handle is sane... + ok( SSLify_GetSocket( $socket )->blocking == 0, 'SERVER: SSLified socket is non-blocking?'); + + return ($socket); + }, + ClientInput => sub + { + my ($kernel, $heap, $line) = @_[KERNEL, HEAP, ARG0]; + + if ($line eq 'pong') { + ok(1, "SERVER: recv: $line"); + + ## At this point, connection MUST be encrypted. + my $cipher = SSLify_GetCipher($heap->{client}->get_output_handle); + ok($cipher ne '(NONE)', "SERVER: SSLify_GetCipher: $cipher"); + + Net::SSLeay::renegotiate( SSLify_GetSSL( $heap->{client}->get_output_handle ) ); + + $heap->{client}->put("ping2"); + } elsif ($line eq 'pong2') { + $server_ping2++; + $kernel->yield( 'shutdown' ); + } else { + die "Unknown line from CLIENT: $line"; + } + }, + ClientError => sub + { + # Thanks to H. Merijn Brand for spotting this FAIL in 5.12.0! + # The default PoCo::Server::TCP handler will throw a warning, which causes Test::NoWarnings to FAIL :( + my ($syscall, $errno, $error) = @_[ ARG0..ARG2 ]; + + # TODO are there other "errors" that is harmless? + $error = "Normal disconnection" unless $error; + my $msg = "Got SERVER $syscall error $errno: $error"; + unless ( $syscall eq 'read' and $errno == 0 ) { +# fail( $msg ); + } else { + diag( $msg ) if $ENV{TEST_VERBOSE}; + } + }, +); + +POE::Component::Client::TCP->new +( + Alias => 'myclient', + RemoteAddress => '127.0.0.1', + RemotePort => $port, + + Connected => sub + { + ok(1, 'CLIENT: connected'); + }, + PreConnect => sub + { + my $ctx = eval { SSLify_ContextCreate(undef, undef, 'sslv3') }; + ok(!$@, "CLIENT: SSLify_ContextCreate $@"); + my $socket = eval { Client_SSLify($_[ARG0], undef, undef, $ctx) }; + ok(!$@, "CLIENT: Client_SSLify $@"); + ok(1, 'CLIENT: SSLify_GetCipher: '. SSLify_GetCipher($socket)); + + # We pray that IO::Handle is sane... + ok( SSLify_GetSocket( $socket )->blocking == 0, 'CLIENT: SSLified socket is non-blocking?'); + + return ($socket); + }, + ServerInput => sub + { + my ($kernel, $heap, $line) = @_[KERNEL, HEAP, ARG0]; + + if ($line eq 'ping') { + ok(1, "CLIENT: recv: $line"); + + ## At this point, connection MUST be encrypted. + my $cipher = SSLify_GetCipher($heap->{server}->get_output_handle); + ok($cipher ne '(NONE)', "CLIENT: SSLify_GetCipher: $cipher"); + + $_[HEAP]->{server}->put("pong"); + } elsif ( $line eq 'ping2' ) { + $client_ping2++; + $_[HEAP]->{server}->put("pong2"); + } else { + die "Unknown line from SERVER: $line"; + } + }, + ServerError => sub + { + # Thanks to H. Merijn Brand for spotting this FAIL in 5.12.0! + # The default PoCo::Client::TCP handler will throw a warning, which causes Test::NoWarnings to FAIL :( + my ($syscall, $errno, $error) = @_[ ARG0..ARG2 ]; + + $error = "Normal disconnection" unless $error; + my $msg = "Got CLIENT $syscall error $errno: $error"; + diag( $msg ) if $ENV{TEST_VERBOSE}; + }, +); + +$poe_kernel->run(); + +if ( ! $server_ping2 or ! $client_ping2 ) { + diag( "WARNING: Your platform/SSL library does not support renegotiation of the SSL socket." ); + diag( "This test harness detected that trying to renegotiate resulted in a disconnected socket." ); + diag( "POE::Component::SSLify will work on your system, but please do not attempt a SSL renegotiate." ); + diag( "Please talk with the author to figure out if this issue can be worked around, thank you!" ); +} + +pass( 'shut down sanely' ); + +exit 0; diff --git a/t/98_renegotiate.t b/t/98_renegotiate.t new file mode 100644 index 0000000..ab82315 --- /dev/null +++ b/t/98_renegotiate.t @@ -0,0 +1,224 @@ +#!/usr/bin/perl +# +# This file is part of POE-Component-SSLify +# +# This software is copyright (c) 2011 by Apocalypse. +# +# This is free software; you can redistribute it and/or modify it under +# the same terms as the Perl 5 programming language system itself. +# +use strict; use warnings; +use strict; use warnings; + +# Thanks to ASCENT for this test! +# This test adds renegotiation to the connection from client-side +# Since this is not supported on all platforms, it's marked TODO and adds custom logic +# to make sure it doesn't FAIL if it's not supported. + +# this version of the test doesn't work as reported in http://rt.cpan.org/Public/Bug/Display.html?id=66741 +# renamed it to this version for posterity and in case I need it for future analysis... + +#my $numtests; +#BEGIN { +# $numtests = 23; +# +# eval "use Test::NoWarnings"; +# if ( ! $@ ) { +# # increment by one +# $numtests++; +# } +#} + +#use Test::More tests => $numtests; +use Test::More; +BEGIN { + plan skip_all => "AUTHOR TEST"; +} + +use POE 1.267; +use POE::Component::Client::TCP; +use POE::Component::Server::TCP; +use POE::Component::SSLify qw/Client_SSLify Server_SSLify SSLify_Options SSLify_GetCipher SSLify_ContextCreate SSLify_GetSocket SSLify_GetSSL/; +use Net::SSLeay qw/ERROR_WANT_READ ERROR_WANT_WRITE/; + +# TODO rewrite this to use Test::POE::Server::TCP and stuff :) + +my $port; +my $server_ping2; +my $client_ping2; + +POE::Component::Server::TCP->new +( + Alias => 'myserver', + Address => '127.0.0.1', + Port => 0, + + Started => sub + { + use Socket qw/sockaddr_in/; + $port = (sockaddr_in($_[HEAP]->{listener}->getsockname))[0]; + }, + ClientConnected => sub + { + ok(1, 'SERVER: accepted'); + }, + ClientDisconnected => sub + { + ok(1, 'SERVER: client disconnected'); + $_[KERNEL]->post(myserver => 'shutdown'); + }, + ClientPreConnect => sub + { + eval { SSLify_Options('mylib/example.key', 'mylib/example.crt', 'sslv3') }; + eval { SSLify_Options('../mylib/example.key', '../mylib/example.crt', 'sslv3') } if ($@); + ok(!$@, "SERVER: SSLify_Options $@"); + + my $socket = eval { Server_SSLify($_[ARG0]) }; + ok(!$@, "SERVER: Server_SSLify $@"); + ok(1, 'SERVER: SSLify_GetCipher: '. SSLify_GetCipher($socket)); + + # We pray that IO::Handle is sane... + ok( SSLify_GetSocket( $socket )->blocking == 0, 'SERVER: SSLified socket is non-blocking?'); + + return ($socket); + }, + ClientInput => sub + { + my ($kernel, $heap, $request) = @_[KERNEL, HEAP, ARG0]; + + ## At this point, connection MUST be encrypted. + my $cipher = SSLify_GetCipher($heap->{client}->get_output_handle); + ok($cipher ne '(NONE)', "SERVER: SSLify_GetCipher: $cipher"); + + if ($request eq 'ping') + { + ok(1, "SERVER: recv: $request"); + $heap->{client}->put("pong"); + } + elsif ($request eq 'ping2') + { + ok(1, "SERVER: recv: $request"); + $server_ping2++; + $heap->{client}->put("pong2"); + } + }, + ClientError => sub + { + # Thanks to H. Merijn Brand for spotting this FAIL in 5.12.0! + # The default PoCo::Server::TCP handler will throw a warning, which causes Test::NoWarnings to FAIL :( + my ($syscall, $errno, $error) = @_[ ARG0..ARG2 ]; + + # TODO are there other "errors" that is harmless? + $error = "Normal disconnection" unless $error; + my $msg = "Got SERVER $syscall error $errno: $error"; + unless ( $syscall eq 'read' and $errno == 0 ) { + fail( $msg ); + } else { + diag( $msg ) if $ENV{TEST_VERBOSE}; + } + }, +); + +POE::Component::Client::TCP->new +( + Alias => 'myclient', + RemoteAddress => '127.0.0.1', + RemotePort => $port, + + Connected => sub + { + ok(1, 'CLIENT: connected'); + + $_[HEAP]->{server}->put("ping"); + }, + PreConnect => sub + { + my $ctx = eval { SSLify_ContextCreate(undef, undef, 'sslv3') }; + ok(!$@, "CLIENT: SSLify_ContextCreate $@"); + my $socket = eval { Client_SSLify($_[ARG0], undef, undef, $ctx) }; + ok(!$@, "CLIENT: Client_SSLify $@"); + ok(1, 'CLIENT: SSLify_GetCipher: '. SSLify_GetCipher($socket)); + + # We pray that IO::Handle is sane... + ok( SSLify_GetSocket( $socket )->blocking == 0, 'CLIENT: SSLified socket is non-blocking?'); + + return ($socket); + }, + ServerInput => sub + { + my ($kernel, $heap, $line) = @_[KERNEL, HEAP, ARG0]; + + ## At this point, connection MUST be encrypted. + my $cipher = SSLify_GetCipher($heap->{server}->get_output_handle); + ok($cipher ne '(NONE)', "CLIENT: SSLify_GetCipher: $cipher"); + + if ($line eq 'pong') + { + ok(1, "CLIENT: recv: $line"); + + # Skip 2 Net::SSLeay::renegotiate() tests on FreeBSD because of + # http://security.freebsd.org/advisories/FreeBSD-SA-09:15.ssl.asc + TODO: { + local $TODO = "Net::SSLeay::renegotiate() does not work on all platforms"; + + ## Force SSL renegotiation + my $ssl = SSLify_GetSSL( $heap->{server}->get_output_handle ); + my $reneg_num = Net::SSLeay::num_renegotiations($ssl); + + ok(1 == Net::SSLeay::renegotiate($ssl), 'CLIENT: SSL renegotiation'); + my $handshake = Net::SSLeay::do_handshake($ssl); + my $err = Net::SSLeay::get_error($ssl, $handshake); + + ## 1 == Successful handshake, ERROR_WANT_(READ|WRITE) == non-blocking. + ok($handshake == 1 || $err == ERROR_WANT_READ || $err == ERROR_WANT_WRITE, 'CLIENT: SSL handshake'); + ok($reneg_num < Net::SSLeay::num_renegotiations($ssl), 'CLIENT: Increased number of negotiations'); + } + + $heap->{server}->put('ping2'); + } + + elsif ($line eq 'pong2') + { + ok(1, "CLIENT: recv: $line"); + $client_ping2++; + $kernel->yield('shutdown'); + } + }, + ServerError => sub + { + # Thanks to H. Merijn Brand for spotting this FAIL in 5.12.0! + # The default PoCo::Client::TCP handler will throw a warning, which causes Test::NoWarnings to FAIL :( + my ($syscall, $errno, $error) = @_[ ARG0..ARG2 ]; + + # TODO are there other "errors" that is harmless? + $error = "Normal disconnection" unless $error; + my $msg = "Got CLIENT $syscall error $errno: $error"; + unless ( $syscall eq 'read' and $errno == 0 ) { + fail( $msg ); + } else { + diag( $msg ) if $ENV{TEST_VERBOSE}; + } + }, +); + +$poe_kernel->run(); + +# Add extra pass() to make the test harness happy if renegotiate did not work +if ( ! $server_ping2 ) { + local $TODO = "Net::SSLeay::renegotiate() does not work on all platforms"; + fail( "SERVER: Failed SSL renegotiation" ); +} +if ( ! $client_ping2 ) { + local $TODO = "Net::SSLeay::renegotiate() does not work on all platforms"; + fail( "CLIENT: Failed SSL renegotiation" ); +} +if ( ! $server_ping2 or ! $client_ping2 ) { + diag( "WARNING: Your platform/SSL library does not support renegotiation of the SSL socket." ); + diag( "This test harness detected that trying to renegotiate resulted in a disconnected socket." ); + diag( "POE::Component::SSLify will work on your system, but please do not attempt a SSL renegotiate." ); + diag( "Please talk with the author to figure out if this issue can be worked around, thank you!" ); +} + +pass( 'shut down sanely' ); + +exit 0; diff --git a/t/99_mire_test.t b/t/99_mire_test.t new file mode 100644 index 0000000..c331d49 --- /dev/null +++ b/t/99_mire_test.t @@ -0,0 +1,270 @@ +#!/usr/bin/perl +# +# This file is part of POE-Component-SSLify +# +# This software is copyright (c) 2011 by Apocalypse. +# +# This is free software; you can redistribute it and/or modify it under +# the same terms as the Perl 5 programming language system itself. +# +use strict; use warnings; + +# Test contributed by mire@irc which used this to hit the WRITE_WANTS_READ case +# mire created package Ub because he couldn't reproduce it with poco-cl-http :( +# tweaked slightly to turn it into a real testcase ( not done yet ) + +BEGIN { +# sub POE::Kernel::ASSERT_DEFAULT () { 1 } +# sub POE::Kernel::TRACE_STATISTICS () { 0 } # makes POE hang, it's been removed in git but not in 1.299 heh +# sub POE::Kernel::TRACE_DEFAULT () { 1 } +# sub POE::Kernel::CATCH_EXCEPTIONS () { 0 } # make sure we die right away so it's easier to debug +} + +use strict; +use warnings; +use POE; + +use Test::More; +BEGIN { + plan skip_all => "AUTHOR TEST"; +} + +our $DEBUG=0; + +package Ub; +use strict; +use warnings; +use POE qw( Component::Client::TCP Filter::Stream ); +use POE::Component::SSLify qw( Client_SSLify ); + +# non-core deps +BEGIN { + eval "use POE::Filter::HTTPChunk; use HTTP::Parser; use HTTP::Response;"; + if ( $@ ) { + use Test::More; + plan skip_all => "Unable to load deps: $@"; + } +} + +sub new { + my $this = shift; + my %p = @_; + + my $class = ref($this) || $this; + my $self = {}; + bless $self, $class; + + $self->{'_p'} = \%p; + + return $self; +} + +sub spawn { +my $self = shift; + + my $session_id = POE::Session->create( + inline_states => { +_child => sub {}, +_start => sub { + my ($kernel, $heap) = @_[KERNEL, HEAP]; + ($heap->{'self'}) = @_[ARG0..$#_]; + print 'INFO: ' . __PACKAGE__ . "_start\n" + if $main::DEBUG; + $kernel->alias_set( 'ub' ); + #$_[KERNEL]->refcount_increment($_[SESSION]->ID, 'ub'); +}, +_stop => sub { + my ($kernel, $heap) = @_[KERNEL, HEAP]; + print 'INFO: ' . __PACKAGE__ . "_stop\n" + if $main::DEBUG; + $heap = {}; +}, +on_shutdown => sub { + print 'INFO: ' . __PACKAGE__ . "on_shutdown\n" + if $main::DEBUG; +}, +_shutdown => sub { + print 'INFO: ' . __PACKAGE__ . "_shutdown\n" + if $main::DEBUG; +}, +r => sub { + my ($kernel, $heap, $ev_res, $cont_ref, $host, $port, $do_ssl) = @_[KERNEL, HEAP, ARG0..$#_]; + + my $s_res = $_[SENDER]->ID; + + # TODO pravi alarm za ubijanje konekcije + my $tcp_sid = POE::Component::Client::TCP->new( + #SessionParams => [ options => { debug => 1, trace => 1 } ], +# SessionParams => [ options => { debug => 1 } ], + Args => [$s_res, $ev_res, $cont_ref, $do_ssl], + Filter => "POE::Filter::Stream", + RemoteAddress => $host, + RemotePort => $port, + ConnectTimeout => 30, + Started => sub { + my ($kernel, $heap) = @_[KERNEL, HEAP]; + print "INFO: Started\n" + if $main::DEBUG; + (@$heap{qw|s_res ev_res cont_ref do_ssl|}) = @_[ARG0..$#_]; + }, + PreConnect => sub { + my ($kernel, $heap) = @_[KERNEL, HEAP]; + + print "INFO: PreConnect\n" + if $main::DEBUG; + + $heap->{'parser'} = HTTP::Parser->new(response => 1); + + return $_[ARG0] + unless $heap->{'do_ssl'}; + + # Convert the socket into an SSL socket. + my $socket = eval { Client_SSLify($_[ARG0]) }; + + # Disconnect if SSL failed. + if ($@) { + warn $@ if $main::DEBUG; + return; + } + # Return the SSL-ified socket. + return $socket; + }, + ConnectError => sub { + my ($kernel, $heap) = @_[KERNEL, HEAP]; + #print Dumper $heap; exit; + my ($operation, $error_number, $error_string) = @_[ARG0..ARG2]; + print "ERROR: ConnectError $operation error $error_number occurred: $error_string\n" + if $main::DEBUG; + my $dc = ''; + $kernel->post($heap->{'s_res'}, $heap->{'ev_res'}, {'error' => 1, 'error_type' => 'connect_error', 'content' => \$dc}); + $_[KERNEL]->yield('shutdown'); + }, + ServerError => sub { + my ($kernel, $heap) = @_[KERNEL, HEAP]; + my ($operation, $error_number, $error_string) = @_[ARG0..ARG2]; + + print "not informing master session, ERROR: ServerError $operation error $error_number occurred: $error_string\n" + if $main::DEBUG; + $kernel->yield('shutdown'); + }, + Connected => sub { + my ($kernel, $heap) = @_[KERNEL, HEAP]; + print "INFO: Connected\n" + if $main::DEBUG; + $heap->{server}->put(${$heap->{'cont_ref'}}); + # start timeout thing + # za pravu shutdown funkciju + $heap->{'al_cest_id'} = $_[KERNEL]->alarm_set( shutdown => time + 60 ); + }, + ServerInput => sub { + my ($kernel, $heap) = @_[KERNEL, HEAP]; + print "INFO: ServerInput\n" + if $main::DEBUG; + my $input = $_[ARG0]; + #print 'from server: ' . Dumper $input; + eval { + $heap->{'parser'}->add($input); + }; + # TODO error response + $kernel->yield('shutdown') + if $@; + }, + ServerFlushed => sub { + print "INFO: ServerFlushed\n" + if $main::DEBUG; + }, + Disconnected => sub { + my ($kernel, $heap) = @_[KERNEL, HEAP]; + print "INFO: disconnected ;)\n" + if $main::DEBUG; + my $dc = ''; + $dc = $heap->{'parser'}->object->decoded_content + if $heap->{'parser'}->object; + $kernel->post($heap->{'s_res'}, $heap->{'ev_res'}, {'error' => 0, 'error_type' => '', 'content' => \$dc}); + $_[KERNEL]->alarm_remove(delete $heap->{'al_cest_id'}) + if (exists $heap->{'al_cest_id'} and $heap->{'al_cest_id'}); + $_[KERNEL]->yield('shutdown'); + }, + + ); + print "tcp_sid: $tcp_sid\n" + if $main::DEBUG; + +}, +}, + 'args' => [$self], +)->ID; + + return $session_id; +} + +1; + +package main; + +my $ub = Ub->new()->spawn(); + + + + + my $session_id_test = POE::Session->create( + inline_states => { +_start => sub { + my ($kernel, $heap) = @_[KERNEL, HEAP]; + ($heap->{'self'}) = @_[ARG0..$#_]; + print 'INFO: ' . __PACKAGE__ . "_start\n" + if $main::DEBUG; + $kernel->yield('test'); +}, +_stop => sub { + my ($kernel, $heap) = @_[KERNEL, HEAP]; + print 'INFO: ' . __PACKAGE__ . "_stop\n" + if $main::DEBUG; + $heap = {}; +}, +on_shutdown => sub { + print 'INFO: ' . __PACKAGE__ . "on_shutdown\n" + if $main::DEBUG; +}, +_shutdown => sub { + print 'INFO: ' . __PACKAGE__ . "_shutdown\n" + if $main::DEBUG; +}, +test => sub { + my ($kernel, $heap) = @_[KERNEL, HEAP]; + my ($cont, $host, $port, $do_ssl); + + $kernel->refcount_increment($_[SESSION]->ID, 'test'); + + if (1) { + $host = '0ne.us'; + $port = 443; + $do_ssl = 1; + + $cont = <<'EOF'; +GET /get.php HTTP/1.1 +Host: osadmin.com +User-Agent: proba 123 +Connection: close + + +EOF + + } + $kernel->post('ub', 'r', 'test_res', \$cont, $host, $port, $do_ssl); + +}, +test_res => sub { + my ($kernel, $heap, $dat) = @_[KERNEL, HEAP, ARG0..$#_]; + $kernel->refcount_decrement($_[SESSION]->ID, 'test'); + my $cont = ${$dat->{'content'}}; + chomp $cont; + warn $cont; +die "HIT BUG" if length $cont == 0; + $kernel->yield('test'); + return; +}, +},)->ID; + +POE::Kernel->run(); +exit;