NAME
POE::Component::TLSify - Makes using SSL/TLS in the world of POE easy!
VERSION
version 0.08
SYNOPSIS
# look at the DESCRIPTION for client and server example code
DESCRIPTION
This component is a method to simplify the TLSification of a socket
before it is passed to a POE::Wheel::ReadWrite wheel in your
application.
Based on POE::Component::SSLify, instead of directly wrapping
Net::SSLeay it uses IO::Socket::SSL and has slight differences in API
as a result.
Client usage
# Import the module
use POE::Component::TLSify qw( Client_TLSify );
# Create a normal SocketFactory wheel and connect to a TLS-enabled server
my $factory = POE::Wheel::SocketFactory->new;
# Time passes, SocketFactory gives you a socket when it connects in SuccessEvent
# Convert the socket into a TLS socket POE can communicate with
my $socket = shift;
eval { $socket = Client_TLSify( $socket ) };
if ( $@ ) {
# Unable to TLSify it...
}
# Now, hand it off to ReadWrite
my $rw = POE::Wheel::ReadWrite->new(
Handle => $socket,
# other options as usual
);
Server usage
# !!! Make sure you have a public key + certificate
# Import the module
use POE::Component::TLSify qw( Server_TLSify );
# Create a normal SocketFactory wheel to listen for connections
my $factory = POE::Wheel::SocketFactory->new;
# Time passes, SocketFactory gives you a socket when it gets a connection in SuccessEvent
# Convert the socket into a SSL socket POE can communicate with
my $socket = shift;
# Set the key + certificate file options to pass to IO::Socket::SSL
my $io_socket_ssl_args = {
SSL_cert_file => 'server.crt',
SSL_key_file => 'server.key',
};
eval { $socket = Server_TLSify( $socket, $io_socket_ssl_args ) };
if ( $@ ) {
# Unable to TLSify it...
}
# Now, hand it off to ReadWrite
my $rw = POE::Wheel::ReadWrite->new(
Handle => $socket,
# other options as usual
);
FUNCTIONS
Client_TLSify
This function tlsifies a client-side socket. You can pass several
options to it:
my $socket = shift;
$socket = Client_TLSify( $socket, $io_socket_ssl_args, $callback );
$socket is the non-ssl socket you got from somewhere ( required )
$io_socket_ssl_args is a hashref of IO::Socket::SSL options to pass to that module
$callback is the callback hook on success/failure of tlsification
# This is an example of the callback and you should pass it as Client_SSLify( $socket, ... , \&callback );
sub callback {
my( $socket, $status, $errval ) = @_;
# $socket is the original sslified socket in case you need to play with it
# $status is either 1 or 0; with 1 signifying success and 0 failure
# $errval will be defined if $status == 0; it's whatever IO::Socket::SSL returned from errstr
# The return value from the callback is discarded
}
The function uses IO::Socket::SSL start_SSL to start tlsification and
calls connect_SSL. The hashref of options passed in are passed to
start_SSL so you can adjust the tlsification to taste, such as adding
client certificates, etc.
The callback unlike in POE::Component::SSLify must be the third
argument. As with POE::Component::SSLify the callback can be a POE
event, see postback/callback stuff in POE::Session.
Server_TLSify
This function sslifies a server-side socket. You can pass several
options to it:
my $socket = shift;
my $io_socket_ssl_args = {
SSL_cert_file => 'server.crt',
SSL_key_file => 'server.key',
};
$socket = Server_TLSify( $socket, $io_socket_ssl_args, $callback );
$socket is the non-ssl socket you got from somewhere ( required )
$io_socket_ssl_args is a hashref of IO::Socket::SSL options to pass to that module
$callback is the callback hook on success/failure of tlsification
The function uses IO::Socket::SSL start_SSL to start tlsification and
calls accept_SSL. The hashref of options passed in are passed to
start_SSL so you can adjust the tlsification to taste. At a minimum for
a server you will require a certificate and key that should be passed
with the SSL_cert_file and SSL_key_file options.
Please look at "Client_SSLify" for more details on the callback hook.
TLSify_GetSocket
Returns the actual IO::Socket::SSL socket used by the TLSified socket,
useful for stuff like getpeername()/getsockname()
print "Remote IP is: " . inet_ntoa( ( unpack_sockaddr_in( getpeername( SSLify_GetSocket( $sslified_sock ) ) ) )[1] ) . "\n";
and all the other methods that IO::Socket::SSL provides.
TLSify_GetCipher
Returns the cipher used by the TLSified socket
print "SSL Cipher is: " . TLSify_GetCipher( $tlsified_sock ) . "\n";
NOTE: Doing this immediately after Client_TLSify or Server_TLSify will
result in "(NONE)" because the SSL handshake is not done yet. The
socket is nonblocking, so you will have to wait a little bit for it to
get ready.
NOTES
Certificate Verification
POE::Component::SSLify did not do certificate validation and
verification. IO::Socket::SSL does by default. It would be useful to
make yourself aware of this default behaviour and check out the
documentation for the following options SSL_verify_mode,
SSL_verify_callback and SSL_ocsp_mode.
Socket methods doesn't work
The new socket this module gives you actually is tied socket magic, so
you cannot do stuff like getpeername() or getsockname(). The only way
to do it is to use "TLSify_GetSocket" and then operate on the
IO::Socket::SSL socket it returns.
Dying to meet you ...
This module will die() if TLSification process fails. So, it is
recommended that you check for errors and not use SSL, like so:
eval { use POE::Component::TLSify };
if ( $@ ) {
$sslavailable = 0;
}
else {
$sslavailable = 1;
}
# Make socket SSL!
if ( $sslavailable ) {
eval { $socket = POE::Component::TLSify::Client_TLSify( $socket ) };
if ( $@ ) {
# Unable to TLSify the socket...
}
}
IO::Socket::SSL methods
The underlying socket is a IO::Socket::SSL so you may use any of the
supported methods on the socket object. Use "TLSify_GetSocket" to
retrieve that object.
Upgrading a non-ssl socket to SSL
You can have a normal plaintext socket, and convert it to TLS anytime.
Just keep in mind that the client and the server must agree to tlsify
at the same time, or they will be waiting on each other forever!
Downgrading a SSL socket to non-ssl
As of now this is unsupported. If you need this feature please let us
know and we'll work on it together! In theory IO::Socket::SSL does
provide a stop_SSL method, so this should be possible.
ACKNOWLEDGEMENTS
Original POE::Component::SSLify:
Original code is entirely Rocco Caputo ( Creator of POE ) -> I (APOCAL) simply
packaged up the code into something everyone could use and accepted the burden
of maintaining it :)
POE::Component::TLSify is based on POE::Component::SSLify, I (BINGOS) simply
ported the code to use IO::Socket::SSL instead of using Net::SSLeay
Thanks also to Paul Evans (PEVANS), the IO::Async author, whose IO::Async::SSL
provided inspiration for using IO::Socket::SSL
AUTHORS
* Chris Williams <chris@bingosnet.co.uk>
* Apocalypse <APOCAL@cpan.org>
COPYRIGHT AND LICENSE
This software is copyright (c) 2020 by Chris Williams, 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.