IO-Socket-SSL-1.965/0000755000175100017520000000000012265775222012475 5ustar workworkIO-Socket-SSL-1.965/Changes0000644000175100017520000012543012265775116013777 0ustar workwork1.965 2014/01/16 - new key SSL_session_key to influence how sessions are inserted and looked up in the clients session cache. This makes it possible to share sessions over different ip:host (like required with some FTPS servers) - t/core.t - handle case, were default loopback source is not 127.0.0.1, like in FreeBSD jails 1.964 2014/01/15 - Disabling TLSv1_1 did not work, because the constant was wrong. Now it gets the constants from calling Net::SSLeay::SSL_OP_NO_TLSv1_1 etc - The new syntax for the protocols is TLSv1_1 instead of TLSv11. This matches the syntax from OpenSSL. The old syntax continues to work in SSL_version. - New functions get_sslversion and get_sslversion_int which get the SSL version of the establish session as string or int. - disable t/io-socket-inet6.t if Acme::Override::INET is installed 1.963 2014/01/13 - fix behavior of stop_SSL: for blocking sockets it now enough to call it once, for non-blocking it should be called again as long as EAGAIN and SSL_ERROR is set to SSL_WANT_(READ|WRITE). - don't call blocking if start_SSL failed and downgraded socket has no blocking method, thanks to tokuhirom - documentation enhancements: - special section for differences to IO::Socket - describe problem with blocking accept on non-blocking socket - describe arguments to new_from_fd and make clear, that for upgrading an existing IO::Socket start_SSL should be used directly 1.962 2013/11/27 - work around problems with older F5 BIG-IP by offering fewer ciphers on the client side by default, so that the client hello stays below 255 byte 1.961 2013/11/26 - IO::Socket::SSL::Utils::CERT_create can now create CA-certificates which are not self-signed (by giving issuer_*) 1.960 2013/11/12 only documentation enhancements: - clarify with text and example code, that within event loops not only select/poll should be used, but also pending has to be called. - better introduction into SSL, at least mention anonymous authentication as something you don't want and should take care with the right cipher - make it more clear, that user better does not change the cipher list, unless he really know what he is doing 1.959 2013/11/12 - bugfix test core.t windows only 1.958 2013/11/11 - cleanup: remove workaround for old IO::Socket::INET6 but instead require at least version 2.55 which is now 5 years old - fix t/session.t #RT90240, thanks to paul[AT]city-fan[DOT]org 1.957 2013/11/11 - fixed t/core.t: test uses cipher_list of HIGH, which includes anonymous authorization. With the DH param given by default since 1.956 old versions of openssl (like 0.9.8k) used cipher ADH-AES256-SHA (e.g. anonymous authorization) instead of AES256-SHA and thus the check for the peer certificate failed (because ADH does not exchanges certificates). Fixed by explicitly specifying HIGH:!aNULL as cipher RT#90221, thanks to paul[AT]city-fan[DOT]org - cleaned up tests: - remove ssl_settings.req and 02settings.t, because all tests now create a simple socket at 127.0.0.1 and thus global settings are no longer needed. - some tests did not have use strict(!), fixed it. - removed special handling for older Net::SSLeay versions, which are less than our minimum requirement - some syntax enhancements, removed some SSL_version and SSL_cipher_list options where they were not really needed 1.956 2013/11/10 lots of behavior changes for more secure defaults: - BEHAVIOR CHANGE: make default cipher list more secure, especially - no longer support MD5 by default (broken) - no longer support anonymous authentication by default (vulnerable to man in the middle attacks) - prefer ECDHE/DHE ciphers and add necessary ECDH curve and DH keys, so that it uses by default forward secrecy, if underlying Net::SSLeay/openssl supports it - move RC4 at the end, e.g. 3DES is prefered (BEAST attack should hopefully been fixed and now RC4 is considered less safe than 3DES) - default SSL_honor_cipher_order to 1, e.g. when used as server it tries to get the best cipher even if client preferes other ciphers PLEASE NOTE that this might break connections with older, less secure implementations. In this case revert to 'ALL:!LOW:!EXP:!aNULL' or so. - BEHAVIOR CHANGE: SSL_cipher_list now gets set on context not SSL object and thus gets reused if context gets reused. PLEASE NOTE that using SSL_cipher_list together with SSL_reuse_ctx has no longer effect on the ciphers of the context. - rework hostname verification schemes - add rfc names as scheme (e.g. 'rfc2818',...) - add SIP, SNMP, syslog, netconf, GIST - BEHAVIOR CHANGE: fix SMTP - now accept wildcards in CN and subjectAltName - BEHAVIOR CHANGE: fix IMAP, POP3, ACAP, NNTP - now accept wildcards in CN - BEHAVIOR CHANGE: anywhere wildcards like www* now match only 'www1', 'www2'.. but not 'www' - anywhere wildcards like x* are no longer applied to IDNA names (which start with 'xn--') - fix crash of Utils::CERT_free - support TLSv11, TLSv12 as handshake protocols 1.955 2013/10/11 - support for forward secrecy using ECDH, if the Net::SSLeay/openssl version supports it. 1.954 2013/9/15 - accept older versions of ExtUtils::MakeMaker and add meta information like link to repository only for newer versions. 1.953 2013/7/22 - fixes to IO::Socket::SSL::Utils, thanks to rurban[AT]x-ray[DOT]at, RT#87052 1.952 2013/7/11 - fix t/acceptSSL-timeout.t on Win32, RT#86862 1.951 2013/7/3 - better document builtin defaults for key,cert,CA and how they are depreceated - use Net::SSLeay::CTX_set_default_verify_paths to use openssl's builtin defaults for CA unless CA path/file was given (or IO::Socket::SSL builtins used) 1.950 2013/7/3 - MAJOR BEHAVIOR CHANGE: ssl_verify_mode now defaults to verify_peer for client. Until now it used verify_none, but loudly complained since 1.79 about it. It will not complain any longer, but the connection might probably fail. Please don't simply disable ssl verification, but instead set SSL_ca_file etc so that verification succeeds! - MAJOR BEHAVIOR CHANGE: it will now complain if the builtin defaults of certs/my-ca.pem or ca/ for CA and certs/{server,client}-{key,cert}.pem for cert and key are used, e.g. no certificates are specified explicitly. In the future these insecure (relative path!) defaults will be removed and the CA replaced with the system defaults. v1.94 2013.06.01 - Makefile.PL reported wrong version of openssl, if Net::SSLeay was not installed instead of reporting missing dependency to Net::SSLeay. v1.93 2013.05.31 - need at least OpenSSL version 0.9.8 now, since last 0.9.7 was released 6 years ago. Remove code to work around older releases. - changed AUTHOR in Makefile.PL from array back to string, because the array feature is not available in MakeMaker shipped with 5.8.9 (RT#85739) v1.92 2013.05.30 - Intercept: use sha1-fingerprint of original cert for id into cache unless otherwise given - Fix pod error in IO::Socket::SSL::Utils RT#85733 v1.91 2013.05.30 - added IO::Socket::SSL::Utils for easier manipulation of certificates and keys - moved SSL interception into IO::Socket::SSL::Intercept and simplified it using IO::Socket::SSL::Utils - enhance meta information in Makefile.PL v1.90 2013.05.27 - RT#85290, support more digest, especially SHA-2. Thanks to ujvari[AT]microsec[DOT]hu - added support for easy SSL interception (man in the middle) based on ideas found in mojo-mitm proxy (which was written by Karel Miko) - make 1.46 the minimal required version for Net::SSLeay, because it introduced lots of useful functions. v1.89 2013.05.14 - if IO::Socket::IP is used it should be at least version 0.20, otherwise we get problems with HTTP::Daemon::SSL and maybe others (RT#81932) - Spelling corrections, thanks to dsteinbrunner v1.88 2013.05.02 - consider a value of '' the same as undef for SSL_ca_(path|file), SSL_key* and SSL_cert* - some apps like Net::LDAP use it that way. Thanks to alexander[AT]kuehn[AT]nagilum[DOT]de for reporting the problem. v1.87 2013.04.24 - RT#84829 - complain if given SSL_(key|cert|ca)_(file|path) do not exist or if they are not readable. Thanks to perl[AT]minty[DOT]org - fix use of SSL_key|SSL_file objects instead of files, broken with 1.83 v1.86 2013.04.17 - RT#84686 - don't complain about SSL_verify_mode is SSL_reuse_ctx, thanks to CLEACH v1.85 2013.04.14 - probe for available modules with local __DIE__ and __WARN__handlers. fixes RT#84574, thanks to FRAZER - fix warning, when IO::Socket::IP is installed and inet6 support gets explictly requested. RT#84619, thanks to Prashant[DOT]Tekriwal[AT]netapp[DOT]com v1.84 2013.02.15 - disabled client side SNI for openssl version < 1.0.0 because of RT#83289 - added functions can_client_sni, can_server_sni, can_npn to check avaibility of SNI and NPN features. Added more documentation for SNI and NPN. v1.83_1 2013.02.14 - seperated documention of non-blocking I/O from error handling - changed and documented behavior of readline to return the read data on EAGAIN/EWOULDBLOCK in case of non-blocking socket. See https://github.com/noxxi/p5-io-socket-ssl/issues/1, thanks to mytram v1.83 2013.02.03 - Server Name Indication (SNI) support on the server side, inspired by patch provided by karel[DOT]miko[AT]gmail[DOT]com. https://rt.cpan.org/Ticket/Display.html?id=82761 - reworked part of the documentation, like providing better examples. v1.82 2013.01.28 - sub error sets $SSL_ERROR etc only if there really is an error, otherwise it will keep the latest error. This causes IO::Socket::SSL->new.. to report the correct problem, even if the problem is deeper in the code (like in connect) - correct spelling, rt#8270. Thanks to ETHER v1.81 2012.12.06 - deprecated set_ctx_defaults, new name ist set_defaults (but old name still available) - changed handling of default path for SSL_(ca|cert|key)* keys: either if one of these keys is user defined don't add defaults for the others, e.g. don't mix user settings and defaults - cleaner handling of module defaults vs. global settings vs. socket specific settings. Global and socket specific settings are both provided by the user, while module defaults not. - make IO::Socket::INET6 and IO::Socket::IP specific tests run both, even if both modules are installed by faking a failed load of the other module. v1.80 2012.11.30 - removed some warnings in test (missing SSL_verify_mode => 0) which caused tests to hang on Windows. https://rt.cpan.org/Ticket/Display.html?id=81493 v1.79 2012.11.25 - prepare transition to a more secure default for SSL_verify_mode. The use of the current default SSL_VERIFY_NONE will cause a big warning for clients, unless SSL_verify_mode was explicitly set inside the application to this insecure value. In the near future the default will be SSL_VERIFY_PEER, and thus causing verification failures in unchanged applications. v1.78 2012.11.25 - use getnameinfo instead of unpack_sockaddr_in6 to get PeerAddr and PeerPort from sockaddr in _update_peer, because this provides scope too. Thanks to bluhm[AT]genua[DOT]de. - work around systems which don't defined AF_INET6 https://rt.cpan.org/Ticket/Display.html?id=81216 Thanks to GAAS for reporting v1.77 2012.10.05 - update_peer for IPv6 also, applied fix to https://rt.cpan.org/Ticket/Display.html?id=79916 by tlhackque[AT]yahoo[DOT]com v1.76 2012.06.18 - no longer depend on Socket.pm 1.95 for inet_pton, but use Socket6.pm if no current Socket.pm is available. Thanks to paul[AT]city-fan[DOT]org for pointing out the problem and providing first patch v1.75 2012.06.15 - made it possible to explicitly disable TLSv11 and TLSv12 in SSL_version v1.74_2 2012.06.07 - fixed documentation errors, reported by MARSCHAP https://rt.cpan.org/Ticket/Display.html?id=77690 v1.74_1 2012.06.07 - add support to IO::Socket::IP which support inet6 and inet4 by integrating patch from PEVANS for https://rt.cpan.org/Ticket/Display.html?id=75218 v1.74 2012.05.13 - accept a version of SSLv2/3 as SSLv23, because older documentation could be interpreted like this v1.73 2012.05.11 - make test t/dhe.t hopefully work for more version of openssl Thanks to paul[AT]city-fan[DOT]org for providing bug reports and testing environment v1.72 2012.05.10 - set DEFAULT_CIPHER_LIST to ALL:!LOW instead of HIGH:!LOW Thanks to dcostas[AT]gmail[DOT]com for problem report v1.71 2012.05.09 - 1.70 done right. Also don't disable SSLv2 ciphers, SSLv2 support is better disabled by the default SSL_version of 'SSLv23:!SSLv2' v1.70 2012.05.08 - make it possible to disable protols using SSL_version, make SSL_version default to 'SSLv23:!SSLv2' v1.69 2012.05.08 - re-added workaround in t/dhe.t v1.68 2012.05.07 - remove SSLv2 from default cipher list, which makes failed tests after last change work again, fix behvior for empty cipher list (use default) v1.67 2012.05.07 - https://rt.cpan.org/Ticket/Display.html?id=76929 thanks to d[DOT]thomas[AT]its[DOT]uq[DOT]edu[DOT]au for reporting - if no explicit cipher list is given it will now default to ALL:!LOW instead of the openssl default, which usually includes weak ciphers like DES. - new config key SSL_honor_cipher_order and documented how to use it to fight BEAST attack. v1.66 2012.04.16 - make it thread safer, thanks to bug report from vega[DOT]james[AT]gmail [DOT]com, https://rt.cpan.org/Ticket/Display.html?id=76538 v1.65 2012.04.16 - added NPN (Next Protocol Negotiation) support based on patch from kmx https://rt.cpan.org/Ticket/Display.html?id=76223 v1.64 2012.04.06 - clarify some behavior regarding hostname verfication. Thanks to DOHERTY for reporting. v1.63 2012.04.06 - applied patch of DOUGDUDE to ignore die from within eval to make tests more stable on Win32, https://rt.cpan.org/Ticket/Display.html?id=76147 v1.62 2012.03.28 - small fix to last version v1.61 2012.03.27 - call CTX_set_session_id_context so that servers session caching works with client certificates too. https://rt.cpan.org/Ticket/Display.html?id=76053 v1.60 2012.03.20 - don't make blocking readline if socket was set nonblocking, but return as soon no more data are available https://rt.cpan.org/Ticket/Display.html?id=75910 - fix BUG section about threading so that it shows package as thread safe as long as Net::SSLeay >= 1.43 is used https://rt.cpan.org/Ticket/Display.html?id=75749 v1.59 2012.03.08 - if SSLv2 is not supported by Net::SSLeay set SSL_ERROR with useful message when attempting to use it. - modify constant declarations so that 5.6.1 should work again v1.58 2012.02.26 - fix t/dhe.t again to enable the workaround only for newer openssl versions, because this would cause failures on older versions v1.57 2012.02.26 - fix t/dhe.t for openssl 1.0.1 beta by forcing tlsv1, so that it does not complain about the too small rsa key which it should not use anyway. Thanks to paul[AT]city-fan[DOT]org for reporting. https://rt.cpan.org/Ticket/Display.html?id=75165 v1.56 2012.02.22 - add automatic or explicit (via SSL_hostname) SNI support, needed for multiple SSL hostnames with same IP. Currently only supported for the client. v1.55 2012.02.20 - work around IO::Sockets work around for systems returning EISCONN etc on connect retry for non-blocking sockets by clearing $! if SUPER::connect returned true. https://rt.cpan.org/Ticket/Display.html?id=75101 Thanks for Manoj Kumar for reporting. v1.54 2012.01.11 - return 0 instead of undef in SSL_verify_callback to fix unitialized warnings. Thanks to d[DOT]thomas[AT]its[DOT]uq[DOT]edu[DOT]au for reporting the bug and MIKEM for the fix. https://rt.cpan.org/Ticket/Display.html?id=73629 v1.53 2011.12.11 - kill child in t/memleak_bad_hanshake.t if test fails https://rt.cpan.org/Ticket/Display.html?id=73146 Thanks to CLEACH ofr reporting v1.52 2011.12.07 - fix syntax error in t/memleak_bad_handshake.t thanks to cazzaniga[DOT]sandro[AT]gmail[DOT]com for reporting v1.51 2011.12.06 - disable t/memleak_bad_handshake.t on AIX, because it might hang https://rt.cpan.org/Ticket/Display.html?id=72170 v1.50 2011.12.06 Thanks to HMBRAND for reporting and Rainer Tammer tammer[AT]tammer[DOT]net for providing access to AIX system v1.49 2011.10.28 - another regression for readline fix, this time it failed to return lines at eof which don't end with newline. Extended t/readline.t to catch this case and the fix for 1.48 Thanks to christoph[DOT]mallon[AT]gmx[DOT]de for reporting v1.48 2011.10.26 - bugfix for readline fix in 1.45. If the pending data where false (like '0') it failed to read rest of line. Thanks to Victor Popov for reporting https://rt.cpan.org/Ticket/Display.html?id=71953 v1.47 2011.10.21 - fix for 1.46 - check for mswin32 needs to be /i. Thanks to Alexandr Ciornii for reporting v1.46 2011.10.18 - disable test t/signal-readline.t on windows, because signals are not relevant for this platform and test does not work. https://rt.cpan.org/Ticket/Display.html?id=71699 v1.45 2011.10.12 - fix readline to continue when getting interrupt waiting for more data. Thanks to kgc[AT]corp[DOT]sonic[DOT]net for reporting problem v1.44 2011.05.27 - fix invalid call to inet_pton in verify_hostname_of_cert when identity should be verified as ipv6 address, because it contains colon. v1.43_1 2011.05.12 - try to make t/nonblock.t more stable, especially on Mac OS X v1.43 2011.05.11 - fix t/nonblock.t - stability improvements t/inet6.t v1.42 2011.05.10 - add SSL_create_ctx_callback to have a way to adjust context on creation. https://rt.cpan.org/Ticket/Display.html?id=67799 - describe problem of fake memory leak because of big session cache and how to fix it, see https://rt.cpan.org/Ticket/Display.html?id=68073 v1.41 2011.05.09 - fix issue in stop_SSL where it did not issue a shutdown of the SSL connection if it first received the shutdown from the other side. Thanks to fencingleo[AT]gmail[DOT]com for reporting - try to make t/nonblock.t more reliable, at least report the real cause of ssl connection errors v1.40 2011.05.02 - integrated patch from GAAS to get IDN support from URI. https://rt.cpan.org/Ticket/Display.html?id=67676 v1.39_1 2011.05.02 - fix in exampel/async_https_server. Thanks to DetlefPilzecker[AT]web[DOT]de for reporting v1.39 2011.03.03 - fixed documentation of http verification: wildcards in cn is allowed v1.38_1 2011.01.24 - close should undef _SSL_fileno, because the fileno is no longer valid (SSL connection and socket are closed) v1.38 2011.01.18 - fixed wildcards_in_cn setting for http (wrongly set in 1.34 to 1 instead of anywhere). Thanks to dagolden[AT]cpan[DOT]org for reporting https://rt.cpan.org/Ticket/Display.html?id=64864 v1.37 2010.12.09 - don't complain about invalid certificate locations if user explicitly set SSL_ca_path and SSL_ca_file to undef. Assume that user knows what he is doing and will work around the problems by itself. http://rt.cpan.org/Ticket/Display.html?id=63741 v1.36 2010.12.08 - update documentation for SSL_verify_callback based on https://rt.cpan.org/Ticket/Display.html?id=63743 https://rt.cpan.org/Ticket/Display.html?id=63740 v1.35 2010.12.06 - if verify_mode is not VERIFY_NONE and the ca_file/ca_path cannot be verified as valid it will no longer fall back to VERIFY_NONE but throw an error. Thanks to Salvatore Bonaccorso and Daniel Kahn Gillmor for pointing out the problem, see also http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=606058 v1.34 2010.11.01 - scheme http for certificate verification changed to wildcards_in_cn=1, because according to rfc2818 this is valid and also seen in the wild - if upgrading socket from inet to ssl fails due to handshake problems the socket gets downgraded, but is still open. See https://rt.cpan.org/Ticket/Display.html?id=61466 - deprecate kill_socket, just use close() v1.33 2010.03.17 - attempt to make t/memleak_bad_handshake.t more stable, it fails for unknown reason on various systems - fix hostname checking: an IP should only be checked against subjectAltName GEN_IPADD, never against GEN_DNS or CN. Thanks to rusch[AT]genua[DOT]de for bug report v1.32 2010.02.22 - Makefile.PL: die if Scalar::Util has no dualvar support instead of only complaining. Thanks to w[DOT]phillip[DOT]moore[AT]gmail[DOT]com for reporting. v1.31 2009.09.25 - add and export constants for SSL_VERIFY_* - set SSL_use_cert if cert is given and not SSL_server - support alternative CRL file with SSL_crl_file thanks to patch of w[DOT]phillip[DOT]moore[AT]gmail[DOT]com v1.30_3 2009.09.03 - make t/memleak_bad_handshake.t more stable (increase listen queue, ignore errors on connect, don't run on windows..) v1.30_2 2009.09.01 - t/memleak_bad_handshake.t don't write errors with ps to stderr, -o vsize argument is not supported on all platforms, just skip test then v1.30_1 2009.08.31 - make sure that idn_to_ascii gets no \0 bytes from identity, because it simply cuts the string their (using C semantics). Not really a security problem because IDN like identity is provided by user in hostname, not by certificate. v1.30 2009.08.19 - fix test t/memleak_bad_handshake.t v1.29 2009.08.19 - fixed thanks for version 1.28 v1.28 2009.08.19 - fix memleak when SSL handshake failed. Thanks richardhundtu[AT]gmail[DOT]com v1.27 2009.07.24 - changed possible local/utf-8 depended \w in some regex against more explicit [a-zA-Z0-9_]. Fixed one regex, where it assumed, that service names can't have '-' inside - fixed bug https://rt.cpan.org/Ticket/Display.html?id=48131 where eli[AT]dvns[DOT]com reported warnings when perl -w was used. While there made it more aware of errors in Net::ssl_write_all (return undef not 0 in generic_write) v1.26 2009.07.03 - SECURITY BUGFIX! fix Bug in verify_hostname_of_cert where it matched only the prefix for the hostname when no wildcard was given, e.g. www.example.org matched against a certificate with name www.exam in it Thanks to MLEHMANN for reporting v1.25 2009.07.02 - t/nonblock.t: increase number of bytes written to fix bug with OS X 10.5 https://rt.cpan.org/Ticket/Display.html?id=47240 v1.24 2009.04.01 - add verify hostname scheme ftp, same as http - renew test certificates again (root CA expired, now valid for 10 years) v1.23 2009.02.23 - if neither SSL_ca_file nor SSL_ca_path are known (e.g not given and the default values have no existing file|path) disable checking of certificates, but carp about the problem - new test certificates, the old ones expired and caused tests to fail v1.22 2009.01.24 - Net::SSLeay stores verify callbacks inside hash and never clears them, so set verify callback to NULL in destroy of context v1.21 2009.01.22 - auto verification of name in certificate created circular reference between SSL and CTX object with the verify_callback, which caused the objects to be destroyed only at program end. Fix it be no longer access $self from inside the callback. Thanks to odenbach[AT]uni-paderborn[DOT]de for reporting v1.20 2009.01.15 - only changes on test suite to make it ready for win32 (tested with strawberry perl 5.8.8) v1.19 2008.12.31 - fix verifycn_name autodetection from PeerAddr/PeerHost v1.18 2008.11.17 - fixed typo in argument: wildcars_in_cn -> wildcards_in_cn http://rt.cpan.org/Ticket/Display.html?id=40997 thanks to ludwig[DOT]nussel[AT]suse[DOT]de for reporting v1.17 2008.10.13 - no code changes, publish v.16_3 as v.17 because it looks better than v.16 - document win32 behavior regarding non-blocking and timeouts v1.16_3 2008.09.25 - fix t/nonblock.t with workaround for problems with IO::Socket::INET on some systems (Mac,5.6.2) where it cannot do nonblocking connect and leaves socket blocked. - make some tests less verbose by fixing diag in t/testlib.t (send output to STDOUT not STDERR and prefix with '#') v1.16_2 2008.09.24 - work around Bug in IO::Socket::INET6 on BSD systems http://rt.cpan.org/Ticket/Display.html?id=39550 by setting Domain based on PeerAddr Thanks to srezic for report and support - remove tests of recv/send from t/core.t. Might badly interact with SSL handshake and cause crashes as seen on OS X 10.4 v1.16_1 2008.09.19 - better support for IPv6: - IPv6 is enabled by default if IO::Socket::INET6 is available - t/inet6.t for basic tests v1.16 2008.09.19 - change code for SSL_check_crl to use X509_STORE_set_flags instead of X509_STORE_CTX_set_flags based on bug report from - change opened() to report -1 if the IO::Handle is open, but the SSL connection failed, needed with HTTP::Daemon::SSL which will send an error mssage over the unencrypted socket v1.15 - change internal behavior when SSL handshake failed (like when verify callback returned an error) in the hope to fix spurios errors in t/auto_verify_hostname.t v1.14 - added support for verification of hostname from certificate including subjectAltNames, support for IDN etc based on patch and input from christopher[AT]odenbachs[DOT]de and achim[AT]grolmsnet[DOT]de. It is also possible to get more information from peer_certificate based on this patch. See documentation for peer_certificate and verify_hostname - automatic verification of hostnames with SSL_verifycn_scheme and SSL_verifycn_name - global setting of default context options like SSL_verifycn_scheme, SSL_verify_mode with set_ctx_defaults - fix import of inet4,inet6 which got broken within 1.13_X. Thanks to for bugreport and patch - clarified and enhanced debugging supppport based on bugreport http://rt.cpan.org/Ticket/Display.html?id=32960 - put information into README regarding the supported and recommanded version of Net::SSLeay v1.13 - removed CLONE_SKIP which was added in 1.03 because this breaks windows forking. Handled threads/windows forking better by making sure that CTX from Net::SSLeay gets not freed multiple times from different threads after cloning/forking - removed setting LocalPort to 0 in tests, instead leave it undef if a random port should be allocated. This should fix build problems with 5.6.1. Thanks to v1.12 - treat timeouts of 0 for accept_SSL and connect_SSL like no timeout, like IO::Socket does. v1.11 - fixed errors in accept_SSL which would work when called from start_SSL but not from accept v1.10 - start_SSL, accept_SSL and connect_SSL have argument for Timeout so that the SSL handshake will not block forever. Only used if the socket is blocking. If not set the Timeout value from the underlying IO::Socket is used v1.09 - new method stop_SSL as opposite of start_SSL based on a idea of Bron Gondwana To support this method the SSL_shutdown handling had to be fixed, e.g. in close a proper unidirectional shutdown should be done while in stop_SSL a bidirectional shutdown - try to make it clearer that thread support is buggy v1.08 - make sure that Scalar::Util has support for dualvar (Makefile.PL,SSL.pm) because the perl-only version has has no dualvar v1.07 - fix t/nonblock.t on systems which have by default a larger socket buffer. Set SO_SNDBUF explicitly with setsockopt to force smaller writes on the socket v1.06 - instead of setting undef args to '' in configure_SSL drop them. This makes Net::SMTP::SSL working again because it does not give LocalPort of '' to IO::Socket::INET any more v1.05 - make session cache working even if the IO::Socket::SSL object was not created with IO::Socket::SSL->new but with IO::Socket::SSL->start_SSL on an established socket v1.04 - added way to create SSL object with predefined session cache, thus making it possible to share the cache between objects even if the rest of the context is not shared key SSL_session_cache Note that the arguments of IO::Socket::SSL::SessionCache::new changed (but you should never have used this class directly because it's internal to IO::Socket::SSL) v1.03 - add CLONE_SKIP as proposed by Jarrod Johnson jbjohnso at us dot ibm dot com v1.02 - added some info to BUGS and to BUGS section of pod - added TELL and BINMODE to IO::Socket::SSL::SSL_HANDLE, even if they do nothing useful. - all tests allocate now the ports dynamically, so there should be no longer a conflict with open ports on the system where the tests run v1.01 - work around Bug in Net::HTTPS where it defines sub blocking as {}, e.g. force scalar context when calling sub blocking (in IO::Socket::SSL::write) see http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=383106 v1.0 - fix deprecated and practically undocumented function get_peer_certificate so that LWP Net::HTTPS works again - set arg 'Blocking' while calling SUPER::configure only if it was set by the caller to work around Problem in LWP Net::HTTPS v0.999 - If SSL_cipher_list is not given it uses the openssl default instead of setting it to 'ALL:!LOW:!EXP' like before. The old value included ADH and this might be a bad idea, see BUGS why. v0.998 - declare socket as opened before calling fatal_ssl_error because the SSL_error_trap set up from HTTP::Daemon needs this - accept_SSL sets errors on $socket (the accepted socket) not $self (the listening socket if called from accept) so it can be queried from SSL_error_trap - note in BUGS section that IO::Socket::SSL is not thread-safe v0.997 - fix readline (e.g. getline,getlines,<>) so that it behaves regarding $/ like written in the $/ dokumentation. v0.996 - removed links and comments to inofficial release of Net::SSLeay, because there is a newer version already v0.995 - add support for Diffie Hellman Key Exchange. See parameter SSL_dh_file and SSL_dh. v0.994 - hide DEBUG statements and remove test to load Debug.pm because packets like Spamassisin cannot cope with it (at least the OpenBSD port) v0.993 - added SSL_cert and SSL_key parameter which do not take a file name like SSL_cert_file and SSL_key_file but an internal X509* resp. EVP_PKEY* value. Useful for dynamically created certificates and keys. - added test for sysread/syswrite behavior (which was changed in v0.991) v0.992 - _set_rw_error does $!||=EAGAIN only if error is one of SSL_WANT_READ|SSL_WANT_WRITE (patch from Mike Smith ) - Fix Makefile.PL to allow detectection of failures in PREREQ_PM (http://rt.cpan.org/Public/Bug/Display.html?id=20563, patch by alexchorny at gmail dot com) v0.991 - sysread and syswrite ar no longer the same as read and write, but can return already if only parts of the data are read or written (which is the usual semantic for sysread and syswrite) This should fix problems with HTTP::Daemon::SSL v0.99 - just upgrade Version number because I've screwed up upload of v0.98 to cpan v0.98 - Maintainer changed to - Better support for nonblocking sockets: . exports $SSL_ERROR which contains the latest error from the openssl library. Exports constants SSL_WANT_READ and SSL_WANT_WRITE es special errors which will be set if openssl wants to write or read during nonblocking connects, accepts, reads or writes. . accept,accept_SSL,connect and connect_SSL don't block anymore if the socket is nonblocking. Instead $! will be set from the underlying IO::Socket::INET connect or accept if it failed there (usually EAGAIN or EINPROGRESS) or if the underlying openssl needs to read or write $! will be set to EAGAIN and $SSL_ERROR will be set to SSL_WANT_READ or SSL_WANT_WRITE . syswrite returns undef and sets $!,$SSL_ERROR if it fails to write instead of returning 0. - Bugfixes (http://rt.cpan.org/Public/Bug/Display.html?id=Bugid) . Bug 18439: fileno 0 should be valid . Bug 15001: sysread interpretes buffer "0" as "" - peer_certifcate returns X509 struct string if no field for extraction was specified - get_peer_certificate returns the certificate instead of the IO::Socket::SSL object v0.97 - Writes now correctly return errors. (Problem noted by Dominique Quatravaux ). - CA paths now work without passing an empty SSL_ca_file argument. (Problem found by Phil Pennock, ). - IO::Socket::SSL now automatically passes Proto => tcp (if not already specified) to IO::Socket::INET to work around /etc/services files with udp entries listed first. (Fix suggested by Phil Pennock). - $socket->accept() now returns the peer address in array context for better conformance with IO::Socket::INET. However, if you were doing "map { $_->accept } (@sockets)", or similar tricks, you will need to use "scalar" to get the old behavior back. (Problem noted by Nils Sowen, ). - IO::Socket::SSL should now properly block on reads larger than the buffer size of Net::SSLeay. (Problem found by Eric Jergensen, ). - IO::Socket::SSL should now send CA Certs (if necessary) along with certificates. (Problem found by ). - Timeouts should now work, but be aware that if multiple reads/writes are necessary to complete a connection, then each one may have a separate timeout. (Request from Dominique Quatravaux ). - In certain cases, start_SSL() would misplace a socket's fileno, causing problems with starting SSL. This should now be fixed. (Problem found by ). - IO::Socket::SSL now requires a minimum of Net::SSLeay 1.21. --- Old Versions -------------------------------------------------- v0.96 2004.4.30 - Makefile's error messages now correct if output is redirected (patch from Ilya Zakharevich ). - Non-blocking connects/accepts now work (Problem found by Uri Guttman ). - new_from_fd() now works. - getline() and <> in scalar context now return undef instead of '' if the read failed. (Problem found by Christian Gilmore ). - Broken pipe signals are now ignored during socket close to prevent a SSL shutdown message from killing the parent program. (Problem found by Christian Gilmore). - Tests should proceed much more quickly, and a semi-race was fixed, meaning that on slow machines the tests should be more reliable. - Check for Scalar::Util and Weakref now uses default $SIG{__DIE__} instead of a potentially user-altered one (suggestion from Olaf Schneider ). This only applies to Perl 5.6.0 & above. - Session caching support (patch from Marko Asplund ). - set_default_context() added to alter the behavior of modules that use IO::Socket::SSL from the main program. - get_ssl_object() renamed to _get_ssl_object() to reflect the fact that it's only supposed to be used internally (not that you should have cared, of course). - Added patch for Net::SSLeay to take advantage of client-side session caching. v0.95 2003.8.25 - Changed PeerAddr in example/ssl_client.pl back to localhost. - Update of examples to automatically switch to the proper directory if they cannot find the necessary SSL certificates. - Minor documentation update with more INET6 info. - Corrected some error messages for IO::Socket::INET6. - Better opened() behavior when sockets close unexpectedly. - Added note about random number generators for Solaris users (Problem found by Christian Gilmore ). - Added support for WeakRef and Scalar::Util to allow IO::Socket::SSL objects to auto-destroy themselves when they go out of scope. - Added croak()ing for unimplemented send() and recv() methods so they are not accidentally used to transmit unencrypted data. The Perl builtin functions cannot be reliably trapped and are still dangerous, a fact that the POD now reflects (Problem noted by Michal Ludvig ). v0.94 2003.6.26 - Changed accept() to use inherited accept() instead of IO::Socket::accept, so that IPv6 inheritance is possible. - Added options to import() so that a user could specify IPv6 or IPv4 mode of operation. - Documentation fixes, esp. e-mail address. v0.93 2003.6.24 - Fixed error-checking slip in connect_SSL() (Problem found by Uri Guttman ). - All functions now return the empty list () on errors. - Added note about the above change to appease Graham Barr . - Fixed Net::SSLeay giving warnings when arguments are undef; in all cases, undef arguments may be set to '' without any change in behavior except for removing the warnings. (Problem found by Dominique Quatravaux ) - If accept() or connect() fails in SSL negotiation, the user now has the option to print something to the failed socket before it is closed. (error_trap option in new()) - Added support for CRLs (SSL_check_crl option in new()) for versions of OpenSSL >= 0.9.7b (Original patch from Brian Lindauer ) - Finally added decent support for certificate callbacks. (SSL_verify_callback option in new(), suggestion from Dariush Pietrzak ). - accept()/connect()/socket_to_SSL() now fail immediately if the socket in question does not have a fileno. - Added the kill_socket() method to guarantee that a socket dies. - Fixed extra warning when printing errors in debug mode. - Deprecated socket_to_SSL() in favor of the class method start_SSL() (Class method suggestion from Graham Barr ). - Added the class method start_SSL() to allow for cases when the desired class of the socket is not IO::Socket::SSL (Request from Dariush Pietrzak ) - Changed socket_to_SSL to rebless socket to original class if SSL negotiation failed (Request from Graham Barr ) - Removed the daemon.pl example, as it did not work with the standard distribution of HTTP::Daemon (use HTTP::Daemon::SSL instead). v0.92 2002.10.22 - Changed the fileno() function to support returning the fileno of server sockets. (Problem found by Roland Giersig ). - Fixed SSL_version incorrectly defaulting to SSLv2 (patch from Roland Alder ). v0.91 2002.08.31 - Added support for SSL_peek and SSL_pending (peek() and pending()). Updated documentation, tests, etc. to reflect this. v0.901 2002.08.19 - Fixed the warning that happens when sockets are not explicitly closed() before the program terminates. v0.90 2002.08.13 - This version is a complete rewrite of IO::Socket::SSL. It now has about half the lines of code, twice the amount of documentation, and a slightly more polished interface. - IO::Socket::SSL now works properly with mod_perl and taint mode. - Major documentation update. - Update of the BUGS file to reflect changes made in the rewrite. - Update of the test suite for Perl v5.8.0 (or, more precisely, for Scalar::Util). - Update of the test suite for Perl v5.00503 (or, more precisely, for the lack of several nice features added in v5.6.0) (Marko Asplund ). - New test suite that does not need the Internet to function. - Update of all the files in example/ to use more current features of IO::Socket::SSL. - Removal of SSL_SSL and X509_Certificate classes. - There have been a few name changes (like socketToSSL -> socket_to_SSL) for better consistency. - The functionality of get_peer_certificate() and friends is deprecated. - The functionality of want_write() and want_read() is deprecated. - The functionality of context_init() is deprecated for normal use. - Support for all SSL context options in the new() call. - SSL contexts are no longer global. The SSL_reuse_ctx option is provided for those who want to re-use a context. - The default verify mode is now VERIFY_NONE. - IO::Socket::SSL::DEBUG is now linked to Net::SSLeay::trace to provide different levels of debugging information. - There is a uniform interface for error reporting, so on error all functions will return undef and the error will be available by calling errstr(). - The dump_peer_certificate() and peer_certificate() functions have been added. - sysread() will now behave correctly if the offset argument is greater than the length of the read buffer. It also will truncate the read buffer properly, according to the Perl documentation for sysread(). - getline(), getlines(), and getc() have been added. - syswrite() now uses references to avoid copying large amounts of data. - readline() uses ssl_read_all in array context for improved speed. - close() now uses SSL_shutdown() to properly close an SSL connection, unless you tell it not to. - If you have Net::SSLeay version 1.18 or greater, X509 certificates will be properly freed. - All other known bugs have been fixed. v0.81a (Not publically released) - Added support for SSL_passwd_cb. - Added accept() server socket support to socketToSSL(). v0.81 2002.04.10 - calling context_init twice destroyed global context. fix from Jason Heiss . - file handle tying interface implementation moved to a separate class to prevent problems resulting from self-tying filehandles. Harmon S. Nine . - docs/debugging.txt file added - require Net::SSLeay v1.08 - preliminary support for non-blocking read/write - socketToSSL() now respects context's SSL verify setting reported by Uri Guttman . v0.80 2001.08.19 - fixed startTLS support (socketToSSL) (Graham Barr ) - make accept() set fileno attribute on newly created IO::Socket::SSL object (Martin Oldfield ). - certificate updates. - use SSL_CTX_use_PrivateKey_file in SSL_Context::new. v0.79 2001.06.04 - angle bracket readline operator support (David Darville ). - eliminate warnings in choosing SSL protocol version. - implement our own opened method and make length parameter optional in syswrite (Robert Bihlmeyer ). v0.78 2001.04.24 - test script targets changed, certificate setup fixed - support for TLS in SSL_version. SSL_version parameter values changed from integer to string. NB: this is an incompatible change. all SSL_version parameter values have to be changed. valid values include: 'sslv2', 'sslv3', 'sslv23'. Stephen C. Koehler . - enable selecting SSL version for connections. patch from Takanori Ugai . - allow setting SSL_ca_file to ''. this is needed for being able to use SSL_ca_path (Robert Bihlmeyer ). - include the Apache CA bundle file in the distribution (my-ca.pem). - BUGS file added. v0.77 2001.01.15 - don't setup SSL CA verification unless cert verification is actually used for the connections. - default SSL protocol version selection in SSL.pm. v0.76 2000.11.17 - patch from Kwok Chern Yue for making IO::Socket::SSL work with HTTP::Daemon. v0.75 2000.07.26 - IO::Socket::SSL should now work with perl v5.6.0 - demo/*.pl and t/*.t now turn module debugging on if DEBUG command line argument is given - default certificates changed v0.74 2000.07.05 - Changes file added - bugfix in IO::Socket::SSL::sysread() (zliu2 at acsu.buffalo.edu) - libwww-perl and IO::Socket::SSL UML models added in docs - URL changes in test scripts - preliminary support for startTLS in IO::Socket::SSL::socketToSSL() - miscellanous patches for Net::SSLeay added in diffs IO-Socket-SSL-1.965/Makefile.PL0000644000175100017520000000651212263174431014444 0ustar workwork# vim: set sts=4 sw=4 ts=8 ai: use 5.008; use ExtUtils::MakeMaker; # Test to make sure that Net::SSLeay can be properly seeded! unless (defined $ENV{EGD_PATH}) { foreach (qw(/var/run/egd-pool /dev/egd-pool /etc/egd-pool /etc/entropy)) { if (-S) { $ENV{EGD_PATH}=$_; last } } } $| = 1; { # issue warning, if Net::SSLeay cannot find random generator # redefine __WARN__ only locally to allow detection of failures # in PREREQ_PM local $SIG{__WARN__} = sub { undef $SIG{__WARN__}; my $warning = shift; return unless $warning =~ /random/i; print "Net::SSLeay could not find a random number generator on\n"; print "your system. This will likely cause most of the tests\n"; print "to fail. Please see the README file for more information.\n"; print "the message from Net::SSLeay was: $warning\n"; # Taken from ExtUtils::MakeMaker 6.16 (Michael Schwern) so that # the prompt() function can be emulated for older versions of ExtUtils::MakeMaker. my $isa_tty = -t STDIN && (-t STDOUT || !(-f STDOUT || -c STDOUT)); if ($isa_tty) { print "Do you REALLY want to continue? [Default: no] "; die "User cancelled install!\n" if ( !~ /^y(?:es)?$/); } else { die "Install cancelled.\n"; } }; if (! defined $ENV{SKIP_RNG_TEST}) { eval { require Net::SSLeay; $Net::SSLeay::trace=1; Net::SSLeay::randomize(); }; die $@ if $@ =~ /cancelled/; } else { print "Random Number Generator test skipped.\n"; } } { # don't support too old OpenSSL versions anymore, only causes trouble my $openssl = eval { require Net::SSLeay; Net::SSLeay::OPENSSL_VERSION_NUMBER() }; die sprintf( "minimal required version for OpenSSL is 0.9.8, but your Net::SSLeay reports 0x%08x", $openssl) if $openssl && $openssl < 0x00908000; } # make sure that we have dualvar from the XS Version of Scalar::Util if ( eval { require Scalar::Util } ) { eval { Scalar::Util::dualvar( 0,'' ) }; die "You need the XS Version of Scalar::Util for dualvar() support" if ($@); } # check if we have something which handles IDN if ( ! eval { require Net::IDN::Encode } and ! eval { require Net::LibIDN } and ! eval { require URI; URI->VERSION(1.50) }) { warn <<'EOM'; WARNING No library for handling international domain names found. It will work but croak if you try to verify an international name against a certificate. It's recommended to install either Net::IDN::Encode, Net::LibIDN or URI version>=1.50 EOM } # See lib/ExtUtils/MakeMaker.pm for details of how to influence # the contents of the Makefile that is written. WriteMakefile( 'NAME' => 'IO::Socket::SSL', 'ABSTRACT' => 'Nearly transparent SSL encapsulation for IO::Socket::INET.', 'AUTHOR' => "Steffen Ullrich , Peter Behroozi, Marko Asplund", 'LICENSE' => 'perl', 'DISTNAME' => 'IO-Socket-SSL', 'VERSION_FROM' => 'lib/IO/Socket/SSL.pm', 'PREREQ_PM' => { 'Net::SSLeay' => 1.46, 'Scalar::Util' => 0, }, 'dist' => { COMPRESS => 'gzip', SUFFIX => 'gz', }, $ExtUtils::MakeMaker::VERSION >= 6.46 ? ( 'META_MERGE' => { resources => { license => 'http://dev.perl.org/licenses/', repository => 'https://github.com/noxxi/p5-io-socket-ssl', homepage => 'https://github.com/noxxi/p5-io-socket-ssl', bugtracker => 'https://rt.cpan.org/Dist/Display.html?Queue=IO-Socket-SSL', }, }, ):(), ); IO-Socket-SSL-1.965/README0000644000175100017520000000221012263174431013341 0ustar workwork IO::Socket::SSL is a class implementing an object oriented interface to SSL sockets. The class is a descendent of IO::Socket::INET. In order to use IO::Socket::SSL you need to have Net::SSLeay v1.46 or newer installed. To use ECDH curves (needed for perfect forward secrecy) you need to use Net::SSLeay >= 1.56 (not released at time of writing) or patch Net::SSLeay yourself using docs/net-ssley-ecdh.patch. For those who do not have a built-in random number generator (including most users of Solaris), you should install one before attempting to install IO::Socket::SSL. If you don't already have a favorite, try "egd" (egd.sourceforge.net) or one of the other "Related Projects" listed on its home page. If you want to bypass the test for existence of the RNG, then set the "SKIP_RNG_TEST" environment variable to a true value. In addition to providing a general OO interface to SSL sockets, this package can be used with libwww-perl. installation: perl Makefile.PL make make test make install -- Steffen Ullrich, Steffen_Ullrich at genua.de Peter Behroozi, behrooz at fas.harvard.edu (Originally by Marko Asplund, marko.asplund at kronodoc.fi) IO-Socket-SSL-1.965/docs/0000755000175100017520000000000012265775222013425 5ustar workworkIO-Socket-SSL-1.965/docs/net-ssley-ecdh.patch0000644000175100017520000000141512263174431017264 0ustar workworkIndex: typemap =================================================================== --- typemap (revision 382) +++ typemap (working copy) @@ -6,6 +6,7 @@ SSL * T_PTR RSA * T_PTR DH * T_PTR +EC_KEY * T_PTR const X509 * T_PTR const X509_CRL * T_PTR const X509_REQ * T_PTR Index: SSLeay.xs =================================================================== --- SSLeay.xs (revision 382) +++ SSLeay.xs (working copy) @@ -4127,6 +4127,23 @@ SSL_CTX * ctx RSA * rsa +#if OPENSSL_VERSION_NUMBER > 0x10000000L + +EC_KEY * +EC_KEY_new_by_curve_name(nid) + int nid + +void +EC_KEY_free(key) + EC_KEY * key + +long +SSL_CTX_set_tmp_ecdh(ctx,ecdh); + SSL_CTX * ctx + EC_KEY * ecdh + +#endif + void * SSL_get_app_data(s) SSL * s IO-Socket-SSL-1.965/docs/debugging.txt0000644000175100017520000000163411136164317016116 0ustar workwork - check that IO::Socket::SSL and Net::SSLeay are properly installed, and that the versions are recently new: perl -MIO::Socket::SSL -e 'print "$IO::Socket::SSL::VERSION\n"' perl -MNet::SSLeay -e 'print "$Net::SSLeay::VERSION\n"' - run the tests in IO::Socket::SSL directory try running the tests with 'make test'. if some of the tests fail run the scripts one by one e.g.: perl -Ilib t/core.t - try running the demos using the DEBUG option - use the OpenSSL client and server for debugging the demo client and server. 'openssl s_client' and 'openssl s_server' against tests/demos testing the demo server: openssl s_client -connect localhost:9000 \ -key certs/client-key.pem -cert certs/client-cert.pem -verify 1 testing the demo client: openssl s_server -accept 9000 \ -key certs/server-key.pem -cert certs/server-cert.pem -verify 1 also, try these commands without the verify argument. IO-Socket-SSL-1.965/README.Win320000644000175100017520000000042511136164317014250 0ustar workworkThe underlying IO::Socket::INET does not support non-blocking sockets on Win32, thus non-blocking IO::Socket::SSL is not supported on Win32, which means also, that timeouts don't work (because they are based on non-blocking). See also http://www.perlmonks.org/?node_id=378675 IO-Socket-SSL-1.965/MANIFEST0000644000175100017520000000201012265775222013617 0ustar workworkBUGS certs/client-cert.pem certs/client-key.enc certs/client-key.pem certs/my-ca.pem certs/proxyca.pem certs/server-cert.pem certs/server-key.enc certs/server-key.pem certs/server-rsa384-dh.pem certs/server-wildcard.pem certs/test-ca.pem Changes docs/debugging.txt docs/net-ssley-ecdh.patch example/async_https_server.pl example/lwp-with-verifycn.pl example/ssl_client.pl example/ssl_server.pl example/ssl_mitm.pl Makefile.PL MANIFEST README README.Win32 lib/IO/Socket/SSL.pm lib/IO/Socket/SSL/Intercept.pm lib/IO/Socket/SSL/Utils.pm t/01loadmodule.t t/acceptSSL-timeout.t t/auto_verify_hostname.t t/cert_no_file.t t/compatibility.t t/connectSSL-timeout.t t/core.t t/dhe.t t/io-socket-inet6.t t/io-socket-ip.t t/memleak_bad_handshake.t t/nonblock.t t/npn.t t/readline.t t/sessions.t t/signal-readline.t t/startssl-failed.t t/startssl.t t/start-stopssl.t t/sysread_write.t t/testlib.pl t/verify_hostname.t t/sni.t t/mitm.t t/ecdhe.t util/export_certs.pl META.yml Module meta-data (added by MakeMaker) IO-Socket-SSL-1.965/util/0000755000175100017520000000000012265775222013452 5ustar workworkIO-Socket-SSL-1.965/util/export_certs.pl0000644000175100017520000000244611136164317016527 0ustar workwork# # a script for exporting Netscape navigator's certificate database # (aspa@hip.fi). # # $Id: export_certs.pl,v 1.1 2000/08/08 06:37:56 aspa Exp $. # # additional information: # - http://www.drh-consultancy.demon.co.uk/cert7.html # - man xxd # # conversion from DER format: # /usr/local/ssl/bin/x509 -inform der -text < cert.der # use strict; my (%certhash, $key, $val); my $cert_db_path = $ENV{'HOME'} . "/.netscape/cert7"; my $rcnt = 0; print STDERR "opening '$cert_db_path'.\n"; if( ! dbmopen(%certhash, $cert_db_path, undef) ) { print STDERR "dbmopen failed: '$!'.\n"; } while ( ($key, $val) = each %certhash ) { my ($rec_type, $data, $klen, $vlen, $cert); $rcnt++; # get key info: [type] [data] ($rec_type, $data) = unpack("Ca*", $key); # get additional diagnostics info. $klen = length($key); $vlen = length($val); print STDERR "$rcnt: \t record type: '$rec_type'. key len: " . "'$klen, \t value len: '$vlen'.\n"; # check record type. if($rec_type != 1) { # not a certificate record. skip it. next; } # it is a certificate record. # certificates are stored in DER format starting at offset 13. $cert = substr($val, 13); # save cert in DER format. open(C_FILE, ">tmp/cert-$rcnt.der"); print C_FILE "$cert"; close(C_FILE); } dbmclose(%certhash); IO-Socket-SSL-1.965/lib/0000755000175100017520000000000012265775222013243 5ustar workworkIO-Socket-SSL-1.965/lib/IO/0000755000175100017520000000000012265775222013552 5ustar workworkIO-Socket-SSL-1.965/lib/IO/Socket/0000755000175100017520000000000012265775222015002 5ustar workworkIO-Socket-SSL-1.965/lib/IO/Socket/SSL.pm0000644000175100017520000033237512265774242016017 0ustar workwork# vim: set sts=4 sw=4 ts=8 ai: # # IO::Socket::SSL: # provide an interface to SSL connections similar to IO::Socket modules # # Current Code Shepherd: Steffen Ullrich # Code Shepherd before: Peter Behroozi, # # The original version of this module was written by # Marko Asplund, , who drew from # Crypt::SSLeay (Net::SSL) by Gisle Aas. # package IO::Socket::SSL; use IO::Socket; use Net::SSLeay 1.46; use Exporter (); use Errno qw( EAGAIN ETIMEDOUT ); use Carp; use strict; our $VERSION = '1.965'; use constant SSL_VERIFY_NONE => Net::SSLeay::VERIFY_NONE(); use constant SSL_VERIFY_PEER => Net::SSLeay::VERIFY_PEER(); use constant SSL_VERIFY_FAIL_IF_NO_PEER_CERT => Net::SSLeay::VERIFY_FAIL_IF_NO_PEER_CERT(); use constant SSL_VERIFY_CLIENT_ONCE => Net::SSLeay::VERIFY_CLIENT_ONCE(); # from openssl/ssl.h; should be better in Net::SSLeay use constant SSL_SENT_SHUTDOWN => 1; use constant SSL_RECEIVED_SHUTDOWN => 2; # capabilities of underlying Net::SSLeay/openssl my $can_client_sni; # do we support SNI on the client side my $can_server_sni; # do we support SNI on the server side my $can_npn; # do we support NPN my $can_ecdh; # do we support ECDH key exchange BEGIN { $can_client_sni = Net::SSLeay::OPENSSL_VERSION_NUMBER() >= 0x01000000; $can_server_sni = defined &Net::SSLeay::get_servername; $can_npn = defined &Net::SSLeay::P_next_proto_negotiated; $can_ecdh = defined &Net::SSLeay::CTX_set_tmp_ecdh; } # global defaults my %DEFAULT_SSL_ARGS = ( SSL_check_crl => 0, SSL_version => 'SSLv23:!SSLv2', SSL_verify_callback => undef, SSL_verifycn_scheme => undef, # don't verify cn SSL_verifycn_name => undef, # use from PeerAddr/PeerHost SSL_npn_protocols => undef, # meaning depends whether on server or client side SSL_cipher_list => 'EECDH+AESGCM+ECDSA EECDH+AESGCM EECDH+ECDSA +AES256 EECDH EDH+AESGCM '. 'EDH ALL +SHA +3DES +RC4 !LOW !EXP !eNULL !aNULL !DES !MD5 !PSK !SRP', ); my %DEFAULT_SSL_CLIENT_ARGS = ( %DEFAULT_SSL_ARGS, SSL_verify_mode => SSL_VERIFY_PEER, # older versions of F5 BIG-IP hang when getting SSL client hello >255 bytes # http://support.f5.com/kb/en-us/solutions/public/13000/000/sol13037.html # http://guest:guest@rt.openssl.org/Ticket/Display.html?id=2771 # Debian works around this by disabling TLSv1_2 on the client side # Chrome and IE11 use TLSv1_2 but use only a few ciphers, so that packet # stays small enough # The following list is taken from IE11, except that we don't do RC4-MD5, # RC4-SHA is already bad enough. Also, we have a different sort order # compared to IE11, because we put ciphers supporting forward secrecy on top SSL_cipher_list => join(" ", qw( ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-ECDSA-AES128-SHA256 ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-ECDSA-AES256-SHA384 ECDHE-ECDSA-AES128-SHA ECDHE-ECDSA-AES256-SHA ECDHE-RSA-AES128-SHA256 ECDHE-RSA-AES128-SHA ECDHE-RSA-AES256-SHA DHE-DSS-AES128-SHA256 DHE-DSS-AES128-SHA DHE-DSS-AES256-SHA256 DHE-DSS-AES256-SHA AES128-SHA256 AES128-SHA AES256-SHA256 AES256-SHA EDH-DSS-DES-CBC3-SHA DES-CBC3-SHA RC4-SHA ), # just to make sure, that we don't accidentely add bad ciphers above "!EXP !LOW !eNULL !aNULL !DES !MD5 !PSK !SRP" ) ); my %DEFAULT_SSL_SERVER_ARGS = ( %DEFAULT_SSL_ARGS, SSL_verify_mode => SSL_VERIFY_NONE, SSL_honor_cipher_order => 1, # trust server to know the best cipher SSL_dh => do { my $bio = Net::SSLeay::BIO_new(Net::SSLeay::BIO_s_mem()); # generated with: openssl dhparam 2048 Net::SSLeay::BIO_write($bio,<<'DH'); -----BEGIN DH PARAMETERS----- MIIBCAKCAQEAr8wskArj5+1VCVsnWt/RUR7tXkHJ7mGW7XxrLSPOaFyKyWf8lZht iSY2Lc4oa4Zw8wibGQ3faeQu/s8fvPq/aqTxYmyHPKCMoze77QJHtrYtJAosB9SY CN7s5Hexxb5/vQ4qlQuOkVrZDiZO9GC4KaH9mJYnCoAsXDhDft6JT0oRVSgtZQnU gWFKShIm+JVjN94kGs0TcBEesPTK2g8XVHK9H8AtSUb9BwW2qD/T5RmgNABysApO Ps2vlkxjAHjJcqc3O+OiImKik/X2rtBTZjpKmzN3WWTB0RJZCOWaLlDO81D01o1E aZecz3Np9KIYey900f+X7zC2bJxEHp95ywIBAg== -----END DH PARAMETERS----- DH my $dh = Net::SSLeay::PEM_read_bio_DHparams($bio); Net::SSLeay::BIO_free($bio); $dh or die "no DH"; $dh; }, $can_ecdh ? ( SSL_ecdh_curve => 'prime256v1' ):(), ); # global defaults which can be changed using set_defaults # either key/value can be set or it can just be set to an external hash my $GLOBAL_SSL_ARGS = {}; my $GLOBAL_SSL_CLIENT_ARGS = {}; my $GLOBAL_SSL_SERVER_ARGS = {}; # non-XS Versions of Scalar::Util will fail BEGIN{ local $SIG{__DIE__}; local $SIG{__WARN__}; # be silent eval { use Scalar::Util 'dualvar'; dualvar(0,'') }; die "You need the XS Version of Scalar::Util for dualvar() support" if $@; } # get constants for SSL_OP_NO_* now, instead calling the releated functions # everytime we setup a connection my %SSL_OP_NO; for(qw( SSLv2 SSLv3 TLSv1 TLSv1_1 TLSv11:TLSv1_1 TLSv1_2 TLSv1_2:TLSv1_2 )) { my ($k,$op) = m{:} ? split(m{:},$_,2) : ($_,$_); my $sub = "Net::SSLeay::OP_NO_$op"; $SSL_OP_NO{$k} = eval { no strict 'refs'; &$sub } || 0; } our $DEBUG; use vars qw(@ISA $SSL_ERROR @EXPORT ); { # These constants will be used in $! at return from SSL_connect, # SSL_accept, generic_read and write, thus notifying the caller # the usual way of problems. Like with EAGAIN, EINPROGRESS.. # these are especially important for non-blocking sockets my $x = Net::SSLeay::ERROR_WANT_READ(); use constant SSL_WANT_READ => dualvar( \$x, 'SSL wants a read first' ); my $y = Net::SSLeay::ERROR_WANT_WRITE(); use constant SSL_WANT_WRITE => dualvar( \$y, 'SSL wants a write first' ); @EXPORT = qw( SSL_WANT_READ SSL_WANT_WRITE SSL_VERIFY_NONE SSL_VERIFY_PEER SSL_VERIFY_FAIL_IF_NO_PEER_CERT SSL_VERIFY_CLIENT_ONCE $SSL_ERROR GEN_DNS GEN_IPADD ); } my @caller_force_inet4; # in case inet4 gets forced we store here who forced it BEGIN { # declare @ISA depending of the installed socket class # try to load inet_pton from Socket or Socket6 local $SIG{__DIE__}; local $SIG{__WARN__}; # be silent my $ip6 = eval { require Socket; Socket->VERSION(1.95); Socket->import( qw/inet_pton getnameinfo NI_NUMERICHOST NI_NUMERICSERV/ ); AF_INET6(); # >0 if defined in IO::Socket } || eval { require Socket6; Socket6->import( qw/inet_pton getnameinfo NI_NUMERICHOST NI_NUMERICSERV/ ); AF_INET6(); # >0 if defined in IO::Socket }; # try IO::Socket::IP or IO::Socket::INET6 for IPv6 support if ( $ip6 ) { # if we have IO::Socket::IP >= 0.20 we will use this in preference # because it can handle both IPv4 and IPv6 if ( eval { require IO::Socket::IP; IO::Socket::IP->VERSION(0.20); } ) { @ISA = qw(IO::Socket::IP); constant->import( CAN_IPV6 => "IO::Socket::IP" ); # if we have IO::Socket::INET6 we will use this not IO::Socket::INET # because it can handle both IPv4 and IPv6 # require at least 2.55 because of # https://rt.cpan.org/Ticket/Display.html?id=39550 } elsif( eval { require IO::Socket::INET6; IO::Socket::INET6->VERSION(2.55) } ) { @ISA = qw(IO::Socket::INET6); constant->import( CAN_IPV6 => "IO::Socket::INET6" ); } else { $ip6 = 0; } } # fall back to IO::Socket::INET for IPv4 only if ( ! $ip6 ) { @ISA = qw(IO::Socket::INET); constant->import( CAN_IPV6 => '' ); } #Make $DEBUG another name for $Net::SSLeay::trace *DEBUG = \$Net::SSLeay::trace; #Compability *ERROR = \$SSL_ERROR; # Do Net::SSLeay initialization Net::SSLeay::load_error_strings(); Net::SSLeay::SSLeay_add_ssl_algorithms(); Net::SSLeay::OpenSSL_add_all_digests(); Net::SSLeay::randomize(); } sub DEBUG { $DEBUG or return; my (undef,$file,$line) = caller; my $msg = shift; $file = '...'.substr( $file,-17 ) if length($file)>20; $msg = sprintf $msg,@_ if @_; print STDERR "DEBUG: $file:$line: $msg\n"; } BEGIN { # import some constants from Net::SSLeay or use hard-coded defaults # if Net::SSLeay isn't recent enough to provide the constants my %const = ( NID_CommonName => 13, GEN_DNS => 2, GEN_IPADD => 7, ); while ( my ($name,$value) = each %const ) { no strict 'refs'; *{$name} = UNIVERSAL::can( 'Net::SSLeay', $name ) || sub { $value }; } # check if we have something to handle IDN local $SIG{__DIE__}; local $SIG{__WARN__}; # be silent if ( eval { require Net::IDN::Encode }) { *{idn_to_ascii} = \&Net::IDN::Encode::domain_to_ascii; } elsif ( eval { require Net::LibIDN }) { *{idn_to_ascii} = \&Net::LibIDN::idn_to_ascii; } elsif ( eval { require URI; URI->VERSION(1.50) }) { *{idn_to_ascii} = sub { URI->new("http://" . shift)->host } } else { # default: croak if we really got an unencoded international domain *{idn_to_ascii} = sub { my $domain = shift; return $domain if $domain =~m{^[a-zA-Z0-9-_\.]+$}; croak "cannot handle international domains, please install Net::LibIDN, Net::IDN::Encode or URI" } } } # Export some stuff # inet4|inet6|debug will be handled by myself, everything # else will be handled the Exporter way sub import { my $class = shift; my @export; foreach (@_) { if ( /^inet4$/i ) { # explicitly fall back to inet4 @ISA = 'IO::Socket::INET'; @caller_force_inet4 = caller(); # save for warnings for 'inet6' case } elsif ( /^inet6$/i ) { # check if we have already ipv6 as base if ( ! UNIVERSAL::isa( $class, 'IO::Socket::INET6') and ! UNIVERSAL::isa( $class, 'IO::Socket::IP' )) { # either we don't support it or we disabled it by explicitly # loading it with 'inet4'. In this case re-enable but warn # because this is probably an error if ( CAN_IPV6 ) { @ISA = ( CAN_IPV6 ); warn "IPv6 support re-enabled in __PACKAGE__, got disabled in file $caller_force_inet4[1] line $caller_force_inet4[2]"; } else { die "INET6 is not supported, install IO::Socket::INET6"; } } } elsif ( /^:?debug(\d+)/ ) { $DEBUG=$1; } else { push @export,$_ } } @_ = ( $class,@export ); goto &Exporter::import; } my %CREATED_IN_THIS_THREAD; sub CLONE { %CREATED_IN_THIS_THREAD = (); } # You might be expecting to find a new() subroutine here, but that is # not how IO::Socket::INET works. All configuration gets performed in # the calls to configure() and either connect() or accept(). #Call to configure occurs when a new socket is made using #IO::Socket::INET. Returns false (empty list) on failure. sub configure { my ($self, $arg_hash) = @_; return _invalid_object() unless($self); # force initial blocking # otherwise IO::Socket::SSL->new might return undef if the # socket is nonblocking and it fails to connect immediately # for real nonblocking behavior one should create a nonblocking # socket and later call connect explicitly my $blocking = delete $arg_hash->{Blocking}; # because Net::HTTPS simple redefines blocking() to {} (e.g # return undef) and IO::Socket::INET does not like this we # set Blocking only explicitly if it was set $arg_hash->{Blocking} = 1 if defined ($blocking); $self->configure_SSL($arg_hash) || return; $self->SUPER::configure($arg_hash) || return $self->error("@ISA configuration failed"); $self->blocking(0) if defined $blocking && !$blocking; return $self; } sub configure_SSL { my ($self, $arg_hash) = @_; $arg_hash->{Proto} ||= 'tcp'; my $is_server = $arg_hash->{SSL_server}; if ( ! defined $is_server ) { $is_server = $arg_hash->{SSL_server} = $arg_hash->{Listen} || 0; } # add user defined defaults %$arg_hash = ( %$GLOBAL_SSL_ARGS, $is_server ? %$GLOBAL_SSL_SERVER_ARGS : %$GLOBAL_SSL_CLIENT_ARGS, %$arg_hash ); my $ctx = $arg_hash->{'SSL_reuse_ctx'}; if ($ctx) { if ($ctx->isa('IO::Socket::SSL::SSL_Context') and $ctx->{context}) { # valid context } elsif ( $ctx = ${*$ctx}{_SSL_ctx} ) { # reuse context from existing SSL object } } # create context # this will fill in defaults in $arg_hash $ctx ||= IO::Socket::SSL::SSL_Context->new($arg_hash); ${*$self}{'_SSL_arguments'} = $arg_hash; ${*$self}{'_SSL_ctx'} = $ctx; ${*$self}{'_SSL_opened'} = 1 if $is_server; return $self; } sub _set_rw_error { my ($self,$ssl,$rv) = @_; my $err = Net::SSLeay::get_error($ssl,$rv); $SSL_ERROR = $err == Net::SSLeay::ERROR_WANT_READ() ? SSL_WANT_READ : $err == Net::SSLeay::ERROR_WANT_WRITE() ? SSL_WANT_WRITE : return; $! ||= EAGAIN; ${*$self}{'_SSL_last_err'} = $SSL_ERROR if ref($self); return 1; } #Call to connect occurs when a new client socket is made using #IO::Socket::INET sub connect { my $self = shift || return _invalid_object(); return $self if ${*$self}{'_SSL_opened'}; # already connected if ( ! ${*$self}{'_SSL_opening'} ) { # call SUPER::connect if the underlying socket is not connected # if this fails this might not be an error (e.g. if $! = EINPROGRESS # and socket is nonblocking this is normal), so keep any error # handling to the client $DEBUG>=2 && DEBUG('socket not yet connected' ); $self->SUPER::connect(@_) || return; $DEBUG>=2 && DEBUG('socket connected' ); # IO::Socket works around systems, which return EISCONN or similar # on non-blocking re-connect by returning true, even if $! is set # but it does not clear $!, so do it here $! = undef; } return $self->connect_SSL; } sub connect_SSL { my $self = shift; my $args = @_>1 ? {@_}: $_[0]||{}; my ($ssl,$ctx); if ( ! ${*$self}{'_SSL_opening'} ) { # start ssl connection $DEBUG>=2 && DEBUG('ssl handshake not started' ); ${*$self}{'_SSL_opening'} = 1; my $arg_hash = ${*$self}{'_SSL_arguments'}; my $fileno = ${*$self}{'_SSL_fileno'} = fileno($self); return $self->error("Socket has no fileno") unless (defined $fileno); $ctx = ${*$self}{'_SSL_ctx'}; # Reference to real context $ssl = ${*$self}{'_SSL_object'} = Net::SSLeay::new($ctx->{context}) || return $self->error("SSL structure creation failed"); $CREATED_IN_THIS_THREAD{$ssl} = 1; Net::SSLeay::set_fd($ssl, $fileno) || return $self->error("SSL filehandle association failed"); if ( $can_client_sni ) { my $host; if ( exists $arg_hash->{SSL_hostname} ) { # explicitly given # can be set to undef/'' to not use extension $host = $arg_hash->{SSL_hostname} } elsif ( $host = $arg_hash->{PeerAddr} || $arg_hash->{PeerHost} ) { # implicitly given $host =~s{:[a-zA-Z0-9_\-]+$}{}; # should be hostname, not IPv4/6 $host = undef if $host !~m{[a-z_]} or $host =~m{:}; } # define SSL_CTRL_SET_TLSEXT_HOSTNAME 55 # define TLSEXT_NAMETYPE_host_name 0 if ($host) { $DEBUG>=2 && DEBUG("using SNI with hostname $host"); Net::SSLeay::ctrl($ssl,55,0,$host); } else { $DEBUG>=2 && DEBUG("not using SNI because hostname is unknown"); } } elsif ( $arg_hash->{SSL_hostname} ) { return $self->error( "Client side SNI not supported for this openssl"); } else { $DEBUG>=2 && DEBUG("not using SNI because openssl is too old"); } $arg_hash->{PeerAddr} || $self->_update_peer; my $session = $ctx->session_cache( $arg_hash->{SSL_session_key} ? ( $arg_hash->{SSL_session_key},1 ) : ( $arg_hash->{PeerAddr}, $arg_hash->{PeerPort} ) ); Net::SSLeay::set_session($ssl, $session) if ($session); } $ssl ||= ${*$self}{'_SSL_object'}; $SSL_ERROR = undef; my $timeout = exists $args->{Timeout} ? $args->{Timeout} : ${*$self}{io_socket_timeout}; # from IO::Socket if ( defined($timeout) && $timeout>0 && $self->blocking(0) ) { $DEBUG>=2 && DEBUG( "set socket to non-blocking to enforce timeout=$timeout" ); # timeout was given and socket was blocking # enforce timeout with now non-blocking socket } else { # timeout does not apply because invalid or socket non-blocking $timeout = undef; } my $start = defined($timeout) && time(); for my $dummy (1) { #DEBUG( 'calling ssleay::connect' ); my $rv = Net::SSLeay::connect($ssl); $DEBUG>=3 && DEBUG("Net::SSLeay::connect -> $rv" ); if ( $rv < 0 ) { unless ( $self->_set_rw_error( $ssl,$rv )) { $self->error("SSL connect attempt failed with unknown error"); delete ${*$self}{'_SSL_opening'}; ${*$self}{'_SSL_opened'} = -1; $DEBUG>=1 && DEBUG( "fatal SSL error: $SSL_ERROR" ); return $self->fatal_ssl_error(); } $DEBUG>=2 && DEBUG('ssl handshake in progress' ); # connect failed because handshake needs to be completed # if socket was non-blocking or no timeout was given return with this error return if ! defined($timeout); # wait until socket is readable or writable my $rv; if ( $timeout>0 ) { my $vec = ''; vec($vec,$self->fileno,1) = 1; $DEBUG>=2 && DEBUG( "waiting for fd to become ready: $SSL_ERROR" ); $rv = $SSL_ERROR == SSL_WANT_READ ? select( $vec,undef,undef,$timeout) : $SSL_ERROR == SSL_WANT_WRITE ? select( undef,$vec,undef,$timeout) : undef; } else { $DEBUG>=2 && DEBUG("handshake failed because no more time" ); $! = ETIMEDOUT } if ( ! $rv ) { $DEBUG>=2 && DEBUG("handshake failed because socket did not became ready" ); # failed because of timeout, return $! ||= ETIMEDOUT; delete ${*$self}{'_SSL_opening'}; ${*$self}{'_SSL_opened'} = -1; $self->blocking(1); # was blocking before return } # socket is ready, try non-blocking connect again after recomputing timeout $DEBUG>=2 && DEBUG("socket ready, retrying connect" ); my $now = time(); $timeout -= $now - $start; $start = $now; redo; } elsif ( $rv == 0 ) { delete ${*$self}{'_SSL_opening'}; $DEBUG>=2 && DEBUG("connection failed - connect returned 0" ); $self->error("SSL connect attempt failed because of handshake problems" ); ${*$self}{'_SSL_opened'} = -1; return $self->fatal_ssl_error(); } } $DEBUG>=2 && DEBUG('ssl handshake done' ); # ssl connect successful delete ${*$self}{'_SSL_opening'}; ${*$self}{'_SSL_opened'}=1; $self->blocking(1) if defined($timeout); # was blocking before $ctx ||= ${*$self}{'_SSL_ctx'}; if ( $ctx->has_session_cache and my $session = Net::SSLeay::get1_session($ssl)) { my $arg_hash = ${*$self}{'_SSL_arguments'}; $arg_hash->{PeerAddr} || $self->_update_peer; $ctx->session_cache( $arg_hash->{SSL_session_key} ? ( $arg_hash->{SSL_session_key},1 ) : ( $arg_hash->{PeerAddr},$arg_hash->{PeerPort} ), $session ); } tie *{$self}, "IO::Socket::SSL::SSL_HANDLE", $self; return $self; } # called if PeerAddr is not set in ${*$self}{'_SSL_arguments'} # this can be the case if start_SSL is called with a normal IO::Socket::INET # so that PeerAddr|PeerPort are not set from args sub _update_peer { my $self = shift; my $arg_hash = ${*$self}{'_SSL_arguments'}; eval { my $sockaddr = getpeername( $self ); my $af = sockaddr_family($sockaddr); if( CAN_IPV6 && $af == AF_INET6 ) { my ($host, $port) = getnameinfo($sockaddr, NI_NUMERICHOST | NI_NUMERICSERV); $arg_hash->{PeerAddr} = $host; $arg_hash->{PeerPort} = $port; } else { my ($port,$addr) = sockaddr_in( $sockaddr); $arg_hash->{PeerAddr} = inet_ntoa( $addr ); $arg_hash->{PeerPort} = $port; } } } #Call to accept occurs when a new client connects to a server using #IO::Socket::SSL sub accept { my $self = shift || return _invalid_object(); my $class = shift || 'IO::Socket::SSL'; my $socket = ${*$self}{'_SSL_opening'}; if ( ! $socket ) { # underlying socket not done $DEBUG>=2 && DEBUG('no socket yet' ); $socket = $self->SUPER::accept($class) || return; $DEBUG>=2 && DEBUG('accept created normal socket '.$socket ); } $self->accept_SSL($socket) || return; $DEBUG>=2 && DEBUG('accept_SSL ok' ); return wantarray ? ($socket, getpeername($socket) ) : $socket; } sub accept_SSL { my $self = shift; my $socket = ( @_ && UNIVERSAL::isa( $_[0], 'IO::Handle' )) ? shift : $self; my $args = @_>1 ? {@_}: $_[0]||{}; my $ssl; if ( ! ${*$self}{'_SSL_opening'} ) { $DEBUG>=2 && DEBUG('starting sslifying' ); ${*$self}{'_SSL_opening'} = $socket; my $arg_hash = ${*$self}{'_SSL_arguments'}; ${*$socket}{'_SSL_arguments'} = { %$arg_hash, SSL_server => 0 }; my $ctx = ${*$socket}{'_SSL_ctx'} = ${*$self}{'_SSL_ctx'}; my $fileno = ${*$socket}{'_SSL_fileno'} = fileno($socket); return $socket->error("Socket has no fileno") unless (defined $fileno); $ssl = ${*$socket}{'_SSL_object'} = Net::SSLeay::new($ctx->{context}) || return $socket->error("SSL structure creation failed"); $CREATED_IN_THIS_THREAD{$ssl} = 1; Net::SSLeay::set_fd($ssl, $fileno) || return $socket->error("SSL filehandle association failed"); } $ssl ||= ${*$socket}{'_SSL_object'}; $SSL_ERROR = undef; #$DEBUG>=2 && DEBUG('calling ssleay::accept' ); my $timeout = exists $args->{Timeout} ? $args->{Timeout} : ${*$self}{io_socket_timeout}; # from IO::Socket if ( defined($timeout) && $timeout>0 && $socket->blocking(0) ) { # timeout was given and socket was blocking # enforce timeout with now non-blocking socket } else { # timeout does not apply because invalid or socket non-blocking $timeout = undef; } my $start = defined($timeout) && time(); for my $dummy (1) { my $rv = Net::SSLeay::accept($ssl); $DEBUG>=3 && DEBUG( "Net::SSLeay::accept -> $rv" ); if ( $rv < 0 ) { unless ( $socket->_set_rw_error( $ssl,$rv )) { $socket->error("SSL accept attempt failed with unknown error"); delete ${*$self}{'_SSL_opening'}; ${*$socket}{'_SSL_opened'} = -1; return $socket->fatal_ssl_error(); } # accept failed because handshake needs to be completed # if socket was non-blocking or no timeout was given return with this error return if ! defined($timeout); # wait until socket is readable or writable my $rv; if ( $timeout>0 ) { my $vec = ''; vec($vec,$socket->fileno,1) = 1; $rv = $SSL_ERROR == SSL_WANT_READ ? select( $vec,undef,undef,$timeout) : $SSL_ERROR == SSL_WANT_WRITE ? select( undef,$vec,undef,$timeout) : undef; } else { $! = ETIMEDOUT } if ( ! $rv ) { # failed because of timeout, return $! ||= ETIMEDOUT; delete ${*$self}{'_SSL_opening'}; ${*$socket}{'_SSL_opened'} = -1; $socket->blocking(1); # was blocking before return } # socket is ready, try non-blocking accept again after recomputing timeout my $now = time(); $timeout -= $now - $start; $start = $now; redo; } elsif ( $rv == 0 ) { $socket->error("SSL connect accept failed because of handshake problems" ); delete ${*$self}{'_SSL_opening'}; ${*$socket}{'_SSL_opened'} = -1; return $socket->fatal_ssl_error(); } } $DEBUG>=2 && DEBUG('handshake done, socket ready' ); # socket opened delete ${*$self}{'_SSL_opening'}; ${*$socket}{'_SSL_opened'} = 1; $socket->blocking(1) if defined($timeout); # was blocking before tie *{$socket}, "IO::Socket::SSL::SSL_HANDLE", $socket; return $socket; } ####### I/O subroutines ######################## sub generic_read { my ($self, $read_func, undef, $length, $offset) = @_; my $ssl = $self->_get_ssl_object || return; my $buffer=\$_[2]; $SSL_ERROR = undef; my $data = $read_func->($ssl, $length); if ( !defined($data)) { $self->_set_rw_error( $ssl,-1 ) || $self->error("SSL read error"); return; } $length = length($data); $$buffer = '' if !defined $$buffer; $offset ||= 0; if ($offset>length($$buffer)) { $$buffer.="\0" x ($offset-length($$buffer)); #mimic behavior of read } substr($$buffer, $offset, length($$buffer), $data); return $length; } sub read { my $self = shift; return $self->generic_read( $self->blocking ? \&Net::SSLeay::ssl_read_all : \&Net::SSLeay::read, @_ ); } # contrary to the behavior of read sysread can read partial data sub sysread { my $self = shift; return $self->generic_read( \&Net::SSLeay::read, @_ ); } sub peek { my $self = shift; return $self->generic_read(\&Net::SSLeay::peek, @_); } sub generic_write { my ($self, $write_all, undef, $length, $offset) = @_; my $ssl = $self->_get_ssl_object || return; my $buffer = \$_[2]; my $buf_len = length($$buffer); $length ||= $buf_len; $offset ||= 0; return $self->error("Invalid offset for SSL write") if ($offset>$buf_len); return 0 if ($offset == $buf_len); $SSL_ERROR = undef; my $written; if ( $write_all ) { my $data = $length < $buf_len-$offset ? substr($$buffer, $offset, $length) : $$buffer; ($written, my $errs) = Net::SSLeay::ssl_write_all($ssl, $data); # ssl_write_all returns number of bytes written $written = undef if ! $written && $errs; } else { $written = Net::SSLeay::write_partial( $ssl,$offset,$length,$$buffer ); # write_partial does SSL_write which returns -1 on error $written = undef if $written < 0; } if ( !defined($written) ) { $self->_set_rw_error( $ssl,-1 ) || $self->error("SSL write error"); return; } return $written; } # if socket is blocking write() should return only on error or # if all data are written sub write { my $self = shift; return $self->generic_write( scalar($self->blocking),@_ ); } # contrary to write syswrite() returns already if only # a part of the data is written sub syswrite { my $self = shift; return $self->generic_write( 0,@_ ); } sub print { my $self = shift; my $string = join(($, or ''), @_, ($\ or '')); return $self->write( $string ); } sub printf { my ($self,$format) = (shift,shift); return $self->write(sprintf($format, @_)); } sub getc { my ($self, $buffer) = (shift, undef); return $buffer if $self->read($buffer, 1, 0); } sub readline { my $self = shift; if ( not defined $/ or wantarray) { # read all and split my $buf = ''; while (1) { my $rv = $self->sysread($buf,2**16,length($buf)); if ( ! defined $rv ) { next if $!{EINTR}; # retry last if $!{EAGAIN} || $!{EWOULDBLOCK}; # use everything so far return; # return error } elsif ( ! $rv ) { last } } if ( ! defined $/ ) { return $buf } elsif ( ref($/)) { my $size = ${$/}; die "bad value in ref \$/: $size" unless $size>0; return $buf=~m{\G(.{1,$size})}g; } elsif ( $/ eq '' ) { return $buf =~m{\G(.*\n\n+|.+)}g; } else { return $buf =~m{\G(.*$/|.+)}g; } } # read only one line if ( ref($/) ) { my $size = ${$/}; # read record of $size bytes die "bad value in ref \$/: $size" unless $size>0; my $buf = ''; while ( $size>length($buf)) { my $rv = $self->sysread($buf,$size-length($buf),length($buf)); if ( ! defined $rv ) { next if $!{EINTR}; # retry last if $!{EAGAIN} || $!{EWOULDBLOCK}; # use everything so far return; # return error } elsif ( ! $rv ) { last } } return $buf; } my ($delim0,$delim1) = $/ eq '' ? ("\n\n","\n"):($/,''); # find first occurrence of $delim0 followed by as much as possible $delim1 my $buf = ''; my $eod = 0; # pointer into $buf after $delim0 $delim1* my $ssl = $self->_get_ssl_object or return; while (1) { # wait until we have more data or eof my $poke = Net::SSLeay::peek($ssl,1); if ( ! defined $poke or $poke eq '' ) { next if $!{EINTR}; } my $skip = 0; # peek into available data w/o reading my $pending = Net::SSLeay::pending($ssl); if ( $pending and ( my $pb = Net::SSLeay::peek( $ssl,$pending )) ne '' ) { $buf .= $pb } else { return $buf eq '' ? ():$buf; }; if ( !$eod ) { my $pos = index( $buf,$delim0 ); if ( $pos<0 ) { $skip = $pending } else { $eod = $pos + length($delim0); # pos after delim0 } } if ( $eod ) { if ( $delim1 ne '' ) { # delim0 found, check for as much delim1 as possible while ( index( $buf,$delim1,$eod ) == $eod ) { $eod+= length($delim1); } } $skip = $pending - ( length($buf) - $eod ); } # remove data from $self which I already have in buf while ( $skip>0 ) { if ($self->sysread(my $p,$skip,0)) { $skip -= length($p); next; } $!{EINTR} or last; } if ( $eod and ( $delim1 eq '' or $eod < length($buf))) { # delim0 found and there can be no more delim1 pending last } } return substr($buf,0,$eod); } sub close { my $self = shift || return _invalid_object(); my $close_args = (ref($_[0]) eq 'HASH') ? $_[0] : {@_}; return if ! $self->stop_SSL( SSL_fast_shutdown => 1, %$close_args, _SSL_ioclass_downgrade => 0, ); if ( ! $close_args->{_SSL_in_DESTROY} ) { untie( *$self ); undef ${*$self}{_SSL_fileno}; return $self->SUPER::close; } return 1; } sub stop_SSL { my $self = shift || return _invalid_object(); my $stop_args = (ref($_[0]) eq 'HASH') ? $_[0] : {@_}; $stop_args->{SSL_no_shutdown} = 1 if ! ${*$self}{_SSL_opened}; if (my $ssl = ${*$self}{'_SSL_object'}) { if ( ! $stop_args->{SSL_no_shutdown} ) { my $status = Net::SSLeay::get_shutdown($ssl); while (1) { if ( $status & SSL_SENT_SHUTDOWN and # don't care for received if fast shutdown $status & SSL_RECEIVED_SHUTDOWN || $stop_args->{SSL_fast_shutdown}) { # shutdown complete last; } # initiate or complete shutdown local $SIG{PIPE} = 'IGNORE'; my $rv = Net::SSLeay::shutdown($ssl); if ( $rv < 0 ) { # non-blocking socket? $self->_set_rw_error( $ssl,$rv ); # need to try again return; } $status |= SSL_SENT_SHUTDOWN; $status |= SSL_RECEIVED_SHUTDOWN if $rv>0; } } Net::SSLeay::free($ssl); delete ${*$self}{_SSL_object}; } if ($stop_args->{'SSL_ctx_free'}) { my $ctx = delete ${*$self}{'_SSL_ctx'}; $ctx && $ctx->DESTROY(); } if (my $cert = delete ${*$self}{'_SSL_certificate'}) { Net::SSLeay::X509_free($cert); } ${*$self}{'_SSL_opened'} = 0; if ( ! $stop_args->{_SSL_in_DESTROY} ) { my $downgrade = $stop_args->{_SSL_ioclass_downgrade}; if ( $downgrade || ! defined $downgrade ) { # rebless to original class from start_SSL if ( my $orig_class = delete ${*$self}{'_SSL_ioclass_upgraded'} ) { bless $self,$orig_class; untie(*$self); # FIXME: if original class was tied too we need to restore the tie } # remove all _SSL related from *$self my @sslkeys = grep { m{^_?SSL_} } keys %{*$self}; delete @{*$self}{@sslkeys} if @sslkeys; } } return 1; } sub fileno { my $self = shift; my $fn = ${*$self}{'_SSL_fileno'}; return defined($fn) ? $fn : $self->SUPER::fileno(); } ####### IO::Socket::SSL specific functions ####### # _get_ssl_object is for internal use ONLY! sub _get_ssl_object { my $self = shift; my $ssl = ${*$self}{'_SSL_object'}; return IO::Socket::SSL->error("Undefined SSL object") unless($ssl); return $ssl; } # _get_ctx_object is for internal use ONLY! sub _get_ctx_object { my $self = shift; my $ctx_object = ${*$self}{_SSL_ctx}; return $ctx_object && $ctx_object->{context}; } # default error for undefined arguments sub _invalid_object { return IO::Socket::SSL->error("Undefined IO::Socket::SSL object"); } sub pending { my $ssl = shift()->_get_ssl_object || return; return Net::SSLeay::pending($ssl); } sub start_SSL { my ($class,$socket) = (shift,shift); return $class->error("Not a socket") unless(ref($socket)); my $arg_hash = (ref($_[0]) eq 'HASH') ? $_[0] : {@_}; my %to = exists $arg_hash->{Timeout} ? ( Timeout => delete $arg_hash->{Timeout} ) :(); my $original_class = ref($socket); my $original_fileno = (UNIVERSAL::can($socket, "fileno")) ? $socket->fileno : CORE::fileno($socket); return $class->error("Socket has no fileno") unless defined $original_fileno; bless $socket, $class; $socket->configure_SSL($arg_hash) or bless($socket, $original_class) && return; ${*$socket}{'_SSL_fileno'} = $original_fileno; ${*$socket}{'_SSL_ioclass_upgraded'} = $original_class; my $start_handshake = $arg_hash->{SSL_startHandshake}; if ( ! defined($start_handshake) || $start_handshake ) { # if we have no callback force blocking mode $DEBUG>=2 && DEBUG( "start handshake" ); my $was_blocking = $socket->blocking(1); my $result = ${*$socket}{'_SSL_arguments'}{SSL_server} ? $socket->accept_SSL(%to) : $socket->connect_SSL(%to); if ( $result ) { $socket->blocking(0) if ! $was_blocking; return $socket; } else { # upgrade to SSL failed, downgrade socket to original class if ( $original_class ) { bless($socket,$original_class); $socket->blocking(0) if ! $was_blocking && $socket->can('blocking'); } return; } } else { $DEBUG>=2 && DEBUG( "dont start handshake: $socket" ); return $socket; # just return upgraded socket } } sub new_from_fd { my ($class, $fd) = (shift,shift); # Check for accidental inclusion of MODE in the argument list if (length($_[0]) < 4) { (my $mode = $_[0]) =~ tr/+<>//d; shift unless length($mode); } my $handle = $ISA[0]->new_from_fd($fd, '+<') || return($class->error("Could not create socket from file descriptor.")); # Annoying workaround for Perl 5.6.1 and below: $handle = $ISA[0]->new_from_fd($handle, '+<'); return $class->start_SSL($handle, @_); } sub dump_peer_certificate { my $ssl = shift()->_get_ssl_object || return; return Net::SSLeay::dump_peer_certificate($ssl); } { my %dispatcher = ( issuer => sub { Net::SSLeay::X509_NAME_oneline( Net::SSLeay::X509_get_issuer_name( shift )) }, subject => sub { Net::SSLeay::X509_NAME_oneline( Net::SSLeay::X509_get_subject_name( shift )) }, commonName => sub { my $cn = Net::SSLeay::X509_NAME_get_text_by_NID( Net::SSLeay::X509_get_subject_name( shift ), NID_CommonName); $cn; }, subjectAltNames => sub { Net::SSLeay::X509_get_subjectAltNames( shift ) }, ); # alternative names $dispatcher{authority} = $dispatcher{issuer}; $dispatcher{owner} = $dispatcher{subject}; $dispatcher{cn} = $dispatcher{commonName}; sub peer_certificate { my ($self, $field) = @_; my $ssl = $self->_get_ssl_object or return; my $cert = ${*$self}{_SSL_certificate} ||= Net::SSLeay::get_peer_certificate($ssl) or return $self->error("Could not retrieve peer certificate"); if ($field) { my $sub = $dispatcher{$field} or croak "invalid argument for peer_certificate, valid are: ".join( " ",keys %dispatcher ). "\nMaybe you need to upgrade your Net::SSLeay"; return $sub->($cert); } else { return $cert } } # known schemes, possible attributes are: # - wildcards_in_alt (0, 'leftmost', 'anywhere') # - wildcards_in_cn (0, 'leftmost', 'anywhere') # - check_cn (0, 'always', 'when_only') # unfortunatly there are a lot of different schemes used, see RFC 6125 for a # summary, which references all of the following except RFC4217/ftp my %scheme = ( none => {}, # do not check ); for(qw( rfc2818 http www rfc3920 xmpp rfc4217 ftp )) { $scheme{$_} = { wildcards_in_cn => 'anywhere', wildcards_in_alt => 'anywhere', check_cn => 'when_only', } } for(qw( rfc4513 ldap )) { $scheme{$_} = { wildcards_in_cn => 0, wildcards_in_alt => 'leftmost', check_cn => 'always', }; } for(qw( rfc2595 smtp rfc4642 imap pop3 acap rfc5539 nntp rfc5538 netconf rfc5425 syslog rfc5953 snmp )) { $scheme{$_} = { wildcards_in_cn => 'leftmost', wildcards_in_alt => 'leftmost', check_cn => 'always' }; } for(qw( rfc5971 gist )) { $scheme{$_} = { wildcards_in_cn => 'leftmost', wildcards_in_alt => 'leftmost', check_cn => 'when_only', }; } for(qw( rfc5922 sip )) { $scheme{$_} = { wildcards_in_cn => 0, wildcards_in_alt => 0, check_cn => 'always', }; } # function to verify the hostname # # as every application protocol has its own rules to do this # we provide some default rules as well as a user-defined # callback sub verify_hostname_of_cert { my $identity = shift; my $cert = shift; my $scheme = shift || 'none'; if ( ! ref($scheme) ) { $DEBUG>=3 && DEBUG( "scheme=$scheme cert=$cert" ); $scheme = $scheme{$scheme} or croak "scheme $scheme not defined"; } return 1 if ! %$scheme; # 'none' # get data from certificate my $commonName = $dispatcher{cn}->($cert); my @altNames = $dispatcher{subjectAltNames}->($cert); $DEBUG>=3 && DEBUG("identity=$identity cn=$commonName alt=@altNames" ); if ( my $sub = $scheme->{callback} ) { # use custom callback return $sub->($identity,$commonName,@altNames); } # is the given hostname an IP address? Then we have to convert to network byte order [RFC791][RFC2460] my $ipn; if ( CAN_IPV6 and $identity =~m{:} ) { # no IPv4 or hostname have ':' in it, try IPv6. $ipn = inet_pton(AF_INET6,$identity) or croak "'$identity' is not IPv6, but neither IPv4 nor hostname"; } elsif ( $identity =~m{^\d+\.\d+\.\d+\.\d+$} ) { # definitely no hostname, try IPv4 $ipn = inet_aton( $identity ) or croak "'$identity' is not IPv4, but neither IPv6 nor hostname"; } else { # assume hostname, check for umlauts etc if ( $identity =~m{[^a-zA-Z0-9_.\-]} ) { $identity =~m{\0} and croak("name '$identity' has \\0 byte"); $identity = idn_to_ascii($identity) or croak "Warning: Given name '$identity' could not be converted to IDNA!"; } } # do the actual verification my $check_name = sub { my ($name,$identity,$wtyp) = @_; $wtyp ||= ''; my $pattern; ### IMPORTANT! # We accept only a single wildcard and only for a single part of the FQDN # e.g *.example.org does match www.example.org but not bla.www.example.org # The RFCs are in this regard unspecific but we don't want to have to # deal with certificates like *.com, *.co.uk or even * # see also http://nils.toedtmann.net/pub/subjectAltName.txt . # Also, we fall back to leftmost matches if the identity is an IDNA # name, see RFC6125 and the discussion at # http://bugs.python.org/issue17997#msg194950 if ( $wtyp eq 'anywhere' and $name =~m{^([a-zA-Z0-9_\-]*)\*(.+)} ) { return if $1 ne '' and substr($identity,0,4) eq 'xn--'; # IDNA $pattern = qr{^\Q$1\E[a-zA-Z0-9_\-]+\Q$2\E$}i; } elsif ( $wtyp eq 'leftmost' and $name =~m{^\*(\..+)$} ) { $pattern = qr{^[a-zA-Z0-9_\-]+\Q$1\E$}i; } else { $pattern = qr{^\Q$name\E$}i; } return $identity =~ $pattern; }; my $alt_dnsNames = 0; while (@altNames) { my ($type, $name) = splice (@altNames, 0, 2); if ( $ipn and $type == GEN_IPADD ) { # exact match needed for IP # $name is already packed format (inet_xton) return 1 if $ipn eq $name; } elsif ( ! $ipn and $type == GEN_DNS ) { $name =~s/\s+$//; $name =~s/^\s+//; $alt_dnsNames++; $check_name->($name,$identity,$scheme->{wildcards_in_alt}) and return 1; } } if ( ! $ipn and ( $scheme->{check_cn} eq 'always' or $scheme->{check_cn} eq 'when_only' and !$alt_dnsNames)) { $check_name->($commonName,$identity,$scheme->{wildcards_in_cn}) and return 1; } return 0; # no match } } sub verify_hostname { my $self = shift; my $host = shift; my $cert = $self->peer_certificate; return verify_hostname_of_cert( $host,$cert,@_ ); } sub get_servername { my $self = shift; return ${*$self}{_SSL_servername} ||= do { my $ssl = $self->_get_ssl_object or return; Net::SSLeay::get_servername($ssl); }; } sub get_cipher { my $ssl = shift()->_get_ssl_object || return; return Net::SSLeay::get_cipher($ssl); } sub get_sslversion { my $ssl = shift()->_get_ssl_object || return; my $version = Net::SSLeay::version($ssl) or return; return $version == 0x0303 ? 'TLSv1_2' : $version == 0x0302 ? 'TLSv1_1' : $version == 0x0301 ? 'TLSv1' : $version == 0x0300 ? 'SSLv3' : $version == 0x0002 ? 'SSLv2' : $version == 0xfeff ? 'DTLS1' : undef; } sub get_sslversion_int { my $ssl = shift()->_get_ssl_object || return; return Net::SSLeay::version($ssl); } sub errstr { my $self = shift; return (ref($self) ? ${*$self}{'_SSL_last_err'} : $SSL_ERROR) || ''; } sub fatal_ssl_error { my $self = shift; my $error_trap = ${*$self}{'_SSL_arguments'}->{'SSL_error_trap'}; $@ = $self->errstr; if (defined $error_trap and ref($error_trap) eq 'CODE') { $error_trap->($self, $self->errstr()."\n".$self->get_ssleay_error()); } elsif ( ${*$self}{'_SSL_ioclass_upgraded'} ) { # downgrade only $self->stop_SSL; } else { # kill socket $self->close } return; } sub get_ssleay_error { #Net::SSLeay will print out the errors itself unless we explicitly #undefine $Net::SSLeay::trace while running print_errs() local $Net::SSLeay::trace; return Net::SSLeay::print_errs('SSL error: ') || ''; } sub error { my ($self, $error, $destroy_socket) = @_; my @err; while ( my $err = Net::SSLeay::ERR_get_error()) { push @err, Net::SSLeay::ERR_error_string($err); $DEBUG>=2 && DEBUG( $error."\n".$self->get_ssleay_error()); } # if no new error occurred report last again if ( ! @err and my $err = ref($self) ? ${*$self}{'_SSL_last_err'} : $SSL_ERROR ) { push @err,$err; } $error .= ' '.join(' ',@err) if @err; if ($error) { $SSL_ERROR = dualvar( -1, $error ); ${*$self}{'_SSL_last_err'} = $SSL_ERROR if (ref($self)); } return; } sub can_client_sni { return $can_client_sni } sub can_server_sni { return $can_server_sni } sub can_npn { return $can_npn } sub DESTROY { my $self = shift or return; my $ssl = ${*$self}{_SSL_object} or return; if ($CREATED_IN_THIS_THREAD{$ssl}) { $self->close(_SSL_in_DESTROY => 1, SSL_no_shutdown => 1) if ${*$self}{'_SSL_opened'}; delete(${*$self}{'_SSL_ctx'}); } } #######Extra Backwards Compatibility Functionality####### sub socket_to_SSL { IO::Socket::SSL->start_SSL(@_); } sub socketToSSL { IO::Socket::SSL->start_SSL(@_); } sub kill_socket { shift->close } sub issuer_name { return(shift()->peer_certificate("issuer")) } sub subject_name { return(shift()->peer_certificate("subject")) } sub get_peer_certificate { return shift() } sub context_init { return($GLOBAL_SSL_ARGS = (ref($_[0]) eq 'HASH') ? $_[0] : {@_}); } sub set_default_context { $GLOBAL_SSL_ARGS->{'SSL_reuse_ctx'} = shift; } sub set_default_session_cache { $GLOBAL_SSL_ARGS->{SSL_session_cache} = shift; } sub set_defaults { my %args = @_; while ( my ($k,$v) = each %args ) { $k =~s{^(SSL_)?}{SSL_}; $GLOBAL_SSL_ARGS->{$k} = $v; } } { # deprecated API no warnings; *set_ctx_defaults = \&set_defaults; } sub set_client_defaults { my %args = @_; while ( my ($k,$v) = each %args ) { $k =~s{^(SSL_)?}{SSL_}; $GLOBAL_SSL_CLIENT_ARGS->{$k} = $v; } } sub set_server_defaults { my %args = @_; while ( my ($k,$v) = each %args ) { $k =~s{^(SSL_)?}{SSL_}; $GLOBAL_SSL_SERVER_ARGS->{$k} = $v; } } sub next_proto_negotiated { my $self = shift; return $self->error("NPN not supported in Net::SSLeay") if ! $can_npn; my $ssl = $self->_get_ssl_object || return; return Net::SSLeay::P_next_proto_negotiated($ssl); } sub opened { my $self = shift; return IO::Handle::opened($self) && ${*$self}{'_SSL_opened'}; } sub opening { my $self = shift; return ${*$self}{'_SSL_opening'}; } sub want_read { shift->errstr == SSL_WANT_READ } sub want_write { shift->errstr == SSL_WANT_WRITE } #Redundant IO::Handle functionality sub getline { return(scalar shift->readline()) } sub getlines { return(shift->readline()) if wantarray(); croak("Use of getlines() not allowed in scalar context"); } #Useless IO::Handle functionality sub truncate { croak("Use of truncate() not allowed with SSL") } sub stat { croak("Use of stat() not allowed with SSL" ) } sub setbuf { croak("Use of setbuf() not allowed with SSL" ) } sub setvbuf { croak("Use of setvbuf() not allowed with SSL" ) } sub fdopen { croak("Use of fdopen() not allowed with SSL" ) } #Unsupported socket functionality sub ungetc { croak("Use of ungetc() not implemented in IO::Socket::SSL") } sub send { croak("Use of send() not implemented in IO::Socket::SSL; use print/printf/syswrite instead") } sub recv { croak("Use of recv() not implemented in IO::Socket::SSL; use read/sysread instead") } package IO::Socket::SSL::SSL_HANDLE; use strict; use vars qw($HAVE_WEAKREF); use Errno 'EBADF'; BEGIN { local ($@, $SIG{__DIE__}); #Use Scalar::Util or WeakRef if possible: eval "use Scalar::Util qw(weaken isweak); 1" or eval "use WeakRef"; $HAVE_WEAKREF = $@ ? 0 : 1; } sub TIEHANDLE { my ($class, $handle) = @_; weaken($handle) if $HAVE_WEAKREF; bless \$handle, $class; } sub READ { ${shift()}->sysread(@_) } sub READLINE { ${shift()}->readline(@_) } sub GETC { ${shift()}->getc(@_) } sub PRINT { ${shift()}->print(@_) } sub PRINTF { ${shift()}->printf(@_) } sub WRITE { ${shift()}->syswrite(@_) } sub FILENO { ${shift()}->fileno(@_) } sub TELL { $! = EBADF; return -1 } sub BINMODE { return 0 } # not perfect, but better than not implementing the method sub CLOSE { #<---- Do not change this function! my $ssl = ${$_[0]}; local @_; $ssl->close(); } package IO::Socket::SSL::SSL_Context; use Carp; use strict; my %CTX_CREATED_IN_THIS_THREAD; *DEBUG = *IO::Socket::SSL::DEBUG; # should be better taken from Net::SSLeay, but they are not (yet) defined there use constant SSL_MODE_ENABLE_PARTIAL_WRITE => 1; use constant SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER => 2; # Note that the final object will actually be a reference to the scalar # (C-style pointer) returned by Net::SSLeay::CTX_*_new() so that # it can be blessed. sub new { my $class = shift; #DEBUG( "$class @_" ); my $arg_hash = (ref($_[0]) eq 'HASH') ? $_[0] : {@_}; # common problem forgetting to set SSL_use_cert # if client cert is given by user but SSL_use_cert is undef, assume that it # should be set my $is_server = $arg_hash->{SSL_server}; if ( ! $is_server && ! defined $arg_hash->{SSL_use_cert} && ( grep { $arg_hash->{$_} } qw(SSL_cert SSL_cert_file)) && ( grep { $arg_hash->{$_} } qw(SSL_key SSL_key_file)) ) { $arg_hash->{SSL_use_cert} = 1 } # add library defaults %$arg_hash = ( SSL_use_cert => $is_server, $is_server ? %DEFAULT_SSL_SERVER_ARGS : %DEFAULT_SSL_CLIENT_ARGS, %$arg_hash ); # Avoid passing undef arguments to Net::SSLeay defined($arg_hash->{$_}) or delete($arg_hash->{$_}) for(keys %$arg_hash); # use default path to certs and ca unless another one was given # don't mix default path with user specified path, either we use all # or no defaults { my $use_default = 1; for (qw( SSL_cert SSL_cert_file SSL_key SSL_key_file SSL_ca_file SSL_ca_path )) { next if ! defined $arg_hash->{$_}; # some apps set keys '' to signal that it is not set, replace with undef if ( $arg_hash->{$_} eq '' ) { $arg_hash->{$_} = undef; next; } $use_default = 0; } $use_default = 0 if $use_default and ! $is_server and ! $arg_hash->{SSL_verify_mode}; if ( $use_default ) { my %ca = -f 'certs/my-ca.pem' ? ( SSL_ca_file => 'certs/my-ca.pem' ) : -d 'ca/' ? ( SSL_ca_path => 'ca/' ) : (); my %certs = $is_server ? ( SSL_key_file => 'certs/server-key.pem', SSL_cert_file => 'certs/server-cert.pem', ) : $arg_hash->{SSL_use_cert} ? ( SSL_key_file => 'certs/client-key.pem', SSL_cert_file => 'certs/client-cert.pem', ) :(); %$arg_hash = ( %$arg_hash, %ca, %certs ); carp( "*******************************************************************\n". " The implicite use of IO::Socket::SSL specific default settings for \n". " CA, cert and key is depreceated.\n". " Please explicitly specify your own CA, cert and key using:\n". " - SSL_ca_file or SSL_ca_path for the CA\n". " - SSL_cert_file and SSL_key_file for cert and key\n". " To specify your own system wide defaults you can use \n". " set_defaults, set_client_defaults and set_server_defaults.\n". "*******************************************************************\n". " " ) if %ca or %certs; } else { for(qw(SSL_cert_file SSL_key_file)) { defined( my $file = $arg_hash->{$_} ) or next; for my $f (ref($file) eq 'HASH' ? values(%$file):$file ) { die "$_ $f does not exist" if ! -f $f; die "$_ $f is not accessable" if ! -r _; } } if ( defined( my $f = $arg_hash->{SSL_ca_file} )) { die "SSL_ca_file $f does not exist" if ! -f $f; die "SSL_ca_file $f is not accessable" if ! -r _; } if ( defined( my $d = $arg_hash->{SSL_ca_path} )) { die "only SSL_ca_path or SSL_ca_file should be given" if defined $arg_hash->{SSL_ca_file}; die "SSL_ca_path $d does not exist" if ! -d $d; die "SSL_ca_path $d is not accessable" if ! -r _; } } } my $vcn_scheme = delete $arg_hash->{SSL_verifycn_scheme}; if ( $vcn_scheme && $vcn_scheme ne 'none' ) { # don't access ${*self} inside callback - this seems to create # circular references from the ssl object to the context and back # use SSL_verifycn_name or determine from PeerAddr my $host = $arg_hash->{SSL_verifycn_name}; if (not defined($host)) { if ( $host = $arg_hash->{PeerAddr} || $arg_hash->{PeerHost} ) { $host =~s{:[a-zA-Z0-9_\-]+$}{}; } } $host ||= ref($vcn_scheme) && $vcn_scheme->{callback} && 'unknown'; $host or return IO::Socket::SSL->error( "Cannot determine peer hostname for verification" ); my $vcb = $arg_hash->{SSL_verify_callback}; $arg_hash->{SSL_verify_callback} = sub { my ($ok,$ctx_store,$certname,$error,$cert) = @_; $ok = $vcb->($ok,$ctx_store,$certname,$error,$cert) if $vcb; $ok or return 0; my $depth = Net::SSLeay::X509_STORE_CTX_get_error_depth($ctx_store); return $ok if $depth != 0; # verify name my $rv = IO::Socket::SSL::verify_hostname_of_cert( $host,$cert,$vcn_scheme ); # just do some code here against optimization because x509 has no # increased reference and CRYPTO_add is not available from Net::SSLeay return $rv; }; } my $ssl_op = Net::SSLeay::OP_ALL(); my $ver; for (split(/\s*:\s*/,$arg_hash->{SSL_version})) { m{^(!?)(?:(SSL(?:v2|v3|v23|v2/3))|(TLSv1(?:_?[12])?))$}i or croak("invalid SSL_version specified"); my $not = $1; ( my $v = lc($2||$3) ) =~s{^(...)}{\U$1}; if ( $not ) { $ssl_op |= $SSL_OP_NO{$v}; } else { croak("cannot set multiple SSL protocols in SSL_version") if $ver && $v ne $ver; $ver = $v; $ver =~s{/}{}; # interpret SSLv2/3 as SSLv23 $ver =~s{(TLSv1)(\d)}{$1\_$2}; # TLSv1_1 } } my $ctx_new_sub = UNIVERSAL::can( 'Net::SSLeay', $ver eq 'SSLv2' ? 'CTX_v2_new' : $ver eq 'SSLv3' ? 'CTX_v3_new' : $ver eq 'TLSv1' ? 'CTX_tlsv1_new' : $ver eq 'TLSv1_1' ? 'CTX_tlsv1_1_new' : $ver eq 'TLSv1_2' ? 'CTX_tlsv1_2_new' : 'CTX_new' ) or return IO::Socket::SSL->error("SSL Version $ver not supported"); my $ctx = $ctx_new_sub->() or return IO::Socket::SSL->error("SSL Context init failed"); # SSL_OP_CIPHER_SERVER_PREFERENCE $ssl_op |= 0x00400000 if $arg_hash->{SSL_honor_cipher_order}; Net::SSLeay::CTX_set_options($ctx,$ssl_op); # if we don't set session_id_context if client certificate is expected # client session caching will fail # if user does not provide explicit id just use the stringification # of the context if ( my $id = $arg_hash->{SSL_session_id_context} || ( $arg_hash->{SSL_verify_mode} & 0x01 ) && "$ctx" ) { Net::SSLeay::CTX_set_session_id_context($ctx,$id,length($id)); } # SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER makes syswrite return if at least one # buffer was written and not block for the rest # SSL_MODE_ENABLE_PARTIAL_WRITE can be necessary for non-blocking because we # cannot guarantee, that the location of the buffer stays constant Net::SSLeay::CTX_set_mode( $ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER|SSL_MODE_ENABLE_PARTIAL_WRITE); if ( my $proto_list = $arg_hash->{SSL_npn_protocols} ) { return IO::Socket::SSL->error("NPN not supported in Net::SSLeay") if ! $can_npn; if($arg_hash->{SSL_server}) { # on server side SSL_npn_protocols means a list of advertised protocols Net::SSLeay::CTX_set_next_protos_advertised_cb($ctx, $proto_list); } else { # on client side SSL_npn_protocols means a list of preferred protocols # negotiation algorithm used is "as-openssl-implements-it" Net::SSLeay::CTX_set_next_proto_select_cb($ctx, $proto_list); } } my $verify_mode = $arg_hash->{SSL_verify_mode}; if ( $verify_mode != Net::SSLeay::VERIFY_NONE()) { if ( defined $arg_hash->{SSL_ca_file} || defined $arg_hash->{SSL_ca_path} ) { return IO::Socket::SSL->error("Invalid certificate authority locations") if ! Net::SSLeay::CTX_load_verify_locations( $ctx, $arg_hash->{SSL_ca_file} || '',$arg_hash->{SSL_ca_path} || ''); } else { # no CA path given, continue with system defaults Net::SSLeay::CTX_set_default_verify_paths($ctx); } } if ($arg_hash->{'SSL_check_crl'}) { Net::SSLeay::X509_STORE_set_flags( Net::SSLeay::CTX_get_cert_store($ctx), Net::SSLeay::X509_V_FLAG_CRL_CHECK() ); if ($arg_hash->{'SSL_crl_file'}) { my $bio = Net::SSLeay::BIO_new_file($arg_hash->{'SSL_crl_file'}, 'r'); my $crl = Net::SSLeay::PEM_read_bio_X509_CRL($bio); if ( $crl ) { Net::SSLeay::X509_STORE_add_crl(Net::SSLeay::CTX_get_cert_store($ctx), $crl); } else { return IO::Socket::SSL->error("Invalid certificate revocation list"); } } } if ($arg_hash->{'SSL_server'} || $arg_hash->{'SSL_use_cert'}) { my $filetype = Net::SSLeay::FILETYPE_PEM(); if ($arg_hash->{'SSL_passwd_cb'}) { Net::SSLeay::CTX_set_default_passwd_cb($ctx, $arg_hash->{'SSL_passwd_cb'}); } my %sni; for my $opt (qw(SSL_key SSL_key_file SSL_cert SSL_cert_file)) { my $val = $arg_hash->{$opt} or next; if ( ref($val) eq 'HASH' ) { # SNI while ( my ($host,$v) = each %$val ) { $sni{lc($host)}{$opt} = $v; } } else { $sni{''}{$opt} = $val; } } $sni{''}{ctx} = $ctx if exists $sni{''}; # default if no SNI for my $sni (values %sni) { # we need a new context for each server my $snictx = $sni->{ctx} ||= $ctx_new_sub->() or return IO::Socket::SSL->error("SSL Context init failed"); if ( my $pkey = $sni->{SSL_key} ) { # binary, e.g. EVP_PKEY* Net::SSLeay::CTX_use_PrivateKey($snictx, $pkey) || return IO::Socket::SSL->error("Failed to use Private Key"); } elsif ( my $f = $sni->{SSL_key_file} ) { Net::SSLeay::CTX_use_PrivateKey_file($snictx, $f, $filetype) || return IO::Socket::SSL->error("Failed to open Private Key"); } if ( my $x509 = $sni->{SSL_cert} ) { # binary, e.g. X509* # we have either a single certificate or a list with # a chain of certificates my @x509 = ref($x509) eq 'ARRAY' ? @$x509: ($x509); my $cert = shift @x509; Net::SSLeay::CTX_use_certificate( $snictx,$cert ) || return IO::Socket::SSL->error("Failed to use Certificate"); foreach my $ca (@x509) { Net::SSLeay::CTX_add_extra_chain_cert( $snictx,$ca ) || return IO::Socket::SSL->error("Failed to use Certificate"); } } elsif ( my $f = $sni->{SSL_cert_file} ) { Net::SSLeay::CTX_use_certificate_chain_file($snictx, $f) || return IO::Socket::SSL->error("Failed to open Certificate"); } } if ( keys %sni > 1 or ! exists $sni{''} ) { # we definitely want SNI support $can_server_sni or return IO::Socket::SSL->error( "Server side SNI not supported for this openssl/Net::SSLeay"); $_ = $_->{ctx} for( values %sni); Net::SSLeay::CTX_set_tlsext_servername_callback($ctx, sub { my $ssl = shift; my $host = Net::SSLeay::get_servername($ssl); $host = '' if ! defined $host; my $snictx = $sni{lc($host)} || $sni{''} or do { $DEBUG>1 and DEBUG( "cannot get context from servername '$host'"); return 0; }; $DEBUG>1 and DEBUG("set context from servername $host"); Net::SSLeay::set_SSL_CTX($ssl,$snictx) if $snictx != $ctx; return 1; }); } if ( my $f = $arg_hash->{SSL_dh_file} ) { my $bio = Net::SSLeay::BIO_new_file( $f,'r' ) || return IO::Socket::SSL->error( "Failed to open DH file $f" ); my $dh = Net::SSLeay::PEM_read_bio_DHparams($bio); Net::SSLeay::BIO_free($bio); $dh || return IO::Socket::SSL->error( "Failed to read PEM for DH from $f - wrong format?" ); my $rv = Net::SSLeay::CTX_set_tmp_dh( $ctx,$dh ); Net::SSLeay::DH_free( $dh ); $rv || return IO::Socket::SSL->error( "Failed to set DH from $f" ); } elsif ( my $dh = $arg_hash->{SSL_dh} ) { # binary, e.g. DH* Net::SSLeay::CTX_set_tmp_dh( $ctx,$dh ) || return IO::Socket::SSL->error( "Failed to set DH from SSL_dh" ); } if ( my $curve = $arg_hash->{SSL_ecdh_curve} ) { return IO::Socket::SSL->error( "ECDH curve needs Net::SSLeay>=1.56 and OpenSSL>=1.0") if ! $can_ecdh; if ( $curve !~ /^\d+$/ ) { # name of curve, find NID $curve = Net::SSLeay::OBJ_txt2nid($curve) || return IO::Socket::SSL->error( "cannot find NID for curve name '$curve'"); } my $ecdh = Net::SSLeay::EC_KEY_new_by_curve_name($curve) or return IO::Socket::SSL->error( "cannot create curve for NID $curve"); Net::SSLeay::CTX_set_tmp_ecdh($ctx,$ecdh) or return IO::Socket::SSL->error( "failed to set ECDH curve context"); Net::SSLeay::EC_KEY_free($ecdh); } } my $verify_cb = $arg_hash->{SSL_verify_callback}; my $verify_callback = $verify_cb && sub { my ($ok, $ctx_store) = @_; my ($certname,$cert,$error); if ($ctx_store) { $cert = Net::SSLeay::X509_STORE_CTX_get_current_cert($ctx_store); $error = Net::SSLeay::X509_STORE_CTX_get_error($ctx_store); $certname = Net::SSLeay::X509_NAME_oneline(Net::SSLeay::X509_get_issuer_name($cert)). Net::SSLeay::X509_NAME_oneline(Net::SSLeay::X509_get_subject_name($cert)); $error &&= Net::SSLeay::ERR_error_string($error); } $DEBUG>=3 && DEBUG( "ok=$ok cert=$cert" ); return $verify_cb->($ok,$ctx_store,$certname,$error,$cert); }; Net::SSLeay::CTX_set_verify($ctx, $verify_mode, $verify_callback); if ( my $cl = $arg_hash->{SSL_cipher_list} ) { Net::SSLeay::CTX_set_cipher_list($ctx, $cl ) || return IO::Socket::SSL->error("Failed to set SSL cipher list"); } if ( my $cb = $arg_hash->{SSL_create_ctx_callback} ) { $cb->($ctx); } my $self = bless { context => $ctx },$class; $self->{has_verifycb} = 1 if $verify_callback; $DEBUG>=3 && DEBUG( "new ctx $ctx" ); $CTX_CREATED_IN_THIS_THREAD{$ctx} = 1; if ( my $cache = $arg_hash->{SSL_session_cache} ) { # use predefined cache $self->{session_cache} = $cache } elsif ( my $size = $arg_hash->{SSL_session_cache_size}) { $self->{session_cache} = IO::Socket::SSL::Session_Cache->new( $size ); } return $self; } sub session_cache { my $self = shift; my $cache = $self->{session_cache} || return; my ($addr,$port,$session) = @_; $port ||= $addr =~s{:(\w+)$}{} && $1; # host:port my $key = "$addr:$port"; return defined($session) ? $cache->add_session($key, $session) : $cache->get_session($key); } sub has_session_cache { return defined shift->{session_cache}; } sub CLONE { %CTX_CREATED_IN_THIS_THREAD = (); } sub DESTROY { my $self = shift; if ( my $ctx = $self->{context} ) { $DEBUG>=3 && DEBUG("free ctx $ctx open=".join( " ",keys %CTX_CREATED_IN_THIS_THREAD )); if ( %CTX_CREATED_IN_THIS_THREAD and delete $CTX_CREATED_IN_THIS_THREAD{$ctx} ) { # remove any verify callback for this context if ( $self->{has_verifycb}) { $DEBUG>=3 && DEBUG("free ctx $ctx callback" ); Net::SSLeay::CTX_set_verify($ctx, 0,undef); } $DEBUG>=3 && DEBUG("OK free ctx $ctx" ); Net::SSLeay::CTX_free($ctx); } } delete(@{$self}{'context','session_cache'}); } package IO::Socket::SSL::Session_Cache; use strict; sub new { my ($class, $size) = @_; $size>0 or return; return bless { _maxsize => $size }, $class; } sub get_session { my ($self, $key) = @_; my $session = $self->{$key} || return; return $session->{session} if ($self->{'_head'} eq $session); $session->{prev}->{next} = $session->{next}; $session->{next}->{prev} = $session->{prev}; $session->{next} = $self->{'_head'}; $session->{prev} = $self->{'_head'}->{prev}; $self->{'_head'}->{prev} = $self->{'_head'}->{prev}->{next} = $session; $self->{'_head'} = $session; return $session->{session}; } sub add_session { my ($self, $key, $val) = @_; return if ($key eq '_maxsize' or $key eq '_head'); if ( $self->{$key} ) { $self->{$key}{session} = $val; return get_session($self,$key); # will put key on front } my $session = $self->{$key} = { session => $val, key => $key }; if ( keys(%$self) > $self->{_maxsize}+2) { my $last = $self->{'_head'}->{prev}; Net::SSLeay::SESSION_free($last->{session}); delete($self->{$last->{key}}); $self->{'_head'}->{prev} = $self->{'_head'}->{prev}->{prev}; delete($self->{'_head'}) if ($self->{'_maxsize'} == 1); } if ($self->{'_head'}) { $session->{next} = $self->{'_head'}; $session->{prev} = $self->{'_head'}->{prev}; $self->{'_head'}->{prev}->{next} = $session; $self->{'_head'}->{prev} = $session; } else { $session->{next} = $session->{prev} = $session; } $self->{'_head'} = $session; return $session; } sub DESTROY { my $self = shift; delete(@{$self}{'_head','_maxsize'}); for (values %$self) { Net::SSLeay::SESSION_free($_->{session} || next); } } 1; __END__ =head1 NAME IO::Socket::SSL -- SSL sockets with IO::Socket interface =head1 SYNOPSIS use strict; use IO::Socket::SSL; # simple HTTP client ----------------------------------------------- my $client = IO::Socket::SSL->new( # where to connect PeerHost => "www.example.com", PeerPort => "https", # certificate verification SSL_verify_mode => SSL_VERIFY_PEER, SSL_ca_path => '/etc/ssl/certs', # typical CA path on Linux # on OpenBSD instead: SSL_ca_file => '/etc/ssl/cert.pem' # easy hostname verification SSL_verifycn_name => 'foo.bar', # defaults to PeerHost SSL_verifycn_scheme => 'http', # SNI support SSL_hostname => 'foo.bar', # defaults to PeerHost ) or die "failed connect or ssl handshake: $!,$SSL_ERROR"; # send and receive over SSL connection print $client "GET / HTTP/1.0\r\n\r\n"; print <$client>; # simple server ---------------------------------------------------- my $server = IO::Socket::SSL->new( # where to listen LocalAddr => '127.0.0.1', LocalPort => 8080, Listen => 10, # which certificate to offer # with SNI support there can be different certificates per hostname SSL_cert_file => 'cert.pem', SSL_key_file => 'key.pem', ) or die "failed to listen: $!"; # accept client my $client = $server->accept or die "failed to accept or ssl handshake: $!,$SSL_ERROR"; # Upgrade existing socket to SSL --------------------------------- my $sock = IO::Socket::INET->new('imap.example.com:imap'); # ... receive greeting, send STARTTLS, receive ok ... IO::Socket::SSL->start_SSL($sock, SSL_verify_mode => SSL_VERIFY_PEER, SSL_ca_path => '/etc/ssl/certs', ... ) or die "failed to upgrade to SSL: $SSL_ERROR"; # manual name verification, could also be done in start_SSL with # SSL_verifycn_name etc $client->verify_hostname( 'imap.example.com','imap' ) or die "hostname verification failed"; # all data are now SSL encrypted print $sock .... # use non-blocking socket (BEWARE OF SELECT!) ------------------- my $cl = IO::Socket::SSL->new($dst); $cl->blocking(0); my $sel = IO::Select->new($cl); while (1) { # with SSL a call for reading n bytes does not result in reading of n # bytes from the socket, but instead it must read at least one full SSL # frame. If the socket has no new bytes, but there are unprocessed data # from the SSL frame can_read will block! # wait for data on socket $sel->can_read(); # new data on socket or eof READ: # this does not read only 1 byte from socket, but reads the complete SSL # frame and then just returns one byte. On subsequent calls it than # returns more byte of the same SSL frame until it needs to read the # next frame. my $n = sysread( $cl,my $buf,1); if ( ! defined $n ) { die $! if not ${EAGAIN}; next if $SSL_ERROR == SSL_WANT_READ; if ( $SSL_ERROR == SSL_WANT_WRITE ) { # need to write data on renegotiation $sel->can_write; next; } die "something went wrong: $SSL_ERROR"; } elsif ( ! $n ) { last; # eof } else { # read next bytes # we might have still data within the current SSL frame # thus first process these data instead of waiting on the underlying # socket object goto READ if $self->pending; # goto sysread next; # goto $sel->can_read } } =head1 DESCRIPTION This module provides an interface to SSL sockets, similar to other IO::Socket modules. Because of that, it can be used to make existing programs using IO::Socket::INET or similar modules to provide SSL encryption without much effort. IO::Socket::SSL supports all the extra features that one needs to write a full-featured SSL client or server application: multiple SSL contexts, cipher selection, certificate verification, Server Name Indication (SNI), Next Protocol Negotiation (NPN), SSL version selection and more. If you have never used SSL before, you should read the section 'Using SSL' before attempting to use this module. If you used IO::Socket before you should read the following section 'Differences to IO::Socket'. If you want to use SSL with non-blocking sockets and/or within an event loop please read very carefully the sections about non-blocking I/O and polling of SSL sockets. If you are trying to use it with threads see the BUGS section. =head2 Differences to IO::Socket Although L tries to behave similar to L there are some important differences due to the way SSL works: =over 4 =item * buffered input Data are transmitted inside the SSL protocol using encrypted frames, which can only be decrypted once the full frame is received. So if you use C or C to receive less data than the SSL frame contains, it will read the whole frame, return part of it and buffer the rest for later reads. This does not make a difference for simple programs, but if you use select-loops or polling or non-blocking I/O please read the related sections. =item * SSL handshakes Before any encryption can be done the peers have to agree to common algorithms, verify certificates etc. So a handshake needs to be done before any payload is send or received and might additionally happen later in the connection again. This has important implications when doing non-blocking or event-based I/O (please read the related sections), but means also, that connect and accept calls include the SSL handshake and thus might block or fail, if the peer does not behave like expected. For instance accept will wait infinitly if a TCP client connects to the socket but does not initiate an SSL handshake. =back =head1 METHODS IO::Socket::SSL inherits from another IO::Socket module. The choice of the super class depends on the installed modules: =over 4 =item * If IO::Socket::IP with at least version 0.20 is installed it will use this module as super class, transparently providing IPv6 and IPv4 support. =item * If IO::Socket::INET6 is installed it will use this module as super class, transparently providing IPv6 and IPv4 support. =item * Otherwise it will fall back to IO::Socket::INET, which is a perl core module. With IO::Socket::INET you only get IPv4 support. =back Please be aware, that with the IPv6 capable super classes, it will lookup first for the IPv6 address of a given hostname. If the resolver provides an IPv6 address, but the host cannot be reached by IPv6, there will be no automatic fallback to IPv4. To avoid these problems you can either force IPv4 by specifying and AF_INET as C of the socket or globally enforce IPv4 by loading IO::Socket::SSL with the option 'inet4'. IO::Socket::SSL will provide all of the methods of its super class, but sometimes it will override them to match the behavior expected from SSL or to provide additional arguments. The new or changed methods are described below, but please read also the section about SSL specific error handling. =over 4 =item B Creates a new IO::Socket::SSL object. You may use all the friendly options that came bundled with the super class (e.g. IO::Socket::IP, IO::Socket::INET, ...) plus (optionally) the ones described below. If you don't specify any SSL related options it will do it's best in using secure defaults, e.g. chosing good ciphers, enabling proper verification etc. =over 2 =item SSL_hostname This can be given to specify the hostname used for SNI, which is needed if you have multiple SSL hostnames on the same IP address. If not given it will try to determine hostname from PeerAddr, which will fail if only IP was given or if this argument is used within start_SSL. If you want to disable SNI set this argument to ''. Currently only supported for the client side and will be ignored for the server side. See section "SNI Support" for details of SNI the support. =item SSL_version Sets the version of the SSL protocol used to transmit data. 'SSLv23' auto-negotiates between SSLv2 and SSLv3, while 'SSLv2', 'SSLv3', 'TLSv1', 'TLSv1_1' or 'TLSv1_2' restrict the protocol to the specified version. All values are case-insensitive. Instead of 'TLSv1_1' and 'TLSv1_2' one can also use 'TLSv11' and 'TLSv12'. Support for 'TLSv1_1' and 'TLSv1_2' requires recent versions of Net::SSLeay and openssl. You can limit to set of supported protocols by adding !version separated by ':'. The default SSL_version is 'SSLv23:!SSLv2' which means, that SSLv2, SSLv3 and TLSv1 are supported for initial protocol handshakes, but SSLv2 will not be accepted, leaving only SSLv3 and TLSv1. You can also use !TLSv1_1 and !TLSv1_2 to disable TLS versions 1.1 and 1.2 while allowing TLS version 1.0. Setting the version instead to 'TLSv1' will probably break interaction with lots of clients which start with SSLv2 and then upgrade to TLSv1. On the other side some clients just close the connection when they receive a TLS version 1.1 request. In this case setting the version to 'SSLv23:!SSLv2:!TLSv1_1:!TLSv1_2' might help. =item SSL_cipher_list If this option is set the cipher list for the connection will be set to the given value, e.g. something like 'ALL:!LOW:!EXP:!aNULL'. Look into the OpenSSL documentation (L) for more details. Unless you fail to contact your peer because of no shared ciphers it is recommended to leave this option at the default setting. The default setting prefers ciphers with forward secrecy, disables anonymous authentication and disables known insecure ciphers like MD5, DES etc. This gives a grade A result at the tests of SSL Labs. To use the less secure OpenSSL builtin default (whatever this is) set SSL_cipher_list to ''. =item SSL_honor_cipher_order If this option is true the cipher order the server specified is used instead of the order proposed by the client. This option defaults to true to make use of our secure cipher list setting. =item SSL_use_cert If this is true, it forces IO::Socket::SSL to use a certificate and key, even if you are setting up an SSL client. If this is set to 0 (the default), then you will only need a certificate and key if you are setting up a server. SSL_use_cert will implicitly be set if SSL_server is set. For convenience it is also set if it was not given but a cert was given for use (SSL_cert_file or similar). =item SSL_server Set this option to a true value, if the socket should be used as a server. If this is not explicitly set it is assumed, if the Listen parameter is given when creating the socket. =item SSL_cert_file | SSL_cert | SSL_key_file | SSL_key If you create a server you usually need to specify a server certificate which should be verified by the client. Same is true for client certificates, which should be verified by the server. The certificate can be given as a file in PEM format with SSL_cert_file or as an internal representation of a X509* object with SSL_cert. For each certificate a key is need, which can either be given as a file in PEM format with SSL_key_file or as an internal representation of a EVP_PKEY* object with SSL_key. If your SSL server should be able to use different certificates on the same IP address, depending on the name given by SNI, you can use a hash reference instead of a file with C< cert_file>>. In case certs and keys are needed but not given it might fall back to builtin defaults, see "Defaults for Cert, Key and CA". Examples: SSL_cert_file => 'mycert.pem', SSL_key_file => 'mykey.pem', SSL_cert_file => { "foo.example.org" => 'foo-cert.pem', "bar.example.org" => 'bar-cert.pem', # used when nothing matches or client does not support SNI '' => 'default-cert.pem', } SSL_key_file => { "foo.example.org" => 'foo-key.pem', "bar.example.org" => 'bar-key.pem', # used when nothing matches or client does not support SNI '' => 'default-key.pem', } =item SSL_dh_file If you want Diffie-Hellman key exchange you need to supply a suitable file here or use the SSL_dh parameter. See dhparam command in openssl for more information. To create a server which provides forward secrecy you need to either give the DH parameters or (better, because faster) the ECDH curve. If neither C not C is set a builtin DH parameter with a length of 2048 bit is used to offer DH key exchange by default. If you don't want this (e.g. disable DH key exchange) explicitly set this or the C parameter to undef. =item SSL_dh Like SSL_dh_file, but instead of giving a file you use a preloaded or generated DH*. =item SSL_ecdh_curve If you want Elliptic Curve Diffie-Hellmann key exchange you need to supply the OID or NID of a suitable curve (like 'prime256v1') here. To create a server which provides forward secrecy you need to either give the DH parameters or (better, because faster) the ECDH curve. This parameter defaults to 'prime256v1' (builtin of OpenSSL) to offer ECDH key exchange by default. If you don't want this explicitly set it to undef. =item SSL_passwd_cb If your private key is encrypted, you might not want the default password prompt from Net::SSLeay. This option takes a reference to a subroutine that should return the password required to decrypt your private key. =item SSL_ca_file | SSL_ca_path Usually you want to verify that the peer certificate has been signed by a trusted certificate authority. In this case you should use this option to specify the file (SSL_ca_file) or directory (SSL_ca_path) containing the certificateZ<>(s) of the trusted certificate authorities. If both SSL_ca_file and SSL_ca_path are undefined and not builtin defaults (see "Defaults for Cert, Key and CA".) can be used, it will try to use the system defaults used built into the OpenSSL library. If you really don't want to set a CA set this key to C<''>. =item SSL_verify_mode This option sets the verification mode for the peer certificate. You may combine SSL_VERIFY_PEER (verify_peer), SSL_VERIFY_FAIL_IF_NO_PEER_CERT (fail verification if no peer certificate exists; ignored for clients), SSL_VERIFY_CLIENT_ONCE (verify client once; ignored for clients). See OpenSSL man page for SSL_CTX_set_verify for more information. The default is SSL_VERIFY_NONE for server (e.g. no check for client certificate) and SSL_VERIFY_PEER for client (check server certificate). =item SSL_verify_callback If you want to verify certificates yourself, you can pass a sub reference along with this parameter to do so. When the callback is called, it will be passed: =over 4 =item 1. a true/false value that indicates what OpenSSL thinks of the certificate, =item 2. a C-style memory address of the certificate store, =item 3. a string containing the certificate's issuer attributes and owner attributes, and =item 4. a string containing any errors encountered (0 if no errors). =item 5. a C-style memory address of the peer's own certificate (convertible to PEM form with Net::SSLeay::PEM_get_string_X509()). =back The function should return 1 or 0, depending on whether it thinks the certificate is valid or invalid. The default is to let OpenSSL do all of the busy work. The callback will be called for each element in the certificate chain. See the OpenSSL documentation for SSL_CTX_set_verify for more information. =item SSL_verifycn_scheme Set the scheme used to automatically verify the hostname of the peer. See the information about the verification schemes in B. The default is undef, e.g. to not automatically verify the hostname. If no verification is done the other B options have no effect, but you might still do manual verification by calling B. =item SSL_verifycn_name Set the name which is used in verification of hostname. If SSL_verifycn_scheme is set and no SSL_verifycn_name is given it will try to use the PeerHost and PeerAddr settings and fail if no name can be determined. Using PeerHost or PeerAddr works only if you create the connection directly with C<< IO::Socket::SSL->new >>, if an IO::Socket::INET object is upgraded with B the name has to be given in B. =item SSL_check_crl If you want to verify that the peer certificate has not been revoked by the signing authority, set this value to true. OpenSSL will search for the CRL in your SSL_ca_path, or use the file specified by SSL_crl_file. See the Net::SSLeay documentation for more details. Note that this functionality appears to be broken with OpenSSL < v0.9.7b, so its use with lower versions will result in an error. =item SSL_crl_file If you want to specify the CRL file to be used, set this value to the pathname to be used. This must be used in addition to setting SSL_check_crl. =item SSL_reuse_ctx If you have already set the above options for a previous instance of IO::Socket::SSL, then you can reuse the SSL context of that instance by passing it as the value for the SSL_reuse_ctx parameter. You may also create a new instance of the IO::Socket::SSL::SSL_Context class, using any context options that you desire without specifying connection options, and pass that here instead. If you use this option, all other context-related options that you pass in the same call to new() will be ignored unless the context supplied was invalid. Note that, contrary to versions of IO::Socket::SSL below v0.90, a global SSL context will not be implicitly used unless you use the set_default_context() function. =item SSL_create_ctx_callback With this callback you can make individual settings to the context after it got created and the default setup was done. The callback will be called with the CTX object from Net::SSLeay as the single argument. Example for limiting the server session cache size: SSL_create_ctx_callback => sub { my $ctx = shift; Net::SSLeay::CTX_sess_set_cache_size($ctx,128); } =item SSL_session_cache_size If you make repeated connections to the same host/port and the SSL renegotiation time is an issue, you can turn on client-side session caching with this option by specifying a positive cache size. For successive connections, pass the SSL_reuse_ctx option to the new() calls (or use set_default_context()) to make use of the cached sessions. The session cache size refers to the number of unique host/port pairs that can be stored at one time; the oldest sessions in the cache will be removed if new ones are added. This option does not effect the session cache a server has for it's clients, e.g. it does not affect SSL objects with SSL_server set. =item SSL_session_cache Specifies session cache object which should be used instead of creating a new. Overrules SSL_session_cache_size. This option is useful if you want to reuse the cache, but not the rest of the context. A session cache object can be created using C<< IO::Socket::SSL::Session_Cache->new( cachesize ) >>. Use set_default_session_cache() to set a global cache object. =item SSL_session_key Specifies a key to use for lookups and inserts into client-side session cache. Per default ip:port of destination will be used, but sometimes you want to share the same session over multiple ports on the same server (like with FTPS). =item SSL_session_id_context This gives an id for the servers session cache. It's necessary if you want clients to connect with a client certificate. If not given but SSL_verify_mode specifies the need for client certificate a context unique id will be picked. =item SSL_error_trap When using the accept() or connect() methods, it may be the case that the actual socket connection works but the SSL negotiation fails, as in the case of an HTTP client connecting to an HTTPS server. Passing a subroutine ref attached to this parameter allows you to gain control of the orphaned socket instead of having it be closed forcibly. The subroutine, if called, will be passed two parameters: a reference to the socket on which the SSL negotiation failed and the full text of the error message. =item SSL_npn_protocols If used on the server side it specifies list of protocols advertised by SSL server as an array ref, e.g. ['spdy/2','http1.1']. On the client side it specifies the protocols offered by the client for NPN as an array ref. See also method L. Next Protocol Negotioation (NPN) is available with Net::SSLeay 1.46+ and openssl-1.0.1+. To check support you might call Ccan_npn()>. If you use this option with an unsupported Net::SSLeay/OpenSSL it will throw an error. =back =item B This behaves similar to the accept function of the underlying socket class, but additionally does the initial SSL handshake. But because the underlying socket class does return a blocking file handle even when accept is called on a non-blocking socket, the SSL handshake on the new file object will be done in a blocking way. Please see the section about non-blocking I/O for details. If you don't like this behavior you should do accept on the TCP socket and then upgrade it with C later. =item B This behaves similar to the connnect function but also does an SSL handshake. Because you cannot give SSL specific arguments to this function, you should better either use C to create a connect SSL socket or C to upgrade an established TCP socket to SSL. =item B There are a number of nasty traps that lie in wait if you are not careful about using close(). The first of these will bite you if you have been using shutdown() on your sockets. Since the SSL protocol mandates that a SSL "close notify" message be sent before the socket is closed, a shutdown() that closes the socket's write channel will cause the close() call to hang. For a similar reason, if you try to close a copy of a socket (as in a forking server) you will affect the original socket as well. To get around these problems, call close with an object-oriented syntax (e.g. $socket->close(SSL_no_shutdown => 1)) and one or more of the following parameters: =over 2 =item SSL_no_shutdown If set to a true value, this option will make close() not use the SSL_shutdown() call on the socket in question so that the close operation can complete without problems if you have used shutdown() or are working on a copy of a socket. Not using a real ssl shutdown on a socket will make session caching unusable. =item SSL_fast_shutdown If set to true only a unidirectional shutdown will be done, e.g. only the close_notify (see SSL_shutdown(3)) will be sent. Otherwise a bidirectional shutdown will be done where it waits for the close_notify of the peer too. Because a unidirectional shutdown is enough to keep session cache working it defaults to fast shutdown inside close. =item SSL_ctx_free If you want to make sure that the SSL context of the socket is destroyed when you close it, set this option to a true value. =back =item B This function behaves from the outside the same as B in other L objects, e.g. it returns at most LEN bytes of data. But in reality it reads not only LEN bytes from the underlying socket, but at a single SSL frame. It then returns up to LEN bytes it decrypted from this SSL frame. If the frame contained more data than requested it will return only LEN data, buffer the rest and return it on futher read calls. This means, that it might be possible to read data, even if the underlying socket is not readable, so using poll or select might not be sufficient. sysread will only return data from a single SSL frame, e.g. either the pending data from the already buffered frame or it will read a frame from the underlying socket and return the decrypted data. It will not return data spanning several SSL frames in a single call. Also, calls to sysread might fail, because it must first finish an SSL handshake. To understand these behaviors is essential, if you write applications which use event loops and/or non-blocking sockets. Please read the specific sections in this documentation. =item B This functions behaves from the outside the same as B in other L objects, e.g. it will write at most LEN bytes to the socket, but there is no guarantee, that all LEN bytes are written. It will return the number of bytes written. syswrite will write all the data within a single SSL frame, which means, that no more than 16.384 bytes, which is the maximum size of an SSL frame, can be written at once. For non-blocking sockets SSL specific behavior applies. Pease read the specific section in this documentation. =item B This function has exactly the same syntax as B, and performs nearly the same task but will not advance the read position so that successive calls to peek() with the same arguments will return the same results. This function requires OpenSSL 0.9.6a or later to work. =item B This function gives you the number of bytes available without reading from the underlying socket object. This function is essential if you work with event loops, please see the section about polling SSL sockets. =item B Returns the string form of the cipher that the IO::Socket::SSL object is using. =item B Returns the string representation of the SSL version of an established connection. =item B Returns the integer representation of the SSL version of an established connection. =item B Returns a parsable string with select fields from the peer SSL certificate. This method directly returns the result of the dump_peer_certificate() method of Net::SSLeay. =item B If a peer certificate exists, this function can retrieve values from it. If no field is given the internal representation of certificate from Net::SSLeay is returned. The following fields can be queried: =over 8 =item authority (alias issuer) The certificate authority which signed the certificate. =item owner (alias subject) The owner of the certificate. =item commonName (alias cn) - only for Net::SSLeay version >=1.30 The common name, usually the server name for SSL certificates. =item subjectAltNames - only for Net::SSLeay version >=1.33 Alternative names for the subject, usually different names for the same server, like example.org, example.com, *.example.com. It returns a list of (typ,value) with typ GEN_DNS, GEN_IPADD etc (these constants are exported from IO::Socket::SSL). See Net::SSLeay::X509_get_subjectAltNames. =back =item B This gives the name requested by the client if Server Name Indication (SNI) was used. =item B This verifies the given hostname against the peer certificate using the given scheme. Hostname is usually what you specify within the PeerAddr. Verification of hostname against a certificate is different between various applications and RFCs. Some scheme allow wildcards for hostnames, some only in subjectAltNames, and even their different wildcard schemes are possible. To ease the verification the following schemes are predefined: =over 8 =item ldap (rfc4513), pop3,imap,acap (rfc2995), nntp (rfc4642) Simple wildcards in subjectAltNames are possible, e.g. *.example.org matches www.example.org but not lala.www.example.org. If nothing from subjectAltNames match it checks against the common name, but there are no wildcards allowed. =item http (rfc2818), alias is www Extended wildcards in subjectAltNames and common name are possible, e.g. *.example.org or even www*.example.org. The common name will be only checked if no names are given in subjectAltNames. =item smtp (rfc3207) This RFC doesn't say much useful about the verification so it just assumes that subjectAltNames are possible, but no wildcards are possible anywhere. =item none No verification will be done. Actually is does not make any sense to call verify_hostname in this case. =back The scheme can be given either by specifying the name for one of the above predefined schemes, or by using a hash which can have the following keys and values: =over 8 =item check_cn: 0|'always'|'when_only' Determines if the common name gets checked. If 'always' it will always be checked (like in ldap), if 'when_only' it will only be checked if no names are given in subjectAltNames (like in http), for any other values the common name will not be checked. =item wildcards_in_alt: 0|'leftmost'|'anywhere' Determines if and where wildcards in subjectAltNames are possible. If 'leftmost' only cases like *.example.org will be possible (like in ldap), for 'anywhere' www*.example.org is possible too (like http), dangerous things like but www.*.org or even '*' will not be allowed. =item wildcards_in_cn: 0|'leftmost'|'anywhere' Similar to wildcards_in_alt, but checks the common name. There is no predefined scheme which allows wildcards in common names. =item callback: \&coderef If you give a subroutine for verification it will be called with the arguments ($hostname,$commonName,@subjectAltNames), where hostname is the name given for verification, commonName is the result from peer_certificate('cn') and subjectAltNames is the result from peer_certificate('subjectAltNames'). All other arguments for the verification scheme will be ignored in this case. =back =item B This method returns the name of negotiated protocol - e.g. 'http/1.1'. It works for both client and server side of SSL connection. NPN support is available with Net::SSLeay 1.46+ and openssl-1.0.1+. To check support you might call Ccan_npn()>. =item B Returns the last error (in string form) that occurred. If you do not have a real object to perform this method on, call IO::Socket::SSL::errstr() instead. For read and write errors on non-blocking sockets, this method may include the string C or C meaning that the other side is expecting to read from or write to the socket and wants to be satisfied before you get to do anything. But with version 0.98 you are better comparing the global exported variable $SSL_ERROR against the exported symbols SSL_WANT_READ and SSL_WANT_WRITE. =item B This returns false if the socket could not be opened, 1 if the socket could be opened and the SSL handshake was successful done and -1 if the underlying IO::Handle is open, but the SSL handshake failed. =item B<< IO::Socket::SSL->start_SSL($socket, ... ) >> This will convert a glob reference or a socket that you provide to an IO::Socket::SSL object. You may also pass parameters to specify context or connection options as with a call to new(). If you are using this function on an accept()ed socket, you must set the parameter "SSL_server" to 1, i.e. IO::Socket::SSL->start_SSL($socket, SSL_server => 1). If you have a class that inherits from IO::Socket::SSL and you want the $socket to be blessed into your own class instead, use MyClass->start_SSL($socket) to achieve the desired effect. Note that if start_SSL() fails in SSL negotiation, $socket will remain blessed in its original class. For non-blocking sockets you better just upgrade the socket to IO::Socket::SSL and call accept_SSL or connect_SSL and the upgraded object. To just upgrade the socket set B explicitly to 0. If you call start_SSL w/o this parameter it will revert to blocking behavior for accept_SSL and connect_SSL. If given the parameter "Timeout" it will stop if after the timeout no SSL connection was established. This parameter is only used for blocking sockets, if it is not given the default Timeout from the underlying IO::Socket will be used. =item B This is the opposite of start_SSL(), e.g. it will shutdown the SSL connection and return to the class before start_SSL(). It gets the same arguments as close(), in fact close() calls stop_SSL() (but without downgrading the class). Will return true if it succeeded and undef if failed. This might be the case for non-blocking sockets. In this case $! is set to EAGAIN and the ssl error to SSL_WANT_READ or SSL_WANT_WRITE. In this case the call should be retried again with the same arguments once the socket is ready. For calling from C C default to false, e.g. it waits for the close_notify of the peer. This is necesarry in case you want to downgrade the socket and continue to use it as a plain socket. =item B<< IO::Socket::SSL->new_from_fd($fd, [mode], %sslargs) >> This will convert a socket identified via a file descriptor into an SSL socket. Note that the argument list does not include a "MODE" argument; if you supply one, it will be thoughtfully ignored (for compatibility with IO::Socket::INET). Instead, a mode of '+<' is assumed, and the file descriptor passed must be able to handle such I/O because the initial SSL handshake requires bidirectional communication. Internally the given $fd will be upgraded to a socket object using the C method of the super class (L or similar) and then C will be called using the given C<%sslargs>. If C<$fd> is already an IO::Socket object you should better call C directly. =item B You may use this to make IO::Socket::SSL automatically re-use a given context (unless specifically overridden in a call to new()). It accepts one argument, which should be either an IO::Socket::SSL object or an IO::Socket::SSL::SSL_Context object. See the SSL_reuse_ctx option of new() for more details. Note that this sets the default context globally, so use with caution (esp. in mod_perl scripts). =item B You may use this to make IO::Socket::SSL automatically re-use a given session cache (unless specifically overridden in a call to new()). It accepts one argument, which should be an IO::Socket::SSL::Session_Cache object or similar (e.g something which implements get_session and add_session like IO::Socket::SSL::Session_Cache does). See the SSL_session_cache option of new() for more details. Note that this sets the default cache globally, so use with caution. =item B With this function one can set defaults for all SSL_* parameter used for creation of the context, like the SSL_verify* parameter. =over 8 =item mode - set default SSL_verify_mode =item callback - set default SSL_verify_callback =item scheme - set default SSL_verifycn_scheme =item name - set default SSL_verifycn_name If not given and scheme is hash reference with key callback it will be set to 'unknown' =back =item B Similar to C, but only sets the defaults for client mode. =item B Similar to C, but only sets the defaults for server mode. =back The following methods are unsupported (not to mention futile!) and IO::Socket::SSL will emit a large CROAK() if you are silly enough to use them: =over 4 =item truncate =item stat =item ungetc =item setbuf =item setvbuf =item fdopen =item send/recv Note that send() and recv() cannot be reliably trapped by a tied filehandle (such as that used by IO::Socket::SSL) and so may send unencrypted data over the socket. Object-oriented calls to these functions will fail, telling you to use the print/printf/syswrite and read/sysread families instead. =back =head2 Defaults for Cert, Key and CA Only if no SSL_key*, no SSL_cert* and no SSL_ca* options are given it will fall back to the following builtin defaults: =over 4 =item SSL_cert_file Depending on the SSL_server setting it will be either C or C. =item SSL_key_file Depending on the SSL_server setting it will be either C or C. =item SSL_ca_file | SSL_ca_path It will set SSL_ca_file to C if it exist. Otherwise it will set SSL_ca_path to C if it exist. =back B, e.g. you should specify all the certificates and keys you use. If you don't specify a CA file or path it will fall back to the system default built into OpenSSL. =head1 ERROR HANDLING If an SSL specific error occurs the global variable C<$SSL_ERROR> will be set. If the error occurred on an existing SSL socket the method C will give access to the latest socket specific error. Both C<$SSL_ERROR> and C method give a dualvar similar to C<$!>, e.g. providing an error number in numeric context or an error description in string context. =head1 Polling of SSL Sockets (e.g. select, poll and other event loops) If you sysread one byte on a normal socket it will result in a syscall to read one byte. Thus, if more than one byte is available on the socket it will be kept in the network stack of your OS and the next select or poll call will return the socket as readable. But, with SSL you don't deliver single bytes. Multiple data bytes are packet and encrypted together in an SSL frame. Decryption can only be done on the whole frame, so a sysread for one byte actually reads the complete SSL frame from the socket, decrypts it and returns the first decrypted byte. Further sysreads will return more bytes from the same frame until all bytes are returned and the next SSL frame will be read from the socket. Thus, in order to decide if you can read more data (e.g. if sysread will block) you must check, if there are still data in the current SSL frame by calling C and if there are no data pending you might check the underlying socket with select or poll. Another way might be if you try to sysread at least 16k all the time. 16k is the maximum size of an SSL frame and because sysread returns data from only a single SSL frame you guarantee this way, that there are no pending data. Please see the example on top of this documentation on how to use SSL within a select loop. =head1 Non-blocking I/O If you have a non-blocking socket, the expected behavior on read, write, accept or connect is to set C<$!> to EAGAIN if the operation can not be completed immediately. With SSL handshakes might occure at any time, even within an established connections. In this cases it is necessary to finish the handshake, before you can read or write data. This might result in situations, where you want to read but must first finish the write of a handshake or where you want to write but must first finish a read. In these cases C<$!> is set to EGAIN like expected, and additionally C<$SSL_ERROR> is set to either SSL_WANT_READ or SSL_WANT_WRITE. Thus if you get EAGAIN on a SSL socket you must check C<$SSL_ERROR> for SSL_WANT_* and adapt your event mask accordingly. Using readline on non-blocking sockets does not make much sense and I would advise against using it. And, while the behavior is not documented for other L classes, it will try to emulate the behavior seen there, e.g. to return the received data instead of blocking, even if the line is not complete. If an unrecoverable error occurs it will return nothing, even if it already received some data. Also, I would advise against using C with a non-blocking SSL object, because it might block and this is not what most would expect. The reason for this is that accept on a non-blocking TCP socket (e.g. IO::Socket::IP, IO::Socket::INET..) results in a new TCP socket, which does not inherit the non-blocking behavior of the master socket. And thus the initial SSL handshake on the new socket inside C will be done in a blocking way. To work around it you should better do an TCP accept and later upgrade the TCP socket in a non-blocking way with C and C. =head1 SNI Support Newer extensions to SSL can distinguish between multiple hostnames on the same IP address using Server Name Indication (SNI). Support for SNI on the client side was added somewhere in the OpenSSL 0.9.8 series, but only with 1.0 a bug was fixed when the server could not decide about its hostname. Therefore client side SNI is only supported with OpenSSL 1.0 or higher in L. With a supported version, SNI is used automatically on the client side, if it can determine the hostname from C or C. On unsupported OpenSSL versions it will silently not use SNI. The hostname can also be given explicitly given with C, but in this case it will throw in error, if SNI is not supported. To check for support you might call Ccan_client_sni()>. On the server side earlier versions of OpenSSL are supported, but only together with L version >= 1.50. To check for support you might call Ccan_server_sni()>. If server side SNI is supported, you might specify different certificates per host with C and C, and check the requested name using C. =head1 RETURN VALUES A few changes have gone into IO::Socket::SSL v0.93 and later with respect to return values. The behavior on success remains unchanged, but for I functions, the return value on error is now an empty list. Therefore, the return value will be false in all contexts, but those who have been using the return values as arguments to subroutines (like Cnew, ...)>) may run into problems. The moral of the story: I check the return values of these functions before using them in any way that you consider meaningful. =head1 DEBUGGING If you are having problems using IO::Socket::SSL despite the fact that can recite backwards the section of this documentation labelled 'Using SSL', you should try enabling debugging. To specify the debug level, pass 'debug#' (where # is a number from 0 to 3) to IO::Socket::SSL when calling it. The debug level will also be propagated to Net::SSLeay::trace, see also L: =over 4 =item use IO::Socket::SSL qw(debug0); No debugging (default). =item use IO::Socket::SSL qw(debug1); Print out errors from IO::Socket::SSL and ciphers from Net::SSLeay. =item use IO::Socket::SSL qw(debug2); Print also information about call flow from IO::Socket::SSL and progress information from Net::SSLeay. =item use IO::Socket::SSL qw(debug3); Print also some data dumps from IO::Socket::SSL and from Net::SSLeay. =back =head1 EXAMPLES See the 'example' directory. =head1 BUGS IO::Socket::SSL depends on Net::SSLeay. Up to version 1.43 of Net::SSLeay it was not thread safe, although it did probably work if you did not use SSL_verify_callback and SSL_password_cb. If you use IO::Socket::SSL together with threads you should load it (e.g. use or require) inside the main thread before creating any other threads which use it. This way it is much faster because it will be initialized only once. Also there are reports that it might crash the other way. Creating an IO::Socket::SSL object in one thread and closing it in another thread will not work. IO::Socket::SSL does not work together with Storable::fd_retrieve/fd_store. See BUGS file for more information and how to work around the problem. Non-blocking and timeouts (which are based on non-blocking) are not supported on Win32, because the underlying IO::Socket::INET does not support non-blocking on this platform. If you have a server and it looks like you have a memory leak you might check the size of your session cache. Default for Net::SSLeay seems to be 20480, see the example for SSL_create_ctx_callback for how to limit it. The default for SSL_verify_mode on the client is currently SSL_VERIFY_NONE, which is a very bad idea, thus the default will change in the near future. See documentation for SSL_verify_mode for more information. =head1 LIMITATIONS IO::Socket::SSL uses Net::SSLeay as the shiny interface to OpenSSL, which is the shiny interface to the ugliness of SSL. As a result, you will need both Net::SSLeay and OpenSSL on your computer before using this module. If you have Scalar::Util (standard with Perl 5.8.0 and above) or WeakRef, IO::Socket::SSL sockets will auto-close when they go out of scope, just like IO::Socket::INET sockets. If you do not have one of these modules, then IO::Socket::SSL sockets will stay open until the program ends or you explicitly close them. This is due to the fact that a circular reference is required to make IO::Socket::SSL sockets act simultaneously like objects and glob references. =head1 DEPRECATIONS The following functions are deprecated and are only retained for compatibility: =over 2 =item context_init() use the SSL_reuse_ctx option if you want to re-use a context =item socketToSSL() and socket_to_SSL() use IO::Socket::SSL->start_SSL() instead =item kill_socket() use close() instead =item get_peer_certificate() use the peer_certificate() function instead. Used to return X509_Certificate with methods subject_name and issuer_name. Now simply returns $self which has these methods (although deprecated). =item issuer_name() use peer_certificate( 'issuer' ) instead =item subject_name() use peer_certificate( 'subject' ) instead =back =head1 SEE ALSO IO::Socket::INET, IO::Socket::INET6, IO::Socket::IP, Net::SSLeay. =head1 AUTHORS Steffen Ullrich, is the current maintainer. Peter Behroozi, (Note the lack of an "i" at the end of "behrooz") Marko Asplund, , was the original author of IO::Socket::SSL. Patches incorporated from various people, see file Changes. =head1 COPYRIGHT The original versions of this module are Copyright (C) 1999-2002 Marko Asplund. The rewrite of this module is Copyright (C) 2002-2005 Peter Behroozi. Versions 0.98 and newer are Copyright (C) 2006-2013 Steffen Ullrich. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 Appendix: Using SSL If you are unfamiliar with the way OpenSSL works, good references may be found in both the book "Network Security with OpenSSL" (Oreilly & Assoc.) and the web site L. Read on for a quick overview. =head2 The Long of It (Detail) The usual reason for using SSL is to keep your data safe. This means that not only do you have to encrypt the data while it is being transported over a network, but you also have to make sure that the right person gets the data, e.g. you need to authenticate the person. To accomplish this with SSL, you have to use certificates. A certificate closely resembles a Government-issued ID (at least in places where you can trust them). The ID contains some sort of identifying information such as a name and address, and is usually stamped with a seal of Government Approval. Theoretically, this means that you may trust the information on the card and do business with the owner of the card. The same ideas apply to SSL certificates, which have some identifying information and are "stamped" (signed) by someone (a CA, e.g. Certificate Authority) who you trust will adequately verify the identifying information. In this case, because of some clever number theory, it is extremely difficult to falsify the signing process. Another useful consequence of number theory is that the certificate is linked to the encryption process, so you may encrypt data (using information on the certificate) that only the certificate owner can decrypt. What does this mean for you? So most common case is that at least the server has a certificate which the client can verify, but the server may also ask back for a certificate to authenticate the client. To verify that a certificate is trusted, one checks if the certificate is signed by the expected CA (Certificate Authority), which often means any CA installed on the system (IO::Socket::SSL tries to use the CAs installed on the system by default). So if you trust the CA, trust the number theory and trust the used algorithms you can be confident, that no-one is reading your data. Beside the authentication using certificates there is also anonymous authentication, which effectivly means no authentication. In this case it is easy for somebody in between to intercept the connection, e.g. playing man in the middle and nobody notices. By default IO::Socket::SSL uses only ciphers which require certificates and which are safe enough, but if you want to set your own cipher_list make sure, that you explicitly exclude anonymous authentication. E.g. setting the cipher list to HIGH is not enough, you should use at least HIGH:!aNULL. =head2 The Short of It (Summary) For servers, you will need to generate a cryptographic private key and a certificate request. You will need to send the certificate request to a Certificate Authority to get a real certificate back, after which you can start serving people. For clients, you will not need anything unless the server wants validation, in which case you will also need a private key and a real certificate. For more information about how to get these, see L. =cut IO-Socket-SSL-1.965/lib/IO/Socket/SSL/0000755000175100017520000000000012265775222015443 5ustar workworkIO-Socket-SSL-1.965/lib/IO/Socket/SSL/Utils.pm0000644000175100017520000002411312263174431017073 0ustar workwork package IO::Socket::SSL::Utils; use strict; use warnings; use Carp 'croak'; use Net::SSLeay; use Time::Local; use Exporter 'import'; our $VERSION = '0.02'; our @EXPORT = qw( PEM_file2cert PEM_string2cert PEM_cert2file PEM_cert2string PEM_file2key PEM_string2key PEM_key2file PEM_key2string KEY_free CERT_free KEY_create_rsa CERT_asHash CERT_create ); sub PEM_file2cert { my $file = shift; my $bio = Net::SSLeay::BIO_new_file($file,'r') or croak "cannot read $file: $!"; my $cert = Net::SSLeay::PEM_read_bio_X509($bio); Net::SSLeay::BIO_free($bio); $cert or croak "cannot parse $file as PEM X509 cert: ". Net::SSLeay::ERR_error_string(Net::SSLeay::ERR_get_error()); return $cert; } sub PEM_cert2file { my ($cert,$file) = @_; my $string = Net::SSLeay::PEM_get_string_X509($cert) or croak("cannot get string from cert"); open( my $fh,'>',$file ) or croak("cannot write $file: $!"); print $fh $string; } sub PEM_string2cert { my $string = shift; my $bio = Net::SSLeay::BIO_new( Net::SSLeay::BIO_s_mem()); Net::SSLeay::BIO_write($bio,$string); my $cert = Net::SSLeay::PEM_read_bio_X509($bio); Net::SSLeay::BIO_free($bio); $cert or croak "cannot parse string as PEM X509 cert: ". Net::SSLeay::ERR_error_string(Net::SSLeay::ERR_get_error()); return $cert; } sub PEM_cert2string { my $cert = shift; return Net::SSLeay::PEM_get_string_X509($cert) || croak("cannot get string from cert"); } sub PEM_file2key { my $file = shift; my $bio = Net::SSLeay::BIO_new_file($file,'r') or croak "cannot read $file: $!"; my $cert = Net::SSLeay::PEM_read_bio_PrivateKey($bio); Net::SSLeay::BIO_free($bio); $cert or croak "cannot parse $file as PEM private key: ". Net::SSLeay::ERR_error_string(Net::SSLeay::ERR_get_error()); return $cert; } sub PEM_key2file { my ($key,$file) = @_; my $string = Net::SSLeay::PEM_get_string_PrivateKey($key) or croak("cannot get string from key"); open( my $fh,'>',$file ) or croak("cannot write $file: $!"); print $fh $string; } sub PEM_string2key { my $string = shift; my $bio = Net::SSLeay::BIO_new( Net::SSLeay::BIO_s_mem()); Net::SSLeay::BIO_write($bio,$string); my $cert = Net::SSLeay::PEM_read_bio_PrivateKey($bio); Net::SSLeay::BIO_free($bio); $cert or croak "cannot parse string as PEM private key: ". Net::SSLeay::ERR_error_string(Net::SSLeay::ERR_get_error()); return $cert; } sub PEM_key2string { my $key = shift; return Net::SSLeay::PEM_get_string_PrivateKey($key) || croak("cannot get string from key"); } sub CERT_free { my $cert = shift or return; Net::SSLeay::X509_free($cert); } sub KEY_free { my $key = shift or return; Net::SSLeay::EVP_KEY_free($key); } sub KEY_create_rsa { my $bits = shift || 1024; my $key = Net::SSLeay::EVP_PKEY_new(); my $rsa = Net::SSLeay::RSA_generate_key(1024, 0x10001); # 0x10001 = RSA_F4 Net::SSLeay::EVP_PKEY_assign_RSA($key,$rsa); return $key; } # extract information from cert my %gen2i = qw( OTHERNAME 0 EMAIL 1 DNS 2 X400 3 DIRNAME 4 EDIPARTY 5 URI 6 IP 7 RID 8 ); my %i2gen = reverse %gen2i; sub CERT_asHash { my $cert = shift; my %hash = ( version => Net::SSLeay::X509_get_version($cert), not_before => _asn1t2t(Net::SSLeay::X509_get_notBefore($cert)), not_after => _asn1t2t(Net::SSLeay::X509_get_notAfter($cert)), serial => Net::SSLeay::ASN1_INTEGER_get( Net::SSLeay::X509_get_serialNumber($cert)), ); my $subj = Net::SSLeay::X509_get_subject_name($cert); my %subj; for ( 0..Net::SSLeay::X509_NAME_entry_count($subj)-1 ) { my $e = Net::SSLeay::X509_NAME_get_entry($subj,$_); my $o = Net::SSLeay::X509_NAME_ENTRY_get_object($e); $subj{ Net::SSLeay::OBJ_obj2txt($o) } = Net::SSLeay::P_ASN1_STRING_get( Net::SSLeay::X509_NAME_ENTRY_get_data($e)); } $hash{subject} = \%subj; if ( my @names = Net::SSLeay::X509_get_subjectAltNames($cert) ) { my $alt = $hash{subjectAltNames} = []; while (my ($t,$v) = splice(@names,0,2)) { $t = $i2gen{$t} || die "unknown type $t in subjectAltName"; if ( $t eq 'IP' ) { if (length($v) == 4) { $v = join('.',unpack("CCCC",$v)); } elsif ( length($v) == 16 ) { $v = join(':',map { sprintf( "%x",$_) } unpack("NNNN",$v)); } } push @$alt,[$t,$v] } } return \%hash; } my $sha1_digest; sub CERT_create { my %args = @_%2 ? %{ shift() } : @_; my $cert = Net::SSLeay::X509_new(); $sha1_digest ||= do { Net::SSLeay::SSLeay_add_ssl_algorithms(); Net::SSLeay::EVP_get_digestbyname("sha1") or die "SHA1 not available"; }; Net::SSLeay::ASN1_INTEGER_set( Net::SSLeay::X509_get_serialNumber($cert), delete $args{serial} || rand(2**32), ); # version default to 2 (V3) Net::SSLeay::X509_set_version($cert, delete $args{version} || 2 ); # not_before default to now Net::SSLeay::ASN1_TIME_set( Net::SSLeay::X509_get_notBefore($cert), delete $args{not_before} || time() ); # not_after default to now+365 days Net::SSLeay::ASN1_TIME_set( Net::SSLeay::X509_get_notAfter($cert), delete $args{not_after} || time() + 365*86400 ); # set subject my $subj_e = Net::SSLeay::X509_get_subject_name($cert); my $subj = delete $args{subject} || { organizationName => 'IO::Socket::SSL', commonName => 'IO::Socket::SSL Test' }; while ( my ($k,$v) = each %$subj ) { # 0x1000 = MBSTRING_UTF8 Net::SSLeay::X509_NAME_add_entry_by_txt($subj_e, $k, 0x1000, $v, -1, 0) or croak("failed to add entry for $k - ". Net::SSLeay::ERR_error_string(Net::SSLeay::ERR_get_error())); } my @ext = ( &Net::SSLeay::NID_subject_key_identifier => 'hash', &Net::SSLeay::NID_authority_key_identifier => 'keyid', &Net::SSLeay::NID_authority_key_identifier => 'issuer', ); if ( my $altsubj = delete $args{subjectAltNames} ) { push @ext, &Net::SSLeay::NID_subject_alt_name => join(',', map { "$_->[0]:$_->[1]" } @$altsubj) } my $key = delete $args{key} || KEY_create_rsa(); Net::SSLeay::X509_set_pubkey($cert,$key); my $issuer_cert = delete $args{issuer_cert}; my $issuer_key = delete $args{issuer_key}; if ( delete $args{CA} ) { $issuer_cert ||= $cert; $issuer_key ||= $key; push @ext, &Net::SSLeay::NID_basic_constraints => 'CA:TRUE', } else { $issuer_cert || croak "no issuer_cert given"; $issuer_key || croak "no issuer_key given"; push @ext, &Net::SSLeay::NID_key_usage => 'digitalSignature,keyEncipherment', &Net::SSLeay::NID_basic_constraints => 'CA:FALSE', &Net::SSLeay::NID_ext_key_usage => 'serverAuth,clientAuth', &Net::SSLeay::NID_netscape_cert_type => 'server'; } Net::SSLeay::P_X509_add_extensions($cert, $issuer_cert, @ext); Net::SSLeay::X509_set_issuer_name($cert, Net::SSLeay::X509_get_subject_name($issuer_cert)); Net::SSLeay::X509_sign($cert,$issuer_key,$sha1_digest); return ($cert,$key); } my %mon2i = qw( Jan 0 Feb 1 Mar 2 Apr 3 May 4 Jun 5 Jul 6 Aug 7 Sep 8 Oct 9 Nov 10 Dec 11 ); sub _asn1t2t { my $t = Net::SSLeay::P_ASN1_TIME_put2string( shift ); my ($mon,$d,$h,$m,$s,$y) = split(/[\s:]+/,$t); defined( $mon = $mon2i{$mon} ) or die "invalid month in $t"; my $tz = $y =~s{^(\d+)([A-Z]\S*)}{$1} && $2; if ( ! $tz ) { return timelocal($s,$m,$h,$d,$mon,$y) } elsif ( $tz eq 'GMT' ) { return timegm($s,$m,$h,$d,$mon,$y) } else { die "unexpected TZ $tz from ASN1_TIME_print"; } } 1; __END__ =head1 NAME IO::Socket::SSL::Utils -- loading, storing, creating certificates and keys =head1 SYNOPSIS use IO::Socket::SSL::Utils; my $cert = PEM_file2cert('cert.pem'); my $string = PEM_cert2string($cert); CERT_free($cert); my $key = KEY_create_rsa(2048); PEM_string2file($key); KEY_free($key); =head1 DESCRIPTION This module provides various utility functions to work with certificates and private keys, shielding some of the complexity of the underlying Net::SSLeay and OpenSSL. =head1 FUNCTIONS =over 4 =item * Functions converting between string or file and certificates and keys. They croak if the operation cannot be completed. =over 8 =item PEM_file2cert(file) -> cert =item PEM_cert2file(cert,file) =item PEM_string2cert(string) -> cert =item PEM_cert2string(cert) -> string =item PEM_file2key(file) -> key =item PEM_key2file(key,file) =item PEM_string2key(string) -> key =item PEM_key2string(key) -> string =back =item * Functions for cleaning up. Each loaded or created cert and key must be freed to not leak memory. =over 8 =item CERT_free(cert) =item KEY_free(key) =back =item * KEY_create_rsa(bits) -> key Creates an RSA key pair, bits defaults to 1024. =item * CERT_asHash(cert) -> hash Extracts the information from the certificate into a hash: =over 8 =item serial The serial number =item version Certificate version, usually 2 (x509v3) =item subject Hash with the parts of the subject, e.g. commonName, countryName, organizationName, stateOrProvinceName, localityName. =item subjectAltNames Array with list of alternative names. Each entry in the list is of C<[type,value]>, where C can be OTHERNAME, EMAIL, DNS, X400, DIRNAME, EDIPARTY, URI, IP or RID. =item not_before, not_after The time frame, where the certificate is valid, as time_t, e.g. can be converted with localtime or similar functions. =back =item * CERT_create(hash) -> (cert,key) Creates a certificate based on the given hash. Additionally to the information described in C the following keys can be given: =over 8 =item CA true|false if true declare certificate as CA, defaults to false =item key key use given key as key for certificate, otherwise a new one will be generated and returned =item issuer_cert cert set issuer for new certificate =item issuer_key key sign new certificate with given key =back If not all necessary information are given some will have usable defaults, e.g. =over 8 =item not_before defaults to the current time =item not_after defaults to 365 days in the future =item subject has a default pointing to IO::Socket::SSL =item version defaults to 2 (x509v3) =item serial will be a random number =back =back =head1 AUTHOR Steffen Ullrich IO-Socket-SSL-1.965/lib/IO/Socket/SSL/Intercept.pm0000644000175100017520000002406612263174431017737 0ustar workwork package IO::Socket::SSL::Intercept; use strict; use warnings; use Carp 'croak'; use IO::Socket::SSL::Utils; use Net::SSLeay; our $VERSION = '1.93'; sub new { my ($class,%args) = @_; my $cacert = delete $args{proxy_cert}; if ( ! $cacert ) { if ( my $f = delete $args{proxy_cert_file} ) { $cacert = PEM_file2cert($f); } else { croak "no proxy_cert or proxy_cert_file given"; } } my $cakey = delete $args{proxy_key}; if ( ! $cakey ) { if ( my $f = delete $args{proxy_key_file} ) { $cakey = PEM_file2key($f); } else { croak "no proxy_cert or proxy_cert_file given"; } } my $certkey = delete $args{cert_key}; if ( ! $certkey ) { if ( my $f = delete $args{cert_key_file} ) { $certkey = PEM_file2key($f); } } my $cache = delete $args{cache} || {}; my $self = bless { cacert => $cacert, cakey => $cakey, certkey => $certkey, serial => delete $args{serial} || 1, cache => $cache, }; return $self; } sub DESTROY { # call various ssl _free routines my $self = shift or return; for ( \$self->{cacert}, map { \$_->{cert} } ref($self->{cache}) ne 'CODE' ? values %{$self->{cache}} :()) { $$_ or next; CERT_free($$_); $$_ = undef; } for ( \$self->{cakey}, \$self->{pubkey} ) { $$_ or next; KEY_free($$_); $$_ = undef; } } sub clone_cert { my ($self,$old_cert,$clone_key) = @_; $clone_key ||= substr(unpack("H*",Net::SSLeay::X509_get_fingerprint($old_cert,'sha1')),0,16); if ( my ($clone,$key) = _get_cached($self,$clone_key)) { return ($clone,$key); } # create new certificate based on original my ($clone,$key) = CERT_create( %{ CERT_asHash($old_cert) }, serial => $self->{serial}++, issuer_cert => $self->{cacert}, issuer_key => $self->{cakey}, key => $self->{certkey}, ); # put into cache _set_cached($self,$clone_key,$clone,$key); return ($clone,$key); } sub _get_cached { my ($self,$clone_key) = @_; my $c = $self->{cache}; return $c->($clone_key) if ref($c) eq 'CODE'; my $e = $c->{$clone_key} or return; $e->{atime} = time(); return ($e->{cert},$e->{key} || $self->{certkey}); } sub _set_cached { my ($self,$clone_key,$cert,$key) = @_; my $c = $self->{cache}; return $c->($clone_key,$cert,$key) if ref($c) eq 'CODE'; $c->{$clone_key} = { cert => $cert, $self->{certkey} && $self->{certkey} == $key ? () : ( key => $key ), atime => time() }; } sub STORABLE_freeze { my $self = shift; $self->serialize() } sub STORABLE_thaw { my ($class,undef,$data) = @_; $class->unserialize($data) } sub serialize { my $self = shift; my $data = pack("N",2); # version $data .= pack("N/a", PEM_cert2string($self->{cacert})); $data .= pack("N/a", PEM_key2string($self->{cakey})); if ( $self->{certkey} ) { $data .= pack("N/a", PEM_key2string($self->{certkey})); } else { $data .= pack("N/a", ''); } $data .= pack("N",$self->{serial}); if ( ref($self->{cache}) eq 'HASH' ) { while ( my($k,$v) = each %{ $self->{cache}} ) { $data .= pack("N/aN/aN/aN", $k, PEM_cert2string($k->{cert}), $k->{key} ? PEM_key2string($k->{key}) : '', $k->{atime}); } } return $data; } sub unserialize { my ($class,$data) = @_; unpack("N",substr($data,0,4,'')) == 2 or croak("serialized with wrong version"); ( my $cacert,my $cakey,my $certkey,my $serial,$data) = unpack("N/aN/aN/aNa*",$data); my $self = bless { serial => $serial, cacert => PEM_string2cert($cacert), cakey => PEM_string2key($cakey), $certkey ? ( certkey => PEM_string2key($certkey)):(), }, ref($class)||$class; $self->{cache} = {} if $data ne ''; while ( $data ne '' ) { (my $key,my $cert,my $certkey, my $atime,$data) = unpack("N/aN/aNa*",$data); $self->{cache}{$key} = { cert => PEM_string2cert($cert), $key ? ( key => PEM_string2key($certkey)):(), atime => $atime }; } return $self; } 1; __END__ =head1 NAME IO::Socket::SSL::Intercept -- SSL interception (man in the middle) =head1 SYNOPSIS use IO::Socket::SSL::Intercept; # create interceptor with proxy certificates my $mitm = IO::Socket::SSL::Intercept->new( proxy_cert_file => 'proxy_cert.pem', proxy_key_file => 'proxy_key.pem', ... ); my $listen = IO::Socket::INET->new( LocalAddr => .., Listen => .. ); while (1) { # TCP accept new client my $client = $listen->accept or next; # SSL connect to server my $server = IO::Socket::SSL->new( PeerAddr => .., SSL_verify_mode => ..., ... ) or die "ssl connect failed: $!,$SSL_ERROR"; # clone server certificate my ($cert,$key) = $mitm->clone_cert( $server->peer_certificate ); # and upgrade client side to SSL with cloned certificate IO::Socket::SSL->start_SSL($client, SSL_server => 1, SSL_cert => $cert, SSL_key => $key ) or die "upgrade failed: $SSL_ERROR"; # now transfer data between $client and $server and analyze # the unencrypted data ... } =head1 DESCRIPTION This module provides functionality to clone certificates and sign them with a proxy certificate, thus making it easy to intercept SSL connections (man in the middle). It also manages a cache of the generated certificates. =head1 How Intercepting SSL Works Intercepting SSL connections is useful for analyzing encrypted traffic for security reasons or for testing. It does not break the end-to-end security of SSL, e.g. a properly written client will notice the interception unless you explicitly configure the client to trust your interceptor. Intercepting SSL works the following way: =over 4 =item * Create a new CA certificate, which will be used to sign the cloned certificates. This proxy CA certificate should be trusted by the client, or (a properly written client) will throw error messages or deny the connections because it detected a man in the middle attack. Due to the way the interception works there no support for client side certificates is possible. Using openssl such a proxy CA certificate and private key can be created with: openssl genrsa -out proxy_key.pem 1024 openssl req -new -x509 -extensions v3_ca -key proxy_key.pem -out proxy_cert.pem # export as PKCS12 for import into browser openssl pkcs12 -export -in proxy_cert.pem -inkey proxy_key.pem -out proxy_cert.p12 =item * Configure client to connect to use intercepting proxy or somehow redirect connections from client to the proxy (e.g. packet filter redirects, ARP or DNS spoofing etc). =item * Accept the TCP connection from the client, e.g. don't do any SSL handshakes with the client yet. =item * Establish the SSL connection to the server and verify the servers certificate as usually. Then create a new certificate based on the original servers certificate, but signed by your proxy CA. This a the step where IO::Socket::SSL::Intercept helps. =item * Upgrade the TCP connection to the client to SSL using the cloned certificate from the server. If the client trusts your proxy CA it will accept the upgrade to SSL. =item * Transfer data between client and server. While the connections to client and server are both encrypted with SSL you will read/write the unencrypted data in your proxy application. =back =head1 METHODS IO::Socket::SSL::Intercept helps creating the cloned certificate with the following methods: =over 4 =item B<< $mitm = IO::Socket::SSL::Intercept->new(%args) >> This creates a new interceptor object. C<%args> should be =over 8 =item proxy_cert X509 | proxy_cert_file filename This is the proxy certificate. It can be either given by an X509 object from Ls internal representation, or using a file in PEM format. =item proxy_key EVP_PKEY | proxy_key_file filename This is the key for the proxy certificate. It can be either given by an EVP_PKEY object from Ls internal representation, or using a file in PEM format. The key should not have a passphrase. =item pubkey EVP_PKEY | pubkey_file filename This optional argument specifies the public key used for the cloned certificate. It can be either given by an EVP_PKEY object from Ls internal representation, or using a file in PEM format. If not given it will create a new public key on each call of C. =item serial INTEGER This optional argument gives the starting point for the serial numbers of the newly created certificates. Default to 1. =item cache HASH | SUBROUTINE This optional argument gives a way to cache created certificates, so that they don't get recreated on future accesses to the same host. If the argument ist not given an internal HASH ist used. If the argument is a hash it will store for each generated certificate a hash reference with C and C in the hash, where C is the time of last access (to expire unused entries) and C is the certificate. Please note, that the certificate is in Ls internal X509 format and can thus not be simply dumped and restored. The key for the hash is an C either given to C or generated from the original certificate. If the argument is a subroutine it will be called as C<< $cache->(ident) >> to get an existing certificate and with C<< $cache->(ident,cert) >> to cache the newly created certificate. =back =item B<< ($clone_cert,$key) = $mitm->clone_cert($original_cert,[ $ident ]) >> This clones the given certificate. An ident as the key into the cache can be given (like C), if not it will be created from the properties of the original certificate. It returns the cloned certificate and its key (which is the same for alle created certificates). =item B<< $string = $mitm->serialize >> This creates a serialized version of the object (e.g. a string) which can then be used to persistantly store created certificates over restarts of the application. The cache will only be serialized if it is a HASH. To work together with L the C function is defined to call C. =item B<< $mitm = IO::Socket::SSL::Intercept->unserialize($string) >> This restores an Intercept object from a serialized string. To work together with L the C function is defined to call C. =back =head1 AUTHOR Steffen Ullrich IO-Socket-SSL-1.965/t/0000755000175100017520000000000012265775222012740 5ustar workworkIO-Socket-SSL-1.965/t/memleak_bad_handshake.t0000644000175100017520000000376212263174431017355 0ustar workwork#!perl # Before `make install' is performed this script should be runnable with # `make test'. After `make install' it should work as `perl t/nonblock.t' use strict; use warnings; use Net::SSLeay; use Socket; use IO::Socket::SSL; use IO::Select; use Errno qw(EAGAIN EINPROGRESS ); if ( grep { $^O =~m{$_}i } qw( MacOS VOS vmesa riscos amigaos mswin32) ) { print "1..0 # Skipped: ps not implemented on this platform\n"; exit } if ( $^O =~m{aix}i ) { print "1..0 # Skipped: might hang, see https://rt.cpan.org/Ticket/Display.html?id=72170\n"; exit } $|=1; if ( ! getsize($$) ) { print "1..0 # Skipped: no usable ps\n"; exit; } my $server = IO::Socket::SSL->new( LocalAddr => '127.0.0.1', LocalPort => 0, Listen => 200, SSL_cert_file => 'certs/server-cert.pem', SSL_key_file => 'certs/server-key.pem', ); my $saddr = $server->sockhost.':'.$server->sockport; defined( my $pid = fork()) or die "fork failed: $!"; if ( $pid == 0 ) { # server while (1) { # socket accept, client handshake and client close $server->accept; } exit(0); } close($server); # plain non-SSL connect and close w/o sending data for(1..100) { IO::Socket::INET->new( $saddr ) or next; } my $size100 = getsize($pid); if ( ! $size100 ) { print "1..0 # Skipped: cannot get size of child process\n"; goto done; } for(100..200) { IO::Socket::INET->new( $saddr ) or next; } my $size200 = getsize($pid); for(200..300) { IO::Socket::INET->new( $saddr ) or next; } my $size300 = getsize($pid); if ($size100>$size200 or $size200<$size300) {; print "1..0 # skipped - do we measure the right thing?\n"; goto done; } print "1..1\n"; print "not " if $size100 < $size200 and $size200 < $size300; print "ok # check memleak failed handshake ($size100,$size200,$size300)\n"; done: kill(9,$pid); wait; exit; sub getsize { my $pid = shift; open( my $ps,'-|',"ps -o vsize -p $pid 2>/dev/null" ) or return; $ps && <$ps> or return; # header return int(<$ps>); # size } IO-Socket-SSL-1.965/t/core.t0000644000175100017520000002145512265775054014067 0ustar workwork#!perl # Before `make install' is performed this script should be runnable with # `make test'. After `make install' it should work as `perl t/core.t' use strict; use warnings; use Net::SSLeay; use Socket; use IO::Socket::SSL; use Errno 'EAGAIN'; $|=1; foreach ($^O) { if (/MacOS/ or /VOS/ or /vmesa/ or /riscos/ or /amigaos/) { print "1..0 # Skipped: fork not implemented on this platform\n"; exit; } } my $CAN_NONBLOCK = $^O =~m{mswin32}i ? 0 : eval "use 5.006; use IO::Select; 1"; my $CAN_PEEK = &Net::SSLeay::OPENSSL_VERSION_NUMBER >= 0x0090601f; my $numtests = 40; $numtests+=5 if $CAN_NONBLOCK; $numtests+=3 if $CAN_PEEK; my $expected_peer = do { my $us = IO::Socket::INET->new( LocalAddr => '127.0.0.1', Proto => 'udp' ); my $uc = IO::Socket::INET->new( PeerAddr => $us->sockhost, PeerPort => $us->sockport, Proto => 'udp' ) or do { print "1..0 # Skipped: cannot determine default peer IP\n"; exit }; $uc->sockhost, }; print "1..$numtests\n"; my $error_trapped = 0; my $server = IO::Socket::SSL->new( LocalAddr => '127.0.0.1', LocalPort => 0, Listen => 2, Timeout => 30, ReuseAddr => 1, SSL_verify_mode => 0x00, SSL_ca_file => "certs/test-ca.pem", SSL_use_cert => 1, SSL_cert_file => "certs/client-cert.pem", SSL_version => 'TLSv1', SSL_cipher_list => 'HIGH:!aNULL', SSL_error_trap => sub { my $self = shift; print $self "This server is SSL only"; $error_trapped = 1; $self->close; }, SSL_key_file => "certs/client-key.enc", SSL_passwd_cb => sub { return "opossum" } ); if (!$server) { print "not ok\n"; exit; } &ok("Server Initialization"); print "not " if (!defined fileno($server)); &ok("Server Fileno Check"); my $saddr = $server->sockhost.':'.$server->sockport; unless (fork) { close $server; my $client = IO::Socket::INET->new($saddr); print $client "Test\n"; (<$client> eq "This server is SSL only") || print "not "; &ok("Client non-SSL connection"); close $client; $client = IO::Socket::SSL->new( PeerAddr => $saddr, SSL_verify_mode => 0x01, SSL_ca_file => "certs/test-ca.pem", SSL_use_cert => 1, SSL_cert_file => "certs/server-cert.pem", SSL_version => 'TLSv1', SSL_cipher_list => 'HIGH', SSL_key_file => "certs/server-key.enc", SSL_passwd_cb => sub { return "bluebell" }, SSL_verify_callback => \&verify_sub, ); sub verify_sub { my ($ok, $ctx_store, $cert, $error) = @_; unless ($ok && $ctx_store && $cert && !$error) { print("not ok #client failure\n") && exit; } ($cert =~ /IO::Socket::SSL Demo CA/) || print "not"; &ok("Client Verify-sub Check"); return 1; } $client || (print("not ok #client failure\n") && exit); &ok("Client Initialization"); $client->fileno() || print "not "; &ok("Client Fileno Check"); # $client->untaint() if ($HAVE_SCALAR_UTIL); # In the future... $client->dump_peer_certificate() || print "not "; &ok("Client Peer Certificate Check"); $client->peer_certificate("issuer") || print "not "; &ok("Client Peer Certificate Issuer Check"); $client->get_cipher() || print "not "; &ok("Client Cipher Check"); $client->syswrite('00waaaanf00', 7, 2); if ($CAN_PEEK) { my $buffer; $client->read($buffer,2); print "not " if ($buffer ne 'ok'); &ok("Client Peek Check"); } $client->print("Test\n"); $client->printf("\$%.2f\n%d\n%c\n%s", 1.0444442342, 4.0, ord("y"), "Test\nBeaver\nBeaver\n"); shutdown($client, 1); my $buffer="\0\0aaaaaaaaaaaaaaaaaaaa"; $client->sysread($buffer, 7, 2); print "not " if ($buffer ne "\0\0waaaanf"); &ok("Client Sysread Check"); ## The future... # if ($HAVE_SCALAR_UTIL) { # print "not " if (is_tainted($buffer)); # &ok("client"); # } my @array = $client->getline(); print "not " if (@array != 1 or $array[0] ne "Test\n"); &ok("Client Getline Check"); print "not " if ($client->getc ne "\$"); &ok("Client Getc Check"); @array = $client->getlines; print "not " if (@array != 6); &ok("Client Getlines Check 1"); print "not " if ($array[0] != "1.04\n"); &ok("Client Getlines Check 2"); print "not " if ($array[1] ne "4\n"); &ok("Client Getlines Check 3"); print "not " if ($array[2] ne "y\n"); &ok("Client Getlines Check 4"); print "not " if (join("", @array[3..5]) ne "Test\nBeaver\nBeaver\n"); &ok("Client Getlines Check 5"); print "not " if (defined(<$client>)); &ok("Client Finished Reading Check"); $client->close(SSL_no_shutdown => 1); my $client_2 = IO::Socket::INET->new($saddr); print "not " if (!$client_2); &ok("Second Client Initialization"); $client_2 = IO::Socket::SSL->new_from_fd($client_2->fileno, '+<>', SSL_reuse_ctx => $client); print "not " if (!$client_2); &ok("Client Init from Fileno Check"); $buffer = <$client_2>; print "not " unless ($buffer eq "Boojums\n"); &ok("Client (fileno) Readline Check"); $client_2->close(SSL_ctx_free => 1); if ($CAN_NONBLOCK) { my $client_3 = IO::Socket::SSL->new( PeerAddr => $saddr, SSL_verify_mode => 0x01, SSL_version => 'TLSv1', SSL_cipher_list => 'HIGH', SSL_ca_file => "certs/test-ca.pem", SSL_use_cert => 1, SSL_cert_file => "certs/server-cert.pem", SSL_key_file => "certs/server-key.enc", SSL_passwd_cb => sub { return "bluebell" }, Blocking => 0, ); print "not " if (!$client_3); &ok("Client Nonblocking Check 1"); close $client_3; my $client_4 = IO::Socket::SSL->new( PeerAddr => $saddr, SSL_reuse_ctx => $client_3, Blocking => 0 ); print "not " if (!$client_4); &ok("Client Nonblocking Check 2"); $client_3->close(SSL_ctx_free => 1); } exit(0); } my $client = $server->accept; $error_trapped or print "not "; &ok("Server non-SSL Client Check"); if ($client && $client->opened) { print "not ok # client stayed alive!\n"; exit; } &ok("Server Kill-client Check"); ($client, my $peer) = $server->accept; if (!$client) { print "not ok # no client\n"; exit; } &ok("Server Client Accept Check"); print "not " unless defined $peer; &ok("Accept returning peer address check."); fileno($client) || print "not "; &ok("Server Client Fileno Check"); my $buffer; if ($CAN_PEEK) { $client->peek($buffer, 7, 2); print "not " if ($buffer ne "\0\0waaaanf"); &ok("Server Peek Check"); print "not " if ($client->pending() != 7); &ok("Server Pending Check"); print $client "ok"; } sysread($client, $buffer, 7, 2); print "not " if ($buffer ne "\0\0waaaanf"); &ok("Server Sysread Check"); my @array = scalar <$client>; print "not " if ($array[0] ne "Test\n"); &ok("Server Getline Check"); print "not " if (getc($client) ne "\$"); &ok("Server Getc Check"); @array = <$client>; print "not " if (@array != 6); &ok("Server Getlines Check 1"); print "not " if ($array[0] != "1.04\n"); &ok("Server Getlines Check 2"); print "not " if ($array[1] ne "4\n"); &ok("Server Getlines Check 3"); print "not " if ($array[2] ne "y\n"); &ok("Server Getlines Check 4"); print "not " if (join("", @array[3..5]) ne "Test\nBeaver\nBeaver\n"); &ok("Server Getlines Check 5"); syswrite($client, '00waaaanf00', 7, 2); print($client "Test\n"); printf $client "\$%.2f\n%d\n%c\n%s", (1.0444442342, 4.0, ord("y"), "Test\nBeaver\nBeaver\n"); close $client; ($client, $peer) = $server->accept; &bail unless $client; print "not " unless (inet_ntoa((unpack_sockaddr_in($peer))[1]) eq $expected_peer); &ok("Peer address check"); if ($CAN_NONBLOCK) { $client->blocking(0); $client->read($buffer, 20, 0); print "not " if $SSL_ERROR != SSL_WANT_READ; &ok("Server Nonblocking Check 1"); } print "not " unless ($client->opened); &ok("Server Client Opened Check 1"); print $client "Boojums\n"; close($client); ${*$client}{'_SSL_opened'} = 1; print "not " if ($client->opened); &ok("Server Client Opened Check 2"); ${*$client}{'_SSL_opened'} = 0; if ($CAN_NONBLOCK) { $client = $server->accept; print "not " if (!$client->opened); &ok("Server Nonblocking Check 2"); close $client; $server->blocking(0); IO::Select->new($server)->can_read(30); $client = $server->accept; while ( ! $client ) { #DEBUG( "$!,$SSL_ERROR" ); if ( $! == EAGAIN ) { if ( $SSL_ERROR == SSL_WANT_WRITE ) { IO::Select->new( $server->opening )->can_write(30); } else { IO::Select->new( $server->opening )->can_read(30); } } else { last } $client = $server->accept; } print "not " unless ($client && $client->opened); &ok("Server Nonblocking Check 3"); close $client; } $server->close(SSL_ctx_free => 1); wait; sub ok { print "ok #$_[0]\n"; } sub bail { print "Bail Out! $IO::Socket::SSL::ERROR"; } ## The future.... #sub is_tainted { # my $arg = shift; # my $nada = substr($arg, 0, 0); # local $@; # eval {eval "# $nada"}; # return length($@); #} IO-Socket-SSL-1.965/t/nonblock.t0000644000175100017520000002546312263174431014735 0ustar workwork#!perl # Before `make install' is performed this script should be runnable with # `make test'. After `make install' it should work as `perl t/nonblock.t' use strict; use warnings; use Net::SSLeay; use Socket; use IO::Socket::SSL; use IO::Select; use Errno qw( EAGAIN EINPROGRESS EPIPE ECONNRESET ); if ( ! eval "use 5.006; use IO::Select; return 1" ) { print "1..0 # Skipped: no support for nonblocking sockets\n"; exit; } if ( grep { $^O =~m{$_} } qw( MacOS VOS vmesa riscos amigaos ) ) { print "1..0 # Skipped: fork not implemented on this platform\n"; exit } if ( $^O =~m{mswin32}i ) { print "1..0 # Skipped: nonblocking does not work on Win32\n"; exit } $SIG{PIPE} = 'IGNORE'; # use EPIPE not signal handler $|=1; print "1..27\n"; # first create simple non-blocking tcp-server my $ID = 'server'; my $server = IO::Socket::INET->new( Blocking => 0, LocalAddr => '127.0.0.1', LocalPort => 0, Listen => 2, ); print "not ok: $!\n", exit if !$server; # Address in use? ok("Server Initialization"); my $saddr = $server->sockhost.':'.$server->sockport; my $ssock = $server->sockname; defined( my $pid = fork() ) || die $!; if ( $pid == 0 ) { ############################################################ # CLIENT == child process ############################################################ close($server); $ID = 'client'; # fast: try connect_SSL immediatly after sending plain text # connect_SSL should fail on the first attempt because server # is not ready yet # slow: wait before calling connect_SSL # connect_SSL should succeed, because server was already waiting for my $test ( 'fast','slow' ) { # initial socket is unconnected, tcp, nonblocking my $to_server = IO::Socket::INET->new( Proto => 'tcp', Blocking => 0 ); # nonblocking connect of tcp socket while (1) { connect($to_server,$ssock ) && last; if ( $!{EINPROGRESS} ) { diag( 'connect in progress' ); IO::Select->new( $to_server )->can_write(30) && next; print "not "; last; } elsif ( $!{EALREADY} ) { diag( 'connect not yet completed'); # just wait select(undef,undef,undef,0.1); next; } elsif ( $!{EISCONN} ) { diag('claims that socket is already connected'); # found on Mac OS X, dunno why it does not tell me that # the connect succeeded before last; } diag( 'connect failed: '.$! ); print "not "; last; } ok( "client tcp connect" ); # work around (older?) systems where IO::Socket::INET # cannot do non-blocking connect by forcing non-blocking # again (we want to test non-blocking behavior of IO::Socket::SSL, # not IO::Socket::INET) $to_server->blocking(0); # send some plain text on non-ssl socket my $pmsg = 'plaintext'; while ( $pmsg ne '' ) { my $w = syswrite( $to_server,$pmsg ); if ( ! defined $w ) { if ( ! $!{EAGAIN} ) { diag("syswrite failed with $!"); print "not "; last; } IO::Select->new($to_server)->can_write(30) or do { diag("failed to get write ready"); print "not "; last; }; } elsif ( $w>0 ) { diag("wrote $w bytes"); substr($pmsg,0,$w,''); } else { die "syswrite returned 0"; } } ok( "write plain text" ); # let server catch up, so that it awaits my connection # so that connect_SSL does not have to wait sleep(5) if ( $test eq 'slow' ); # upgrade to SSL socket w/o connection yet if ( ! IO::Socket::SSL->start_SSL( $to_server, SSL_startHandshake => 0, SSL_verify_mode => 0, SSL_key_file => "certs/server-key.enc", SSL_passwd_cb => sub { return "bluebell" }, )) { diag( 'start_SSL return undef' ); print "not "; } elsif ( !UNIVERSAL::isa( $to_server,'IO::Socket::SSL' ) ) { diag( 'failed to upgrade socket' ); print "not "; } ok( "upgrade client to IO::Socket::SSL" ); # SSL handshake thru connect_SSL # if $test eq 'fast' we expect one failed attempt because server # did not call accept_SSL yet my $attempts = 0; while ( 1 ) { $to_server->connect_SSL && last; diag( $SSL_ERROR ); if ( $SSL_ERROR == SSL_WANT_READ ) { $attempts++; IO::Select->new($to_server)->can_read(30) && next; # retry if can read } elsif ( $SSL_ERROR == SSL_WANT_WRITE ) { IO::Select->new($to_server)->can_write(30) && next; # retry if can write } diag( "failed to connect: $@" ); print "not "; last; } ok( "connected" ); if ( $test ne 'slow' ) { print "not " if !$attempts; ok( "nonblocking connect with $attempts attempts" ); } # send some data # we send up to 500000 bytes, server reads first 10 bytes and then sleeps # before reading more. In total server only reads 30000 bytes # the sleep will cause the internal buffers to fill up so that the syswrite # should return with EAGAIN+SSL_WANT_WRITE. # the socket close should cause EPIPE or ECONNRESET my $msg = "1234567890"; $attempts = 0; my $bytes_send = 0; # set send buffer to 8192 so it will definitly fail writing all 500000 bytes in it # beware that linux allocates twice as much (see tcp(7)) # AIX seems to get very slow if you set the sndbuf on localhost, so don't to it # https://rt.cpan.org/Public/Bug/Display.html?id=72305 if ( $^O !~m/aix/i ) { eval q{ setsockopt( $to_server, SOL_SOCKET, SO_SNDBUF, pack( "I",8192 )); diag( "sndbuf=".unpack( "I",getsockopt( $to_server, SOL_SOCKET, SO_SNDBUF ))); }; } my $test_might_fail; if ( $@ ) { # the next test might fail because setsockopt(... SO_SNDBUF...) failed $test_might_fail = 1; } my $can; WRITE: for( my $i=0;$i<50000;$i++ ) { my $offset = 0; while (1) { if ( $can && ! IO::Select->new($to_server)->$can(30)) { diag("fail $can"); print "not "; last WRITE; }; my $n = syswrite( $to_server,$msg,length($msg)-$offset,$offset ); if ( !defined($n) ) { diag( "\$!=$! \$SSL_ERROR=$SSL_ERROR send=$bytes_send" ); if ( $! == EAGAIN ) { if ( $SSL_ERROR == SSL_WANT_WRITE ) { diag( 'wait for write' ); $can = 'can_write'; $attempts++; } elsif ( $SSL_ERROR == SSL_WANT_READ ) { diag( 'wait for read' ); $can = 'can_read'; } else { $can = 'can_write'; } } elsif ( ( $! == EPIPE || $! == ECONNRESET ) && $bytes_send > 30000 ) { diag( "connection closed hard" ); last WRITE; } else { print "not "; last WRITE; } next; } elsif ( $n == 0 ) { diag( "connection closed" ); last WRITE; } elsif ( $n<0 ) { diag( "syswrite returned $n!" ); print "not "; last WRITE; } $bytes_send += $n; if ( $n + $offset == 10 ) { last } else { $offset += $n; diag( "partial write of $n new offset=$offset" ); } } } ok( "syswrite" ); if ( ! $attempts && $test_might_fail ) { ok( " write attempts failed, but OK nevertheless because setsockopt failed" ); } else { print "not " if !$attempts; ok( "multiple write attempts" ); } print "not " if $bytes_send < 30000; ok( "30000 bytes send" ); } } else { ############################################################ # SERVER == parent process ############################################################ # pendant to tests in client. Where client is slow (sleep # between plain text sending and connect_SSL) I need to # be fast and where client is fast I need to be slow (sleep # between receiving plain text and accept_SSL) foreach my $test ( 'slow','fast' ) { # accept a connection IO::Select->new( $server )->can_read(30); my $from_client = $server->accept or print "not "; ok( "tcp accept" ); $from_client || do { diag( "failed to tcp accept: $!" ); next; }; # make client non-blocking! $from_client->blocking(0); # read plain text data my $buf = ''; while ( length($buf) <9 ) { sysread( $from_client, $buf,9-length($buf),length($buf) ) && next; die "sysread failed: $!" if $! != EAGAIN; IO::Select->new( $from_client )->can_read(30); } $buf eq 'plaintext' || print "not "; ok( "received plain text" ); # upgrade socket to IO::Socket::SSL # no handshake yet if ( ! IO::Socket::SSL->start_SSL( $from_client, SSL_startHandshake => 0, SSL_server => 1, SSL_verify_mode => 0x00, SSL_ca_file => "certs/test-ca.pem", SSL_use_cert => 1, SSL_cert_file => "certs/client-cert.pem", SSL_key_file => "certs/client-key.enc", SSL_passwd_cb => sub { return "opossum" }, )) { diag( 'start_SSL return undef' ); print "not "; } elsif ( !UNIVERSAL::isa( $from_client,'IO::Socket::SSL' ) ) { diag( 'failed to upgrade socket' ); print "not "; } ok( "upgrade to_client to IO::Socket::SSL" ); sleep(5) if $test eq 'slow'; # wait until client calls connect_SSL # SSL handshake thru accept_SSL # if test is 'fast' (e.g. client is 'slow') we excpect the first # accept_SSL attempt to fail because client did not call connect_SSL yet my $attempts = 0; while ( 1 ) { $from_client->accept_SSL && last; if ( $SSL_ERROR == SSL_WANT_READ ) { $attempts++; IO::Select->new($from_client)->can_read(30) && next; # retry if can read } elsif ( $SSL_ERROR == SSL_WANT_WRITE ) { $attempts++; IO::Select->new($from_client)->can_write(30) && next; # retry if can write } else { diag( "failed to ssl accept ($test): $@" ); print "not "; last; } } ok( "ssl accept handshake done" ); if ( $test eq 'fast' ) { print "not " if !$attempts; ok( "nonblocking accept_SSL with $attempts attempts" ); } # reading 10 bytes # then sleeping so that buffers from client to server gets # filled up and clients receives EAGAIN+SSL_WANT_WRITE IO::Select->new( $from_client )->can_read(30); ( sysread( $from_client, $buf,10 ) == 10 ) || print "not "; #diag($buf); ok( "received client message" ); sleep(5); my $bytes_received = 10; # read up to 30000 bytes from client, then close the socket my $can; READ: while ( ( my $diff = 30000 - $bytes_received ) > 0 ) { if ( $can && ! IO::Select->new($from_client)->$can(30)) { diag("failed $can"); print "not "; last READ; } my $n = sysread( $from_client,my $buf,$diff ); if ( !defined($n) ) { diag( "\$!=$! \$SSL_ERROR=$SSL_ERROR" ); if ( $! == EAGAIN ) { if ( $SSL_ERROR == SSL_WANT_READ ) { $attempts++; $can = 'can_read'; } elsif ( $SSL_ERROR == SSL_WANT_WRITE ) { $attempts++; $can = 'can_write'; } else { $can = 'can_read'; } } else { print "not "; last READ; } next; } elsif ( $n == 0 ) { diag( "connection closed" ); last READ; } elsif ( $n<0 ) { diag( "sysread returned $n!" ); print "not "; last READ; } $bytes_received += $n; #diag( "read of $n bytes total $bytes_received" ); } diag( "read $bytes_received ($attempts r/w attempts)" ); close($from_client); } # wait until client exits wait; } exit; sub ok { print "ok # [$ID] @_\n"; } sub diag { print "# @_\n" } IO-Socket-SSL-1.965/t/cert_no_file.t0000644000175100017520000000566012263174431015555 0ustar workwork#!perl # Before `make install' is performed this script should be runnable with # `make test'. After `make install' it should work as `perl t/nonblock.t' # Tests the use if SSL_cert instead of SSL_cert_file # because Net::SSLeay does not implement the necessary functions # to create a X509 from file/string (PEM_read_bio_X509) I just # create a server with SSL_cert_file and get the X509 from it using # Net::SSLeay::get_certificate. # Test should also test if SSL_cert is an array of X509* # and if SSL_key is an EVP_PKEY* but with the current function in # Net::SSLeay I don't see a way to test it use strict; use warnings; use Net::SSLeay; use Socket; use IO::Socket::SSL; if ( grep { $^O =~m{$_} } qw( MacOS VOS vmesa riscos amigaos ) ) { print "1..0 # Skipped: fork not implemented on this platform\n"; exit } $|=1; print "1..9\n"; my $ID = 'server'; my %server_args = ( LocalAddr => '127.0.0.1', LocalPort => 0, Listen => 2, SSL_server => 1, SSL_verify_mode => 0x00, SSL_ca_file => "certs/test-ca.pem", SSL_key_file => "certs/client-key.pem", ); my ($x509,@server); foreach my $test ( 1,2,3 ) { my %args = %server_args; my $spec; if ( $test == 1 ) { # 1st test: create server with SSL_cert_file $args{SSL_cert_file} = "certs/client-cert.pem"; $spec = 'Using SSL_cert_file'; } elsif ( $test == 2 ) { # 2nd test: use x509 from previous server # with SSL_cert instead of SSL_cert_file $args{SSL_cert} = $x509; $spec = 'Using SSL_cert'; } elsif ( $test == 3 ) { # 3rd test: empty SSL_cert, so that default # SSL_cert_file gets not used # server creation should fail $spec = 'Empty SSL_cert'; $args{SSL_cert} = undef; } # create server my $server = IO::Socket::SSL->new( %args ) || do { notok( "$spec: $!" ); next; }; my $saddr = $server->sockhost.':'.$server->sockport; ok("Server Initialization $spec"); push @server,$server; # then connect to it from a child defined( my $pid = fork() ) || die $!; if ( $pid == 0 ) { close($server); $ID = 'client'; my $to_server = IO::Socket::SSL->new( PeerAddr => $saddr, SSL_verify_mode => 0x00, ); if ( $test == 3 ) { notok( "$spec: connect suceeded" ) if $to_server; ok( "$spec: connect failed" ); exit; } elsif ( ! $to_server ) { notok( "connect failed: $!" ); exit }; ok( "client connected $spec" ); <$to_server>; # wait for close from parent exit; } my $to_client = $server->accept; if ( $test == 3 ) { notok( "$spec: accept suceeded" ) if $to_client; ok( "$spec: accept failed" ); } elsif ( ! $to_client ) { notok( "$spec: accept failed: $!" ); kill(9,$pid); } else { ok( "Server accepted $spec" ); # save the X509 certificate from the server $x509 ||= Net::SSLeay::get_certificate($to_client->_get_ssl_object); } close($to_client) if $to_client; wait; } sub ok { print "ok # [$ID] @_\n"; } sub notok { print "not ok # [$ID] @_\n"; } IO-Socket-SSL-1.965/t/readline.t0000644000175100017520000000740612263174431014710 0ustar workwork#!perl # Before `make install' is performed this script should be runnable with # `make test'. After `make install' it should work as `perl t/readline.t' # This tests the behavior of readline with the variety of # cases with $/: # $/ undef - read all # $/ '' - read up to next nonempty line: .*?\n\n+ # $/ s - read up to string s # $/ \$num - read $num bytes # scalar context - get first match # array context - get all matches use strict; use warnings; use Net::SSLeay; use Socket; use IO::Socket::SSL; if ( grep { $^O =~m{$_} } qw( MacOS VOS vmesa riscos amigaos ) ) { print "1..0 # Skipped: fork not implemented on this platform\n"; exit } my @tests; push @tests, [ "multi\nple\n\n1234567890line\n\n\n\nbla\n\nblubb\n\nblip", sub { my $c = shift; local $/ = "\n\n"; my $b; ($b=<$c>) eq "multi\nple\n\n" || die "LFLF failed ($b)"; $/ = \"10"; ($b=<$c>) eq "1234567890" || die "\\size failed ($b)"; $/ = ''; ($b=<$c>) eq "line\n\n\n\n" || die "'' failed ($b)"; my @c = <$c>; die "'' @ failed: @c" unless $c[0] eq "bla\n\n" && $c[1] eq "blubb\n\n" && $c[2] eq "blip" && @c == 3; }, ]; push @tests, [ "some\nstring\nwith\nsome\nlines\nwhatever", sub { my $c = shift; local $/ = "\n"; my $b; ($b=<$c>) eq "some\n" || die "LF failed ($b)"; $/ = undef; ($b=<$c>) eq "string\nwith\nsome\nlines\nwhatever" || die "undef failed ($b)"; }, ]; push @tests, [ "some\nstring\nwith\nsome\nlines\nwhatever", sub { my $c = shift; local $/ = "\n"; my @c = <$c>; die "LF @ failed: @c" unless $c[0] eq "some\n" && $c[1] eq "string\n" && $c[2] eq "with\n" && $c[3] eq "some\n" && $c[4] eq "lines\n" && $c[5] eq "whatever" && @c == 6; }, ]; push @tests, [ "some\nstring\nwith\nsome\nlines\nwhatever", sub { my $c = shift; local $/; my @c = <$c>; die "undef @ failed: @c" unless $c[0] eq "some\nstring\nwith\nsome\nlines\nwhatever" && @c == 1; }, ]; push @tests, [ "1234567890", sub { my $c = shift; local $/ = \2; my @c = <$c>; die "\\2 @ failed: @c" unless $c[0] eq '12' && $c[1] eq '34' && $c[2] eq '56' && $c[3] eq '78' && $c[4] eq '90' && @c == 5; }, ]; push @tests, [ [ "bla\n","0","blubb\n","no newline" ], sub { my $c = shift; my $l = <$c>; $l eq "bla\n" or die "'bla\\n' failed"; $l = <$c>; $l eq "0blubb\n" or die "'0blubb\\n' failed"; $l = <$c>; $l eq "no newline" or die "'no newline' failed"; }, ]; $|=1; print "1..".(1+3*@tests)."\n"; # first create simple ssl-server my $ID = 'server'; my $addr = '127.0.0.1'; my $server = IO::Socket::SSL->new( LocalAddr => $addr, Listen => 2, ReuseAddr => 1, SSL_cert_file => "certs/server-cert.pem", SSL_key_file => "certs/server-key.pem", ) || do { notok($!); exit }; ok("Server Initialization"); # add server port to addr $addr.= ':'.(sockaddr_in( getsockname( $server )))[0]; my $pid = fork(); if ( !defined $pid ) { die $!; # fork failed } elsif ( $pid ) { ###### Server foreach my $test (@tests) { my $to_client = $server->accept || do { notok( "accept failed: ".$server->errstr() ); kill(9,$pid); exit; }; ok( "Server accepted" ); $to_client->autoflush; my $t = $test->[0]; $t = [$t] if ! ref($t); for(@$t) { $to_client->print($_); select(undef,undef,undef,0.1); } } wait; exit; } $ID = 'client'; close($server); my $testid = "Test00"; foreach my $test (@tests) { my $to_server = IO::Socket::SSL->new( PeerAddr => $addr, SSL_verify_mode => 0 ) || do { notok( "connect failed: ".IO::Socket::SSL->errstr() ); exit }; ok( "client connected" ); eval { $test->[1]( $to_server ) }; $@ ? notok( "$testid $@" ) : ok( $testid ); $testid++ } sub ok { print "ok # [$ID] @_\n"; } sub notok { print "not ok # [$ID] @_\n"; } IO-Socket-SSL-1.965/t/auto_verify_hostname.t0000644000175100017520000000451712263174431017357 0ustar workwork#!perl use strict; use warnings; use Net::SSLeay; use Socket; use IO::Socket::SSL; if ( grep { $^O =~m{$_} } qw( MacOS VOS vmesa riscos amigaos ) ) { print "1..0 # Skipped: fork not implemented on this platform\n"; exit } $|=1; print "1..30\n"; my $server = IO::Socket::SSL->new( LocalAddr => '127.0.0.1', LocalPort => 0, Listen => 2, ReuseAddr => 1, SSL_server => 1, SSL_ca_file => "certs/test-ca.pem", SSL_cert_file => "certs/server-wildcard.pem", SSL_key_file => "certs/server-wildcard.pem", ); warn "\$!=$!, \$\@=$@, S\$SSL_ERROR=$SSL_ERROR" if ! $server; print "not ok\n", exit if !$server; ok("Server Initialization"); my $saddr = $server->sockhost.':'.$server->sockport; defined( my $pid = fork() ) || die $!; if ( $pid == 0 ) { while (1) { my $csock = $server->accept || next; print $csock "hallo\n"; } } close($server); my @tests = qw( example.com www FAIL server.local ldap OK server.local www FAIL bla.server.local www OK www7.other.local www OK www7.other.local ldap FAIL bla.server.local ldap OK ); for( my $i=0;$i<@tests;$i+=3 ) { my ($name,$scheme,$result) = @tests[$i,$i+1,$i+2]; my $cl = IO::Socket::SSL->new( SSL_ca_file => 'certs/test-ca.pem', PeerAddr => $saddr, SSL_verify_mode => 1, SSL_verifycn_scheme => $scheme, SSL_verifycn_name => $name, ); if ( $result eq 'FAIL' ) { print "not " if $cl; ok( "connection to $name/$scheme failed" ); } else { print "not " if !$cl; ok( "connection to $name/$scheme succeeded" ); } $cl || next; print "not " if <$cl> ne "hallo\n"; ok( "received hallo" ); } for( my $i=0;$i<@tests;$i+=3 ) { my ($name,$scheme,$result) = @tests[$i,$i+1,$i+2]; my $cl = IO::Socket::INET->new( PeerAddr => $saddr, ) || print "not "; ok( "tcp connect" ); $cl = IO::Socket::SSL->start_SSL( $cl, SSL_ca_file => 'certs/test-ca.pem', SSL_verify_mode => 1, SSL_verifycn_scheme => $scheme, SSL_verifycn_name => $name, ); if ( $result eq 'FAIL' ) { print "not " if $cl; ok( "ssl upgrade of connection to $name/$scheme failed" ); } else { print "not " if !$cl; ok( "ssl upgrade of connection to $name/$scheme succeeded" ); } $cl || next; print "not " if <$cl> ne "hallo\n"; ok( "received hallo" ); } kill(9,$pid); wait; sub ok { print "ok #$_[0]\n"; } IO-Socket-SSL-1.965/t/startssl-failed.t0000644000175100017520000000351212263174431016220 0ustar workwork#!perl use strict; use warnings; use Net::SSLeay; use Socket; use IO::Socket::SSL; use IO::Select; use Errno qw(EAGAIN EINPROGRESS ); if ( grep { $^O =~m{$_} } qw( MacOS VOS vmesa riscos amigaos ) ) { print "1..0 # Skipped: fork not implemented on this platform\n"; exit } $|=1; print "1..9\n"; my $server = IO::Socket::INET->new( LocalAddr => '127.0.0.1', LocalPort => 0, Listen => 2, ); print("not ok\n"),exit if !$server; ok("Server Initialization"); my $saddr = $server->sockhost.':'.$server->sockport; defined( my $pid = fork() ) || die $!; if ( $pid == 0 ) { client(); } else { server(); #kill(9,$pid); wait; } sub client { close($server); my $client = IO::Socket::INET->new($saddr) or return fail("client tcp connect"); ok("client tcp connect"); IO::Socket::SSL->start_SSL($client, SSL_verify_mode => 0) and return fail('start ssl should fail'); ok("startssl client failed: $SSL_ERROR"); UNIVERSAL::isa($client,'IO::Socket::INET') or return fail('downgrade socket after error'); ok('downgrade socket after error'); print $client "foo\n" or return fail("send to server: $!"); ok("send to server"); my $l; while (defined($l = <$client>)) { if ( $l =~m{bar\n} ) { return ok('client receive non-ssl data'); } #warn "XXXXXXXX $l"; } fail("receive non-ssl data"); } sub server { my $csock = $server->accept or return fail('tcp accept'); ok('tcp accept'); print $csock "This is no SSL handshake\n"; ok('send non-ssl data'); alarm(10); my $l; while (defined( $l = <$csock>)) { if ($l =~m{foo\n} ) { print $csock "bar\n"; return ok("received non-ssl data"); } #warn "XXXXXXXXX $l"; } fail('no data from client'.$!); } sub ok { print "ok #$_[0]\n"; return 1 } sub fail { print "not ok #$_[0]\n"; return } IO-Socket-SSL-1.965/t/dhe.t0000644000175100017520000000375212263174431013665 0ustar workwork#!perl # Before `make install' is performed this script should be runnable with # `make test'. After `make install' it should work as `perl t/dhe.t' # This tests the use of Diffie Hellman Key Exchange (DHE) # If you have only a 384bit RSA key you can not use RSA key exchange, # but DHE is usable. For an explanation see # http://groups.google.de/group/mailing.openssl.users/msg/d60330cfa7a6034b # So this test simple uses a 384bit RSA key to make sure that DHE is used. use strict; use warnings; use Net::SSLeay; use Socket; use IO::Socket::SSL; if ( grep { $^O =~m{$_} } qw( MacOS VOS vmesa riscos amigaos ) ) { print "1..0 # Skipped: fork not implemented on this platform\n"; exit } $|=1; print "1..3\n"; # first create simple ssl-server my $ID = 'server'; my $addr = '127.0.0.1'; my $server = IO::Socket::SSL->new( LocalAddr => $addr, Listen => 2, ReuseAddr => 1, SSL_cert_file => "certs/server-rsa384-dh.pem", SSL_key_file => "certs/server-rsa384-dh.pem", SSL_dh_file => "certs/server-rsa384-dh.pem", # at least 0.9.8[ab] have problems if we don't explicitly disable # RSA or EXPORT56, and 1.0.1 complains if we have RSA authentication # enabled SSL_cipher_list => 'ALL:RSA:!aRSA', ) || do { notok($!); exit }; ok("Server Initialization"); # add server port to addr $addr.= ':'.(sockaddr_in( getsockname( $server )))[0]; my $pid = fork(); if ( !defined $pid ) { die $!; # fork failed } elsif ( !$pid ) { ###### Client $ID = 'client'; close($server); my $to_server = IO::Socket::SSL->new( PeerAddr => $addr, SSL_cipher_list => 'ALL:RSA:!aRSA', SSL_verify_mode => 0 ) || do { notok( "connect failed: $SSL_ERROR" ); exit }; ok( "client connected" ); } else { ###### Server my $to_client = $server->accept || do { notok( "accept failed: $SSL_ERROR" ); kill(9,$pid); exit; }; ok( "Server accepted" ); wait; } sub ok { print "ok # [$ID] @_\n"; } sub notok { print "not ok # [$ID] @_\n"; } IO-Socket-SSL-1.965/t/testlib.pl0000644000175100017520000001264012263174431014737 0ustar workworkuse strict; use warnings; use IO::Socket; use IO::Socket::SSL; ############################################################################ # # small test lib for common tasks: # adapted from t/testlib.pl in Net::SIP package # ############################################################################ if ( grep { $^O =~m{$_} } qw( MacOS VOS vmesa riscos amigaos ) ) { print "1..0 # Skipped: fork not implemented on this platform\n"; exit } # small implementations if not used from Test::More (09_fdleak.t) if ( ! defined &ok ) { no strict 'refs'; *{'ok'} = sub { my ($bool,$desc) = @_; print $bool ? "ok ":"not ok ", '# ',$desc || '',"\n"; }; *{'diag'} = sub { print "# @_\n"; }; *{'like'} = sub { my ( $data,$rx,$desc ) = @_; ok( $data =~ $rx ? 1:0, $desc ); }; } $SIG{ __DIE__ } = sub { return if $^S; # Ignore from within evals ok( 0,"@_" ); killall(); exit(1); }; ############################################################################ # kill all process collected by fork_sub # Args: ?$signal # $signal: signal to use, default 9 # Returns: NONE ############################################################################ my @pids; sub killall { my $sig = shift || 9; kill $sig, @pids; #diag( "killed @pids with $sig" ); while ( wait() >= 0 ) {} # collect all @pids = (); } ############################################################################ # fork named sub with args and provide fd into subs STDOUT # Args: ($name,@args) # $name: name or ref to sub, if name it will be used for debugging # @args: arguments for sub # Returns: $fh # $fh: file handle to read STDOUT of sub ############################################################################ my %fd2name; # associated sub-name for file descriptor to subs STDOUT sub fork_sub { my ($name,@arg) = @_; my $sub = ref($name) ? $name : UNIVERSAL::can( 'main',$name ) || die; pipe( my $rh, my $wh ) || die $!; defined( my $pid = fork() ) || die $!; if ( ! $pid ) { # CHILD, exec sub close($rh); local *STDOUT = local *STDERR = $wh; $wh->autoflush; print "OK\n"; $sub->(@arg); exit(0); } push @pids,$pid; close( $wh ); $fd2name{$rh} = $name; fd_grep_ok( 'OK',10,$rh ) || die 'startup failed'; return $rh; } ############################################################################ # grep within fd's for specified regex or substring # Args: ($pattern,[ $timeout ],@fd) # $pattern: regex or substring # $timeout: how many seconds to wait for pattern, default 10 # @fd: which fds to search, usually fds from fork_sub(..) # Returns: $rv| ($rv,$name) # $rv: matched text if pattern is found, else undef # $name: name for file handle ############################################################################ my %fd2buf; # already read data from fd sub fd_grep { my $pattern = shift; my $timeout = 10; $timeout = shift if !ref($_[0]); my @fd = @_; $pattern = qr{\Q$pattern} if ! UNIVERSAL::isa( $pattern,'Regexp' ); my $name = join( "|", map { $fd2name{$_} || "$_" } @fd ); #diag( "look for $pattern in $name" ); my @bad = wantarray ? ( undef,$name ):(undef); @fd || return @bad; my $rin = ''; map { $_->blocking(0); vec( $rin,fileno($_),1 ) = 1 } @fd; my $end = defined( $timeout ) ? time() + $timeout : undef; while (@fd) { # check existing buf from previous reads foreach my $fd (@fd) { my $buf = \$fd2buf{$fd}; $$buf || next; if ( $$buf =~s{\A(?:.*?)($pattern)}{}s ) { #diag( "found" ); return wantarray ? ( $1,$name ) : $1; } } # if not found try to read new data $timeout = $end - time() if $end; return @bad if $timeout < 0; select( my $rout = $rin,undef,undef,$timeout ); $rout || return @bad; # not found foreach my $fd (@fd) { my $name = $fd2name{$fd} || "$fd"; my $buf = \$fd2buf{$fd}; my $fn = fileno($fd); my $n; if ( defined ($fn)) { vec( $rout,$fn,1 ) || next; my $l = $$buf && length($$buf) || 0; $n = sysread( $fd,$$buf,8192,$l ); } if ( ! $n ) { #diag( "$name >CLOSED<" ); delete $fd2buf{$fd}; @fd = grep { $_ != $fd } @fd; close($fd); next; } diag( "$name >> ".substr( $$buf,-$n ). "<<" ); } } return @bad; } ############################################################################ # like Test::Simple::ok, but based on fd_grep, same as # ok( fd_grep( pattern,... ), "[$subname] $pattern" ) # Args: ($pattern,[ $timeout ],@fd) - see fd_grep # Returns: $rv - like in fd_grep # Comment: if !$rv and wantarray says void it will die() ############################################################################ sub fd_grep_ok { my $pattern = shift; my ($rv,$name) = fd_grep( $pattern, @_ ); local $Test::Builder::Level = $Test::Builder::Level || 0 +1; ok( $rv,"[$name] $pattern" ); die "fatal error" if !$rv && ! defined wantarray; return $rv; } ############################################################################ # create socket on IP # return socket and ip:port ############################################################################ sub create_listen_socket { my ($addr,$port,$proto) = @_; $addr ||= '127.0.0.1'; my $sock = IO::Socket::INET->new( LocalAddr => $addr, $port ? ( LocalPort => $port, Reuse => 1 ) : (), Listen => 10, ) || die $!; ($port,$addr) = unpack_sockaddr_in( getsockname($sock) ); return wantarray ? ( $sock, inet_ntoa($addr).':'.$port ) : $sock; } 1; IO-Socket-SSL-1.965/t/ecdhe.t0000644000175100017520000000333112263174431014166 0ustar workwork#!perl # Before `make install' is performed this script should be runnable with # `make test'. After `make install' it should work as `perl t/ecdhe.t' use strict; use warnings; use Net::SSLeay; use Socket; use IO::Socket::SSL; if ( grep { $^O =~m{$_} } qw( MacOS VOS vmesa riscos amigaos ) ) { print "1..0 # Skipped: fork not implemented on this platform\n"; exit } if ( ! defined &Net::SSLeay::CTX_set_tmp_ecdh ) { print "1..0 # Skipped: no support for ecdh with this openssl/Net::SSLeay\n"; exit } $|=1; print "1..4\n"; # first create simple ssl-server my $ID = 'server'; my $addr = '127.0.0.1'; my $server = IO::Socket::SSL->new( LocalAddr => $addr, Listen => 2, ReuseAddr => 1, SSL_cert_file => "certs/server-cert.pem", SSL_key_file => "certs/server-key.pem", SSL_ecdh_curve => 'prime256v1', ) || do { notok($!); exit }; ok("Server Initialization"); # add server port to addr $addr.= ':'.(sockaddr_in( getsockname( $server )))[0]; my $pid = fork(); if ( !defined $pid ) { die $!; # fork failed } elsif ( !$pid ) { ###### Client $ID = 'client'; close($server); my $to_server = IO::Socket::SSL->new( PeerAddr => $addr, SSL_verify_mode => 0 ) || do { notok( "connect failed: $SSL_ERROR" ); exit }; ok( "client connected" ); my $cipher = $to_server->get_cipher(); if ( $cipher !~m/^ECDHE-/ ) { notok("bad key exchange: $cipher"); exit; } ok("ecdh key exchange: $cipher"); } else { ###### Server my $to_client = $server->accept || do { notok( "accept failed: $SSL_ERROR" ); kill(9,$pid); exit; }; ok( "Server accepted" ); wait; } sub ok { print "ok # [$ID] @_\n"; } sub notok { print "not ok # [$ID] @_\n"; } IO-Socket-SSL-1.965/t/connectSSL-timeout.t0000644000175100017520000000373512263174431016625 0ustar workworkuse strict; use warnings; use IO::Socket::SSL; do './testlib.pl' || do './t/testlib.pl' || die "no testlib"; $|=1; print "1..16\n"; { # first use SSL client my ($server,$saddr) = create_listen_socket(); ok( 1, "listening \@$saddr" ); my $srv = fork_sub( 'server','ssl',$server ); close($server); fd_grep_ok( 'Waiting', $srv ); my $cl = fork_sub( 'client',$saddr ); fd_grep_ok( 'Connect from',$srv ); fd_grep_ok( 'Connected', $cl ); fd_grep_ok( 'Server SSL Handshake OK', $srv ); fd_grep_ok( 'Client SSL Handshake OK', $cl ); fd_grep_ok( 'Hi!', $cl ); } if ( $^O =~m{mswin32}i ) { # skip ok( 1, "skip - TODO on win32" ) for(1..7); } else { # then try bad non-SSL client my ($server,$saddr) = create_listen_socket(); ok( 1, "listening \@$saddr" ); my $srv = fork_sub( 'server','nossl',$server ); close($server); fd_grep_ok( 'Waiting', $srv ); my $cl = fork_sub( 'client',$saddr ); fd_grep_ok( 'Connect from',$srv ); fd_grep_ok( 'Connected', $cl ); fd_grep_ok( 'Client SSL Handshake FAILED', $cl ); } sub server { my ($behavior,$server) = @_; print "Waiting\n"; my $client = $server->accept || die "accept failed: $!"; print "Connect from ".$client->peerhost.':'.$client->peerport."\n"; if ( $behavior eq 'ssl' ) { if ( IO::Socket::SSL->start_SSL( $client, SSL_server => 1, Timeout => 30, SSL_cert_file => 'certs/server-cert.pem', SSL_key_file => 'certs/server-key.pem', )) { print "Server SSL Handshake OK\n"; print $client "Hi!\n"; } } else { while ( sysread( $client, my $buf,8000 )) {} } } sub client { my $saddr = shift; my $c = IO::Socket::INET->new( $saddr ) || die "connect failed: $!"; print "Connected\n"; if ( IO::Socket::SSL->start_SSL( $c, Timeout => 5, SSL_ca_file => 'certs/my-ca.pem', )) { print "Client SSL Handshake OK\n"; print <$c> } else { print "Client SSL Handshake FAILED - $SSL_ERROR\n"; } } IO-Socket-SSL-1.965/t/startssl.t0000644000175100017520000000426312263174431015002 0ustar workwork#!perl # Before `make install' is performed this script should be runnable with # `make test'. After `make install' it should work as `perl t/nonblock.t' use strict; use warnings; use Net::SSLeay; use Socket; use IO::Socket::SSL; use IO::Select; use Errno qw(EAGAIN EINPROGRESS ); if ( ! eval "use 5.006; use IO::Select; return 1" ) { print "1..0 # Skipped: no support for nonblocking sockets\n"; exit; } if ( grep { $^O =~m{$_} } qw( MacOS VOS vmesa riscos amigaos ) ) { print "1..0 # Skipped: fork not implemented on this platform\n"; exit } $|=1; print "1..9\n"; my $server = IO::Socket::INET->new( LocalAddr => '127.0.0.1', LocalPort => 0, Listen => 2, ); print "not ok\n", exit if !$server; ok("Server Initialization"); print "not " if (!defined fileno($server)); ok("Server Fileno Check"); my $saddr = $server->sockhost.':'.$server->sockport; defined( my $pid = fork() ) || die $!; if ( $pid == 0 ) { close($server); my $client = IO::Socket::INET->new($saddr) || print "not "; ok( "client tcp connect" ); unless ( IO::Socket::SSL->start_SSL( $client, SSL_version => 'TLSv1', SSL_cipher_list => 'HIGH', SSL_verify_mode => 0, SSL_key_file => "certs/server-key.enc", SSL_passwd_cb => sub { return "bluebell" }, )) { #DEBUG( $SSL_ERROR ); print "not "; } ok( "sslify client" ); UNIVERSAL::isa( $client,'IO::Socket::SSL' ) || print "not "; ok( 'client reblessed as IO::Socket::SSL' ); print $client "hannibal\n"; exit; } my $csock = $server->accept || print "not "; ok( "tcp accept" ); IO::Socket::SSL->start_SSL( $csock, SSL_server => 1, SSL_verify_mode => 0x00, SSL_ca_file => "certs/test-ca.pem", SSL_cert_file => "certs/client-cert.pem", SSL_version => 'TLSv1', SSL_cipher_list => 'HIGH', SSL_key_file => "certs/client-key.enc", SSL_passwd_cb => sub { return "opossum" } ) || print "not "; #DEBUG( $IO::Socket::SSL::ERROR ); ok( 'sslify server' ); UNIVERSAL::isa( $csock,'IO::Socket::SSL' ) || print "not "; ok( 'server reblessed as IO::Socket::SSL' ); my $l = <$csock>; #DEBUG($l); print "not " if $l ne "hannibal\n"; ok( "received client message" ); wait; sub ok { print "ok #$_[0]\n"; } IO-Socket-SSL-1.965/t/compatibility.t0000644000175100017520000000420112263174431015764 0ustar workwork#!perl # Before `make install' is performed this script should be runnable with # `make test'. After `make install' it should work as `perl t/compatibility.t' use strict; use warnings; use IO::Socket::SSL; use Socket; $|=1; foreach ($^O) { if (/MacOS/ or /VOS/ or /vmesa/ or /riscos/ or /amigaos/) { print "1..0 # Skipped: fork not implemented on this platform\n"; exit; } } $SIG{'CHLD'} = "IGNORE"; print "1..9\n"; IO::Socket::SSL::context_init(SSL_verify_mode => 0x01, SSL_version => 'TLSv1' ); my $server = IO::Socket::INET->new( LocalAddr => '127.0.0.1', LocalPort => 0, Listen => 1, ) or do { print "Bail out! "; print("Setup of test IO::Socket::INET client and server failed. All the rest of ", "the tests in this suite will fail also unless you change the values in ", "ssl_settings.req in the t/ directory."); exit; }; print "ok # server create\n"; { package MyClass; use IO::Socket::SSL; our @ISA = "IO::Socket::SSL"; } my $saddr = $server->sockhost.':'.$server->sockport; unless (fork) { close $server; my $client = IO::Socket::INET->new($saddr); MyClass->start_SSL($client, SSL_verify_mode => 0) || print "not "; print "ok # ssl upgrade\n"; (ref($client) eq "MyClass") || print "not "; print "ok # class MyClass\n"; $client->issuer_name || print "not "; print "ok # issuer_name\n"; $client->subject_name || print "not "; print "ok # subject_name\n"; $client->opened || print "not "; print "ok # opened\n"; print $client "Ok to close\n"; close $client; exit(0); } my $contact = $server->accept; IO::Socket::SSL::socketToSSL($contact, { SSL_server => 1, SSL_verify_mode => 0, SSL_cert_file => 'certs/server-cert.pem', SSL_key_file => 'certs/server-key.pem', }) || print "not "; print "ok # socketToSSL\n"; <$contact>; close $contact; close $server; bless $contact, "MyClass"; print "not " if IO::Socket::SSL::socket_to_SSL($contact, SSL_server => 1); print "ok # socket_to_SSL\n"; print "not " unless (ref($contact) eq "MyClass"); print "ok # upgrade is MyClass\n"; sub bail { print "Bail Out! $IO::Socket::SSL::ERROR"; } IO-Socket-SSL-1.965/t/01loadmodule.t0000644000175100017520000000113412263174431015403 0ustar workworkuse strict; use warnings; my ($foo,$test,$loaded); BEGIN { $| = 1; print "1..4\n"; } END {print "Load failed ... not ok 1\n" unless $loaded;} use Carp; BEGIN { $foo = 0; $SIG{__DIE__} = sub { $foo++ if defined $^S && !$^S } if $] > 5.006; } use IO::Socket::SSL qw(:debug1); $loaded = 1; $test=1; print "ok $test\n"; $test++; if ($foo) { print "not ";} print "ok $test\n"; delete $SIG{__DIE__}; $test++; if ($IO::Socket::SSL::DEBUG == 1) { print "ok $test\n"; } else { print "not ok $test\n"; } $test++; if ($Net::SSLeay::trace == 1) { print "ok $test\n"; } else { print "not ok $test\n"; } IO-Socket-SSL-1.965/t/io-socket-ip.t0000644000175100017520000000420512263174431015422 0ustar workwork#!perl # Before `make install' is performed this script should be runnable with # `make test'. After `make install' it should work as `perl t/dhe.t' # make sure IO::Socket::INET6 will not be used BEGIN { $INC{'IO/Socket/INET6.pm'} = undef } use strict; use warnings; use Net::SSLeay; use Socket; use IO::Socket::SSL; if ( grep { $^O =~m{$_} } qw( MacOS VOS vmesa riscos amigaos ) ) { print "1..0 # Skipped: fork not implemented on this platform\n"; exit } # check if we have loaded IO::Socket::IP, IO::Socket::SSL should do it by # itself if it is available unless( IO::Socket::SSL->CAN_IPV6 eq "IO::Socket::IP" ) { # not available or IO::Socket::SSL forgot to load it if ( ! eval { require IO::Socket::IP; IO::Socket::IP->VERSION(0.20) } ) { print "1..0 # Skipped: no IO::Socket::IP 0.20 available\n"; } else { print "1..1\nnot ok # automatic use of IO::Socket::IP\n"; } exit } my $addr = '::1'; # check if we can use ::1, e.g if the computer has IPv6 enabled if ( ! IO::Socket::IP->new( Listen => 10, LocalAddr => $addr, )) { print "1..0 # no IPv6 enabled on this computer\n"; exit } $|=1; print "1..3\n"; # first create simple ssl-server my $ID = 'server'; my $server = IO::Socket::SSL->new( LocalAddr => $addr, Listen => 2, SSL_cert_file => "certs/server-cert.pem", SSL_key_file => "certs/server-key.pem", ) || do { notok($!); exit }; ok("Server Initialization at $addr"); # add server port to addr $addr = "[$addr]:".$server->sockport; print "# server at $addr\n"; my $pid = fork(); if ( !defined $pid ) { die $!; # fork failed } elsif ( !$pid ) { ###### Client $ID = 'client'; close($server); my $to_server = IO::Socket::SSL->new( PeerAddr => $addr, SSL_verify_mode => 0 ) || do { notok( "connect failed: ".IO::Socket::SSL->errstr() ); exit }; ok( "client connected" ); } else { ###### Server my $to_client = $server->accept || do { notok( "accept failed: ".$server->errstr() ); kill(9,$pid); exit; }; ok( "Server accepted" ); wait; } sub ok { print "ok # [$ID] @_\n"; } sub notok { print "not ok # [$ID] @_\n"; } IO-Socket-SSL-1.965/t/start-stopssl.t0000644000175100017520000000614412263174431015765 0ustar workwork#!perl use strict; use warnings; use IO::Socket::INET; use IO::Socket::SSL; if ( grep { $^O =~m{$_} } qw( MacOS VOS vmesa riscos amigaos ) ) { print "1..0 # Skipped: fork not implemented on this platform\n"; exit } $|=1; my @tests = qw( start stop start close ); print "1..16\n"; my $server = IO::Socket::INET->new( LocalAddr => '127.0.0.1', LocalPort => 0, Listen => 2, ) || die "not ok #tcp listen failed: $!\n"; print "ok #listen\n"; my $saddr = $server->sockhost.':'.$server->sockport; defined( my $pid = fork() ) || die $!; $pid ? server():client(); wait; exit(0); sub client { close($server); my $client = IO::Socket::INET->new($saddr) or die "not ok #client connect: $!\n"; $client->autoflush; print "ok #client connect\n"; for my $test (@tests) { alarm(15); #print STDERR "begin test $test\n"; if ( $test eq 'start' ) { print $client "start\n"; sleep(1); # avoid race condition, if client calls start but server is not yet available #print STDERR ">>$$(client) start\n"; IO::Socket::SSL->start_SSL($client, SSL_verify_mode => 0 ) || die "not ok #client::start_SSL: $SSL_ERROR\n"; #print STDERR "<<$$(client) start\n"; print "ok # client::start_SSL\n"; ref($client) eq "IO::Socket::SSL" or print "not "; print "ok # client::class=".ref($client)."\n"; } elsif ( $test eq 'stop' ) { print $client "stop\n"; $client->stop_SSL || die "not ok #client::stop_SSL\n"; print "ok # client::stop_SSL\n"; ref($client) eq "IO::Socket::INET" or print "not "; print "ok # client::class=".ref($client)."\n"; } elsif ( $test eq 'close' ) { print $client "close\n"; my $class = ref($client); $client->close || die "not ok # client::close\n"; print "ok # client::close\n"; ref($client) eq $class or print "not "; print "ok # client::class=".ref($client)."\n"; last; } #print STDERR "cont test $test\n"; defined( my $line = <$client> ) or return; die "'$line'" if $line ne "OK\n"; } } sub server { my $client = $server->accept || die $!; $client->autoflush; while (1) { alarm(15); defined( my $line = <$client> ) or last; chomp($line); if ( $line eq 'start' ) { #print STDERR ">>$$ start\n"; IO::Socket::SSL->start_SSL( $client, SSL_server => 1, SSL_cert_file => "certs/client-cert.pem", SSL_key_file => "certs/client-key.pem" ) || die "not ok #server::start_SSL: $SSL_ERROR\n"; #print STDERR "<<$$ start\n"; ref($client) eq "IO::Socket::SSL" or print "not "; print "ok # server::class=".ref($client)."\n"; print $client "OK\n"; } elsif ( $line eq 'stop' ) { $client->stop_SSL || die "not ok #server::stop_SSL\n"; print "ok #server::stop_SSL\n"; ref($client) eq "IO::Socket::INET" or print "not "; print "ok # class=".ref($client)."\n"; print $client "OK\n"; } elsif ( $line eq 'close' ) { my $class = ref($client); $client->close || die "not ok #server::close\n"; print "ok #server::close\n"; ref($client) eq $class or print "not "; print "ok # class=".ref($client)."\n"; last; } } } IO-Socket-SSL-1.965/t/mitm.t0000644000175100017520000000544312263174431014072 0ustar workwork#!perl use strict; use warnings; use Net::SSLeay; use Socket; use IO::Socket::SSL; use IO::Socket::SSL::Intercept; if ( grep { $^O =~m{$_} } qw( MacOS VOS vmesa riscos amigaos ) ) { print "1..0 # Skipped: fork not implemented on this platform\n"; exit } print "1..8\n"; my @pid; END { kill 9,@pid } my $server = IO::Socket::SSL->new( LocalAddr => '127.0.0.1', LocalPort => 0, SSL_cert_file => 'certs/server-cert.pem', SSL_key_file => 'certs/server-key.pem', Listen => 10, ); ok($server,"server ssl socket"); my $saddr = $server->sockhost.':'.$server->sockport; defined( my $pid = fork ) or die $!; exit( server()) if ! $pid; # child -> server() push @pid,$pid; close($server); my $proxy = IO::Socket::INET->new( LocalAddr => '127.0.0.1', LocalPort => 0, Listen => 10, Reuse => 1, ); sys_ok($proxy,"proxy tcp socket"); my $paddr = $proxy->sockhost.':'.$proxy->sockport; defined( $pid = fork ) or die $!; exit( proxy()) if ! $pid; # child -> proxy() push @pid,$pid; close($proxy); # connect to server, check certificate my $cl = IO::Socket::SSL->new( PeerAddr => $saddr, SSL_verify_mode => 1, SSL_ca_file => 'certs/my-ca.pem', ); ssl_ok($cl,"ssl connected to server"); ok( $cl->peer_certificate('subject') =~ m{server\.local}, "subject w/o mitm"); ok( $cl->peer_certificate('issuer') =~ m{IO::Socket::SSL Demo CA}, "issuer w/o mitm"); # connect to proxy, check certificate $cl = IO::Socket::SSL->new( PeerAddr => $paddr, SSL_verify_mode => 1, SSL_ca_file => 'certs/proxyca.pem', ); ssl_ok($cl,"ssl connected to proxy"); ok( $cl->peer_certificate('subject') =~ m{server\.local}, "subject w/ mitm"); ok( $cl->peer_certificate('issuer') =~ m{IO::Socket::SSL::Intercept}, "issuer w/ mitm"); sub server { while (1) { my $cl = $server->accept or next; sleep(1); } } sub proxy { my $mitm = IO::Socket::SSL::Intercept->new( proxy_cert_file => 'certs/proxyca.pem', proxy_key_file => 'certs/proxyca.pem', ); while (1) { my $toc = $proxy->accept or next; my $tos = IO::Socket::SSL->new( PeerAddr => $saddr, SSL_verify_mode => 1, SSL_ca_file => 'certs/my-ca.pem', ) or die "failed connect to server: $!, $SSL_ERROR"; my ($cert,$key) = $mitm->clone_cert($tos->peer_certificate); $toc = IO::Socket::SSL->start_SSL( $toc, SSL_server => 1, SSL_cert => $cert, SSL_key => $key, ) or die "ssl upgrade client failed: $SSL_ERROR"; sleep(1); } } sub ok { my ($what,$msg) = @_; print "not " if ! $what; print "ok # $msg\n"; } sub sys_ok { my ($what,$msg) = @_; if ( $what ) { print "ok # $msg\n"; } else { print "not ok # $msg - $!\n"; exit } } sub ssl_ok { my ($what,$msg) = @_; if ( $what ) { print "ok # $msg\n"; } else { print "not ok # $msg - $SSL_ERROR\n"; exit } } IO-Socket-SSL-1.965/t/verify_hostname.t0000644000175100017520000000560612263174431016327 0ustar workwork#!perl use strict; use warnings; use Net::SSLeay; use Socket; use IO::Socket::SSL; if ( grep { $^O =~m{$_} } qw( MacOS VOS vmesa riscos amigaos ) ) { print "1..0 # Skipped: fork not implemented on this platform\n"; exit } # if we have an IDN library max the IDN tests too my $can_idn = eval { require Encode } && ( eval { require Net::LibIDN } || eval { require Net::IDN::Encode } || eval { require URI; URI->VERSION(1.50) } ); $|=1; my $max = 40; $max+=3 if $can_idn; print "1..$max\n"; my $server = IO::Socket::SSL->new( LocalAddr => '127.0.0.1', LocalPort => 0, Listen => 2, ReuseAddr => 1, SSL_ca_file => "certs/test-ca.pem", SSL_cert_file => "certs/server-wildcard.pem", SSL_key_file => "certs/server-wildcard.pem", ); warn "\$!=$!, \$\@=$@, S\$SSL_ERROR=$SSL_ERROR" if ! $server; print "not ok\n", exit if !$server; ok("Server Initialization"); my $saddr = $server->sockhost.':'.$server->sockport; defined( my $pid = fork() ) || die $!; if ( $pid == 0 ) { close($server); my $client = IO::Socket::SSL->new( PeerAddr => $saddr, SSL_verify_mode => 0 ) || print "not "; ok( "client ssl connect" ); my $issuer = $client->peer_certificate( 'issuer' ); print "not " if $issuer !~m{IO::Socket::SSL Demo CA}; ok("issuer"); my $cn = $client->peer_certificate( 'cn' ); print "not " unless $cn eq "server.local"; ok("cn"); my @alt = $client->peer_certificate( 'subjectAltNames' ); my @want = ( GEN_DNS() => '*.server.local', GEN_IPADD() => '127.0.0.1', GEN_DNS() => 'www*.other.local', GEN_DNS() => 'smtp.mydomain.local', GEN_DNS() => 'xn--lwe-sna.idntest.local', ); while (@want) { my ($typ,$text) = splice(@want,0,2); my $data = ($typ == GEN_IPADD() ) ? inet_aton($text):$text; my ($th,$dh) = splice(@alt,0,2); $th == $typ and $dh eq $data or print "not "; ok( $text ); } @alt and print "not "; ok( 'no more altSubjectNames' ); my @tests = ( '127.0.0.1' => [qw( smtp ldap www)], 'server.local' => [qw(smtp ldap)], 'blafasel.server.local' => [qw(smtp ldap www)], 'lala.blafasel.server.local' => [], 'www.other.local' => [qw()], 'www-13.other.local' => [qw(www)], 'www-13.lala.other.local' => [], 'smtp.mydomain.local' => [qw(smtp ldap www)], 'xn--lwe-sna.idntest.local' => [qw(smtp ldap www)], 'smtp.mydomain.localizing.useless.local' => [], ); if ( $can_idn ) { # check IDN handling my $loewe = "l\366we.idntest.local"; push @tests, ( $loewe => [qw(smtp ldap www)] ); } while (@tests) { my ($host,$expect) = splice(@tests,0,2); my %expect = map { $_=>1 } @$expect; for my $typ (qw( smtp ldap www)) { my $is = $client->verify_hostname( $host, $typ ) ? 'pass':'fail'; my $want = $expect{$typ} ? 'pass':'fail'; print "not " if $is ne $want; ok( "$want $host $typ" ); } } exit; } my $csock = $server->accept; wait; sub ok { print "ok #$_[0]\n"; } IO-Socket-SSL-1.965/t/sessions.t0000644000175100017520000001136112265774242014776 0ustar workwork#!perl # Before `make install' is performed this script should be runnable with # `make test'. After `make install' it should work as `perl t/core.t' use strict; use warnings; use Net::SSLeay; use Socket; use IO::Socket::SSL; foreach ($^O) { if (/MacOS/ or /VOS/ or /vmesa/ or /riscos/ or /amigaos/) { print "1..0 # Skipped: fork not implemented on this platform\n"; exit; } } $|=1; my $numtests = 35; print "1..$numtests\n"; my @servers = map { IO::Socket::SSL->new( LocalAddr => '127.0.0.1', LocalPort => 0, Listen => 2, Timeout => 30, ReuseAddr => 1, SSL_key_file => "certs/server-key.enc", SSL_passwd_cb => sub { return "bluebell" }, SSL_verify_mode => SSL_VERIFY_NONE, SSL_ca_file => "certs/test-ca.pem", SSL_cert_file => "certs/server-cert.pem", ) } (1..3); if ( grep { !$_ } @servers > 0 ) { print "not ok # Server init\n"; exit; } &ok("Server initialization"); my @saddr = map { $_->sockhost.':'.$_->sockport } @servers; unless (fork) { @servers = (); my $ctx = IO::Socket::SSL::SSL_Context->new( SSL_passwd_cb => sub { return "opossum" }, SSL_verify_mode => SSL_VERIFY_PEER, SSL_ca_file => "certs/test-ca.pem", SSL_ca_path => '', SSL_version => 'TLSv1', SSL_cipher_list => 'HIGH', SSL_session_cache_size => 4 ); if (! defined $ctx->{'session_cache'}) { print "not ok \# Context init\n"; exit; } &ok("Context init"); # Bogus session test unless ($ctx->session_cache("bogus", "bogus", 0)) { print "not "; } &ok("Superficial Cache Addition Test"); unless ($ctx->session_cache("bogus1", "bogus1", 0)) { print "not "; } &ok("Superficial Cache Addition Test 2"); my $cache = $ctx->{'session_cache'}; if (keys(%$cache) != 4) { print "not "; } &ok("Cache Keys Check 1"); unless ($cache->{'bogus1:bogus1'} and $cache->{'bogus:bogus'}) { print "not "; } &ok("Cache Keys Check 2"); my ($bogus, $bogus1) = ($cache->{'bogus:bogus'}, $cache->{'bogus1:bogus1'}); unless ($cache->{'_head'} eq $bogus1) { print "not "; } &ok("Cache Head Check"); unless ($bogus1->{prev} eq $bogus and $bogus1->{next} eq $bogus and $bogus->{prev} eq $bogus1 and $bogus->{next} eq $bogus1) { print "not "; } &ok("Cache Link Check"); IO::Socket::SSL::set_default_context($ctx); my $sock3 = IO::Socket::INET->new($saddr[2]); my @clients = ( IO::Socket::SSL->new( PeerAddr => $saddr[0], SSL_verify_mode => 0 ), IO::Socket::SSL->new( PeerAddr => $saddr[1], SSL_verify_mode => 0 ), IO::Socket::SSL->start_SSL( $sock3 , SSL_verify_mode => 0), ); if ( grep { !$_ } @clients >0 ) { print "not ok \# Client init\n"; exit; } &ok("Client init"); # Make sure that first 'bogus' entry has been removed if (keys(%$cache) != 6) { warn Dumper($cache); use Data::Dumper; print "not "; } &ok("Cache Keys Check 3"); if ($cache->{'bogus:bogus'}) { print "not "; } &ok("Cache Removal Test"); if ($cache->{'_head'}->{prev} ne $bogus1) { print "not "; } &ok("Cache Tail Check"); if ($cache->{'_head'} ne $cache->{$saddr[2]}) { print "not "; } &ok("Cache Insertion Test"); for (0..2) { if (Net::SSLeay::get_session($clients[$_]->_get_ssl_object) ne $cache->{$saddr[$_]}->{session}) { print "not "; } &ok("Cache Entry Test $_"); close $clients[$_]; } @clients = map { IO::Socket::SSL->new( PeerAddr => $_, SSL_verify_mode => 0, ) } @saddr; if (keys(%$cache) != 6) { print "not "; } &ok("Cache Keys Check 4"); if (!$cache->{'bogus1:bogus1'}) { print "not "; } &ok("Cache Keys Check 5"); for (0..2) { if (Net::SSLeay::get_session($clients[$_]->_get_ssl_object) ne $cache->{$saddr[$_]}->{session}) { print "not "; } &ok("Second Cache Entry Test $_"); unless ($clients[$_]->print("Test $_\n")) { print "not "; } &ok("Write Test $_"); unless ($clients[$_]->readline eq "Ok $_\n") { print "not "; } &ok("Read Test $_"); close $clients[$_]; } exit(0); } my @clients = map { scalar $_->accept } @servers; if ( grep { !$_ } @clients > 0 ) { print "not ok \# Client init\n"; exit; } &ok("Client init"); close($_) for @clients; @clients = map { scalar $_->accept } @servers; if ( grep { !$_ } @clients > 0 ) { print $SSL_ERROR; print "not ok \# Client init 2\n"; exit; } &ok("Client init 2"); for (0..2) { unless ($clients[$_]->readline eq "Test $_\n") { print "not "; } &ok("Server Read $_"); unless ($clients[$_]->print("Ok $_\n")) { print "not "; } &ok("Server Write $_"); close $clients[$_]; close $servers[$_]; } wait; sub ok { print "ok #$_[0]\n"; } sub bail { print "Bail Out! $IO::Socket::SSL::ERROR"; } IO-Socket-SSL-1.965/t/io-socket-inet6.t0000644000175100017520000000447212265470670016053 0ustar workwork#!perl # make sure IO::Socket::IP will not be used BEGIN { if ( eval { require Acme::Override::INET }) { print "1..0 # Skipped: will not work with Acme::Override::INET installed\n"; exit } $INC{'IO/Socket/IP.pm'} = undef } use strict; use warnings; use Net::SSLeay; use Socket; use IO::Socket::SSL; if ( grep { $^O =~m{$_} } qw( MacOS VOS vmesa riscos amigaos ) ) { print "1..0 # Skipped: fork not implemented on this platform\n"; exit } # check first if we have loaded IO::Socket::IP, as if so we won't need or use # IO::Socket::INET6 if( IO::Socket::SSL->CAN_IPV6 eq "IO::Socket::IP" ) { print "1..0 # Skipped: using IO::Socket::IP instead\n"; exit; } # check if we have loaded INET6, IO::Socket::SSL should do it by itself # if it is available unless( IO::Socket::SSL->CAN_IPV6 eq "IO::Socket::INET6" ) { # not available or IO::Socket::SSL forgot to load it if ( ! eval { require IO::Socket::INET6 } ) { print "1..0 # Skipped: no IO::Socket::INET6 available\n"; } else { print "1..1\nnot ok # automatic use of INET6\n"; } exit } my $addr = '::1'; # check if we can use ::1, e.g if the computer has IPv6 enabled if ( ! IO::Socket::INET6->new( Listen => 10, LocalAddr => $addr, )) { print "1..0 # no IPv6 enabled on this computer\n"; exit } $|=1; print "1..3\n"; # first create simple ssl-server my $ID = 'server'; my $server = IO::Socket::SSL->new( LocalAddr => $addr, Listen => 2, SSL_cert_file => "certs/server-cert.pem", SSL_key_file => "certs/server-key.pem", ) || do { notok($!); exit }; ok("Server Initialization at $addr"); # add server port to addr $addr = "[$addr]:".$server->sockport; print "# server at $addr\n"; my $pid = fork(); if ( !defined $pid ) { die $!; # fork failed } elsif ( !$pid ) { ###### Client $ID = 'client'; close($server); my $to_server = IO::Socket::SSL->new( PeerAddr => $addr, SSL_verify_mode => 0, ) || do { notok( "connect failed: ".IO::Socket::SSL->errstr() ); exit }; ok( "client connected" ); } else { ###### Server my $to_client = $server->accept || do { notok( "accept failed: ".$server->errstr() ); kill(9,$pid); exit; }; ok( "Server accepted" ); wait; } sub ok { print "ok # [$ID] @_\n"; } sub notok { print "not ok # [$ID] @_\n"; } IO-Socket-SSL-1.965/t/npn.t0000644000175100017520000000351712263174431013717 0ustar workwork#!perl # Before `make install' is performed this script should be runnable with # `make test'. After `make install' it should work as `perl t/dhe.t' use strict; use warnings; use Net::SSLeay; use Socket; use IO::Socket::SSL; if ( grep { $^O =~m{$_} } qw( MacOS VOS vmesa riscos amigaos ) ) { print "1..0 # Skipped: fork not implemented on this platform\n"; exit } # check if we have NPN available # if it is available if ( ! IO::Socket::SSL->can_npn ) { print "1..0 # Skipped: NPN not available in Net::SSLeay\n"; exit } $|=1; print "1..5\n"; # first create simple ssl-server my $ID = 'server'; my $addr = '127.0.0.1'; my $server = IO::Socket::SSL->new( LocalAddr => $addr, Listen => 2, SSL_cert_file => 'certs/server-cert.pem', SSL_key_file => 'certs/server-key.pem', SSL_npn_protocols => [qw(one two)], ) || do { ok(0,$!); exit }; ok(1,"Server Initialization at $addr"); # add server port to addr $addr = "$addr:".$server->sockport; print "# server at $addr\n"; my $pid = fork(); if ( !defined $pid ) { die $!; # fork failed } elsif ( !$pid ) { ###### Client $ID = 'client'; close($server); my $to_server = IO::Socket::SSL->new( PeerHost => $addr, SSL_verify_mode => 0, SSL_npn_protocols => [qw(two three)], ) or do { ok(0, "connect failed: ".IO::Socket::SSL->errstr() ); exit }; ok(1,"client connected" ); my $proto = $to_server->next_proto_negotiated; ok($proto eq 'two',"negotiated $proto"); } else { ###### Server my $to_client = $server->accept or do { ok(0,"accept failed: ".$server->errstr() ); kill(9,$pid); exit; }; ok(1,"Server accepted" ); my $proto = $to_client->next_proto_negotiated; ok($proto eq 'two',"negotiated $proto"); wait; } sub ok { my $ok = shift; print $ok ? '' : 'not ', "ok # [$ID] @_\n"; } IO-Socket-SSL-1.965/t/sysread_write.t0000644000175100017520000000745412263174431016014 0ustar workwork#!perl # Before `make install' is performed this script should be runnable with # `make test'. After `make install' it should work as `perl t/sysread_write.t' # This tests that sysread/syswrite behave different to read/write, e.g. # that the latter ones are blocking until they read/write everything while # the sys* function also can read/write partial data. use strict; use warnings; use Net::SSLeay; use Socket; use IO::Socket::SSL; if ( grep { $^O =~m{$_} } qw( MacOS VOS vmesa riscos amigaos ) ) { print "1..0 # Skipped: fork not implemented on this platform\n"; exit } $|=1; print "1..9\n"; ################################################################# # create Server socket before forking client, so that it is # guaranteed to be listening ################################################################# # first create simple ssl-server my $ID = 'server'; my $server = IO::Socket::SSL->new( LocalAddr => '127.0.0.1', LocalPort => 0, Listen => 2, SSL_cert_file => "certs/client-cert.pem", SSL_key_file => "certs/client-key.pem", ); print "not ok: $!\n", exit if !$server; ok("Server Initialization"); my $saddr = $server->sockhost.':'.$server->sockport; defined( my $pid = fork() ) || die $!; if ( $pid == 0 ) { ############################################################ # CLIENT == child process ############################################################ close($server); $ID = 'client'; my $to_server = IO::Socket::SSL->new( PeerAddr => $saddr, SSL_ca_file => "certs/test-ca.pem", ) || do { print "not ok: connect failed: $!\n"; exit }; ok( "client connected" ); # write 512 byte, server reads it in 66 byte chunks which # should cause at least the last read to be less then 66 bytes # (and not block). alarm(10); $SIG{ALRM} = sub { print "not ok: timed out\n"; exit; }; #DEBUG( "send 2x512 byte" ); unless ( syswrite( $to_server, 'x' x 512 ) == 512 and syswrite( $to_server, 'x' x 512 ) == 512 ) { print "not ok: write to small: $!\n"; exit; } sysread( $to_server,my $ack,1 ) || print "not "; ok( "received ack" ); alarm(0); ok( "send in time" ); # make a syswrite with a buffer length greater than the # ssl message block size (16k for sslv3). It should send # only a partial packet of 16k my $n = syswrite( $to_server, 'x' x 18000 ); #DEBUG( "send $n bytes" ); print "not " if $n != 16384; ok( "partial write in syswrite" ); # TODO does not work on Win32!!! print "ok # TODO(win32): " if $^O=~m{mswin32}i; # but write should send everything because it does ssl_write_all $n = $to_server->write( 'x' x 18000 ); #DEBUG( "send $n bytes" ); print "not " if $n != 18000; ok( "full write in write ($n)" ); exit; } else { ############################################################ # SERVER == parent process ############################################################ my $to_client = $server->accept || do { print "not ok: accept failed: $!\n"; kill(9,$pid); exit; }; ok( "Server accepted" ); my $total = 1024; my $partial; while ( $total > 0 ) { #DEBUG( "reading 66 of $total bytes pending=".$to_client->pending() ); my $n = sysread( $to_client, my $buf,66 ); #DEBUG( "read $n bytes" ); if ( !$n ) { print "not ok: read failed: $!\n"; kill(9,$pid); exit; } elsif ( $n != 66 ) { $partial++; } $total -= $n; } print "not " if !$partial; ok( "partial read in sysread" ); # send ack back print "not " if !syswrite( $to_client, 'x' ); ok( "send ack back" ); # just read so that the writes will not block $to_client->read( my $buf,18000 ); $to_client->read( $buf,18000 ); # wait until client exits wait; } exit; sub ok { print "ok # [$ID] @_\n"; } IO-Socket-SSL-1.965/t/signal-readline.t0000644000175100017520000000270612263174431016161 0ustar workwork#!perl use strict; use warnings; use Net::SSLeay; use Socket; use IO::Socket::SSL; if ( grep { $^O =~m{$_} } qw( MacOS VOS vmesa riscos amigaos ) ) { print "1..0 # Skipped: fork not implemented on this platform\n"; exit } if ( $^O =~m{mswin32}i ) { print "1..0 # Skipped: signals not relevant on this platform\n"; exit } print "1..9\n"; my $server = IO::Socket::SSL->new( LocalAddr => '127.0.0.1', LocalPort => 0, Listen => 2, SSL_server => 1, SSL_ca_file => "certs/test-ca.pem", SSL_cert_file => "certs/server-wildcard.pem", SSL_key_file => "certs/server-wildcard.pem", ); warn "\$!=$!, \$\@=$@, S\$SSL_ERROR=$SSL_ERROR" if ! $server; print "not ok\n", exit if !$server; ok("Server Initialization"); my $saddr = $server->sockhost.':'.$server->sockport; defined( my $pid = fork() ) || die $!; if ( $pid == 0 ) { $SIG{HUP} = sub { ok("got hup") }; close($server); my $client = IO::Socket::SSL->new( PeerAddr => $saddr, SSL_verify_mode => 0 ) || print "not "; ok( "client ssl connect" ); my $line = <$client>; print "not " if $line ne "foobar\n"; ok("got line"); exit; } my $csock = $server->accept; ok("accept"); $SIG{PIPE} = 'IGNORE'; syswrite($csock,"foo") or print "not "; ok("wrote foo"); sleep(1); kill HUP => $pid or print "not "; ok("send hup"); sleep(1); syswrite($csock,"bar\n") or print "not "; ok("wrote bar\\n"); wait; ok("wait: $?"); sub ok { print "ok #$_[0]\n"; } IO-Socket-SSL-1.965/t/sni.t0000644000175100017520000000425412263174431013714 0ustar workwork#!perl use strict; use warnings; use Net::SSLeay; use Socket; use IO::Socket::SSL; if ( grep { $^O =~m{$_} } qw( MacOS VOS vmesa riscos amigaos ) ) { print "1..0 # Skipped: fork not implemented on this platform\n"; exit } if ( ! IO::Socket::SSL->can_server_sni() ) { print "1..0 # skipped because no server side SNI support - openssl/Net::SSleay too old\n"; exit; } if ( ! IO::Socket::SSL->can_client_sni() ) { print "1..0 # skipped because no client side SNI support - openssl/Net::SSleay too old\n"; exit; } print "1..17\n"; my $server = IO::Socket::SSL->new( LocalAddr => '127.0.0.1', Listen => 2, ReuseAddr => 1, SSL_server => 1, SSL_ca_file => "certs/test-ca.pem", SSL_cert_file => { 'server.local' => 'certs/server-cert.pem', 'client.local' => 'certs/client-cert.pem', 'smtp.mydomain.local' => "certs/server-wildcard.pem", '' => "certs/server-wildcard.pem", }, SSL_key_file => { 'server.local' => 'certs/server-key.pem', 'client.local' => 'certs/client-key.pem', 'smtp.mydomain.local' => "certs/server-wildcard.pem", '' => "certs/server-wildcard.pem", }, ); warn "\$!=$!, \$\@=$@, S\$SSL_ERROR=$SSL_ERROR" if ! $server; print "not ok\n", exit if !$server; print "ok # Server Initialization\n"; my $saddr = $server->sockhost.':'.$server->sockport; # www13.other.local should match default '' # all other should match the specific entries my @tests = qw( server.local client.local smtp.mydomain.local www13.other.local ); defined( my $pid = fork() ) || die $!; if ( $pid == 0 ) { close($server); for my $host (@tests) { my $client = IO::Socket::SSL->new( PeerAddr => $saddr, SSL_verify_mode => 1, SSL_hostname => $host, SSL_ca_file => 'certs/my-ca.pem', ) || print "not "; print "ok # client ssl connect $host\n"; $client->verify_hostname($host,'http') or print "not "; print "ok # client verify hostname in cert $host\n"; } exit; } for my $host (@tests) { my $csock = $server->accept or print "not "; print "ok # server accept\n"; my $name = $csock->get_servername; print "not " if ! $name or $name ne $host; print "ok # server got SNI name $host\n"; } wait; IO-Socket-SSL-1.965/t/acceptSSL-timeout.t0000644000175100017520000000360712263174431016431 0ustar workworkuse strict; use warnings; use IO::Socket::SSL; do './testlib.pl' || do './t/testlib.pl' || die "no testlib"; $|=1; print "1..15\n"; # first use SSL client { my ($server,$saddr) = create_listen_socket(); ok(1, "listening \@$saddr" ); my $srv = fork_sub( 'server',$server ); close($server); fd_grep_ok( 'Waiting', $srv ); my $cl = fork_sub( 'client_ssl',$saddr ); fd_grep_ok( 'Connect from',$srv ); fd_grep_ok( 'Connected', $cl ); fd_grep_ok( 'SSL Handshake OK', $srv ); fd_grep_ok( 'Hi!', $cl ); } # then try bad non-SSL client if ( $^O =~m{mswin32}i ) { # skip ok( 1, "skip - TODO on win32" ) for(1..7); } else { my ($server,$saddr) = create_listen_socket(); ok(1, "listening \@$saddr" ); my $srv = fork_sub( 'server',$server ); close($server); fd_grep_ok( 'Waiting', $srv ); my $cl = fork_sub( 'client_no_ssl',$saddr ); fd_grep_ok( 'Connect from',$srv ); fd_grep_ok( 'Connected', $cl ); fd_grep_ok( 'SSL Handshake FAILED', $srv ); } sub server { my $server = shift; print "Waiting\n"; my $client = $server->accept || die "accept failed: $!"; print "Connect from ".$client->peerhost.':'.$client->peerport."\n"; if ( IO::Socket::SSL->start_SSL( $client, SSL_server => 1, Timeout => 5, SSL_cert_file => 'certs/server-cert.pem', SSL_key_file => 'certs/server-key.pem', )) { print "SSL Handshake OK\n"; print $client "Hi!\n"; } else { print "SSL Handshake FAILED - $!\n" } } sub client_no_ssl { my $saddr = shift; my $c = IO::Socket::INET->new( $saddr ) || die "connect failed: $!"; print "Connected\n"; while ( sysread( $c,my $buf,8000 )) {} } sub client_ssl { my $saddr = shift; my $c = IO::Socket::SSL->new( PeerAddr => $saddr, SSL_verify_mode => 0 ) || die "connect failed: $!|$SSL_ERROR"; print "Connected\n"; while ( sysread( $c,my $buf,8000 )) { print $buf } } IO-Socket-SSL-1.965/META.yml0000644000175100017520000000156212265775222013752 0ustar workwork--- #YAML:1.0 name: IO-Socket-SSL version: 1.965 abstract: Nearly transparent SSL encapsulation for IO::Socket::INET. author: - Steffen Ullrich , Peter Behroozi, Marko Asplund license: perl distribution_type: module configure_requires: ExtUtils::MakeMaker: 0 build_requires: ExtUtils::MakeMaker: 0 requires: Net::SSLeay: 1.46 Scalar::Util: 0 resources: bugtracker: https://rt.cpan.org/Dist/Display.html?Queue=IO-Socket-SSL homepage: https://github.com/noxxi/p5-io-socket-ssl license: http://dev.perl.org/licenses/ repository: https://github.com/noxxi/p5-io-socket-ssl no_index: directory: - t - inc generated_by: ExtUtils::MakeMaker version 6.57_05 meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 IO-Socket-SSL-1.965/example/0000755000175100017520000000000012265775222014130 5ustar workworkIO-Socket-SSL-1.965/example/ssl_server.pl0000644000175100017520000000313211136164317016644 0ustar workwork# # a test server for testing IO::Socket::SSL-class's behavior # (marko.asplund at kronodoc.fi). # # $Id: ssl_server.pl,v 1.7 2000/11/08 09:25:21 aspa Exp $. # use strict; use IO::Socket::SSL; my ($sock, $s, $v_mode); if($ARGV[0] eq "DEBUG") { $IO::Socket::SSL::DEBUG = 1; } # Check to make sure that we were not accidentally run in the wrong # directory: unless (-d "certs") { if (-d "../certs") { chdir ".."; } else { die "Please run this example from the IO::Socket::SSL distribution directory!\n"; } } if(!($sock = IO::Socket::SSL->new( Listen => 5, LocalAddr => 'localhost', LocalPort => 9000, Proto => 'tcp', Reuse => 1, SSL_verify_mode => 0x01, SSL_passwd_cb => sub {return "bluebell"}, )) ) { warn "unable to create socket: ", &IO::Socket::SSL::errstr, "\n"; exit(0); } warn "socket created: $sock.\n"; while (1) { warn "waiting for next connection.\n"; while(($s = $sock->accept())) { my ($peer_cert, $subject_name, $issuer_name, $date, $str); if( ! $s ) { warn "error: ", $sock->errstr, "\n"; next; } warn "connection opened ($s).\n"; if( ref($sock) eq "IO::Socket::SSL") { $subject_name = $s->peer_certificate("subject"); $issuer_name = $s->peer_certificate("issuer"); } warn "\t subject: '$subject_name'.\n"; warn "\t issuer: '$issuer_name'.\n"; my $date = localtime(); print $s "my date command says it's: '$date'"; close($s); warn "\t connection closed.\n"; } } $sock->close(); warn "loop exited.\n"; IO-Socket-SSL-1.965/example/async_https_server.pl0000644000175100017520000001106312263174431020404 0ustar workwork########################################################## # example HTTPS server using nonblocking sockets # requires Event::Lib # at the moment the response consists only of the HTTP # request, send back as text/plain ########################################################## use strict; use IO::Socket; use IO::Socket::SSL; use Event::Lib; use Errno ':POSIX'; #$Net::SSLeay::trace=3; eval 'use Debug'; *{DEBUG} = sub {} if !defined(&DEBUG); # create server socket my $server = IO::Socket::INET->new( LocalAddr => '0.0.0.0:9000', Listen => 10, Reuse => 1, Blocking => 0, ) || die $!; event_new( $server, EV_READ|EV_PERSIST, \&_s_accept )->add(); event_mainloop; ########################################################## ### accept new client on server socket ########################################################## sub _s_accept { my $fds = shift->fh; my $fdc = $fds->accept || return; DEBUG( "new client" ); $fdc = IO::Socket::SSL->start_SSL( $fdc, SSL_startHandshake => 0, SSL_server => 1, ) || die $!; $fdc->blocking(0); _ssl_accept( undef,$fdc ); } ########################################################## ### ssl handshake with client ### called again and again until the handshake is done ### this is called first from _s_accept w/o an event ### and later enters itself as new event until the ### handshake is done ### if the handshake is done it inits the buffers for the ### client socket and adds an event for reading the HTTP header ########################################################## sub _ssl_accept { my ($event,$fdc) = @_; $fdc ||= $event->fh; if ( $fdc->accept_SSL ) { DEBUG( "new client ssl handshake done" ); # setup the client ${*$fdc}{rbuf} = ${*$fdc}{wbuf} = ''; event_new( $fdc, EV_READ, \&_client_read_header )->add; } elsif ( $! != EAGAIN ) { die "new client failed: $!|$SSL_ERROR"; } else { DEBUG( "new client need to retry accept: $SSL_ERROR" ); my $what = $SSL_ERROR == SSL_WANT_READ ? EV_READ : $SSL_ERROR == SSL_WANT_WRITE ? EV_WRITE : die "unknown error"; event_new( $fdc, $what, \&_ssl_accept )->add; } } ########################################################## ### read http header ### this will re-add itself as an event until the full ### http header was read ### after reading the header it will setup the response ### which will for now just send the header back as text/plain ########################################################## sub _client_read_header { my $event = shift; my $fdc = $event->fh; DEBUG( "reading header" ); my $rbuf_ref = \${*$fdc}{rbuf}; my $n = sysread( $fdc,$$rbuf_ref,8192,length($$rbuf_ref)); if ( !defined($n)) { die $! if $! != EAGAIN; DEBUG( $SSL_ERROR ); if ( $SSL_ERROR == SSL_WANT_WRITE ) { # retry read once I can write event_new( $fdc, EV_WRITE, \&_client_read_header )->add; } else { $event->add; # retry } } elsif ( $n == 0 ) { DEBUG( "connection closed" ); close($fdc); } else { # check if we have the whole http header my $i = index( $$rbuf_ref,"\r\n\r\n" ); # check \r\n\r\n $i = index( $$rbuf_ref,"\n\n" ) if $i<0; # bad clients send \n\n only if ( $i<0 ) { $event->add; # read more from header return; } # got full header, send request back (we don't serve real pages yet) my $header = substr( $$rbuf_ref,0,$i,'' ); DEBUG( "got header:\n$header" ); my $wbuf_ref = \${*$fdc}{wbuf}; $$wbuf_ref = "HTTP/1.0 200 Ok\r\nContent-type: text/plain\r\n\r\n".$header; DEBUG( "will send $$wbuf_ref" ); event_new( $fdc, EV_WRITE, \&_client_write_response )->add; } } ########################################################## ### this is called to write the response to the client ### this will re-add itself as an event as until the full ### response was send ### if it's done it will just close the socket ########################################################## sub _client_write_response { my $event = shift; DEBUG( "writing response" ); my $fdc = $event->fh; my $wbuf_ref = \${*$fdc}{wbuf}; my $n = syswrite( $fdc,$$wbuf_ref ); if ( !defined($n) && $! == EAGAIN) { # retry DEBUG( $SSL_ERROR ); if ( $SSL_ERROR == SSL_WANT_READ ) { # retry write once we can read event_new( $fdc, EV_READ, \&_client_write_response )->add; } else { $event->add; # retry again } } elsif ( $n == 0 ) { DEBUG( "connection closed: $!" ); close($fdc); } else { DEBUG( "wrote $n bytes" ); substr($$wbuf_ref,0,$n,'' ); if ($$wbuf_ref eq '') { DEBUG( "done" ); close($fdc); } else { # send more $event->add } } } IO-Socket-SSL-1.965/example/lwp-with-verifycn.pl0000644000175100017520000000057611136164317020064 0ustar workworkuse strict; use warnings; ## !!! make sure that Net::SSL never gets loaded, otherwise it will ## be used instead of IO::Socket::SSL from LWP use IO::Socket::SSL 'debug0'; use LWP::Simple; IO::Socket::SSL::set_ctx_defaults( SSL_verifycn_scheme => 'www', SSL_verify_mode => 1, SSL_ca_file => 'verisign.pem', # root CA of verisign ); print get( 'https://signin.ebay.com' ); IO-Socket-SSL-1.965/example/ssl_mitm.pl0000644000175100017520000000327012263174431016307 0ustar workwork#!/usr/bin/perl # simple HTTPS proxy with SSL bridging, uses Net::PcapWriter to # to log unencrypted traffic my $listen = '127.0.0.1:8443'; # where to listen my $connect = 'www.google.com:443'; # where to connect use strict; use warnings; use IO::Socket::SSL; use IO::Socket::SSL::Intercept; use IO::Socket::SSL::Utils; my ($proxy_cert,$proxy_key) = CERT_create( CA => 1, subject => { commonName => 'foobar' } ); my $mitm = IO::Socket::SSL::Intercept->new( proxy_cert => $proxy_cert, proxy_key => $proxy_key, ); my $listener = IO::Socket::INET->new( LocalAddr => $listen, Listen => 10, Reuse => 1, ) or die "failed to create listener: $!"; while (1) { # get connection from client my $toc = $listener->accept or next; # create new connection to server my $tos = IO::Socket::SSL->new( PeerAddr => $connect, SSL_verify_mode => 1, SSL_ca_path => '/etc/ssl/certs', ) or die "ssl connect to $connect failed: $!,$SSL_ERROR"; # clone cert from server my ($cert,$key) = $mitm->clone_cert( $tos->peer_certificate ); # and upgrade connection to client to SSL with cloned cert IO::Socket::SSL->start_SSL($toc, SSL_server => 1, SSL_cert => $cert, SSL_key => $key, ) or die "failed to ssl upgrade: $SSL_ERROR"; # transfer data my $readmask = ''; vec($readmask,fileno($tos),1) = 1; vec($readmask,fileno($toc),1) = 1; while (1) { select( my $can_read = $readmask,undef,undef,undef ) >0 or die $!; if ( vec($can_read,fileno($tos),1)) { sysread($tos,my $buf,100) or last; print $toc $buf; } if ( vec($can_read,fileno($toc),1)) { sysread($toc,my $buf,100) or last; print $tos $buf; } } } IO-Socket-SSL-1.965/example/ssl_client.pl0000644000175100017520000000246711136164317016626 0ustar workwork# # a test client for testing IO::Socket::SSL-class's behavior # (marko.asplund at kronodoc.fi). # # $Id: ssl_client.pl,v 1.7 2002/01/04 08:45:12 aspa Exp $. # use strict; use IO::Socket::SSL; my ($v_mode, $sock, $buf); if($ARGV[0] eq "DEBUG") { $IO::Socket::SSL::DEBUG = 1; } # Check to make sure that we were not accidentally run in the wrong # directory: unless (-d "certs") { if (-d "../certs") { chdir ".."; } else { die "Please run this example from the IO::Socket::SSL distribution directory!\n"; } } if(!($sock = IO::Socket::SSL->new( PeerAddr => 'localhost', PeerPort => '9000', Proto => 'tcp', SSL_use_cert => 1, SSL_verify_mode => 0x01, SSL_passwd_cb => sub { return "opossum" }, ))) { warn "unable to create socket: ", &IO::Socket::SSL::errstr, "\n"; exit(0); } else { warn "connect ($sock).\n" if ($IO::Socket::SSL::DEBUG); } # check server cert. my ($subject_name, $issuer_name, $cipher); if( ref($sock) eq "IO::Socket::SSL") { $subject_name = $sock->peer_certificate("subject"); $issuer_name = $sock->peer_certificate("issuer"); $cipher = $sock->get_cipher(); } warn "cipher: $cipher.\n", "server cert:\n", "\t '$subject_name' \n\t '$issuer_name'.\n\n"; my ($buf) = $sock->getlines; $sock->close(); print "read: '$buf'.\n"; IO-Socket-SSL-1.965/BUGS0000644000175100017520000000633212263174431013155 0ustar workworkSee documentation. Following are some common errors to watch out for: It doesn't work together with Storable::fd_retrieve|fd_store, see https://rt.cpan.org/Ticket/Display.html?id=23419. You need to use freeze/nfreeze/thaw and syswrite/sysread the data yourself. See the bug for examples how to do it. --------------------- If you get an SSL connection but not certificate you might check the cipher with Net::SSLeay::get_cipher( $socket->_get_ssl_object ). If it is something like 'ADH-AES256-SHA' you should try to disable ADH in your cipherlist, e.g. set SSL_cipherlist to 'ALL:!ADH' or just leave it empty so that it uses the openssl default which does not include ADH. --------------------- There is a problem with openssl versions 0.9.8a and 0.9.8b, see http://marc.theaimsgroup.com/?l=openssl-dev&m=113550694922967&w=2 The bug was fixed in newer releases, but if you are forced to use these buggy versions you should apply a patch to Net::SSLeay 1.30, see http://rt.cpan.org/Public/Bug/Display.html?id=22910. --------------------- If you plan on having IO::Socket::SSL sockets auto-close themselves when they go out of scope (like LWP::UserAgent expects), you will need to get Scalar::Util or WeakRef from CPAN (Scalar::Util comes standard with Perl 5.8.0 and above). This is because the self-tying mechanism that IO::Socket::SSL uses to appear simultaneously as an object and a glob reference only works if a circular reference is used. --------------------- Note that a random number generator is required for the proper operation of this module. Systems that have /dev/random or /dev/urandom are fine, but those that do not, like most versions of Solaris, will need to fetch one before installing IO::Socket::SSL. If you don't already have a favorite, try EGD (egd.sourceforge.net). --------------------- Versions of perl-ldap below v0.26 do not work with this version of IO::Socket::SSL because they contain a workaround for old versions of IO::Socket::SSL that breaks new versions. --------------------- Note that when writing a preforking server (a server that accepts a connection and then hands it off to a child for processing), it is best to handle SSL negotiation after the socket has been passed to the child (using socket_to_SSL()). If implemented so that the server handles negotiation, a failed negotiation may tie up the server until the connection times out. --------------------- One user mentioned that the following did not work as it should in IO::Socket::SSL, but worked in IO::Socket::INET: chomp($var = <$socket>); print ord(chop($var)); # Prints "10" for people using ASCII This is due to a bug in Perl that is fixed in 5.8.1. If you need a workaround, try one of the following: chomp($var = $socket->getline()); chomp($var = scalar <$socket>); chomp($var = $var = <$socket>); Any function that returns the value of <$socket> (in scalar context) unchanged will work. --------------------- If you have 384-bit RSA keys you need to use Diffie Hellman Key Exchange. See the parameter SSL_dh_file or SSL_dh for how to use it and http://groups.google.de/group/mailing.openssl.users/msg/d60330cfa7a6034b for an explanation why you need it. -- Steffen Ullrich (Steffen_Ullrich at genua.de) Peter Behroozi (behrooz at fas.harvard.edu) IO-Socket-SSL-1.965/certs/0000755000175100017520000000000012265775222013615 5ustar workworkIO-Socket-SSL-1.965/certs/proxyca.pem0000644000175100017520000000334612263174431016004 0ustar workwork-----BEGIN CERTIFICATE----- MIICXDCCAcWgAwIBAgIJAPcrxpCHBqEIMA0GCSqGSIb3DQEBBQUAMEcxCzAJBgNV BAYTAkRFMRMwEQYDVQQIDApTb21lLVN0YXRlMSMwIQYDVQQKDBpJTzo6U29ja2V0 OjpTU0w6OkludGVyY2VwdDAeFw0xMzA1MjkxNzE3MjdaFw0yMzA1MjcxNzE3Mjda MEcxCzAJBgNVBAYTAkRFMRMwEQYDVQQIDApTb21lLVN0YXRlMSMwIQYDVQQKDBpJ Tzo6U29ja2V0OjpTU0w6OkludGVyY2VwdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAw gYkCgYEA3tXNX5XOwibRHUyHU2tN1FlI8dYMJtI9L+Si1QFA/DBsEXDJUocDf9SU UPacGtEsqRiRaptw3I7QnrggmR+4Id8np5rO9xlucLtQSBvVDZy8Y4hI3kV7Oeup 14JnfSQj/gVTJNolDUzI0u08ZZiKSS7d5DOw5cOu5F67UAfSOdUCAwEAAaNQME4w HQYDVR0OBBYEFBfCIp9KkFUPPix/KFXyTIa7hNN3MB8GA1UdIwQYMBaAFBfCIp9K kFUPPix/KFXyTIa7hNN3MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEA MiF5uUZE4Xm5lUc8Yql1k1eGiVKR9nKpGIwOIUFC0SahiG8wZDkp7v8id0vtu8Pk R8tcOLsiKHYMfg49DiByBiMKA7m5+DQL8av4LD5wNJLM5Ha592jhqblVBLeEOCuB TfouWu+ieAQO/kAU+WCZLRN5Oc/NnI4fsV6ph5zqSc4= -----END CERTIFICATE----- -----BEGIN RSA PRIVATE KEY----- MIICWwIBAAKBgQDe1c1flc7CJtEdTIdTa03UWUjx1gwm0j0v5KLVAUD8MGwRcMlS hwN/1JRQ9pwa0SypGJFqm3DcjtCeuCCZH7gh3yenms73GW5wu1BIG9UNnLxjiEje RXs566nXgmd9JCP+BVMk2iUNTMjS7TxlmIpJLt3kM7Dlw67kXrtQB9I51QIDAQAB AoGAK3Xrnk7rinZjpqE8a4qsHVRko7YpnJC4mlSvZXffItCW4zfqLAxlJFNjsf7H J3vQiBJgmjhC5OF90tb6lKLZGHTvUQRLIGOytHKJlO4qHKWvzqDv9R4qQPBnAHeC tOUXnxSmvxNrNKHW4talLPn6aqHkQwBeKKq1E85d+NzGnGkCQQDxoUUvI5S8/qFb CpaSa3GoDc89r9shnEUzoR24M+oDA3jwtMXy/q8dLtYCX7//PUaScqaOw5APVz8z osiBRxC7AkEA7BZjT0RD+1u9KmVZQfiiVCrJoasd2vDhCcAL0KCFEttMjjutaPeA QMFZiXwUIZWo/7NdRrD9PiQpmw7FZcm+rwJAVQ+fylNtRgchiGo2zX6zeSS7Ywzo SHG5zs4WJ0VnSP5M8ffBg6RywwQ85IMOlOzeTim8Rp/DtBLTtfrFOPVqhwJAB0ix i7KJfmnYLkSuOlDXgU1Ip0pGQ4kHCGv6cVdig7Bsbj79HK32MQlGH+3KGTcq3ajF CfdP+OjYt8X+5SMSVQJAF1zVY5UOQenILFyRCWpgUwIQZRo3FjfJzMykTb8LqgWc nQApujWvWi8qQerxPsAaDLgtfQh3V7ZCZxZRWvuh8A== -----END RSA PRIVATE KEY----- IO-Socket-SSL-1.965/certs/server-wildcard.pem0000644000175100017520000001127711164610340017407 0ustar workworkCertificate: Data: Version: 3 (0x2) Serial Number: d6:d7:e1:b4:b3:30:91:ef Signature Algorithm: sha1WithRSAEncryption Issuer: C=DE, ST=Bayern, L=Muenchen, O=Whatever it is, CN=IO::Socket::SSL Demo CA Validity Not Before: Jan 1 00:00:01 2008 GMT Not After : Mar 30 06:58:42 2019 GMT Subject: C=DE, ST=Bayern, L=Muenchen, O=Whatever it is, CN=server.local Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public Key: (1024 bit) Modulus (1024 bit): 00:bc:5e:af:1f:ac:1b:72:fd:51:d7:54:0c:77:9d: 15:3b:ef:1a:e4:cd:67:70:5a:d5:16:c2:a1:8d:db: a8:ee:79:7a:10:4d:55:60:21:15:34:7b:44:d0:8b: 21:05:3a:d3:2c:26:83:6f:0a:f6:1a:3c:69:cb:bf: 25:4b:77:0d:1a:c4:6f:7a:e5:f3:18:4d:d7:c5:65: d2:90:6a:45:b3:a3:51:73:b8:b1:d2:95:51:bb:73: 0a:85:11:c7:a8:cf:63:8e:24:b8:9a:e3:88:6d:90: 86:ee:ed:97:fd:9a:51:9e:44:9d:b1:c6:3b:92:3a: d5:30:a0:26:98:e9:17:03:15 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE Netscape Comment: OpenSSL Generated Certificate X509v3 Subject Key Identifier: 38:21:43:F0:B2:21:77:17:88:B9:97:49:AE:2B:0A:0E:61:D6:DB:8A X509v3 Authority Key Identifier: keyid:DE:65:01:16:19:2E:51:E0:9A:51:1A:37:50:94:7D:39:29:2A:42:2C DirName:/C=DE/ST=Bayern/L=Muenchen/O=Whatever it is/CN=IO::Socket::SSL Demo CA serial:E7:AD:8B:07:55:8A:17:27 X509v3 Key Usage: Digital Signature, Non Repudiation, Key Encipherment X509v3 Subject Alternative Name: DNS:*.server.local, IP Address:127.0.0.1, DNS:www*.other.local, DNS:smtp.mydomain.local, DNS:xn--lwe-sna.idntest.local Signature Algorithm: sha1WithRSAEncryption 57:e3:6d:aa:00:c3:da:61:ed:75:9a:29:1f:d9:d5:c5:f1:70: f3:c6:00:81:11:95:b4:e1:a3:9d:3a:86:f8:a0:53:42:3b:22: 1d:4b:23:97:b6:69:d7:ea:66:49:67:d4:18:e5:cb:5e:1c:c0: 6f:4d:42:a6:a9:3f:05:5d:4f:6d:38:e9:c1:ca:94:98:45:e3: eb:7b:c5:96:fb:f6:00:a2:0b:29:63:29:be:77:3a:4d:16:d0: 3b:e9:01:0d:95:a6:5c:3f:02:50:23:16:59:a6:26:78:c8:8b: 15:6f:48:b6:d1:77:0f:80:bb:99:c3:5a:ce:58:d3:2e:85:5b: 57:c3 -----BEGIN CERTIFICATE----- MIIDujCCAyOgAwIBAgIJANbX4bSzMJHvMA0GCSqGSIb3DQEBBQUAMGwxCzAJBgNV BAYTAkRFMQ8wDQYDVQQIEwZCYXllcm4xETAPBgNVBAcTCE11ZW5jaGVuMRcwFQYD VQQKEw5XaGF0ZXZlciBpdCBpczEgMB4GA1UEAxMXSU86OlNvY2tldDo6U1NMIERl bW8gQ0EwHhcNMDgwMTAxMDAwMDAxWhcNMTkwMzMwMDY1ODQyWjBhMQswCQYDVQQG EwJERTEPMA0GA1UECBMGQmF5ZXJuMREwDwYDVQQHEwhNdWVuY2hlbjEXMBUGA1UE ChMOV2hhdGV2ZXIgaXQgaXMxFTATBgNVBAMTDHNlcnZlci5sb2NhbDCBnzANBgkq hkiG9w0BAQEFAAOBjQAwgYkCgYEAvF6vH6wbcv1R11QMd50VO+8a5M1ncFrVFsKh jduo7nl6EE1VYCEVNHtE0IshBTrTLCaDbwr2Gjxpy78lS3cNGsRveuXzGE3XxWXS kGpFs6NRc7ix0pVRu3MKhRHHqM9jjiS4muOIbZCG7u2X/ZpRnkSdscY7kjrVMKAm mOkXAxUCAwEAAaOCAW0wggFpMAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9w ZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBQ4IUPwsiF3F4i5 l0muKwoOYdbbijCBngYDVR0jBIGWMIGTgBTeZQEWGS5R4JpRGjdQlH05KSpCLKFw pG4wbDELMAkGA1UEBhMCREUxDzANBgNVBAgTBkJheWVybjERMA8GA1UEBxMITXVl bmNoZW4xFzAVBgNVBAoTDldoYXRldmVyIGl0IGlzMSAwHgYDVQQDExdJTzo6U29j a2V0OjpTU0wgRGVtbyBDQYIJAOetiwdVihcnMAsGA1UdDwQEAwIF4DBhBgNVHREE WjBYgg4qLnNlcnZlci5sb2NhbIcEfwAAAYIQd3d3Ki5vdGhlci5sb2NhbIITc210 cC5teWRvbWFpbi5sb2NhbIIZeG4tLWx3ZS1zbmEuaWRudGVzdC5sb2NhbDANBgkq hkiG9w0BAQUFAAOBgQBX422qAMPaYe11mikf2dXF8XDzxgCBEZW04aOdOob4oFNC OyIdSyOXtmnX6mZJZ9QY5cteHMBvTUKmqT8FXU9tOOnBypSYRePre8WW+/YAogsp Yym+dzpNFtA76QENlaZcPwJQIxZZpiZ4yIsVb0i20XcPgLuZw1rOWNMuhVtXww== -----END CERTIFICATE----- -----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQC8Xq8frBty/VHXVAx3nRU77xrkzWdwWtUWwqGN26jueXoQTVVg IRU0e0TQiyEFOtMsJoNvCvYaPGnLvyVLdw0axG965fMYTdfFZdKQakWzo1FzuLHS lVG7cwqFEceoz2OOJLia44htkIbu7Zf9mlGeRJ2xxjuSOtUwoCaY6RcDFQIDAQAB AoGBALilE4K3YRzBhaTOJX5mgzcBtVoMolV3JCOwW05DwH8qomUyePrG0xNjtdu6 VX7b374KbpG9q+mhyI7I6pTjuPoRaQmVNdUOU8i5F8Wy0vOZFhDSaJoZpehQPkbk f+IqgjAGOQdFXeTMNAeRjUBqfuL5V15uaD9VX/1Xq3pWZyxtAkEA7BVDODOfKTTV Zfgmy4u2KdP4a3E2mHm+MwKpvdrxfmpgphpqfuc077f/36BSPN0jpYVw1IvDdy5z /iSuw+PIPwJBAMxC8vr7wtlTIDbgQWKZLQ8p9N/DUrTlBTUiJCeMdbrOL3tCJETn klaES7gjrgctvU8209T0yv3yTi+kkfInf6sCQGzJ/4fOgfGDHzM1/uqdHvx3aWpZ aUcqErN+7qlGUzJl4tOoKJsCACrXJ1ntjvftD5gevbe0EAbDqT/bt40dUhECQBWW 8fXDTIoJ9jq2o1KXnCKhLafFDmXeWxmNnUKs3vi6uFwP1qON0nLgktxIsSlDFWJd CjDVGuuSg98XRvHQaPcCQHSpGVcl7Y42cYprxSgSWXrLXBIIrq6AT9nREzFTPc3/ TNOdzTyL23tvqYFMzxgA4QK4aLUIdgLlMhx0oXZfaOA= -----END RSA PRIVATE KEY----- IO-Socket-SSL-1.965/certs/my-ca.pem0000644000175100017520000000220311164607314015314 0ustar workwork-----BEGIN CERTIFICATE----- MIIDKDCCApGgAwIBAgIJAOetiwdVihcnMA0GCSqGSIb3DQEBBQUAMGwxCzAJBgNV BAYTAkRFMQ8wDQYDVQQIEwZCYXllcm4xETAPBgNVBAcTCE11ZW5jaGVuMRcwFQYD VQQKEw5XaGF0ZXZlciBpdCBpczEgMB4GA1UEAxMXSU86OlNvY2tldDo6U1NMIERl bW8gQ0EwHhcNMDkwNDAxMDY0NDQ4WhcNMTkwMzMwMDY0NDQ4WjBsMQswCQYDVQQG EwJERTEPMA0GA1UECBMGQmF5ZXJuMREwDwYDVQQHEwhNdWVuY2hlbjEXMBUGA1UE ChMOV2hhdGV2ZXIgaXQgaXMxIDAeBgNVBAMTF0lPOjpTb2NrZXQ6OlNTTCBEZW1v IENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZROfatylcxcbrx0dTXvgo zlqFwps7ghgyx+Qvgwrv72w8dPIpMDk1zTeQPNSy8nTCYIsEr1tGC+T/dYt3raYm 2kXk20QzYiuXOCIUR+JY9xvUdnee9Z1vJD5u7DfkhnAsCJhkxVZ7xoSF4Zei812v i+Z+ePR+/F7uTJyeBbf5QQIDAQABo4HRMIHOMB0GA1UdDgQWBBTeZQEWGS5R4JpR GjdQlH05KSpCLDCBngYDVR0jBIGWMIGTgBTeZQEWGS5R4JpRGjdQlH05KSpCLKFw pG4wbDELMAkGA1UEBhMCREUxDzANBgNVBAgTBkJheWVybjERMA8GA1UEBxMITXVl bmNoZW4xFzAVBgNVBAoTDldoYXRldmVyIGl0IGlzMSAwHgYDVQQDExdJTzo6U29j a2V0OjpTU0wgRGVtbyBDQYIJAOetiwdVihcnMAwGA1UdEwQFMAMBAf8wDQYJKoZI hvcNAQEFBQADgYEAZu8EXePCEhV0LeC0zBXBMUlqu7p0fzQByL9U6SuOmwkKih/w OcsjxX6PFjJm3C5/NJ9mUw8WrbbBTKcMg7t2PvuyIuKK+wK3Nf5XZaGnzwtn1aFz M0LUhtV8z6OcURDEfnQBsgLCPODc9Mg4FEViDGVaZ1i233ZeAlLzXSZeXL8= -----END CERTIFICATE----- IO-Socket-SSL-1.965/certs/server-rsa384-dh.pem0000644000175100017520000000167011164437157017244 0ustar workwork-----BEGIN CERTIFICATE----- MIH7MIG2oAMCAQICAhI0MA0GCSqGSIb3DQEBBAUAMBYxFDASBgNVBAMTC3Jvb3Qu c2VydmVyMB4XDTA2MDgwMTE1MTU1MloXDTA2MDgwMjE1MTU1MlowFjEUMBIGA1UE AxMLcm9vdC5zZXJ2ZXIwTDANBgkqhkiG9w0BAQEFAAM7ADA4AjEAoANEs5TuVeJQ OzQ2+2DKApESDF6JVasfAG/8KnXbv5uYSAio2Eb0SUiP3HdEAvgdAgMBAAEwDQYJ KoZIhvcNAQEEBQADMQBWs7i5qaq8jBhaf4kqAO72s7xawhobUvbi9++6ayu3cg5Z 7KzRgdK3wDV2H/jCkpU= -----END CERTIFICATE----- -----BEGIN RSA PRIVATE KEY----- MIHyAgEAAjEAoANEs5TuVeJQOzQ2+2DKApESDF6JVasfAG/8KnXbv5uYSAio2Eb0 SUiP3HdEAvgdAgMBAAECMFA8E1DxFuldx9lH/2HhUKok0CX/qWGZofDQnTr9CiN7 O+s7Wf07r8Oped85n/IKiQIZANMa1CwI5lo5zdrv0ayn9fWGkHiLlFEs0wIZAMIK 1nsU39QtreUeKNJ9GTlO8NE4bP9xTwIZAK9ACH996+1fK1vj10bkMLXhPjI0fa5d 7QIYRAxW8Sz93cPzMuFjwYVbfix/6W9XUjGjAhgEZGzKnur+N8HvShyhV74TIg7Q XfWYMhQ= -----END RSA PRIVATE KEY----- -----BEGIN DH PARAMETERS----- MEYCQQDeHNGXWnPTGUD8zHYq1XinwW7W1cu/mWBf1WibTJOpIwIrHvfLF9Z0v7Up nOuxI12P+vQUIs73Jjv5lseml+nrAgEC -----END DH PARAMETERS----- IO-Socket-SSL-1.965/certs/server-key.enc0000644000175100017520000000170311164611077016373 0ustar workwork-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,B23BC22B9F68A8C3 oYwok70k0gvbWFIBTXIVJ6QNeXGZZUwRh8DjKKlaNy4UfYS9gINPbmaQgW0ynR0j haKMfPInUwXzIINC8NBc+ALx7fkPcWhZEEyow3nh9WTDggtNAU+Km2x76W/vgNKH PdQAYxqH67zaQK6dGumSTCG/Gz6CLKsHklsvvLZtqJwSeFGp+Vkn/CS7cILiG/Jr tZGSVrcfA3eB6U3+TnZw9F8k09G02hkt5wHk3j44pf9mIgJSS42aZXJ0vwiY8Fjt vjN3fywPN/0YsR+ahtKOvdyXkXsK2Bl5hbUv8wJNMy0wB86/esy8tSO/grhb8d9k KJ8uXm1DoaAd8d4oHwoCvSmMwujIcNkXSIsNUlBwN27FR58PjJA/XAl3uRiTHWZA D1feH3Aplxak94NfnHgfipW5hEYorM6zzYT8dvQ01RzaX8D8cgw1LhuBwXvbj8B6 4gLz+FkVQROIF0w7pJm3QBVCS2HZd36ZLOMVkqfWYxW16dZglvcT0ELkTeddwUHc A59CEL4pfLqqqVOnud13fxR4XXD+qZQPNx0Pm+zD3p+KRUuTupIg/suFEJNZSTpA WPiQ0EbFMcv7lg9jGCDZOG+E5Ir1na4oqDHt+uchF5h3EY1gnQKO/Pu4H3ShfSQ+ u9mMAQ74/ZwQ9nNFDd6+BmbomqORefqKMF/2xdkhfXoG3YwKLWXenOCG0j3DWiml Hlv9WpWLxnifkm2f6kpvwJ623c5E0U/Y4uNf6Vxlxqr+IaG0o6dPVHYz/q0Hsqhf hrWD45uTJrjFhV7nEBcOlukGkUFsNetWyb8EGFb5nimvgKGeJPbcyA== -----END RSA PRIVATE KEY----- IO-Socket-SSL-1.965/certs/client-cert.pem0000644000175100017520000000701511164610044016517 0ustar workworkCertificate: Data: Version: 3 (0x2) Serial Number: d6:d7:e1:b4:b3:30:91:ee Signature Algorithm: sha1WithRSAEncryption Issuer: C=DE, ST=Bayern, L=Muenchen, O=Whatever it is, CN=IO::Socket::SSL Demo CA Validity Not Before: Jan 1 00:00:01 2008 GMT Not After : Mar 30 06:56:31 2019 GMT Subject: C=DE, ST=Bayern, L=Muenchen, O=Whatever it is, CN=client.local Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public Key: (1024 bit) Modulus (1024 bit): 00:d9:49:27:43:41:46:9b:83:d3:22:2a:ed:1f:97: 0c:63:8c:06:3f:4c:0a:74:3e:c3:97:be:27:57:f2: 40:18:40:7c:9d:3f:af:12:be:7c:ec:3f:01:bb:0e: bd:0b:fd:0d:30:8f:7a:b9:b7:f2:f7:ef:f8:c7:e2: bf:77:6f:25:26:ab:76:e4:17:4c:3c:e5:c3:29:22: 92:38:de:82:f7:03:9c:3d:f8:08:35:b5:fb:90:57: 05:48:8b:11:00:4d:97:f8:39:07:bb:36:5a:13:df: a6:15:d3:6c:5a:7f:31:31:39:8e:b0:82:8d:43:ac: 3c:9f:a6:f0:6f:3f:c9:f7:a7 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE Netscape Comment: OpenSSL Generated Certificate X509v3 Subject Key Identifier: A3:81:A9:13:5B:B5:3B:0E:99:0E:EF:09:C4:8C:EA:8B:F5:BD:A8:B0 X509v3 Authority Key Identifier: keyid:DE:65:01:16:19:2E:51:E0:9A:51:1A:37:50:94:7D:39:29:2A:42:2C DirName:/C=DE/ST=Bayern/L=Muenchen/O=Whatever it is/CN=IO::Socket::SSL Demo CA serial:E7:AD:8B:07:55:8A:17:27 X509v3 Key Usage: Digital Signature, Non Repudiation, Key Encipherment Signature Algorithm: sha1WithRSAEncryption 7f:2b:5f:6b:dd:37:57:df:1c:37:d6:c5:64:d0:51:93:c0:d8: 41:dd:60:38:cb:37:dd:c3:4d:94:7c:3d:39:aa:29:38:7b:fe: 9a:4d:cc:fc:35:10:0f:1d:f5:5c:f5:1f:fa:c1:eb:b9:5f:40: fc:15:cb:ae:f4:49:93:31:bf:f6:e6:0c:ce:6e:c1:35:b9:12: 87:77:52:4f:18:e0:e9:a1:3e:41:ae:9d:59:be:ea:8e:42:1b: 4f:3e:1e:99:3a:c0:01:b3:eb:1f:de:0a:01:26:d3:4f:8f:f2: 0d:9a:ef:bb:33:b1:5e:46:b9:8d:74:bf:37:aa:2a:71:aa:f4: d9:95 -----BEGIN CERTIFICATE----- MIIDVzCCAsCgAwIBAgIJANbX4bSzMJHuMA0GCSqGSIb3DQEBBQUAMGwxCzAJBgNV BAYTAkRFMQ8wDQYDVQQIEwZCYXllcm4xETAPBgNVBAcTCE11ZW5jaGVuMRcwFQYD VQQKEw5XaGF0ZXZlciBpdCBpczEgMB4GA1UEAxMXSU86OlNvY2tldDo6U1NMIERl bW8gQ0EwHhcNMDgwMTAxMDAwMDAxWhcNMTkwMzMwMDY1NjMxWjBhMQswCQYDVQQG EwJERTEPMA0GA1UECBMGQmF5ZXJuMREwDwYDVQQHEwhNdWVuY2hlbjEXMBUGA1UE ChMOV2hhdGV2ZXIgaXQgaXMxFTATBgNVBAMTDGNsaWVudC5sb2NhbDCBnzANBgkq hkiG9w0BAQEFAAOBjQAwgYkCgYEA2UknQ0FGm4PTIirtH5cMY4wGP0wKdD7Dl74n V/JAGEB8nT+vEr587D8Buw69C/0NMI96ubfy9+/4x+K/d28lJqt25BdMPOXDKSKS ON6C9wOcPfgINbX7kFcFSIsRAE2X+DkHuzZaE9+mFdNsWn8xMTmOsIKNQ6w8n6bw bz/J96cCAwEAAaOCAQowggEGMAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9w ZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSjgakTW7U7DpkO 7wnEjOqL9b2osDCBngYDVR0jBIGWMIGTgBTeZQEWGS5R4JpRGjdQlH05KSpCLKFw pG4wbDELMAkGA1UEBhMCREUxDzANBgNVBAgTBkJheWVybjERMA8GA1UEBxMITXVl bmNoZW4xFzAVBgNVBAoTDldoYXRldmVyIGl0IGlzMSAwHgYDVQQDExdJTzo6U29j a2V0OjpTU0wgRGVtbyBDQYIJAOetiwdVihcnMAsGA1UdDwQEAwIF4DANBgkqhkiG 9w0BAQUFAAOBgQB/K19r3TdX3xw31sVk0FGTwNhB3WA4yzfdw02UfD05qik4e/6a Tcz8NRAPHfVc9R/6weu5X0D8Fcuu9EmTMb/25gzObsE1uRKHd1JPGODpoT5Brp1Z vuqOQhtPPh6ZOsABs+sf3goBJtNPj/INmu+7M7FeRrmNdL83qipxqvTZlQ== -----END CERTIFICATE----- IO-Socket-SSL-1.965/certs/client-key.enc0000644000175100017520000000170311164615536016347 0ustar workwork-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,B8D106E5875DEBC3 fdoA/G4J5lNf+F71QaL3bC1BtQqM/tJ+9C+FgYN4ECoV9T5gQZQ7FkACBWuPAbki BNKzvKH5TvSdpxUjgQuMtBcQQZEH9931ZjWLnxNEyoSYkvVI7jmdT66bZWOEuJmy UojLQG5FTXCqpBlTj59wY2Z1/6sS1rDoWnNcSKGRiOMyjNYr0qrVXjLNX63+j6Ng 2Sk9j2RhViLzAX+OfdpfgrXwAWt01z+zsa1nJq921vyBsfAHmyMVLUv5W1iQMLEc lNxwnTyl31x4AzD9S4GbpGoQoH2TOmVKnXQCcla4qiVSMLRrzJpEDTXk3BvSdXoB 8RwDpmfN2hhNQuUXBXEsm550ZQ2RzegX7ZJOQ6qYFixctm7t6TdG0x68JzZi7sTY kGB2JbgMFVfTdcqrfxHMnq1Wp0+XBbKj+EdSqSVY9D3BjmBFoAmUAVuwWg1gTdVG kVoSfQ4BB5CvDEYx9S0t1NHCQoF9DpEX/eOHp7gxitqvYryb9DSn+f28U5crTFRL GRRZ8093OBZRZqOmnvCTF3tnamPJnCw10tYCo6rNrnWReZpEPvGpPkAWNDgkfnUU ///QTfa1zoi1Cmgs2hYRx3k/y2Ttbq1ysalMOZektQ+99Y0kYRcLq2FN7NI4125r QfH+HvU/WHKVoksD60RZ1nWvC59n/innWJooFJ+pBqxe6WGabBdT6qXoHIt64JrU ZJXmwdnX3Cl2RcVNZ+213PqNEgRZ7/fi8+/qGaEJkzwWJB/yhS+tgYrzNPsaUs9g dY5CKbFCuG1K8sWY0kObFRq2uqM4Md7UfKXbi5kDXhnuWO+cyQCCjA== -----END RSA PRIVATE KEY----- IO-Socket-SSL-1.965/certs/server-cert.pem0000644000175100017520000000701511164611113016545 0ustar workworkCertificate: Data: Version: 3 (0x2) Serial Number: d6:d7:e1:b4:b3:30:91:f0 Signature Algorithm: sha1WithRSAEncryption Issuer: C=DE, ST=Bayern, L=Muenchen, O=Whatever it is, CN=IO::Socket::SSL Demo CA Validity Not Before: Jan 1 00:00:01 2008 GMT Not After : Mar 30 07:05:44 2019 GMT Subject: C=DE, ST=Bayern, L=Muenchen, O=Whatever it is, CN=server.local Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public Key: (1024 bit) Modulus (1024 bit): 00:9f:98:73:4b:34:aa:4f:c2:5a:3c:3d:ba:f0:54: 55:e6:d5:8a:a0:8f:e4:94:5a:72:47:34:9a:61:50: cc:d0:81:8d:37:c4:8e:0c:79:b4:e4:d9:0d:71:06: 3d:07:4d:2a:ff:b5:6a:ef:db:36:f0:be:ed:b2:b0: 2e:18:af:f3:35:92:71:15:84:f5:2a:cb:18:bd:7e: db:26:18:c1:4e:31:2a:01:b8:1b:c9:a9:df:6c:62: 74:20:49:4d:51:14:93:f4:d6:18:07:f3:3d:d9:f7: dc:10:33:e4:00:a2:6c:62:b0:59:7e:5f:f9:8e:b6: a5:af:ad:f6:fb:e6:fa:df:9b Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE Netscape Comment: OpenSSL Generated Certificate X509v3 Subject Key Identifier: BC:81:38:7B:62:C9:DD:A9:BA:5E:9C:44:AA:AE:71:39:7A:81:C9:E8 X509v3 Authority Key Identifier: keyid:DE:65:01:16:19:2E:51:E0:9A:51:1A:37:50:94:7D:39:29:2A:42:2C DirName:/C=DE/ST=Bayern/L=Muenchen/O=Whatever it is/CN=IO::Socket::SSL Demo CA serial:E7:AD:8B:07:55:8A:17:27 X509v3 Key Usage: Digital Signature, Non Repudiation, Key Encipherment Signature Algorithm: sha1WithRSAEncryption 22:ac:b3:a0:67:eb:c2:40:36:9a:56:71:20:fc:2e:4b:3d:db: b1:83:f3:96:5a:33:9b:db:33:de:52:dc:9c:80:36:78:9b:e3: 90:ea:63:cc:0c:ac:0f:bd:01:20:26:8f:47:27:83:23:a9:90: b6:ae:5c:d8:3c:20:27:ca:04:b4:5e:9b:85:fc:34:af:5e:91: 60:3b:d2:df:b7:06:ae:e3:01:09:1f:89:af:0a:18:0a:3f:ef: 43:d6:3d:6e:16:74:32:b3:06:f0:8a:f4:80:61:f7:f1:83:85: e8:2c:1d:b8:83:f6:81:87:b3:cd:2b:0b:88:1a:f9:3f:15:77: 3b:cc -----BEGIN CERTIFICATE----- MIIDVzCCAsCgAwIBAgIJANbX4bSzMJHwMA0GCSqGSIb3DQEBBQUAMGwxCzAJBgNV BAYTAkRFMQ8wDQYDVQQIEwZCYXllcm4xETAPBgNVBAcTCE11ZW5jaGVuMRcwFQYD VQQKEw5XaGF0ZXZlciBpdCBpczEgMB4GA1UEAxMXSU86OlNvY2tldDo6U1NMIERl bW8gQ0EwHhcNMDgwMTAxMDAwMDAxWhcNMTkwMzMwMDcwNTQ0WjBhMQswCQYDVQQG EwJERTEPMA0GA1UECBMGQmF5ZXJuMREwDwYDVQQHEwhNdWVuY2hlbjEXMBUGA1UE ChMOV2hhdGV2ZXIgaXQgaXMxFTATBgNVBAMTDHNlcnZlci5sb2NhbDCBnzANBgkq hkiG9w0BAQEFAAOBjQAwgYkCgYEAn5hzSzSqT8JaPD268FRV5tWKoI/klFpyRzSa YVDM0IGNN8SODHm05NkNcQY9B00q/7Vq79s28L7tsrAuGK/zNZJxFYT1KssYvX7b JhjBTjEqAbgbyanfbGJ0IElNURST9NYYB/M92ffcEDPkAKJsYrBZfl/5jralr632 ++b635sCAwEAAaOCAQowggEGMAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9w ZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBS8gTh7Ysndqbpe nESqrnE5eoHJ6DCBngYDVR0jBIGWMIGTgBTeZQEWGS5R4JpRGjdQlH05KSpCLKFw pG4wbDELMAkGA1UEBhMCREUxDzANBgNVBAgTBkJheWVybjERMA8GA1UEBxMITXVl bmNoZW4xFzAVBgNVBAoTDldoYXRldmVyIGl0IGlzMSAwHgYDVQQDExdJTzo6U29j a2V0OjpTU0wgRGVtbyBDQYIJAOetiwdVihcnMAsGA1UdDwQEAwIF4DANBgkqhkiG 9w0BAQUFAAOBgQAirLOgZ+vCQDaaVnEg/C5LPduxg/OWWjOb2zPeUtycgDZ4m+OQ 6mPMDKwPvQEgJo9HJ4MjqZC2rlzYPCAnygS0XpuF/DSvXpFgO9Lftwau4wEJH4mv ChgKP+9D1j1uFnQyswbwivSAYffxg4XoLB24g/aBh7PNKwuIGvk/FXc7zA== -----END CERTIFICATE----- IO-Socket-SSL-1.965/certs/test-ca.pem0000644000175100017520000000220311164607317015651 0ustar workwork-----BEGIN CERTIFICATE----- MIIDKDCCApGgAwIBAgIJAOetiwdVihcnMA0GCSqGSIb3DQEBBQUAMGwxCzAJBgNV BAYTAkRFMQ8wDQYDVQQIEwZCYXllcm4xETAPBgNVBAcTCE11ZW5jaGVuMRcwFQYD VQQKEw5XaGF0ZXZlciBpdCBpczEgMB4GA1UEAxMXSU86OlNvY2tldDo6U1NMIERl bW8gQ0EwHhcNMDkwNDAxMDY0NDQ4WhcNMTkwMzMwMDY0NDQ4WjBsMQswCQYDVQQG EwJERTEPMA0GA1UECBMGQmF5ZXJuMREwDwYDVQQHEwhNdWVuY2hlbjEXMBUGA1UE ChMOV2hhdGV2ZXIgaXQgaXMxIDAeBgNVBAMTF0lPOjpTb2NrZXQ6OlNTTCBEZW1v IENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZROfatylcxcbrx0dTXvgo zlqFwps7ghgyx+Qvgwrv72w8dPIpMDk1zTeQPNSy8nTCYIsEr1tGC+T/dYt3raYm 2kXk20QzYiuXOCIUR+JY9xvUdnee9Z1vJD5u7DfkhnAsCJhkxVZ7xoSF4Zei812v i+Z+ePR+/F7uTJyeBbf5QQIDAQABo4HRMIHOMB0GA1UdDgQWBBTeZQEWGS5R4JpR GjdQlH05KSpCLDCBngYDVR0jBIGWMIGTgBTeZQEWGS5R4JpRGjdQlH05KSpCLKFw pG4wbDELMAkGA1UEBhMCREUxDzANBgNVBAgTBkJheWVybjERMA8GA1UEBxMITXVl bmNoZW4xFzAVBgNVBAoTDldoYXRldmVyIGl0IGlzMSAwHgYDVQQDExdJTzo6U29j a2V0OjpTU0wgRGVtbyBDQYIJAOetiwdVihcnMAwGA1UdEwQFMAMBAf8wDQYJKoZI hvcNAQEFBQADgYEAZu8EXePCEhV0LeC0zBXBMUlqu7p0fzQByL9U6SuOmwkKih/w OcsjxX6PFjJm3C5/NJ9mUw8WrbbBTKcMg7t2PvuyIuKK+wK3Nf5XZaGnzwtn1aFz M0LUhtV8z6OcURDEfnQBsgLCPODc9Mg4FEViDGVaZ1i233ZeAlLzXSZeXL8= -----END CERTIFICATE----- IO-Socket-SSL-1.965/certs/server-key.pem0000644000175100017520000000156711164611166016416 0ustar workwork-----BEGIN RSA PRIVATE KEY----- MIICXQIBAAKBgQCfmHNLNKpPwlo8PbrwVFXm1Yqgj+SUWnJHNJphUMzQgY03xI4M ebTk2Q1xBj0HTSr/tWrv2zbwvu2ysC4Yr/M1knEVhPUqyxi9ftsmGMFOMSoBuBvJ qd9sYnQgSU1RFJP01hgH8z3Z99wQM+QAomxisFl+X/mOtqWvrfb75vrfmwIDAQAB AoGBAJmJZ7m9U+/hkUANPzAAYpftbi1j4Urb7L8WG0NuIWyihgJVxTa5S88yBZ1r nADPO4O/u74/Tg60ECdtGRvFAhtNwQA1DWIqoVat9kaFsXaJDRqalSFVNyJL94C8 NEDNkBOfL0LNDfbLdekHrsEx16Sk4Cb3+GwPcQlCBj83Oft5AkEA0QXrySU0/+yb 2M30SOe5m9h5G42RQHJ5wFz7e3NwN9iFd6rIcYAKaJ2vNjN67fYV8TqdCncOL2+2 ZjkeHIeWpQJBAMN2uh1ma0JRGHBG0zK5IiL5C0tvajoF+cNAgOfl7vf1CtRx5KW9 x2aOZumfzm9t0NbcutmEjGB0XbZdCNg9CT8CQEbUetHuiccvpqARKnaKD5t//4oW ruHn6NoGqDFtLNm/xXqHpOTRPrW0uWrkhwOcIFNeSVkCfwwUDvsU399LEwECQQCc GpIBMO6wg/u0j5vUgq6Up7kxgcWgmW0jVrycd7ImLXl8uYkWJT6+1TOzmYFQ1K9Z KefAGG/UCJtfLWYG7JgZAkBNooGdD0taYFyfAlxgbjVqNpgubgnpXvh3G4SRbm3J itE3l4HvYIrLPQVBzG2fomU+AIH8T9NleyFQNRB0BZay -----END RSA PRIVATE KEY----- IO-Socket-SSL-1.965/certs/client-key.pem0000644000175100017520000000156711164610117016361 0ustar workwork-----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQDZSSdDQUabg9MiKu0flwxjjAY/TAp0PsOXvidX8kAYQHydP68S vnzsPwG7Dr0L/Q0wj3q5t/L37/jH4r93byUmq3bkF0w85cMpIpI43oL3A5w9+Ag1 tfuQVwVIixEATZf4OQe7NloT36YV02xafzExOY6wgo1DrDyfpvBvP8n3pwIDAQAB AoGAVDCM/vke04jrWLTLNc8/5J5PmVzsPAhJntT1x5S8kukBn6gaPKgEHUF4eTMH uspsvuEJC0aj5L9dZI2N5EfzW2YZsKx7vWn2A0j+XfQ1CT/p7Qq2ywr6RhmJux9l +ChupTvx/jsym7XAJoEsxD8KMjrLddxCPButk/Z7B+nX1uECQQD9qxccaJ1/3T7h tzJN7R8SEWAqj5Kc4Sk6oZRMV4Jn6x3jPoML8wkMiORGoeX8c+mJszTo+Ao3Gayz 4XtYEixRAkEA20hzbJWXvTW3xm3aePbkybLR5mT4c1RcU1h03wzPV3o06V34bahu k+JYXEvGzt7b3X1Lbuq+BTRfnhdoPK/+dwJAfQlIawhmGhDEXh4e/apUFmPaMyBx 9EJIQE5E+xxnezG5mbnGfq1dWIBhhS9oXfgEtYtQGUWqQ160cjZCxjavAQJAMFXi C3dWAUEMB1NDqxJREBy4o95x3Yok58JB0MDUG2Y2r5IlJpbP+Q0ViRKy+fqp4EK0 E/judds7kG98bJQmtQJBAIBkK4fWPkuSwxiLO7jsLUltXe6dzu3oEYYCpJWs7wy5 BtK/ta3rfXp1zNiu2XdCiccGJhuEB3WbCPBBpmvMye0= -----END RSA PRIVATE KEY-----