NAME POE::Component::TLSify - Makes using SSL/TLS in the world of POE easy! VERSION version 0.04 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 # excellent howto: http://www.akadia.com/services/ssh_test_certificate.html # 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 * Apocalypse 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.