Codebase list libpoe-component-sslify-perl / 200d56d
fix damn tabs Apocalypse 9 years ago
2 changed file(s) with 555 addition(s) and 2 deletion(s). Raw diff Collapse all Expand all
0 =pod
1
2 =encoding UTF-8
3
4 =for :stopwords Apocalypse cpan testmatrix url annocpan anno bugtracker rt cpants kwalitee
5 diff irc mailto metadata placeholders metacpan
6
7 =head1 NAME
8
9 POE::Component::SSLify - Makes using SSL in the world of POE easy!
10
11 =head1 VERSION
12
13 This document describes v1.009 of POE::Component::SSLify - released November 11, 2014 as part of POE-Component-SSLify.
14
15 =head1 SYNOPSIS
16
17 # look at the DESCRIPTION for client and server example code
18
19 =head1 DESCRIPTION
20
21 This component is a method to simplify the SSLification of a socket before it is passed
22 to a L<POE::Wheel::ReadWrite> wheel in your application.
23
24 =head2 Client usage
25
26 # Import the module
27 use POE::Component::SSLify qw( Client_SSLify );
28
29 # Create a normal SocketFactory wheel and connect to a SSL-enabled server
30 my $factory = POE::Wheel::SocketFactory->new;
31
32 # Time passes, SocketFactory gives you a socket when it connects in SuccessEvent
33 # Convert the socket into a SSL socket POE can communicate with
34 my $socket = shift;
35 eval { $socket = Client_SSLify( $socket ) };
36 if ( $@ ) {
37 # Unable to SSLify it...
38 }
39
40 # Now, hand it off to ReadWrite
41 my $rw = POE::Wheel::ReadWrite->new(
42 Handle => $socket,
43 # other options as usual
44 );
45
46 =head2 Server usage
47
48 # !!! Make sure you have a public key + certificate
49 # excellent howto: http://www.akadia.com/services/ssh_test_certificate.html
50
51 # Import the module
52 use POE::Component::SSLify qw( Server_SSLify SSLify_Options );
53
54 # Set the key + certificate file
55 eval { SSLify_Options( 'server.key', 'server.crt' ) };
56 if ( $@ ) {
57 # Unable to load key or certificate file...
58 }
59
60 # Create a normal SocketFactory wheel to listen for connections
61 my $factory = POE::Wheel::SocketFactory->new;
62
63 # Time passes, SocketFactory gives you a socket when it gets a connection in SuccessEvent
64 # Convert the socket into a SSL socket POE can communicate with
65 my $socket = shift;
66 eval { $socket = Server_SSLify( $socket ) };
67 if ( $@ ) {
68 # Unable to SSLify it...
69 }
70
71 # Now, hand it off to ReadWrite
72 my $rw = POE::Wheel::ReadWrite->new(
73 Handle => $socket,
74 # other options as usual
75 );
76
77 =head1 FUNCTIONS
78
79 =head2 Client_SSLify
80
81 This function sslifies a client-side socket. You can pass several options to it:
82
83 my $socket = shift;
84 $socket = Client_SSLify( $socket, $version, $options, $ctx, $callback );
85 $socket is the non-ssl socket you got from somewhere ( required )
86 $version is the SSL version you want to use
87 $options is the SSL options you want to use
88 $ctx is the custom SSL context you want to use
89 $callback is the callback hook on success/failure of sslification
90
91 # This is an example of the callback and you should pass it as Client_SSLify( $socket, ... , \&callback );
92 sub callback {
93 my( $socket, $status, $errval ) = @_;
94 # $socket is the original sslified socket in case you need to play with it
95 # $status is either 1 or 0; with 1 signifying success and 0 failure
96 # $errval will be defined if $status == 0; it's the numeric SSL error code
97 # check http://www.openssl.org/docs/ssl/SSL_get_error.html for the possible error values ( and import them from Net::SSLeay! )
98
99 # The return value from the callback is discarded
100 }
101
102 If $ctx is defined, SSLify will ignore $version and $options. Otherwise, it will be created from the $version and
103 $options parameters. If all of them are undefined, it will follow the defaults in L</SSLify_ContextCreate>.
104
105 BEWARE: If you passed in a CTX, SSLify will do Net::SSLeay::CTX_free( $ctx ) when the
106 socket is destroyed. This means you cannot reuse contexts!
107
108 NOTE: The way to have a client socket with proper certificates set up is:
109
110 my $socket = shift; # get the socket from somewhere
111 my $ctx = SSLify_ContextCreate( 'server.key', 'server.crt' );
112 $socket = Client_SSLify( $socket, undef, undef, $ctx );
113
114 NOTE: You can pass the callback anywhere in the arguments, we'll figure it out for you! If you want to call a POE event, please look
115 into the postback/callback stuff in L<POE::Session>.
116
117 # we got this from POE::Wheel::SocketFactory
118 sub event_SuccessEvent {
119 my $socket = $_[ARG0];
120 $socket = Client_SSLify( $socket, $_[SESSION]->callback( 'sslify_result' ) );
121 $_[HEAP]->{client} = POE::Wheel::ReadWrite->new(
122 Handle => $socket,
123 ...
124 );
125 return;
126 }
127
128 # the callback event
129 sub event_sslify_result {
130 my ($creation_args, $called_args) = @_[ARG0, ARG1];
131 my( $socket, $status, $errval ) = @$called_args;
132
133 if ( $status ) {
134 print "Yay, SSLification worked!";
135 } else {
136 print "Aw, SSLification failed with error $errval";
137 }
138 }
139
140 =head2 Server_SSLify
141
142 This function sslifies a server-side socket. You can pass several options to it:
143
144 my $socket = shift;
145 $socket = Server_SSLify( $socket, $ctx, $callback );
146 $socket is the non-ssl socket you got from somewhere ( required )
147 $ctx is the custom SSL context you want to use; overrides the global ctx set in SSLify_Options
148 $callback is the callback hook on success/failure of sslification
149
150 BEWARE: L</SSLify_Options> must be called first if you aren't passing a $ctx. If you want to set some options per-connection, do this:
151
152 my $socket = shift; # get the socket from somewhere
153 my $ctx = SSLify_ContextCreate();
154 # set various options on $ctx as desired
155 $socket = Server_SSLify( $socket, $ctx );
156
157 NOTE: You can use L</SSLify_GetCTX> to modify the global, and avoid doing this on every connection if the
158 options are the same...
159
160 Please look at L</Client_SSLify> for more details on the callback hook.
161
162 =head2 SSLify_ContextCreate
163
164 Accepts some options, and returns a brand-new Net::SSLeay context object ( $ctx )
165
166 my $ctx = SSLify_ContextCreate( $key, $cert, $version, $options );
167 $key is the certificate key file
168 $cert is the certificate file
169 $version is the SSL version to use
170 $options is the SSL options to use
171
172 You can then call various Net::SSLeay methods on the context
173
174 my $mode = Net::SSLeay::CTX_get_mode( $ctx );
175
176 By default we don't use the SSL key + certificate files
177
178 By default we use the version: default. Known versions of the SSL connection - look at
179 L<http://www.openssl.org/docs/ssl/SSL_CTX_new.html> for more info.
180
181 * sslv2
182 * sslv3
183 * tlsv1
184 * sslv23
185 * default ( sslv23 )
186
187 By default we don't set any options - look at L<http://www.openssl.org/docs/ssl/SSL_CTX_set_options.html> for more info.
188
189 =head2 SSLify_Options
190
191 Call this function to initialize the global server-side context object. This will be the default context whenever you call
192 L</Server_SSLify> without passing a custom context to it.
193
194 SSLify_Options( $key, $cert, $version, $options );
195 $key is the certificate key file ( required )
196 $cert is the certificate file ( required )
197 $version is the SSL version to use
198 $options is the SSL options to use
199
200 By default we use the version: default
201
202 By default we use the options: Net::SSLeay::OP_ALL
203
204 Please look at L</SSLify_ContextCreate> for more info on the available versions/options.
205
206 =head2 SSLify_GetCTX
207
208 Returns the actual Net::SSLeay context object in case you wanted to play with it :)
209
210 If passed in a socket, it will return that socket's $ctx instead of the global.
211
212 my $ctx = SSLify_GetCTX(); # get the one set via SSLify_Options
213 my $ctx = SSLify_GetCTX( $sslified_sock ); # get the one in the object
214
215 =head2 SSLify_GetCipher
216
217 Returns the cipher used by the SSLified socket
218
219 print "SSL Cipher is: " . SSLify_GetCipher( $sslified_sock ) . "\n";
220
221 NOTE: Doing this immediately after Client_SSLify or Server_SSLify will result in "(NONE)" because the SSL handshake
222 is not done yet. The socket is nonblocking, so you will have to wait a little bit for it to get ready.
223
224 apoc@blackhole:~/mygit/perl-poe-sslify/examples$ perl serverclient.pl
225 got connection from: 127.0.0.1 - commencing Server_SSLify()
226 SSLified: 127.0.0.1 cipher type: ((NONE))
227 Connected to server, commencing Client_SSLify()
228 SSLified the connection to the server
229 Connected to SSL server
230 Input: hola
231 got input from: 127.0.0.1 cipher type: (AES256-SHA) input: 'hola'
232 Got Reply: hola
233 Input: ^C
234 stopped at serverclient.pl line 126.
235
236 =head2 SSLify_GetSocket
237
238 Returns the actual socket used by the SSLified socket, useful for stuff like getpeername()/getsockname()
239
240 print "Remote IP is: " . inet_ntoa( ( unpack_sockaddr_in( getpeername( SSLify_GetSocket( $sslified_sock ) ) ) )[1] ) . "\n";
241
242 =head2 SSLify_GetSSL
243
244 Returns the actual Net::SSLeay object so you can call methods on it
245
246 print Net::SSLeay::dump_peer_certificate( SSLify_GetSSL( $sslified_sock ) );
247
248 =head2 SSLify_GetStatus
249
250 Returns the status of the SSL negotiation/handshake/connection. See L<http://www.openssl.org/docs/ssl/SSL_connect.html#RETURN_VALUES>
251 for more info.
252
253 my $status = SSLify_GetStatus( $socket );
254 -1 = still in negotiation stage ( or error )
255 0 = internal SSL error, connection will be dead
256 1 = negotiation successful
257
258 =head1 NOTES
259
260 =head2 Socket methods doesn't work
261
262 The new socket this module gives you actually is tied socket magic, so you cannot do stuff like
263 getpeername() or getsockname(). The only way to do it is to use L</SSLify_GetSocket> and then operate on
264 the socket it returns.
265
266 =head2 Dying everywhere...
267
268 This module will die() if Net::SSLeay could not be loaded or it is not the version we want. So, it is recommended
269 that you check for errors and not use SSL, like so:
270
271 eval { use POE::Component::SSLify };
272 if ( $@ ) {
273 $sslavailable = 0;
274 } else {
275 $sslavailable = 1;
276 }
277
278 # Make socket SSL!
279 if ( $sslavailable ) {
280 eval { $socket = POE::Component::SSLify::Client_SSLify( $socket ) };
281 if ( $@ ) {
282 # Unable to SSLify the socket...
283 }
284 }
285
286 =head3 $IGNORE_SSL_ERRORS
287
288 As of SSLify v1.003 you can override this variable to temporarily ignore some SSL errors. This is useful if you are doing crazy things
289 with the underlying Net::SSLeay stuff and don't want to die. However, it won't ignore all errors as some is still considered fatal.
290 Here's an example:
291
292 {
293 local $POE::Component::SSLify::IGNORE_SSL_ERRORS=1;
294 my $ctx = SSLify_CreateContext(...);
295 #Some more stuff
296 }
297
298 =head2 OpenSSL functions
299
300 Theoretically you can do anything that Net::SSLeay exports from the OpenSSL libs on the socket. However, I have not tested every
301 possible function against SSLify, so use them carefully!
302
303 =head3 Net::SSLeay::renegotiate
304
305 This function has been tested ( it's in C<t/2_renegotiate_client.t> ) but it doesn't work on FreeBSD! I tracked it down to this security
306 advisory: L<http://security.freebsd.org/advisories/FreeBSD-SA-09:15.ssl.asc> which explains it in detail. The test will skip this function
307 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.
308
309 NOTE: Calling this means the callback function you passed in L</Client_SSLify> or L</Server_SSLify> will not fire! If you need this
310 please let me know and we can come up with a way to make it work.
311
312 =head2 Upgrading a non-ssl socket to SSL
313
314 You can have a normal plaintext socket, and convert it to SSL anytime. Just keep in mind that the client and the server must agree to sslify
315 at the same time, or they will be waiting on each other forever! See C<t/3_upgrade.t> for an example of how this works.
316
317 =head2 Downgrading a SSL socket to non-ssl
318
319 As of now this is unsupported. If you need this feature please let us know and we'll work on it together!
320
321 =head2 MSWin32 is not supported
322
323 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
324 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!
325
326 =head2 LOAD_SSL_ENGINES
327
328 OpenSSL supports loading ENGINEs to accelerate the crypto algorithms. SSLify v1.004 automatically loaded the engines, but there was some
329 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
330 and you would need to explicitly enable it.
331
332 sub POE::Component::SSLify::LOAD_SSL_ENGINES () { 1 }
333 use POE::Component::SSLify qw( Client::SSLify );
334
335 =head1 EXPORT
336
337 Stuffs all of the functions in @EXPORT_OK so you have to request them directly.
338
339 =head1 SEE ALSO
340
341 Please see those modules/websites for more information related to this module.
342
343 =over 4
344
345 =item *
346
347 L<POE|POE>
348
349 =item *
350
351 L<Net::SSLeay|Net::SSLeay>
352
353 =back
354
355 =head1 SUPPORT
356
357 =head2 Perldoc
358
359 You can find documentation for this module with the perldoc command.
360
361 perldoc POE::Component::SSLify
362
363 =head2 Websites
364
365 The following websites have more information about this module, and may be of help to you. As always,
366 in addition to those websites please use your favorite search engine to discover more resources.
367
368 =over 4
369
370 =item *
371
372 MetaCPAN
373
374 A modern, open-source CPAN search engine, useful to view POD in HTML format.
375
376 L<http://metacpan.org/release/POE-Component-SSLify>
377
378 =item *
379
380 Search CPAN
381
382 The default CPAN search engine, useful to view POD in HTML format.
383
384 L<http://search.cpan.org/dist/POE-Component-SSLify>
385
386 =item *
387
388 RT: CPAN's Bug Tracker
389
390 The RT ( Request Tracker ) website is the default bug/issue tracking system for CPAN.
391
392 L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=POE-Component-SSLify>
393
394 =item *
395
396 AnnoCPAN
397
398 The AnnoCPAN is a website that allows community annotations of Perl module documentation.
399
400 L<http://annocpan.org/dist/POE-Component-SSLify>
401
402 =item *
403
404 CPAN Ratings
405
406 The CPAN Ratings is a website that allows community ratings and reviews of Perl modules.
407
408 L<http://cpanratings.perl.org/d/POE-Component-SSLify>
409
410 =item *
411
412 CPAN Forum
413
414 The CPAN Forum is a web forum for discussing Perl modules.
415
416 L<http://cpanforum.com/dist/POE-Component-SSLify>
417
418 =item *
419
420 CPANTS
421
422 The CPANTS is a website that analyzes the Kwalitee ( code metrics ) of a distribution.
423
424 L<http://cpants.cpanauthors.org/dist/overview/POE-Component-SSLify>
425
426 =item *
427
428 CPAN Testers
429
430 The CPAN Testers is a network of smokers who run automated tests on uploaded CPAN distributions.
431
432 L<http://www.cpantesters.org/distro/P/POE-Component-SSLify>
433
434 =item *
435
436 CPAN Testers Matrix
437
438 The CPAN Testers Matrix is a website that provides a visual overview of the test results for a distribution on various Perls/platforms.
439
440 L<http://matrix.cpantesters.org/?dist=POE-Component-SSLify>
441
442 =item *
443
444 CPAN Testers Dependencies
445
446 The CPAN Testers Dependencies is a website that shows a chart of the test results of all dependencies for a distribution.
447
448 L<http://deps.cpantesters.org/?module=POE::Component::SSLify>
449
450 =back
451
452 =head2 Email
453
454 You can email the author of this module at C<APOCAL at cpan.org> asking for help with any problems you have.
455
456 =head2 Internet Relay Chat
457
458 You can get live help by using IRC ( Internet Relay Chat ). If you don't know what IRC is,
459 please read this excellent guide: L<http://en.wikipedia.org/wiki/Internet_Relay_Chat>. Please
460 be courteous and patient when talking to us, as we might be busy or sleeping! You can join
461 those networks/channels and get help:
462
463 =over 4
464
465 =item *
466
467 irc.perl.org
468
469 You can connect to the server at 'irc.perl.org' and join this channel: #perl-help then talk to this person for help: Apocalypse.
470
471 =item *
472
473 irc.freenode.net
474
475 You can connect to the server at 'irc.freenode.net' and join this channel: #perl then talk to this person for help: Apocal.
476
477 =item *
478
479 irc.efnet.org
480
481 You can connect to the server at 'irc.efnet.org' and join this channel: #perl then talk to this person for help: Ap0cal.
482
483 =back
484
485 =head2 Bugs / Feature Requests
486
487 Please report any bugs or feature requests by email to C<bug-poe-component-sslify at rt.cpan.org>, or through
488 the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=POE-Component-SSLify>. You will be automatically notified of any
489 progress on the request by the system.
490
491 =head2 Source Code
492
493 The code is open to the world, and available for you to hack on. Please feel free to browse it and play
494 with it, or whatever. If you want to contribute patches, please send me a diff or prod me to pull
495 from your repository :)
496
497 L<https://github.com/apocalypse/perl-poe-sslify>
498
499 git clone https://github.com/apocalypse/perl-poe-sslify.git
500
501 =head1 AUTHOR
502
503 Apocalypse <APOCAL@cpan.org>
504
505 =head1 ACKNOWLEDGEMENTS
506
507 Original code is entirely Rocco Caputo ( Creator of POE ) -> I simply
508 packaged up the code into something everyone could use and accepted the burden
509 of maintaining it :)
510
511 From the PoCo::Client::HTTP code =]
512 # This code should probably become a POE::Kernel method,
513 # seeing as it's rather baroque and potentially useful in a number
514 # of places.
515
516 ASCENT also helped a lot with the nonblocking mode, without his hard work this
517 module would still be stuck in the stone age :)
518
519 A lot of people helped add various features/functions - please look at the changelog for more detail.
520
521 =head1 COPYRIGHT AND LICENSE
522
523 This software is copyright (c) 2014 by Apocalypse.
524
525 This is free software; you can redistribute it and/or modify it under
526 the same terms as the Perl 5 programming language system itself.
527
528 The full text of the license can be found in the
529 F<LICENSE> file included with this distribution.
530
531 =head1 DISCLAIMER OF WARRANTY
532
533 THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
534 APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
535 HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
536 OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
537 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
538 PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
539 IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
540 ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
541
542 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
543 WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
544 THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
545 GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
546 USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
547 DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
548 PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
549 EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
550 SUCH DAMAGES.
551
552 =cut
632632
633633 From the PoCo::Client::HTTP code =]
634634 # This code should probably become a POE::Kernel method,
635 # seeing as it's rather baroque and potentially useful in a number
636 # of places.
635 # seeing as it's rather baroque and potentially useful in a number
636 # of places.
637637
638638 ASCENT also helped a lot with the nonblocking mode, without his hard work this
639639 module would still be stuck in the stone age :)